Doch nun endlich: Erfolgreiche Verbindung von FiPy mit EiNCE-SIM im LTE NB-IoT-Band
Auf den Schultern von den Giganten hier stehend und insb. dank jüngster Unterrichtungen durch Herrn Prof. Dr. @Andreas kann ich eine kleine Erfolgsmeldung aus dem Erdgeschoss eines berliner Mietshauses verbuchen:
- Das FiPy-Board ist mit v1.2 gelabeled gekauft, aufs frischeste, Firmware v1.18.2.r6, geupdated.
- Als Antenne wird eine “800-960/1710-2170MHz 2dBi”-, Gehäuse-interne Antenne verwendet, 20cm Kabel direkt auf U.FL (aka IPEX/IPAX). Empfangswert “CSQ” = 20-30.
- Die Firmware des LTE-Modems auf NB-IoT-Betrieb gemäß dieser ganz genau zu befolgenden Anleitung geflashed. (Man muss sich auch zwischendrin einen Forums-Account anlegen, um ein dort hinterlegtes, hochgeheimes Passwort für die Modem-Firmware zu erfahren.)
- Eine EiNCE-SIM-Karte eingelegt, die sonst nicht bedaddelt wurde (außer vorher testweise ins Mobiltelefon eingelegt, um zu gucken, ob das SIM ne PIN erfragt: Nö, ist nicht der Fall).
- Das Ersteinbuchen ging auch relativ schnell (keine 1-2 Minuten), nicht die befürchteten 10 Minuten.
- Nen erneuter Connect nach nem Reboot scheint unterschiedlich <1s aber auch vielleicht auch mal 10-20s zu brauchen. Müsste-man-mal™ tracken und weiter studieren.
- Ein Reconnect findet nach nem “Reset-Button-Reboot” sehr schnell statt, nach nem “Kaltstart” braucht es seine ~5-15s.
- Folgende Codezeilen sind ins main.py geklöppelt, das dem LTE-Modem erst ein paar Infos entlockt, dann den Connect macht und am Ende regelmäßig nen MQTT-Submit macht (und ein bisschen mit den LEDs spielt). Zwischendrin wir noch ne Temperatur gemessen.
- Es geht doch auch ins Internet! DNS offenbar nicht (hackable?). Der Traffic fällt ausm Amazon-AWS raus, echt nen show-stopper, wenn da auch die übrigige Netz & VPN-Infrastruktur drüber läuft. “Netzwerk to the Cloud”, sagten sie auch neulich am Späti.
- Es gibt wohl nur IPv4 (hinter nem NAT), kein IPv6. Also insofern kein echtes Internet.
- Latenzen hab ich bis zu 7 Sekunden gesehen. Wildes rumgepinge vermittelt den Eindruck, als würde das Netz alle 5-10 Sekunden den Clients ne Chance für nen paar Datenverkehre geben: Wenn dreimal nacheinander jeweils vier Pings an unterschiedeliche Ziele kommen, jittern die vier Pings zu einander recht wenig, aber die drei Reihen (a vier Pings) zu einander erheblich: mal 1.5s, mal 5s, mal 3s.
- Ab und an fehlt auch mal nen Paket. Wir sollten mal die Zuverlässigkeit “messen” und überlegen ob nen UDP-Submit oder “MQTT-QoS 0” noch tragbar wären.
##!/usr/bin/env python
# fipy-nbiot-rtd v0.0.1, https://git.cicer.de/autonome-zelle/fipy-nbiot-rtd
# Connecting a Pt100-thermometer via an MAX31865 Adafruit-board at an PyCom FiPy via Narrow-Band-IoT-LTE to a MQTT-Server.
#
# by The Hiveeyes Project, https://hiveeyes.org/
# based on Software by Pycom Limited (2019, GPLv3)
#
# Known issues:
# - way too many
#
# Legend: Initial discussion for creating this thing
# https://community.hiveeyes.org/t/erschliessung-von-lte-cat-m1-und-nb1-mit-dem-pycom-fipy/
#
# This software is licensed under the GNU GPL version 3 or any
# later version, with permitted additional terms. For more information
# see the Pycom Licence v1.0 document supplied with this file, or
# available at https://www.pycom.io/opensource/licensing
print("[system] Hello world.")
import machine
from machine import RTC
import time
import pycom
from lopy_max31865 import MAX31865
import network
from network import LTE
#import sqnsupgrade
#import uping
from mqtt import MQTTClient
# rtd: instance
print("[Pt100] instance.")
rtd = MAX31865()
# lte: instance
print("[LTE] instance.")
lte = LTE()
# rtc: instance
print("[RTC] instance.")
rtc = RTC()
rtc.ntp_sync("192.53.103.108")
# LTE: get infos from Modem
#lte.send_at_cmd('AT!="RRC:setDbgPerm full"')
#print(lte.send_at_cmd('AT!="RRC:showcaps"'))
#print(lte.send_at_cmd('AT!="showver"'))
#sqnsupgrade.info()
# LTE: init()
try:
lte.init()
except:
print("[LTE] try() (except). will reset.")
machine.reset()
# LTE: attach()
try:
lte.attach(band=8, apn="iot.1nce.net")
while not lte.isattached():
time.sleep(1)
print('[LTE] Attaching...')
lte.send_at_cmd("AT+CFUN=1")
print(lte.send_at_cmd("AT+CSQ"))
except:
print("[LTE] attach() (except). Will reset.")
machine.reset()
# LTE: connect()
try:
lte.connect()
while not lte.isconnected():
time.sleep(1)
print('[LTE] connecting...')
except:
print("[LTE] connect() (except). will reset.")
machine.reset()
# MQTT: connect()
try:
print("[MQTT] trying connect.")
client = MQTTClient("ef3423be2", "46.4.251.67", port=1883)
client.settimeout = 60
client.connect()
except:
print("[MQTT] connecterror (except). will reset.")
machine.reset()
# LED: turn off
pycom.heartbeat(False)
while True:
# LED: blue
print("[LED] blue")
# Pt100: read measurement
print("[Pt100] trying measurement.")
pycom.rgbled(0x0000FF)
try:
temp = rtd.read()
Tpoy = str(temp)
print("[Pt100] got measurement: {0}°C".format(temp))
except:
print("[Pt100] error (except). will reset.")
machine.reset()
# LED: red
print("[LED] red")
# MQTT: publish
print("[MQTT] trying submit.")
pycom.rgbled(0xFF0000)
try:
client.publish("umwelt/airrohr/research/pt100-wtf-02/data.json", "{ \"Tpoly\": " + Tpoy + " }")
print("[MQTT] done. sent: " + "{ \"Tpoly\":" + Tpoy + " }")
except:
print("[MQTT] error (except). will reset.")
machine.reset()
# LED: green
print("[LED] green")
# System: idle
pycom.rgbled(0x001100)
time.sleep(9)
Ergebnis ist dann ungefähr das hier:
[system] Hello world.
[Pt100] instance.
[LTE] instance.
[RTC] instance.
[LTE] Attaching...
+CSQ: 99,99
OK
[LTE] Attaching...
+CSQ: 99,99
OK
[LTE] Attaching...
+CSQ: 99,99
OK
[LTE] Attaching...
+CSQ: 99,99
OK
[LTE] Attaching...
+CSQ: 99,99
OK
[LTE] Attaching...
+CSQ: 19,99
OK
[LTE] Attaching...
+CSQ: 19,99
OK
[LTE] Attaching...
+CSQ: 20,99
OK
[LTE] Attaching...
+CSQ: 20,99
OK
[LTE] Attaching...
+CSQ: 19,99
OK
[LTE] Attaching...
+CSQ: 20,99
OK
[LTE] Attaching...
+CSQ: 19,99
OK
+CSQ: 19,99
OK
[LTE] Attaching...
+CSQ: 19,99
OK
[LTE] Attaching...
+CSQ: 20,99
OK
[LTE] Attaching...
+CSQ: 20,99
OK
[LTE] Attaching...
+CSQ: 19,99
OK
[LTE] Attaching...
+CSQ: 20,99
OK
[LTE] Attaching...
+CSQ: 19,99
OK
[LTE] Attaching...
+CSQ: 19,99
OK
[LTE] Attaching...
+CSQ: 19,99
OK
[LTE] Attaching...
+CSQ: 19,99
OK
[LTE] Attaching...
+CSQ: 20,99
OK
[LTE] Attaching...
+CSQ: 19,99
OK
[LTE] connecting...
('46.4.251.67', 1883)
[LED] blue
[Pt100] trying measurement.
[Pt100] got measurement: 24.61998°C
0
[LED] red
[MQTT] trying submit ...
[MQTT] done. Sent: { "Tpoly":24.61998 }
[LED] green
[LED] blue
[Pt100] trying measurement.
[Pt100] got measurement: 24.61998°C
0
Und fürs Protokoll noch:
boot.py
#!/usr/bin/env python
#
# Copyright (c) 2019, Pycom Limited.
#
# This software is licensed under the GNU GPL version 3 or any
# later version, with permitted additional terms. For more information
# see the Pycom Licence v1.0 document supplied with this file, or
# available at https://www.pycom.io/opensource/licensing
#
from machine import UART
import machine
import os
uart = UART(0, baudrate=115200)
os.dupterm(uart)
#from network import WLAN
#wlan = WLAN(mode=WLAN.STA)
machine.main('main.py')
Fazit: Das ging dann doch jetz eigentlich-irgendwie ziemlich “by the book”, die Doku erstreckt sich auf drei Artikel:
CAT-M1 (vor allem fürs HTTPS-Beispiel)
NB-IoT (für den Connect selbst)
LTE (Referenz/Funktionsbeschreibungen)
und natürlich:
Modem Firmware Update (s. o.)
ps.: Man will mit den timeouts großzügig sein. Das testweise zwischendrin verwendete urequests für http(s)-GETs ists wohl nicht, drum hab ich da noch manuell diesen diff/pull-request reingeprepelt, der ne timeout-Angabe ermöglicht.
pps.: hab das ding grad zwischen 16 und 17h mal 35min lang gepingt, durch den beigelegten openvpn tunnel: mean von 3s. max von 29s. 2% loss.
--- 10.194.84.3 ping statistics ---
2125 packets transmitted, 2079 received, 2% packet loss, time 2140313ms
rtt min/avg/max/mdev = 263.301/1574.289/28513.890/3079.014 ms, pipe 28