懶人的快遞提醒小助手


前言

歡迎小伙伴們來到第二部分,在前文中 Latest Linux Distributions on LattePanda and Kernel Customization 我們費盡周折配置好了相關環境,本文開始進入第二部分:Core Code to Track the Packages | 包裹監視追蹤項目的核心代碼

在這里我們會用到以下知識:

  1. Interaction between MPU and MCU on LattePanda with Firmata protocol | LattePanda上Linux和Arduino使用Firmata協議進行交互
  2. Python GUI Programming with remi | Python圖形化編程(使用remi)
  3. Usage of TinyDB——a lightweight database | 介紹輕量級數據庫TinyDB的使用
  4. Wechat notification via ServerChan | 使用Server醬實現微信通知功能
  5. Remote Development with Visual Studio Code | 使用VSC進行遠程開發

這一部分將實現如下功能:

  1. 網頁前端添加待監視快遞信息
  2. 查詢的所有快遞歷史記錄
  3. 自定義查詢頻率
  4. 快遞信息變動時微信通知

the Purpose of this Project | 為什么要做這個項目

可能很多小伙伴要問了,我的淘寶、京東、菜鳥裹裹也可以幫我查快遞,為啥還要弄這個哩?

  1. 隱私性。現在的信息泄露太嚴重了,不想使用第三方軟件。
  2. 合並通知。希望有一個軟件可以統一查詢大多數的
  3. 減少冗雜的程序。不希望安裝過多軟件,特別國內的一些軟件太流氓,捆綁過多無用功能
  4. 物流信息的訂閱與實時追蹤。一般的是服務端定時 push 物流信息到手機上,可能存在一定滯后性,而主動 pull 物流信息則可以更快獲得相關信息。

另外我不知道大家是怎樣,我有時候買到心儀的東西,特別盼着早點到貨,然后隔一會就去打開手機客戶端刷新一下查看快遞信息,時間久了浪費生命,所以想着用電腦幫我查,有變動主動告訴我。

Project Architecture | 項目架構

  1. 通過網頁前端或者命令行前端,錄入待查詢快遞信息到數據庫中,例如 TinyDB
  2. 讀取數據庫中的信息,利用 Requests 從互聯網上的相關網站獲取物流信息。
  3. 對獲取的物流信息進行處理、如果有變動則錄入數據庫中,同時調用微信通知接口,使用 Firmata 協議與板載 Arduino Leonardo 交互。
  4. 使用計划任務 crontab 定期獲取物流信息。
  5. 使用 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的網站

  1. kuaidi100、kuaidi、baidu—— express-plus 上述實行了嚴格的請求限制,不推薦使用

  2. 伙伴數據資源 | 推薦 加客服QQ即可以獲得密鑰,調用簡單,但是支持的快遞公司不全

  3. TrackingMore | 免費API申請,不推薦

  4. 快寶開放平台 | 可用,類似快遞鳥,需要加密

  5. 快遞鳥 | 推薦,支持快遞公司較全,但是調用麻煩點?參考 kdniao_pythonPython3 調用快遞鳥 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協議 交互

之前寫過一部分,由於相關庫更新,這里寫一下。

之前主要介紹三個兩款:

如果你需要的功能不多,用起來越簡單越好,就選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。同時通過包管理器安裝 ``

image-20200524231047375

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 也支持藍牙嗅探,但是需要專門的藍牙芯片,適用性不那么強,而且並不是所有人的手機藍牙都是一直開着的,比如我。

效果類似於這樣:

好,我們下期再見!

版本更新歷史

  1. 2020年5月26日
    • 增加核心代碼中所查詢單號尚未有物流信息的錯誤。
    • 更正 healthchecks.io 圖片鏈接,該網站目前打開特別慢


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM