Review: Fortebit Polaris 3g kit+
Eine Frage der Software
Dieser GPS-Tracker ist anders, und das in einem aus Entwickler- und Kundensicht sehr gutem Sinne. Es handelt sich um eine offene Plattform, etwas das bei GPS-Trackern sonst eher seltener der Fall ist. Ab Werk ist eine Firmware mit Basisfunktionen für das Tracken von Fahrzeugen installiert, etwas das andere Systeme natürlich auch erlauben. Der große Unterschied liegt darin, dass für diesen GPS-Tracker eigene Software geschrieben werden kann und dieses Mal nicht nur C/C++ als Programmiersprache zur Verfügung steht. Jedes Gerät wird mit der ZERYNTH Middleware und einer integrierten Lizenz für die darin enthaltene Python-Umgebung ausgeliefert. Für die Entwicklung wird das ZERYNTH Studio benötigt, das beim Hersteller heruntergeladen werden kann. Auch wer nicht mit Python loslegen möchte, sollte dieses durchführen, da die integrierte Lizenz für die Python-Umgebung auf der MCU sonst verloren gehen würde, wenn nicht zumindest einmal ein Python-Programm erfolgreich übertragen und auf dem Weg auch die Lizenz auf dem lokalen Rechner gesichert wird. Etwas das beim ZERYNTH Studio erwähnt werden muss, ist der Zwang eines Accounts beim Hersteller, um das ZERYNTH Studio nutzen zu können.Das ZERYNTH Studio selbst ist vom Editor her schlicht gehalten; wer einen reinen Editor für den Quelltext haben möchte, der ist mit anderer kostenfreier Software besser bedient. Es wird unter anderem Visual Code offiziell unterstützt. Vor weiteren Aktionen kann und sollte die Lizenz für die Python-Umgebung gesichert werden. Nachdem das geschehen ist, kann mit dem ersten Test des GPS-Trackers begonnen werden. Die Firmware auf dem Gerät kann von Haus aus nur mit dem Portal von Fortebit Daten austauschen, das wiederum einen Account benötigt. Dieser Account ist kostenpflichtig und kann einmalig mit dem Erwerb des GPS-Tracker für 30 Tage ohne Kosten getestet werden. Jeder der eine Flotte von Fahrzeugen oder anderen Dinge überwachen möchte, hat seine ganz eigenen Anforderrungen an die Datenverarbeitung und Aufbereitung. Daher wird hier das Portal auch nicht weiter beachtet, da es hier in erster Linie um die Hardware gehen soll und nicht um das Telematik-Portal.
Ab diesem Punkt muss selber Hand angelegt werden, um die Demoapplikation dazu zu bewegen, die Daten mit einem eigenen System der Wahl auszutauschen. Auch wer selbst ein Portal zum Tracken von Fahrzeugdaten betreibt, kommt um diesen Schritt nicht herum. Dies ist etwas, das gegenüber dem ansonsten guten ersten Eindruck noch Raum für Verbesserungen bietet. Wer nicht mit Python arbeiten möchte, kann den GPS-Tracker über das Arduino Framework mit neuer Software versorgen. Die nötige Software und Board Packages lassen sich auf dem GitHub Account von ForteBit finden und per Boardmanager in die Arduino IDE integrieren.
Für einen kurzen Testlauf wurde das Python-Beispiel umgestaltet (es handelt sich um Demo-Software, ist also nicht für einen Produktivbetrieb geeignet). Die Demo zeigt aber, wie die Hardware an einen MQTT-Broker eigener Wahl angebunden werden kann. Mit ein paar Zeilen Python sind die Anpassungen umgesetzt und zügig auf die Hardware übertragen. Die GPS-Daten werden an einen MQTT-Broker eigener Wahl gesendet.
Zusammenfassung
Der offene Hardwareansatz des GPS-Tracker und die Flexibilität bei der Auswahl der Entwicklungsumgebung und Programmiersprache machen das Fortebit Polaris 3G+ Kit zu einer sehr interessanten Plattform, vor allem wenn eigene Sonderfunktionen realisiert werden sollen. Die Dokumentation und Unterstützung mit Beispielen für Python und die Arduino-Welt sind sicherlich noch ausbaufähig, das Ganze wird hoffentlich auch durch den Hersteller vorangetrieben.Um das Fortebit Polaris 3G+ mit dem eigenen MQTT-Broker zu starten ist nachfolgend die modifizierte main.py gelistet:
# POLARIS_FORTEBIT
# Created at 2019-07-26 11:34:26.282569
# modified by someone(tm) 06-08-2020 for generic MQTT ( unsecured ) transport
# to use test.mosquitto.org as mqtt broker
# not for production use at all !
from mqtt import mqtt
from fortebit.polaris import polaris
from fortebit.polaris import modem
from fortebit.polaris import gnss
import vm
import sfw
vm.set_option(vm.VM_OPT_RESET_ON_EXCEPTION, 1)
vm.set_option(vm.VM_OPT_TRACE_ON_EXCEPTION, 1)
vm.set_option(vm.VM_OPT_RESET_ON_HARDFAULT, 1)
vm.set_option(vm.VM_OPT_TRACE_ON_HARDFAULT, 1)
import streams
s = streams.serial()
import mcu
import timestamp
import timers
import ssl
import requests
import threading
from wireless import gsm
import utils
sleep(1000)
# CONFIG
poll_time = 100 # poll inputs at twice the specified period in ms
gps_period = 10000 # gps lat,lon and speed telemetry period in ms
update_period = 6 * gps_period # other telemetry data period in ms
no_ignition_period = 300000 # no ignition telemetry data period in ms
fw_version = "1.11"
# POLARIS INIT
try:
print("Polaris default app")
polaris.init()
print("MCU UID:", [hex(b) for b in mcu.uid()])
print("VM info:", vm.info())
print("FW version:", fw_version)
print("Watchdog was triggered:", sfw.watchdog_triggered())
polaris.ledRedOn()
polaris.ledGreenOff()
except Exception as e:
print("Failed polaris init with", e)
sleep(500)
mcu.reset()
# INIT HW
try:
print("Initializing Modem...")
modem = modem.init()
print("Initializing GNSS...")
gnss = gnss.init()
# verify preconditions and start utility thread
utils.start()
print("Starting Accelerometer...")
import accel
accel.start()
print("Starting GNSS...")
gnss.start()
gnss.set_rate(2000)
print("Starting Modem...")
modem.startup()
# enable modem/gnss utilities
utils.modem = modem
utils.gnss = gnss
sfw.watchdog(0, 30000)
sfw.kick()
if utils.check_terminal(s):
utils.do_terminal(s)
minfo = gsm.mobile_info()
print("Modem:", minfo)
# enable SMS checking
utils.check_sms = True
except Exception as e:
print("Failed init hw with", e)
sleep(500)
mcu.reset()
# GATHERING SETTINGS
name = None
apn = None
email = None
try:
print("Read settings...")
settings = utils.readSettings()
sfw.kick()
if "apn" in settings:
apn = settings["apn"]
print("APN:", apn)
if "email" in settings:
email = settings["email"]
print("Email:", email)
if "name" in settings:
name = settings["name"]
print("Name:", name)
if apn is not None and not utils.validate_apn(apn):
print("Invalid APN!")
apn = None
if email is not None and not utils.validate_email(email):
print("Invalid email!")
email = None
if name is None:
name = "Polaris"
print("Saving name:", name)
settings["name"] = name
utils.saveSettings(settings)
if apn is None:
print("APN is not defined, can't connect to Internet!")
apn = utils.request_apn(s)
print("Saving email:", email)
print("Saving APN:", apn)
settings["apn"] = apn
utils.saveSettings(settings)
if email is None:
print("email is not defined, can't register to Cloud!")
email = utils.request_email(s)
settings["email"] = email
utils.saveSettings(settings)
except Exception as e:
print("Failed gathering settings with", e)
sleep(500)
mcu.reset()
# GSM ATTACH
try:
print("Waiting for network...",end='')
for _ in range(150):
sfw.kick()
ninfo = gsm.network_info()
if ninfo[6]:
break
sleep(1000)
if (_ % 10) == 9:
print('.',end='')
else:
raise TimeoutError
print("ok!")
print("Attached to network:", ninfo)
print("Activating data connection...")
for _ in range(3):
try:
gsm.attach(apn)
break
except Exception as e:
print("Retrying...", e)
try:
gsm.detach()
sleep(5000 * (_ + 1))
except:
pass
else:
raise TimeoutError
linfo = gsm.link_info()
print("Connection parameters:", linfo)
except Exception as e:
print("Network failure", e)
sleep(500)
mcu.reset()
# TELEMETRY LOOP
try:
accel.get_sigma() # reset accumulated value
sleep(500)
last_time = -(no_ignition_period + gps_period) # force sending data immediately
counter = 0
sos = -1
connected = True
ignition = None
sos = None
telemetry = {}
disconn_time = None
while True:
# allow other threads to run while waiting
sleep(poll_time*2)
sfw.kick()
now_time = timers.now()
if utils.check_terminal(s):
utils.do_terminal(s)
# read inputs
old_ign = ignition
ignition = polaris.getIgnitionStatus()
old_sos = sos
sos = polaris.getEmergencyStatus()
extra_send = False
# led waiting status
utils.status_led(False, ignition, connected)
if sos != old_sos:
telemetry['sos'] = sos
extra_send = True
if ignition != old_ign:
telemetry['ignition'] = ignition
extra_send = True
if not extra_send:
if ignition == 0:
# sleep as indicated by rate for no ignition
if now_time - last_time < no_ignition_period - poll_time:
continue
extra_send = True
else:
# sleep as indicated by rate
if now_time - last_time < gps_period - poll_time:
continue
ts = modem.rtc()
#print("MODEM RTC =", ts)
if counter % (update_period / gps_period) == 0 or extra_send:
telemetry['ignition'] = ignition
telemetry['sos'] = sos
if polaris.isBatteryBackup():
telemetry['charger'] = -1
else:
telemetry['battery'] = utils.decimal(3, polaris.readMainVoltage())
telemetry['charger'] = polaris.getChargerStatus()
telemetry['backup'] = utils.decimal(3, polaris.readBattVoltage())
telemetry['temperature'] = utils.decimal(2, accel.get_temperature())
telemetry['sigma'] = utils.decimal(3, accel.get_sigma())
pr = accel.get_pitchroll()
telemetry['pitch'] = utils.decimal(1, pr[0])
telemetry['roll'] = utils.decimal(1, pr[1])
if gnss.has_fix():
fix = gnss.fix()
# only transmit position when it's accurate
if fix[6] < 2.5:
telemetry['latitude'] = utils.decimal(6, fix[0])
telemetry['longitude'] = utils.decimal(6, fix[1])
telemetry['speed'] = utils.decimal(1, fix[3])
if counter % (update_period / gps_period) == 0 or extra_send:
telemetry['altitude'] = utils.decimal(1, fix[2])
telemetry['COG'] = utils.decimal(1, fix[4])
if counter % (update_period / gps_period) == 0 or extra_send:
telemetry['nsat'] = fix[5]
telemetry['HDOP'] = utils.decimal(2, fix[6])
# replace timestamp with GPS
ts = fix[9]
elif ts is not None and ts[0] < 2019:
ts = None
if ts is not None:
ts = str(timestamp.to_unix(ts)) + "000"
counter += 1
last_time = now_time
# led sending status
utils.status_led(True, ignition, connected)
telemetry['counter']=counter
telemetry['dev_ts']=ts
sfw.kick()
# set the mqtt id to "zerynth-mqtt"
client = mqtt.Client("zerynth-mqtt",True)
# and try to connect to "test.mosquitto.org"
for retry in range(10):
try:
client.connect("test.mosquitto.org", 60)
break
except Exception as e:
print("connecting...")
print("connected.")
print("Publishing:", telemetry)
client.publish("test", str(telemetry))
client.loop()
ok = False;
except Exception as e:
print("Failed telemetry loop", e)
sleep(500)
mcu.reset()
Mehr anzeigen
Weniger anzeigen
Diskussion (0 Kommentare)