2018年5月23日 星期三

利用網頁控制樹莓派(Raspberry Pi)運作

這算是很多人應用過的項目了
最近重碰Python也想到之前看過用Python的RPI.GPIO用網頁控制
就順便試著實作看看了

其實也很簡單,先把Python程式寫出來,程式碼如下:
#!/usr/bin/python3
"""上面這行不是單純註解,是讓CGI執行用的,不能忘了加"""
import sys
import cgi
import time
form = cgi.FieldStorage()

print("Content-type: text/html\n\n")
print("Hi, Python.
")
print("\n")
print(form["weblink"].value)

就把用chmod把python程式改成可執行
然後丟到CGI相關資料夾,通常是cgi-bin底下
接著就開瀏覽器去執行
結束!很簡單
所以這篇的重點不是說這個 XD

當完成上面的範例後,接著遇到的就是
如果要長時間的執行,那就必須要等待CGI程式跑完,不能關網頁
→那麼想辦法讓程式可以背景執行
→已經執行期間,給不了參數
→讓程式可以讀到網頁給的參數,甚至進行交握
→可以進行交握,可是正在運算時還是無法接受新的命令
→想辦法進行多執行緒化,讓程式可以平行作業
看來都可以解決,問題是…
怎麼做?


首先,背景執行的話
python的話,有查到可以這樣做
import os

os.system("batch <<< '/home/some_user/do_the_due.py'")
# or if you don't want to wait for system idle, 
#   os.system("at now <<< '/home/some_user/do_the_due.py'")

print 'Content-type: text/html\n'
print 'Done!'
直接call另一個py來執行
看來很簡單,不過失敗
失敗的原因三個:
一個是沒有安裝at在樹莓派裡,執行sudo apt-get install at就解決了
第二個則是os.system裡跑的是sh,而不是bash介面,所以不支援<<<的指令
會出現sh: 1: Syntax error: redirection unexpected的異常
解決辦法是,先把要執行的項目放在變數中,然後執行/bin/bash -c $變數
像這樣os.system('GREPDB="at now <<< /home/pi/ehc/client.py"; /bin/bash -c "$GREPDB"')
這樣用python下去跑是OK的,
不過最終還是失敗,因為從web側執行沒有效果,不會額外執行at指令
再查一下apache的Log看到了, You do not have permission to use at.
上網查at的權限處理,然後把/etc/at.deny裡對www-data的限制拿掉
成功了,可以執行外部的python了
可是用這個方法有個缺點,我無法對於一連串的輸入做掌控
例如,我要用樹莓做搖控車。下了往東走10秒的指令後。
我又再下了往西走15秒的指令。
因為兩邊可能各自執行,就會互衝。
所以最終放棄從web側執行,php的system函數也就沒有試了
改成先在樹莓派執行一個背景服務
然後想辦法跟它溝通。

溝通的方式呢?最簡單就是用檔案
由網頁側產生個文字檔,然後給背景程式讀取
或是利用資料庫來溝通也行
背景執行完成後,更新目前的狀態
再去查檔案或資料庫有沒有新的東西,繼續執行
兩種其實大同小異,不過還是想用新的辦法處理
因為命令的處理上,用檔案或資料庫都沒有那種即時性與反應性。
簡單地說,文字檔上的命令要消除要怎麼處理?
所以還是靠著可以交握(Handshaking)的方式來處理比較完整

那網頁目前有辦法做到即時性的交握就是這個websocket了。
而目前Javascript也有支援websocket的功能
想著想著,要不然用這個看看
結果我不會用websocket…
不,嚴格來說,是懶得再架個websocket的伺服器
架完如果還要靠apache來當通道的話,還要設定一堆東西
想想就蠻煩的,那找別的替代品吧

最後想到,不然只靠傳統socket來處理好了
由伺服器這邊對localhost發socket
這樣資料雖然沒有加密性,至少不會在網際網路中傳播
本來是想要用python cgi發socket啦,不過被Apache擋了。
只有用php跑是正常的,所以最終是改用php發socket,然後python背景程式接受。

寫到這裡問題是處理了一大半,不過遇到了最終的問題
當程式接受到命令正全力運轉時
此時再發任何命令,都不會再接受了
也就是假設我用網頁對樹莓派做的掃地機下了打掃命令
然後中途想停止,想知道掃了多久,都沒有辦法
怎麼辦?python想平行工作的話,就要靠多執行緒了

所以就開始研究怎麼寫執行緖的程式
開始爬聊聊Python中的多進程和多線程這個香港網站
寫的很詳細,不過一些用語看不懂
就併著[筆記] python3 多執行緒與多核心平行計算這一篇來看
終於理解了multi thread與multi process的用法
然後寫出自己要的東西了

雖然最後的成品有點陽春
算是別有收穫吧
詳細應用multi thread與multi process的部分
再寫下去就篇幅太長
這個就下次再說啦

沒有留言: