From b2886971ca7324e18436cd9c4a30792c18dee939 Mon Sep 17 00:00:00 2001
From: YunHorn Technology <dp.s@yunhorn.com>
Date: Thu, 18 Apr 2024 17:37:17 +0800
Subject: [PATCH] add decoder.js

---
 STM32CubeIDE/.project |   5 ++
 as923_jp_decoder.js   | 126 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 131 insertions(+)
 create mode 100644 as923_jp_decoder.js

diff --git a/STM32CubeIDE/.project b/STM32CubeIDE/.project
index e8fa120..44dd590 100644
--- a/STM32CubeIDE/.project
+++ b/STM32CubeIDE/.project
@@ -32,6 +32,11 @@
 		<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
 	</natures>
 	<linkedResources>
+		<link>
+			<name>Doc/as923_jp_decoder.js</name>
+			<type>1</type>
+			<locationURI>copy_PARENT/as923_jp_decoder.js</locationURI>
+		</link>
 		<link>
 			<name>Doc/readme.txt</name>
 			<type>1</type>
diff --git a/as923_jp_decoder.js b/as923_jp_decoder.js
new file mode 100644
index 0000000..559af9b
--- /dev/null
+++ b/as923_jp_decoder.js
@@ -0,0 +1,126 @@
+// 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]
+//  - variables contains the device variables e.g. {"calibration": "3.5"} (both the key / value are of type string)
+// The function must return an object, e.g. {"temperature": 22.5}
+function Decode(fPort, bytes, variables) {
+    // O5 Door contact sensor
+    if (fPort === 4) {
+        return [
+            {
+                led_state: bytes[0] === 0 ? "Off" : "On",
+                mtm_code_1: bytes[1],
+                mtm_code_2: bytes[2],
+                hw_code: bytes[3],
+                battery_level: bytes[4] + "%",
+                size_value: bytes[5],
+                HALL_1_state: bytes[6] === 1 ? "Door_Open" : "Door_Close",
+                HALL_2_state: bytes[7] === 1 ? "Door_Open" : "Door_Close",
+            }
+        ];
+    }
+    // heart-beat of O5
+    else if (fPort === 5) {
+        return [
+            {
+                led_state: (bytes[0] & 0x7f) === 0 ? "Off" : "On",
+                battery_level: bytes[4] + " %",
+            }
+        ];
+    }
+    // R4 soap/sanitizer sensor
+    else if (fPort === 7) {
+        return [
+            {
+                led_state: bytes[0] === 0 ? "Off" : "On",
+                mtm_code_1: bytes[1],
+                mtm_code_2: bytes[2],
+                hw_code: bytes[3],
+                battery_level: bytes[4] + "%",
+                size_value: bytes[5],
+                measure_tech: bytes[6] === 0 ? "Capacitive" : "Other",
+                liquid_level_event: bytes[7] === 0 ? "Liquid Detected" : "No Liquid",
+            }
+        ];
+    }
+    // R4 soap/sanitizer heart-beat
+    else if (fPort === 8) {
+        return [
+            {
+                led_state: (bytes[0] & 0x7f) === 0 ? "Off" : "On",
+                battery_level: bytes[1] + " %",
+            }
+        ];
+    }
+    // R1D dual roll toilet paper sensor
+    else if (fPort === 57) {
+        return [
+            {
+                led_state: bytes[0] === 0 ? "Off" : "On",
+                mtm_code_1: bytes[1],
+                mtm_code_2: bytes[2],
+                hw_code: bytes[3],
+                battery_level: bytes[4] + "%",
+                size_value: bytes[5],
+                distance_1_mm: bytes[6] << 8 | bytes[7],
+                distance_2_mm: bytes[8] << 8 | bytes[9],
+                distance_unit: "mm",
+            }
+        ];
+    }
+    // R1D, Heart-beat 
+    else if (fPort === 58) {
+        return [
+            {
+                led_state: (bytes[0] & 0x7f) === 0 ? "Off" : "On",
+                battery_level: bytes[4] + " %",
+            }
+        ];
+    }
+    // R5 waste bin sensor
+    else if (fPort === 11) {
+        return [
+            {
+                led_state: bytes[0] === 0 ? "Off" : "On",
+                mtm_code_1: bytes[1],
+                mtm_code_2: bytes[2],
+                hw_code: bytes[3],
+                battery_level: bytes[4] + "%",
+                size_value: bytes[5],
+                distance_1_mm: (bytes[6] << 8 | bytes[7]),
+                //distance_2_mm:bytes[8]*256+bytes[9],        
+                //distance_3_mm:bytes[10]*256+bytes[11],        
+                distance_unit: "mm",
+            }
+        ];
+    }
+    // R5, Heart-beat 
+    else if (fPort === 12) {
+        return [
+            {
+                led_state: (bytes[0] & 0x7f) === 0 ? "Off" : "On",
+                battery_level: bytes[4] + " %",
+            }
+        ];
+    }
+    // UPLINK, RFAC
+    else if (fPort === 1) {
+        var data = {};
+        data.length = bytes.length;
+        if (bytes[0] === 0x59) {
+            if (bytes[1] === 0x44) {
+                data.Uplink_interval = (bytes[2] - 0x30) * 60 + (bytes[3] - 0x30);
+                data.Uplink_interval_unit = String.fromCharCode(bytes[4]);
+            }
+            else if (bytes[1] === 0x53) {
+                data.Heart_Beat_interval = (bytes[2] - 0x30) * 60 + (bytes[3] - 0x30);
+                data.Heart_Beat_interval_unit = String.fromCharCode(bytes[4]);
+            }
+        }
+        else if ((bytes[0] === 0x41) && (bytes[1] === 0x43)) {
+            data.RFAC = "OK";
+        }
+
+        return { "Yunhorn_SmarToilets_data": data };
+    }
+}
\ No newline at end of file