查看: 570|回复: 11

#创意# 懒人的快递提醒小助手 Part 2

[复制链接]
本帖最后由 pATAq 于 2020-5-26 09:36 编辑

前言

欢迎小伙伴们来到第二部分,在前文中 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 | 项目架构

202005259097..png

  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 。

202005251828..png

安装常用库

  • 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! pls 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

202005252643..png

如何使用

  • 你需要去 Server酱 注册登录账号,获取自己的 SCKEY ,然后绑定微信即可
  • 去伙伴数据联系客服 QQ 免费获取自己的 IDKEY
  • 设置数据库存储路径,建议使用绝对路径,我的是/home/sjqlwy/Projects/kd/db.json

效果展示:

# 首次需要输入参数以向数据库中添加相关信息,为物品名称(自定义)、快递公司(可以选auto来自动识别,如果获取信息错误可以移步伙伴数据获取名称,如shentong)、快递单号。
python3 kd.py FS-T6 auto 773037873703622
# 录入信息后,后续查询不带参数运行则会遍历数据库中所有未签收的快递
python3 kd.py

202005255676..png

定期执行

这里想到最省资源最方便的就是系统自带的计划任务,定时每 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。

202005254398..png

该前端实现的功能就是增加欲追踪包裹数据,发给后端。remi带了一个图形化编辑器,支持拖拽。[TBD] 202005251281..png

使用 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。同时通过包管理器安装 ``

202005251814..png

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 也支持蓝牙嗅探,但是需要专门的蓝牙芯片,适用性不那么强,而且并不是所有人的手机蓝牙都是一直开着的,比如我。

效果类似于这样:

202005258134..png

好,我们下期再见!  ## 版本更新历史

  1. 2020年5月26日
    • 增加核心代码中所查询单号尚未有物流信息的错误。
    • 更正 healthchecks.io 图片链接,该网站目前打开特别慢  



珠韵  中级技师

发表于 2020-5-25 09:26:02

这太厉害了,慢慢看,慢慢消化学习
回复

使用道具 举报

gray6666  初级技神

发表于 2020-5-26 07:44:43

涨知识,学习了
回复

使用道具 举报

rzegkly  版主

发表于 2020-5-26 16:29:55

厉害了
回复

使用道具 举报

hnyzcj  版主

发表于 2020-5-26 18:36:12

回复

使用道具 举报

DFHJM_IpFmV  中级技师

发表于 2020-5-31 12:11:29


这个厉害呀!
回复

使用道具 举报

DFS1w2cb8o8  初级技师

发表于 2020-6-9 17:49:01

厉害厉害
回复

使用道具 举报

微笑的rockets  NPC

发表于 2020-6-12 10:54:46

关注之。
回复

使用道具 举报

DFHJM_IpFmV  中级技师

发表于 昨天 10:05

这个lattepanda自己就可以编程吧?
回复

使用道具 举报

DFHJM_IpFmV  中级技师

发表于 昨天 10:23

就不用软件写入程序吗?
回复

使用道具 举报

pATAq  版主
 楼主|

发表于 昨天 11:01

DFHJM_IpFmV 发表于 2020-7-2 10:23
就不用软件写入程序吗?

啥意思?LattePanda 本身就是一台小电脑,可以直接在 LP 上编程,但是我很多时候不接显示器用,所以用的 VS Code 的远程开发模式
回复

使用道具 举报

DFHJM_IpFmV  中级技师

发表于 昨天 11:05

pATAq 发表于 2020-7-2 11:01
啥意思?LattePanda 本身就是一台小电脑,可以直接在 LP 上编程,但是我很多时候不接显示器用,所以用的  ...

哦,好吧@pATAq
回复

使用道具 举报

高级模式
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2020 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail