Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrong packet_type and SP1 ideas #1

Open
andryyy opened this issue Nov 4, 2020 · 7 comments
Open

Wrong packet_type and SP1 ideas #1

andryyy opened this issue Nov 4, 2020 · 7 comments

Comments

@andryyy
Copy link

andryyy commented Nov 4, 2020

Hi,

I think this should be an A. :) But that would mean the types need to be strings:

I am still struggling with the SP1 packages, but I think I understood it now...

Meaning Value Binary
Battery end of life 0x0200 0000 0010 0000 0000
Smoke chamber pollution prewarning 0x0800 0000 1000 0000 0000
Smoke chamber pollution warning 0x1000 0001 0000 0000 0000
Test button failure 0x2000 0010 0000 0000 0000
Acoustic alarm failure 0x4000 0100 0000 0000 0000
Removal detection 0x8000 1000 0000 0000 0000
Test alarm 0x0001 0000 0000 0000 0001
Smoke alarm 0x0002 0000 0000 0000 0010
Obstruction detection 0x0004 0000 0000 0000 0100
Surrounding area monitoring 0x0008 0000 0000 0000 1000
LED failure 0x0010 0000 0000 0001 0000

Payload seems to be "11 XX XX XX XX" where 1 is SP1 and 1 is oddly enough a subtype 1 (while there is no subtype defined).

The examples make sense then...

Payload 11 04 00 00 00 indicates obstruction detection
Payload 11 0C 00 00 00 indicates obstruction and surrounding area monitoring

The second example 0C 00 00 00 was always a bit tricky for me. It will equal to 0011 0000 0000 0000 in binary. Reverse it to 0000 0000 0000 1100 and the table above will match.

André

@andryyy
Copy link
Author

andryyy commented Nov 5, 2020

Or... no.

After talking to them:

Only 2 bytes of the 4 bytes are used (sigh), furthermore the bytes are flipped.

So: 0C 00 00 00 is 0C 00 is (flipped) 00 0C is 0000 0000 0000 1100.

I forgot to mention, that this should equal 1 instead of 0 (for whatever reason it is 0001 0001):

@jonaskonig
Copy link

Hey,
Don't know if this is still active, but I found another decode that has implemented the SP1 payloads. It lacks the 9.2 pyload but maybe you can merge them together:
MarkStanley/zenner-lorawan-smoke-detector-payload-decoder
Best regards
Jonas

@Lordcybertracker
Copy link

Guten Morgen,
leider funktionieren beide Decoder bei mir nicht.
Ich bekomme keine Decodierung.
Ausserdem zeigt es mir im Decoder fehler an: use !== to compare with ´null´

@miller-alex-github
Copy link

Hi,
please check my parser lora.miller-alex.de
Use SD device for EasyProtect.
Best regards, Alex Miller

@Sandmann171
Copy link

Sandmann171 commented Feb 26, 2024

Hey
I have already spent hours creating a decoder for Zenner EDC. Unfortunately it just won't work. Does anyone have an idea? The gateway is a UG65 Milesight
I used the parser from Miller alex, which is great but does not bring me to the solution

Heey
Ich habe schon Stunden damit verbracht einen Decoder für Zenner EDC zu erstellen. Leider will er einfach nicht. Hat jemand eine Idee? Das Gateway ist ein UG65 Milesight

`

  • - fPort: 1
    
  • - bytes: Array of bytes
    

*/
function Decode(fPort, bytes) {
var decoded = {
removal_detection: 0,
battery_low: 0,
battery_end_of_life: 0,
hw_error: 0,
coil_manipulation: 0,
meter_values: []
};

if (fPort === 1) {
    // Status bytes decoding
    var statusByte = bytes[0];
    decoded.removal_detection = (statusByte & 0x01) ? 1 : 0;
    decoded.battery_low = (statusByte & 0x02) ? 1 : 0;
    decoded.battery_end_of_life = (statusByte & 0x04) ? 1 : 0;
    decoded.hw_error = (statusByte & 0x08) ? 1 : 0;
    decoded.coil_manipulation = (statusByte & 0x10) ? 1 : 0;

    // Meter values decoding
    for (var i = 1; i < bytes.length; i += 4) {
        // Assuming meter values are 32-bit unsigned integers
        var meterValue = (bytes[i] << 24) | (bytes[i+1] << 16) | (bytes[i+2] << 8) | bytes[i+3];
        decoded.meter_values.push(meterValue);
    }
}

return decoded;

}

`

greeze

@jonaskonig
Copy link

I assembled a full decoder, maybe this helps:

function Decoder(bytes, port) {
    if(bytes === null || bytes === 0){
        obj.status_dedcoded = false;
        obj.status_info = "payload_raw: " + payloadRawHexToString(bytes);
    } else {
        var TYPE_SP1 = 0x1;
        var TYPE_SP9 = 0x9;
        var SUBTYPE_SP9_1 = 0x01;
        var SUBTYPE_SP9_2 = 0x02;
        var TYPE_AP1 = 0xA;

        var SP_REMOVAL = 0x8000;
        var SP_TEST = 0x0001;
        var SP_SMOKE = 0x0002;
        var SP_OBSTRUCTION = 0x0004;
        var SP_MONITORING = 0x0008;
        var SP_LED_FAIL = 0x0010;
        var SP_BATTERY_EOL = 0x0200;
        var SP_CHAMBER_PRE_POLLUTION = 0x0800;
        var SP_HORN_FAIL = 0x4000
        var SP_CHAMBER_POLLUTION = 0x1000;
        var SP_TEST_BUTTON_FAIL = 0x2000;


        var SP9_REMOVAL = 0x01;
        var SP9_BATTERY_EOL = 0x04;
        var SP9_HORN_FAIL = 0x08;
        var SP9_OBSTRUCTION = 0x10;
        var SP9_MONITORING = 0x20;


        var A_REMOVAL = 0x02;
        var A_BATTERY_END_OF_LIFE = 0x0C;
        var A_HORN_DRIVE_LEVEL_FAILURE = 0x16;
        var A_TEST_ALARM = 0x18;
        var A_SMOKE_ALARM = 0x19;
        var A_OBSTRUCTION_DETECTION = 0x1A;
        var A_OBJECT_IN_THE_SURROUNDING_AREA = 0x1C;




        var obj = {};
		obj.removal = 0;
		obj.test_alarm = 0;
        obj.smoke_alarm = 0;
        obj.obstruction = 0;
        obj.monitoring_area = 0;
        obj.led_fail = 0;
        obj.test_button_fail = 0;
        obj.chamber_pollution = 0;
        obj.chamber_pollution_pre_warning = 0;
        obj.horn_fail = 0;
        obj.battery_eol = 0;
        obj.object_in_area = 0;
        obj.port = port;

        switch (bytes[0] >> 4) {
            case TYPE_SP1:
                obj.packet_type = 1;
                obj.packet_subtype = 0;
                obj.packet_type_info = "synchronous";
                obj.status_dedcoded = true;
                obj.status_info = "payload_raw: " + payloadRawHexToString(bytes);
                if (bytes[1] & SP_REMOVAL) {
					obj.removal = 1;
                }
                if (bytes[1] & SP_TEST) {
					obj.test_alarm = 1;
                }
                if (bytes[1] & SP_SMOKE) {
					obj.smoke_alarm = 1;

                }
                if (bytes[1] & SP_OBSTRUCTION) {
					obj.obstruction = 1;

                }
                if (bytes[1] & SP_MONITORING) {
					obj.monitoring_area = 1;

                }
                if (bytes[1] & SP_LED_FAIL) {
					obj.led_fail = 1;

                }
                if (bytes[1] & SP_TEST_BUTTON_FAIL){
					obj.test_button_fail = 1;
				}
				if (bytes[1] & SP_CHAMBER_POLLUTION){
					obj.chamber_pollution = 1;
				}
				if (bytes[1] & SP_CHAMBER_PRE_POLLUTION){
					obj.chamber_pollution_pre_warning = 1;
				}
				if (bytes[1] & SP_HORN_FAIL){
					obj.horn_fail = 1;
				}
				if (bytes[1] & SP_BATTERY_EOL){
					obj.battery_eol = 1;
				}
                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 = true;
                obj.status_info = null;
                obj.status_info = "payload_raw: " + payloadRawHexToString(bytes);

                switch (bytes[1]) {
                    case A_REMOVAL:
						obj.removal = 1;
                        break;
                    case A_BATTERY_END_OF_LIFE:
                        obj.battery_eol = 1;
                        break;
                    case A_HORN_DRIVE_LEVEL_FAILURE:
                        obj.horn_fail = 1;
                        break;
                    case A_TEST_ALARM:
                        obj.test_alarm = 1;
                        break;
                    case A_SMOKE_ALARM:
                        obj.smoke_alarm = 1;
                        break;
                    case A_OBSTRUCTION_DETECTION:
                        obj.obstruction = 1;
                        break;
                    case A_OBJECT_IN_THE_SURROUNDING_AREA:
                        obj.object_in_area = 1;
                        break;
                    default:
                        obj.status_info = "payload_raw: " + payloadRawHexToString(bytes);
                        obj.status_dedcoded = false;
                        break;
                }
                break;
              case TYPE_SP9:
                obj.packet_type = 9;
                obj.packet_type_info = "synchronous";
                switch (bytes[0] & 0x0F) {
					case SUBTYPE_SP9_1:
						obj.packet_subtype = 1
						obj.date = (decodeSP9Date(bytes[4] << 8 | bytes[3]));
						if (bytes[5] & SP9_REMOVAL) {
							obj.removal = 1;
						}
						if (bytes[5] & SP9_BATTERY_EOL) {
							obj.battery_eol = 1;
						}
						if (bytes[5] & SP9_HORN_FAIL) {
							obj.horn_fail = 1;
						}
						if (bytes[5] & SP9_OBSTRUCTION) {
							obj.obstruction = 1;
						}
						if (bytes[5] & SP9_MONITORING) {
							obj.monitoring_area = 1;
						}
						obj.status_dedcoded = true;
						obj.status_info = "payload_raw: " + payloadRawHexToString(bytes);
						break;
					case SUBTYPE_SP9_2:
						obj.packet_subtype = 2;
						obj.firmware_version = (
                                ((bytes[1] << 24) + (bytes[2] << 16) + (bytes[3] << 8) + (bytes[4]))
                                    .toString(16)).toUpperCase();
                        obj.LoRa_WAN_version = (bytes[5]).toString(16) + "." + (bytes[6])
                                .toString(16) + "." + (bytes[7]).toString(16);
                        obj.LoRa_command_version = (bytes[9]).toString(16) + "." + (bytes[8]).toString(16),
                            "device type: " + (bytes[10]).toString(16);
                        obj.device_type = (bytes[10]).toString(16);
                        obj.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;
            default:
                obj.status_dedcoded = false;
                obj.status_info = "payload_raw: " + payloadRawHexToString(bytes);
                break;
        }
    }
    return obj;
}


function decodeDate(bytes) {
    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();
}

function decodeSP9Date(bytes) {
    var day = (bytes & 0x001F);
    var month = (bytes & 0x0F00) >> 8;
    var year = ((bytes & 0xF000) >> 9) | ((bytes & 0x00E0) >> 5);
    return "20" + year.toString() + "-" + month.toString() + "-" + day.toString();
}

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();
    }
}

function decodeUplink(input) {
  payload=Decoder(input.bytes, input.fPort)
  return {
    data:  payload,
    warnings: [],
    errors: []
  };
}

@andryyy
Copy link
Author

andryyy commented Feb 28, 2024

Funny place for this information, but in case someone’s interested: I have about 5 or 6 of them lying around that I don’t need anymore.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants