라즈베리파이와 안드로이드 앱, 그리고 Firebase를 이용한 백엔드 서비스 구현(로그인, 데이터 관리 등) 방법에 도움을 얻을 수 있을만한 코드를 공유합니다!

(원래는 블로그에 각 기능들에 상세하게 작성하려고 했으나 귀찮아 버린지 벌써 1년 가까이 넘었네..)

 

제가 졸업작품을 준비하면서(2021년) 초반에 작성했던 코드들입니다.

 

IoT 주제로 프로젝트를 진행하면서 라즈베리파이, 안드로이드 앱, Firebase에 관심이 있으신 분들이 많이 계실텐데 

코드를 공부하며 많은 도움이 될 수 있을거라고 생각합니다!

 

참고 링크: https://github.com/jow1025/Smart-fire-detection-system

 

GitHub - jow1025/Smart-fire-detection-system: IOT센서와 카메라를 결합한 스마트 화재감지 시스템입니다.

IOT센서와 카메라를 결합한 스마트 화재감지 시스템입니다. Contribute to jow1025/Smart-fire-detection-system development by creating an account on GitHub.

github.com

위 깃허브 링크를 통해 확인할 수 있는 기능은 다음과 같습니다.

 

1. Firebase

- 로그인/회원가입/로그인정보 재설정을 위한 메일 전송 기능

- 라즈베리파이에서 센서 데이터를 Firebase Realtime DB에 원하는 주기로, 원하는 Depth(단계)로 저장하기

- 라즈베리파이 카메라로 촬영한 사진을 Firebase Storage에 저장하기

- Storage에 저장된 사진을 외부에서 접근할 수 있는 URL를 이용하여 해당 URL을 Realtime DB에 데이터 처럼 담아서 해당 사진/동영상을 조회하기

(프로젝트를 진행하시다 보면 공감하시겠지만 센서 데이터 외에 사진/동영상 등을 Storage에 바로 담아서 앱/웹에서 꺼내는 방법보다 DB에 해당 파일의 URL을 담아서 이 URL정보를 이용하는 것이 훨씬 효율적입니다.)

- 안드로이드 앱 푸시 알람(ex. DB에 담긴 온도데이터가 특정 기준치를 넘었을 시 앱으로 알람 전송)

(수동 알람이 아닌 데이터 수치가 본인이 설정한 기준치를 넘었을 때 자동으로 알람되는 기능이기에 충분히 도움이 될거에요.)

- Firebase 사용자 권한을 설정하여 Storage에 담긴 파일의 URL를 외부에서 public으로 접근하도록 하기

(파일 접근 URL이 default는 private이기에 외부에서 접근 불가능합니다.)

 

2. Raspberry pi

- 라즈베리파이 카메라를 이용한 opencv 기반의 불꽃 인식

- 촬영한 사진을 Firebase Storage에 담고, 해당 파일의 접근 URL를 Realtime DB에 저장하기

- Flask웹서버를 이용하여 앱, 웹 등에서 원격으로 모터를 제어하여 카메라 각도 조절(로컬 서버 한정)

- 여러개의 센서를 이용하여 동시에 데이터 측정하기(아두이노+라즈베리파이)

- 멀티 쓰레드를 이용하여 원격제어/불꽃인식/사진전송/데이터 수집 등을 동시에 진행하기

 

3. 안드로이드 앱 

- Firebase Realtime DB에 저장된 센서데이터 전송받기

- MPAndroidChart 라이브러리를 활용하여 해당 데이터를 이용하여 그래프, 파이차트 등을 표현

- 앱에서 Firebase에 저장된 사진들을 조회/수정/삭제하기 

- 원격으로 라즈베리파이 모터 제어(카메라 각도 조절)

- 라즈베리파이 카메라로 찍고 있는 전방 화면 실시간 스트리밍(Mjpg streamer)

- 스트리밍 하며 불꽃을 인식하면 사진 촬영 후 Firebase에 전송

- Firebase를 이용하여 푸시알람 받기(불꽃인식, 데이터 수치 등)

 

 

4. 아두이노

- 센서로 측정한 데이터를 라즈베리파이로 전송

(wifi기능이 내장된 보드를 사용하지 않고 시리얼통신을 이용하였습니다.)

- 아두이노에서 전송되는 데이터 파싱

 

 

 

라즈베리파이에서 opencv로 실시간으로 스트리밍하는 코드에서 자꾸 오류가 나서 검색해봤더니

 

나오지도않고 많이 애를 먹었는데 생각보다 간단했기에 정리해봤습니다.

이 오류 때문에 단순히 카메라 자원을 쓰는것 자체가 불가능 했었는데요..

오류 문구는 아래와 같습니다. 저와 비슷하게 오류문구가 떴다면 한번 확인해보셨으면 좋겠습니다~~

 

[ WARN:0] global /home/pi/opencv/modules/videoio/src/cap_gstreamer.cpp (1901) handleMessage OpenCV | GStreamer warning: Embedded video playback halted; module v4l2src0 reported: Cannot identify device '/dev/video-1'. [ WARN:0] global /home/pi/opencv/modules/videoio/src/cap_gstreamer.cpp (990) open OpenCV | GStreamer warning: unable to start pipeline [ WARN:0] global /home/pi/opencv/modules/videoio/src/cap_gstreamer.cpp (577) isPipelinePlaying OpenCV | GStreamer warning: GStreamer: pipeline have not been created [ WARN:0] global /home/pi/opencv/modules/videoio/src/cap_v4l.cpp (833) createBuffers VIDEOIO(V4L2:/dev/video0): failed mmap(921600): errno=19 (No such device) [ WARN:0] global /home/pi/opencv/modules/videoio/src/cap_v4l.cpp (890) open VIDEOIO(V4L2:/dev/video0): can't open camera by index Traceback (most recent call last): File "/home/pi/ll.py", line 43, in observe() File "/home/pi/ll.py", line 18, in observe cv.imshow("VideoFrame", frame) cv2.error: OpenCV(4.5.1-dev) /home/pi/opencv/modules/highgui/src/window.cpp:404: error: (-215:Assertion failed) size.width>0 && size.height>0 in function 'imshow'

 

 

저의 경우 스트리밍 성능을 비교하기 위해 mjpeg-streamer, uv4l 패키지를 깔았는데요.

결과적으로 uv4l이 백그라운드 프로세스로 계속 열려있었고 카메라 자원을 점유하고 있는데

제가 계속 카메라 자원을 요청하고있었기에 발생한 출동 문제였습니다.

상단 오류 문구의 can't open camera by index가 그 증거이구요.

 

일단 사전에 카메라가 잘 연결되었는지, 장치가 등록되어있는지 확인해야합니다.

아래 명령어로 확인했을 때 detected, supported가 둘다 1이 떠야합니다.

vcgencmd get_camera

 

그리고 웹캠은 잘 모르겠으나 rpi cam ( v2모듈 등등)을 사용하고 계시다면 기본적으로

카메라 자원이 0번(video0)으로 등록이 되어있을 텐데 이 부분도 확인해야합니다.

 

ls /dev/video* 또는 ls /dev/video* -l 명령어로 video0이 뜨는지 확인해야합니다.

안뜬다면 카메라 재연결 + 리부트 해보시길 바랍니다.

 

이제 다음 단계입니다. 아래 순서대로 한번 확인해보시면 될 것 같네요.

 

1. 프로세스 확인 ps 명령어 혹은 ps -ef 

2. 사용하지 않는 카메라 스트리밍관련 서버 패키지 프로세스 kill

3. 그래도 안되면? 스트리밍 패키지가 데몬으로 부팅시마다 계속 실행 중인지 확인-> 있다면 해제

chkconfig --list 명령어로 확인하면 될 것 같습니다

(이 부분에서 제가 사용하지 않는 uv4l이 데몬으로 돌아가고 있어서 문제가 발생하였습니다.)

4. 확인 차 리부트 + 실행= 완료

 

**2021-07-06 추가 수정 사항 ***

videocapture함수의 인자를 -1또는 0으로 지정하여 프리뷰 화면을 이용하려 할 때 동시에 스트리밍을 하려고할 때 (mjpg streamer, uv4l, gstreamer등등) 자원선점 오류로 실행에 에러가 발생합니다.

이것은 카메라 자원을 동시에 두 군데에서 요청하기 때문에 발생하는 자연스러운 오류이며 위의 캡처본 같은 오류가 발생할 수 있습니다. 따라서 별도로 스트리밍 서버를 실행시켜놓고 파이썬 코드에서 opencv를 이용한 이미지 처리를 할 때 videocapture()함수 인자에 0또는 -1이 아닌 스트리밍 서버의 주소를 불러와야합니다. 프레임이 끊기는 문제에 대한 해결책은 좀 더 고민한 뒤 업로드 하겠습니다.

 

 

 

저번에 mjpeg-streamer을 이용한 스트리밍 방법에 대해 알아보았습니다.

라즈베리파이를 이용한 스트리밍 방법으로 mjpeg-streamer, uv4l, motion, VLC 등 다양한 방법들이 존재하고

각 방법마다 장단점이 있기에 이번시간에 UV4L을 이용한 스트리밍 방법에 대해 알아보겠습니다.

 

V4L2는 리눅스에서 카메라를 이용한 영상 획득과 출력 장치의 제어를 위한 API, 드라이버 프레임워크를 가리키며, USB 웹캠, TV 튜너장치등을 지원하는 소프트웨어입니다.

 

이제 설치와 실행단계를 진행하겠습니다.

 

1. 파이카메라 설정

 1) 라즈베리파이 보드에 연결한 뒤 "vcgencmd get_camera" 명령어로 잘 연결되었는지 확인합니다.

 2) sudo nano /etc/modules를 입력한 뒤 bcm2835-v4l2(알파벳L)를 추가해줍니다.

 (라즈베리파이가 부팅 될 때 마다 bcm2835-v4l2모듈을 로드하게됩니다.)

2. 버전 세팅(주의)

uv4l을 사용하기 위해 버전에 따라 apt 키(인증키)를 추가해주는 작업입니다.

대부분 rpi OS Lite버전이나 buster버전을 사용하기 때문에 이 방법으로 설명하겠습니다.

그 외 다른 버전의 OS이라면 아래 링크를 참고해주세요.

www.linux-projects.org/uv4l/installation/

 

Installation for ARM (Raspberry Pi) – (advanced) Projects

How to install or upgrade UV4L on Raspbian Wheezy, Raspbian Jessie, Raspbian Stretch, Raspbian Buster (Raspberry PI OS) for Raspberry Pi IMPORTANT! Packages for Raspbian Wheezy and Raspbian Jessie are no longer maintained, consider to upgrade your system t

www.linux-projects.org

 1) 이제 아래 명령어를 입력해줍니다.

 curl https://www.linux-projects.org/listing/uv4l_repo/lpkey.asc | sudo apt-key add - 

 주의: https -> http로 작성하면 나중에 에러납니다 ㅠㅠ 이거때문에 힘들었네요;

 맨 아랫줄에 OK가 나와야합니다. 아래 사진은 에러가 난 경우입니다. (s 하나 빼먹어서 에러가 난다고?...)

 

 2) sudo nano /etc/apt/sources.list에 아래 문장을 입력한 뒤 저장합니다. (두 번 째 줄 추가)

 3) sudo apt-get update 명령어로 패키지를 업데이트 해줍니다.

 아래 처럼 나온다면 1) 단계에서 잘못된겁니다.

3. UV4L 설치

 1) sudo apt-get install uv4l uv4l-raspicam 명령어를 입력합니다.

 2) 부팅 시 드라이버가 로드 될 수 있도록 아래 명령어를 입력합니다.

 sudo apt-get install uv4l-raspicam-extras

4. 시작, 종료하기

 1) 스트리밍 서버 패키지 설치단계로, 아래 명령어를 입력합니다. 이제 웹에서 스트리밍을 볼 수 있습니다.

 sudo apt-get install uv4l-server uv4l-uvc uv4l-xscreen uv4l-mjpegstream uv4l-dummy uv4l-raspidisp

 

 2) sudo service uv4l_raspicam restart 명령을 입력하여 서비스를 시작합니다.

  "/etc/uv4l/uv4l-raspicam.conf" 파일에서 높이, 너비 등의 여러 설정을 변경할 수 있습니다.

 

 3) 웹 브라우저에 https://ip:8080"을 입력하면 아래 화면이 나타납니다.

 4) 해상도를 조절하기 위해 톱니바퀴 모양(control panel)을 클릭합니다.

 * default 해상도는 1920*1080으로, 너무 해상도가 높으면 화면이 끊길 수 있습니다.

 해상도를 640*480으로 맞추고 포맷을 MJPEG로 맞춘뒤 상하반전을 위해 vertical mirror를 enable로 변경했습니다.

 이제 맨 아래 apply버튼을 클릭해줍니다.

 5) 스트리밍 화면 출력

 http://라즈베리파이주소:8080/stream/video.mjpeg 명어를 실행해보면 스트리밍 화면이 뜹니다!

 원래 많이 끊기는건지 와이파이 연결상태가 안좋아서 그런건지.... 해상도를 낮췄는데도 많이 끊겼습니다.

 6) 스트리밍 종료

 uv4l은 ps 명령어를 입력해도 프로세스가 안떠서 sudo pkill uv4l 명령어로 종료합니다.

 

이로써 uv4l을 이용한 스트리밍 실습이 끝났습니다~

 

 

이번시간에 라즈베리파이 카메라로 동영상을 스트리밍 하는 방법에 대해 알아보겠습니다.

라즈베리파이의 스트리밍 기술스택을 알아보면서 motion, G-streamer, mjpg-streamer 등 많은 방법들이 있음을 알게되었습니다.

이 중에서 mjpg-streamer라는 패키지를 이용해서 동영상을 스트리밍 해보겠습니다.

 

일단 패키지 설치 전 다음 두 명령어로 패키지를 업데이트/업그레이드 해줍니다.

 

sudo apt-get update

sudo apt-get upgrade

 

스트리밍 패키지를 깃허브에서 클론 해 와야하기 때문에 저장할 폴더를 만들어주고 이동한 뒤 패키지를 클론합니다.

mkdir ./mjpg

cd mjpg/

git clone https://github.com/jacksonliam/mjpg-streamer.git 

다운이 완료 됐으면 받은 폴더의 mjpg-streamer/mjpg-streamer-experimental/로 이동합니다.

cd mjpg-streamer/

cd mjpg-streamer-experimental/

 

아래 명령어를 입력하여 컴파일 및 설치를 해줍니다.

sudo apt-get install cmake

 

이제 mjpg-streamer에 필요한 패키지를 설치하는데, 이부분은 다른분들의 참고를 했는데 될 때도 있고 안될 때도 있는 것 같습니다. 나중에 확인해도 문제가 없었기 때문에 일단 명령어를 입력해봅니다.

 

sudo apt-get install python-imaging (저는 이 패키지 설치에서 에러났지만 결과에 영향이 없었습니다.)

sudo apt-get install libjpeg-dev

 

이제 컴파일 해줍니다.

make CMAKE_BUILD_TYPE=Debug

완료되었습니다. 컴파일이 정상 완료되었으니 이제 mjpg-streamer를 설치합니다.

 

sudo make install

패키지 설치는 모두 끝났고 이제 홈 디렉토리로 돌아와 쉘 편집기를 열어줍니다.

cd ~

sudo nano mjpg.sh

적혀있는 코드를 아래와 같이 수정합니다. 포트는 사용하지않는 8091를 사용했습니다.

fps 는 디폴트로 5가 설정되어있는데 너무 끊기기 때문에 10정도로 맞춰줬고(전 나중에 15로 바꿔줬어요) -vf옵션으로 상하 반전으로 맞췄습니다.

fps를 높이고 -x,-y 가로세로 폭을 줄여주니깐 화질이 비교적 매끄럽게 나오더라구요.

 

명령어 옵션은 아래 그림을 참고해주세여

이제 아래 명령어로 스트리밍을 실행해봅니다. 

sh mjpg.sh

명령어를 입력하면 아래와 같은 화면이 뜨면서 스트리밍 서버가 실행중임을 알 수 있습니다.

이제 웹에서 ip주소:8091(아까 지정한 포트넘버)를 입력해보겠습니다. 아래화면이 떠야 정상입니다.

왼쪽 배너에서 stream을 클릭해주면 실시간 스트리밍 화면을 볼 수 있습니다.!!

15fps로 맞춰놨는데 엄청 부드럽진 않습니다. 카메라 사양 차이도 있을 것 같네요.

스트리밍을 중단하고 싶으면 아까 스트리밍을 실행시켰던 cmd창에 ctrl+Z를 입력하면 됩니다.

바로 스트리밍을 동작 시키면 프로세스 간 충돌이 일어날 수 있어서 에러가 납니다.

cmd창에 ps명령어로 지금 돌아가고있는 프로세스 목록을 확인하고

아래 명령어로 아직 종료되지 않은 1649 PID를 종료합니다.

 

kill -9 1649

 

이제 다시 확인해보면 지워졋죠?

아닙니다.(defunct는 좀비프로세스로 아직 완전히 종료되지않고 떠돌고 있는 상태의 프로세스입니다.)

mjpg-streamer 프로세스를 종료시키는게 아니라 sh 프로세스(1648번)를 종료해야합니다.

kill -9 1648

sh프로세스와 mjpg_streamer 프로세스가 같이 종료되었습니다.

이제 다시 쉘 명령어로 스트리밍을 시작할 수 있습니다. 

 

참고로 아까 웹사이트에 ip, 포트넘버를 입력하면 어떤 창이 하나 떴잖아요?

이거를 안띄우고 바로 스트리밍 화면을 보고싶다면 웹 주소에 ip주소:포트넘버/?action=stream 꼴로 작성하면됩니다.

ex) 162.178.31.2:8091/?action=stream

 

엔터치면 바로 스트리밍 화면이 뜨는 걸 확인할 수 있습니다.

다시 ps -> kill 명령어로 프로세스를 종료하여 사용을 마치도록합니다.

 

이상입니다!

 

 

 

요 근래에 서버/DB 사용을 위해 파이어베이스를 다뤄보고 있는데 여러모로 쓸만 한 것 같습니다. 

 

이번시간에는 라즈베리파이 카메라 v2로 주기적으로 사진을 촬영하고 이미지를 파이어베이스의 storage에 저장하는 코드를 작성해보겠습니다.

처음에 파이어베이스의 realtime database와 firestore database, 그리고 storage의 차이가 뭔지 몰랐는데 이미지파일은 DB에 저장이 안되는 것 같습니다.

(검색해보니까 이렇게 나오네요)

 

이제 순서대로 이 예제를 실행해보겠습니다.

라즈베리파이 카메라 연결

일단 라즈베리파이에 카메라를 연결해야합니다. 연결하고 라즈베리파이 configuration->interface에서 카메라를 enable 시켜준 뒤 잘 연결이 되었는지 아래 명령어로 확인합니다.

만약 supported 값은 1인데 detected가 0이라면 정상적으로 연결되지 않은 것입니다.

 

vcgencmd get_camera

 

그리고 firebase-admin 패키지를 설치하고 주기적으로 사진을 찍는 스케쥴을 관리하기 위해 스케줄 패키지를 설치해줍니다.

 

sudo pip3 install firebase-admin

 

sudo pip3 install schedule

 

이제 파이어베이스 홈페이지에서 간단하게 설정을 해줘야 하는데, 우리가 필요한 건 프로젝트 ID, 비공개 키, 스토리지 주소입니다.

차례대로 설정단계를 알아보겠습니다.

 

파이어베이스 프로젝트 생성

파이어베이스 storage생성 전 프로젝트 생성단계는 간단하므로 넘어가겠습니다. 프로젝트 ID는 프로젝트 생성 후 프로젝트 목록을 보시면 프로젝트 이름과 아래에 작게 아이디가 적혀있습니다.

파이어베이스 Admin SDK 키 생성

이제 키를 발급받아야하는데, 파이썬에서 프로그래밍으로 파이어베이스와 연동하기 위해 일종의 자격 증명서 같은 전용 "키"의 역할을 합니다.

프로젝트로 들어간 뒤 왼쪽 배너의 톱니바퀴-> 프로젝트 설정으로 들어갑니다. 파이썬을 사용하므로 구성 스니펫을 파이썬으로 체크한 뒤 비공개 키를 생성합니다. 키를 다운받아놓고 본인이 잘 기억할만한 폴더에 저장해 둡니다.(까먹거나 잃어버리면 안됩니다..;)

라즈베리파이에서 이 키를 사용해야 하므로 이제 그 키를 라즈베리파이의 디렉토리에 복사를 해야합니다.

삼바를 통해 json파일을 넘겨주고 아무 디렉토리에 저장시켜줍니다.

파이어베이스 storage생성

왼쪽 배너에서 storage를 클릭하고 새 스토리지를 생성하는데, 이 때 보안규칙, 위치설정 등은 기본 디폴트로 진행합니다.

완료를 누르면 "버킷 생성중" 메시지가 뜨고 생성이 완료됩니다. 창을 보면 ~~appspot.com 주소가 있는데 파이어베이스 스토리지의 주소라고 보시면됩니다.

 

이제 라즈베리파이에서 파이어베이스 연동을 위해 필요한 프로젝트ID, 비공개 키, 스토리지 주소까지 모두 준비가 완료되었습니다. 

라즈베리파이 코드 작성 및 실행

자칫 헷갈릴 수 있으므로 코드 작성 전에 코드에 필요한 정보들을 나열하고 넘어가겠습니다. 

1. 프로젝트 ID : 프로젝트 생성 후 프로젝트 목록에 나와있음 

2. Admin SDK 키 : .json키 파일을 삼바를 통해 라즈베리파이 디렉토리에 저장합니다.

저는 /home/pi/Downloads(생성폴더)에 저장시켜 놨습니다.

3. 스토리지 주소 : 파이어베이스 storage에 들어가면 gs://키정보.appspot.com 이 있는데 이 정보도 이용합니다.

4. 스토리지 디렉토리 이름 : 프로그래밍으로 본인이 지정한 이름의 폴더를 파이어베이스 저장소에 만들 수 있습니다.

5. 사진 찍고 저장할 디렉토리 이름 : 주기별로 사진을 찍고 저장할 디렉토리입니다. 저는 /home/pi/image_store로 만들어주었습니다.

 

이제 코드를 살펴볼 차례입니다. 기본적인 틀은 다른분들의 코드와 공식 문서를 참고하여 작성했습니다.

웬만한 중요 부분은 주석으로 보충 설명하였고 64~69행 설정으로 사진을 찍고 삭제하는 주기를 조절할 수 있습니다.

파일명은 현재 년/월/일로 시/분/초로 나타냈습니다.   

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# _*_ coding: utf-8 _*_
from picamera import PiCamera
from time import sleep
import datetime
import sys, os
import requests
import firebase_admin
from firebase_admin import credentials
from firebase_admin import storage
from uuid import uuid4
import schedule
 
PROJECT_ID = "project-8965d"
#my project id
 
cred = credentials.Certificate("/home/pi/Downloads/(키 이름).json"#(키 이름 ) 부분에 본인의 키이름을 적어주세요.
default_app = firebase_admin.initialize_app(cred,{'storageBucket':f"{PROJECT_ID}.appspot.com"})
#버킷은 바이너리 객체의 상위 컨테이너이다. 버킷은 Storage에서 데이터를 보관하는 기본 컨테이너이다.
bucket = storage.bucket()#기본 버킷 사용
 
def fileUpload(file):
    blob = bucket.blob('image_store/'+file#저장한 사진을 파이어베이스 storage의 image_store라는 이름의 디렉토리에 저장
    #new token and metadata 설정
    new_token = uuid4()
    metadata = {"firebaseStorageDownloadTokens": new_token} #access token이 필요하다.
    blob.metadata = metadata
 
    #upload file
    blob.upload_from_filename(filename='/home/pi/image_store/'+file, content_type='image/png'#파일이 저장된 주소와 이미지 형식(jpeg도 됨)
    #debugging hello
    print("hello ")
    print(blob.public_url)
 
def execute_camera():
    
    #사진찍기
    #중복없는 파일명 만들기
    basename = "smr"
    suffix = datetime.datetime.now().strftime("%Y%m%d_%H%M%S"+ '.png'
    filename = "_".join([basename, suffix])
 
    camera = PiCamera()
    camera.resolution = (640480)
    camera.start_preview()
    #이미지에 텍스트를 새겨 넣자.
    camera.annotate_text = "Smart Mirror"
    camera.annotate_text_size = 20
    sleep(5)
    #사진을 찍어서 저장한다. 파일의 중복되지 않도록 날짜시간을 넣어서 만듬
    camera.capture('/home/pi/image_store/' + filename)
    #사진 파일을 파이어베이스에 업로드 한다.
    fileUpload(filename)
    #로컬 하드의 사진을 삭제한다.
    camera.stop_preview()
    camera.close()
 
#메모리 카드의 파일을 정리 해 주자.
def clearAll():
    #제대로 할려면 용량 체크 하고 먼저 촬영된 이미지 부터 지워야 할것 같지만 여기선 폴더안에 파일을 몽땅 지우자.
    path = '/home/pi/image_store'
    os.system('rm -rf %s/*' % path)
 
 
#10초 마다 실행
schedule.every(10).seconds.do(execute_camera)
#10분에 한번씩 실행
#schedule.every(10).minutes.do(execute_camera)
#매 시간 마다 실행
schedule.every().hour.do(clearAll)
#기타 정해진 시간에 실행/매주 월요일에 실행/매주 수요일 몇시에 실행 등의 옵션이 있다.
 
 
while True:
    schedule.run_pending()
    sleep(1)
 
 
 
cs

 

이제 실행해봅니다. 위 코드를 test.py라는 이름으로 작성했다고 한다면 다음처럼 실행하면됩니다.

sudo python test.py 

 

주의할점으로 제 환경 기준으로 커맨드 창에서 코드를 작성하고 실행해보니 계속 오류가 떴었습니다.

No module name firebase_admin 이라는 오류가 뜨면 sudo pip install firebase_admin으로 다시 깔아주면(파이썬3버전이 아닌 1버전) 오류는 사라집니다. 

 

여기까지 진행하고 정상 진행이 되면 상관없으나 에러가 나시는 분들은 당황하지 마시고  화면 상단의 산딸기 모양을 클릭하고 개발 탭에서 토니IDE에 소스를 복붙해서 실행해봅니다. (아마 잘 되실겁니다.) 토니 IDE는 기본으로 깔려있고 그냥 가벼운 비쥬얼 스튜디오라고 생각하시면됩니다.

이제 다시 실행해봅니다 !!

 

출력되는 "hello"는 제가 그냥 정상작동되는지를 확인하기 위해 넣은 코드입니다. 잘 작동한다면 이렇게 출력되겠죠??

20초동안 두 장만 촬영하고 프로그램을 중지 해 보겠습니다.

이제 파이어베이스 storage에 정상적으로 저장되었는지 볼까요??

 

이렇게 이미지 업로드 폴더가 생겼고

클릭해보면 두장의 사진이 잘 저장되어있음을 알 수 있습니다~~

아무거나 클릭해보면 사진화면이 잘 나오는걸 확인할 수 있어요.(TMI: 카메라에 비친 인공눈물 박스)

 

 

안드로이드와 연동하는 시스템을 목표로 파이어베이스를 사용하시는 분들은 위 그림 오른쪽 처럼 사진파일의 메타 데이터들도 쉽게 이용할 수 있습니다.

관련 예제를 본 것 같은데 다음에 한번 시도해 보겠습니다.

 

이상입니다~

 

 

이번시간에는 라즈베리파이의 웹서버 사용 및 간단한 웹 페이지 구축을 해보고 웹서버를 데스크탑(외부)환경에서 접근하는 방법에 대해 알아보겠습니다.

 

일반적으로 공유기 설정을 통한 포트 포워드 방식이 아닌, 작은 프로젝트에서 간이로 사용하는 방법임을 말씀드립니다.

 

먼저, 실습에 사용할 웹서버를 알아보겠습니다.

 

라즈베리파이에서 웹서버를 구축하기 위해 다양한 방법이 존재합니다.

 

아파치, AWS, Nginx 등 많은 웹서버 구축 방법이 존재하는데, 이번시간에 알아볼 웹서버 환경은 "CherryPy" 입니다.

 

체리파이는 파이썬 프로그래밍 언어를 사용하는 객체지향 웹 프레임워크입니다.

다른 WAS, 프레임워크들에 비해 간단하고 신속하지만, 낮은 수준을 유지하고 오래되서 많이 쓰이진 않습니다. 

 

이제 설치단계부터 하나씩 알아보겠습니다.

 

우선 cmd창에 아래 명령어로 체리파이를 설치해줍니다.

 

sudo pip3 install cherrypy

 

이제 잘 설치되었는지 확인해야합니다.

소스코드작성은 라즈비안에 내장된 IDE인 Thonny를 쓸 것 입니다.

Thonny 실행 화면에서 상단의 Tools -> Manage packages.. 를 클릭합니다.

아래와 같이 패키지가 잘 뜨면 설치가 정상적으로 완료된 것입니다.

이제 간단하게 웹 브라우저에 텍스트를 찍어보겠습니다.

아래와 같이 소스코드 작성 후 상단의 시작 버튼을 클릭하면 쉘창에 서버가 시작되었다는 문구가 출력됩니다.

맨 하단의 두 줄을 보면 엔진서버가 127.0.0.1:8080이고 시작되었다고 나와있죠.

127.0.0.1 은 자기 pc의 IP주소, 즉 루프백 주소를 나타냅니다. 기본적으로 로컬 포트번호는 8080으로 지정되있습니다.

 

이제 라즈비안의 웹 브라우저를 키고 127.0.0.1:8080 를 입력하면 아래와 같이 문구가 뜨게됩니다.

서버를 멈추고 싶으면 실행 프로그램을 중지 시키면됩니다.

 

아래처럼 html 코드를 이용할 수도 있습니다.

1. static.html코드 작성

2. StaticPage.py작성

3. 결과

 

파이썬 언어 뿐만 아니라 기본적인 웹언어(html, css, js)를 모두 사용할 수 있습니다.

html로 기본 틀을 잡고 css로 디자인을 하는 등(ex) 부트스트랩)  모든 것이 가능합니다.

위의 예제 코드처럼 클래스 안에 html 코드를 작성 한 뒤 똑같이 cherrypy.quickstart(클래스 명)을 입력하면 웹에 정상적으로 출력됩니다.

 

아래는 weatherMap API를 이용하여 세계 도시의 기상정보를 웹에 출력한 화면입니다.

 

 

이제 본론으로 돌아와서 간단하게 외부환경에서 이 웹에 접근하는 방법에 대해 알아봅니다.

 

단순히 어떠한 설정 없이 데스크탑 크롬, 엣지, 익스플로어 등으로 127.0.1:8080을 입력하면 실행이 되지 않습니다.

 

이는 라즈베리-데스크탑의 망이 서로 다르기 때문인데 이는 포트포워딩 방법으로 외부방에서 내부방 접근을 허용하는 설정을 통해 해결할 수 있습니다.

 

우리는 이 방법을 쓰지않고 간단하게 외부에서 로컬 호스트로 접속하는 시도를 해보겠습니다.

이 방법은 내가 만든 프로젝트를 외부에서 접근하고싶을 때 간단하게 사용하는 방법입니다.

 

우선 라즈비안에서 웹 브라우저로 ngrok.com/download 에 접속하여 리눅스 버전 압축파일을 다운 받습니다.

cmd창에서 명령어로 다운받을 수 있지만 간혹 설치 에러가 발생하여 위 방법으로 진행하는 게 마음이 편합니다. 

다운을 받고 압축파일을 우클릭하여 압축을 풀어줍니다. 저는 똑같은 디렉토리에 압축을 해제했습니다.

실행파일이 정상적으로 저장되었음을 확인합니다.

이제 cmd창에서 파일 실행을 위해 파일이 저장된 디렉토리로 이동합니다.

(파일이 저장된 디렉토리로 이동하지 않으면 당연히 실행되지 않습니다.)

이제 "./ngrok http 8080" 를 입력합니다.

이 명령어는  ngrok을 실행하여 localhost에 8080포트를 열어 체리파이 index를 외부에서 접근하도록 한다는 의미입니다.

http 터널을 8080포트에 열어주기 위해 위 명령으로 실행하는 것입니다.

엔터 치고나면 프로그램이 진행되며 다음과 같은 정보들을 알려줍니다.

Session Expires의 7hours, 59munutes는 동작 시간이 최대 8시간임을 타나내는 것이고 빨간 박스부분이 포워딩된 웹 사이트의 주소가 됩니다.

이제 아까 위에서 보았던 날씨API 웹사이트 코드를 실행합니다. cherrypy를 이용하여 서버를 실행하게 되죠?

 

이제 위 사진에서 포워딩된 두 웹 주소 중 아무거나 데스크탑 환경의 크롬, IE, edge 등에서 띄워봅니다.

 

아래와 같이 잘 동작함을 알 수 있습니다!

(css를 적용하지 않고 html의 그리드로 수정했기 때문에 위에서 본 페이지와 디자인이 다릅니다.)

 

 

이번시간에는 라즈베리파이와 PC간에 서로 파일을 주고받기 위해 SAMBA라는 파일공유 패지지를 설치해보겠습니다.

 

매우 간편하고 쉽기 때문에 많이 사용하는 방식입니다.

 

내컴퓨터에 라즈베리파이 ip를 입력하게되면 라즈베리파이의 파일 디렉토리가 뜨게되고 실제 데스크탑의 디렉토리처럼

 

쉽고 간편하게 서로 간에 파일을 전송할 수 있습니다.

 

일단 패키지 설치에 앞서 아래 두 명령어로 현재 패키지를 업데이트 해줍니다.

 

sudo apt-get update

sudo apt-get upgrade

 

그 다음 아래 명령어로 SMABA 패키지를 설치해줍니다.

 

sudo apt-get install samba samba-common-bin

 

설치  도중 아래 화면이 뜨면 <아니오>에 체크해주면 됩니다.

 

그 다음 아래 명령어로 삼바서버에 사용할 계정과 비밀번호를 설정합니다.

아이디는 pi 이고 password는 두번 입력하면 설정됩니다. (설정:"raspberry")

이후 아래 명령어로 설정파일을 열어준 뒤 파일 하단에 다음과 같은 텍스트를 추가하고 저장합니다.

 

sudo nano /etc/samba/smb.conf

 

path는 공유할 디렉토리의 경로를 의미합니다.

 

이제 samba를 재실행합니다.

 

sudo service smbd restart

 

이제 내컴퓨터를 열고 검색창에 \\192.168.0.9(라즈베리파이 ip)를 입력하면 pi디렉토리가 뜨는것을 확인할 수 있습니다.

 

pi 디렉토리를 클릭한 뒤 id/비밀번호 ( pi/raspberry)를 입력하면 다음과 같이 라즈베리파이의 모든 파일목록이 보이게됩니다.

 

이를 이용해 pc에서 라즈베리파이로, 혹은 반대로 라즈베리파이에서 pc로 파일을 전송하고 싶을 때 쉽게 파일을 주고받을 수 있습니다.

 

 

 

이번시간에는 데이터 베이스 사용을 위해 라즈베리파이에 MariaDB를 설치하고 다른 인터넷 환경(웹, 앱 등)에서

DB를 연동해서 사용하기 위한 준비단계에 대해 알아보겠습니다.

 

이를 통해 라즈베리파이에서 센서나 카메라 모듈을 통한 동영상 파일 등을 DB에 저장하여 앱이나 웹에서 이 데이터를 이용할 수 있을 것입니다.

 

설치 순서는 다음과 같습니다.

 

라즈베리파이에 mariadb 설치-> 외부 접속 ip 설정 -> 윈도우에 workbench 설치-> db연동 정상동작 확인

 

 

일단 새로운 패키지를 설치하기 전에 다음 두 명령어로 기존의 패키지들을 업데이트해줍니다.

 

sudo apt-get update

sudo apt-get upgrade

 

그 다음 아래 명령어로 mariadb를 설치해줍니다.

 

sudo apt-get install mariadb-server

설치된 mariadb의 버전을 아래의 명령어로 확인합니다. 10.3.27 버전이 설치되었음을 확인할 수 있습니다.

 

이제 db에 접속합니다.

mysql 명령어를 입력 시 권한 문제로 오류가 뜨기 때문에 루트 계정으로 db에 접속합니다.

 

아래 사진은 기본 데이터 베이스 목록을 확인하고 mysql 이름의 db로 접속하는 명령어입니다.

 

다음 명령어를 입력하면 기본으로 저장되어있는 mysql 데이터베이스의 plugin 컬럼이 unix_socket으로 되어있습니다.

 

select user,host,plugin from mysql.user; 

 

이 플러그인 정보를 mysql_native_password로 변경합니다. 

flush privileges 명령은 테이블 변경정보를 즉시 적용하는 명령어입니다.

이제 exit명령어로 빠져나와 다시 아래 명령어로 db에 접속합니다.

패스워드는 기본적으로 저장되어있지 않기 때문에 Enter password: 부분에서 enter를 누르면 접속됩니다.

이제 아래 명령어로 루트 계정의 db 비밀번호를 raspberry로 바꿔준 뒤 (비밀번호는 자유) exit로 빠져나옵니다.

 

이제 다른 인터넷 환경에서 라즈베리파이의 db에 접속하기위해 ip설정을 변경하는 단계입니다.

아래 그림처럼 순서대로 명령어를 입력해줍니다. 이 때 아래 2줄을 보면 nano와 sudo nano가 있는데

무조건 sudo nano 50-server.cnf 명령어로 파일을 열어야 합니다. (그냥 nano 적용 시 변경 값 저장이 안됨)

 

이제 그림 하단부의 bind-address를 0.0.0.0로 바꿔준 뒤 저장 후 파일에서 빠져나옵니다.

초기설정은 127.0.0.1로 되어있는데, 이는 로컬 ip주소로 자신의 ip주소를 나타내는데, 이 경우 로컬 ip주소만(라즈베리파이) DB에 접속할 수 있으므로 다른 인터넷 환경에서도 접속할 수 있도록 0.0.0.0으로 변경합니다.

이제 아래 명령어로 db를 재부팅해줌으로써 라즈베리파에서의 모든 설정은 끝났습니다.

 

이제 window환경에서 db를 연동하여 사용하기 위해 데스크탑에 workbench 프로그램을 설치해줍니다.

*workbench: 데이터 베이스를 gui 환경에서 손쉽게 이용, 제어할 수 있는 프로그램

 

https://dev.mysql.com/downloads/workbench/

 

MySQL :: Download MySQL Workbench

Select Operating System: Select Operating System… Microsoft Windows Ubuntu Linux Red Hat Enterprise Linux / Oracle Linux Fedora macOS Source Code Select OS Version: All Windows (x86, 64-bit) Recommended Download: Other Downloads: Windows (x86, 64-bit), M

dev.mysql.com

설치 완료 후 프로그램을 실행한 뒤 상단의 Database 탭-> Manage Connections..를 클릭하여준 뒤 아래처럼 설정해줍니다.

Connection Name: raspberry(자유)

Host name: 라즈베리파이 ip주소

user name: root

Store in Vault.. 버튼 클릭-> 아까 라즈베리파이에서 설정한 비밀번호("raspberry") -> OK클릭

 

이제 하단의 Test Connection버튼을 클릭하여 다음과 같은 화면이 뜬다면 연결에 성공한 것입니다.

                                

 

이제 홈화면에 아래와 같이 raspberry 커넥션이 뜨게 되고 아래와 같이 정상 연결되었음을 확인할 수 있습니다.

 

이제 db연동이 정상작동 되는지 확인해보겠습니다. workbench에서 새 db를 생성하고 라즈베리파이에서 확인해봅니다.

오른쪽 Query창에 아래처럼 입력한 뒤 두줄을 블럭처리하여 ctrl+enter 를 누르면 쿼리문이 수행됩니다.

 

 

이제 라즈베리파이에서 아래 순서대로 진행하여 workbench에서 생성한 "jow1025" db가 출력되는 것을 확인할 수 있습니다.

 

이상입니다! 

+ Recent posts