Falls jemand Interesse hat:
Grüße
richimaint
Gesendet von iPhone XS mit Tapatalk
Falls jemand Interesse hat:
Grüße
richimaint
Gesendet von iPhone XS mit Tapatalk
Das TTN-Device war meine erste Instanz. Die kann tatsächlich die Rohdaten verwalten wenn die Daten als solche gesendet werden, ist jedoch in den meinsten fällen nicht der Fall (Habe ich auch dazu gelernt :rolleyes:)
Daher habe ich auch in der Doku geschrieben, dass ich diese Instanz auch nicht mehr weiterentwickle. Falls sie doch noch jemand verwendet wollte ich sie aber nicht ersatzlos raus werfen. Durch die Struktur von TTN werden die Daten ja im Decoder bereits zerteilt und werden dann als Objekte über die API raus gegeben. Daher macht es wenig Sinn mit den Rohdaten zu arbeiten sondern mit dem Objekten und das dann im „TTN Object Device“.
Danke da verliert man beim Programmieren gerne den Überblick ![]()
Beim nächsten Update passt das wieder ![]()
Da Bist du schon auf dem richtigen Weg die Daten werden im Decoder zerlegt und werden dann in das „TTN Object Device“ weiter gegeben. Hierbei muss „RAW-Payload“ deaktiviert sein, da das bedeuten würde, dass die Daten als JSON im Payload des LoRa Gerätes stehen (macht aus Sicht des Overheads keinen Sinn)
Wenn du „Variablen automatisch erstellen“ aktiviert hast sollten sich diese beim Empfang der ersten Nachricht selbst erstellen.
Wenn RSSI-Werte vorhanden sind aber keine Daten erstellt werden stimmt vermutlich etwas mit deinem Decoder nicht.
Beispieldecoder:
function Decoder(bytes, port) {
var decoded = {};
decoded.value = parseFloat(String.fromCharCode.apply(null, bytes).substring(0, 4))/10
return decoded;
}
die Variablen müssen unter decoded stehen. Wie z.B. decodet.value. Dann wird die Variable „value“ erstellt.
Tiefere Verschachtelungen sind hier nicht möglich.
Viel einfacher geht das wenn der Node das Cayenn LPP-Format unterstützt. Dann geht das alles automatisch ![]()
Der Enviroment Sensor ist im Grunde ein „TTN Object Device“ mit festen Keys für die Parameter:
[ul]
[li]Temperatur
[/li][li]Luftfeuchtigkeit
[/li][li]Luftdruck
[/li][li]Batteriespannung
[/li][li]Solarzellen-Spannung
[/li][li]Fehler
[/li][/ul]
Diese Variablen werden dann auch geloggt wenn man das aktiviert hat.
Eigentlich sollte das noch nicht online gehen weil die Doku noch nicht fertig ist aber beim Update für Symcon 5.5 war es heimlich dabei ![]()
Moin,
ich nutze folgenden Decoder:
https://github.com/Alpha-Omega-Technology/ttn-klax
Bei mir wird nichts automatisch angelegt, dafür bekomme ich, aber folgenden Fehler:
21.09.2020, 06:02:03 | FlowHandler | Kann Daten nicht zur Instanz #38498 weiterleiten: <br />
<b>Fatal error</b>: Uncaught Error: Object of class stdClass could not be converted to string in C:\ProgramData\Symcon\modules\.store\firebuster.thethingsnetwork\TtnObjectDevice\module.php:113
Stack trace:
#0 C:\Windows\System32\-(3): TtnObjectDevice->ReceiveData('{"DataID":"{474...')
#1 {main}
thrown in <b>C:\ProgramData\Symcon\modules\.store\firebuster.thethingsnetwork\TtnObjectDevice\module.php</b> on line <b>113</b><br />
Die Instanz #38498 ist das „TTN Object Device“
Habe noch ein zweites Gerät angelegt, ein Tabs Door Sensor, da funktionierte das automatische Anlegen einwandfrei.
Eine weitere Frage habe ich aber auch noch, muss ich für jedes Gerät ein extra „TTN HTTP Integration Gateway“ anlegen?
Hein09
Also auf die Schnelle würde ich sagen der Decoder gibt keine Objekte aus sondern direkt die Variablen.
Ich schick dir mal meine Mail-Adresse.
Würde gerne mal sehen wie das in der Console aussieht und im Debug vom Symcon.
Eine HTTP Integration muss genau einmal angelegt werden.
Beim anschauen der Debug-Dateien sieht man, dass die Daten in mehreren Ebenen verschachtelt sind.
Das wird von der Instanz so zur Zeit nicht abgedeckt. Dies ist auch der erste Fall wo dieses Problem Auftritt.
Es gibt zwei Lösungsmöglichkeiten um damit umzugehen.
{
"header_batteryPerc":100,
"header_configured":true,
"header_connTest":false,
"header_deviceType":"SML Klax",
"header_meterType":"SML",
"header_version":1,
"msgInfo_msgCnt":1,
"msgInfo_msgIdx":176,
"msgInfo_msgNum“:1
..
Im Script rufst du das Payload-Feld ab und holst dir die Daten selbst raus:
$data = TTN_GetData(TTN_Object_Device_ID);
$header = $data->payload_fields->header;
$msgInfo = $data->payload_fields->msgInfo;
…
$batteryPerc = $header->batteryPerc;
...
Ich habe zum Modul ein eigenes Thema eröffnet.
Hier können spezielle Fragen zum Modul beantwortet werden.
Hallo, ich hoffe, ich sprenge den Rahmen dieses Threads nicht. Ich würde mich gerne mal etwas mit LORAWAN beschäftigen, hab aber dazu typische Einsteigerfragen:
Welches Gateway ist denn gerade „angesagt“? Es gibt so viele von 100 EUR bis 1000 EUR und ich sehe die Unterschiede gar nicht. Selbstbau mit IMST IC880a und Raspberry erscheint zumindest finanziell ja kein Vorteil mehr zu sein. Ich finde derzeit das MikroTik wAP LoRa8 kit ganz okay, da outdoor und mit 150EUR wohl halbwegs im Rahmen.
Ich verstehe die Reichweiten nicht: Angeblich hat das doch so eine enorme Reichweite bis 15km oder so, aber wenn ich auf den ttn-mapper schaue, reicht jeder Kreis höchstens 200m. Ich bin angeblich ca. 2km von einem Gateway entfernt, habe aber Null Empfang.
Vielleicht habt ihr ja den einen oder anderen Tip für mich. Was ich damit genau mache, weiß ich noch nicht - erster Versuch wäre, eine Datenverbindung vom 3.OG in den Keller aufzubauen.
Danke,
Tom
Zu 1
Ich bin auch ein Fan von den MikroTik wAP Lora8. Ein Selbstbau rentiert sich eher weniger. Ggf wenn man was passendes in der Bucht schießt.
Habe mal was zu verschiedenen Gateways und Antennen zusammen gefasst:
Gateway und Antennen
Zu 2.
LoRaWAN bietet trotz der geringen Sendeleistung eine beeindruckende Link-Margin. Das bedeutet ein Signal kann noch sehr schwach empfangen werden.
Die beste Funkverbindung hat man natürlich bei LOS (Line of Sight). Hier gibt es in der Praxis quasi keine Reichweitenbegrenzung. Problem ist, dass durch die Erdkrümmung dies nur bis zu einer bestimmten Entfernung erreicht werden kann.
Daher gilt es beim errichten eines Gateways möglichst hoch zu kommen.
Wenn ein Gateway auf einem Berg steht kann man somit ein ganzes Tal ausleuchten.
Auf einem hohen Gebäude kann man auch problemlos mehrere Kilometer weit kommen.
Im Innerstädtischen Bereich ohne exponierten Standort kommt man jedoch leider nur wenige hundert Meter weit (immer noch ein Vielfaches von dem, was man über WLAN erreicht).
Durch das 868MHz Band kommt man auch problemlos durch Wände oder in den Keller sofern ein Gateway in der Nähe ist.
Hier mal ein Beispiel für einen guten Standort und der Ausleuchtung
Danke, Timo. Das erklärt mir einiges! So ein 15€ ESP32-Selbstbaunode ersetzt wohl kein Gateway, aber wofür ist das?
Ein Gateway kann auf allen Kanälen mit unterschiedlichen Spreadingfaktoren gleichzeitig arbeiten. Durch Kombinationen daraus haben die Gateways dadurch typischerweise 49 Demodulatoren ![]()
Ein „Single Channel Gateway“ kann nur einen Kanal bei einem Spreadingfactor. Das will man einfach nicht haben ![]()
Das TTIG ist mit das kleinste vollwertige Gateway. Darin schlummert nur ein ESP8266/ESP32 aber ein vollwertiger LoRaWAN Empfänger.
Ich betreibe auch ein TTIG. Der „Anschluss“ ans TTN war recht einfach, aber…
die Reichweite.
Das Gateway ist natürlich für Indoor gedacht. Ich habe mal Versuche mit dem Lora-GPS-Modul von ELV gemacht. Enttäuschend.
Jetzt suche ich noch ein preiswertes Gateway, das ich auf dem Dach montieren will, habe aber das richtige noch nicht gefunden.
Das TTiG ist nicht schlecht.
Man kann die Antenne im inneren abmachen und via u.FL Pigtail eine externe Antenne anschließen. Diese dann mit einem kurzen und guten Kabel (H155) aufs Dach gelegt.
Als Antenne macht man mit der LoRaWAN Antenne von MikroTik auch nichts falsch.
Das TTiG ist eigentlich echt gut … natürlich nicht mit der internen Antenne und irgendwo im Gebäude …
Alternativ das MikroTik wAP Lora8. Aber hier am besten auch mit der externen Antenne.
Gute Idee. Das werde ich mal versuchen.
Aber hätte ich das Gehäuse schon ohne Beschädigung auf. ![]()
Ergänzung Öffnen bei 3:00
![]()
Hallo zusammen,
ich bin neu in der Symcon und Lora-Welt. Daher habt bitte etwas Geduld und Verständnis für mich. ![]()
Ich bin hier am experementieren mit einem Wasserzähler der Firma Sontex (dem Superaqua1). Es war schon ein Kampf genug den Payload-Formatter vom Hersteller zu bekommen. Doch dieser funktioniert leider nicht so wie gewollt, und der Hersteller ist leider hier nicht sehr kooperativ. Er meinte es handel sich um ein handelsübliches Lora-Produkt und wieso es in Symcon nicht funktioniert kann er nicht sagen da er nichts mit Symcon am Hut hat.
Im “The Things Stack” scheint es soooooweit zu funktionieren. Zwar werden mir im “Live data” in der Payload auch keine Werte angezeigt, aber er decodiert zumindest die “Variablen”. Wenn ich dann auf die Payload klicke dann sehe ich rechts das “Code-Fenster (Event details)” in dem alle Werte passend eingetragen sind.
Ich verwende in Symcon das TTN-Modul von “Timo-u.de”
Leider werden hier nicht alle Variablen automatisch erzeugt. Gerade das wichtigste (der aktuelle Zählerstand) fehlt leider.
Ich bin leider auch kein Programmierer
so fällt es mir hier leider schwer den Fehler zu finden.
Vielleicht hat ja von euch einer Mitleid mit mir und kann mir hier auf die Sprünge helfen.
Ich habe mal den Decoder den ich vom Hersteller erhalten habe unten angefügt, da ich als neuer Nutzer leider keine Anhänge hochladen darf ![]()
Ich danke euch schon mal recht herzlich und hoffe dass ich es einigermaßen verständlich beschreiben konnte und mir irgendjemand hier helfen kann.
Denn der Wasserzähler würde ansonsten genau dem entsprechen was ich suche. Wäre schade wenn es an so einer “Kleinigkeit” scheitern würde. ![]()
Beste Grüße
Manuel
Ab hier die Datei des Herstellers:
/*
/ __
| | | | _
| | || ____ _ ___ / | ___ __ __
\ \ / __ \ | /__ \ | | / _ \ \ \ / /
\ \ | | | | | / | | | | | | | | \ V /
\ \ | | | | | | | | | | | || | \ /
\ \ | | | | | | | | | | | | X
_ \ \ | | | | | | | | | | | | _ /
| | | | | || | | | | | | | | || | / ^
| |__| |
Your link to innovative metering
Copyright (c) 2024 Sontex SA
File: ParserSQ1.js
Version: 1.2
Description:
This js script parses the SQ1 M-Bus LoRaWAN frames to make it readable.
Usage :
This parser is specially done to work with The Things Stack.
Usage example :
input = {
„bytes“: [
4,6,0,0,0,0,4,20,0,0,0,0,12,120,64,102,136,38,4,109,22,14,173,44,2,255,44,0,0,132,16,6,0,0,0,0,130,10,108,
225,241,132,10,6,0,0,0,0,132,10,20,0,0,0,0,2,89,32,10,2,93,42,10,2,59,0,0,3,44,0,0,127,132,26,6,255,0,0,0
],„fPort“: 2};
console.log(decodeUplink(input));
*/
// Initialize global variable names
var fraud_manipulation;
var pipe_break;
var leakage;
var qmax;
var backward_flow;
var zero_flow;
var device_end_of_legal_life;
var error_flag_last_60_days;
var application_error_unknown_field_c;
var application_error_unknown_field_ci;
var application_error_unknown_record;
var application_error_access_right;
var application_error_record_size;
var application_error_record_value;
var application_error_bad_password;
var no_error_flags;
var volumeTotalizer;
var fabricationNumber;
var currentDateAndTime;
var daylightSavingTime;
var dateAndTimeValid;
var detailedErrors;
var setDay;
var volumeTotalizerAtSetDay;
var commissioningDay;
var internalVersion;
var volumeAtHourMinus1;
var volumeAtHourMinus2;
var volumeAtHourMinus3;
var volumeAtHourMinus4;
var decoded = {};
// Supported languages: raw, en, de
var language = „raw“;
// Defines if units are appended directly to the value:
// 42 kWh
// or stored in an object:
// { value: 42, unit: kWh }
var appendUnits = false;
function decodeUplink(input) {
// set the language of the output result default is english if no language is not set
setLanguage(language);
var bytes = input.bytes
for (var i = 0; i < bytes.length;) {
var identifier = bytes[i++];
var dataBytes = ;
var unit = „“;
var multiplier = 1;
var toFixedDigits = 0;
var byte = 0x00;
switch (identifier) {
case 0x78:
// console.debug(„Detected headless MBus frame“);
break;
case 0x04:
byte = bytes[i++];
dataBytes.push(bytes[i++]);
dataBytes.push(bytes[i++]);
dataBytes.push(bytes[i++]);
dataBytes.push(bytes[i++]);
if (byte === 0x6D) {
decoded[currentDateAndTime] = formatUnit(getValueCodingF(dataBytes), unit);
}
break;
case 0x0C:
var key = bytes[i++];
switch (key) {
case 0x78:
dataBytes.push(bytes[i++]);
dataBytes.push(bytes[i++]);
dataBytes.push(bytes[i++]);
dataBytes.push(bytes[i++]);
decoded[fabricationNumber] = formatUnit((getValueCodingA(dataBytes) * multiplier), unit);
break;
case 0x13:
dataBytes.push(bytes[i++]);
dataBytes.push(bytes[i++]);
dataBytes.push(bytes[i++]);
dataBytes.push(bytes[i++]);
unit = getUnit(key);
multiplier = getMultiplier(key);
toFixedDigits = getNumberOfDigits(multiplier);
decoded[volumeTotalizer] = formatUnit((getValueCodingA(dataBytes) * multiplier), unit);
break;
}
break;
case 0x02:
byte = bytes[i++];
var byte2 = bytes[i++];
if (byte === 0xFD && byte2 === 0x17) {
dataBytes.push(bytes[i++]);
dataBytes.push(bytes[i++]);
decoded[detailedErrors] = getErrorFlags(dataBytes);
}
break;
case 0x82:
byte = bytes[i++];
var byte2 = bytes[i++];
if (byte === 0x20 && byte2 === 0x6C) {
dataBytes.push(bytes[i++]);
dataBytes.push(bytes[i++]);
decoded[commissioningDay] = formatUnit(getValueCodingG(dataBytes), unit);
}
break;
case 0x42:
byte = bytes[i++];
if (byte === 0x20) {
dataBytes.push(bytes[i++]);
dataBytes.push(bytes[i++]);
decoded[setDay] = formatUnit(getValueCodingG(dataBytes), unit);
}
break;
case 0x4C:
key = bytes[i++];
if (key === 0x13) {
dataBytes.push(bytes[i++]);
dataBytes.push(bytes[i++]);
dataBytes.push(bytes[i++]);
dataBytes.push(bytes[i++]);
unit = getUnit(key);
multiplier = getMultiplier(key);
toFixedDigits = getNumberOfDigits(multiplier);
decoded[volumeTotalizerAtSetDay] = formatUnit((getValueCodingA(dataBytes) * multiplier), unit);
}
break;
case 0xCC:
byte = bytes[i++];
key = bytes[i++];
if (key === 0x13) {
dataBytes.push(bytes[i++]);
dataBytes.push(bytes[i++]);
dataBytes.push(bytes[i++]);
dataBytes.push(bytes[i++]);
unit = getUnit(key);
multiplier = getMultiplier(key);
toFixedDigits = getNumberOfDigits(multiplier);
switch (byte) {
case 0x0C:
decoded[volumeAtHourMinus1] = formatUnit((getValueCodingA(dataBytes) * multiplier), unit);
break;
case 0x0D:
decoded[volumeAtHourMinus3] = formatUnit((getValueCodingA(dataBytes) * multiplier), unit);
break;
}
}
break;
case 0x8C:
byte = bytes[i++];
key = bytes[i++];
if (key === 0x13) {
dataBytes.push(bytes[i++]);
dataBytes.push(bytes[i++]);
dataBytes.push(bytes[i++]);
dataBytes.push(bytes[i++]);
unit = getUnit(key);
multiplier = getMultiplier(key);
toFixedDigits = getNumberOfDigits(multiplier);
switch (byte) {
case 0x0D:
decoded[volumeAtHourMinus2] = formatUnit((getValueCodingA(dataBytes) * multiplier), unit);
break;
case 0x0E:
decoded[volumeAtHourMinus4] = formatUnit((getValueCodingA(dataBytes) * multiplier), unit);
break;
}
}
break;
case 0x0B:
byte = bytes[i++];
var byte2 = bytes[i++];
if (byte === 0xFD && byte2 === 0x0F) {
dataBytes.push(bytes[i++]);
dataBytes.push(bytes[i++]);
dataBytes.push(bytes[i++]);
decoded[internalVersion] = formatUnit((getValueCodingA(dataBytes) * multiplier), unit);
}
break;
}
}
return {
data: decoded
};
}
function getNumberOfDigits(multiplier) {
switch (multiplier) {
case 1:
return 0;
case 0.1:
return 1;
case 0.01:
return 2;
case 0.001:
return 3;
}
}
function getMultiplier(key) {
switch (key) {
case 0x05: // 0.1 kWh
case 0x15: // 0.1 m³
return 0.1;
case 0x06: // 1 kWh
case 0x0E: // 1 MJ
case 0x16: // 1 m³
case 0xFD: // 1 without unit
return 1;
case 0x07: // 0.01 MWh
case 0x0F: // 0.01 GJ
case 0x14: // 0.01 m³
return 0.01;
case 0x13: // 0.001 m³ or
return 0.001;
}
}
function getUnit(key) {
switch (key) {
case 0x05: // 0.1 kWh
case 0x06: // 1 kWh
return " kWh";
case 0x07: // 0.01 MWh
return " MWh";
case 0x0E: // 1 MJ
return " MJ";
case 0x0F: // 0.01 GJ
return " GJ";
case 0x13: // 0.001 m³
case 0x14: // 0.01 m³
case 0x15: // 0.1 m³
case 0x16: // 1 m³
return " m³";
case 0xFD: // 1 without unit
return „“;
}
}
function getValueCodingA(bytes) {
var binary = getBinaryString(bytes);
var i = 7;
var number = 0;
for (var n = 0; n <= i; n++) {
var currentDigit = 8 * binary.charAt(n * 4) + 4 * binary.charAt(n * 4 + 1)
function getValueCodingB(bytes) {
var binary = getBinaryString(bytes);
var i = binary.length - 1;
var m = 0;
for (var n = 1; n < binary.length; n++) {
var currentBit = parseInt(binary.charAt(n));
m += Math.pow(2, i - n) * currentBit;
}
if (binary.charAt(0) === „1“) m = m - Math.pow(2, i);
var floor = -Math.pow(2, i);
if (m < floor) m = floor;
var ceiling = Math.pow(2, i) - 1;
if (m > ceiling) m = ceiling;
return m;
}
function getValueCodingF(bytes) {
var binary = getBinaryString(bytes);
calculateDate(binary);
var dateString = calculateDate(binary);
var hour = parseInt(binary.charAt(19)) * 16 + parseInt(binary.charAt(20)) * 8
function getValueCodingG(bytes) {
var binary = getBinaryString(bytes);
return calculateDate(binary);
}
function calculateDate(binary) {
var year = parseInt(binary.charAt(0)) * 64 + parseInt(binary.charAt(1)) * 32
function getErrorFlags(bytes) {
// getBinaryString returns string as it would be printed out, bit0 is at the
// last position. The string is therefore first reversed so that character positions
// match directly the bit positions in the documentation.
var binary = getBinaryString(bytes).split(„“).reverse().join(„“);
var flags = ;
// bit15 not used
if (binary.charAt(14) === „1“) flags.push(error_flag_last_60_days);
if (binary.charAt(13) === „1“) flags.push(device_end_of_legal_life);
if (binary.charAt(12) === „1“) flags.push(zero_flow);
if (binary.charAt(11) === „1“) flags.push(backward_flow);
if (binary.charAt(10) === „1“) flags.push(qmax);
if (binary.charAt(9) === „1“) flags.push(leakage);
if (binary.charAt(8) === „1“) flags.push(pipe_break);
if (binary.charAt(7) === „1“) flags.push(fraud_manipulation);
if (binary.charAt(6) === „1“) flags.push(application_error_bad_password);
if (binary.charAt(5) === „1“) flags.push(application_error_record_value);
if (binary.charAt(4) === „1“) flags.push(application_error_record_size);
if (binary.charAt(3) === „1“) flags.push(application_error_access_right);
if (binary.charAt(2) === „1“) flags.push(application_error_unknown_record);
if (binary.charAt(1) === „1“) flags.push(application_error_unknown_field_ci);
if (binary.charAt(0) === „1“) flags.push(application_error_unknown_field_c);
if (flags === ) {
flags.push(no_error_flags);
}
return flags;
}
function convertToBinary(value) {
var binary = value.toString(2);
if (binary.length < 8) {
var missingBits = 8 - binary.length;
for (var i = 0; i < missingBits; i++) {
binary = „0“ + binary;
}
}
return binary;
}
function getBinaryString(bytes) {
var binary = „“;
for (var i = 0; i < bytes.length; i++) {
binary += convertToBinary(bytes[i]);
}
if (binary.length < 9) {
return binary;
} else if (binary.length < 17) {
var first = binary.substring(binary.length / 2, binary.length);
var second = binary.substring(0, binary.length / 2);
binary = first + second;
} else if (binary.length < 25) {
var first = binary.substring(0, binary.length / 3);
var second = binary.substring(binary.length / 3, binary.length);
var first1 = second.substring(second.length / 2, second.length);
var second1 = second.substring(0, second.length / 2);
binary = first1 + second1 + first;
} else if (binary.length === 32) {
var first = binary.substring(binary.length / 2, binary.length);
var second = binary.substring(0, binary.length / 2);
var first1 = first.substring(first.length / 2, first.length);
var second1 = first.substring(0, first.length / 2);
var first2 = second.substring(second.length / 2, second.length);
var second2 = second.substring(0, second.length / 2);
binary = first1 + second1 + first2 + second2;
}
return binary;
}
// Append unit or create object containing value and unit
// depending if appendUnits is true/false
function formatUnit(v, u) {
if (appendUnits) {
if (u) {
return v + „“ + u;
} else {
return v;
}
} else {
return {
value: v,
unit: u.trim()
};
}
}
/*
Set the language of the output result function.
language values :
en : return the results in english
de : return the results in german
raw : return the results in english, all lowercase without special characters, only a-z and _
optimized for further processing with tago.io
*/
function setLanguage(language) {
if (language === „de“) {
fraud_manipulation = „Manipulation“;
pipe_break = „Rohrbruch“;
leakage = „Leck“;
qmax = „Maximaler Volumenstrom“;
backward_flow = „Rückfluss“;
zero_flow = „Kein Druchfluss“;
device_end_of_legal_life = „Zulässige Lebensdauer überschritten“;
error_flag_last_60_days = „Fehler in den letzten 60 Tagen“;
application_error_unknown_field_c = „application_error_unknown_field_c“;
application_error_unknown_field_ci = „application_error_unknown_field_ci“;
application_error_unknown_record = „application_error_unknown_record“;
application_error_access_right = „Keine Zugriffsrechte vorhanden“;
application_error_record_size = „application_error_record_size“;
application_error_record_value = „application_error_record_value“;
application_error_bad_password = „Falsches Passwort“;
no_error_flags = „Keine Fehler vorhanden“;
volumeTotalizer = "Volumen";
fabricationNumber = "Fabrikationsnummer";
currentDateAndTime = "Datum und Zeit";
daylightSavingTime = "Sommerzeit";
dateAndTimeValid = "Datum und Zeit valide";
detailedErrors = "Fehlermeldungen";
setDay = "Stichtag";
volumeTotalizerAtSetDay = "Volumen zum Stichtag";
commissioningDay = "Installationsdatum";
internalVersion = "Version";
volumeAtHourMinus1 = "Volumen zur vollen Stunde - 1";
volumeAtHourMinus2 = "Volumen zur vollen Stunde - 2";
volumeAtHourMinus3 = "Volumen zur vollen Stunde - 3";
volumeAtHourMinus4 = "Volumen zur vollen Stunde - 4";
}
if (language === "en") {
fraud_manipulation = "Fraud / Manipulation";
pipe_break = "Pipe break";
leakage = "Leakage";
qmax = "Max. flow";
backward_flow = "Backward flow";
zero_flow = "Zero flow";
device_end_of_legal_life = "End of life";
error_flag_last_60_days = "Error in the last 60 days";
application_error_unknown_field_c = "application_error_unknown_field_c";
application_error_unknown_field_ci = "application_error_unknown_field_ci";
application_error_unknown_record = "application_error_unknown_record";
application_error_access_right = "No access rights available";
application_error_record_size = "application_error_record_size";
application_error_record_value = "application_error_record_value";
application_error_bad_password = "Bad password";
no_error_flags = "No errors present";
volumeTotalizer = "Volume";
fabricationNumber = "Fabrication number";
currentDateAndTime = "Date and time";
daylightSavingTime = "Daylight saving time";
dateAndTimeValid = "Valid Date and time";
detailedErrors = "Detailed errors";
setDay = "Target day";
volumeTotalizerAtSetDay = "Volume totalizer at target day";
commissioningDay = "Commissioning date";
internalVersion = "Version";
volumeAtHourMinus1 = "Volume on the hour - 1";
volumeAtHourMinus2 = "Volume on the hour - 2";
volumeAtHourMinus3 = "Volume on the hour - 3";
volumeAtHourMinus4 = "Volume on the hour - 4";
}
if (language === "raw") {
fraud_manipulation = "fraud_manipulation";
pipe_break = "pipe_break";
leakage = "leakage";
qmax = "qmax";
backward_flow = "backward_flow";
zero_flow = "zero_flow";
device_end_of_legal_life = "device_end_of_legal_life";
error_flag_last_60_days = "error_flag_last_60_days";
application_error_unknown_field_c = "application_error_unknown_field_c";
application_error_unknown_field_ci = "application_error_unknown_field_ci";
application_error_unknown_record = "application_error_unknown_record";
application_error_access_right = "application_error_access_right";
application_error_record_size = "application_error_record_size";
application_error_record_value = "application_error_record_value";
application_error_bad_password = "application_error_bad_password";
no_error_flags = "no_error_flags";
volumeTotalizer = "volume_totalizer";
fabricationNumber = "fabrication_number";
currentDateAndTime = "current_date_and_time";
daylightSavingTime = "daylight_saving_time";
dateAndTimeValid = "date_and_time_valid";
detailedErrors = "detailed_errors";
setDay = "ser_day";
volumeTotalizerAtSetDay = "volume_totalizer_at_set_day";
commissioningDay = "commissioning_day";
internalVersion = "internal_version";
volumeAtHourMinus1 = "volume_at_hour_minus_1";
volumeAtHourMinus2 = "volume_at_hour_minus_2";
volumeAtHourMinus3 = "volume_at_hour_minus_3";
volumeAtHourMinus4 = "volume_at_hour_minus_4";
}
}
Wenn dort nichts angezeigt wird, dann kommen auch keine Daten. Somit kann in IP-Symcon erst einmal auch nichts angezeigt werden.
Wahrscheinlich, weil es keine Daten sendet.
Grundsätzlich heißt es erst einmal, das Gerät vernünftig einzurichten, sodass du es im TTN siehst und dort Werte empfängst.
Die grundsätzliche Einrichtung mit DevEUI, JoinEUI und Appkey im TTN ist abgeschlossen? Hier scheint mir schon irgendwas schiefgelaufen zu sein, wenn du unter LiveData nichts empfängst.
Was für ein Gateway nutzt du bzw ist sichergestellt, dass du dich innerhalb der Reichweite eines Gateways befindest?
Hallo,
erstmal Danke für die schnelle Hilfestellung.
Vieleicht habe ich es oben nicht richtig formuliert. Ich versuche es nochmals. Sorry ich bin wie gesagt in dem Bereich leider Neuling. ![]()
in TTS “Live data” werden die Variablen/Texte/Kategorien (Datum, Zeit, Zählerstand, …) decodiert und angezeigt jedoch werden die entsprechenden Werte dahinter nicht angezeigt. Wie z.B. der Zählerstand. In dem Feld in dem z.B. der Zahlenwert für den Zählerstand stehen sollte steht nichts.
Wenn ich nun auf die Payload in “Live data” klicke, dann geht rechts ein Fenster auf mit einer “Codeansicht” in dem alle Variablen/Texte/Kategorien (Datum, Zeit, Zählerstand, …) mit jeweils den richtigen Werten darunter dargestellt werden.
Für mich sieht es so aus als würde der Payload-Formatter an sich schon funktionieren und der Wasserzähler richtig angelegt sein. Sonst würde ich ja im TTS keinen Zählerstand etc. in dieser “Codeansicht” sehen können.
Nutze ich nun in Symcon das TTN Modul und integriere den Wasserzähler, so erstellt er mir leider nicht alle Variablen/Texte/Kategorien (Datum, Zeit, Zählerstand, …). Sondern nur einen Teil davon.
Gerade die wichtigste Angabe, der Zählerstand, fehlt leider.
Als Gateway nutze ich ein “SenseCAP M2”. Über dieses Gateway läuft das Ganze. Ansonsten ist leider kein LoRaWAN Gateway in der Nähe.
Ich habe zudem noch einen Dragino PS-LB-NA (Wasser-Pegelmessung) im System. Dieser funktioniert in TTS und Symcon einwandfrei.
Ich freue mich von euch zu hören.
Beste Grüße an die Community
Manuel
Hier scheint es sich um ein Problem mit dem Decoder zu handeln.
Der Payload-Decoder muss die Werte in der obersten Ebene bereit stellen. Dann kann das Symcon-Modul die automatisch parsen.
Du kannst mit das Gerät/die Applikation in TTN mal freigeben dann kann ich da mal draufschauen ![]()
(PN)
Das Problem lag am Payload-Decoder.
Habe ihn mal so umgeschrieben, dass es problemlos laufen sollte ![]()