TTN-Daten an Kotori weiterleiten

#1

Habe ich schon erwähnt, dass TTN die Daten auch an einen HTTP Endpoint senden kann [1]? Es wäre doch schön, wenn Kotori das auch annimmt. Zur Zeit nutze ich eine MQTT Bridge, die ich auf elbanco konfigurieren muss - und zwar für jedes Device in /etc/mosquitto/conf/bridge-thias-ttn-cayennelpp.conf

Dann müssten wir uns aber wohl Gedanken um den Namespace der TTN Applikationen und Device-Namen machen, damit das sauber und getrennt nach Nutzern in Influx landet.

[1] HTTP | The Things Network

2 Likes
More data acquisition payload formats for Kotori
X-beliebige Plattformwaage von ebay
IoT4Bees / LoRaWAN-Bienenwaagen an der Bergstraße
Terkin for MicroPython
#2

@Thias, ja, hatte ich mir auch so vorgestellt, um das Problem zu umgehen, dass TTN nicht direkt MQTT kann!!

#3

Super Idee, machen wir gerne gleich in einem Aufwasch. Kannst Du (vielleicht in einem ordentlichen Beitrag) das Payloadformat teilen? Dann haben wir alle Anträge für alle neuen Datenformate in einem Thread gesammelt. Das wäre riesig, das kann ich dann bei Gelegenheit in einem Rutsch abarbeiten ;].

Danke!

P.S.: Trial and error

Kannst Du das Payloadformat teilen?

Du kannst gern einmal direkt den Endpunkt

https://swarm.hiveeyes.org/api/hiveeyes/testdrive/ttn/he-one/data

angeben. Dann können wir schauen, was da so passiert. Wenn das parallel zu Deinem bisherigen Telemetriekanal konfiguriert sein kann, dann schalte das doch kurzerhand dazu und lass es ggf. einfach mitlaufen, wenn es nicht schadet.

#4

Habe den Endpoint eingerichtet. Zwei Geräte senden darüber im 5 Minuten Takt Daten. Das Payload Format ist auch JSON.

1 Like
#5

Tiptop, vielen Dank! Es wird vermutlich noch ein wenig Zeit brauchen, bis ich mich an die Implementierung setzen kann, aber wir können das Thema in der Zwischenzeit schonmal weiter diskutieren.

Payload

Das Payload sieht schematisch folgendermaßen aus:

{
  "dev_id": "nodename",
  "downlink_url": "https://integrations.thethingsnetwork.org/ttn-eu/api/v2/down/hiveeyes/hiveeyes?key=ttn-account-v2.{redacted}",
  "counter": 11,
  "app_id": "hiveeyes",
  "payload_fields": {
    "temperature_2": -3.2,
    "temperature_1": -2.9,
    "analog_in_1": 35.99,
    "analog_in_3": 3.53,
    "relative_humidity_2": 57.5,
    "relative_humidity_1": 55.5
  },
  "payload_raw": "AQIODwFn/+MBaG8CZ//gAmhzAwIBYQ==",
  "hardware_serial": "{redacted}",
  "port": 1,
  "metadata": {
    "location_source": "registry",
    "data_rate": "SF8BW125",
    "modulation": "LORA",
    "longitude": 10.00,
    "coding_rate": "4/5",
    "frequency": 867.3,
    "gateways": [
      {
        "location_source": "registry",
        "gtw_id": "eui-{redacted}",
        "timestamp": 692492724,
        "altitude": 40,
        "longitude": 10.00,
        "rf_chain": 0,
        "snr": -2.2,
        "time": "2019-01-24T20:34:23.836347Z",
        "latitude": 50.00,
        "rssi": -111,
        "channel": 4
      }
    ],
    "time": "2019-01-24T20:34:23.85854123Z",
    "latitude": 50.00
  }
}

Meßdaten

Ganz schön umfangreich, exzellent! Ich würde versuchen, alle sinnvollen Werte rauszuholen und in den Meßdatensatz einfließen zu lassen.

Kanaladresse

Zwei Geräte sogar - wunderbar!

Ein kleiner Gedankenaustausch vielleicht auch hierzu: Auch wenn die Geräte sich zwar über das Feld "dev_id": "nodename" verschieden identifizieren, wäre es praktisch, wenn sie ungeachtet dessen trotzdem auf unterschiedlichen Datenkanälen senden würden, beispielsweise also testdrive/ttn/thias-one vs. testdrive/ttn/thias-two.

Meine Fragen dazu:

  • a) Könntest Du das so einrichten? Dann wäre serverseitig nur ein Adapter für das TTN Format notwendig und die Semantik des Datenkanals bzgl. des Adressierungsaspekts wird nicht sonderlich geändert.
  • b) Oder wäre es in der Tat Dein sehnlicher Wunsch, das Device Mapping über das Feld "dev_id" zu realisieren, um den TTN-seitigen Konfigurationsaufwand pro Gerät zu minimieren? Falls ja, dann können wir natürlich gern versuchen, der Gegenstelle auch diese speziellere Variante beizubringen.

P.S.: Wenn wir Variante b) angehen, würde es semantisch mehr Sinn machen, die Nachrichten an eine gekürzte Datenkanaladresse à la "testdrive/ttn-thias" zu adressieren, nicht? Der Knotenname müsste in diesem Fall ja nicht in der Kanaladresse stehen, wenn er aus dem Payload selbst bezogen werden kann (und soll). Das wäre aber dann weitere Zukunftsmusik, erstmal würde ich gerne Variante a) realisieren und auch das wird wohl noch ein Weilchen dauern.

Danke einstweilen für diesen Blick unter die Haub! Wenn es Deiner Infrastruktur nichts ausmacht, lass den Feed gerne weiter so laufen, auch wenn derzeit leider noch nichts passiert.

#6

Ich habe meine beiden Nodes unter der TTN app_id “hiveeyes” verankert. AppIDs sind bei TTN global unique, dh. niemand anders kann unter seinem Account eine gleichnaminge AppID nutzen. Ich kann aber gerne die App öffnen, so dass auch andere LoRa Nutzer dort ihre Devices betreuen. Das ganze erfolgt dann per Einladung anderer TTN Accounts zur App. Für dein Beispiel dann die App names testdrive. War bis eben noch nicht vergeben :)

Edit: die Konfiguration des HTTP Endpoints gilt auch per TTN App und nicht per Device

Ich würde vorschlagen, das Topic folgendermaßen abzuleiten, wobei #1_#2 auf die Influx interne Datenbank verweisen:

  • #1 -> app_id (hiveeyes)
  • #2 -> erster String der dev_id, mit Bindestrich als Separator, zB thias aus thias-hive1
  • #3 -> dev_id

Devices von anderen Teilnehmern müssten dann nur dem Schema folgen, indem sie ihren persönlichen Hiveeyes Identifier als ersten Teil ihrer TTN Device ID verwenden.

Der Endpoint könnte dann auch genetischer sein. Zb

https://swarm.hiveeyes.org/api/ttn/data

Meine Daten würden dann weiterhin unter der DB hiveeyes_thias in Influx abgelegt werden. Ich habe es bisher geschätzt alle meine Daten in Influx unter einer eigenen Datenbank zu haben und musste mir deshalb bei Eingriffen nie Sorgen machen, die Daten von anderen Teilnehmern zu riskieren.

#7

Neben payload_fields würde mich noch SNR und RSSI interessieren. Sie geben mir Auskunft über die Qualität der Funkverbindung zum Gateway.

#8

Hi Matthias,

merci vielmals!

Das wäre also Variante b)++: Generischer tunnelartiger non-REST HTTP Endpunkt und die Adressierungsinformationen werden vollständig aus den Metadaten des Payloads abgeleitet? Ja, hört sich in diesem Fall absolut sinnvoll an, können wir gern so machen.

Freilich, diese Felder holen wir gern dazu.

Es dauert nur leider noch ein wenig, inzwischen herzlichen Dank für den konzeptionellen Input!

Viele Grüße,
Andreas.

1 Like
#9

Alles klar, danke für den Einblick. Apps sind also absolut global unique, deren optional konfigurierbare HTTP Endpunkte sind also ebenfalls absolute Einzelgänger. Alle Daten aller über diese App funkenden Geräte landen also zwangsläufig immer bei der gleichen HTTP Senke. Richtig?

Absolut, die Datenbankisolation auf Mandantenebene soll in der neuen TTN-spezifischen Adressierungsart genauso beibehalten werden können.


Meine Gedanken dazu:

Kanaladressierung

  • Wenn wir mit der app_id also fest auf einen bestimmten “realm” festgenagelt sind (das ist die erste Komponente unseres Adressierungsquadrupels) und wir derzeit die “Apps” hiveeyes sowie testdrive in Beschlag haben (weil Du sie reserviert hast, falls ich das richtig verstanden habe; danke!) …

  • … so dass für die Adressierung eines Geräts also nur die dev_id übrigt bleibt und Du ohnehin diesen Vorschlag machtest:

    #2 -> erster String der dev_id , mit Bindestrich als Separator, zB thias aus thias-hive1

… wollen wir dann vielleicht gleich sagen, dass wir unsere drei herkömmlichen Adressierungskomponenten (Network, Gateway, Node) bzw. (Imker, Standort, Beute) mit Bindestrich als Separator in der dev_id unterbringen? Also nicht nur thias-hive1, sondern thias-freiland-hive1?

Implementierungsdetails

  • Als Trenner für die drei Adressierungskomponenten mit entsprechender Semantik bietet sich der Dash ("-") ganz gut an. Man könnte aber auch den Punkt “.” oder den Slash “/” oder alle drei Zeichen gleichermaßen dafür zulassen.

  • Zusatzregel für die Adaptierungslogik: Wenn eine der drei in der dev_id anzugebenden Adressierungskomponente fehlt, wird sie mit “default” aufgefüllt. Aus einer dev_id namens “thias-freiland” würde also implizit “thias-freiland-default”.

#10

Absolut richtig verstanden.

Fein, entspricht auch meinem Wunsch.

Gute Idee! Da mach ich mit, aber :) …

… ich habe aber noch mal über die gemeinsame Nutzung meiner TTN hiveeyes App nachgedacht. Zwei Dinge sind mir dabei eingefallen, die gegen die gemeinsame Nutzung sprechen:

  • Für die Datencodierung vom Node zu TTN kann man entweder CayenneLPP nutzen oder eine individuelle Decoderfunktion hinterlegen, die dann zur Implementierung der Codierung auf dem Node passt und zB. ein JSON Paket zerlegt und auf den Variablenraum bei TTN packt. CayenneLPP nutzt hier einen vorgeschriebenen Namensraum (siehe Payload-Beispiel oben). Der Variablenraum von TTN landet dann schließlich im Payload an den HTTP Endpoint oder in der MQTT subscription bei TTN. Meine Empfehlung lautet zwar klar CayenneLPP zu nutzen, weil es die Datenpakete sehr klein hält (im Payload-Beispiel oben -> payload_raw: 35Bytes, verschlüsselt mit Overhead) und damit Airtime spart - ein ernsthaft zu berücksichtigender Aspekt bei LoRaWAN. Die Wahl des Decoders gilt allerdings für alle Devices unterhalb einer App gleichermaßen. Alle Teilnehmer an der App müssten also auch auf CayenneLPP umschwenken und das will ich niemandem vorschreiben, auch wenn die Implementierung in der Firmware einfach ist und diejenigen, die anders codieren wollen, damit mehr Airtime verbraten.
    Bildschirmfoto%20von%202019-01-25%2009-38-08
  • ich müsste andere TTN Nutzer jedesmal manuell zur App hinzufügen, mit Rechten versehen usw. Eine für jeden Nutzer autarke Lösung, wo jeder seine TTN-App pflegt, fände ich schöner und minimiert auch Fremdeinwirkungen auf die Konfiguration anderer, zB Device-EUIs, App-EUIs, App-Keys und Activation Methods.

Drum schlage ich vor, die app_id aus dem Payload erst gar nicht zu verwenden und an dessen statt nur auf die dev_id zu setzen. Diese darf maximal 36 Zeichen lang sein(!) und sollte dann aus vier Komponenten bestehen - getrennt durch einen Bindestrich, zB.

hiveeyes-thias-freiland-hive1

Das würde andere Realms wie testdrive-... o.ä. auf einfache Weise gleich mit ermöglichen. Andere Realms können einfach verworfen werden.

Unter welcher TTN App das dann läuft, ist egal. In der Konfiguration der HTTP Integration bei TTN gibt dann einfach jeder den gleichen Endpoint ein. Fertig ist der Lack :) Theoretisch ;)

2 Likes
#11

Wenn ich Zeit finde, stelle ich den Testaufbau mit dem Wägegestell aus China am Wochenende um auf die dev_id:

testdrive-thias-freiland-cnwaage

1 Like
#12

Autorisierung auf dem Endpoint wollen wir sicherlich auch, oder? Die HTTP Integration bei TTN bietet die Möglichkeit einen Authorization header anzugeben. Ob das dann per User eingerichtet wird oder mit einer Autorisierung für alle, bleibt dir überlassen, Andreas.

Bildschirmfoto%20von%202019-01-25%2013-20-49

2 Likes
#13

Der Teststand nutzt jetzt die dev_id:

hiveeyes-testdrive-freiland-cnwaage

Daten kommen frühestens morgen wieder an, wenn ich die LoRa Einheit im freiLand installiert habe.

Nachtrag: auch meine Livedaten eines echten Volkes funken jetzt mit einer neuen dev_id:

hiveeyes-thias-freiland-hive1

1 Like
#14

Weil sich auch @tonke gerade mit TTN beschäftigt, konnten wir hier ein weiteres TTN Datenpaket aufschnappen, das heute Vormittag über zwei Gateways gleichzeitig gelaufen ist:

{
  "app_id": "{redacted}",
  "dev_id": "{redacted}",
  "hardware_serial": "{redacted}",
  "port": 2,
  "counter": 61,
  "payload_raw": "oLsNQHcbU004qQY1EoYAWD4PWD4Pxo4P8KYd",
  "payload_fields": {
    "battery": 3.4322,
    "cog": 0,
    "hexstring": "160,187,13,64,119,27,83,77,56,169,6,53,18,134,0,88,62,15,88,62,15,198,142,15,240,166,29",
    "latitude": 0,
    "longitude": 0,
    "pitch": -12.4887,
    "pressure": 944.28,
    "raw": "oLsNQHcbU004qQY1EoYAWD4PWD4Pxo4P8KYd",
    "roll": 8.9811,
    "speed": 0,
    "temp": 20.59
  },
  "metadata": {
    "time": "2019-02-08T10:02:39.405910743Z",
    "frequency": 868.3,
    "modulation": "LORA",
    "data_rate": "SF7BW125",
    "airtime": 82176000,
    "coding_rate": "4/5",
    "gateways": [
      {
        "gtw_id": "eui-{redacted}",
        "timestamp": 513428579,
        "time": "2019-02-08T10:02:39.381198Z",
        "channel": 1,
        "rssi": -107,
        "snr": -4.5,
        "rf_chain": 1,
        "latitude": 47.000000,
        "longitude": 11.000000,
        "location_source": "registry"
      },
      {
        "gtw_id": "eui-{redacted}",
        "timestamp": 2307776099,
        "time": "",
        "channel": 1,
        "rssi": -63,
        "snr": 9.5,
        "rf_chain": 1,
        "latitude": 47.000000,
        "longitude": 11.000000,
        "altitude": 700,
        "location_source": "registry"
      }
    ]
  }
}

Merci!


Da wir ja gerne möglichst umfangreiche Telemetriedaten erhalten wollen (stimmts?), finde ich diese Information sehr wertvoll, weil wir u.U. auch die Metadaten aller involvierten Gateways aufzeichnen wollen, wenn wir schon dabei sind.

1 Like
#15

Fürs Debuggen mag das interessant sein und um am Standort vielleicht die optimale Position einer Richtantenne zu finden - für die erste halbe Stunde. Wenn wir aber anschließend vielleicht Jahre lang den ganzen Schrott bei uns in die DB schreiben wird die zur Müllhalde. Bei beweglichen nodes ist das ggf. anders, wenn man über die Gateways an die lat / long der nodes kommt.

#16

Korrekt, genau darum geht es in diesem Fall gemeinsam mit @tonke, da sind wir mobil unterwegs. Wir wollen - unabhängig von der Speicherung der Zeitseriendaten in einer InfluxDB Datenbank - alle TTN Datenpakete 1:1 in einer MongoDB Datenbank aufzeichnen. Da es (verschachtelte) JSON Dokumente sind, die da über die TTN Infrastruktur hinten rausfallen, eignet sich das hervorragend, um z.B. nach einer Meßfahrt die Möglichkeit zu haben, die Daten bei der Abfrage flexibel nach beliebigen Kriterien im JSON Dokument filtern zu können.

#17

Ich würde mir gut überlegen, was wir von den metadaten brauchen. Schau’ dir nur im Beispiel oben das Verhältnis von eigentlcher payload und metadaten an. Klar, was kostet die Welt, bzw. TB an Speicher, aber warum den ganzen Schrott speichern, wenn man es später nie wieder braucht.

#18

was Generelles in diesem Zusammenhang (unabhängig von “welche meta-Daten oder Verkehrsdaten recorden wir”):

MongoDB ist bei Debian und bei RedHat aus den repos geflogen aufgrund ihrer server-side public license (SSPL) . Wenngleich die Intention hinter der Lizenz nachvollziehbar ist, hätten sie besser die GPLv3 nehmen sollen, anstatt an der AGPL herumzupopeln; man kann diskutieren, ob ein Linux mit MongoDB neu lizensiert werden müßte…

Wenn also MongoDB, dann einen der forks - oder gleich Postgres.

#19

Für dieses spezielle Vorhaben, im mobilen Betrieb Meßfahrten und dergleichen durchzuführen, und für alle Menschen die Ähnliches vorhaben, wollen wir in der Tat den vollständigen Payload aufzeichnen.

Den Dekoder, der aus diesem kompletten Satz die für eine Zeitseriendatenerfassung sinnvollen Daten herausfiltert, haben wir bereits, siehe store(self, ttn_message) beim GitHub - daq-tools/ttnlogger: Converge TTN messages into InfluxDB and MongoDB and display in Grafana.

Es geht dabei also v.a. um eine noch fehlende zusätzliche Funktionalität.

#20

ttnlogger -> InfluxDB + MongoDB

Gern. Hab da grade nicht so geschaut, was sich da so herauskristallisiert, nehme aber gerne Tipps entgegen. “Lebt z.B. TokuMX noch und was haben die (Percona) aus der Relizensierung gemacht?” frage ich mich z.B. an dieser Stelle.

MongoDB durch PostgreSQL ersetzen?

Grundsätzlich schon auch gern. Allerdings: Wir haben neulich die ersten Schritte unternommen, uns dem JSON Datentyp [1] und entsprechenden Funktionen [2] von PostgreSQL zu widmen. Das ist zwar alles ziemlich mächtig und man kann als Datenbankadministrator auch dort Datenbankindizes auf verschachtelte Strukturen legen, die Abfragesyntax ist aber nichts für Anfänger im Alltagsgebrauch, dort hat MongoDB für mich noch die Nase etwas vorn.

ttnlogger -> InfluxDB + PostgreSQL/JSON

Vielleicht - die MongoDB Implementierung ist schließlich noch nicht im Kasten - schwenken wir aber noch rechtzeitig um und erarbeiten uns bei der Gelegenheit ein entsprechendes Tutorial à la “Getting started with PostgreSQL/JSON”, dann wird da u.U. ein Schuh draus und die Codebase des "ttnlogger" kann als Testbed/Blaupause dafür herhalten, dass wir uns da endlich weiterentwickeln.

Daher danke vielmals für den Impuls! Ich könnte mir vorstellen, dass auch @tonke nicht abgeneigt sein wird, erst recht wenn ihm die Dinge wie wir sie bei GIS Funktionalitäten zur Abfrage der luftdaten.info Stationsliste eingerichtet haben genauso gefallen wie uns.

[1] PostgreSQL: Documentation: 10: 8.14. JSON Types
[2] PostgreSQL: Documentation: 10: 9.15. JSON Functions and Operators