Codec Decoder for zelsius C5 IUF

Hi everyone,

I’m struggling to create a working codec for the Zelsius C5-IUF device. I’ve received files from Zenner Support and attempted to write code using AI, but the output is incorrect. As I’m new to this, I would greatly appreciate any help in creating the correct code.

Please email me at eldionadvantx@gmail.com, and I’ll send the PDF files as I can’t upload them here.

The protocol is confidential? You can’t post it here? I didn’t find their protocol in their website.

No it’s not confidential but you have to reach to them to get it, and they only gave me the instruction documents but the files can’t be uploaded to this conversation.

Post the relevant details or upload it to a service (example). Split the url if the forum does not allow you to submit a URL.

here is the link for the files LoRa C5-IUF - Google Drive

Oh! That is absurd. Timestamp in the payload, CRC in the payload, there is 14 (?) variations of payload and I don’t understand the payloads. That’s what a I call a nightmare.

I would admire the person that would be able to write a decoder for that.

And the worst part is that they only sent the two attached files, claiming they couldn’t provide further assistance. They said the files contained all the necessary information to build the decoder, but after two weeks of unsuccessful attempts, I’m still not been able to get value readings.

The only solution is to try to decode the examples locally with node.

This is the ‘master file’ with the payloads. Name it launch_decoder.js

// Trick from: https://stackoverflow.com/a/5809968
var fs = require('fs');
eval(fs.readFileSync("decoder.js")+'');

data = [ 0x02, 0x78, 0x87 ];
input = { fPort:"207", bytes:data };
var result = decodeUplink(input);
console.log(result);

data = [ 0x01, 0x05 ];
input = { fPort:"200", bytes:data };
var result = decodeUplink(input);
console.log(result);

data = [ 0x44, 0x5D, 0x64, 0x06, 0x12, 0x5D, 0x02, 0xAC, 0x02, 0x08, 0x59 ];
input = { fPort:"204", bytes:data };
var result = decodeUplink(input);
console.log(result);

data = [0x39, 0xc0, 0xdd, 0x10, 0x59, 0xf4, 0x00, 0x6b, 0x02, 0x65, 0x90]; 
input = { fPort:"204", bytes:data };
var result = decodeUplink(input);
console.log(result);

This is the decoder. Name it decoder.js

// https://forum.chirpstack.io/t/decoder-testing/10619/7

// Decode decodes an array of bytes into an object.
//  - fPort contains the LoRaWAN fPort number
//  - bytes is an array of bytes, e.g. [225, 230, 255, 0]
// The function must return an object, e.g. {"temperature": 22.5}

function decodeUplink(input) {
	// return raw un-encrypted payload
//  return { data: input };

/*
44 5D 64 06 12 5D 02 AC 02 08 59
445D6406125D02AC020859
"alt": 684,
"battery": "59",
"lat": "48.069016,
"lon": "8.538374",
"temp": 20.8
*/
  var decoded = {};

  if ( input.fPort == 204){
    lat = input.bytes[0] << 16;
    lat |= input.bytes[1] << 8;
    lat |= input.bytes[2];
    lat = lat/8388606 * 90;
    if (lat > 90) lat -= 180;
    decoded.latitude = lat.toFixed(6);
    
    lon = input.bytes[3] << 16;
    lon |= input.bytes[4] << 8;
    lon |= input.bytes[5];
    lon = lon/8388606 * 180;
    if (lat > 180) lon -= 360;
    decoded.longitude = lon.toFixed(6);
    
alt = input.bytes[6] << 8;
alt |= input.bytes[7];
    decoded.altitude = alt;
    
    temp = (input.bytes[8] & 0x0F) * 100;
    temp += ((input.bytes[9] & 0xF0) >> 4 ) * 10;
    temp += input.bytes[9] & 0x0F;
    
    if( input.bytes[8] & 80)
      temp /= -10;
    else
      temp /= 10;
    decoded.temp = temp;
    
    bat = ((input.bytes[10] & 0xF0) >> 4) * 10;
    bat += input.bytes[10] & 0x0F;
    decoded.battery = bat;
    decoded.accuracy = 10;
  } 
  else
    if (input.fPort == 207 || input.fPort == 205){
      temp = (input.bytes[0] & 0x0F) * 100;
      temp += ((input.bytes[1] & 0xF0) >> 4 ) * 10;
      temp += input.bytes[1] & 0x0F;
      
      if( input.bytes[0] & 80)
        temp /= -10;
      else
        temp /= 10;
      decoded.temp = temp;
      
      bat = ((input.bytes[2] & 0xF0) >> 4) * 10;
      bat += input.bytes[2] & 0x0F;
      decoded.battery = bat;
    }
  // if port 200 or 208 two bytes firmware version 0103 = 1.0.3 //
   else
    if (input.fPort == 200 || input.fPort == 208){
      if ( input.bytes[1] < 10 )
      decoded.firmware =  input.bytes[0] + ".0." + input.bytes[1]
      else
      decoded.firmware =  input.bytes[0] + "." + input.bytes[1] << 4; + "." + input.bytes[1];
    }

  return decoded;

}// function 

Run node launch_decoder.js to see the results.

Put in the data the data from examples and try to have the same results with the decoder.js.

If I understood correctly, they use the first byte to identify the type (and subtype) of the message instead of LoRaWAN port.

You have interest on all types of messages? What types of messages you receiving? (SP0 to SP13) or and AP1 and AP2?

Try to have success with one type to feel powerful and proceed.

it would be good if i could recive daily and monthly expenses and temperature values i belive are SP5, I’m currenlty have the device in diagnostic mode and sends SP01

How you know it’s SP01? From the first byte? Next 4 bytes seems to have the payload of SP01. Problem is that I can’t understand what kind of payload is and if it’s need decoding or it’s a value ready to use.

‘‘In diagnostic mode, in addition to the scenario 1 or scenario 2 packets special
diagnostic mode packets (SP 0.1) are sent.’’ It says this in documentation.

I repeat. How do you know it’s in SP01 mode? From the first byte?

So, this it the payload?

no. of Bytes content remark
0,5 packet type 0x00
0,5 packet subtype 0x01
4 Heating energy For a pure cooling meter always 0
4 Cooling energy For a pure heat meter always 0
4 Volume
1,5 AverageReturnTemperature int12 Temperature [°C] = value/10 Min: -204,8 Max: 204,7 Resolution: 0,1
1,5 MaxReturnTemperatur int12 Coding like AverageReturnTemperature
0,375 bit 0..2 DiagnosticIntervalSetup Used to choose the cycle time out of a table.
0,125 bit 3 empty tube
0,125 bit 4 device defect
0,125 bit 5 Device status and error bit (not defined)
0,125 bit 6 Device status and error bit (not defined)
0,125 bit 7 Device status and error bit (not defined)

yes from first byte, yeah this is the payload, i tried to decode it but still sends wrong values