zigbee2mqtt 설치

(이전 글에 합쳐져있던 내용을 새 글로 분리)

zigbee2mqtt (이하 z2m) 은 mqtt 란 프로토콜을 기반으로 작동하는건데,
z2m은 mqtt 클라이언트로서 연결할 mqtt broker (서버라고 생각하면 됨)가 필요하다.

docker 로 mqtt broker 인 eclipse-mosquitto 와 z2m 둘 다 설치할거임.

# eclipse-mosquitto 이미지 다운 및 실행
docker pull eclipse-mosquitto
sudo docker run -d \
    --name=mosquitto \
    -p 1883:1883 \
    -p 9001:9001 \
    --restart=always \
    -v /home/pi/ha/mosquitto/data:/mosquitto/data \
    -v /home/pi/ha/mosquitto/log:/mosquitto/log \
    eclipse-mosquitto

# z2m 이미지 다운 및 실행
docker pull koenkk/zigbee2mqtt
docker run -d \
    --name="z2m" \
    --net=host \
    --restart=always \
    -v /home/pi/ha/z2m:/app/data \
    --device=/dev/ttyACM0 \
    -v /run/udev:/run/udev:ro \
    -e TZ=Asia/Seoul \
    --privileged=true \
    koenkk/zigbee2mqtt


설정 파일 경로는 이전글에 이어서 /home/pi/ha/ 폴더 안에 각 폴더를 만들고 지정해주었다.

z2m 실행시 필요한 --device 이름 역시 필요하다면 알아서 바꿔주자.


z2m 의 설정을 조금 변경해준다.

기본값으로 꺼져있는 homeassistant 를 켜주고, devices, group 을 관리하기 편하게 별도 파일로 만든다

cd ~/ha/z2m
sudo touch devices.yaml groups.yaml
sudo vi /home/pi/ha/z2m/configuration.yaml
homeassistant: true
permit_join: true
mqtt:
  base_topic: zigbee2mqtt
  server: 'mqtt://localhost'
serial:
  port: /dev/ttyACM0
devices: devices.yaml
groups: groups.yaml

zigbee 장비가 다 추가되고 나면 permit_join: false 로 바꿔주면 됨.


그 다음 HA의 설정도 변경, mqtt 항목을 추가해준다.

mqtt broker 를 추가하는거기 때문에 혹시나 eclipse-mosquitto 를 다른 장비나 다른 포트에서 작동시킬 경우 적당히 수정해주자.

sudo vi ~/ha/config/configuration.yaml
mqtt:
  broker: 127.0.0.1
  discovery: true


둘 다 재시작

docker restart z2m home-assistant


이제 HA의 통합 구성요소에 MQTT 가 나타나고 기기와 구성요소에도 z2m을 통해 연결된 장비가 나타단다.

deCONZ 로는 안 보였던 다원 스마트 플러그의 전력량도 잘 보이고, 다원 전등 스위치도 연결이 잘 됨.


실시간으로 올라오는 z2m의 로그를 보려면

tail -f $(ls -td ~/ha/z2m/log/*/ | head -1)log.txt

이렇게 하면 됨. z2m을 재시작할 때마다 실행 시간으로 디렉토리가 생긴다.

tail 명령어로 열었는데, 지난 로그를 보고 싶으면 vim이나 nano 등으로 직접 열어봐도 됨.

zigbee IoT 장치들(End Device)를 사용하기 위해선 장치들이 연결되기 위한 Coordinator가 필요하다.

코디네이터를 중심으로 end device 들이 연결되는데, 중간에 네트워크 확장을 위해서 라우터를 추가하기도 함.

코디네이터 혹은 라우터로 사용할 수 있는 CC2531 을 구매 후 펌웨어 변경 작업을 정리해 보았음.


CC2531 펌웨어 플래싱 with RPi

* 참고: 
    * What do I need? | zigbee2mqtt.io - https://www.zigbee2mqtt.io/getting_started/what_do_i_need.html
    * Flashing the firmware on the CC2531 USB stick | zigbee2mqtt.io - https://www.zigbee2mqtt.io/getting_started/flashing_the_cc2531.html
    * Alternative flashing methods | zigbee2mqtt.io - https://www.zigbee2mqtt.io/information/alternative_flashing_methods.html
    * ConBee implementation #72 - https://github.com/jmichault/flash_cc2531/issues/9


우선 CC2531(약 $5) 이랑 다운로더 케이블(약 $2)를 준비한다. 난 AliExpress 에서 주문하였음.

칩안테나(회로에 안테나가 그려져 있는) 버전이 있고 안테나 단자가 달려 있고 안테나를 같이 파는 버전도 있다.

CC2531 을 그냥 쓸 경우 신호가 약하다는 글을 많이 봐서 난 안테나 버전으로 구매하였음.


펌웨어 작업이 이미 되어 있는 CC2531을 팔기도 한다던데 그걸 살 경우 다운로더 케이블과 이 작업이 필요없다.


위에 참고로 건 글 중 Flashing the firmware on the CC2531 USB stick 글을 보면 Windows, Mac, Linux 에서 플래싱을 할 수 있지만, 왠지 pi에서 하는게 더 편할 것 같았다.

pi나 아두이노로 진행하는 방법은 Alternative flashing methods 글을 참고하면 됨.


1. 파이에 WiringPI 설치

sudo apt install wiringpi


2. 파이에서 툴 다운로드

git clone https://github.com/jmichault/flash_cc2531.git


3. 파이와 다운로더 모듈 간에 GPIO핀 연결

연결을 위해선 암-암 점퍼 케이블 4개가 필요함.

다운로더 모듈

 파이

 pin 1 (GND)

 pin 39 (GND)

 pin 7 (reset)

 pin 35 (GPIO24, BCM19)

 pin 3 (DC)

 pin 36 (GPIO27, BCM16)

 pin 4 (DD)

 pin 38 (GPIO28, BCM20)

다운로더 모듈의 핀보드는 모듈에 적혀있으니 그걸 보면 되고, 파이의 핀 위치는 https://pinout.xyz/ 사이트 참고.


4개 핀도 연결하고 전원 공급을 위해 CC2531 을 파이의 USB단자에도 연결해준다.


4. 플래싱

1) 먼저 잘 연결이 되었는지 확인해본다.

cd flash_cc2531
./cc_chipid -m 90
  ID = b524.

ID가 0000, ffff 등이 나온다면 뭔가 오류가 있음.

원래 -m 90 을 붙여주지 않아도 되는데, 나의 경우 계속 붙여줘야 정상적으로 진행이 가능했다.


2) 펌웨어 파일 다운로드

코디네이터 버전 - https://github.com/Koenkk/Z-Stack-firmware/tree/master/coordinator/Z-Stack_Home_1.2/bin/default

라우터 버전 - https://github.com/Koenkk/Z-Stack-firmware/tree/master/router/CC2531/bin

# 코디네이터
wget https://github.com/Koenkk/Z-Stack-firmware/raw/master/coordinator/Z-Stack_Home_1.2/bin/default/CC2531_DEFAULT_20190608.zip
unzip CC2531_DEFAULT_20190608.zip

# 라우터
wget https://github.com/Koenkk/Z-Stack-firmware/raw/master/router/CC2531/bin/CC2531_router_2020_09_29.zip
unzip CC2531_router_2020_09_29.zip


라우터 버전은 펌웨어가 3개가 나온다.

- router-cc2531-std.hex: 라우터 기능만 작동
- router-cc2531-diag.hex: 라우터 + 진단 정보
- router-cc2531-diag-usb.hex: 라우터 + 진당전보 + USB 시리얼포트로 인식 (진단정보를 USB로 읽기 가능)

진단정보가 뭘 말하는건지 모르겠어서 난 그냥 -std 버전을 사용하였음.


3) 펌웨어 플래싱

./cc_erase -m 90
./cc_write -m 90 CC2531ZNP-Prod.hex (혹은 해당하는 펌웨어명)


----------------------------------------------------------------------------

[목차]

1. IoT 사물 / 인증서 / 정책 생성

2. Python + paho-mqtt 를 사용하여 주제 구독, 게시 및 테스트

3. AWS Lambda에 연결하고 텔레그램 봇 메시지 보내기

----------------------------------------------------------------------------


2. Python + paho-mqtt 를 사용하여 주제 구독, 게시 및 테스트


AWS IoT 용 파이썬 패키지도 있는 것 같았지만, 메서드명도 괴랄하고 어떻게 쓰는지 한눈에 안보여서 사용하지 않았다.

Prepare your Raspberry Pi to work with AWS IoT (Getting started with IoT #2)

글을 참고하여, 작성해보았는데, 잘되어서 걍 이거 쓸 듯.


테스트용 AWS MQTT 클라이언트 사용

우선 AWS 에서 MQTT 테스트용 클라이언트를 제공한다.

일단 임의로 test/1 토픽을 구독해본다



구독할 토픽 이름을 임의로 설정하고, 주제 구독을 누른다. 와일드카드(+) 도 사용가능하다.




그럼 이런 화면이 나오는데, 좌측에 구독 중인 주제들이 보이고, 구독한 주제에 대해 메시지가 있으면 하단에 표시된다.




구독하고 있는 주제로 바로 게시도 가능하니, 해볼 경우 이렇게 나온다.



라즈베리파이 + Python

(사실 꼭 라즈베리일 필요는 없다. 나도 처음 해볼 땐 파이에서 했지만, 지금은 맥에서 그냥 진행.)


특정 버전 이상의 ssl 이 필요하지만, 내 기억에 파이에 기본으로 설치되어 있었던 것으로 기억한다.

파이썬3 기준으로 할거니 2로 쓰고 싶으신 분은 알아서 필요한 부분을 수정.


pip 이 없다면 이것부터 설치

$ curl https://bootstrap.pypa.io/get-pip.py | sudo python3


paho-mqtt 설치

$ sudo python3 -m pip install paho-mqtt


Python 코드는 아래처럼 작성하면 된다. 적당히 mqtt.py 정도로 만들자.

대충 mqtt 연결을 수립하고, 연결되면 test/2 주제를 구독하기 시작하며,

test/2 주제로 메시지가 게시되면 json 으로 load 해서 message 키의 값을 출력하는 코드이다.




--------------------------------------------------

[유의사항]

1.  클라이언트 생성자에 clean_session 인자가 있는데, True(기본값)로 해야한다. False 로 할시 AWS 에서 연결을 끊어버린다.

2. publish 할때 retain 인자는 False(기본값)로 해야한다. True 로 보내면 마찬가지로 AWS 에서 연결을 끊어버린다.

3. 같은 아이디로 두개 이상이 연결되면 둘 다 연결이 종료된다.

4. AWS IoT 에서 qos 0 은 "0번 이상 전달"을 의미한다. qos 2 는 지원되지 않는다.


* 자세한건 AWS IoT 메시지 브로커 - 프로토콜 문서 참고.

--------------------------------------------------



publish 도 테스트해보려고 메인 루프는 주석처리 해뒀으니, 인터프리터 모드로 실행

$ python3 -i mqtt.py



정상적으로 연결되었을 경우 connected 로그가 뜬다.


혹시 ssl.SSLError: [SSL: SSLV3_ALERT_CERTIFICATE_UNKNOWN] sslv3 alert certificate unknown

같은 에러가 뜬다면, AWS 에서 인증서를 활성화하지 않은 경우니 활성화해주고 다시 시도해보자.


이후 아래쪽에 주석 처리 해둔대로 publish 를 시도해보면


>>> payload = json.dumps({'action': 'test'})

>>> mqtt_client.publish('test/1', payload, qos=1)



이렇게 아까 열어둔 mqtt 테스트 클라이언트에서 정상적으로 publish 된 것을 확인할 수 있다.


마찬가지로 파이에서 구독하고 있는 test/2 주제로 게시하면, 파이에서 on_message 함수가 실행되어 로그가 찍히는걸 확인할 수 있다.


메시지는 꼭 json 일 필요는 없다. 코드를 보면 알겠지만, 보낼땐 dump 하고 받을땐 load 한다. 다만 걍 json 을 쓰자..ㅋㅋ

그냥 나보고 만들어라고 하면 http 리퀘스트 만으로 어떻게 퉁쳤겠지만... 다른 사람의 서비스 제작을 도와줄 필요가 있었다.

최대한 AWS 의 솔루션을 사용하는게 향후 유지관리에도 좋을 것이고, AWS IoT 를 써보고도 싶었고, 서버->디바이스 요청도 쉽게 보낼 수 있게 되니, 한번 써보고 정리하는 글. 사실 친구놈 보라고 쓰는거다 휘수야 보고 있니


우선 AWS IoT 에 대한 특징 같은건 다른 글에 많으니 다 생략하고 내가 찾는데 시간이 걸렸거나, 관심이 있는 부분만 기술한다.

즉 mqtt 가 뭔지, 주제 구독이 뭔지 이런건 생략.


이번 글의 목표는, 라즈베리파이에서 mqtt 주제를 publish, subscribe 해보고 라즈베리파이에서 publish 된 주제를 통해 aws lambda 함수를 실행시켜서 텔레그램 알림을 받는 것 까지.


----------------------------------------------------------------------------

[목차]

1. IoT 사물 / 인증서 / 정책 생성

2. Python + paho-mqtt 를 사용하여 주제 구독, 게시 및 테스트

3. AWS Lambda에 연결하고 텔레그램 봇 메시지 보내기

----------------------------------------------------------------------------


1. [AWS 콘솔] IoT 사물 / 인증서 / 정책 생성



AWS 에서 IoT 대시보드로 이동한 후 좌측 관리 - 사물 - 사물 등록



지금은 한개만 등록할거니 단일 사물 생성.




관리의 편의성을 위해 유형이나 그룹 등등을 설정할 수 있지만, 지금은 필요없다. 이름만 적당히 생성하고 다음으로 넘어가자.

이 이름은 thing name 이자 client id 로 사용된다.




ioT 디바이스를 인증하고 암호화 통신을 위해 사용하는 인증서를 선택해야한다.

이미 만든 인증서가 있다면 그걸 사용해도 되지만 없을테니 이 창이 뜰텐데, 권장하는 방법을 쓰자! ㅋㅋㅋ




적혀있듯이 퍼블릭 키와 프라이빗 키는 이 창이 지나가면 다시는 받을 수 없다.

혹시나 못 받았다면 인증서를 새로 만들면 되니 부담은 안가져도 되지만, 잘 가지고 있도록 하자.


활성화는 말 그대로 이 인증서를 사용가능하게 할건지 설정하는건데, 조금 있다가 해도 된다.


정책은 아마 만들어진 정책이 없을테니, 0개 선택으로 두고 일단 넘어가면 된다.




IoT 디바이스가 어떠한 작업을 할 수 있는지 그 권한을 설정하는 정책(Policy)를 만들어야 한다.

참고로 이 정책은 개별 디바이스가 아니라 인증서에 연결된다.


즉, 같은 디바이스라도 사용하는 인증서에 따라 정책이 달라진다.

물론 인증서와 디바이스도 AWS 콘솔에서 연결 작업은 해줘야하지만.


IoT 대시보드 좌측 메뉴에서 보안 - 정책을 찾아가자.



이름을 적당히 설정해주고, 권한을 넣어주자.


작업 항목에는 

iot:Publish / Subscribe / Connect / Receive / UpdateThingShadow / GetThingShadow / DeleteThingShadow

7개 항목이 있지만 지금은 귀찮으니 와일드카드 * 로 사용.

다른건 이름만 봐도 알겠는데 Connect와 Receive 는 왜 있는지 모르겠다.. 나중에 찾아봐야지


리소스 ARN 은 토픽이나 shadow의 리소스 arn 을 넣으면 된다.

arn:aws:iot:<REGION>:<USER ID>:topic/<TOPIC NAME>

의 형태. 참고로 "토픽 이름"에서 와일드카드는 * 이 아니라 + 다.


일단은 테스트 목적이니 이것도 대충 와일드카드로 만들자




그 다음, 정책을 인증서에 연결해줘야 한다.

디바이스에 정책을 연결하는게 아님을 주의.


인증서 메뉴에서 아까 만든 인증서에 방금 만든 정책을 연결해주자.


아까 생성할때 활성화를 안했다면 여기서 활성화를 해줄 수 있다. 나중되면 까먹을테니 지금 활성화 ㄱㄱ





마지막으로 좌측 하단 설정에 들어가서 엔드포인트 URL 을 확인한다.


+ Recent posts