前言
原創文章,轉載引用務必注明鏈接,水平有限,如有疏漏,歡迎指正。
本文使用Markdown寫成,為獲得更好的閱讀體驗和正常的鏈接、圖片顯示,請訪問我的博客原文:
http://www.cnblogs.com/sjqlwy/p/lattepanda_pyui.html
本文測試環境:LattePanda:Windows 10 x64;Arduino 1.8.2;Python 3.6 + pyFirmata;TeamViewer 12|TightVNC C&S;host:Windows 7 x64
影響飛機飛行的六大氣象因素
來自中國天氣網:http://www.weather.com.cn/science/qxbk/jt/09/392758.shtml
氣壓 | 風 |
---|---|
雲 | 能見度 |
顛簸 | 結冰 |
目前,我們可以獲取氣壓、風力、雲層、能見度等方面的數據,而四軸飛行器屬於低空飛行,並不會受顛簸、結冰影響。為此,我們設計如下:
- 通過在線天氣預報API獲取當前天氣、風力、氣壓、能見度等信息;以及次日天氣狀況並進行判斷
- 獲取傳感器數據顯示當前環境狀況(由於缺少專業傳感器,未來會連接氣象站套件、購置新傳感器、連接其他MCU獲取氣壓等數據)
- 顯示結果:
- 終端程序(CLI):Python Shell|Windows Command Prompt
- 圖形界面(GUI):圖形程序或網頁界面(Web Interface)
- 物理面板:使用LCD液晶屏、物理按鈕、LED燈等指示起飛條件狀態
獲取天氣條件(輸入)
天氣預報API
最簡便且准確的途徑就是獲取天氣預報啦,這里我們可以使用國內外諸多網站提供的服務API,可以在百度API Store查找使用各種免費收費服務。之前用過Yahoo、Weather等的API,這次無意中發現github上網友TonnyL整理的Awesome_APIs 列表,非常棒,感謝TonnyL,有可能的話大家可以去star或者捐贈。
我們選擇中央天氣預報(非官方) 這個API,首先數據准確,其次使用異常簡單。
使用方法講得很清楚,數據格式為json,如果不進行格式化,輸出結果如下:
其中\uXXXX
為JS string,雖然有很多小工具如curl、httpie配合json格式化工具可以完成解碼,但是為了后續拓展方便,我們使用Python + requests庫來實現數據獲取與處理。
獲取天氣狀況
測試環境:Python 3.6.1 for Windows;pyFirmata 1.0.3 (pyserial needed);requests 2.14.2
代碼如下:
#!/usr/bin/env python3
#-*utf-8*-
import requests
def get_weather():
# use api from https://github.com/jokermonn/-Api/blob/master/CenterWeather.md
weather = requests.get('http://tj.nineton.cn/Heart/index/all',params = 'city=CHJS070000')
return weather.json()
status = get_weather()['status']
cond = get_weather()['weather'][0]['now']
tomorrow = get_weather()['weather'][0]['future'][1]
if status == 'OK':
print("********當前天氣********")
print("當前城市:{0}\n當前天氣狀況: {1}\n溫度: {2} ℃\n風向: {3}\n風速: {4} m/s\n風力大小: {5}\n空氣濕度: {6}\n能見度: {7} km\n氣壓: {8} hPa".format(get_weather()['weather'][0]['city_name'], cond['text'], cond['temperature'], cond['wind_direction'], cond['wind_speed'], cond['wind_scale'], cond['humidity'], cond['visibility'], cond['pressure']))
print("********明日天氣********")
print("明日天氣情況:{0}\n風力大小:{1}".format(tomorrow["text"], tomorrow['wind']))
if '雨' not in tomorrow['text']:
affordable_wind = ('風力0級', '風力1級', '風力2級', '風力3級', '風力4級')
if tomorrow['wind'] in affordable_wind:
# 后續加入字體顏色
print("明日適宜飛行!")
# 綠燈亮
else:
# 后續加入字體顏色
print('明日不宜飛行!')
# 紅燈亮
else:
print('failed to fetch weather condition of XuZhou!')
執行效果如下:
注意:
- 注意Python2和Python3的語法上稍有區別,建議閱讀廖雪峰的Python教程和免費的《A Byte of Python3(中文版)》這本書。
- requests庫簡單易用,內置json格式化功能。雖然還有許多其他更輕巧的庫或者工具可以使用,但是使用優美的requests庫可以降低學習成本,並為后續網絡爬蟲等的學習打下基礎。
- 請參考該api的json返回示例,注意字典
{}
和序列[]
,《A Byte of Python3(中文版)》有專門的講解。- 這里推薦使用字符串的format()方法進行格式化輸出。
- params = 'city=CHJS070000'以我家徐州為例,具體城市代碼參考作者提供的數據庫文件
- 因為計算機都是業余愛好,所以代碼質量相當低,歡迎指正提建議。
- 當服務端 (Server)和客戶端 (Viewer)都使用TightVNC時,可以直接進行文字復制黏貼,但是我這里中文會出現亂碼,可能是兩個文件編碼不同也可能是TightVNC內置編碼問題,不過使用文件傳輸功能沒亂碼。
- 后續准備增加適宜和不適宜起飛的字體顏色,由於Windows和Linux的實現有所不同,考慮可移植性,暫時不進行功能整合。可以參考Python實現Windows CMD命令行彩色輸出和Python 命令行輸出的顏色設置 。
獲取傳感器數據與物理按鈕控制
前文LattePanda 之深入學習 Firmata通訊有所介紹,我們這里先用簡單的pyFirmata
庫進行演示模擬、數字傳感器讀寫。最終效果為:讀取光敏傳感器、溫濕度傳感器數據進行顯示(模擬、數字傳感器讀取),並且根據天氣預報情況判斷明日天氣條件是否可以起飛,如果可以,則綠色led亮5s,否則紅色led亮5s(數字寫入)。未來加入物理大黃按鈕進行控制(數字讀取)。代碼如下:
from pyfirmata import Arduino, util
from time import sleep
# 初始化串口
board = Arduino('COM5')
print("********傳感器數據********")
it = util.Iterator(board)
it.start()
board.analog[0].enable_reporting()
sleep(1) # 緩沖時間
# 待補充DHT11以及校准光敏傳感器
print("環境亮度:{0}\n環境溫度:{1}\n環境濕度:{2}\n".format(board.analog[0].read(), "N/A", "N/A"))
board.analog[0].disable_reporting()
# 綠燈亮
board.digital[9].write(1)
sleep(5)
board.digital[9].write(0)
# 紅燈亮
board.digital[10].write(1)
sleep(5)
board.digital[10].write(0)
注意:
- 請填寫正確的串口編號
- 使用第三方
StandardFirmataPlus
固件是出現問題,led點亮后無法熄滅,重新燒錄官方StandardFirmata
固件后回復正常,等待重新驗證問題。- 操作模擬端口時,建議啟動一個迭代器線程進行處理,否則開發板會持續向串口發送數據,直到串口溢出。更多例子及使用方法請參考官方
tests.py
- 開啟reporting后請延時后讀取模擬量,否則可能獲取不到傳感器數值;另外單次讀取完畢請disable,不然也會一直發送數據(Tx白色指示燈常亮)
- 后續使用pyMata-aio取代pyFirmata庫,它支持最新的firmata協議,使用異步,並且可以自動檢測Arduino串口。
- A9、A10分別接綠色、紅色LED。
【APRS氣象站套件(帶風速計、風向儀、雨量器)】
整合兩個功能,即可以得到命令行界面版控制界面完整源碼:
Graphics User Interface
前面搞定了CLI界面,基本功能實現了,但是此時的我想起來v2ex上一個段子:
原先 PM 將一個用的人少的運維管理頁面( web application ) JAVA web 給我用 Python 做,期待做成小工具。后來我想給客戶的東西總不能沒有界面吧,就用 bat 擼了一個。
客戶:握草,這界面?!還墨綠色?
我:恩,目前是這樣
客戶:這滾動的怎么像黑客一樣?!!
我:。。。
所以我們准備為地面站系統做一個圖形界面。用慣了CLI界面,對圖形界面設計編程這個新領域學習了一番,收獲頗豐,記錄如下。
計划中的地面控制站包括網頁版用戶交互界面(屏幕軟件交互)+物理控制面板(按鈕LED交互)。
Windows下的桌面軟件開發
- 快手 aardio| 國人出品,專注於桌面軟件快速開發,功能強大,永久免費,不過存在一些爭議,名詞也從AAuto改成了aardio。相關文章:快手軟件存在哪些優點和不足? 、桌面程序開發語言選擇易語言還是快手aauto 、 AAuto為何更名為aardio? 。后續有時間准備學學看。
- C#|Windows桌面程序開發非常給力,然而我沒學
- electron | Build cross platform desktop apps with JavaScript, HTML, and CSS。我不會網頁那些東西
- Qt | 跨平台,文檔眾多。Linux下的KDE桌面環境就是基於Qt做出來的,還針對嵌入式系統推出了一個Qt Lite。即使有Qt Design,然而學習成本依然高,需要花時間去學習。
- Visual Basic | 也支持Firmata協議。
因為比較熟悉Python,所以后續以它為例。在v2ex.com上搜索了一下:如果 Python 硬要寫桌面應用,該如何是好?
已有的Python GUI庫方案
- tkinter|難看,接口也難用。適合小玩意
- wxPython | 還闊以
- PyQt | 資料多,依賴復雜
- REMI | Python REMote Interface library. Platform independent. In about 100 Kbytes, perfect for your diet.
- Kivy | Open source Python library for rapid development of applicationsthat make use of innovative user interfaces, such as multi-touch apps.
- Ironpython | IronPython is an open-source implementation of the Python programming language which is tightly integrated with the .NET Framework.
- Gooey | Turn (almost) any Python command line program into a full GUI application with one line
最終我們選擇REMI庫來開發圖形界面版程序。主要看中依賴少、身材小巧、上手容易、跨平台能力強等。
Python2 與 Python3 :
因為Python2即將結束支持。使用Python的原因是因為簡單方便,庫多不用重復造輪子,跨平台,功能強大。運行效率其實已經不是最優先的考慮要求啦,畢竟不是嵌入式設備。之前也學過Visual Basic、C、Linux Shell,但是用上Python之后立即愛上了,此外也有現成優秀的庫支持Firmata協議。
REMI
既然有了那么多優秀的GUI庫,為什么還要創建一個呢,作者是這樣回答的:
Why another GUI lib?
Kivy, PyQT and PyGObject all require native code for the host operating system, which means installing or compiling large dependencies. Remi needs only a web browser to show your GUI.Kivy,PyQT,PyGobject都需要安裝編譯大量依賴才能在宿主機上原生運行,而Remi僅需要網頁瀏覽器就可以顯示GUI界面了。
Do I need to know HTML?
NO, It is not required, you have to code only in Python.僅需要會使用Python編程,而不用學習了解HTML(超文本標記語言,網頁開發語言)就可以進行開發。
私以為其他優點包括擴拓展性強,方便外網訪問等。我們可以看到REMI目前可實現的控件演示:
包括按鈕、文本框、標簽、輸入對話框、列表、圖片、表格、滑動條、顏色選擇器、日期、文件選擇對話框、菜單欄、菜單選項、視頻播放等控件。具體用法可以參考doc
和examples
文件夾里的內容。
最后推薦一個好用的Python IDE——PyCharm:
安裝與hello_DFROBOT!
REMI項目主頁:https://github.com/dddomodossola/remi
安裝方法很簡單,如上文所述:Win+R
——cmd
——python -m pip install remi
,也可以pip install remi
,注意需要管理員身份運行。另外新建的文件名不要和待加載的模塊名相同(比如remi.py),否則會提示ModuleNotFoundError: No module named remi
之類的錯誤(別問我怎么知道的。。。)。我們新建一個文件如remi_demo.py,代碼如下:
import remi.gui as gui
from remi import start, App
class Hello_DFRobot(App):
def __init__(self, *args):
super(Hello_DFRobot, self).__init__(*args)
def main(self):
container = gui.VBox(width = 120, height = 100)
self.lbl = gui.Label('DFROBOT')
self.bt = gui.Button('Press me!')
# setting the listener for the onclick event of the button
self.bt.set_on_click_listener(self.on_button_pressed)
# appending a widget to another, the first argument is a string key
container.append(self.lbl)
container.append(self.bt)
# returning the root widget
return container
# listener function
def on_button_pressed(self, widget):
self.lbl.set_text('Drive the Future!')
self.bt.set_text('Button pressed!')
# starts the webserver
start(Hello_DFRobot)
效果如圖所示:
運行后會自動打開一個網頁,點擊按鈕,按鈕和標簽文字都會改變。這里簡單講解一下,詳細的可以看官方doc文檔和examples示例。
我們下面將會結合
-
requests庫獲取天氣
-
pyFirmata庫與Arduino交互
-
remi庫作為圖形顯示
REMI editor
相信很多人都用過Visual Basic、Qt Designer這種可視化的用戶界面設計工具,而REMI也有類似的,而且是使用remi本身實現的,就在editor文件夾里,具體使用說明參考其下的README.md文件,說明比較簡略,這里詳述如下:
安裝好相關依賴庫之后,運行editor.py (我這里是用的PyCharm IDE打開運行的)。
注意:
- 某個控件的響應可以在左下角signal connections里面設置。
- 雖然Web界面具有極大的跨平台優勢,但是由於存在諸多瀏覽器、平台、屏幕大小分辨率,仍有可能設計出的界面在其他上面顯示不全,所以仍要了解一些基本HTML常識
- ☆網頁制作的層絕對定位和相對定位:一般選中主widget,右下角最后設置
position
為absolute
絕對定位(相對於瀏覽器左上角),其他widget中的控件設置為relative
相對定位,然后在Geometry
里設置坐標。- 菜單欄
Project Config
可以設置項目的一些基本屬性(支持中文項目名稱),設計完畢后,點擊File
->Save YourApp
->Save As
即可保存界面代碼,並在隨后的程序中使用。
GUI 來了!
然后GUI又走了!表示這太丑了,自己也看不下去。。。遂棄用。決定回頭仔細看看文檔再重新來過。