Apr 102017
 

최근 IoT와 원격 및 자동 제어에 개인적인 관심이 생겨 취미 삼아 공부중이다. Raspberry Pi등의 Open source H/W SBC류, Arduino/ESP8266등으로 DIY, 기성 RF/WIFI 센서/스위치등의 해킹, 자동화 플랫폼 OpenHAB 등의 학습 등을 진행하면서 실제 적용을 위해 집 IoT 및 원격/자동 제어 시스템을 구축해 나가려고 한다. 누구라도 관심이 있는 사람이라면 따라할 수 있을 정도의 내용 기술을 목표로 하고는 있는데 어찌 될런지, 얼마나 걸릴런지는 모르겠다.

그 첫번째로 Node-RED에 대해 알아보자. 찾아보면 정말 많은 자동화 플랫폼이 있다. 오픈소스 진영만 해도 OpenHAB2, Domoticz 와 Home Assistant 등 쟁쟁한 녀석들이 많다. 그런데 Node-RED가 첫번째 내용이 되어야 하는데에는 나름의 이유가 있다.

Node-RED는 Node.js 기반의 HW, API와 온라인 서비스 등의 “Wiring”해주는 브라우저 기반의 프로그래밍 환경이다. 각각의 기능들은 “Node”로 표현되며, 기본적으로 제공되는 Node들 이외에도 수많은 사람들이 기여한 3rd party Node들을 사용할 수 있다. 그러한 Node들을 브라우저 상에서 “연결”하는 것만으로도 HW, API와 온라인 서비스 등을 쉽게 연동할 수 있게 된다.  예를 들어 기본 제공되는 HTTP input node와 HTTP response node만을 가지고 몇 초 안에 HTTP Restful API를 prototyping할 수 있다. 3rd party node 중 Modbus node와 기본제공되는 MQTT node를 사용하면 Modbus 장치에서 값을 읽어서 MQTT로 push하는 기능을 실제 Modbus 장치 없이도 구현/테스트 가능하다.

http-api-with-mongodb

modbus-to-mqtt

Node-RED는 손쉬운 테스트/디버깅을 가능하게 해준다. 여타 유명한 자동화 플랫폼에서는 해당 플랫폼에서 사용하는 설정 방법이나 특정 파일 형식 등을 사용해서 어떠한 규칙을 기술함으로써 제어, 자동화 혹은 연동이 이뤄진다. 문제는 그러한 방법에 익숙해지지 않고서는 원하고자 하는 것을 구현하기가 그다지 쉽지 않다는 것이다. 또한 테스트도 쉽지 않다. 규칙을 기술하고 나서 장치를 가지고 실제 테스트를 진행해야, 해당 규칙이 잘 동작하는 지 알 수 있다. 하지만 Node-RED는 정말 강력한 테스트/디버깅 기능을 제공한다. Inject node를 통해 수동 혹은 인터벌 trigger를 쉽게 지정할 수 있고, 테스트할 값도 실제 장치없이도 지정할 수 있어서 테스트가 매우 쉽다. 또한 Debugging node를 어느 Node에나 붙일 수 있고, 디버깅 on/off도 쉽게 조절이 가능해야 디버깅 창에서 문제 확인이 바로 바로 가능하다.

inject-and-debugging

Node-RED에서는 자바스크립트 기반의 custom function을 사용할 수 있는데, 자바스크립트 개발 경험이 있는 많은 사람들에게는 정말 반가운 환경이라고 할 수 있다.

custom-function

위에 기술한 3가지 강력한 장점들이 여타의 자동화 플랫폼보다 Node-RED에 좀 더 몰두하도록 만들었지만, 그렇다고 해서 Node-RED가 자동화 플랫폼의 대안이 되기는 아직 시기 상조인듯 하다. 웹기반의 Dash board UI도 있고 사용자 인증도 제공하고, DB 연동도 가능하며, HTTPS 등도 가능하기는 하다. 그래도 그보다는 자동화 플랫폼과 HW/API/온라인 서비스 사이에서 기능별 연동/변환용 시스템으로 사용하는 것이, 현 시점에서는 맞는 활용방법인 거 같다. 자동화 플랫폼들을 보면, 각기 지원되는 기능과 지원되지 않는 기능등이 모두 달라서 그 어느 것 하나 “완벽”하지 않고, 또한 “완벽”할 수도 없다고 생각한다. 그러한 점에서 Node-RED가 그러한 자동화 플랫폼들을 보완해주는 Swiss Army Knife같은 주머니속의 강력한 Middleware system이 될 수 있다고 생각한다.

Mar 172017
 

언제나 그렇듯 클리앙 팁&강좌 게시판과 사용기게시판을 보다가 우연히 acme.sh을 이용한 무료 SSL 자동 갱신에 대한 글을 보았다. 안 그래도 최근 SSL/TLS 적용해야 할 일이 있기도 했기에 바로 착수했다. 우선 목표는 acme.sh(https://github.com/Neilpang/acme.sh)를 이용해서 인증서 자동 갱신 및 갱신 후 아파치 자동 재시작하는 것이다.

acme.sh
Let’s Encrypt 무료 인증서를 자동갱신해주는 쉘스크립트이다. Ubuntu 12.04에서 권한때문에 문제 생기는 게 귀찮아서 acme.sh 실행시 sudo를 사용할 예정인데, crontab에 등록해야 하므로 비밀번호 입력을 생략하기 위해 /etc/sudoer파일을 다음과 같이 수정한다.

vi /etc/sudoer
아이디 ALL=(ALL:ALL) NOPASSWD:ALL

이제 암호를 다시 입력하지 않고도 sudo를 사용할 수 있게 되었다. 만약 권한 문제가 없으리라 생각되면 이 과정은 생략해도 될듯 하다.

acme.sh를 다운받아서 이제 인증서 생성 및 적용하면 되는데, 무슨 이유에서인지 sudo사용시 절대경로를 지정해야만 실행이 되었다.

sudo “/home/아이디/.acme.sh”/acme.sh –issue -d abc.com -w /var/www/wp_abc_com
-d = domain
-w = document root

sudo ~/.acme.sh/acme.sh –issue -d abc.com -w /var/www/wp_abc_com
[Wed Mar 15 13:40:27 EDT 2017] Single domain=’abc.com
[Wed Mar 15 13:40:27 EDT 2017] Getting domain auth token for each domain
[Wed Mar 15 13:40:27 EDT 2017] Getting webroot for domain=’abc.com
[Wed Mar 15 13:40:27 EDT 2017] Getting new-authz for domain=’abc.com
[Wed Mar 15 13:40:28 EDT 2017] The new-authz request is ok.

[Wed Mar 15 13:40:29 EDT 2017] Cert success.
—–BEGIN CERTIFICATE—–

—–END CERTIFICATE—–
[Wed Mar 15 13:40:29 EDT 2017] Your cert is in  /home/아이디/.acme.sh/abc.com/abc.com.cer
[Wed Mar 15 13:40:29 EDT 2017] Your cert key is in  /home/아이디/.acme.sh/abc.com/abc.com.key
[Wed Mar 15 13:40:29 EDT 2017] The intermediate CA cert is in  /home/아이디/.acme.sh/abc.com/ca.cer
[Wed Mar 15 13:40:29 EDT 2017] And the full chain certs is there:  /home/아이디/.acme.sh/abc.com/fullchain.cer

마지막 부분에 인증서가 저장된 위치를 보여주면 인증서 생성이 성공된 것이다. crontab -e 해서 보면 acme.sh에 대한 항목이 이미 생성되어 있는 것을 볼 수 있다. 개인 취향상 자동 지정된 시간을 매일 자정에 맞추었고 sudo지정 및 절대경로로 변경했다.

0 0 * * * sudo “/home/아이디/.acme.sh”/acme.sh –cron –home “/home/아이디/.acme.sh” > /dev/null

아파치에 인증서 갱신 적용하기
이제 아파치에 적용해야 할 시간이다. 그런데 이 부분이 조금 어려웠다. 최초 적용시에는 아무래도 수동으로 직접 인증서를 복사해줘야 하는 것으로 보인다. 복사하지 않고 했더니 자꾸 에러가 났다.

먼저 인증서를 저장한 디렉토리를 생성하자
sudo mkdir /etc/apache2/ssl

이제 생성된 인증서를 복사해넣자.
sudo cp /home/아이디/.acme.sh/abc.com/abc.com.cer /etc/apache2/ssl
sudo cp /home/아이디/.acme.sh/abc.com/abc.com.key /etc/apache2/ssl
sudo cp /home/아이디/.acme.sh/abc.com/fullchain.cer /etc/apache2/ssl

이제는 httpd.conf를 수정해서 https가 사용가능하게 하고, http로 접속시 자동으로 https로 변경되도록 해보자.
sudo vi /etc/apache2/httpd.conf
# Load SSL module
LoadModule ssl_module /usr/lib/apache2/modules/mod_ssl.so

# 기존 VirtualHost를 수정해서 https로 자동 이동되도록 함
<VirtualHost *:80>
ServerName      abc.com
ServerAlias        www.abc.com
DocumentRoot    /var/www/wp_abc_com
#  외부링크방지
SetEnvIfNoCase Referer abc\.com link_allow
SetEnvIfNoCase Referer www\.abc\.com link_allow
SetEnvIfNoCase Referer clien\.net link_allow
SetEnvIfNoCase Referer m\.clien\.net link_allow
SetEnvIfNoCase Referer ^$ link_allow
<FilesMatch “\.(jpe?g|gif|png|bmp|avi|swf|mpe?g|zip|z[00-99]|rar|mp[1-9]|arj|exe|asf|wm[a-z]*|ra[a-z]*|alz|ZIP|Z[00-99])$”>
Order Deny,Allow
Allow from env=link_allow
Deny from all
ErrorDocument 403 /error_page.php
</FilesMatch>
CustomLog /var/log/apache2/abc.com.access.log combined
LogLevel Error
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://abc.com%{REQUEST_URI} [L,R=301]

</VirtualHost>

# 위의 설정을 카피한 후 아래 부분을 변경처리
<VirtualHost *:443>
ServerName      abc.com:443
DocumentRoot    /var/www/wp_abc_com
#  외부링크방지
SetEnvIfNoCase Referer abc\.com link_allow
SetEnvIfNoCase Referer www\.abc\.com link_allow
SetEnvIfNoCase Referer clien\.net link_allow
SetEnvIfNoCase Referer m\.clien\.net link_allow
SetEnvIfNoCase Referer ^$ link_allow
<FilesMatch “\.(jpe?g|gif|png|bmp|avi|swf|mpe?g|zip|z[00-99]|rar|mp[1-9]|arj|exe|asf|wm[a-z]*|ra[a-z]*|alz|ZIP|Z[00-99])$”>
Order Deny,Allow
Allow from env=link_allow
Deny from all
ErrorDocument 403 /error_page.php
</FilesMatch>
CustomLog /var/log/apache2/abc.com.access.log combined
LogLevel Error
# 인증서 설정
SSLEngine on
SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW

SSLCertificateFile /etc/apache2/ssl/abc.com.cer
SSLCertificateKeyFile /etc/apache2/ssl/abc.com.key
SSLCertificateChainFile /etc/apache2/ssl/abc.com.key
# Disable SSL V2 and V3
SSLProtocol all -SSLv2 -SSLv3
</VirtualHost>

이제는 https 접속을 위해 포트 443이 막혀있다면 방화벽에서 열어줘야 한다.
sudo ufw allow 443

이제 아파치를 재기동(sudo service apache restart)하고 http://abc.com 접속해서 https://abc.com 으로 자동 이동되고 안전한 사이트로 표시되는 지 확인해보자.

다 잘 되었다면 이제 acme.sh가 인증서 갱신 후 아까 생성해둔 디렉토리로 인증서를 복사해넣고 아파치를 재기동하게 해주면 끝이다. 이에 앞서 아까 수동으로 복사해둔 인증서들을 삭제하고 다음 명령을 실행해서 인증서들이 잘 복사되는 지 확인하면 된다.

sudo “/home/아이디/.acme.sh”/acme.sh –install-cert -d abc.com \
–home “/home/아이디/.acme.sh” \
–certpath      /etc/apache2/ssl/abc.com.cer \
–keypath      /etc/apache2/ssl/abc.com.key \
–fullchainpath /etc/apache2/ssl/fullchain.cer \
–reloadcmd    “sudo service apache2 force-reload”

이제 acme.sh가 생성한 설정을 확인해보자. 다음 갱신이 언제인지, 어디로 인증서를 복사해넣을지 등에 대한 설정이 저장되어 있는 것을 볼 수 있을 것이다.

vi /home/아이디/.acme.sh/abc.com/abc.com.conf
Le_Domain=’abc.com
Le_Alt=’no’
Le_Webroot=’/var/www/wp_abc_com’
Le_PreHook=”
Le_PostHook=”
Le_RenewHook=”
Le_API=’https://acme-v01.api.letsencrypt.org’
Le_Keylength=”
Le_LinkCert=’https://acme-v01.api.letsencrypt.org/acme/cert/…’
Le_LinkIssuer=’https://acme-v01.api.letsencrypt.org/acme/issuer-cert’
Le_CertCreateTime=’1489601638′
Le_CertCreateTimeStr=’Wed Mar 15 18:13:58 UTC 2017′
Le_NextRenewTimeStr=’Sun May 14 18:13:58 UTC 2017′
Le_NextRenewTime=’1494699238′
Le_RealCertPath=’/etc/apache2/ssl/abc.com.cer’
Le_RealCACertPath=”
Le_RealKeyPath=’/etc/apache2/ssl/abc.com.key’
Le_ReloadCmd=’sudo service apache2 force-reload’
Le_RealFullChainPath=’/etc/apache2/ssl/fullchain.cer’

이제 Let’s Encrypt 인증서 자동 갱신 적용이 끝났다.

[Updated]
PC 브라우저에서는 문제가 없었는데 안드로이드 크롬에서 보니 insecure로 나와서 다시 확인을 해보았다. certificate chain 파일이 잘못된 듯 했다. acme.sh에서 생성해준 fullchain.cer을 지정해봤으나 타임아웃이 걸릴 정도로 뭔가 문제가 있었고… 구글 검색을 통해 https://whatsmychaincert.com/ 에 가서 사이트명 넣고 chain cert파일을 다운로드 받은 후 http.conf에 적용했다.

SSLCertificateChainFile /etc/apache2/ssl/abc.com.chain.crt

아파치 재부팅 후 테스트해보니 pc와 안드로이드 모두 제대로 나온다.

Mar 042017
 

Rule작성법을 연습하기 위해 PushBullet 연동을 해보았다. Kankun wifi plug의 상태가 변할 때마다 push notification을 받을 수 있도록 OpenHAB2 rule을 작성하면 된다.

*PushBullet api token 준비
Pushbullet에서 Account setting페이지를 가보면 Access token을 생성할 수 있다.

*Rule 작성
sudo -u openhab vi /etc/openhab2/rules/switch.rules 해서 다음을 입력

rule “switchOn”
when
Item mqttsw1 changed from OFF to ON
then
executeCommandLine(“curl@@-k@@-H@@Access-Token: 토큰키@@-XPOST@@https://api.pushbullet.com/v2/pushes@@-H@@Content-Type: application/json@@–data-binary@@{\”type\”: \”note\”, \”title\”: \”스위치1 상태”, \”body\”: \”현재 On입니다.\”}@@”)

end

rule “switchOff”
when
Item mqttsw1 changed from ON to OFF
then
executeCommandLine(“curl@@-k@@-H@@Access-Token: 토큰키@@-XPOST@@https://api.pushbullet.com/v2/pushes@@-H@@Content-Type: application/json@@–data-binary@@{\”type\”: \”note\”, \”title\”: \”스위치1 상태\”, \”body\”: \”현재 Off입니다.”}@@”)
end

스위치를 On/Off하면 이제 푸쉬메시지가 온다.

Mar 042017
 

이상하게 들리겠지만, 기본적으로 OpenHAB2는 UI(관리 페이지)에 대해 사용자 인증이 없다. 이 얘기는 관리자 페이지를 외부 접속이 되게 하면, 무방비로 노출이 된다는 얘기다. 이것에 대해 여러 보완책이 있는데 OpenHAB cloud connector를 사용해보기로 했다.

*overrides.propertie파일로 인한 에러를 막기 위해 빈 파일 생성
sudo -u openhab touch /var/lib/openhab2/etc/overrides.properties

*Paper UI의 Add-on메뉴에서 Misc항목에 있는 OpenHAB cloud connector를 설치
이상하게 Installing이 멈추지 않는데, 그래도 괜찮은듯 하다

*uuid와 secret
다음 파일의 내용을 적어둔다
/var/lib/openhab2/uuid
/var/lib/openhab2/openhabcloud/secret

*myopenhab.org에서 위에서 생성한 uuid와 secret을 가지고 회원 가입

*가입시 사용한 이메일 확인하면 인증메일이 와 있다. 메일내의 링크를 클릭해서 인증 완료

*openhab2 재시작
sudo /etc/init.d/openhab2 stop
sudo /etc/init.d/openhab2 start

*myopenhab.org에 로그인하면 다음과 같은 메시지가 나오고 링크를 클릭하면 관리자 페이지 접근이 가능함
You are using openHAB 2.x. Click here to access your openHAB’s dashboard

*안드로이드 OpenHAB 앱의 Settings에 Remote URL = https://myopenhab.org와 가입한 id/pw를 입력하고 URL에 적었던 url/ip를 삭제 후 제어/모니터링 되는지 확인

*이제 myopenhab.org를 통해 접근이 되므로 Paper UI를 외부 접근이 안되도록 만들면 된다.
sudo -u openhab vi /var/lib/openhab2/etc/org.ops4j.pax.web.cfg 후 다음처럼 변경 후 openhab2 재시작
org.ops4j.pax.web.listening.addresses = 127.0.0.1

sudo /etc/init.d/openhab2 stop
sudo /etc/init.d/openhab2 start

*주의
관리페이지에 대해 방화벽을 열어놔야 한다. 방화벽을 열어도 OpenHAB2가 127.0.0.1에 대해서만 응답하므로 걱정하지 않아도 된다.

Mar 012017
 

(1) Mosquitto client(No-SSL 버전) 설치
다음의 두 명령어를 Kankun wifi plug에 SSH 접속 후 실행하면 MQTT client 중 하나인 mosquitto_pub과 mosquito_sub가 설치된다.
[Kankun] opkg update
[Kankun] opkg install mosquitto-client-nossl

(2) 메시지 송수신 테스트
[MQTT] mosquitto_sub -h localhost -t /testsw/1/state -u user_1  -P password_1 실행해서 메시지 수신 대기
[Kankun] mosquitto_pub -h mqtt_server_ip -t /testsw/1/state -m 1 -u user_1  -P password_1 실행해서 메시지 송신해서 MQTT서버측에 잘 송신되는지 확인

[Kankun] mosquitto_sub -h mqtt_server_ip -t /testsw/1/state -u user_1  -P password_1 실행해서 메시지 수신 대기
[MQTT] mosquitto_pub -h localhost -t /testsw/1/state -m 1 -u user_1  -P password_1 실행해서 메시지 송신해서 Kankun 스위치쪽으로 잘 송신되는지 확인

2번의 테스트를 통해 망이나 방화벽 상관없이 외부 MQTT 서버를 통해 메시지가 문제없이 송수신 됨을 확인했다. 즉, 스위치가 어떤 환경에 있던지 상관없이 외부망에 있는 브로커를 통해 어디서든 통신이 가능하다는 점을 확인한 것이다.

(3) Kankun 스위치에서 현재 상태 publish
[Kankun] mkdir /root/scripts

[Kankun] vi /root/scripts/mqtt_publish.sh해서 다음을 입력

#!/bin/sh

while true
do
CURR_STATUS=”`cat /sys/class/leds/tp-link:blue:relay/brightness`”
mosquitto_pub -h mptt_server_ip -t /testsw/1/state -u user_1 -P password_1 -m $CURR_STATUS
sleep 5
done

[Kankun] chmod 755 /root/scripts/mqtt_publish.sh

[Kankun] vi /etc/profile해서 다음을 추가
/root/scripts/mqtt_publish.sh &

[Kankun] reboot 실행해서 재부팅

[Kankun] echo “1” > /sys/class/leds/tp-link:blue:relay/brightness 해서 안드로이드앱의 스위치 상태가 ON으로 변경되는지 확인

[Kankun] echo “0” > /sys/class/leds/tp-link:blue:relay/brightness 해서 안드로이드앱의 스위치 상태가 OFF으로 변경되는지 확인

(4) MQTT 서버에서 Kankun 스위치 제어
[Kankun] mkdir /root/work

[Kankun] vi /root/scripts/mqtt_subscribe.sh해서 다음을 입력
#!/bin/sh

mosquitto_sub -h mqtt_server_ip-t /testsw/1/command -u user_1-P password_1 >> /root/work/mqtt.dat 2>/dev/null

[Kankun] chmod 755 /root/scripts/mqtt_subscribe.sh

[Kankun] vi /etc/profile해서 다음을 추가
/root/scripts/mqtt_subscribe.sh &

[Kankun] vi /root/scripts/mqtt_command.sh 해서 다음을 입력
#!/bin/sh

while true
do
if [ -e /root/work/mqtt.dat ]; then
COMMAND=”`tail -1 /root/work/mqtt.dat`”
fi

if [ “$COMMAND” = “1” ]; then
echo “1” > /sys/class/leds/tp-link:blue:relay/brightness
elif [ “$COMMAND” = “0” ]; then
echo “0” > /sys/class/leds/tp-link:blue:relay/brightness
fi
echo “” > /root/work/mqtt.dat
sleep 5
done

[Kankun] chmod 755 /root/scripts/mqtt_command.sh

[Kankun] vi /etc/profile해서 다음을 추가
/root/scripts/mqtt_command.sh &

[Kankun] reboot 실행해서 재부팅

[OpenHAB앱] 스위치 ON –> [Kankun] cat /sys/class/leds/tp-link:blue:relay/brightness 했을 때 1이 되는지 확인(5초 소요)

[OpenHAB앱] 스위치 OFF –> [Kankun] cat /sys/class/leds/tp-link:blue:relay/brightness 했을 때 0이 되는지 확인(5초 소요)

Notes. 스위치를 추가할 때 변경해야 하는 부분들
– /etc/openhab2/item/switch.items에 스위치별 topic(제어용/모니터링용) 선정 후 스위치 추가
– /etc/openhab2/sitemap/Test.sitemap에 추가된 스위치 추가
– /etc/mosquitto/mosquitto.acl에 추가된 topic을 사용자별로 추가
– Kankun 스위치에 위의 스크립트를 복사해 넣고 topic을 변경

기나긴 설정과 테스트의 끝에 드디어 Kankun wifi plug를 OpenHAB2 + MQTT 기반으로 제어 및 모니터링에 성공했다. 전용앱으로 쉽게 갈 수 있는 길을 어렵게 간 듯 하지만, 나중에 구현할 Follow Me 기능(특정 스마트폰이 집안 인터넷에 무선랜 접속시 뭔가를 하거나, 무선랜에서 접속이 사라지면 뭔가를 하거나 하는 등의 기능)을 위해서는 OpenHAB과 MQTT가 꼭 필요했다. 언제 다시 할 수 있을지는 모르겠지만…

« 1 2 3 4 5 6 7 8 9 10 11 12 ... 66 »