OpenCV 학습을 위한 스테레오 카메라 테스트

다시금 4족 보행 로봇에 관심을 기울이게 되면서 기왕이면 OpenCV를 이용하여 Object Detection을 구현하고
낮은 수준의 자율주행 기능을 포함시키고 싶었다. 하지만 새로운 것을 공부해야 한다는 부담감 때문에 섣불리
손을 못대고 있다가 본능에 따라 한 번 들이대보기로 하였다.

 

아직은 정리할만큼도 학습을 못했기 때문에 실제 OpenCV에 대해서는 언급할 내용이 없고 오늘은 카메라에 대한
이야기나 조금 찌끄려보려고 한다.

 

USB Web CAM을 이용한 스테레오 카메라

사실 라즈베리파이에서 카메라 모듈을 2개 이상(4개까지) 연결하여 사용할 수 있는 모듈이 있다. 하지만 가격이
만만치 않다(6~7만원 선). 게다가 파이 카메라 모듈도 필요하고(그나마 V1.3 만 지원한다고 하니 파이 카메라
가격은 좀 저렴하게 구성할 수 있다), 어쨌든 대충 계산해도 한 10만원은 있어야 스테레오 카메라를 구성할 수
있을 것이다.

 

라즈베리파이에 4개까지 파이 카메라 V1.3을 연결할 수 있는 모듈

 

그래서 생각한 것이 저렴한 USB 웹캠 2개를 이용하면 되지 않을까 하는 생각이었다. 실제로 그렇게 구현한 예도
유튜브에 종종 보이고…그래서 일단 만원짜리 웹캠을 2개 샀다. 그리고 3D 프린터로 작은 홀더를 2개 만들어서
각각 등짝에 하나씩 붙여주고 8∅짜리 스테인레스 파이프로 연결하여 고정해주었다. 

 

 

그리고 라즈베리파이에 USB 웹캠을 연결을 하고 샘플 코드를 돌려보았다.
하지만…언제나 그렇듯이 유튜브에서 보여지는 것은 F1 레이싱카였지만 내가 돌리는 것은 애기들 태우는 전동차
수준…ㅠ.ㅠ 하드웨어 문제인지 뭔가 추가적인 코드가 더 필요한 것인지 영상이 엄청 끊기는데다가 2대의 카메라
영상이 거의 동기화가 되지 않았다…ㅠ.ㅠ

 

 

 

일단 바로 해볼 수 있는 해결 방법은 영상의 크기를 줄이는 방법! 그래서 코드에서 카메라 영상의 크기를 320X240
으로 줄이고 다시 시도해보았다. 역시나 사이즈가 작아지니 영상 끊김도 거의 없고 두 영상이 어느정도 동기화 되는
모습을 볼 수 있었다. 하지만 아직도 만족스러운 정도는 아니었다.

 

 

 

ELP Dual lense USB Camera module

계속해서 스테레오 카메라를 알아보고 있었는데 올 초부터 눈에 밟히는 녀석이 하나 있었다. 물론 전문적인 용도는
아니고 그냥 가볍게 사용해볼 수 있을만한 제품으로 보였다. 그럼에도 가격대는 역시 8만원대로 그리 만만한
녀석은 아니었다.

 

그리고…마침 로봇에 꽂혀 이것 저것 부품을 마련하는데 돈이 필요했던 나는 예전에 빅데이터와 클러스터링을
한번
 공부해보겠다고 어렵게 모은 맥미니 5대 중 3대를 팔아버리고 말았다…ㅠ.ㅠ 물론 가격은 구입 당시의 반토막
…ㅠ.ㅠ

 

그렇게 돈을 마련하고 제일 먼저 알리에서 이 제품을 구매했다. 그리고 생각보다 배송이 일찍되어 오늘 이렇게
라즈베리파이에 연결하여 확인을 해볼 수 있었다.

 

 

일단 하나의 모듈로 만들어진 제품이기 때문에 두 카메라로 입력된 영상이 하나의 영상의로 합쳐져 출력되었고
코드상에서도 하나의 VideoCapture 클래스만 사용하면 되었다. 영상의 동기화도 훌륭하고 기본으로 출력되는
320X240 정도의 크기(두 영상이 합쳐서 나오기 때문에 실제 가로는 640)에서는 영상 프레임도 상당히 좋은
수준을 보여줬다.

 

 

영상 사이즈를 640X480(전체 사이즈 1280X480)으로 출력했을 때도 영상이 끊기는 문제는 있었지만 적어도
프리징 되지는 않았고 동기화는 원활했다.

 

 

다만 사용하다보니 발열이 좀 있었고 하나의 영상의 입력되기 때문에 나중에 여러가지 처리를 하기 위해서는
영상을 둘로 나누는 코드가 필요할
것이다. 설마 이정도 코드 추가가 성능 저하를 일으키진 않겠지…-.-

 

정리

아직 이렇다할 작업 내용이 없어서 오늘은 2대의 웹캠을 이용한 것과 하나의 모듈로 구성된 2대의 카메라를 이용한
것의 영상 출력만을 비교해보았다. 앞으로 어느정도 학습이 진행이 되면 OpenCV에 대한 실습 내용을 위주로
블로그에 정리를 해보도록 하겠다.

블로그 이미지

마즈다

이미 마흔을 넘어섰지만 아직도 꿈을 좇고 있습니다. 그래서 그 꿈에 다가가기 위한 단편들을 하나 둘 씩 모아가고 있지요. 이 곳에 그 단편들이 모일 겁니다...^^



2019/05/13 - [Study/인공지능학습] - [인공지능] coral usb accelerator + Raspberry pi zero w

2019/05/16 - [Study/인공지능학습] - [인공지능] Coral USB Accelerator와 Edge TPU




뭔가 하나를 진득하니 끝내야 하는데…이놈에 호들갑스러운 호기심은 눈밭에 강아지 뛰놀듯한다…
얼른 미니 드론 만들고 다음에 싱글콥터 그 다음에 4족 보행 로봇 최종판을 만들어야 하는데…
도대체 어느세월에...ㅠ.ㅠ


이번 호기심의 대상은 바로 구글에서 엣지 컴퓨팅 보드로 출시한 coral 시리즈 중에 usb 가속기인

coral usb accelerator이다. 페이스북에서 어떤 분이 올려놓으신 엣지 컴퓨팅을 위한 보드들의
성능을 비교한 해외 블로그를 보고 나니 궁금해서 견딜 수가 없었다.


Benchmarking Edge Computing


아직은 책만 줄창 읽어대고 있는 정도의 수준이라 내가 이걸 사서 제대로 써먹을 수나 있을지 의문이었지만
지름의 기본 자세인 '그래도 언젠가는 써먹겠지’라는 마음가짐으로 하나 질렀다.

그리고 다행히도 간단한 테스트 정도는 해볼 수 있었다…^^;



Edge Computing이란?


우선 본론에 들어가기 전에 엣지 컴퓨팅이란 것이 무엇인지 부터 알고 넘어가자.


예전에 메인프레임을 쓸 때는 당연한 일이었고 웹 기반의 시스템이 자리를 잡은 후에도 대부분의 중요한

연산은 서버에서 처리를 하고 클라이언트 기기(PC)에서는 자료를 입력하는 정도의 기능만 수행을 했다.

그만큼 서버는 강력한 기능을 갖고 있었고 클라이언트로부터 전송되는 데이터들은 서버가 감당하기에

충분한양이었다.


하지만 스마트폰이 지배하는 세상이 되면서 클라이언트의 종류와 그로부터 전송되는 데이터는 점점 증가를

하게 되었고 급기야 IoT라는, 모든 것을 인터넷에 연결시키겠다는 야심찬 시도가 진행되면서 이제 클라이언트는

그 종류를 한정할 수 없게 되었고 그 수많은 클라이언트들로부터 올라오는 데이터의 양은 서버가 감당하기 어려운

상황이 되어버렸다.


한편, 스마트폰을 시작으로 한 클라이언트 기기들은 소형화와 고성능화로 인해 웬만한 작업은 그 기기 내에서 처리를

할 수 있게 되었다. 예전같으면 워크스테이션에서나 가능했을 동영상 편집을 스마트폰에서도 할 수 있게 된 것이다.

상황이 이렇다보니 클라이언트 기기를 단순히 서버로 데이터를 전송하는 용도로만 사용하는 것이 엄청난 자원의 낭비가

된 것이다.


결국 가능한 한 클라이언트에서 처리할 수 있는 부분은 처리를 하고 서버에서는 연산에 높은 성능이 필요한 부분을

처리하려는 시도를 하게 되었고 이 과정에서 클라이언트 측에서 처리되는 부분을 Edge Computing이라고 부르게

되었다.


하지만 아무리 클라이언트 기기들의 성능이 좋아졌다고 해도 머신러닝이나 딥러닝을 처리하기에는 한계가 있다보니

이러한 고성능의 연산을 보조해주기 위한 많은 장치들이 개발되었다. 그 자체로 보드형태를 가지고 나온 제품과

기존의 소형 컴퓨터 보드인 라즈베리파이 등에 연결해서 사용 가능한 USB 기기 형태로 나온 제품들이 있는데

처음 소개한 블로그에서는 바로 이러한 기기들의 성능을 벤치마킹하고 있는 것이다.



무엇을 선택할 것인가?


이 블로그를 보면 몇가지 대상에 대해 상당히 많은 항목을 벤치마킹 하고 있다. 하지만 영어 울렁증의 도움으로

아주 가볍게 한 가지를 선택할 수 있었다. 바로 제일 처음 나오는 추론 속도에 대한 벤치마킹을 기준으로 가장

가성비가 높은 제품을 고르기로 한 것이다.


일단 추론 속도에 대한 벤치마킹 그래프를 보면 구글의 coral 시리즈가 매우 성능이 좋다. 그래서 1차로 coral 
시리즈를 구입하기로 결정을 했다(사실 인텔의 NCS2를 더 먼저 알게 되었고 디자인도 NCS2의 사이버틱한

디자인이 더 마음에 들었지만 벤치마킹 결과와 가성비에서 탈락했다).


라즈베리파이가 없었다면 완전체인 coral dev board를 구입했겠지만 이미 예전에 빅데이터 클러스터 공부한다고

깝죽대면서 사다놓은 라즈베리파이가 수두룩 빽빽하게 있어 비용면에서 더 저렴한 coral usb accelerator로

선택을 했다.





구매는 MOUSER에서 했으며 가격은 $74이다. 배송은 DHL로 약 2일만에 도착을 했고 배송비는 무료다!

생각보다 빨리, 안전하게 도착해서 참 다행이었다(가장 최근의 해외 직구는 banggood에서 주문한 모터를

2달 만에 받은 것이었다…-.-).



장비 연결


현재 집에 있는 라즈베리파이는 3B 모델이 5대, zero w 모델이 2대 있다. 그런데 생각해보니 3B 5대는

클러스터 만들면서 스택 케이스에 다 연결하고 배선까지 꽁꽁 묶어놓아서 도무지 풀어서 사용할 엄두가

나질 않았다.


결국 zero w를 사용하기로 결정을 했는데 이게 또 만만치 않다.라즈베리파이 zero w의 경우 USB포트가

마이크로 USB타입으로 꼴랑 2개 있다. 그나마 하나는 전원공급용이므로 실제 사용 가능한 것은 1개 뿐이다.

게다가 w가 무색하게 빌트인 된 Wi-Fi 모듈은 잘 붙는공유기 찾기가 하늘의 별따기라 어쩔 수 없이 USB 형태의

무선 랜카드를 별도로 사용해야 한다.


이렇게 해서 일단 필요한 USB장비는 벌써 2개가 되었다. USB 랜카드와 coral…여기서 또 한가지 생각지 못한

문제가 생겼다. 라즈베리파이 사 모을 때 파이 카메라 V2 버전을 같이 산 것이 있어 그 걸 사용하려고 했는데…

아뿔싸! 라즈베리파이 3B와 zero w의 카메라용 필름 케이블 소켓 크기가 다르다…OTL 변환 케이블이 있긴 있는데…
돈도 돈이고, 배송도 배송이고…ㅠ.ㅠ


다행히 아이들이 학습용으로 사용하던 USB CAM이 있어서 그걸 사용하기로 했다.
이렇게해서 총 3개의 USB장치를 붙여야 하는 상황이 되었다. 결국 USB 허브까지 하나 구매해서 어찌어찌

연결은 성공하였다~^^ (사진은 카메라 연결 전이다.)


사실 최대한 부피를 줄인 장치를 만들어보고 싶어서 보드로 zero w를 선택한 것인데 결과적으로는 배보다 배꼽이 

더 큰 상황이 되어버렸다. 나중에 기회가 된다면 하우징들은 다 벗겨버리고 연결을 해서 작은 통합 기기를 만들어
보고 싶다(하지만 성능 때문에 zero w는 못쓸 듯…-.-).






라이브러리 설치 및 테스트


공식적으로 coral usb accelerator가 지원하는 기기는 라즈베리파이 2와 3의 모델 B와 B+ 뿐이다.

즉, zero w는 공식적으로는 지원하지 않는 보드이다. 하지만 비공식적으로 설치 가능한 라이브러리가 존재하고

공식 사이트에서도 소개하고 있다. zero w에 대한 라이브러리 설치 방법은 아래 링크에서 확인 가능하다.


support for Raspberry Pi Zero


설치 방법은 매우 간단하며, 압축된 라이브러리 패키지를 다운로드 받고 압축을 해제한 후 install.sh를 실행하면

끝이다. 그리고나서 공식 사이트에 있는 설명대로 데모 프로그램을 돌려보면 된다.우선 설치 후 2개의 데모 프로그램을 

실행해보았다. 이미지 분류와 얼굴 인식을 하는 데모였는데 정상적으로결과가 나오는 것을 확인하였다. 


특히 얼굴 인식의 경우 구글에서 받은 이미지로도 테스트를 해보았는데 대체로잘 인식이 되었으나 특정 사진 한장은 전혀 

인식을 못하였다. 다양한 요인이 있을 것 같은데 정확한 이유는 모르겠다. 맨 처음 사진은 Mobilenet SSD v2에서 제공

되는 사진이고 다음 3장은 구글에서 가져온 사진인데 맨 마지막 사진은 인식에 실패했다.









성능의 문제

사실 지금까지 라즈베리파이를 사용해오면서 딱히 성능을 확인해야 할만큼 부하가 걸리는 작업을 해본 적이
없기에 굳이 따져보지 않았는데 막상 coral usb accelerator를 연결하여 이미지 분류나 인식 작업을 해보니
라즈베리파이 3 모델 B와 zero w 사이에는 엄청난 성능의 차이가 있었다.

라즈베리파이 3 모델 B에서 데모 프로그램 실행 시 얼마나 시간이 걸리는지 측정한 자료가 거의 없어 확인이
쉽지 않았는데 유튜브에서 발견한 동영상 하나에서 대략 5초 정도 걸리는 것을 확인했다.

그런데 zero w 모델에서는 15초 정도의 시간이 걸렸다. 처음에는 coral usb accelerator가 연결되지 않았는지
의심도 해보았으나 연결되지 않은 경우에는 실행 시 오류가 발생을 하였고 또 연결되었을 때 연산 시 LED가 
점멸하는 것도 확인을 하였으니 분명 coral usb accelerator가 작동을 하고 있는 것이었다.






이러한 성능의 문제는 다음에 테스트한 동영상에서의 사물 인식의 경우에 더 심각하게 나타났다.


카메라 테스트


일단 앞서 말한대로 파이 카메라를 사용할 수가 없어 USB Cam을 사용하게 되었다. 
그리고…이미 사물 인식을 하기도 전에 영상은 너무 끊겨서 적당한 수양의 과정을 거치지 않고서는 참고 
보아줄 수 없는수준이었다.

그래도 나름 참는데는 일각연이 있는 터라 테스트를 진행해보았다. 2개의 다른 소스로 진행을 해보았다.
처음 테스트는 아래의 블로그를 참고하였다.

Hands-on with the Google Coral USB Accelerator


사용한 모델 및 실행 코드 정보가 모두 위의 블로그에 정리되어 있다. 그저 다운로드 받고 실행하기만 하면
되는 생각보다 간단한 과정으로 진행할 수 있다. 아래 동영상을 보면 알겠지만 일단 상당히 느리다…ㅠ.ㅠ
인식률 또한 상상했던 것보다 좋지 않은데 두 번째 테스트와 종합적으로 봤을 때 사람과 차에 대한 인식룰은
기가 막히다. 특히 사람은 팔뚝만 슬쩍 보여도 사람으로 인식한다.

하지만 드라이버와 커터는 인식을 못했고 귤은 사과로 인식하거나 햄스터를 새, 개 등으로 인식하고 있었다.
두 번째 동영상은 유튜브에서 영상을 하나 틀어놓고 그 영상을 찍으면서 인식을 시킨 것인데 버스나 차를 대체로
잘 인식하는 것 같았다.






두 번째 테스트는 다음의 2개 사이트를 참고했다.

프미케의 낙서장
https://qiita.com/PINTO/items/dd6ba67643bdd3a0e595


사용한 모델은 첫 번째 테스트와 동일하지만 실행코드가 조금 다르다. 두 번째 테스트용 실행코드에는 초당 프레임

정보가 나오는데 위 링크한 블로그들의 프레임 수와 비교하면 형편없는 수준이다. 그리고 특이한 것이 처음 테스트에서는 
커터를 인식하지 못했는데 두 번째 테스트에서는 커터를 인식하였다.





정리


대체로 뭔가 하나에 관심을 갖게 되어 실행을 해볼 때까지 구입, 준비, 실행의 과정이 꽤나 길었는데 이번에는
관심을 갖게된 후 이 블로그 포스팅을 작성하기까지 정확히 5일 걸렸다. 거의 일사천리로 진행이 된 것이다.
그거 하나로도 위안이 된다…^^;;

하지만 앞에서도 강조했듯이 라즈베리파이 zero w는 작다는 것 외에는 그닥 쓸모가 없다는 것이 판명났다.
적어도 엣지 컴퓨팅에서는…최소한 라즈베리파이 3 모델 B 이상은 되어야 암에 걸릴 확률을 낮출 수 있을것이다.
아직은 내 수준이 남들 발바닥 언저리에서 노는 수준이다보니 근거는 없지만 뭔가 모델들이 사람이나 차량에
특화된 것 같은 느낌이다. 자율주행 RC카 같은 것 만들어보면 재밌을 것 같다.

물론 조금 더 실력이 된다면 수화 번역기 같은 것을 한 번 만들어보고 싶다.

어쨌든 이렇게 또 하나의 가능성을 맛본 것으로 만족하면서 포스팅을 마친다.


블로그 이미지

마즈다

이미 마흔을 넘어섰지만 아직도 꿈을 좇고 있습니다. 그래서 그 꿈에 다가가기 위한 단편들을 하나 둘 씩 모아가고 있지요. 이 곳에 그 단편들이 모일 겁니다...^^






Cluster : The Beginning - Raspberry pi에 HAProxy 설치하기


지난시간 까지 2대의 라즈베리파이에 EMQ를 클러스터링하여 설치하는 작업을 진행하였다.
그런데 한 가지 문제가 생겼다. 일반 가정집에서 공유기를 통해 접속을 하다보니 2대 중 한대로만 접속이 이루어진다는
점이다. 혹시나 해서 공유기의 트래픽 관리에 외부 포트는 동일하게, 내부 서버는 서로 다르게 설정을 해보아도 역시나
가장 마지막에 등록된 정보로만 통신이 이루어졌다.


이렇게 되면 세션은 공유가 되지만 만약 외부에서 접속되는 한 대의 서버가 다운되면 전체 시스템을 사용할 수 없게
되는 것이다. 결국 접속을 분산시킬 필요가 생겼다. 그리고 그렇게 해서 HAProxy라는 솔루션을 찾아내었다.


더불어 애초에 EMQ 2대 Apache Kafka 3대로 클러스터를 구성할 생각이었는데 부랴부랴 HAProxy를 위한 
1대의 라즈베리파이를 추가로 구입하여 총 6대의 클러스터가 되었다.



Clustering과 Load Balancing


일반적으로 성능 향상을 위해 여러대의 서버에 동일한 구성을 하여 함께 운영하는 경우가 많다.
그리고 이렇게 구성하는 경우 Clustering이라든가 Load Balancing이라는 용어가 많이 쓰이는데 과연 
이 둘의 차이는 무엇일까?


가장 단순하게 표현하자면 Clustering은 여러대의 컴퓨터 그룹이 같은 정보를 가지고 함께 일을 하는 것이고
Load Balancing이라는 것은 각각의 컴퓨터가 공평하게 일할 수 있도록 일감을 나누어 주는 것이라고 생각하면
되겠다. 이렇게 정의할 때 Clustering은 같은 정보에 방점이 찍히고 Load Balancing은 나누어 주는
방점이 찍히게 된다. 즉, Clustering은 그룹을 지어 함께 일을 하는 서버간의 관계에 대한 개념이고 Load Balancing은
클라이언트에서 서버로 접속하는 과정에서의 처리에 대한 개념이라고 보면 되겠다.

 



여러 대의 컴퓨터를 대상으로 한다는 것 외에는 서로 다른 개념이고 종속관계를 나눌 수는 없지만
최근 Clustering을 지원하는 솔루션들은 내부적으로 Load Balancing을 함께 지원하는 경향이 있다. 하지만 
Load Balancing을 위한 솔루션이 Clustering을 지원하는 경우는 거의 없다.


예를 들어 1대의 서버로 서비스를 제공할 경우 그 서버가 다운되면 서비스 자체를 제공하지 못하므로 2대의 서버에 
각각 Tomcat을 설치하여 동일한 서비스를 제공하고 싶다고 하자. 각각을 Tomcat1, Tomcat2라고 했을 때
Tomcat1로만 또는 Tomcat2로만 접속이 가능하다면 2대의 서버를 구성한 의미가 없어진다. 그래서 서버 앞단에
Load Balancing을 위한 장비를 두고 적절한 알고리즘을 통해 각각의 클라이언트들이 Tomcat1과 Tomcat2에
적절하게 분산되어 접속하도록 조정을 해주는 것이다.


그런데 Load Balancing만 하는 경우에는 문제가 발생할 수 있다. 아래 그림을 보면 client1과 client2가 Load 
Balancer를 통해 각각 Tomcat1과 Tomcat2로 적절하게 나누어 요청을 수행하고 있다. client1은 Tomcat1에
문서 파일인 B를 업로드 했고 client2는 Tomcat2에 그림파일인 A를 업로드 했다. 그런데 Tomcat2 서버에
장애가 발생하여 접속이 불가능하게 되면 Load Balancer는 이후 모든 접속을 정상 작동 중인 Tomcat1로 보낸다.
이 때 client2의 입장에서는 Load Balancer 이후의 구조에 대해서는 알지 못하므로 분명 자신은 그림 파일 A를
서버에 업로드 했는데 그 업로드한 파일을 찾을 수 없게 된다.




이러한 문제 때문에 보통 Load Balancing을 하면 Clustering도 함께 고려를 해야 한다. 물론 간단하게 Tomcat은
이중화를 하되 DB는 1대만 설치하여 중요 정보만 공유하는 것도 고려해볼 수 있을 것이다.


결론적으로 Clustering과 Load Balancing은 다음과 같이 구분지어 볼 수 있을 것이다.



HAProxy


EMQ의 경우 clustering을 통해 상태 공유는 되지만 클라이언트와 접속하는 지점에서의 load balancing은 별도의
작업을 해주어야 한다. 일반적으로 널리 알려진 load balancing 장비는 L4 Switch라는 하드웨어 장비가 있다.
하지만 개인이 그런 비싼 네트워크 장비를 사용할 수도 없을뿐더러 사용할 필요도 없다…우도살계인 격이다.


그러다가 발견한 것이 HAProxy라는 솔루션이다. S/W적으로 load balancing을 지원해주는 솔루션이었다.
홈페이지는 다음과 같다.

http://www.haproxy.org


사실 HAProxy는 전체 구성요소에서 고려하고 있지 않던 부분이라 아주 기초적인 부분만 확인했다.
자세한 내용은 HAProxy로 검색하면 많은 정보를 얻을 수 있으니 여기서는 간단하게 설치와 설정 그리고
모니터링 웹 콘솔에 대해서만 살펴보겠다.


설치


역시나 소스를 컴파일하는 설치 방법이 많이 검색되는데 나는 심플하게 apt-get으로 설치하였다.


$sudo apt-get install haproxy 


홈페이지에는 현재 최종 릴리즈 버전이 1.9인데 apt-get으로 설치하니 1.7.5-2 버전이 설치되었다.
이렇게 설치하고 나면 /etc아래에 haproxy 디렉토리가 생성되고 그 아래 설정파일인 haproxy.cfg가
위치한다.


설정


HAProxy의 설정은 몇개의 영역으로 구분되는데 간단하게 살펴보면 다음과 같다.


  • global : 이름 그대로 전역 변수에 대한 설정으로 로그, 상태, 소유자 및 소유 그룹 SSL 관련 설정들이 있다.
  • default : 아래 내오는 세부 설정에서 명시적으로 추가하지 않은 설정은 이 default 설정을 따른다.
  • frontend : 클라이언트가 접속하는 것과 관련된 설정이다. 기본적으로 외부에서 접속할 포트 정도 지정한다.
  • backend : frontend와 짝을 지어 설정하며 frontend 설정을 통해 접속한 클라이언트가 실제 요청을 보낼 서버를 지정한다.
  • listener : frontend와 backend를 한번에 설정할 때 사용한다. 주로 TCP 연결에 사용한다.


각 설정의 뒤에는 설정을 대표하는 이름을 적게 된다. 그 이름은 모니터링 화면에 표시하여 구분할 수 있도록 한다.
앞서 EMQ에서와 마찬가지로 내가 설정한 부분만 간단하게 살펴보자. global과 default에서는 유의미한 수정이
없으므로 frontend와 backend 그리고 listener 설정만 보도록 하겠다.


#frontend와 backend 설정은 EMQ의 모니터링을 위한 웹 접속 설정이다.
#외부에서 8080포트로 접속을 하게 되면 backend에 설정된 172.30.1.9 서버와 172.30.1.25 서버의
#18083 포트로 접속을 하게 되는데 이 때 클라이언트를 두 서버로 분배하는 알고리즘은 roundrobin이다.
#mode는 프로토콜을 설정하는 항목인데 여기서는 지정을 안했기 때문에 default 설정에 있는 http 접속을
#처리한다.
frontend http-in 
	bind    *:8080
	default_backend servers

backend servers
	balance roundrobin
	server server1 172.30.1.9:18083 maxconn 2048
	server server2 172.30.1.25:18083 maxconn 2048

#아래 설정은 클라이언트로부터 EMQ boker에 접속하기 위한 설정이다.
#HAProxy를 사용하게 된 것도 바로 이 설정이 필요했기 때문이다.
#외부에서 1883 포트로 접속을 하게 되면 두 서버의 1883 포트로 접속이 분배되며 역시
#분배 알고리즘은 roundrobin이다. 프로토콜을 설정하는 mode는 tcp로 설정한다.
listen  tcp-in
        balance roundrobin
        bind    *:1883
        log     global
        mode    tcp
        option  tcplog
        server  mtqqserver1     172.30.1.25:1883
        server  mtqqserver2     172.30.1.9:1883

#아래 설정은 위 설정과 동일한데 개인적으로 위 내용은 모바일이나 IoT로부터의 접속에 사용하기 위해
#설정하였고 아래 내용은 kafka에서 EMQ broker의 메시지를 subscribe하기 위해 따로 설정하였다.
listen  mqtt-kafka
        bind    *:1884
        mode    tcp
        option  clitcpka
        timeout client 3h
        timeout server 3h
        option  tcplog
        balance leastconn
        server  mtqqserver1     172.30.1.25:1883        check
        server  mtqqserver2     172.30.1.9:1883         check

#이 설정은 HAProxt의 모니터링을 위한 웹 콘솔에 접근하기 위한 설정이다.
#이 설정의 이름은 stats로 정해져 있으며 uri의 경우 주소:포트 뒤에 따라올 문자열로
#임의로 설정하면 된다.
listen  stats
        bind    *:8081
        mode    http
        stats   enable
        stats   uri     /haproxy?stats
        stats   auth    guest:guest
        stats   refresh 5s


기본적으로 이정도만 해도 원하는 바는 얻을 수 있다. 좀 더 세밀한 설정을 위해서는 보다 많은 내용을 추가해야 하지만
앞서 말했듯이 HAProxy는 가볍게 지나가도록 하겠다.


실행


실행과 종료는 간단하게 다음과 같이 하면 된다.


$/etc/init.d/haproxy start
$/etc/init.d/haproxy stop


설정이 바뀌면 다음과 같이 재시작 한다.


/etc/init.d/haproxy restart

모니터링


위 설정에서 이미 모니터링을 위한 웹 콘솔에 대한 설정은 마친 상태이다. 설정에 적힌 포트로 접속만 하면 된다.
설정에 따라 브라우저에 아래 주소를 입력하면 모니터링 화면이 뜬다.


http://localhost:8081/haproxy?stats




테스트


별다른 스크린샷은 올리지 않겠지만 지난 번 포스팅에 설명했던 MQTT 클라이언트로 connect와 disconnect를
반복해보면 EMQ 모니터링 화면의 Clients 메뉴에 한 번은 172.30.1.9 서버로, 한 번은 172.30.1.25 서버로
번갈아 접속되는 모습을 볼 수 있다.


정리


이렇게 해서 갑작스럽게 설치하게 된 HAProxy에 대한 정리를 마친다.
물론 집에서 개인 프로젝트용으로 구성하는 서버에 뭘 이런 것까지 설치해야 하나 싶지만 기왕에 다수의 장비를
구성하게 된 김에 곁들여서 한 번 설치를 해보았고 나름 작동하는 모습을 보니 재미는 있다^^;;;

다음 포스팅에서는 나머지 3대의 라즈베리파이에 Apache Kafka를 설치하고 설정 및 실행시키는 과정을
정리해보도록 하겠다.







블로그 이미지

마즈다

이미 마흔을 넘어섰지만 아직도 꿈을 좇고 있습니다. 그래서 그 꿈에 다가가기 위한 단편들을 하나 둘 씩 모아가고 있지요. 이 곳에 그 단편들이 모일 겁니다...^^







Cluster : The Beginning - Raspberry pi에 MQTT (EMQ) 설치하기


클러스터의 입구 - MQTT


현재 근무하는 곳에서도 ActiveMQ를 쓰고 있고 RabbitMQ도 많이 들어보았지만 정작 MQTT라는 프로토콜에
대해서는 제대로 모르고 있었다. 그저 위에 언급한 시스템들이 message queue를 구현한 것이라고 막연히 알고
있었을 뿐 그 내부에 대해서는 무지했던 것이다(물론 무지한 것은 지금도 마찬가지다…-.-)


그러다가 이번에 IoT와 관련하여 아두이노로 만든 센서 기반의 작은 소품들로부터도 정보를 받아보겠다고 계획하면서
MQTT를 알게 되었다. 이렇게 해서 또 한 가지 배우게 된 것이다…^^


MQTT(Message Queuing Telemetry Transport)란?


일단 간단하게 정의 내려 보면 “Message Queue 기반의 원격 전송 프로토콜” 정도로 말할 수 있겠다.
그럼 Message Queue란 무엇이냐?…라고 계속 묻고 들어가면 끝이 없으니 자세한 내용은 링크로 대신한다…-.-



네이버 지식 백과 : [http://terms.naver.com/entry.nhn?docId=3386832&cid=58369&categoryId=58369]

Wikipedia : [https://en.wikipedia.org/wiki/MQTT]


중요한 것은 이 프로토콜이 경량화(저전력, 낮은 대역폭 등) 된 프로토콜이며 주로 M2M(Machine-to-Machine)
통신에 특화되어 IoT와 밀접하게 관련되어 있다는 것이다.


브로커 선정


이 MQTT 프로토콜을 이용한 통신 구현체는 보통 Broker라 부른다.
이 Broker라는 이름은 Message Queue의 일반적인 통신 방식으로부터 비롯되었는데 양 끝단에 publisher와
subscriber가 있고, 이 publisher와 subscriber 사이에서 message를 ‘중개’해주는 역할을 한다고 하여 이런
이름이 붙게 되었다(아래 이미지는 네이버 지식 백과에서 가져왔다). 



이러한 MQTT broker는 앞서 언급한 ActiveMQ와 RabbitMQ외에도 mosquitto, moquette, mosca, HiveMQ 등
상당히 많다. 아래 링크는 이러한 브로커들을 비교해놓은 자료이다.


https://github.com/mqtt/mqtt.github.io/wiki/server-support


일단 라즈베리파이에 가장 흔히 쓰이는 것이 mosquitto인데 나는 2대로 클러스터를 만들어보기 위해 기왕이면 
클러스터링을 기본적으로 지원하는 브로커를 찾게 되었고 그 후보자로 HiveMQ와 EMQ가 선정되었다. 
하지만 HiveMQ가 상용이어서 오픈소스 기반인 EMQ로 정하게 되었다. 그리고 위 링크를 보아서도 알 수 있듯이 
EMQ는 체크 대상 전 항목이 구현되어 있어 도표상으로만 보자면 거의 상용 제품에 맞먹는 기능을 가지고 있다.


설치


아재의 잡설이겠지만 예전에는 오픈소스라는 것들이 웬만하면 소스로 내려받아 컴파일을 해야 사용이 가능했는데 
요즘은 대체로 바이너리로 받아도 별 무리 없이 실행이 된다. 그런데 나는 EMQ를 라즈베리파이에 설치할 계획이었고
EMQ 홈페이지에는 안타깝게도 라즈베리파이용 배포판은 없었다. 리눅스 계열의 배포판 중 하나를 받으면 되겠지만
어떤 것을 받아야 할지 대략 난감이었다.


결국 Github에 있는 소스를 내려받아 컴파일을 하게 되었다.


그러나 나에게는 남들에게 없는 오묘한 재주가 있었으니…
바로 너무 쉽게 설명된 것을 너무 어렵게 진행한다는 것이다…-.-


우선 소스의 다운로드와 컴파일은 다음의 과정을 거쳐 진행하면 된다.

$sudo apt-get update
$sudo apt-get install wget
$sudo apt-get install libssl-dev
$sudo apt-get install ncurses-dev
 
#ERLang 설치
$wget http://www.erlang.org/download/otp_src_19.2.tar.gz

$tar -xzvf otp_src_19.2.tar.gz
$cd otp_src_19.2/
$./configure
$make -j 4 
$sudo make install
$cd ..
$rm otp_src_19.2.tar.gz
$sudo rm -R otp_src_19.2/

#EMQ 설치 및 실행
$git clone https://github.com/emqtt/emq-relx.git
$cd emq-relx && make
$cd _rel/emqttd && ./bin/emqttd console


일단 모든 설치는 문제 없이 잘 끝났다.
그런데 정작 emq를 make하는 과정에서 아래와 같은 오류가 발생을 하였다.



원인은 erlang 설치에 있었으며 라즈베리 파이에 설치하기 위해서는 보다 상위 버전이 필요했었던 듯하다.
일단 erlang의 configure 실행 후 아래 화면과 같이 APPLICATIONS DISABLED에 많은 항목이 보이면
문제가 있는 것이라 보면 된다.



이 문제는 erlang의 버전을 20.1 이상으로 설치하면 해결된다.
이렇게 우여곡절 끝에 emq를 설치하였다. 나는 클러스터링을 원했으므로 2대의 라즈베리파이에 각각 설치를 하였다.


설정


이제 설치를 마쳤으니 설정을 해야 한다.
내가 설치한 버전의 emq는 빌드를 하고 나면 git으로부터 복제(위 설치 명령어 참조)한 경로 아래에 _rel이라는
디렉토리가 생기고 그 아래 빌드된 emq가 설치된다. 즉, git clone을 통해 만들어진 디렉토리가 emq-relx라면
emq-relx/_rel/emqttd 아래에 바이너리가 설치된다. 그리고 설정파일은 emq-relx/_rel/emqttd/etc
아래에 있는 emq.conf 파일이다.



설정파일이 상당히 긴데 사실상 변경할 부분은 그리 많지 않다. 내가 수정한 부분만 적는다.

...

#클러스터를 명시적으로 표시하겠다는 의미다.
cluster.discovery = static

...

#클러스터를 명시적으로 표시하겠다고 했으니 명시적으로 표시한다…-.-
cluster.static.seeds = rpi4@172.30.1.25,rpi5@172.30.1.9

...

#현재 노드를 적는다. 물론 172.30.1.25 라즈베리파이에는 rpi4@172.30.1.25라고 적는다.
node.name = rpi5@172.30.1.9

#쿠키 이름을 적는데 이 쿠키 이름을 적지 않거나 쿠키 이름이 일치하지 않으면 제대로 실행이 되지 않는다.
node.cookie = RPI

...

#웹 모니터링 콘솔을 접속하기 위한 포트 설정. 기본 값을 수정하지는 않았지만 중요한 내용이므로 적음
#아래 설정은 EMQ에서 지원하는 REST API 접속을 위해 필요한 포트이다. 모니터링 콘솔 접속 포트는 18083이다!!
listener.api.mgmt = 0.0.0.0:8080

...

node.name을 제외하고는 모두 동일하게 해서 다른 한 서버도 마저 설정을 한다.


실행


이제 실행을 하면 된다. 서비스로 실행을 하는 경우 아래 링크의 맨 마지막 부분을 보면 설명이 나와있다.

http://emqtt.io/docs/v2/install.html


나는 클러스터를 구성하기로 했으니 아래 링크를 따라 진행을 했으나 오류가 발생을 하였다.

http://emqtt.io/docs/v2/cluster.html


그런데 그냥 양쪽에서 아래와 같이 콘솔 모드로 실행을 했더니 자동으로 클러스터링이 이루어졌다.

$cd _rel/emqttd && ./bin/emqttd console


클러스터링이 된 것은 다음과 같이 확인하면 된다.

$sudo ./bin/emqttd_ctl cluster status
Cluster status: [{running_nodes,['rpi4@172.30.1.25','rpi5@172.30.1.9']}]

이렇게 실행까지 완료 되었다.


모니터링


이제 모든 과정이 끝났다. 브로커가 정상적으로 실행 되었다면 이제 확인을 해보자. 브라우저를 실행하고 아래와 같이
주소를 입력해보자.


http://localhost:8080


그러면 아래와 같은 화면이 나타날 것이다.



화면의 Nodes(2)라고 표시된 부분을 보면 내가 2대의 라즈베리파이로 클러스터를 구성했기 때문에 2개의 노드가
표시된 것이 보인다. 또한 우측 상단의 셀렉트 박스의 선택을 통해 각각의 노드 상황(클라이언트나 세션 등)을 볼 수도 
있다. 아래 2개의 이미지는 각각의 노드에 접속되어있는 클라이언트 정보를 보여주는 화면이다. 현재 Kafka까지 설치를
하여 Kafka에서 연결하고 있는 상태이며 이와 관련해서는 다음 포스팅에서 상세하게 다루겠다.



좌측 메뉴 중 Websocket을 이용하여 웹 화면에서 바로 클라이언트를 생성하여 메시지를 보내 테스트 해볼 수도 있다.


테스트


앞서 말했듯이 Websocket 메뉴를 통해서도 간단하게 테스트가 가능하지만 기왕이면 원격에서 클라이언트 접속 
테스트를 진행해보고 싶었다. 다행히도 구글 플레이스토어나 애플 앱스토어에서 MQTT로 검색을 해보면 MQTT
클라이언트가 많이 등록되어있다. 서버 주소와 포트 및 부가적인 몇가지 정보를 입력하면 바로 테스트 가능하다.


여기서는 아이폰용 MQTT 클라이언트 앱인 MQTT Tool을 이용한 테스트 방법을 간단하게 설명한다.

  1. 연결 화면으로 중요 정보인 브로커의 주소와 포트(기본 포트는 1883) 그리고 클라이언트 ID를 임의로 입력한다. ID와 Password역시 임의로 입력하면 된다. 내가 입력한 클라이언트 ID는 mazdah-iphone이다.


  2. 4개의 입력 폼을 가진 화면이 나온다. 가장 위에서부터 subscribe할 토픽 이름 입력, 전송된 토픽의 메시지 표시, publish할 토픽 입력, publish할 메시지 입력 순이다.


  3. 테스트를 위해 우선 subscribe할 토픽을 입력한다. 나는 /mqtt로 정했다. 토픽 입력 후 입력 폼 우측 아래 있는 Subscribe 버튼을 클릭하면 우측의 이미지처럼 Subscribe 버튼이 Unsubscribe로 바뀌고 메시지 표시 창 우측에는 토픽 이름이 적힌 원형 태그가 표시된다.





  4. 그리고 publish할 토픽 이름을 입력한다. subscribe할 토픽 이름이 /mqtt였으니 전송되는 것을 확인하기 위해 여기도 동일하게 /mqtt를 입력한다.


  5. 메시지 입력창을 선택하여 아무 문장이나 메시지를 입력한다. 여기서는 그냥 MQTT TEST라고 입력하였다.


  6. 그리고 마지막으로 메시지 입력창의 우측 하단에 있는 Publish 버튼을 클릭하면 메시지가 전송되고 위에 있는 Subscribe 메시지 창에 전송된 메시지가 출력되는 것을 볼 수 있다.



모니터링 콘솔을 보게되면 Client 메뉴에 내가 클라이언트에서 입력한 mazdah-iphone이라는 ID를 볼 수 있다.


그리고 Sessions 메뉴로 가면 역시 접속된 클라이언트들의 목록이 보이고 오른쪽 끝에쯤에 DeliverMsg 항목에
보면 28이라는 숫자가 보인다. 28건의 메시지가 전송된 것이다. 참고로 mqtt-kafka-1이라는 클라이언트는 다른
3대의 라즈베리파이에 설치된 kafka에서 연결된 subscriber이다. 


왼쪽 이미지는 172.30.1.25 서버의 상태인데 오른쪽의 172.30.1.9 서버의 콘솔에서도 mqtt-kafka-2와 
mqtt-kafka-3 두 개의 subscriber가 동일한 메시지를 전송받은 것을 알 수 있다. 이를 통해 2대의 서버가 
정상적으로 클러스터링 되었다는 것을 확인하였다.



정리


이렇게 라즈베리파이에 MQTT 브로커 중 EMQ라는 브로커를 설치/설정/실행/테스트까지 진행해보았다.
사실 당장에는 어떤 데이터를 어떻게 모을지도 결정된 것이 없기에 전체 클러스터 구성이 완료될 때까지는 이렇게
단순하게 설치와 실행 방법을 기술하게 될 것이다.


전체 클러스터 구성이 완료되면 본격적으로 아두이노를 이용하여 어떤 식으로 센서 데이터를 수집하게 되는지
좀 더 심도 있게 다루어보고자 한다.


우선 다음 단계로는 2개의 노드로 구성된 EMQ 클러스터의 로드 밸런싱을 위한 HAProxy 설치와 실행에 대해
살펴보고 다음으로는 Big Data 프레임워크로의 데이터 수집을 위한 관문으로써 Kafka에 대한 이야기를 정리해보도록
하겠다. 그리고 그 사이에 맥미니에 Haddop 2.0과 HBase 또는 Spark를 설치하는 작업을 진행하게 될 것이다.


이렇게 적어놓고 보니 아직도 할 일이 많다…ㅠ.ㅠ
부지런히 가자!

블로그 이미지

마즈다

이미 마흔을 넘어섰지만 아직도 꿈을 좇고 있습니다. 그래서 그 꿈에 다가가기 위한 단편들을 하나 둘 씩 모아가고 있지요. 이 곳에 그 단편들이 모일 겁니다...^^


Android Things Release Note 요약 : 4.0 ~ 4.1


지난 5월 14일에 정리한 것이 개발자 프리뷰 3.1까지였는데 그새 4.1까지 업데이트 되었다.
아무래도 짚고 넘어가야 할 것 같다…^^;


Developer Preview 4

릴리즈 날짜 : 2017년 5월
빌드 번호 : NIH40E
play service : 10.0.0


이 프리뷰 릴리즈는 지원되는 하드웨어에 대한 개발과 호환성 테스트를 하기 위해 Android Things를 이용하고자 
하는 개발자들과 얼리 어댑터들을 위한 것으로 이 프리뷰에 대한 아래의 일반 가이드라인에 주의하길 바란다.

  • 이 릴리즈는 지원되는 하드웨어에 대한 여러 지속적 이슈가 있으니 발견한 버그들은 리포트해주길 바란다.
  • 이 프리뷰에서는 API들의 모든 부분을 사용할 수는 없다. 사용 불가한 것으로 알려진 API들은 Known Issue 섹션에 문서화 되어있다.
  • 개발자 프리뷰 4는 Intel EdisonIntel JouleNXP i.MX7DNXP i.MX6UL, 그리고
    Raspberry Pi 3 개발 보드에서 사용 가능하다.

New in Preview 4


NXP i.MX7D support

Android Things는 이제 NXP® i.MX7D Pico 개발 플랫품을 지원한다. 이 기기에 대해 더 알고싶거나 성능을
확인하고 싶으면 developer kits 페이지를 참고하라.


Audio APIs

개발자들은 이제 Peripheral I/O를 이용하여 Inter-IC Sound (I2S)를 통해 디지털 오디오 장치를 연결할 수 
있으며 새로운 audio user-space 드라이버를 이용하여 미디어 프레임워크에 바인드할 수 있다.
보다 상세한 내용은 I2S와 audio drivers에 대한 새로운 API 가이드를 살펴보라.


Peripheral drivers

Peripheral I/O는 이제 PioDriverManager를 이용하여 런타임 시에 추가적인 인터페이스를 등록하는 것을
지원한다. 이를 통해 유닛 테스트를위한 스텁 인터페이스는 물론 주변 장치 버스 확장 장치를 등록 할 수 있다. 
자세한 내용은 reference documentation을 참조하라.


Known Issue

  • 시스템 전원 관리자는 현재 사용 불가능하다. 기기가 suspend 상태로 들어가지 않고 따라서 wake lock 기능이 필요치 않다(wake locks는 sleep 상태로 들어가거나 sleep 상태에서 깨우는 기능).
  • 부팅 시 dex를 미리 최적화하기 위해 Google Plat Service는 2~3분 정도의 시간을 필요로 한다. 이 프로세스가 완료되기 전에는 App을 설치할 수 없다.
  • 하드웨어 그래픽 가속 기능(OpenGL)은 현재 사용 불가능하다. 따라서 이러한 기능에 의존하는 API들(WebView같은) 역시 사용할 수 없다.


Peripheral I/O

  • 주변장치들은 close() 호출 후에 클리어 되거나 리셋되지 않는다. 출력은 그 장치들의 상태를 그대로 간직하고 있을 것이고 시리얼 포트에서는 이전에 버퍼링된 데이터들을 계속해서 보내려 할 것이다.
  • GPIO 핀들은 마지막으로 재부팅 된 이후에 엣지 트리거와 함께 이미 입력으로 활성화 된 경우 출력으로 사용할 수 없을 것이다.


User Driver

  • 사용자 센서들은 현재는 수동으로 해제할 수 없다. 이 센서들은 app 프로세스가 종료되면 자동으로 
    해제된다.
  • 사용자 센서로는 Continuous 및 On-change 센서만 지원 가능하다. One-shot과 special 리포팅 모드는 기대한대로 동작하지 않을 것이다.

Reporting modes란 (지난 프리뷰 번역에 언급했지만 포스팅이 나뉘었으므로 다시 설명함)

센서들은 다양한 방법으로 이벤트를 생성하는데 이를 Reporting mode라고 부른다. 각 센서들은 하나의 유형에 오직 하나의 reporting mode와 관계를 맺으며 모두 4개의 reporting mode가 있다.

  • Continuous : 배치 함수로 전달된 sampling_period_ns 파라미터에서 정의한 일정한 주기로 이벤트를 생성하며 가속도 센서나 자이로 센서가 여기에 포함된다.
  • On-change : 측정된 값에 변화가 있을 때만 이벤트가 발생한다. step counter, 근접 센서, 심박 센서 등이 여기에 포함된다.
  • One-shot : 이벤트가 감지되는 시점에서 HAL을 통해 단일 이벤트를 전송하고 센서 자신은 비활성화 된다. 중요 동작(Significant motion) 센서가 여기에 포함된다.
  • special : 센서별로 특정한 방식으로 이벤트를 발생시키며 자센한 것은 센서 타입 설명을 참조. 기울기 센서, Step detector 등이 여기에 포함된다.


인텔 Edison과 NXP Pico 관련 내용은 생략합니다.


Raspberry Pi

  • Audio : Wi-Fi와 Bluetooth가 모두 활성화 된 경우 Audio 품질 이슈가 발생한다.
  • Network : 인터넷 접속이 없더라도 이미 이더넷으로 네트워크에 연결되어있는 경우 Wi-Fi로 인터넷에 연결할 수 없다.
  • Camera : 하나 이상의 대상 출력 화면에 대해서는 새로운 CameraCaptureSession을 생성할 수 없다.
  • Camera : 어던 CameraCaptureSession에 대해서라도 최초의 요청에 대해서는 2개의 이미지가 queues에 쌓이게 된다. 이런 동작은 같은 session 내에서 연이어 발생하는 CaptureRequest가 이전 capture에서 버퍼링된 프레임을 리턴하는 문제를 야기한다.
  • I/O : BCM13/PWM1, BCM18/PWM0 공유 핀들은 이미 PWM 핀으로 활성화 된 경우 재부팅하기 전까지는 GPIO로 사용할 수 없다.
  • I/O : GPIO 핀인 BCM4, BCM5, 그리고 BCM6는 입력으로 사용할 경우 내부적으로 3.3V로 pulled-up(스위치가 Off 상태이면 전류가 흐르고 On 상태면 흐르지 않는 상태)된다.
  • Audio : 온보드 아날로그 오디오는 PWM과 동시에 사용할 수 없다.

Developer Preview 4.1

릴리즈 날짜 : 2017년 6월
빌드 번호 : NIH40K
play service : 11.0.0


개요는 Developer Preview 4와 동일하다.


New in Preview 2


NXP i.MX6UL Pico

NXP는 Preview 4.1 이상을 지원하는 Android 용 Pico 개발자 키트를 출시했다. 이전의 WandBoard kit
deprecated되고 차후 버전의 Android Things에서는 지원되지 않을 것이다.


Play Services for IoT

이번 릴리즈에는 IoT 기기를 겨냥한 별도의 Google Play Services가 포함되어 있다. 현재 버전에서의 Google
API 지원에 대해 더 배우고 싶다면 SDK overview페이지를 참고하라.


Known Issues

  • 시스템 전원 관리자는 현재 사용 불가능하다. 기기가 suspend 상태로 들어가지 않고 따라서 wake lock 기능이 필요치 않다(wake locks는 sleep 상태로 들어가거나 sleep 상태에서 깨우는 기능).
  • 부팅 시 dex를 미리 최적화하기 위해 Google Plat Service는 2~3분 정도의 시간을 필요로 한다. 이 프로세스가 완료되기 전에는 App을 설치할 수 없다.
  • 하드웨어 그래픽 가속 기능(OpenGL)은 현재 사용 불가능하다. 따라서 이러한 기능에 의존하는 API들(WebView같은) 역시 사용할 수 없다.


Peripheral I/O

  • 주변장치들은 close() 호출 후에 클리어 되거나 리셋되지 않는다. 출력은 그 장치들의 상태를 그대로 간직하고 있을 것이고 시리얼 포트에서는 이전에 버퍼링된 데이터들을 계속해서 보내려 할 것이다.
  • GPIO 핀들은 마지막으로 재부팅 된 이후에 엣지 트리거와 함께 이미 입력으로 활성화 된 경우 출력으로 사용할 수 없을 것이다.


User Driver

  • 사용자 센서들은 현재는 수동으로 해제할 수 없다. 이 센서들은 app 프로세스가 종료되면 자동으로 
    해제된다.
  • 사용자 센서로는 Continuous 및 On-change 센서만 지원 가능하다. One-shot과 special 리포팅 모드는 기대한대로 동작하지 않을 것이다.


인텔 Edison과 Joule 그리고 NXP Pico 관련 내용은 생략합니다.


Raspberry Pi

  • Audio : Wi-Fi와 Bluetooth가 모두 활성화 된 경우 Audio 품질 이슈가 발생한다.
  • Network : 인터넷 접속이 없더라도 이미 이더넷으로 네트워크에 연결되어있는 경우 Wi-Fi로 인터넷에 연결할 수 없다.
  • Camera : 하나 이상의 대상 출력 화면에 대해서는 새로운 CameraCaptureSession을 생성할 수 없다.
  • Camera : 어던 CameraCaptureSession에 대해서라도 최초의 요청에 대해서는 2개의 이미지가 queues에 쌓이게 된다. 이런 동작은 같은 session 내에서 연이어 발생하는 CaptureRequest가 이전 capture에서 버퍼링된 프레임을 리턴하는 문제를 야기한다.
  • I/O : BCM13/PWM1, BCM18/PWM0 공유 핀들은 이미 PWM 핀으로 활성화 된 경우 재부팅하기 전까지는 GPIO로 사용할 수 없다.
  • I/O : GPIO 핀인 BCM4, BCM5, 그리고 BCM6는 입력으로 사용할 경우 내부적으로 3.3V로 pulled-up(스위치가 Off 상태이면 전류가 흐르고 On 상태면 흐르지 않는 상태)된다.









블로그 이미지

마즈다

이미 마흔을 넘어섰지만 아직도 꿈을 좇고 있습니다. 그래서 그 꿈에 다가가기 위한 단편들을 하나 둘 씩 모아가고 있지요. 이 곳에 그 단편들이 모일 겁니다...^^




MagigMirror2 사용해보기


시간은 대체로 망설임을 잡아먹고 산다. 할까? 말까?, 이렇게 할까? 저렇게 할까?, 언제 할까? 물음표가 붙은 매 순간을
시간은 낼름낼름 받아먹으면서 점점 더 기운을 내서 빨리 가버린다.


아두이노를 이용하여 스마트 미러를 만들어보고자 시작한 것이 벌써 2달여가 지나가고 있다. 그 사이 많은 망설임과
다른 선택지에 밀려 별다른 진전도 없이 시간은 흘러갔다. 물론 그 사이 라즈베리파이로 방향 전환을 하여 Alexa도
한 번 테스트를 해보고 Android Things도 한 번 설치해보고 하긴 했으나 실질적인 도움이 되는 건 없었다.


이런 저런 상황을 보니 아무래도 직접 모든 것을 해결하기에는 역부족이다 싶어 그 유명하다는 스마트 미러용 오픈소스
Magic Mirror2를 설치해보기로 했다(2는 원래 윗첨자인데 안타깝게도 Ulyssess 편집기에는 첨자 기능이 없다…ㅠ.ㅠ)


설치와 실행이 너무도 간단하여 굳이 글로 정리하기도 민망하지만 간단한 특징들만 좀 정리해보도록 하겠다.


소스 위치


소스는 다음의 GitHub 경로에서 다운로드 받을 수 있으며 README에 필요한 내용들이 정리되어있다.

https://github.com/MichMich/MagicMirror#configuration


소스 구조


소스는 Node.js 기반의 javascript 코드로 작성이 되어있다. 많은 디렉토리와 파일들이 있으나 가장 중요한 것들은
다음과 같다.


js 디렉토리 : 가장 기본적인 앱 실행에 필요한 파일들이 들어있으며 defaults.js에는 기본 설정이 들어있다.



config 디렉토리 : 말 그대로 설정파일이 들어있다. 자동설치를 하면 달리 작업할 것이 없으나 수동 설치를 할 경우
config.js.sample 파일을 config.js 파일로 복사한 후 필요한 설정을 하면 된다. 앞서 말한대로 이 설정의 기본값들은
js/defaults.js에 코딩되어있다.


modules 디렉토리 : 각각의 기능을 담당하는 모듈들이 들어있다. 기본적으로 화면에 보여지는 모듈은 다음과 같다.
1. calendar : 날짜 및 기념일 과 휴일 표시. calendarlabs.com 서비스 이용
2. clock : 시간 표시
3. currentweather : 현재 날씨 표시. openweathermap.org 서비스 이용
4. weatherforecast : 1주일간의 일기 예보 표시. openweathermap.org 서비스 이용
5. newsfeed : 뉴욕 타임즈의 뉴스 피드 표시. nytimes.com 서비스 이용
6. compliments : ‘Hey there sexy!’ 등 뻘소리 뱉는 모듈…-.-


그밖에 다른 모듈로부터의 경고를 표시해주는 alert, 정적인 텍스트를 표시해주는 hello world, MagicMirror
자체의 버전 업데이트를 알려주는 updatenotification 등의 기본 모듈이 있다.


translations 디렉토리 : 다국어 지원을 위한 언어 파일들이 모여있는 곳. 하지만 사용되는 타이틀이 몇개 없어
다국어 지원의 의미가 별로 없다. 예를들어 한국어 파일인 kr.json의 내용은 전체 코드가 다음과 같다.


{
"LOADING": "로드 중 …",
"TODAY": "오늘",
"TOMORROW": "내일",
"DAYAFTERTOMORROW": "모레",
"RUNNING": "종료 일",
"EMPTY": "예정된 이벤트가 없습니다.",

"N": "북풍",
"NNE": "북북동풍",
"NE": "북동풍",
"ENE": "동북동풍",
"E": "동풍",
"ESE": "동남동풍",
"SE": "남동풍",
"SSE": "남남동풍",
"S": "남풍",
"SSW": "남남서풍",
"SW": "남서풍",
"WSW": "서남서풍",
"W": "서풍",
"WNW": "서북서풍",
"NW": "북서풍",
"NNW": "북북서풍",

"UPDATE_NOTIFICATION": "새로운 MagicMirror² 업데이트가 있습니다.",
"UPDATE_NOTIFICATION_MODULE": "MODULE_NAME 모듈에서 사용 가능한 업데이트 입니다.",
"UPDATE_INFO": "설치할 COMMIT_COUNT 는 BRANCH_NAME 분기에 해당됩니다."
}


그밖의 디렉토리들과 파일들은 자동을로 설치했다면 당장에 수정이 필요한 부분은 없다.


설치


나는 그냥 자동으로 설치 했다. 설치 방법은 GitHub 페이지의 README를 보는 것이 더 정확하고 빠를 것이다.
자동 설치는 콘솔 창에서 다음과 같이 입력한 후 엔터를 치면 된다.


bash -c "$(curl -sL https://raw.githubusercontent.com/MichMich/MagicMirror/master/installers/raspberry.sh)"


모든 설치가 자동으로 이루어지나 중간에 설치 확인하면서 ‘Y’를 한 번 입력해줘야 하고 마지막에 자동 실행 여부를
묻는 부분에서 ‘y/n’을 입력해 주어야 한다. 자동 실행 여부를 ‘y’로 입력해주면 설치 종료 후 바로 MagicMirror가
실행된다. MagicMirror가 실행되면 다음과 같은 화면이 표시된다.



실행과 종료


처음 자동실행을 했더니 바로 MagicMirror가 실행되면서 아무런 메뉴도 없고 키도 특별히 먹는 것이 없다보니
종료시키는 방법을 몰라 한참을 헤맸다.


일단 cmd+tab(나는 Mac을 쓰므로 이 조합이지만 다은 OS는 Ctrl-tab)을 누르면 설치를 진행했던 콘솔 창이
화면 앞으로 나타난다. 콘솔 화면은 아래 그림과 같은 내용이 떠있을 것이다.



MagicMirror는 PM2라는 툴로 시작과 종료를 한다. 각각 다음과 같은 명령어를 사용한다.


$> pm2 start MagicMirror
$> pm2 stop MagicMirror


이 명령어도 README에는 ‘pm2 start mm’이라고 적혀있어 좀 헤맸는데 나중에 위 이미지의 화면을 보니
name에 MagicMirror라고 되어있어서 이 이름으로 입력했더니 되었다…-.-


설정


설정 파일은 MagicMirror가 설치된 경로 아래에 config라는 디렉토리 바로 밑에 있다. 앞서 소스 구조에서 설명한
바와 같이 수동으로 설치할 경우 config.js.sample을 config.js로 복사하여 사용하면 되나 자동 설치할 경우에는
이 과정까지 모두 진행되어 바로 config.js 파일이 보일 것이다. 최초 코드는 다음과 같다.


/* Magic Mirror Config Sample
 *
 * By Michael Teeuw http://michaelteeuw.nl
 * MIT Licensed.
 */

var config = {
	port: 8080,
	ipWhitelist: ["127.0.0.1", "::ffff:127.0.0.1", "::1"], // Set [] to allow all IP addresses.

	language: "en",
	timeFormat: 24,
	units: "metric",

	modules: [
		{
			module: "alert",
		},
		{
			module: "updatenotification",
			position: "top_bar"
		},
		{
			module: "clock",
			position: "top_left"
		},
		{
			module: "calendar",
			header: "US Holidays",
			position: "top_left",
			config: {
				calendars: [
					{
						symbol: "calendar-check-o ",
						url: "webcal://www.calendarlabs.com/templates/ical/US-Holidays.ics"
					}
				]
			}
		},
		{
			module: "compliments",
			position: "lower_third"
		},
		{
			module: "currentweather",
			position: "top_right",
			config: {
				location: "New York",
				locationID: "",  //ID from http://www.openweathermap.org/help/city_list.txt
				appid: "YOUR_OPENWEATHER_API_KEY"
			}
		},
		{
			module: "weatherforecast",
			position: "top_right",
			header: "Weather Forecast",
			config: {
				location: "New York",
				locationID: "5128581",  //ID from http://www.openweathermap.org/help/city_list.txt
				appid: "YOUR_OPENWEATHER_API_KEY"
			}
		},
		{
			module: "newsfeed",
			position: "bottom_bar",
			config: {
				feeds: [
					{
						title: "New York Times",
						url: "http://www.nytimes.com/services/xml/rss/nyt/HomePage.xml"
					}
				],
				showSourceTitle: true,
				showPublishDate: true
			}
		},
	]

};

/*************** DO NOT EDIT THE LINE BELOW ***************/
if (typeof module !== "undefined") {module.exports = config;}


이 기본 설정에 필요한 내용을 추가하거나 수정하여 사용하면 된다. 몇가지 팁을 정리하자면 다음과 같다.


  1. calendarlabs.com의 한국 휴일 데이터 URL은 다음과 같다. 하지만 모두 영어로 표시된다…ㅠ.ㅠ
    webcal://www.calendarlabs.com/templates/ical/SouthKorea-Holidays.ics
  2. openweathermap.org의 경우 서비스를 이용하기 위해서는 가입 후 appid를 발급받아야 한다.
    정상적인 appid를 입력해야 데이터가 화면에 표시된다.
  3. newsfeed의 경우 개발자 문서에 언급된 사용 가능 뉴스는 뉴욕타임즈와 bbc밖에 없다.
  4. 컨텐츠의 크기를 조절하는 zoom이라는 옵션이 있는데 왠지 적용되지 않는 것 같다.
  5. language 옵션을 kr로 하면 한글 표시가 나오나 앞서 말한 바와 같이 설정된 텍스트가 거의 없어 ‘로딩중…’이나 바람 방향을 표시하는 ‘남서풍’ 정도만 한글을 볼 수 있다.

요약


아직 설치하고 실행만 해본터라 이정도에서 정리를 마치고자 한다. 진짜 중요한 부분은 모듈을 만드는 부분일
것이다. 개발자 문서에도 모듈은 만드는 부분에 대해 별도의 페이지를 할애하여 안내하고 있다. 새로운 모듈이
없이는 스마트 미러라고 하기에는 많이 부족하다(그래서 이름이 그냥 MagicMirror인 것 같다). 적어도 음성 명령
정도는 포함시켜주어야…^^;;;


또 언제가 될지는 모르겠지만 일단 만들고 싶은 모듈은 소니에서 제공하는 안드로이드용 건강 앱인 ‘LifeLog’
API를 이용하여 LifeLog 정보를 MagicMirror에 표시해 보는 것이다. 그러려면 일단 소스 분석부터 제대로 좀
해봐야 할 것 같지만…-.-


그리고 현재 5인치 LCD를 사용하는데 아무래도 LCD 사이즈를 좀 더 키워야 할 것 같다.


그럼 기약 없는 다음 어느 날에 후속 이야기를 적어보도록 하겠다…^^;;;






블로그 이미지

마즈다

이미 마흔을 넘어섰지만 아직도 꿈을 좇고 있습니다. 그래서 그 꿈에 다가가기 위한 단편들을 하나 둘 씩 모아가고 있지요. 이 곳에 그 단편들이 모일 겁니다...^^


Android Things SDK 개요


이 글은 Android things의 공식 홈페이지에 있는 Overview를 번역한 것이다. 크게 보자면 Android Things가
embedded 기기에 대한 core Android의 확장이며 그에 따른 Android Things의 이점과 제약을 설명하고 있다.


개인적으로는 다른 어떤 이점보다도 단일 app 기반이라는 점과 UI의 부재라는 제약이 더 크게 보인다.
사실 라즈베리파이는 아두이노나 다른 embedded 기기에 비한다면 상당히 고사양의 기기이다. multi tasking이
가능한 CPU와 HDMI라는 고사양의 display 인터페이스를 가지고 있음에도 불구하고 그 것을 활용하지 못한다는
것은 하드웨어 리소스의 낭비로 보여진다. 


이런 측면으로 보자면 아두이노를 지원해야 할 것 같지만 그 또한 여의치 않은 것이 아두이노같은 저수준의 디바이스는
작은 크기의 소프트웨어와 빠른 속도, 저사양의 기기이므로 메모리 관리가 효율적으로 이루어져야 한다는 점에서 
VM 기반의 Android 플랫폼이 썩 어울려 보이지는 않는다.


이렇게 쓰고보니 Android Things가 마치 쓸모없는 것 처럼 표현이 되었는데…아직 개발자 프리뷰이니 조금 더
지켜보아야 할 것 같다.



Android Things는 동일한 Android 개발 툴, 동급 최고의 Android 프레임워크, 모바일에서 개발자들의 성공을 
보장하는 Google API를 제공함으로써 embedded 기기와 관련된 개발을 쉽게 할 수 있도록 한다.



embedded 기기를 위한 app들은 개발자로 하여금 폰이나 태블릿보다 하드웨어 주변 장치나 드라이버에 더 익숙하게
한다. 또한 일반적으로 embedded 기기는 사용자들에게 단일 app 환경을 제공한다. 이 문서는 core Android 
개발과 Android Things 사이에 추가된 것, 빠진 것 등 중요한 차이점을 설명한다.


Android Things는 Things Support Library를 통해 추가적인 API를 제공하는 Core Android 프레임워크의
확장이다. 이런 추가된 API들은 기존의 모바일 기기에서는 찾아볼 수 없었던 새로운 유형의 하드웨어를 통합시킬 수 
있는 app을 개발할 수 있도록 해준다.


또한 Android Things 플랫폼은 단일 애플리케이션 사용을 위해 간소화 되어있다. 시스템 app이 존재하지 않고
기기의 시작과 동시에 개발자가 개발한 app이 자동으로 실행됨으로써 사용자가 app 환경에 집중할 수 있도록 해준다.


Things Support Library


주변장치 I/O API

주변장치(Peripheral) I/O APIs는 개발한 app이 산업 표준의 프로토콜과 인터페이스를 통해 센서들이나 액츄에이터
들과 통신할 수 있도록 해준다. 다음의 인터페이스들을 지원한다 : GPIO, PWM, I2C, SPI, UART.

APIs의 사용 방법에 대한 추가적인 정보는 다음 링크에서 확인하라. Peripheral I/O API Guides


User Driver API

사용자 Drivers는 기존 Android 프레임워크 서비스를 확장하고 다른 app들이 표준 Android APIs를 통해 접근
가능한 프레임워크에 하드웨어 이벤트를 주입할 수 있도록 해준다.

APIs의 사용 방법에 대한 추가적인 정보는 다음 링크에서 확인하라. User Driver API Guides


동작의 변화


Core application packages


Android Things 는 시스템 apps와 content providers등 표준 API 모음은 포함하지 않는다. 앱을 개발할 때
common intents와 아래 목록의 content provider APIs는 사용을 하면 안된다.

  • CalendarContract
  • ContactsContract
  • DocumentsContract
  • DownloadManager
  • MediaStore
  • Settings
  • Telephony
  • UserDictionary
  • VoicemailContract


화면 출력은 선택 사항

Android Things는 전통적인 Android 애플리케이션과 마찬가지로 UI toolkit을 이용하여 그래픽 사용자 
인터페이스를 제공할 수 있다. 그래픽 모드에서는 애플리케이션의 Window가 전체 화면을 모두 차지하게 된다.
Android Things는 시각적인 사용자 환경을 완벽하게 제어할 수 있는 시스템 상태바라든지 네비게이션 버튼이
포함되어있지 않다. 


따라서 Android Things는 디스플레이가 필요하지 않다. 그래픽 디스플레이가 제공되지 않는 기기상에서도
여전히 Activity들은 Android Things app의 중요한 컴포넌트이다. 그렇기 때문에 프레임워크는 모든 입력 
이벤트를 포커스가 주어진 foreground Activity로 전달한다. 이렇게 개발된 앱은 service와 같은 다른 애플리케이션 
컴포넌트로부터 키 이벤트나 모션 이벤트 등을 수신받지 못한다.


Home activity 지원

Android Things는 부팅 시 자동으로 실행될 수 있도록 애플리케이션의 manifest에 주요 진입점으로 home
activity
를 노출하도록 하고 있다. 이 activity는 CATEGORY_DEFAULT와 IOT_LAUNCHER 두 개의 intent
filter를 반드시 포함시켜야 한다.


개발의 편의를 위해 이 activity는 CATEGORY_LAUNCHER 또한 포함시켜야 하므로 Android Studio를 통한
배포 또는 디버깅시에 이 activity를 기본 activity로 실행시킬 수 있다.

<application
    android:label="@string/app_name">
    <activity android:name=".HomeActivity">
        <!-- Launch activity as default from Android Studio -->
        <intent-filter>
            <action android:name="android.intent.action.MAIN"/>
            <category android:name="android.intent.category.LAUNCHER"/>
        </intent-filter>

        <!-- Launch activity automatically on boot -->
        <intent-filter>
            <action android:name="android.intent.action.MAIN"/>
            <category android:name="android.intent.category.IOT_LAUNCHER"/>
            <category android:name="android.intent.category.DEFAULT"/>
        </intent-filter>
    </activity>
</application>


Google service들의 지원

Android Things는 Google APIs for Android의 일부를 지원한다. 아래의 목록은 Android Things에서의 
API 지원 여부를 보여준다.


Supported APIs


Unavailable APIs

주의 : 일반적으로 사용자의 입력이나 인증 절차가 필요한 APIs는 app에서 사용할 수가 없다.


Android Things의 각 배포버전은 Google Play Services의 최신 안정화 버전을 번들로 제공하며 적어도 
클라이언트 SDK 10.0.0 이상의 버전이 필요하다. Android Things는 기기의 Play 서비스를 자동으로 업데이트
해주는 Google Play Store를 포함하고 있지 않다. 기기의 Play 서비스 버전은 정적으로 고정되어있기 때문에
app은 대상 배포판에 번들로 제공되는 것 보다 큰 버전의 클라이언트 SDK를 대상으로 할 수 없다.


주의 : 개발자 프리뷰 상태인 동안 각 배포판의 번들 버전은 release notes에 그 목록이 표시되어 있다.


Permissions

embedded 기기에서는 app 실행 시에 대화상자에 접근할 수 있는 UI를 제공하지 않기 때문에 app 실행 시의 권한 
요청
은 지원되지 않는다. 필요하다면 app의 manifest 파일에 권한을 선언해야 한다. app의 manifest에 선언된 
정상적이고 워험한 권한들은 설치 시에 부여된다.


Notifications

Android Things에는 시스템 전반적으로 상태표시줄이나 창이 없으므로 notification은 지원되지 않는다.
따라서 NotificationManager APIs의 호출은 피해야 한다.






블로그 이미지

마즈다

이미 마흔을 넘어섰지만 아직도 꿈을 좇고 있습니다. 그래서 그 꿈에 다가가기 위한 단편들을 하나 둘 씩 모아가고 있지요. 이 곳에 그 단편들이 모일 겁니다...^^


Android Things 이미지 설치하기


지난 시간에 간단하게 Android Things의 개요를 살펴보았다. 뭐니뭐니해도 가장 중요한 내용은 바로 광범위한
안드로이드의 생태계를 거의 그대로 사용 가능하다는 것이었다. 편리한 배포와 업데이트, 안드로이드 수준의 보안, 
수많은 리소스들의 활용, 거기에 상용제품에 준하는 하드웨어를 이용한 신속한 개발 등 상당히 매력적인 플랫폼인
것은 분명하다.


공식 홈페이지에는 하드웨어에 대한 기본적인 설명을 먼저 하고 있지만 나는 라즈베리파이에 대해서만 알면 되기에
바로 라즈베리파이에 이미지를 설치하는 내용으로 건너 뛰었다. 


라즈베리파이에 Android Things 이미지 설치하기


공식적으로 Android Things가 지원하는 기종은 라즈베리파이 3다. 2도 설치는 되는 것 같으나 검색을 해보니
오동작하는 경우가 종종 있다고 한다. 그리고 최근 접한 소식에 아직 국내에서는 구하기 어렵지만 라즈베리파이
제로 W도 지원을 하지 않는다고 한다(미지원 사유는 CPU 문제라고 한다).


공식 홈에는 간단하게 라즈베리파이 3의 사양에 대한 설명이 나오고 Android Things의 이미지를 굽는 방법이
나온다. 기존 다른 라즈베리파이용 OS와 유사하게 SD카드에 이미지를 굽고 그 SD카드를 라즈베리파이에 꽂아
기동하게 된다.


준비할 것들 목록이 다음과 같이 정리되어있다.

  • HDMI 케이블
  • HDMI로 연결할 수 있는 디스플레이
  • 마이크로 USB 케이블
  • 이더넷 케이블
  • 마이크로 SD카드 리더기


그리고 목록에는 나와있지 않지만 당연히 마이크로 SD카드가 필요하다. 8Gb 이상이어야 한다.


당연히 준비해야 할 것들이고 이미지를 굽는 방법도 매우 단순하다. 나는 현재 MAC mini를 사용하고 있기에
MAC에서의 설치 방법을 따랐다.


먼저 Eacher라는 앱을 설치한 후 실행하여 다운로드 받은 Android Things 이미지를 선택한다. 그리고 이 이미지를
구울 마이크로 SD 카드의 경로를 선택을 한 후 Flash! 버튼을 클릭하면 이미지가 SD카드에 설치된다. 앱의
UI와 설치 과정이 매우 단순하여 쉽게 이미지를 구울 수 있다.



그리고 이렇게 구워진 마이크로 SD카드를 라즈베리파이에 끼우고 부팅을 하면 끝이다.
나는 간단하게 아래와 같이 준비를 하였다.



안드로이드 개발 환경 구성하기


이미 여러 번 말했거니와 이름 자체가 Android Things이기 때문에 당연히 안드로이드 개발 환경이 갖추어져
있어야 한다. 기본적으로 Android Studio를 설치해야 하므로 아래 링크로 가서 찬찬히 살펴보면서 설치해보자
다행히도 한글화가 잘 되어있다^^


https://developer.android.com/studio/index.html


그리고 Android Things가 실행된 라즈베리파이와 통신하기 위해서는 adb tool이 필요한데 이에 대한 설명
역시 링크로 대신한다.


https://developer.android.com/studio/command-line/adb.html


사실 adb tool은 안드로이드 SDK가 설치되면서 함께 설치되기 때문에 파일 위치만 확인하면 된다. MAC OSX의
경우 다음 위치에 실행 파일이 존재한다.


/Users/[사용자 ID]/Library/Android/sdk/platform-tools



라즈베리파이와 통신하기


이제 공식 홈페이지에서 설명하는 것과 같이 Android Things가 구동되고 있는 라즈베리파이와 통신을 해보자.
Android Things로 부팅이되면 아래와 같은 화면이 보여진다. 다른 라즈베리파이용 OS와 달리 사용자와 인터페이스
할 수 있는 UI는 없고 단지 로고와 몇가지 정보만 보여준다. 그 정보 중 하나가 이더넷 주소이다. 아래 이미지에는
Wi-Fi 주소가 함께 보여지는데 이 것은 내가 Wi-Fi를 연결한 이후 나타난 것이고 Wi-Fi를 설정하여 연결하기 전에는
이더넷 주소만 보인다.



이 이더넷 주소를 이용하여 다음과 같이 연결을 시도한다.

$ adb connect 172.30.1.57
connected to 172.30.1.57:5555


MDNS를 지원하는 기기에서는 IP 주소와 port 대신 Android.local로도 접속이 가능하다고 한다.


늘 이더넷 케이블을 연결시켜놓기는 불편하니 이제 Wi-Fi 연결을 시도해보자. 아래와 같이 adb 명령을 실행하면 된다.

$ adb shell am startservice \
    -n com.google.wifisetup/.WifiSetupService \
    -a WifiSetupService.Connect \
    -e ssid <Network_SSID> \
    -e passphrase <Network_Passcode>


SSID와 비밀번호만 정상적으로 잘 입력하면 잘 연결이 되…어야 하겠지만…돌발 변수가 발생했다.
눈을 부릅뜨고 봐도 내가 잘못 입력한 내용이 없는 것 같은데 요상하게 연결이 안된다. 이 작은 기기들은 왜이리
나를 괴롭히는 것을 좋아하는지…ㅠ.ㅠ


열심히 구글링을 하여 드디어 밝혀낸 원인은…라즈베리파이의 Wi-Fi는 5Ghz 대역을 지원하지 않는다는 것이다.
집에 ‘얼레! 기가찬’ Wi-Fi를 쓰고 있다보니 연결이 되지 않는 것이었다…ㅠ.ㅠ 다행히 기가찬 Wi-Fi에는 기존의
2.4Ghz Wi-Fi 대역도 제공하고 있기에 그쪽으로 연결하니 정상적으로 연결이 되었다. 성공적으로 연결이 되면
다음과 같은 로그 내용을 확인할 수 있다.

$ adb logcat -d | grep Wifi
...
V WifiWatcher: Network state changed to CONNECTED
V WifiWatcher: SSID changed: ...
I WifiConfigurator: Successfully connected to ...


그리고 Android Studio를 켠 상태에서 연결을 하였다면 Android Monitor 창을 통해 다음과 같은 방법으로도 확인 가능하다.


이렇게 Wi-Fi가 연결되고 난 후 이더넷 케이블을 제거하고 라즈베리파이를 부팅하면 다음과 같이 부팅이 되고
화면 하단에는 이더넷 정보는 사라지고 Wi-Fi 정보만 보여진다.



마지막으로 모든 네트워크 설정을 지우고 싶다면 다음과 같이 adb 명령을 사용하면 된다.

$ adb shell am startservice \
    -n com.google.wifisetup/.WifiSetupService \
    -a WifiSetupService.Reset

정리


이후에 원활한 디버깅을 위한 Serial debug console에 대한 이야기가 나오는데 이 부분은 참고로 봐두면 될 것이다.
앞서 말했지만 Android Things는 사용자와 인터페이스 하는 UI가 없기에 샘플 프로젝트를 돌려보기 전까지는 
그야말로 아무것도 할 것이 없다.


그래도 일단 개발할 준비가 되었다는 것만도 뭔가 뿌듯함이 느껴진다. 앞으로 예제를 하나 하나 실행해가면서
Android Things의 API에 익숙해지도록 해야겠다. 이전 포스팅에서도 말했지만 사실 지금 당장 하고 싶은 것은
TensorFlow를 이용하여 사진을 인식하는 예제이다. 어쩌면 바로 이 예제에 도전해볼지도…^^;;;


암튼 빨리 진행은 해보고 싶지만 워낙 잡다하게 공부하는 것이 많다보니 언제쯤 해보게 될런지…ㅠ.ㅠ






블로그 이미지

마즈다

이미 마흔을 넘어섰지만 아직도 꿈을 좇고 있습니다. 그래서 그 꿈에 다가가기 위한 단편들을 하나 둘 씩 모아가고 있지요. 이 곳에 그 단편들이 모일 겁니다...^^


결국 라즈베리파이…ㅠ.ㅠ


몇 주 전부터 아두이노로 스마트미러를 만들겠다고 용트림을 하고 있는데…그게 잘 안된다…아마도 무지의 소치라고
해야 할 듯…아두이노가 내가 원하는대로 쑥쑥 결과를 뽑아줄 것이라 생각한 것이 잘못이었다…ㅠ.ㅠ


이미 이전 글들에서 LCD를 다루는데 있어서의 어려움들은 충분히 토로하였지만 다시 말하자면 다른 것은 다 
제쳐두고라도 한글 표현의 문제와 가독성 높은 UI를 구성하는 부분에서의 장벽으로 거의 포기의 지경이 이를 수
밖에 없었다.


때마침 페이스북을 통해 Android Things에 대한 소식을 접하고는 핑계삼아 결국은 라즈베리파이를 구입하고 말았다.
2대를 구입하여 한 대는 Android Things를 테스트하기로 하고 다른 한 대는 스마트미러에 사용하기로 했다.


신세계~


사실 굳이 따로 언급할 것도 없다. 프로그래밍 언어로 치자면 아두이노는 어셈블리고 라즈베리파이는 VB나 델파이 등
4GL 툴이라고 봐야 할 것이다. 라즈베리파이는 그냥 작은 PC이므로 두말하면 입아픈 사실이지만…


라즈베리파이와 함께 구입한 5인치 LCD를 HDMI 케이블로 연결을 하고 라즈비안을 설치하기 시작했다 (라즈비안 
설치 등은 참고 자료가 많으니 생략한다). 처음에는 5인치 LCD를 제대로 인식하지 못하여 우선 PC에 연결된 
모니터를 이용하여 설치한 후 5인치 LCD에 동봉된 내용대로 설정을 바꾸어주었더니 화면이 정상적으로 나왔다.



아두이노에 LCD를 연결하기 위해 점퍼선 30여개를 작고 틈도 없는 I/O 핀에 꽂았던 것을 생각하면 가히 신세계라
아니할 수 없다.

아두이노는 이랬다...ㅠ.ㅠ



반가워 Alexa


라즈베리파이의 경우 이미 외국의 모 개발자가 만든 스마트 미러 전용 프로그램이 Github에 올라와있다. 하지만
내가 누군가! 남들 가는 길로는 죽어라 가지 않는(그런데 스마트 미러는 뭐하러 만들고 있는지…-.-) 청개구리 아닌가?
그래서 다른 부분들은 추후 개발하기로 하고 우선 “스마트”에 걸맞는 음성 인식 기능부터 찾아보기로 했다.


그리고 가장 처음 눈에 들어온 것이 Google Cloud Speech였다. 하지만 이 Google Cloud Speech는 
구글 클라우드 플랫폼에 가입을 해야 사용이 가능한데 가입 과정에 결재 정보를 등록해야 한다. 그래서 살펴보니
Google Cloud Speech는 1달에 60분까지만 무료이고 60분 이후부터는 15초당 $0.006이 부과 되는 서비스였다.


비록 혼자 테스트하는데 그리고 벌여놓은 일들이 많아 자주 만지지도 못하는데 한달에 60분이나 쓸까 싶었으나
아무래도 뭔가 결재가 될 수 있다는 것은 불안 요소가 아닐 수 없다. 그래서 대안을 찾아보았다. 그리고 발견한 것이
Amazon의 음성 서비스 Alexa였다. Alexa도 역시 가입을 해야 하고 인증키를 받는 절차등이 필요하지만 개발을
위해서는 별다른 과금 같은 것은 없었다. 다만 치명적인 문제가 있었는데…한글을 지원 안한다…ㅠ.ㅠ



그래도 일단 음성 인식이라는 것이 어떻게 작동하는지 감이나 잡아보기 위해 Alexa를 써보기로 했다.


설치 과정은 그리 어렵지 않았다. Alexa의 Github에 너무도 상세하게 나와있어 그대로 따라만 하니 정상 작동하는
모습을 볼 수 있었다.


Alexa의 Github : https://github.com/alexa/alexa-avs-sample-app/wiki/Raspberry-Pi


문제 없이 지나가면 섭하지~


그렇다…모든 것이 순조롭기만 하면 삶이 심심하지 않겠는가…-.- 역시나 하나의 장벽을 만나게 되었는데 바로 USB
마이크 문제였다. 나중에 스마트 미러를 만들 때 가급적 부피가 작아야 하기에 검색 끝에 아래 사진과 같은 제품을
골랐다.



일단 USB 포트에 꽂고 작동을 확인해보니 기본적인 작동은 된다. 그런데 영 녹음되는 소리의 크기도 작고 잡음도 많이
섞이고 뭔가 제대로 작동한다는 느낌이 나질 않았다. 급기야 Alexa를 모두 설치한 후 음성 명령 테스트를 하는데 전혀
음성 입력을 인식하지 못했다.


사방팔방으로 라즈비언에서 USB 마이크 인식시키는 방법을 찾아다녔는데 아무리 용을 써도 되지 않았다. 마이크 
입력을 맞추니 스피커 출력이 안되고 스피커를 맞추는 마이크 입력이 안되고…나중에 알게 되었지만 설정 파일에서
불필요한 부분을 삭제해주어야 했던 것이다.


우선 첫 번째 수정해야 할 파일은 /usr/share/alsa/alsa.conf이다. 이 파일의 다음 2줄을 수정한다.

defaults.ctl.card 0
defaults.pcm.card 0


위의 두 줄을 아래와 같이 수정한다.

defaults.ctl.card 1
defaults.pcm.card 1


문제가 되었던 것은 두 번째 파일이다. 파일은 ~/.asoundrc로 이 파일은 다른 내용은 다 지우고 아래와 같이
남겨놓으면 된다.

pcm.!default {
 type asym
  playback.pcm {
	 type plug
	 slave.pcm "hw:0,0"
  }
  capture.pcm {
	 type plug
	 slave.pcm "hw:1,0"
  }
}


원래 이 아래 다른 내용들이 더 있었는데 그 내용들을 그대로 둔 채 위의 내용만 수정하니 제대로 적용이 되지 않았다.
모든 내용을 삭제하고 위의 내용만 남겨두니 마이크와 스피커가 모두 정상 동작하였다.


드디어 테스트~


Alexa를 실행한 상태에서의 라즈베리파이 화면은 3개의 콘솔 창과 Alexa Voice Service라는 타이틀이 붙은
음성 컨트롤 창이 떠 있는 상태가 된다. 만일 WakeWordAgent를 사용하지 않는다면 이 Alexa Voice Service
창에서 Listen 버튼을 눌러 명령을 입력하게 된다.

WakeWordAgent란 음성 명령을 입력하기 전에 Alexa에게 준비를 하도록 시키는 역할을 한다. 음성 명령을
내리기 전에 ‘Alexa’와 같이 특정 단어를 부르면 준비가 되었다는 의미의 알람음이 한 번 울리고 그 이후에 
명령을 입력하면 되는 것이다.

Alexa가 정상 동작한 후 정작 라즈베리파이는 아이들의 장난감이 되어버렸다. 이미 내 아이폰의 Siri에 맛들인 덕분에
내가 Alexa를 부르는 소리에 유심히 보고 있던 아이들이 앞다퉈 질문을 던진다. 그런데 그 질문이란 것이…


Are You stupid?


뭐 이런거다…-.- 돌아오는 대답이 뭔소린지 모르겠다는 내용인 것으로 봐서는 아직은 Siri가 한 수 위다. 적어도 Siri는
섭섭하다는 표현은 하니까…


드디어 내 차례가 되어 간단하게 몇마디 테스트해본다. 질문은 짧은데 대답은 무지 길다…-.-
다행히 개떡같은 발음도 찰떡같이 알아듣는다. 개떡같은 발음이 부끄럽지만 테스트 동영상을 올려본다.


일단 영어만 알아먹으니 딱히 물어볼 말이 없다…ㅠ.ㅠ 그리고 현재로서는 실질적으로 어떤 액션을 요청할 수 없어
그저 묻고 답하기 수준이지만 최종 목표는 스마트 미러에 필요한 정보를 음성 명령을 통해 화면에 보여주는 것이기에
더 세부적인 내용을 살펴보아야 할 것이다.


정리


우선 생각보다 설치와 실행이 쉽게 되어 다행이었다. 마이크 인식에 애를 먹긴 했지만 그정도는 허용 범위이다.


하지만 아직은 이렇게 Alexa 서비스를 개인 프로젝트에서 어떻게 이용해야 하는지를 잘 모르겠다. 그저 이미 
잘 알려진 명령어를 통해 질문하고 답변을 듣는 정도의 테스트만 할 수 있을 뿐…더군다나 앞서 말한 것 처럼 아직 
Alexa는 한국어 지원이 되지 않기 때문에 Alexa가 최종 후보는 아니다. 아무래도 구글의 Google Cloud Speech도 
테스트를 해보아야겠다.


어떤 측면에서는 스마트 미러를 만드는 과정이 4족보행 로봇을 만들 때보다 더 어려운 것 같다. 그만큼 진행 속도가
더딘 것은 어쩔 수 없다. 음성 명령을 위한 후보자를 결정한 후에나 속도를 좀 낼 수 있을 것 같긴 한데…조금 더 
분발해보자!





블로그 이미지

마즈다

이미 마흔을 넘어섰지만 아직도 꿈을 좇고 있습니다. 그래서 그 꿈에 다가가기 위한 단편들을 하나 둘 씩 모아가고 있지요. 이 곳에 그 단편들이 모일 겁니다...^^


Big을 했으니 Small도 해야지~ 

얼마전 페북을 열심히 보다가 유명 개발자께서 새로운 무언가를 소개한 글을 잠깐 보았다. 바로 구글에서 자사의
안드로이드를 기반으로 추진하는 IoT 프로젝트인 Android Things라는 프로젝트였다. 구글의 개발자 사이트를
가보면 HOME 메뉴 아래 Android, Wear, TV, Auto에 이어 5번째로 자리잡고있다.


마침 작년부터 아두이노에 관심을 갖게 되었고 또 올해 추진하고 있는 아두이노로 스마트 미러를 만드는 계획에
차질을 빚고 있던 차에 이런 정보를 접하니 관심이 안갈 수 없다. 아쉽게도 Android 자체가 고수준 언어인 JAVA에
기반을 하고 있다보니 아두이노는 지원 기기에 없지만 라즈베리 파이를 지원한다고 하니 안그래도 기웃거리고 있던
라즈베리 파이를 시작해 볼 좋은 핑계가 생긴 셈이다.


그래서 오늘은 이 Android Things에 대해 간단하게 알아보고자 한다.
이 글은 Android Things의 메인 페이지를 정리한 것이다.

참조 링크 : https://developer.android.com/things/index.html


예정된 수순?

뭐 애초에 전방위적으로 손을 안뻗친 곳이 없는 구글이다보니 IoT에 눈을 돌렸다 해도 이상할 것도 없고 또 자율
주행 차를 연구하고 있었다 하면 당연히 그 과정에서 IoT가 빠져있었을리가 만무하다. 더군다나 이미 모바일 OS인
Android를 통해 소형 기기에 대한 생태계를 확실하게 굳히고 있는 마당에 사실상 일반 개발자에게 공개된 시점이
최근일 뿐 이미 오래 전에 준비는 다 되어 있었다고 봐야 할 것이다(그렇다면 곧 애플도?).


결국 올 것이 온 것이니 우리는 아~주 자연스럽게 이용만 하면 된다 ^^. 그러기 위해서는 차근 차근 하나씩 그 속을
들여다 보아야겠지.


Android Things 소개

그래서인지 Android Things의 소개에는 Android가 가지고 있는 장점들을 활용할 수 있다는 점을 유독 강조하고
있는 느낌이다. 이름 자체가 Android로 시작하니 두말하면 잔소리인가? 어쨌든 메인 페이지의 표제어가 바로
‘안드로이드의 용이성과 힘’이다. 


여기서 강조하고 있는 것은 기존에 구축된 Android의 개발 툴, API들, 리소스들과 개발자 커뮤니티를 마음껏 이용할
수 있다는 것, 새로운 IoT 기기들을 위해 저수준의 I/O와 라이브러리를 제공하는 새로운 API가 추가되었다는 것,
마지막으로 IoT의 가장 큰 약점인 보안 부분을 Android OS 수준에서 제공할 수 있다는 것 등이다.



다음으로 강조하는 것은 프로토타입의 개발에서부터 실제 상품 개발까지의 과정을 빠르게 진행할 수 있다는 것이다.
기존에 생산된 많은 디바이스들에 대해 인증 받았고 이러한 기기들 덕분에 커널 개발, 펌웨어 개발, 보드 자체의
개발 등 어려운 과정을 거치지 않고도 바로 프로토타입 제품을 생산할 수 있으며 이렇게 개발된 프로토타입 자체가
이미 상용 제품의 수준이기 때문에 상용제품 개발에도 큰 힘이 들지 않는다는 것이다.



그리고 마지막으로 기존에 구굴이 이루어 놓은 많은 것들을 사용할 수 있다는 것이다. 구글 플레이를 이용한 앱의 
배포라든지 Weave라는 IoT 프로토콜을 이용할 수 있다는 것, 각종 시스템 이미지나 업데이트 혹은 버그 픽스등을 
안정적으로 제공받을 수 있다는 점, 그리고 OS와 앱의 업데이트를 OTA 인프라를 이용해 진행할 수 있다는 것 등이
그것이다.



정리

길게 늘어놨지만 요점은 안드로이드 생태계를 기반으로 이미 구축된 구글의 다양한 서비스와 인프라들을 마음껏
이용할 수 있다는 것이다. 그럼 과연 이 것이 구체적으로 무엇을 의미하는가? 하는 것은 Android Things 사이트에
있는 내용을 차근차근 정리하면서 알아보도록 하자 (사실 가장 먼저 손대고 싶은 것은 샘플 프로젝트 중 텐서플로우를
이용하여 이미지 처리를 하는 예제인데 천리길도 한 걸음 부터…차근차근 나가자~^^).



블로그 이미지

마즈다

이미 마흔을 넘어섰지만 아직도 꿈을 좇고 있습니다. 그래서 그 꿈에 다가가기 위한 단편들을 하나 둘 씩 모아가고 있지요. 이 곳에 그 단편들이 모일 겁니다...^^