DIY智慧型家居安全掛鐘(3/3)

        繼續上兩篇居家安全掛鐘的製作,我們回顧一下該掛鐘的功能流程圖如下:

在設定好三項外部服務:Email、Image upload、簡訊之後,我們繼續程式的寫作。

使用者介面

我們希望這個居家安全掛鐘,在外觀及平時使用上仍然保有掛鐘的本質:看時間報時以及裝飾,操作上愈簡單愈好,使用者只有在特定需求時才要去進行額外的操作:按下模式切換鈕。所以外觀上它與普通的掛鐘無異,僅多出一個按鈕:模式切換鈕,我們先看看這個切換鈕的設計。

模式切換鈕

        為了能方便的選擇三個模式:居家/外出/自動,我們拉出一個按鈕讓使用者能夠直接切換,每按一次就會依序的輪替這三個模式。此外我們希望若掛鐘關機或意外重開時,能夠自動回復到上次所選擇的模式繼續運行,所以在每次切換後,我們要把選擇的模式代碼儲存在外部文字檔中,在每次開機運行之後讀取。

運作及模式告知

        我們將兩顆三色LED裝在貓頭鷹掛鐘的眼睛上,透過顏色讓使用者知道目前的執行模式或正在執行的動作。

平時:外觀與正常的掛鐘無異,LED不會發亮。

居家模式:綠色。按下按鈕切換至居家模式時,會發出綠色燈光。

外出模式:紅色。按下按鈕切換至外出模式時,會發出紅色燈光。

自動模式:藍色。按下按鈕切換至自動模式時,會發出藍色燈光。

忙碌中:持續發亮在播放語音或拍攝相片時,則持續發出目前所在模式的顏色。

當機或錯誤:混雜顏色。當機或程式發生錯誤以至於無法運行,則發出混雜的色彩。

語音訊息:

我們透過工研院TTS功能的語音產生器,預先製作了各種語音wav檔,這些語音檔將放置於樹莓派wav資料夾下,讓掛鐘不需連至網路便可依指令迅速的發出聲音,例如整點報時、模式切換告知、目前室內溫溼度及煤氣指數、煤氣外洩警報、嚇阻小偷的各式聲音、靜思語錄…等等。

程式執行流程

程式代碼說明

        以下簡單介紹數個重要的程式功能:

使用者參數設定

        這部份是屬於可彈性調整的參數,提供給使用者進行細部調整或個人化使用。未來我們將討論如何提供使用者設定介面,讓使用者能夠透過手機或外部裝置直接連線物聯網裝置進行設定,而非直接修改程式的內容。

#=======CONFIGURE============================================
APIKEY_MAILGUN = "key-YOUR-API-KEY"
API_MAILGUN_DOMAIN = "YOUR-DOMAIN"

#-for mode 1 ---------------------
tvList = ["wav/tv/tv1.mp3", "wav/tv/tv2.mp3", "wav/tv/tv3.mp3", "wav/tv/tv4.mp3", "wav/tv/tv5.mp3", "wav/tv/tv6.mp3", "wav/tv/tv7.mp3"]

PIR_sleep_PictureAgainPeriod = 30 #要休息幾秒再度開始一輪的拍攝
PIR_sleep_take_2_PicturesPeriod = 0.5 #拍攝每張相片的間隔時間

modeSecutirt_waittime = 300 # 180, 300, 600, 900 設定外出模式後. 幾秒後才會開始動作.
#-for all mode ------------------------------
ENV_checkPeriod = 180 #幾秒要偵測一次溫溼度等環境值
ENV_takePicture_period = 1800 #居家或外出模式下,每隔幾秒拍一次

securityAuto = 0 # 半夜是否自動轉為安全模式,0為否,1為是
securityAuto_start = 1 #開始時間(24小時制)
securityAuto_end = 6 #結束時間(24小時制)

#設定簡訊的主旨
msgSMS = "PIR Alert! 家中有人入侵,請注意。"

speakVolume = "+700" #音量大小

#儲存於本機以及相片上傳的尺寸
localImageSize_w = 1296
localImageSize_h = 972
uploadImageSize_w = 720
uploadImageSize_h = 480

氣象播報功能語音:

        我們直接使用之前在介紹工研院TTS時所製作好的Python class,由於該模組使用PHP呼叫工研院的TTS系統,因此請記得要先安裝Apache及PHP模組,才能順利的透過PHP來呼叫。

        安裝Apache/PHP :

sudo apt-get install apache2 apache2-utils

sudo apt-get install libapache2-mod-php5 php5 php-pear php5-xcache php5-mysql php5-curl php5-gd

調整相片ISO值

        我們知道,當光線愈暗時,透過調整ISO以提高感光度可讓相片拍攝結果不至於過暗,但缺點是ISO愈大雜訊愈多而使得影像畫質較為粗糙。在本系統所使用的樹莓派官方PI Camera模組,它的ISO值可透過程式來調整相當方便,不過上限僅到800。為了能在適當的光線下使用適當的ISO值,我們可以利用TEMT6000光照度模組,先判斷拍攝當時的光照度後再決定最佳的ISO值。

ISO400

ISO640

camera.ISO = 100 #預設ISO

 if lightDegree>50 and lightDegree30:
 camera.ISO = 400

 elif lightDegree<=30 and lightDegree>20:
 camera.ISO = 600

 elif lightDegree<=20:
 camera.ISO = 800


使用中斷interrupts

我們希望PIR在偵測到有人時,能夠立即停止目前工作,優先執行拍照上傳並傳送警示訊息,因此有必要使用中斷功能。所以請記得替PIR使用的腳位註冊中斷程序,當偵測到PIR模組偵測到有人而使得腳位電流上升時,將會立即執行MOTION函式。

        GPIO.add_event_detect(pinPIR, GPIO.RISING, callback=MOTION)

Motion函式

此函式執行拍照上傳以及發送email、簡訊等功能。當在外出或自動模式下偵測到有人時,則將觸發中斷功能執行本函式,並寄出如下的email。

C:\Users\CHE7C6~1.TSE\AppData\Local\Temp\x10sctmp16.png http://res.cloudinary.com/appflyer/image/upload/v1467272941/20160630154857.jpg.jpg

#for Interrupts--------------------------
def MOTION(pinPIR):
 #定義所使用的全域變數
 global lastPIRfounded, PIR_last_pictureTime, modeOperation, modeSecutiry_starttime, ENV_lastwarningtime, ENV_warning_repeat_period, autoSecutiryNow, msgSMS
 #顯示目前模式的燈號
 lightLED(modeOperation)
 #目前PIR動作的時間
 captureTime = time.localtime()
#上次PIR動作的時間
 lastPIRfounded = time.strftime("%Y/%m/%d %H:%M:%S", captureTime)
#若是: 外出模式且已超過五分鐘準備時間 或者 自動模式且在設定的警示時間內,則執行
 if (modeOperation==1 and modeSecutiry_starttime>0 and ((time.time()-modeSecutiry_starttime)>modeSecutirt_waittime)) or (modeOperation==2 and autoSecutiryNow==1):
 logger.info("Motion Detected!")
 picIndex = time.strftime("%Y%m%d%H%M%S", captureTime)
 #確定已超過設定的PIR拍攝間隔時間
 if ((time.time()-PIR_last_pictureTime))>PIR_sleep_PictureAgainPeriod:
 #連續拍攝三張,takePicture此函式除了拍攝外,亦會執行上傳、Email、發簡訊等動作。
 for imgFile in [ "PIR-1", "PIR-2","PIR-3" ]:
 takePicture(imgFile, "PIR偵測", "PIR偵測到有人進入客廳!") 
 time.sleep(PIR_sleep_take_2_PicturesPeriod)
 #播放「已經自動報警…」的相關告示聲音以嚇阻歹徒
 playWAV("wav/warning/warning1.wav")
 #再連續拍攝三張
 for imgFile in [ "PIR-4", "PIR-5","PIR-6" ]:
 takePicture(imgFile, "PIR偵測", "PIR偵測到有人進入客廳!") 
 time.sleep(PIR_sleep_take_2_PicturesPeriod)
 #記錄上次IR的拍攝時間
 PIR_last_pictureTime = time.time()
 #LED燈關閉
 lightLED(9)
 else:
 #模式為外出模式,但尚未過五分鐘的準備時間
 if modeOperation==1:
 if ((time.time()-ENV_lastwarningtime))>ENV_warning_repeat_period:
 tmpTime = (modeSecutirt_waittime - (time.time()-modeSecutiry_starttime))/60
 logger.info("In TIME: " + str(tmpTime) )
 #提醒使用者,幾分鐘之後將開始進入外出模式。
 if tmpTime<=1:
 playWAV("wav/startIn1min.wav")
 elif tmpTime<=3 and tmpTime>1:
 playWAV("wav/startIn3min.wav")
 elif tmpTime<=5 and tmpTime>3:
 playWAV("wav/startIn5min.wav")
 elif tmpTime<=10 and tmpTime>5:
 playWAV("wav/startIn10min.wav")
 elif tmpTime<=30 and tmpTime>10:
 playWAV("wav/startIn30min.wav")
 elif tmpTime>30:
 playWAV("wav/startAfter30min.wav")

 ENV_lastwarningtime = time.time()
 lightLED(9)

回復到上次執行模式

在主程式開始之前,先從finalStatus檔案中讀取上次最終的執行模式代碼。


try:
strMode = &amp;quot;1&amp;quot;
fo = open(&amp;quot;finalStatus&amp;quot;, &amp;quot;r+&amp;quot;)
strMode = fo.read()
fo.close()
logger.info(&amp;quot;Status read from the file : &amp;quot; + strMode)
except: #若無此finalStatus檔案,則產生一個,預設內容為目前的模式
fo = open(&amp;quot;finalStatus&amp;quot;, &amp;quot;wb&amp;quot;)
fo.write(str(modeOperation))
fo.close()

#設定finalStatus的上個模式。
if strMode==&amp;quot;1&amp;quot;:
modeOperation = 0
elif strMode==&amp;quot;2&amp;quot;:
modeOperation = 1
else:
modeOperation = 2
#再透過執行btn_Security()函式來切換到finalStatus的模式。
btn_Security(pinBTN_Security)

startMain.sh 啟始程式

        startMain.sh是用來執行本系統的啟始程式,它先定義CLOUDINARY環境變數之後,再進入系統目錄執行主程式start.py,最後的幾行則是檢查start.py有無運作中,若無則代表發生了意外狀況,在60秒後自動重啟整個系統。


#!/bin/bash

export CLOUDINARY_URL=cloudinary://XXXX:XXXXXXXXXX@XXX

&amp;amp;nbsp;

cd /home/pi/monitor

python start.py

&amp;amp;nbsp;

ps -ef | grep -v grep | grep start.py

&amp;amp;nbsp;

if [ $? -eq 1 ] //EXIT status:true(成功)à0  fasse(失敗) à 1

then

sleep 60

sudo reboot

fi

後記

        我後來發現,其實系統並不需要頻繁的定時寄發回報email,只要每日甚至於每週一次,並搭配一個資訊及相片持續更新的專屬dashboard比較恰當,使用者若想看家中狀況時自然會連到dashboard看,系統頻繁的寄送通知反而會造成困擾,這類郵件或簡訊的傳送方式應該留給緊急突發的PIR或天然氣外洩等重要事件。

        此外,由於牆上的掛鐘剛好離大門口很近,因此我還另外從樹莓派接了一台Web camera放置於門口附近,並增加一個門口專用的PIR ,等於是戶內與戶外各有一組PIR與攝影機。不同於室內所執行的是靜態拍照功能,該戶外攝影機使用了motion套件執行即時影像串流功能,搭配了PIR之後,當有人在門口附近徘徊就會觸發室內掛鐘發出警告聲音,此時室內的家人便可開啟LCD螢幕查看門外狀況。比較可惜的是PIR很容易受到陽光干擾產生誤報,因此該戶外PIR功能在傍晚時分才會被自動開啟。

        所有的程式碼皆置於Github:https://github.com/ch-tseng/Homemonitor,如果您有興趣的話,可依照本文所述接好所有裝置和sensors後,下載本程式放置於/home/pi/monitor/目錄下,再將mailgun及cloudinary的API key、以及收件人email address更換為您自己的,最後直接執行 sudo startMain.sh就可以了。

廣告

發表迴響

Please log in using one of these methods to post your comment:

WordPress.com 標誌

您的留言將使用 WordPress.com 帳號。 登出 /  變更 )

Google+ photo

您的留言將使用 Google+ 帳號。 登出 /  變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 /  變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 /  變更 )

連結到 %s