일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- SK텔레콤
- 해외주식
- 티스토리챌린지
- Bestin
- ConnectedHomeIP
- 매터
- RS-485
- 코스피
- homebridge
- 공모주
- 홈네트워크
- Home Assistant
- 나스닥
- matter
- 파이썬
- esp32
- 현대통신
- 힐스테이트 광교산
- Apple
- Espressif
- raspberry pi
- MQTT
- 미국주식
- 오블완
- 애플
- Python
- 국내주식
- cluster
- 배당
- 월패드
- Today
- Total
YOGYUI
광교아이파크::조명 Apple 홈킷 연동 (3) 본문
[3] RS-485 Signal Hooking
최신버전 라즈비안 깔아두면 FT232 계열은 드라이버 별도로 설치하지 않아도 장치가 잘 인식된다
pyserial 패키지 이용해서 우선 어떤 패킷이 RS-485 통신 라인에 실리는지 후킹해보자
pip3 install pyserial
# Test.py
# 1. 일단 신호 들어오는지나 보자
import serial
recv_cnt = 0
max_recv = 200
ser = serial.Serial()
ser.port = '/dev/ttyUSB0'
ser.baudrate = 9600
ser.open()
while True:
if ser.in_waiting > 0:
recv = ser.read(ser.in_waiting)
print(' '.join(['{:02X}'.format(x) for x in recv]))
recv_cnt += len(recv)
if recv_cnt > max_recv:
break
ser.close()
pi@raspberrypi:~ $ /bin/python3 /home/pi/Desktop/Serial485/Test.py
00 75
02 D1 07 02
83 00 56 02
D1 30 82 83 80 05 01 00 52 58 60 00 03 74 02 00
06 86 58 00 00 00
02 31 07 11 84 02 A2
02 31 1E 91 84 E2 20 83 00 64
00 64 00 00 00 5A 01 00 00 00 00 5A 08 65 07 6F
00 E3 08 F6
02 31 07 11 85 03 A8
02 31 1E 91 85 E3 20
83 00 64 00 64 00 00 00 59 02 6D 00 00 01 5B
16 CF 05 58 00 00 00 9B
02 42 07 11 86 01 D4
02 42 08 91 86
01 16 4E
02
D1 07 02 87 00 52
02 D1 30 82 87 80 05 01 00 52 58 60 00 03
74 02 00 06 86 FE
02 31 07 11 88 01 AF
02 31 1E 91 88 E1 C0 83
00 64 00 64 00 00 00 00 00 E2 02 E7 02 60 19
20 02 D2 1E 18 00 2E
02 31 07 11 89 02
B3 02 31 1E 91
89 E2 20 83 00 64 00 64 00 00 00 5A 01 00 00
일단 신호 자체는 문제없이 읽힌다!!!
(보레이트 9600은 일반적인 상식선에서 때려맞춘 값이다 - 통상적으로 홈네트워크에서 사용하는 속도)
이제 패킷 패턴을 파악해야된다
우선 패킷 출력을 좀 더 예쁘게 만들어보자
# Test2.py
# 2. 일정 개수만큼 모아서 출력
import serial
recv_cnt = 0
max_recv = 512
buffer = bytearray()
ser = serial.Serial()
ser.port = '/dev/ttyUSB0'
ser.baudrate = 9600
ser.open()
while True:
if ser.in_waiting > 0:
recv = ser.read(ser.in_waiting)
buffer.extend(bytearray(recv))
if len(buffer) > 32:
print(' '.join(['{:02X}'.format(x) for x in buffer[:32]]))
buffer = buffer[32:]
recv_cnt += len(recv)
if recv_cnt > max_recv:
break
ser.close()
pi@raspberrypi:~ $ /bin/python3 /home/pi/Desktop/Serial485/Test2.py
00 49 02 31 07 11 C5 01 E6 02 31 1E 91 C5 E1 C0 83 00 64 00 64 00 00 0C E3 00 E1 03 8B 02 60 19
20 02 D2 1E 18 00 E6 02 42 07 11 C6 01 94 02 42 08 91 C6 01 16 0E 02 D1 07 02 C7 00 12 02 D1 30
82 C7 80 05 01 00 F2 02 31 07 11 C8 02 EE 02 31 1E 91 C8 E2 20 83 00 64 00 64 00 00 00 5A 01 01
00 00 00 5A 08 65 07 6F 00 E3 08 93 02 31 07 11 C9 03 F4 02 31 1E 91 C9 E3 20 83 00 64 00 64 00
00 00 59 01 49 00 00 01 5B 16 CF 05 58 00 00 00 B2 02 41 07 11 CA 01 9D 02 41 08 91 CA 01 16 0D
02 D1 07 02 CB 00 1E FF 02 31 07 11 CC 01 EB 02 31 1E 91 CC E1 C0 83 00 64 00 64 00 00 0C E2 00
EE 03 8C 02 60 19 20 02 D2 1E 18 00 A8 02 31 07 11 CD 02 EF 02 31 1E 91 CD E2 20 83 00 64 00 64
00 00 00 5A 01 01 00 00 00 5A 08 65 07 6F 00 E3 08 AC 02 42 07 11 CE 01 9C 02 42 08 91 CE 01 16
06 02 D1 07 02 CF 00 1A 02 D1 30 82 CF 80 05 01 00 52 58 80 00 07 53 02 00 06 86 FF 02 31 07 11
D0 03 F5 02 31 1E 91 D0 E3 20 83 00 64 00 64 00 00 00 59 01 40 00 00 01 5B 16 CF 05 58 00 00 00
EC 02 31 07 11 D1 01 FA 02 31 1E 91 D1 E1 C0 83 00 64 00 64 00 00 0C E4 01 01 03 8B 02 60 19 20
02 D2 1E 18 00 7A 02 41 07 11 D2 01 85 02 41 08 91 D2 01 16 05 02 D1 07 02 D3 00 06 02 D1 30 82
D3 80 05 01 00 52 58 80 00 07 53 02 00 06 86 FF 02 31 07 11 D4 02 F2 02 31 1E 91 D4 E2 20 83 00
64 00 64 00 00 00 59 01 01 00 00 00 5A 08 65 07 6F 00 E3 08 E4 02 31 07 11 D5 03 F8 02 31 1E 91
D5 E3 20 83 00 64 00 64 00 00 00 59 01 46 00 00 01 5B 16 CF 05 58 00 00 00 E5 02 42 07 11 D6 01
84 02 42 08 91 D6 01 16 1E 02 D1 07 02 D7 00 02 02 D1 30 82 D7 80 05 01 00 52 58 80 00 07 71 02
이런 바이트스트림 속에서 패턴을 찾아내는 건 약간의 노가다가 필요하다
(시리얼 통신 관련 개발 경험이 조금이라도 있으면 도움이 된다)
00 49 02 31 07 11 C5 01 E6 02 31 1E 91 C5 E1 C0 83 00 64 00 64 00 00 0C E3 00 E1 03 8B 02 60 19
20 02 D2 1E 18 00 E6 02 42 07 11 C6 01 94 02 42 08 91 C6 01 16 0E 02 D1 07 02 C7 00 12 02 D1 30
82 C7 80 05 01 00 F2 02 31 07 11 C8 02 EE 02 31 1E 91 C8 E2 20 83 00 64 00 64 00 00 00 5A 01 01
00 00 00 5A 08 65 07 6F 00 E3 08 93 02 31 07 11 C9 03 F4 02 31 1E 91 C9 E3 20 83 00 64 00 64 00
00 00 59 01 49 00 00 01 5B 16 CF 05 58 00 00 00 B2 02 41 07 11 CA 01 9D 02 41 08 91 CA 01 16 0D
02 D1 07 02 CB 00 1E FF 02 31 07 11 CC 01 EB 02 31 1E 91 CC E1 C0 83 00 64 00 64 00 00 0C E2 00
EE 03 8C 02 60 19 20 02 D2 1E 18 00 A8 02 31 07 11 CD 02 EF 02 31 1E 91 CD E2 20 83 00 64 00 64
00 00 00 5A 01 01 00 00 00 5A 08 65 07 6F 00 E3 08 AC 02 42 07 11 CE 01 9C 02 42 08 91 CE 01 16
06 02 D1 07 02 CF 00 1A 02 D1 30 82 CF 80 05 01 00 52 58 80 00 07 53 02 00 06 86 FF 02 31 07 11
D0 03 F5 02 31 1E 91 D0 E3 20 83 00 64 00 64 00 00 00 59 01 40 00 00 01 5B 16 CF 05 58 00 00 00
EC 02 31 07 11 D1 01 FA 02 31 1E 91 D1 E1 C0 83 00 64 00 64 00 00 0C E4 01 01 03 8B 02 60 19 20
02 D2 1E 18 00 7A 02 41 07 11 D2 01 85 02 41 08 91 D2 01 16 05 02 D1 07 02 D3 00 06 02 D1 30 82
D3 80 05 01 00 52 58 80 00 07 53 02 00 06 86 FF 02 31 07 11 D4 02 F2 02 31 1E 91 D4 E2 20 83 00
64 00 64 00 00 00 59 01 01 00 00 00 5A 08 65 07 6F 00 E3 08 E4 02 31 07 11 D5 03 F8 02 31 1E 91
D5 E3 20 83 00 64 00 64 00 00 00 59 01 46 00 00 01 5B 16 CF 05 58 00 00 00 E5 02 42 07 11 D6 01
84 02 42 08 91 D6 01 16 1E 02 D1 07 02 D7 00 02 02 D1 30 82 D7 80 05 01 00 52 58 80 00 07 71 02
눈대중으로 훑어보면 [0x02 0x31 0x07 0x11], [0x02 0x31 0x1E 0x91], [0x02 0x42 0x07 0x11] 등의
바이트열이 자주 등장하는 것으로 보인다
(0x02는 ASCii code 상에 <STX, Start of TeXt>로 명시되어 있으며, 시리얼 통신에서 보통 패킷의 시작부를 가리킨다는 경험을 토대로 분석)
이 정보를 토대로 바이트스트림을 패킷으로 분리해 출력해보자
# Test3.py
# 3. 파악된 패턴을 기반으로 패킷 추출
import serial
packet_cnt = 0
max_recv = 64
buffer = bytearray()
defined_headers = [
bytearray([0x02, 0x31, 0x07, 0x11]),
bytearray([0x02, 0x31, 0x1E, 0x91]),
bytearray([0x02, 0x41, 0x07, 0x11]),
bytearray([0x02, 0x41, 0x08, 0x91]),
bytearray([0x02, 0xD1, 0x07, 0x02]),
bytearray([0x02, 0xD1, 0x30, 0x82]),
bytearray([0x02, 0x42, 0x07, 0x11]),
bytearray([0x02, 0x42, 0x08, 0x91])
]
ser = serial.Serial()
ser.port = '/dev/ttyUSB0'
ser.baudrate = 9600
ser.open()
while True:
if ser.in_waiting > 0:
recv = ser.read(ser.in_waiting)
buffer.extend(bytearray(recv))
# 미리 정의된 패킷들의 인덱스 배열 구하기
idx_list = list()
for head in defined_headers:
if buffer.find(head) >= 0:
idx_list.append(buffer.index(head))
idx_list.sort()
# 인덱스 기반으로 바이트스트림 스플릿
# 적어도 미리 정의된 패킷 헤더가 2개 이상일 때 나누자
if len(idx_list) > 1:
for i in range(len(idx_list) - 1):
packet = buffer[idx_list[i]:idx_list[i + 1]]
print(' '.join(['{:02X}'.format(x) for x in packet]))
packet_cnt += 1
buffer = buffer[idx_list[-1]:]
if packet_cnt > max_recv:
break
ser.close()
pi@raspberrypi:~ $ /bin/python3 /home/pi/Desktop/Serial485/Test3.py
02 31 07 11 D1 03 FC
02 31 1E 91 D1 E3 20 83 00 64 00 64 00 00 00 59 01 39 00 00 01 5B 16 CF 05 59 00 00 00 8B
02 41 07 11 D2 01 85
02 41 08 91 D2 01 16 05
02 D1 07 02 D3 00 06
02 D1 30 82 D3 80 05 01 00 52 59 40 00 05 18 02 00 06 86 FF
02 31 07 11 D4 01 F3
02 31 1E 91 D4 E1 C0 83 00 64 00 64 00 00 05 4E 01 67 02 F7 02 60 19 20 02 D2 1E 19 00 74
02 31 07 11 D5 02 F7
02 31 1E 91 D5 E2 20 83 00 64 00 64 00 00 00 5B 00 F4 00 00 00 5A 08 65 07 70 00 E3 08 34
02 42 07 11 D6 01 84
02 42 08 91 D6 01 16 1E
02 D1 07 02 D7 00 02
02 D1 30 82 D7 80 05 01 00 52 59 40 00 05 18 02 00 FE
02 31 07 11 D8 03 FD
02 31 1E 91 D8 E3 20 83 00 64 00 64 00 00 00 59 01 37 00 00 01 5B 16 CF 05 59 00 00 00 86
02 31 07 11 D9 01 02
02 31 1E 91 D9 E1 C0 83 00 64 00 64 00 00 05 4D 01 6F 02 F7 02 60 19 20 02 D2 1E 19 00 A0
02 41 07 11 DA 01 8D
02 41 08 91 DA 01 16 1D
02 D1 07 02 DB 00 0E
02 D1 30 82 DB 80 05 01 00 52 59 F0
02 31 07 11 DC 02 FA
02 31 1E 91 DC E2 20 83 00 64 00 64 00 00 00 5B 00 F4 00 00 00 5A 08 65 07 70 00 E3 08 37
02 31 07 11 DD 03 00
02 31 1E 91 DD E3 20 83 00 64 00 64 00 00 00 59 01 36 00 00 01 5B 16 CF 05 59 00 00 00 8C
02 42 07 11 DE 01 8C
02 42 08 91 DE 01 16 16
02 D1 07 02 DF 00 0A 02 D1
02 31 07 11 E0 01 C7
02 31 1E 91 E0 E1 C0 83 00 64 00 64 00 00 05 4D 01 72 02 F8 02 60 19 20 02 D2 1E 19 00 C1
02 31 07 11 E1 02 CB
02 31 1E 91 E1 E2 20 83 00 64 00 64 00 00 00 5B 00 F4 00 00 00 5A 08 65 07 70 00 E3 08 D8
02 41 07 11 E2 01 B5
02 41 08 91 E2 01 16 55
02 D1 07 02 E3 00 36
02 D1 30 82 E3 80 05 01 00 52 59 40 00 05 11 02 00 06 86 77 00 FE
02 31 07 11 E4 03 C1
02 31 1E 91 E4 E3 20 83 00 64 00 64 00 00 00 59 01 34 00 00 01 5B 16 CF 05 59 00 00 00 85
02 31 07 11 E5 01 C6
02 31 1E 91 E5 E1 C0 83 00 64 00 64 00 00 05 4C 01 6A 02 F7 02 60 19 20 02 D2 1E 19 00 5C
02 42 07 11 E6 01 B4
02 42 08 91 E6 01 16 2E
02 D1 07 02 E7 00 32
02 D1 30 82 E7 80 05 01 00 52 59 40 00 05 11 02 00 06 86 77 00 FE
02 31 07 11 E8 02 CE
02 31 1E 91 E8 E2 20 83 00 64 00 64 00 00 00 5B 00 F4 00 00 00 5A 08 65 07 70 00 E3 08 2B
02 31 07 11 E9 03 D4
02 31 1E 91 E9 E3 20 83 00 64 00 64 00 00 00 59 01 33 00 00 01 5B 16 CF 05 59 00 00 00 99
02 41 07 11 EA 01 BD
02 41 08 91 EA 01 16 2D
02 D1 07 02 EB 00 3E
02 31 07 11 EC 01 CB
02 31 1E 91 EC E1 C0 83 00 64 00 64 00 00 05 4A 01 6C 02 F8 02 60 19 20 02 D2 1E 19 00 AC
02 31 07 11 ED 02 CF
02 31 1E 91 ED E2 20 83 00 64 00 64 00 00 00 5A 00 F4 00 00 00 5A 08 65 07 70 00 E3 08 1D
02 42 07 11 EE 01 BC
02 42 08 91 EE 01 16 26
02 D1 07 02 EF 00 3A
02 D1 30 82 EF 80 05 01 00 52 59 40 00 04 50 02 00 06 86 77 00 FF
02 31 07 11 F0 03 D5
02 31 1E 91 F0 E3 20 83 00 64 00 64 00 00 00 59 01 39 00 00 01 5B 16 CF 05 59 00 00 00 68
02 31 07 11 F1 01 DA
02 31 1E 91 F1 E1 C0 83 00 64 00 64 00 00 05 4B 01 5D 02 F9 02 60 19 20 02 D2 1E 19 00 D2
02 41 07 11 F2 01 A5
패턴이 확연히 눈에 띈다
- 두번째 바이트는 0x31이 가장 많으며 0x41, 0x42, 0xD1이 간혹 등장
- [0x02 0xD1 0x30] 으로 시작하는 패킷을 제외하면 패킷의 길이가 서로 같다
- (대부분) 패킷의 길이는 각 패킷의 세번째 바이트값과 일치한다
(0x07일 경우 7, 0x08일 경우 8, 0x1E일 경우 30 - (대부분) 패킷의 5번째 바이트값은 이전 패킷의 5번째 값과 같거나 1 증가한다
- (대부분) 5번째 바이트값이 같은 패킷들끼리는 4번째 바이트값의 최상위비트가 토글되어있다
0x02 ↔ 0x82, 0x11 ↔ 0x91 - [0x02 0xD1 0x30] 도 위 규칙을 따른다면 길이 48의 패킷이 기대되나, 48개 스트림을 받기도 전에 다른 패킷이 읽히는 것으로 추정
홈네트워크 특성상, 디바이스들의 상태를 중앙처리장치에서는 지속적으로 읽어와야하는데 디바이스가 자기 멋대로 상태를 전송하면 중앙처리장치에 부하가 걸리게되므로 중앙처리장치가 일정 시간마다 상태값을 pulling하는게 아닌가라는 추측이 가능하다 (내멋대로)
그렇다면, 5번째 바이트값이 같은 패킷끼리는 <pull request> - <response>의 관계를 갖는다고 할 수 있다
지금까지 분석한 내용을 정리해보자
Index | 0 | 1 | 2 | 3 | 4 | 5:(N-1) |
Content | 0x02 | Header | Length (N) | Request/ Response |
Timestamp | Data |
아마 패킷은 위와 같이 설계되지 않았을까? (애초에 패킷 명세서 검색만 되었다면 이 고생은 안했겠지...)
보통 시리얼 통신 패킷의 가장 마지막 바이트는 ETX (0x03), CRC Checksum, XOR sum 등의 값이 오는데, 여기 패킷은 그 어떠한 조건에도 부합하지 않았다 (글은 쉽게 썼는데, 몇일동안이나 이리저리 계산해봤다)
위와 같은 가설을 토대로 월패드를 이리저리 만지면서 패킷을 모아보았다
라즈베리파이 SSH 활성화시킨 후, VS Code의 remote-SSH 툴 사용해서 원격 개발환경 구축했기 때문에 맥북하나 들고 이방저방 돌아다니면서 패킷 모으기를 할 수 있었다
반복 분석 결과, 일부 패킷들이 조명과 관련되었다는 확신을 갖게 되었다
[주방과 관련되었다고 추측되는 패킷] - 조명 4개 컨트롤 가능 (싱크대, 후드, 식탁, 거실 구석)
02 31 1E 91 90 E1 C0 83 00 64 00 64 00 00 04 7F 00 EA 01 52 02 59 18 E1 02 C2 1D DD 00 F2 : 모두 OFF
02 31 1E 91 39 E1 C1 83 00 64 00 64 03 7E 04 CC 00 00 01 5C 02 59 18 E3 02 C3 1D DF 00 AB: 조명1(싱크대)만 ON
02 31 1E 91 95 E1 C2 83 00 64 00 64 00 BB 04 C5 00 00 01 5E 02 59 18 E3 02 C3 1D DF 00 F9: 조명2(후드)만 ON
02 31 1E 91 D5 E1 C4 83 00 64 00 64 01 A7 06 36 00 00 01 53 02 59 18 E3 02 C3 1D DF 00 88: 조명3(식탁)만 ON
02 31 1E 91 C0 E1 C8 83 00 64 00 64 03 DE 00 00 00 00 04 35 02 59 18 E3 02 C3 1D DF 00 85: 조명4(거실 구석)만 ON
02 31 1E 91 C1 E1 CF 83 00 64 00 64 09 99 00 00 00 C4 02 FD 02 60 19 21 02 D2 1E 1A 00 01: 모두 ON
[안방(침실)과 관련되었다고 추측되는 패킷] - 조명 2개 컨트롤 가능 (형광등 1, 2)
02 31 1E 91 91 E2 20 83 00 64 00 64 00 00 00 54 01 28 00 00 00 59 08 5C 07 5B 00 E0 08 B6: 모두 OFF
02 31 1E 91 4D E2 21 83 00 64 00 64 02 52 00 4C 01 40 00 00 00 59 08 5D 07 5C 00 E0 08 FB: 조명1만 ON
02 31 1E 91 79 E2 22 83 00 64 00 64 01 22 00 4D 01 1C 00 00 00 59 08 5D 07 5C 00 E0 08 46: 조명2만 ON
02 31 1E 91 C1 E2 23 83 00 64 00 64 03 89 00 64 00 E9 00 00 00 5A 08 65 07 71 00 E3 08 BA: 모두 ON
[작은방(컴퓨터방)과 관련되었다고 추측되는 패킷] - 조명 2개 컨트롤 가능 (형광등 1, 2)
02 31 1E 91 94 E3 20 83 00 64 00 64 00 00 00 4D 01 5F 00 00 01 5B 16 B4 05 47 00 00 00 D7: 모두 ON
02 31 1E 91 9C E3 21 83 00 64 00 64 02 86 00 4B 02 45 00 00 01 5B 16 B4 05 47 00 00 00 89: 조명1만 ON
02 31 1E 91 64 E3 22 83 00 64 00 64 01 46 00 47 01 5A 00 00 01 5B 16 B4 05 48 00 00 00 44: 조명2만 ON
02 31 1E 91 CC E3 23 83 00 64 00 64 03 B3 00 45 01 DC 00 00 01 5B 16 B4 05 47 00 00 00 27: 모두 ON
>> 6번째 바이트의 하위 4비트는 방 인덱스, 7번째 바이트의 하위 4비트는 각 조명의 ON, OFF 여부
(나머지 데이터는 실시간 전력 사용량인 것으로 추정되는데, 레퍼런스가 없어서 파싱이 불가능할 것 같다)
추가로, 월패드에서 다른 방들의 조명을 제어하고자 할 경우 다른 종류의 패킷이 송신되는 것을 발견했다
[주방 제어 시 발견 패킷]
02 31 0D 01 92 01 8F 00 00 00 00 04 22: 모두 ON
02 31 0D 01 A9 01 0F 00 00 00 00 00 9D: 모두 OFF
02 31 0D 01 D0 01 81 00 00 00 00 04 76: 1번 조명 ON
02 31 0D 01 D7 01 01 00 00 00 00 00 F5: 1번 조명 OFF
02 31 0D 01 58 01 82 00 00 00 00 04 E9: 2번 조명 ON
02 31 0D 01 5F 01 02 00 00 00 00 00 6A: 2번 조명 OFF
02 31 0D 01 5C 01 84 00 00 00 00 04 EF: 3번 조명 ON
02 31 0D 01 63 01 04 00 00 00 00 00 6C: 3번 조명 OFF
02 31 0D 01 2B 01 88 00 00 00 00 04 94: 4번 조명 ON
02 31 0D 01 33 01 08 00 00 00 00 00 20: 4번 조명 OFF
[안방(침실) 제어 시 발견 패킷]
02 31 0D 01 97 02 8F 00 00 00 00 04 22 : 모두 ON
02 31 0D 01 A5 02 0F 00 00 00 00 00 9C: 모두 OFF
02 31 0D 01 8C 02 81 00 00 00 00 04 3F: 1번 조명 ON
02 31 0D 01 93 02 01 00 00 00 00 00 B8: 1번 조명 OFF
02 31 0D 01 7B 02 82 00 00 00 00 04 CB: 2번 조명 ON
02 31 0D 01 84 02 02 00 00 00 00 00 C4: 2번 조명 OFF
[작은방(컴퓨터방) 제어 시 발견 패킷]
02 31 0D 01 9A 03 8F 00 00 00 00 04 2C : 모두 ON
02 31 0D 01 A0 03 0F 00 00 00 00 00 96: 모두 OFF
02 31 0D 01 3B 03 81 00 00 00 00 04 97: 1번 조명 ON
02 31 0D 01 43 03 01 00 00 00 00 00 8B: 1번 조명 OFF
02 31 0D 01 76 03 82 00 00 00 00 04 D5: 2번 조명 ON
02 31 0D 01 7E 03 02 00 00 00 00 00 49: 2번 조명 OFF
>> 6번째 바이트의 하위 4비트는 방 인덱스, 7번째 바이트의 최상위비트는 켜기/끄기 여부, 7번째 바이트 하위 4비트는 대상 조명 인덱스, 12번째 바이트는 조명 ON 명령시 04, 조명 OFF 명령시 00 이어야 한다
위 예시 패킷들을 똑같이 485 라인에 송신하면 조명이 응답하는지 여부를 확인할 차례다
# Test4.py
# 4. 시리얼 패킷 전송
import os
import sys
import serial
ser = serial.Serial()
ser.port = '/dev/ttyUSB0'
ser.baudrate = 9600
ser.open()
while True:
os.system('clear')
print('Input: ')
line = sys.stdin.readline()
if len(line) > 0:
temp = line.replace('\n', '').strip()
ser.write(bytearray([int(x, 16) for x in temp.split(' ')]))
else:
break
ser.close()
성공!
테스트삼아 마지막 바이트를 위 예시와 달리 다르게 하여 패킷을 송신해보니 제대로 응답을 하지 못했다
패킷 정합성 여부 판단에 사용하는 것 같은데 값을 만들어내는 규칙을 찾지 못해 그냥 위 예시 패킷들을 그대로 사용하기로 함
[정리]
RS-485 시리얼 바이트스트림을 후킹하여 패킷으로 파싱한 후 각 방들의 조명 상태(On/Off)를 확인할 수 있으며, 사용자가 임의의 패킷을 전송하여 조명을 제어할 수 있으므로, 외부 어플리케이션을 통한 제어를 위한 준비 단계는 모두 끝났다
[시리즈 링크]
'홈네트워크(IoT) > 광교아이파크' 카테고리의 다른 글
광교아이파크::조명 Apple 홈킷 연동 (6) (0) | 2021.01.01 |
---|---|
광교아이파크::조명 Apple 홈킷 연동 (5) (0) | 2021.01.01 |
광교아이파크::조명 Apple 홈킷 연동 (4) (0) | 2021.01.01 |
광교아이파크::조명 Apple 홈킷 연동 (2) (0) | 2020.12.31 |
광교아이파크::조명 Apple 홈킷 연동 (1) (0) | 2020.12.31 |