1. 程式人生 > >樹梅派應用18:用樹莓派DIY一個智慧家居伺服器

樹梅派應用18:用樹莓派DIY一個智慧家居伺服器

其實這東西我自己已經用了一年了~現在就來寫個教程~嘿嘿……
先上個圖
20160626192247896-0
有點亂23333
這是我的房間書櫃,也是我的工作臺……書櫃的側邊是樹莓派搭建的物聯網伺服器~
來一隻近圖~
20160626192247673-0
這就是伺服器的近照啦~
我用的是樹莓派A+作為伺服器的主控,所有的工作都由它完成。
樹莓派A+是單核的處理器,RAM僅256MB,不過如果不是作為複雜工作的話……也足夠了~
這裡,它的主要工作就是收集房間和室外的環境資料並上傳至yeellink,同時獲取yeellink上的開關資料控制房間裡的燈,門,音響等裝置的開關。
以及,在晚上下晚修我回到家的時候,自動開啟燈~睡著了後自動關燈~

先來簡單介紹一下,這裡需要用到一些什麼東西。如上面那張圖,樹莓派是肯定要有的~當然,什麼版本都可以……因為實際上這裡也沒用多少GPIO,以前的A,B版本都可以……
然後,樹莓派左下角那個藍色的是音效卡和音響的整合驅動,用來推動喇叭的~使用5V的電源,當然大家可以直接找個小音箱來代替~~
然後下面那一堆線是麵包板,用來分配電源和繼電器控制,以及……比較方便接線吧23333.各種感測器可以直接插麵包板上,這樣就省去了焊線的麻煩。
另外,由於我用的是樹莓派A+,沒有網路介面,所以用了一個8口的帶電源HUB連線無線網絡卡和其他的比如USB串列埠等裝置。HUB貼在樹莓派上面點,沒拍到。
再下面是電源盒,這裡我用的是桌上型電腦電腦的電源~為什麼用桌上型電腦電源呢?這有很大的好處。
桌上型電腦電源有12V,5V和3.3V,並帶有一路5V VSB電源,以及還可以用GPIO控制電源整體開關。這就非常適合用來做伺服器了,因為我的LED燈條是12V的,電磁鎖也是12V的,而樹莓派和USB裝置都需要5V,一些感測器則需要3.3V,正好一個電源全部搞定它。同時在一些需要耗電的東西不需要用的時候,比如LED燈條,那我還可以把整個電源系統關掉省電~而在關掉總電源的時候,5V VSB是一直保持輸出的,就可以用這一路電源給樹莓派持續供電~ 是不是覺得很方便?

簡單介紹完整個系統了,來看看接線
20160626192247323-0
這是整個系統的接線圖~麵包板左邊那一坨就是桌上型電腦電源的ATX介面。
最下面的電機是電磁鎖。
音響接的是驅動板。
以及這裡用了個arduino mini,這是後來加上的,用來進行AD轉換一些感測器資料然後通過串列埠發給樹莓派。
下面那些繼電器我用洞洞板製作成了一個模組,方便接線用。
20160626192247488-0

20160626192247208-0
正面和背面。和我最終做出來的成品稍微有點點出入,因為我在製作時根據實際優化了一下佈局。但是大致電路是沒什麼變化的,大家可以參考製作。
這個繼電器模組主要是用來控制12V裝置的, 比如開啟LED燈條,開鎖等,都是用樹莓派GPIO驅動三極體讓繼電器吸合導通12V的電源讓裝置工作。
這裡我要特別強調!繼電器和電磁鎖都為磁感裝置,在吸合和釋放時因為磁生電效應會產生很強的反向電動勢,這個電動勢如果不採取措施很容易造成三極體甚至樹莓派軟擊穿!導致樹莓派停止工作甚至損壞!所以在每個繼電器和電磁鎖的線圈兩端我都接有一個反向安裝的二極體,用來吸收線圈在釋放時產生的反向電動勢,以保護裝置。

好了~硬體大概就介紹到這。剩下的是軟體……
先是介紹一下,通過yeellink控制LED燈和門鎖等裝置的控制方案,這個程式還包含了指定時間內檢測我是否在家,比如在晚上,如果我回來了則自動開燈。這個是通過ping我手機的IP地址是否有迴應來完成判斷的。畢竟……出門肯定帶手機吧……所以,當ping手機不通的時候,說明我不在家了,就關掉房間裡的裝置省電。當我回到家時,手機自動連線wifi後,ping通,說明我回來了,然後自動開啟燈~

這一切都是通過bash指令碼寫的~

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 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 #!/bin/bash ##2015年9月29日 23:32:22 echo "##VI  2016年4月8日 22:56:12  ## V2.2" TDIR=/tmp mkdir -p $TDIR export PATH=$PATH:/usr/local/bin gpio -g write 21 1 gpio -g mode 21 out ##電源開關  拉低開 gpio -g write 26 1 gpio -g mode 26 out ##桌面燈條  拉低開 gpio -g write 19 1 gpio -g mode 19 out ##桌面燈條  拉低開 gpio -g write 13 1 gpio -g mode 13 out ##櫃子鎖   拉低開 gpio -g write 6 1 gpio -g mode 6 out  ##門鎖        拉低開 FI35=0 CLE_TIME=0  ##檢測計數器 ##你API的裝置號 DEV= ##你感測器的編號 SW_POWER= SW_DSKLED= SW_DOOR= SW_FORCER= SW_CHANGE= getdev(){ DEVS=$1 wget http://api.yeelink.net/v1.0/device/${DEV}/sensor/${DEVS}/datapoints -O $TDIR/sa${DEVS} -T 5 &> /dev/null FTIME=`cat $TDIR/sa${DEVS} | sed 's/.*\"\:\"//g;s/\"\,\".*$//g'` FYMD=`echo $FTIME | sed 's/T.*$//g'` FHMS=`echo $FTIME | sed 's/^.*T//g'` VAL=`cat $TDIR/sa${DEVS} | sed 's/^.*value\"\://g;s/\}//g'` if [ ! -e $TDIR/savetime${DEVS} ];then echo "" > $TDIR/savetime${DEVS} if [ "$DEVS" == "$SW_POWER" ];then if [ "$VAL" == "1" ];then gpio -g write 21 0 else gpio -g write 21 1 fi fi if [ "$DEVS" == "$SW_DSKLED" ];then if [ "$VAL" == "1" ];then gpio -g write 19 0 else gpio -g write 19 1 fi fi fi echo -e "\e[31;1m$FTIME \e[34;1m# $FYMD ## $FHMS\e[32;1m $DEVS \e[33;1m $VAL\e[0m" if [ "$FYMD" == "`date +%Y-%m-%d`" ];then echo ##操作日期為當天才進行下面的操作 if [ "$FHMS" != "`cat $TDIR/savetime${DEVS}`" ];then echo ##操作時間不和上次的記錄相同才進行下面的操作 if [ "`echo $FHMS | awk -F ':' '{printf $1}'`" == "`date +%H`" ];then A=`echo $FHMS | awk -F ':' '{printf $1}'` echo -e "\e[31;1m$A\e[0m" ##if [ "$VAL" == "1" ];then if [ "$DEVS" == "$SW_DOOR" ];then   #門鎖 gpio -g write 6 0 sleep 2 gpio -g write 6 1 elif [ "$DEVS" == "$SW_FORCER" ];then   #櫃子鎖 gpio -g write 13 0 sleep 2 gpio -g write 13 1 elif [ "$DEVS" == "$SW_POWER" ];then    #電源開關 if [ "$VAL" == "1" ];then gpio -g write 21 0 else gpio -g write 21 1 fi elif [ "$DEVS" == "$SW_DSKLED" ];then   #桌面燈條 if [ "$VAL" == "1" ];then gpio -g write 19 0 else gpio -g write 19 1 fi elif [ "$DEVS" == "$SW_CHANGE" ];then   #充電座 if [ "$VAL" == "1" ];then gpio -g write 26 0 else gpio -g write 26 1 fi fi echo "$FHMS" > $TDIR/savetime${DEVS} ##fi fi fi fi } ##給LED點陣模組傳送時間資料 ledtime(){ if [ -e /dev/ttyUSB0 ];then echo "\`wr`date +%H%M`" | microcom -p /dev/ttyUSB0 -s 115200 fi } ##先初始化鎖和充電開關 getdev $SW_DOOR getdev $SW_FORCER getdev $SW_CHANGE getdev $SW_DSKLED while : do getdev $SW_POWER getdev $SW_DSKLED getdev $SW_DOOR getdev $SW_FORCER getdev $SW_CHANGE if [ "`date +%H%M`" -ge "1900" ];then   ##時間在下午5點20後 if [ "$FI35" == "0" ];then  ##是否查詢過裝置233)0否不線上 1是線上 if [ "`ping 192.168.1.233 -c 1 -S 1 &> /dev/null;echo $?`" == "0" ];then ##查詢手機是否線上 gpio -g write 21 0 gpio -g write 19 0 FI35=1 fi elif [ "`date +%H%M`" -ge "1905" ];then ##如果手機不線上則判斷時間是否在晚上7點以後 if [ "$CLE_TIME" -le "5" ];then ((CLE_TIME++)) echo "CLE_TIME $CLE_TIME" else CLE_TIME=0 if [ "`ping 192.168.1.233 -c 1 -S 1 &> /dev/null;echo $?`" == "1" ];then ##如果不線上則清除標記 if [ "$CLOSE_LED" == "0" ];then CLOSE_LED=1 else CLOSE_LED=0 gpio -g write 21 1  ##關燈關電源 gpio -g write 19 1 FI35=0 fi fi fi fi elif [ "`date +%H%M`" -le "0230" ];then ##時間是否在凌晨2點半以內 if [ "$FI35" == "0" ];then  ##如果是,則判斷手機是否線上 if [ "`ping 192.168.1.233 -c 1 -S 1 &> /dev/null;echo $?`" == "0" ];then ##如果手機線上則開燈 gpio -g write 21 0 gpio -g write 19 0 FI35=1 fi fi elif [ "$FI35" != "0" ];then    ##否則關燈 FI35=0 gpio -g write 19 1 gpio -g write 21 1 fi sleep 1 ledtime gpio -g write 6 1 done

然後,是資料上傳的程式。通過檢測環境資料然後上傳到yeellink上,然後yeellink可以自動記錄並繪製圖表,可以很直觀的看到最近的氣象溫度變化以及樹莓派的狀態。
20160626192247985-0
額……好像光敏感測器有點問題……不管啦…然後可能由於室外18B20被太陽直接照射的原因……最近溫度一直很高……
然後晚上的溫度還是比較正常的……(廣西真的好熱!)
20160626192247377-0

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 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 #!/bin/bash ##連線物聯網傳送CPU溫度 ##BY PokeBox ##創建於:2014年9月27日 ##最後修改:2014年9月30日 02:04:38 echo "  ##Start YeeLink_Temp......" APIKEY=''   ##APIKEY TMPDIR=/tmp/my      ##臨時資料目錄 TTYFIFO=/run/ttyAMA0.fifo   ##/tmp/ttyAMA0.fifo sudo modprobe w1-gpio sudo modprobe w1-therm gettime(){ YY=`date +%Y`;MO=`date +%m`;DD=`date +%d` HH=`date +%H`;MM=`date +%M`;SS=`date +%S` } getCPUMHZ(){ deviceid=你的裝置號 sensorid=你的感測器號 VAL=`cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq | awk '{print $1/1000}'` echo -e "\e[36;1mCPU_MHz : ${VAL}\e[0m" } getCPUdata(){       ##獲取CPU資料 deviceid=你的裝置號                  ##裝置號 sensorid=                   ##感測器號 VAL=`cat /sys/class/thermal/thermal_zone0/temp | awk '{print $1/1000}'` } getCPULoad(){       ##獲取CPU使用率 deviceid=你的裝置號 sensorid= VAL=$(top -b -n 2 | grep ^%Cpu | sed -n "2p" | sed -e 's/^.*://g;s/..,//g;s/st//g' | awk '{print "scale=1; 100-" $4 }' | bc) echo -e "\e[36;1mCPU_USER : ${VAL}\e[0m" } ## 刪除資料點 http://api.yeelink.net/v1.0/device/你的裝置號/sensor/感測器號/datapoint/時間點 getbdata(){     ##獲取18b20溫度資料室內 deviceid=你的裝置號                  ##裝置號 sensorid=                   ##感測器號 VAL=`cat /sys/bus/w1/devices/28-000005823549/w1_slave | grep 't=' | sed 's/^.*t=//g' | awk '{print $1/1000}'` echo -e "\e[36;1m18B20_IN : ${VAL}\e[0m" } getboutdata(){      ##獲取18b20溫度資料室外 deviceid=你的裝置號                  ##裝置號 sensorid=                   ##感測器號 VAL=`cat /sys/bus/w1/devices/28-00000581ea9e/w1_slave | grep 't=' | sed 's/^.*t=//g' | awk '{print $1/1000}'` echo -e "\e[36;1m18B20_Out : ${VAL}\e[0m" } GetPowerTempData(){ sensorid= VAL=`cat /sys/bus/w1/devices/28-031604d2d0ff/w1_slave | grep 't=' | sed 's/^.*t=//g' | awk '{print $1/1000}'` echo -e "\e[36;1m18B20_Power : ${VAL}\e[0m" } getlight(){ sensorid= VALa=`tac ${TTYFIFO} | grep -a 'AD0' | sed -n '2p' | awk '{print $3}' | sed 's/\r//'` VAL=`echo "1024 - ${VALa}" | bc` echo -e  "\e[36;1mLux : ${VAL}\e[0m" } senddata(){     ##傳送資料 gettime echo "{ \"timestamp\":\"${YY}-${MO}-${DD}T${HH}:${MM}:${SS}\", \"value\":${VAL} }" > $TMPDIR/datafile.txt URL="http://api.yeelink.net/v1.0/device/${deviceid}/sensor/${sensorid}/datapoints"  ##物聯網地址 curl --request POST --header "U-ApiKey: ${APIKEY}" --data-binary @$TMPDIR/datafile.txt ${URL} } oraynewph status & while : do getCPUMHZ;senddata  ##CPU頻率 getCPUdata;senddata ##CPU溫度 getCPULoad;senddata ##CPU使用率 getlight; senddata  ##室外亮度 getbdata TMPVAL=$(echo ${VAL%.*}) if [ "$TMPVAL" -le "0" ];then echo 1 &> /dev/null else senddata    ##室內溫度 fi getboutdata TMPVAL=$(echo ${VAL%.*}) if [ "$TMPVAL" -le "0" ];then echo 1 &> /dev/null else senddata    ##室外溫度 fi GetPowerTempData TMPVAL=$(echo ${VAL%.*}) if [ "$TMPVAL" -le "0" ];then echo 1 &> /dev/null else senddata        ##電源溫度 fi sleep 2m    ##間隔2分鐘傳送一次 done

上面是傳送感測器資料到yeellink的bash程式碼,大家如果需要的話……自己去yeellink註冊然後建立裝置和感測器,然後把你的APIKEY和裝置感測器號填到那些對應的變數上就可以用了……然後,上面那三個18B20的裝置號是我的18B20的裝置號,每一個18B20都有唯一的裝置號,大家自己去修改。

除此之外,大家還可以通過樹莓派上的crontab來建立任務,比如在指定時間開啟音響播放音樂來做鬧鐘~
20160626192247312-0
20160626192247665-0
這是我用飲料罐自己DIY的音響,配合那個驅動板使用,這樣的低音炮,媽媽再也不用擔心我起不來床了~

然後,仔細看的話,大家也許發現第一段程式碼裡有一條傳送時間給LED點陣的函式,是的,那個函式是用來驅動這貨的……
20160626192247526-0
因為我房間裡沒有鍾,甚至……我家裡都沒有鍾!所以就自己DIY吧……下面是其他時間段的效果
20160626192247301-0
20160626205550888-0