前言
歡迎小伙伴們來到第二部分,在前文中 Latest Linux Distributions on LattePanda and Kernel Customization 我們費盡周折配置好了相關環境,本文開始進入第二部分:Core Code to Track the Packages | 包裹監視追蹤項目的核心代碼。
在這里我們會用到以下知識:
- Interaction between MPU and MCU on LattePanda with Firmata protocol | LattePanda上Linux和Arduino使用Firmata協議進行交互
- Python GUI Programming with remi | Python圖形化編程(使用remi)
- Usage of TinyDB——a lightweight database | 介紹輕量級數據庫TinyDB的使用
- Wechat notification via ServerChan | 使用Server醬實現微信通知功能
- Remote Development with Visual Studio Code | 使用VSC進行遠程開發
這一部分將實現如下功能:
- 網頁前端添加待監視快遞信息
- 查詢的所有快遞歷史記錄
- 自定義查詢頻率
- 快遞信息變動時微信通知
the Purpose of this Project | 為什么要做這個項目
可能很多小伙伴要問了,我的淘寶、京東、菜鳥裹裹也可以幫我查快遞,為啥還要弄這個哩?
- 隱私性。現在的信息泄露太嚴重了,不想使用第三方軟件。
- 合並通知。希望有一個軟件可以統一查詢大多數的
- 減少冗雜的程序。不希望安裝過多軟件,特別國內的一些軟件太流氓,捆綁過多無用功能
- 物流信息的訂閱與實時追蹤。一般的是服務端定時 push 物流信息到手機上,可能存在一定滯后性,而主動 pull 物流信息則可以更快獲得相關信息。
另外我不知道大家是怎樣,我有時候買到心儀的東西,特別盼着早點到貨,然后隔一會就去打開手機客戶端刷新一下查看快遞信息,時間久了浪費生命,所以想着用電腦幫我查,有變動主動告訴我。
Project Architecture | 項目架構
- 通過網頁前端或者命令行前端,錄入待查詢快遞信息到數據庫中,例如
TinyDB
。 - 讀取數據庫中的信息,利用
Requests
從互聯網上的相關網站獲取物流信息。 - 對獲取的物流信息進行處理、如果有變動則錄入數據庫中,同時調用微信通知接口,使用 Firmata 協議與板載 Arduino Leonardo 交互。
- 使用計划任務
crontab
定期獲取物流信息。 - 使用 Kismet 進行網絡嗅探,判斷目標設備是否在附近,是的話就啟用額外的通知手段。否則只微信通知和在網頁面板上顯示。
注意: Kismet 網絡嗅探將在第三部分中詳述。
配置VSC遠程開發環境
參考 Visual Studio Code remote_ssh 即可。官方提供的工具,非常簡單方便。
- 注意一些拓展需要在 Server 上重新安裝一遍,
- 支持密鑰和賬號密碼登陸,連接遠程服務器時每次都要輸入密碼,不會保存。建議使用密鑰登陸
- Windows 需要ssh-client,我的 Windows_10_1909 默認安裝了,沒有的在應用-可選里面安裝 OpenSSH-Client ,使用 ssh 登陸后會自動配置 server 。
安裝常用庫
- TinyDB 簡單輕量的數據庫,除了官方文檔,也可以看看 王大桃zzZ 的系列分享
- Requests | 優雅好用的 Python HTTP 庫,an elegant and simple HTTP library for Python, built for human beings.
提供物流信息查詢服務API的網站
-
kuaidi100、kuaidi、baidu—— express-plus 上述實行了嚴格的請求限制,不推薦使用
-
伙伴數據資源 | 推薦 加客服QQ即可以獲得密鑰,調用簡單,但是支持的快遞公司不全
-
TrackingMore | 免費API申請,不推薦
-
快寶開放平台 | 可用,類似快遞鳥,需要加密
-
快遞鳥 | 推薦,支持快遞公司較全,但是調用麻煩點?參考 kdniao_python 及 Python3 調用快遞鳥 Api 查快遞
這里我使用的是伙伴數據資源提供的API,首頁可以看到支持的快遞公司列表。
核心代碼(后端)
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
__author__ = 'Code_Paintium'
import requests, time, sys
from tinydb import TinyDB, Query
db = TinyDB("/home/sjqlwy/Projects/kd/db.json")
parcel = Query()
# 填入自己的授權密鑰,http://www.kdpt.net/express_api.html
# 支持快遞公司列表 http://www.kdpt.net/index.html#companies
id = 'YOURIDKEY'
# 增加數據記錄
def AddItem(name, com, postid):
if db.search(parcel.postid == postid) == []:
db.insert({'name': str(name), 'com': str(com), 'postid': str(postid), 'Fstatus': {}, 'Cstatus': {}, 'state': ''})
# 微信提醒
def fqtt(desp):
payload_ftqq = {'text': name, 'desp': str(desp)}
requests.get('https://sc.ftqq.com/YOURKEY.send', params=payload_ftqq)
# 檢查快遞狀態
def check_status(com, postid, name, Cstatus):
payload_status = {'id': id, 'com': com, 'nu': postid}
r = requests.get('http://q.kdpt.net/api', params=payload_status).json()
if Cstatus != r['data'][0]:
Cstatus = r['data'][0]
desp = Cstatus['time'], Cstatus['context']
fqtt(desp)
db.update({'Cstatus': Cstatus, 'Fstatus': r['data'], 'state': r['state']}, parcel.postid == postid)
# Main,當沒有輸入參數時檢查已有數據;正確輸入參數時創建條目;錯誤輸入時提示
if len(sys.argv) == 4:
AddItem(sys.argv[1], sys.argv[2], sys.argv[3])
elif len(sys.argv) == 1:
pass
else:
print("INVAIND INPUT! Please input name, companny, postid and try again.")
print("e.g., python3 kd.py Gaoda zhongtong zt1124991")
exit
# 僅檢查未簽收的項目,注意調用時間不小於1s
for item in db.search(parcel.state != '3'):
com = item['com']
postid = item['postid']
name = item['name']
Cstatus = item['Cstatus']
# print(Cstatus)
try:
check_status(com, postid, name, Cstatus)
except IndexError:
print("Delivery infomation not found yet! Please try again later.")
else:
time.sleep(2)
代碼邏輯:
因為整體代碼比較簡單,所以就不用面向對象代碼了。
AddItem()
向表中寫入數據,該表中包括以下內容:- 物品名稱 name
- 快遞公司 com
- 快遞單號 str
- 物流全程信息 Fstatus
- 最新物流信息 Cstatus
- 是否已簽收 state
fqtt()
用來實現微信提醒功能,借助簡單好用的 Server醬 的服務check_status()
獲取快遞的最新物流信息,通過 伙伴數據資源 提供的API,可以聯系QQ獲取KEY- 首先分析獲取的數據,將最新的物流狀態與已保存對比
- 有變化的話更新數據庫內容
- 運行程序時如果沒有參數,則循環查詢各個快遞狀態,有完整參數時添加新的快遞以便追蹤,參數不對時報錯
- 循環查詢時,采用
db.search(parcel.state != '3')
來排除已經簽收的 - 發現僅有單號但未有物流信息時,r['data'] 為 [] ,此時會 r['data'][0] 報錯
IndexError: list index out of range
。
如何使用
- 你需要去 Server醬 注冊登錄賬號,獲取自己的 SCKEY ,然后綁定微信即可
- 去伙伴數據聯系客服 QQ 免費獲取自己的 IDKEY
- 設置數據庫存儲路徑,建議使用絕對路徑,我的是
/home/sjqlwy/Projects/kd/db.json
效果展示:
# 首次需要輸入參數以向數據庫中添加相關信息,為物品名稱(自定義)、快遞公司(可以選auto來自動識別,如果獲取信息錯誤可以移步伙伴數據獲取名稱,如shentong)、快遞單號。
python3 kd.py FS-T6 auto 773037873703622
# 錄入信息后,后續查詢不帶參數運行則會遍歷數據庫中所有未簽收的快遞
python3 kd.py
定期執行
這里想到最省資源最方便的就是系統自帶的計划任務,定時每 1h 無參數運行 kd.py
即可。
crontab -l
crontab -e
0 */1 * * * /usr/bin/python3 /home/sjqlwy/Projects/kd/kd.py
2 */1 * * * /usr/bin/curl -l https://hc-ping.com/6ebdfd32-1fd5-4ecf-******* # use your own
同時添加計划任務提醒,這里借助 healthchecks 。填寫任務名稱,備注等,然后設置時間和之前的差不多,執行的命令為向下述網址發送一個 http 請求,建議用 curl -l URL
, 最省事。
關於 crontab 的使用參考 之前的文章 ,直接 crontab -e 編輯即可,不需要重啟服務,現在都是 systemd 接管。記得設置好時區,參考 System time 。
網頁前端 [TBD]
相信了解我的小伙伴知道我之前在 LattePanda 項目之 P2.2 起飛條件檢測系統(CLI & GUI) 一文中介紹過 remi, Remi is a GUI library for Python applications that gets rendered in web browsers。
該前端實現的功能就是增加欲追蹤包裹數據,發給后端。remi帶了一個圖形化編輯器,支持拖拽。[TBD]
使用 Firmata協議 交互
之前寫過一部分,由於相關庫更新,這里寫一下。
之前主要介紹三個兩款:
- PyMata 和 PyMata-AIO,目前已更新為 pymata-express 和 pymata4, 支持 FirmataExpress 。
- pyFirmata | 僅支持到 Firmata 2.1和 StandardaFirmata
如果你需要的功能不多,用起來越簡單越好,就選pyFirmata。如果你有一些高級功能的應用需求,就選上面的兩個,同時提供了增強版的FirmataExpress sketch, 相比Arduino IDE 自帶的 StandardFirmata 它提供了如下特性:
- HC-SR04 Ultrasonic Distance Sensors using a single pin.
- DHT Humidity/Temperature Sensors.
- Stepper Motors.
- Piezo Tone Generation.
- Baud rate of 115200
更新Arduino IDE
之前用的 sudo apt install arduino
進行安裝的,打開感覺不太對,一股子歷史感。一看還是超級老的版本,懷疑根本沒人維護源里面的這個軟件包,果斷官網下載最新的 arduino ide 1.8.12
。同時通過包管理器安裝 ``
from pyfirmata import Arduino, util
board = Arduino('/dev/ttyACM0')
board.digital[13].write(1)
剩下的就簡單了,創建一個函數 ArduCom()
, 想干啥干啥了。
Additional Functions | 額外功能
熱敏打印機
今天看了葛老師的帖子,想着也可以用那個標簽打印機打印出來,后續會更新。
網頁面板
類似 Home Assistant 那種
下期預告
想要實現一個功能,就是如果探測到人在旁邊,就激活額外的提醒功能,例如語音播報等。難點就是如何知道人在旁邊,發現的一個思路就是使用 Kismet 這個軟件進行無線嗅探。
一般情況下,我們的設備是如何連接到已經保存的無線網的呢?原理大致是設備一直向空中發送數據包,詢問名為 XXX0 的無線網絡在嗎,如果無應答,就繼續詢問 XXX1 在嗎?而如果相應的無線網絡存在,就會回復我在,可以連接。
題外話: 這也就是網絡欺騙的原理之一,設備詢問有沒有 XXX0 的時候,按規矩如果你不是 XXX0 的話,就不要吱聲,而誘騙設備則會告訴設備我就是 XXX0 ,然后接收設備提供的密碼進行連接,繼而實現 mitm 中間人攻擊。
那我們實現無線追蹤的方法就是記錄設備的 mac 地址,聽到該設備在吆喝,就知道人在旁邊。因為需要一個支持 monitor 模式的無線網卡,所以我們要額外通過有線網或者第二塊無線網卡以供連接。因為板載的無線網卡雖然支持 monitor/station/client 模式的,但是 iw list
不支持同時運行2個以上模式。當然 Kismet 也支持藍牙嗅探,但是需要專門的藍牙芯片,適用性不那么強,而且並不是所有人的手機藍牙都是一直開着的,比如我。
效果類似於這樣:
好,我們下期再見!
版本更新歷史
- 2020年5月26日
- 增加核心代碼中所查詢單號尚未有物流信息的錯誤。
- 更正 healthchecks.io 圖片鏈接,該網站目前打開特別慢