謝作如
寒假期間,忙里偷閑設(shè)計(jì)了一個(gè)名叫“sfarm”的開(kāi)源智慧農(nóng)場(chǎng)方案。sfarm采用了應(yīng)用最廣泛的MQTT協(xié)議,多節(jié)點(diǎn)設(shè)備匯集到一個(gè)服務(wù)器上,不僅能自動(dòng)灌溉,還實(shí)現(xiàn)了遠(yuǎn)程控制,定時(shí)采集各種數(shù)據(jù)。方案中涉及的開(kāi)源硬件、傳感器、電磁閥和其他灌溉設(shè)備,在淘寶上都能買(mǎi)到,因而得到了很多朋友的關(guān)注。其中福州連江五中的盧老師就在學(xué)校的大花壇上部署了一套,運(yùn)行效果很好。
雖然系統(tǒng)運(yùn)行正常,但很快就產(chǎn)生了新的需求:當(dāng)有嘉賓或者學(xué)生來(lái)參觀智慧農(nóng)場(chǎng)系統(tǒng)的時(shí)候,如何快速展示這一系統(tǒng)的“物聯(lián)”功能?畢竟打開(kāi)SIoT(MQTT服務(wù)器)的Web管理頁(yè)面,再進(jìn)行演示總不夠便捷,也難以體現(xiàn)個(gè)性化。這就需要寫(xiě)一個(gè)物聯(lián)網(wǎng)應(yīng)用程序,對(duì)接入的各個(gè)節(jié)點(diǎn)設(shè)備進(jìn)行直觀的管理。當(dāng)然,我們期望這個(gè)物聯(lián)網(wǎng)應(yīng)用程序的開(kāi)發(fā)難度不能太高,最好學(xué)生也能夠開(kāi)發(fā)。這樣,智慧農(nóng)場(chǎng)就和學(xué)生的物聯(lián)網(wǎng)學(xué)習(xí)、編程學(xué)習(xí)密切結(jié)合起來(lái)了。
● 用Web方式開(kāi)發(fā)物聯(lián)網(wǎng)應(yīng)用程序的優(yōu)勢(shì)分析
物聯(lián)網(wǎng)應(yīng)用程序的開(kāi)發(fā)有很多種方式可以選擇,比較常見(jiàn)的是用VB、C#之類的語(yǔ)言來(lái)編寫(xiě),但是開(kāi)發(fā)的應(yīng)用程序要運(yùn)行在電腦上,無(wú)論是演示還是平時(shí)管理都不夠靈活。用App inventor編寫(xiě)一個(gè)手機(jī)App也是不錯(cuò)的選擇,技術(shù)門(mén)檻也低,中學(xué)生大都能參與編寫(xiě)。但美中不足的是,這個(gè)App要事先安裝,而且只能運(yùn)行在安卓手機(jī)上,不夠靈活且不具備普適性。
用類Scratch的軟件來(lái)編寫(xiě)應(yīng)用程序,也是可行的一種選擇,如Mind+(一款圖形化編程軟件)內(nèi)置了MQTT模塊,可以編寫(xiě)物聯(lián)網(wǎng)應(yīng)用程序。Mind+的門(mén)檻很低,小學(xué)生也能夠編寫(xiě)出一個(gè)非常個(gè)性化的物聯(lián)網(wǎng)應(yīng)用。但遺憾的是,Mind+的代碼不能脫離Mind+環(huán)境運(yùn)行,也不能編譯為一款獨(dú)立的軟件。
毫無(wú)疑問(wèn),最靈活的方式肯定是采用B/S架構(gòu),編寫(xiě)一個(gè)單獨(dú)的管理網(wǎng)頁(yè),即WebApp。在服務(wù)器上運(yùn)行該程序,任何手機(jī)的瀏覽器都能打開(kāi)這個(gè)特定的網(wǎng)頁(yè),看到各種采集的數(shù)據(jù),還可以通過(guò)網(wǎng)頁(yè)按鈕來(lái)控制“澆水”。這樣的應(yīng)用場(chǎng)景顯然很“智能”很“貼心”,但遺憾的是,編寫(xiě)WebApp一般需要掌握一定的網(wǎng)頁(yè)前端開(kāi)發(fā)技術(shù),而目前學(xué)生普遍缺少這方面的編程基礎(chǔ)。
● 用Python開(kāi)發(fā)WebApp
能不能用Python來(lái)編寫(xiě)WebApp?現(xiàn)在的中學(xué)信息技術(shù)教材幾乎都采用Python語(yǔ)言了,如果能夠用Python來(lái)編寫(xiě)網(wǎng)頁(yè),學(xué)生就不需要學(xué)習(xí)HTML、JS和CSS等網(wǎng)頁(yè)開(kāi)發(fā)技術(shù)。當(dāng)然,答案是肯定的,一個(gè)名叫“Remi”的Python庫(kù),就是用來(lái)開(kāi)發(fā)WebApp的。
1.Remi庫(kù)簡(jiǎn)介
Remi是一個(gè)用于Python應(yīng)用程序的GUI庫(kù),它將應(yīng)用程序的界面轉(zhuǎn)換為HTML,以便在Web瀏覽器中呈現(xiàn)。嚴(yán)格地說(shuō),我們不能用Remi庫(kù)來(lái)編寫(xiě)傳統(tǒng)的網(wǎng)站,而只將他當(dāng)成Web形式的Tkinter庫(kù)(Python最經(jīng)典的圖形界面庫(kù))來(lái)使用。如果要做網(wǎng)站,還是要老老實(shí)實(shí)學(xué)點(diǎn)前端知識(shí),然后結(jié)合Python的Flask框架來(lái)開(kāi)發(fā)。
2.Remi庫(kù)的安裝
Remi可以采用pip命令安裝,具體如下:
pip install remi
3.Remi庫(kù)的代碼示例(如圖1)
運(yùn)行這段代碼后,瀏覽器會(huì)自動(dòng)打開(kāi)一個(gè)本地的網(wǎng)址,出現(xiàn)如圖2所示的界面。將“127.0.0.1”換成IP地址,就能通過(guò)其他電腦、手機(jī)的瀏覽器來(lái)訪問(wèn)了。
點(diǎn)擊“請(qǐng)點(diǎn)擊這里”按鈕,界面會(huì)發(fā)生變化,如圖3所示。不用寫(xiě)復(fù)雜的JS代碼,在Remi的支持下,網(wǎng)頁(yè)交互就變得這么簡(jiǎn)單。
如果需要了解更多關(guān)于Remi庫(kù)的資源,可以訪問(wèn)github或者官方文檔。
github地址:https://github.com/dddomodossola/remi
文檔地址:https://remi.readthedocs.io/en/latest/
● 基于Remi編寫(xiě)基于Web的物聯(lián)網(wǎng)應(yīng)用程序
既然是編寫(xiě)物聯(lián)網(wǎng)應(yīng)用程序,那么肯定還需要安裝siot庫(kù)。這也是“虛谷物聯(lián)”團(tuán)隊(duì)開(kāi)發(fā)的Python庫(kù),因?yàn)镸QTT的官方Python庫(kù)(paho-mqtt)編寫(xiě)出來(lái)的代碼冗長(zhǎng),不好理解,于是委托上海蘑菇云團(tuán)隊(duì)在paho-mqtt的基礎(chǔ)上進(jìn)行了新的封裝。siot庫(kù)可以通過(guò)pip命令來(lái)安裝,命令如下:
pip install siot
1.物聯(lián)網(wǎng)應(yīng)用的工作流程
因?yàn)椤皊farm”每一個(gè)節(jié)點(diǎn)都有采集土壤、光線信息的功能,都具備單獨(dú)的電磁閥,用物聯(lián)網(wǎng)消息來(lái)控制。那么,這個(gè)應(yīng)用程序既需要顯示消息,又要能夠發(fā)送消息(控制指令),工作流程如圖4所示。其實(shí),絕大多數(shù)的物聯(lián)網(wǎng)應(yīng)用程序,都需要同時(shí)具備訂閱和發(fā)送消息功能。
2.核心代碼1:物聯(lián)網(wǎng)消息的訂閱
因?yàn)橐瑫r(shí)訂閱多個(gè)主題的消息,代碼中采用了“定點(diǎn)存放定時(shí)處理”的方式,即先將接收到的消息放在一個(gè)字典(topic_msg_map)中,然后定時(shí)在字典中查找是否有新消息,讀取新消息后就刪除這一消息,避免重復(fù)讀取。參考代碼如下頁(yè)圖5所示。
3.核心代碼2:物聯(lián)網(wǎng)消息的顯示
顯示消息需要不斷刷新網(wǎng)頁(yè)組件中的文字,這需要啟動(dòng)一個(gè)新的進(jìn)程來(lái)處理,然后在這個(gè)進(jìn)程中不斷循環(huán)讀取字典(topic_msg_map)中的消息。參考代碼如圖6所示。
4.核心代碼3:物聯(lián)網(wǎng)消息的發(fā)送
消息發(fā)送通過(guò)“澆水”按鈕來(lái)實(shí)現(xiàn)。參考代碼如圖7所示。
5.核心代碼4:物聯(lián)網(wǎng)設(shè)備的切換
sfarm是一個(gè)多節(jié)點(diǎn)工作的物聯(lián)網(wǎng)系統(tǒng),因而需要加上設(shè)備切換功能,比較簡(jiǎn)單的做法是用一個(gè)列表(project_list)記錄需要呈現(xiàn)的設(shè)備名稱,然后在切換時(shí)修改全局變量(id)。參考代碼如下頁(yè)圖8所示。
● 運(yùn)行效果和反饋
Python的神奇,就在于其擁有無(wú)窮無(wú)盡的“庫(kù)”,能夠用來(lái)快速解決問(wèn)題。從找到Remi庫(kù)到寫(xiě)出代碼,我僅僅花了一個(gè)晚上的時(shí)間,這種編程的感覺(jué)特別好。最終的代碼運(yùn)行效果如下頁(yè)圖9所示。
福州連江五中的盧老師將代碼運(yùn)行在sfarm系統(tǒng)的物聯(lián)網(wǎng)服務(wù)器上,然后將訪問(wèn)地址做成二維碼,用手機(jī)掃碼(手機(jī)要能夠訪問(wèn)服務(wù)器)的方式來(lái)打開(kāi)這個(gè)網(wǎng)頁(yè),效果很不錯(cuò),如下頁(yè)圖10所示。從難度上看,只要有Python編程基礎(chǔ),就能編出類似的程序。他正在將這方面的內(nèi)容開(kāi)發(fā)成一個(gè)物聯(lián)網(wǎng)課程,讓學(xué)生真正參與到sfarm的開(kāi)發(fā)和維護(hù)中。
完成了這個(gè)物聯(lián)網(wǎng)應(yīng)用后,最大的收獲并不是解決了sfarm系統(tǒng)的演示問(wèn)題,而在于找到了一種設(shè)計(jì)Python程序界面的新方法。例如,可以用Remi庫(kù)寫(xiě)一個(gè)基于Web的校園氣象站、攝像頭遠(yuǎn)程控制程序等。相對(duì)來(lái)說(shuō),用Remi庫(kù)開(kāi)發(fā)WebApp,比Flask(一個(gè)Python開(kāi)發(fā)的Web框架)要簡(jiǎn)單得多,后者需要了解大量的HTML、JS和CSS之類的知識(shí),對(duì)中學(xué)生來(lái)說(shuō)門(mén)檻略高了一些。