여기서 구글 클라우드 계정 생성, API 접속, 라즈베리 파이 구글 클라우드 IoT 연결에 대해 학습하고, 간단한 파이썬 스크립트를 실행하여 데이터가 클라우드로 제대로 전송되고 돌아오는지 알아본다. 그리고 간단한 데모를 만들어본다. 버튼을 누르면 메시지, LED 상태, 그리고 시간으로 구성된 원격데이터를 구글 클라우드로 보내게된다. 그리고 구글 클라우드에서 장치 상태 데이터를 변경하여 라즈베리 파이에 연결된 2개의 LED 를 껐다가 켜는 데모를 진행해본다.
Step #1: Create a Google Cloud account
먼저 구글 클라우드 계정을 생성하고, 클라우드 콘솔로 진입한다. Google Cloud IoT Core 사용을 선택하여 활성화한 후 라즈베리 파이를 위한 레지스트리를 생성한다.
레지스트리 만들기를 누른다.
레지스트리 기기의 데이터를 저장할 지역과 ID 를 입력한다.
다음으로 Pub/Sub 주제를 선택한다. 기본 telemetry 토픽을 선택한 상태에서 [주제 만들기]를 클릭한다. 주제 ID 를 입력하고 주제 만들기를 누른다 (여기서 암호화 방식은 문제되지 않는다). 방금 생성한 주제는 기기의 telemetry 와 state 데이터를 저장한다. 다음으로 디바이스 상태 주제 섹션에서, 방금 만든 주제를 선택한다. Stackdriver Logging 섹션은 None 으로 그냥 둔다.
아래와 같이 레지스트리를 만든다. 프로토콜 이하 내용은 고급옵션 보기를 클릭하면 확인할 수 있다.
프로젝트에 필요한 프로토콜을 선택해야 한다. 여기서는 MQTT 를 사용하지만 HTTP 를 선택되어 있는 상태 그대로 둬도 무방하다.
페이지 하단의 만들기를 눌러서 레지스트리 생성을 마친다. 그러면 다음과 같이 IoT Core 메인 페이지로 돌아오게 Google IoT Core에 대한 자세한 내용은 여기 를 참조한다.
Step #2: Set up and configure Raspberry Pi
이제 “Hello, world!” 를 만들 차례다. 임베디드 엔지니어 입장에세는 새로운 마이크로컨트롤러에 LED 가 깜박거리는 것이 바로 “Hello, world!”라고 생각하면 되겠다. 클라우드를 통해 LED 가 깜박거리고 브레드보드의 버튼을 클릭해서 라즈베리의 JSON 상태값을 전송받는 파이썬 스크립트를 실행해보자.
SD 카드에 라즈베리 파이 시스템을 설치해두어야 한다. OS 설치 후, 라즈베리 파이를 리부팅한다. SD 카드를 카드 리더기에 넣고, 마우스 및 키보드를 USB 포트에 꽂는다. 그리고 HDMI 케이블을 모니터에 연결한다. 그리고 전원케이블을 연결하면 라즈베리 파이가 부팅을 시작한다. 본 튜토리얼을 진행하기 위해서는 와이파이에 또는 이더넷 케이블에 연결되어 있어야 한다는 점도 잊지말자.
1. OS 패키지 업데이트 및 업그레이드를 진행한다.
pi@raspberrypi:~ $ sudo apt-get update && sudo apt-get upgrade
만약 아래와 같이 command not found 에러가 뜨면 호스트네임이나 패스워드를 변경하고 나서 재부팅을 하지 않았는지 확인해보자.
pi@raspberrypi:~ $ sudo apt-get update && sudo apt-get upgrade
-bash: sudo: command not found
https://www.raspberrypi.org/forums/viewtopic.php?t=220985
2. git 다운로드 및 설치
pi@raspberrypi:~ $ sudo apt-get install git
Reading package lists... Done
Building dependency tree
Reading state information... Done
git is already the newest version (1:2.20.1-2+deb10u3).
The following packages were automatically installed and are no longer required:
libmicrodns0 rpi-eeprom-images
Use 'sudo apt autoremove' to remove them.
0 upgraded, 0 newly installed, 0 to remove and 3 not upgraded.
3. pip3 다운로드 및 설치
pi@raspberrypi:~ $ sudo apt-get install python3-pip
Reading package lists... Done
Building dependency tree
Reading state information... Done
python3-pip is already the newest version (18.1-5+rpt1).
The following packages were automatically installed and are no longer required:
libmicrodns0 rpi-eeprom-images
Use 'sudo apt autoremove' to remove them.
0 upgraded, 0 newly installed, 0 to remove and 3 not upgraded.
4. GitHub 에서 스크립트 다운로드
pi@raspberrypi:~ $ git clone https://github.com/Ivan-koz/GC-IoT_Python_example.git
Cloning into 'GC-IoT_Python_example'...
remote: Enumerating objects: 18, done.
remote: Counting objects: 100% (18/18), done.
remote: Compressing objects: 100% (14/14), done.
remote: Total 18 (delta 4), reused 12 (delta 3), pack-reused 0
Unpacking objects: 100% (18/18), done.
5. 다운로드가 끝나면 example 폴더로 이동한다
pi@raspberrypi:~ $ cd GC-IoT_Python_example/example
pi@raspberrypi:~/GC-IoT_Python_example/example $
6. 가상환경 구현을 위한 virtualenv 설치
pi@raspberrypi:~/GC-IoT_Python_example/example $ sudo pip3 install --upgrade virtualenv
Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
Collecting virtualenv
Downloading https://files.pythonhosted.org/packages/1d/09/9179b676c126b2687bf4110e5b88c8c52d9113f31bd5f8f6ab97d380e434/virtualenv-20.0.30-py2.py3-none-any.whl (7.1MB)
100% |████████████████████████████████| 7.1MB 65kB/s
Requirement already satisfied, skipping upgrade: six<2,>=1.9.0 in /usr/lib/python3/dist-packages (from virtualenv) (1.12.0)
Requirement already satisfied, skipping upgrade: appdirs<2,>=1.4.3 in /usr/lib/python3/dist-packages (from virtualenv) (1.4.3)
Collecting filelock<4,>=3.0.0 (from virtualenv)
Downloading https://files.pythonhosted.org/packages/93/83/71a2ee6158bb9f39a90c0dea1637f81d5eef866e188e1971a1b1ab01a35a/filelock-3.0.12-py3-none-any.whl
Collecting importlib-metadata<2,>=0.12; python_version < "3.8" (from virtualenv)
Downloading https://files.pythonhosted.org/packages/8e/58/cdea07eb51fc2b906db0968a94700866fc46249bdc75cac23f9d13168929/importlib_metadata-1.7.0-py2.py3-none-any.whl
Collecting distlib<1,>=0.3.1 (from virtualenv)
Downloading https://files.pythonhosted.org/packages/f5/0a/490fa011d699bb5a5f3a0cf57de82237f52a6db9d40f33c53b2736c9a1f9/distlib-0.3.1-py2.py3-none-any.whl (335kB)
100% |████████████████████████████████| 337kB 1.3MB/s
Collecting zipp>=0.5 (from importlib-metadata<2,>=0.12; python_version < "3.8"->virtualenv)
Downloading https://files.pythonhosted.org/packages/b2/34/bfcb43cc0ba81f527bc4f40ef41ba2ff4080e047acb0586b56b3d017ace4/zipp-3.1.0-py3-none-any.whl
Installing collected packages: filelock, zipp, importlib-metadata, distlib, virtualenv
Successfully installed distlib-0.3.1 filelock-3.0.12 importlib-metadata-1.7.0 virtualenv-20.0.30 zipp-3.1.0
7. 가상환경 생성 및 활성화
pi@raspberrypi:~/GC-IoT_Python_example/example $ virtualenv env && source env/bin/activate
created virtual environment CPython3.7.3.final.0-32 in 1166ms
creator CPython3Posix(dest=/home/pi/GC-IoT_Python_example/example/env, clear=False, global=False)
seeder FromAppData(download=False, pip=bundle, setuptools=bundle, wheel=bundle, via=copy, app_data_dir=/home/pi/.local/share/virtualenv)
added seed packages: pip==20.2.1, setuptools==49.2.1, wheel==0.34.2
activators BashActivator,CShellActivator,FishActivator,PowerShellActivator,PythonActivator,XonshActivator
(env) pi@raspberrypi:~/GC-IoT_Python_example/example $
8. 필수 패키지 설치
(env) pi@raspberrypi:~/GC-IoT_Python_example/example $ pip3 install -r requirements.txt
Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
Collecting cryptography==2.5
Downloading https://www.piwheels.org/simple/cryptography/cryptography-2.5-cp37-cp37m-linux_armv7l.whl (933 kB)
|████████████████████████████████| 933 kB 28 kB/s
Collecting pyjwt==1.7.1
Downloading PyJWT-1.7.1-py2.py3-none-any.whl (18 kB)
Collecting paho-mqtt==1.4.0
Downloading https://www.piwheels.org/simple/paho-mqtt/paho_mqtt-1.4.0-py3-none-any.whl (48 kB)
|████████████████████████████████| 48 kB 1.9 MB/s
Collecting RPi.GPIO==0.7.0
Downloading https://www.piwheels.org/simple/rpi-gpio/RPi.GPIO-0.7.0-cp37-cp37m-linux_armv7l.whl (69 kB)
|████████████████████████████████| 69 kB 3.0 MB/s
Collecting asn1crypto>=0.21.0
Downloading asn1crypto-1.4.0-py2.py3-none-any.whl (104 kB)
|████████████████████████████████| 104 kB 1.0 MB/s
Collecting six>=1.4.1
Downloading six-1.15.0-py2.py3-none-any.whl (10 kB)
Collecting cffi!=1.11.3,>=1.8
Downloading https://www.piwheels.org/simple/cffi/cffi-1.14.2-cp37-cp37m-linux_armv7l.whl (345 kB)
|████████████████████████████████| 345 kB 122 kB/s
Collecting pycparser
Downloading pycparser-2.20-py2.py3-none-any.whl (112 kB)
|████████████████████████████████| 112 kB 7.2 MB/s
Installing collected packages: asn1crypto, six, pycparser, cffi, cryptography, pyjwt, paho-mqtt, RPi.GPIO
Successfully installed RPi.GPIO-0.7.0 asn1crypto-1.4.0 cffi-1.14.2 cryptography-2.5 paho-mqtt-1.4.0 pycparser-2.20 pyjwt-1.7.1 six-1.15.0
WARNING: You are using pip version 20.2.1; however, version 20.2.2 is available.
You should consider upgrading via the '/home/pi/GC-IoT_Python_example/example/env/bin/python -m pip install --upgrade pip' command.
(env) pi@raspberrypi:~/GC-IoT_Python_example/example $
9. RSA 키 생성
(env) pi@raspberrypi:~/GC-IoT_Python_example/example $ openssl genpkey -algorithm RSA -out rsa_private.pem -pkeyopt rsa_keygen_bits:2048 && openssl rsa -in rsa_private.pem -pubout -out rsa_public.pem
................................+++++
...............+++++
writing RSA key
(env) pi@raspberrypi:~/GC-IoT_Python_example/example $
10. Google CA root certificate 다운로드
(env) pi@raspberrypi:~/GC-IoT_Python_example/example $ wget https://pki.goog/roots.pem
--2020-08-17 01:38:50-- https://pki.goog/roots.pem
Resolving pki.goog (pki.goog)... 216.239.32.29, 2001:4860:4802:32::1d
Connecting to pki.goog (pki.goog)|216.239.32.29|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 72865 (71K) [application/x-pem-file]
Saving to: ‘roots.pem’
roots.pem 100%[==============================================>] 71.16K --.-KB/s in 0.1s
2020-08-17 01:38:51 (709 KB/s) - ‘roots.pem’ saved [72865/72865]
(env) pi@raspberrypi:~/GC-IoT_Python_example/example $
이제 구글 클라우드 콘솔 레지스트리 메뉴로 돌아가서 이제 새로운 기기를 생성할 차례다. 기기명을 입력하고 인증 부분에서는 rsa_public.pem 에 포함된 공개키 필드 값을 입력한다.
공개 키 값에는 example 폴더에 들어있는 ras_public.pem 파일의 내용을 복사해서 붙여넣는다.
다음과 같이 터미널에서 해당 파일을 열어볼 수 있다. 생성을 하고 나면, 이제 해당 기기는 Google Cloud IoT 에 연결되게 된다.
다음과 같이 새로운 기기가 생성되었다.
Step #3: Blink an LED through Google Cloud IoT
이제 IoT 기기를 조립할 차례이다. 본 튜토리얼 진행에 필요한 부품은 다음과 같다.
- Raspberry Pi 3 Model B
- Digilent 240-131 Breadboard
- LEDs (1 green and 1 red)
- 510 ohm resistors (x2)
- Button
- 10k ohm resistor
- Jumper wires
저항값 읽는 방법은 아래 링크에서 확인할 수 있다.
http://www.realomega.com/publish/raspberry-pi_kor_25-5-4/
GPIO Pin Assignments 정보는 아래 이미지를 참고한다.
부품 준비가 끝났으면 다음과 같이 연결한다.
- 1번에는 3.3 V 파워
- 6번에는 그라운드
- 12번(BCM 18)에는 적색 LED 양극(anode), 음극(cathode)은 510옴 저항을 통해 그라운드로 연결
- 11번(BCM 17)에는 녹색 LED 양극(anode), 음극(cathode)는 510옴 저항을 통해 그라운드로 연결
- 버튼은 40번(BCM 21)과 3.3 V 라인 연결 (10k 옴 저항과 그라운드로 연결)
조립을 마치면 다음의 형태가 된다.
이제 example.py 의 각종 파라메터를 여러분의 GCP 설정에 맞춰서 수정한다.
- project_id : 구글 클라우드 콘솔에서 확인가능
- registry_id : 레지스트리 이름으로 IoT Core 탭에서 찾을 수 있다
- device_id : 기기이름
- cloud_region : 프로젝트의 위치
나머지 값들은 그대로 둔다. 이제 다음과 같이 스크립트를 실행한다. 파라메터가 제대로 입력이 되었다면 다음의 메시지를 볼 수 있다.
(env) pi@raspberrypi:~/GC-IoT_Python_example/example $ python3 example.py
Creating JWT using RS256 from private key file rsa_private.pem
Connection Result: 0: No error.
Subscribed: (1,)
Received message '' on topic '/devices/tabularasa/config' with Qos 1
스크립트 실행중에 브레드보드의 버튼을 눌러보자. 다음과 같은 기기 상태 정보를 볼 수 있다.
(env) pi@raspberrypi:~/GC-IoT_Python_example/example $ python3 example.py
Creating JWT using RS256 from private key file rsa_private.pem
Connection Result: 0: No error.
Subscribed: (1,)
Received message '' on topic '/devices/tabularasa/config' with Qos 1
Publishing payload {
"num_message": 1,
"led1": false,
"led2": false,
"message": "Hello",
"time": "2020-08-17 06:07:15"
}
Published message acked.
Step #4: Exchange device data with Google Cloud
구글 클라우드로부터 데이터를 받기 위해서는 pub/sub 구독을 통해 메시지를 당겨와야 한다. 검색창에 “pub/sub” 라고 검색하면 Pub/Sub 토픽으로 이동할 수 있다. 아래와 같이 구독을 만든다.
ID 필드에 구독명을 입력하고, 주제명을 projects/<project-id>/topics/<topic-name> 포맷으로 선택한다. 전송유형을 가져오기(Pull)로 선택한다. 나머지 설정은 그냥 둔다. . At this point, the other settings don’t matter, so go ahead and click Create.
Cloud Shell API 를 사용하여 SDK Shell 에 로그인한 후 다음과 같이 실행한다. 그러면 아래와 같이 라즈베리 파이로부터 받은 telemetry 데이터 테이블을 볼 수 있다.
기기로 데이터를 전송하기 위해, IoT Core > 기기 세부정보로 이동하여 기기를 선택한 뒤 Update Config 버튼을 누른다.
그리고 다음과 같이 구성값을 입력한다. {"led1": true, "led2": true} 그리고 기기로 보내기를 클릭한다. 기기가 연결된 상태라면 2개의 LED 모두 불이 들어오는 모습을 볼 수 있을 것이다. 파라메터값을 변경함으로써 LED 를 껐다가 켤 수 있다. 본 예제에서는 LED1 이 적색이고, LED2 가 녹색이다.
pi@raspberrypi:~ $ cd GC-IoT_Python_example/example
pi@raspberrypi:~/GC-IoT_Python_example/example $ source env/bin/activate
(env) pi@raspberrypi:~/GC-IoT_Python_example/example $ python3 example.py
Creating JWT using RS256 from private key file rsa_private.pem
Connection Result: 0: No error.
Subscribed: (1,)
Received message '{"led1": true, "led2": true}' on topic '/devices/tabularasa/co nfig' with Qos 1
Led1 is on
Led2 is on
Publishing payload {
"num_message": 1,
"led1": true,
"led2": true,
"message": "Hello",
"time": "2020-08-17 12:13:07"
}
Published message acked.
Received message '{"led1": true, "led2": false}' on topic '/devices/tabularasa/config' with Qos 1
Led2 is off
Received message '{"led1": false, "led2": false}' on topic '/devices/tabularasa/config' with Qos 1
Led1 is off
Received message '{"led1": true, "led2": true}' on topic '/devices/tabularasa/config' with Qos 1
Led1 is on
Led2 is on
Received message '{"led1": false, "led2": false}' on topic '/devices/tabularasa/config' with Qos 1
Led1 is off
Led2 is off
완성된 모습이다.
[원문출처]