// Decode uplink function. // // Input is an object with the following fields: // - bytes = Byte array containing the uplink payload, e.g. [255, 230, 255, 0] // - fPort = Uplink fPort. // - variables = Object containing the configured device variables. // // Output must be an object with the following fields: // - data = Object representing the decoded payload. function decodeUplink(input) { var bytes=input.bytes; //Payload Formats of RS485_LN Deceive, for TTN/ChirpStack if(bytes.length > 6) // Telemetry, by right should check by fport { // uplink from RS485 has payload version at bytes[0] var cs_temp = (bytes[1] << 8 | bytes[2]) / 10; // Javascript does not support binary 0bxxxx var cs_al1_status = (bytes[3] & 0x04)? true : false; // 0b0100 var cs_al2_status = (bytes[3] & 0x08)? true : false; // 0b1000 // For Temperature and Humid of SHT20 var cs_temp_sht20 = (bytes[4] << 8 | bytes[5]) / 10 - 2.9; // To offset down 2.9 degree var cs_humid_sht20 = (bytes[6] << 8 | bytes[7]) / 10; // Voltage and current var cs_voltage = (bytes[8] << 8 | bytes[9]) / 10; var cs_current = (bytes[10] << 8 | bytes[11]) / 100; var cs_kW = cs_voltage * cs_current / 1000; // kWh var cs_exportKWh = (bytes[12] << 24 | bytes[13] << 16 | bytes[14] << 8 | bytes[15]) / 100; var cs_importKWh = (bytes[16] << 24 | bytes[17] << 16 | bytes[18] << 8 | bytes[19]) / 100; var cs_totalKWh = cs_exportKWh + cs_importKWh; return { data: {"cs_temp":cs_temp, "cs_al1_status":cs_al1_status, "cs_al2_status":cs_al2_status, "cs_temp_sht20":cs_temp_sht20, "cs_humid_sht20":cs_humid_sht20, "cs_voltage":cs_voltage, "cs_current":cs_current, "cs_kW":cs_kW, "cs_exportKWh":cs_exportKWh, "cs_importKWh":cs_importKWh, "cs_totalKWh":cs_totalKWh} }; } else if(bytes.length == 6) // return from RPC commands { // Uplink from RPC response does not have payload version at bytes[0] // AL1: On OK [0x01,0x06,0x20,0x01,0x03,0xe8] if(bytes[0] == 0x01 && bytes[1] == 0x06 && bytes[2] == 0x20 && bytes[3] == 0x01 && bytes[4] == 0x03 && bytes[5] == 0xe8) { return { data: {"cs_al1_status": true}}; } // AL1: Off OK [0x01,0x06,0x20,0x01,0x00,0x00] else if(bytes[0] == 0x01 && bytes[1] == 0x06 && bytes[2] == 0x20 && bytes[3] == 0x01 && bytes[4] == 0x00 && bytes[5] == 0x00) { return { data: {"cs_al1_status": false}}; } // AL2: On OK [0x01,0x06,0x20,0x03,0x03,0xe8] if(bytes[0] == 0x01 && bytes[1] == 0x06 && bytes[2] == 0x20 && bytes[3] == 0x03 && bytes[4] == 0x03 && bytes[5] == 0xe8) { return { data: {"cs_al2_status": true}}; } // AL2: Off OK [0x01,0x06,0x20,0x03,0x00,0x00] else if(bytes[0] == 0x01 && bytes[1] == 0x06 && bytes[2] == 0x20 && bytes[3] == 0x03 && bytes[4] == 0x00 && bytes[5] == 0x00) { return { data: {"cs_al2_status": false}}; } else return { data: {"byte0": bytes[0], "byte1": bytes[1], "byte2": bytes[2], "byte3": bytes[3], "byte4": bytes[4], "byte5": bytes[5]}}; } else // Unknown { return {data: {}}; } } // Encode downlink function. // // Input is an object with the following fields: // - data = Object representing the payload that must be encoded. // - variables = Object containing the configured device variables. // // Output must be an object with the following fields: // - bytes = Byte array containing the downlink payload. function encodeDownlink(input) { var obj=input.data; if(obj["method"] === "setAL1Value") { if(obj["params"]) { // return [0xa8,0x01,0x06,0x01,0x06,0x20,0x01,0x03,0xe8,0x00]; // On return { bytes: [0xa8,0x01,0x06,0x01,0x06,0x20,0x01,0x03,0xe8,0x06]}; // On, to return 6-byte uplink } else { // return [0xa8,0x01,0x06,0x01,0x06,0x20,0x01,0x00,0x00,0x00]; // Off return {bytes: [0xa8,0x01,0x06,0x01,0x06,0x20,0x01,0x00,0x00,0x06]}; // Off, to return 6-byte uplink } } else if(obj["method"] === "setAL2Value") { if(obj["params"]) { // a801060106200303e806 // qAEGAQYgAwPoBg== // return [0xa8,0x01,0x06,0x01,0x06,0x20,0x03,0x03,0xe8,0x00]; // On return {bytes: [0xa8,0x01,0x06,0x01,0x06,0x20,0x03,0x03,0xe8,0x06]}; // On, to return 6-byte uplink } else { // a8010601062003000006 // qAEGAQYgAwAABg== // return [0xa8,0x01,0x06,0x01,0x06,0x20,0x03,0x00,0x00,0x00]; // Off return {bytes: [0xa8,0x01,0x06,0x01,0x06,0x20,0x03,0x00,0x00,0x06]}; // Off, to return 6-byte uplink } } else if(obj["method"] === "getAL1Value" || obj["method"] === "getAL2Value") { return {bytes: [0x08,0xff]}; // To uplink all at+command immediately } // Should not reach here return {bytes: []}; }