LoRaWAN网关移植记录

之前写的LoRaWAN GW NS代码中提到了已经基于Twisted实现了GW/NS代码。其中NS代码设计起来比较简单。因为许多Linux系统中并没有Twisted,甚至CPython也是比较低的版本。所以必须基于MicroPython的多线程版本backport到低版本CPython中。

兼容性

MicroPython是基于CPython 3.4的,而旧版本CPython大多都是2.7的,甚至更低。一种做法是直接交叉编译MicroPython到这些SBC中,另外就是乖乖滴重新写代码了。

主要的兼容性问题在于Timer和time两个模块。

Timer

MicroPython将Timer归为machine下的模块,因为它的定时器是物理定时器,采用定时中断驱动。同时也正是这个原因,ISR代码大多采用lambda来写。

CPython中,Timer归为threading的子类。本质上是线程,所以CPython下循环定时器代码反而比MicroPython要繁琐。移植后的CPython版本,成了1+3四个线程的程序:主程序+UDP接收+两个定时器线程

time

因为MicroPython来自CPython 3.4,所以有些高精度的计时方法,如tick_cpu()/tick_us()/sleep_ms(),其实这些也都是MicroPython特有方法,CPython 3.4里不是这些方法。目前我暂时以time.time()的浮点数来替代,理论上精确到0.1us。其实能够实现1ms就不错了。

LoRaWAN下发窗口其实是有时间精度要求的。在LoRaWANPktFwd协议中有三种方式计时:

  1. 立即下发;
  2. 时间戳下发;
  3. GPS时间戳下发。

如果计时有问题,会返回以下错误报告:

Value Definition
NONE Packet has been programmed for downlink
TOO_LATE Rejected because it was already too late to program this packet for downlink
TOO_EARLY Rejected because downlink packet timestamp is too much in advance
COLLISION_PACKET Rejected because there was already a packet programmed in requested timeframe
COLLISION_BEACON Rejected because there was already a beacon planned in requested timeframe
TX_FREQ Rejected because requested frequency is not supported by TX RF chain
TX_POWER Rejected because requested power is not supported by gateway
GPS_UNLOCKED Rejected because GPS is unlocked, so GPS timestamp cannot be used

问题来了,在许多广域应用中,需要借助GPS授时,这当然没有疑问。立即下发也没有问题。反倒是没有严格要求的情况下,一般通过NTP进行授时,能够精确到ms么?好像不能。局域网内1ms,公网一般在100ms左右。如果终端设备没有授时装置,则需要网关不断地Beacon推送时间戳。加上TOF时间,误差真的还蛮大的。

更新(20180930)

基于CPython的多线程设计已经在Ubuntu和OpenWRT中调试完毕,现在只需要对接LoRaWAN USB dongle的HCI接口即可。改HCI接口参考Bluetooth SIG HCI而来,主要做了减法,简化了设计。

祝大家国庆快乐!

你可能感兴趣的:(LoRaWAN网关移植记录)