Good morning,
I am looking for a TTN decoder for the ZENNER EASY PROTECT radio.
Unfortunately I am not so well versed that I can create this asu the instructions myself.
I’ve found 2 on the net, but unfortunately they don’t work for me.
Does anyone have this in operation and a working decoder to hand that I can use?
Thanks
I use this one:
/*
- studierendenwerk-ulm/payload-decoder-zenner-easy-protect-radio-lora/master/decoder.js
*/
/**
-
Main decoder function
-
@param bytes
-
@param port
-
@constructor
/
function Decoder(bytes, port) {
if(bytes === null || bytes === 0){
//obj.port = port;
obj.status_dedcoded = false;
obj.status_info = "payload_raw: " + payloadRawHexToString(bytes);
} else {
// Definition of head line daily value.
/ let S_SMOKE_CHAMBER_POLLUTION_PREWARNING = 0x0800;
let S_SMOKE_CHAMBER_POLLUTION_WARNING = 0x1000;
let S_TEST_BUTTON_FAILUER = 0x2000;
let S_ACCUSTIC_ALARM_FAILUER = 0x4000;
let S_REMOVAL_DETECTION = 0x8000;
let S_TEST_ALARM = 0x0001;
let S_SMOKE_ALARM = 0x0002;
let S_OBSTRUCTION_DETECTION = 0x0004;
let S_SURROUNDING_AREA_MONITORING = 0x0008;
let S_LED_FAILURE = 0x0010;*/// Definition of the different packet types and subtypes. var TYPE_SP1 = 0x1; //sent daily -> packet, max. 2 retransmissions var TYPE_SP9 = 0x9; // Sent immediately after first activation and from then on every 6 months -> No retransmissions var SUBTYPE_SP9_1 = 0x01; // sent every month except the month of first activation -> No retransmissions var SUBTYPE_SP9_2 = 0x02; // sent immediately after first activation and from then on every 6 months -> No retransmissions var TYPE_AP1 = 0xA; // (status code, status data): event based -> Max 5 AP packets per month, no retransmissions // Device specific status summery definition var A_REMOVAL = 0x02; var A_BATTERY_END_OF_LIFE = 0x0C; var A_HORN_DRIVE_LEVEL_FAILURE = 0x16; var A_OBSTRUCTION_DETECTION = 0x1A; var A_OBJECT_IN_THE_SURROUNDING_AREA = 0x1C; var AP_VALUES = ["removal", "battery end of life", "horn drive level failure", "obstruction detection", "object in the surrounding area"]; var S_STATUS_SUMMERY_VALUES = ["removal", "0", "battery end of life", "acoustic alarm failure", "obstruction detection", "surrounding area monitoring"]; var obj = {}; obj.port = port; switch (bytes[0] >> 4) { case TYPE_SP1: //const casePosition = "SP1"; obj.packet_type = 1; obj.packet_subtype = 0; obj.packet_type_info = "synchronous"; //obj.status_interpretation = null; obj.status_dedcoded = false; obj.status_info = "payload_raw: " + payloadRawHexToString(bytes); //obj.decodingTree = [casePosition]; break; case TYPE_SP9: obj.packet_type = 9; obj.packet_type_info = "synchronous"; obj.status_dedcoded = false; // check for packet subtype SP9.1 and SP9.2 switch (bytes[0] & 0x0F) { case SUBTYPE_SP9_1: obj.packet_subtype = 1; obj.dateTime = decodeDateAndTime(((bytes[1] << 24) | (bytes[2] << 16) | (bytes[3] << 8) | (bytes[4]))); //TODO make a function to check is the device in correct dateAndTime obj.status_interpretation = buildStatusSummery(bytes[5], bytes[6], S_STATUS_SUMMERY_VALUES); obj.status_dedcoded = true; obj.status_info = "payload_raw: " + payloadRawHexToString(bytes); break; case SUBTYPE_SP9_2: obj.packet_subtype = 2; obj.status_interpretation = [ "firmware version: " + ( ((bytes[1] << 24) + (bytes[2] << 16) + (bytes[3] << 8) + (bytes[4])) .toString(16)).toUpperCase(), "LoRa WAN version: " + (bytes[5]).toString(16) + "." + (bytes[6]) .toString(16) + "." + (bytes[7]).toString(16), "LoRa command version: " + (bytes[9]).toString(16) + "." + (bytes[8]).toString(16), "device type: " + (bytes[10]).toString(16), "meter ID: " + (((bytes[11] << 24) + (bytes[12] << 16) + (bytes[13] << 8) + (bytes[14])) .toString(16)).toUpperCase() ]; obj.status_dedcoded = true; obj.status_info = "payload_raw: " + payloadRawHexToString(bytes); break; default: obj.status_dedcoded = false; obj.status_info = "payload_raw: " + payloadRawHexToString(bytes); break; } break; case TYPE_AP1: obj.packet_type = 1; obj.packet_subtype = 0; obj.packet_type_info = "asynchronous"; obj.date = (decodeDate(bytes [3] << 8 | bytes[4])); obj.status_interpretation = null; obj.status_dedcoded = false; obj.status_info = null; obj.status_info = "payload_raw: " + payloadRawHexToString(bytes); switch (bytes[1]) { case A_REMOVAL: obj.status_interpretation = AP_VALUES[0]; obj.status_dedcoded = true; break; case A_BATTERY_END_OF_LIFE: obj.status_interpretation = AP_VALUES[1]; obj.status_dedcoded = true; break; case A_HORN_DRIVE_LEVEL_FAILURE: obj.status_interpretation = AP_VALUES[2]; obj.status_dedcoded = true; break; case A_OBSTRUCTION_DETECTION: obj.status_interpretation = AP_VALUES[3]; obj.status_dedcoded = true; break; case A_OBJECT_IN_THE_SURROUNDING_AREA: obj.status_interpretation = AP_VALUES[4]; obj.status_dedcoded = true; break; default: obj.status_info = "payload_raw: " + payloadRawHexToString(bytes); break; } break; default: obj.status_dedcoded = false; obj.status_info = "payload_raw: " + payloadRawHexToString(bytes); break; }
}
return obj;
}
/**
- decodes date (EN13757-3:2013, Annex A, data type G).
- input: int, lower two bytes interpreted.
- output: date string YYYY-MM-DD.
- @param bytes
-
@returns {string}
*/
function decodeDate(bytes) {
//TODO Handling errors with 0xFF see LoRa radio packet definitions page 15
var day = (bytes & 0x1F00) >> 8;
var month = (bytes & 0x000F);
var year = ((bytes & 0xE000) >> 10) | ((bytes & 0x00F0) >> 4);
return “20” + year.toString() + “-” + month.toString() + “-” + day.toString();
}
/**
- Date and time format.
- Date&Time stamp coding according to EN13757-3:2013, Annex A, data type F
- @param bytes
-
@returns {string}
*/
function decodeDateAndTime(bytes) {
var minute = (bytes & 0x3F000000) >> 24;
var hour = (bytes & 0x001F0000) >> 16;
var day = (bytes & 0x00001F00) >> 8;
var month = (bytes & 0x0000000F);
var year = ((bytes & 0x0000E000) >> 10) | ((bytes & 0x000000F0) >> 4);
return “20” + year.toString() + “-”
+ month.toString() + “-”
+ day.toString() + “T”
+ hour.toString() + “:”
+ minute.toString()
+ “:00Z”;
}
/**
*
- @param byteArray
-
@returns {string}
*/
function payloadRawHexToString(byteArray) {
var str;
if(byteArray === null){
return “00”;
}else {
str = byteArray.map(function (byte) {
return (‘0’ + (byte & 0xFF).toString(16)).slice(-2);
}).join(‘’);
var strArray = str.match(/.{2}/g);
str = strArray.map(function (value, index, array) {
return array[index];
});
var x = str.join();
return x.replace(/([,])/g, " ").toLocaleUpperCase();
}
}
/**
-
Build the summary for package 9.1.
-
@param a
-
@param b
-
@param S_STATUS_SUMMERY_VALUES
-
@returns {}
*/
function buildStatusSummery(a, b,S_STATUS_SUMMERY_VALUES) {var bin1 = parseInt(a.toString(), 16).toString(2);
var bin2 = parseInt(b.toString(), 16).toString(2);
var result = ;for (var i = 0; i < bin1.length; i++) {
console.log(bin1.length);
if (bin1[i] === “1”) {
result.push(S_STATUS_SUMMERY_VALUES[i]);
}
}for (var j = 0; j < bin2.length; j++) {
if (bin2[i] === “1”) {
result.push(S_STATUS_SUMMERY_VALUES[j]);
}
}return result;
}
But I do not get the data correcly into Datacake…as I do not have the knowledge of java, databases and decoding the info
Can you please the complete payload in code.
I can not copy it.
THX
Hi ,
how do I do that…?
Marc
Write in a File und Upload here.
This is the best way.
Hello,
Unfortunately I only got around to testing now.
But the payload only brings me:
Decode uplink data message failure
Just an update on this old thread, my ZENNER devices seem to work fine with TTN and I just share my experience here:
- I bought 8 of the Zenner Easy Protect Radio LoRaWAN directly from here:
ZENNER LoRaWAN® Rauchwarnmelder EASY PROTECT RADIO - On the delivery note (only the paper version in the parcel!), I automatically received a password for a portal website where I can see and download meta data including the EUIs, AppKey, FW-Version, LoRaWan version, etc.
- As soon as I mounted the devices on the base plate, the devices turned on and I was able to join the devices to TTN via OTAA.
- As payload formatter I use: loracodede/lorawan_payload_decoder: This project provides a collection of LoRaWAN payload decoders designed to interpret and transform data transmitted over the LoRaWAN (Long Range Wide Area Network) into a human-readable format. The decoder facilitates the integration of LoRaWAN into various applications. - Codeberg.org
- Every night the devices send a status message. If I remove a device it sends an “Alert” status message before it turns off. I did not test any other alert type yet.