diff --git a/.homeycompose/app.json b/.homeycompose/app.json
index fa85c8d433..9ebad25913 100644
--- a/.homeycompose/app.json
+++ b/.homeycompose/app.json
@@ -28,7 +28,7 @@
"Samotech",
"Silvercrest",
"Smart9",
- "Zemismart",
+ "Zemismart",
"Zigbee",
"Woox",
"Sensor",
diff --git a/app.js b/app.js
index 269f2c2d67..0d8f8b9cc3 100644
--- a/app.js
+++ b/app.js
@@ -7,6 +7,8 @@ const { debug } = require('zigbee-clusters');
class tuyazigbee extends Homey.App {
onInit() {
+ //require('inspector').open(9222, '0.0.0.0', true);
+
this.log('Tuya Zigbee app is running...');
// Register the action card for christmas lights
diff --git a/app.json b/app.json
index 8581cd84ac..7e277a70dd 100644
--- a/app.json
+++ b/app.json
@@ -10248,6 +10248,98 @@
}
]
},
+ {
+ "id": "temperaturesensor_ths317",
+ "name": {
+ "en": "Temperature Sensor THS317"
+ },
+ "class": "sensor",
+ "platforms": [
+ "local"
+ ],
+ "connectivity": [
+ "zigbee"
+ ],
+ "capabilities": [
+ "measure_temperature",
+ "measure_battery",
+ "alarm_battery"
+ ],
+ "energy": {
+ "batteries": [
+ "AAA",
+ "AAA"
+ ]
+ },
+ "images": {
+ "small": "/drivers/temperaturesensor_ths317/assets/images/small.png",
+ "large": "/drivers/temperaturesensor_ths317/assets/images/large.png",
+ "xlarge": "/drivers/temperaturesensor_ths317/assets/images/xlarge.png"
+ },
+ "zigbee": {
+ "manufacturerName": [
+ "_TZE200_iq4ygaai"
+ ],
+ "productId": [
+ "TS0201"
+ ],
+ "endpoints": {
+ "1": {
+ "clusters": [
+ 0,
+ 1,
+ 61184,
+ 1026
+ ],
+ "bindings": [
+ 1,
+ 1026,
+ 61184
+ ]
+ }
+ },
+ "learnmode": {
+ "image": "/drivers/temperaturesensor_ths317/assets/learnmode.svg",
+ "instruction": {
+ "en": "hold button for 10 seconds to reset the device and enter learn mode"
+ }
+ }
+ },
+ "settings": [
+ {
+ "id": "temperature_offset",
+ "type": "number",
+ "label": {
+ "en": "Temperature offset (°C)"
+ },
+ "hint": {
+ "en": "Set a value to compensate a temperature offset.\nRange: -10 - 10, step size 0.1, \ndefault: 0 [°C]"
+ },
+ "value": 0,
+ "attr": {
+ "min": -10,
+ "max": 10,
+ "step": 0.1
+ }
+ },
+ {
+ "id": "batteryThreshold",
+ "type": "number",
+ "label": {
+ "en": "Battery Low Alarm Voltage Threshold (percent)"
+ },
+ "hint": {
+ "en": "This setting determines the threshold before a battery alarm is given."
+ },
+ "value": 20,
+ "attr": {
+ "step": 1,
+ "min": 10,
+ "max": 90
+ }
+ }
+ ]
+ },
{
"id": "temphumidsensor",
"name": {
diff --git a/drivers/temperaturesensor_ths317/assets/icon.svg b/drivers/temperaturesensor_ths317/assets/icon.svg
new file mode 100644
index 0000000000..a964c2fe27
--- /dev/null
+++ b/drivers/temperaturesensor_ths317/assets/icon.svg
@@ -0,0 +1,43 @@
+
+
+
diff --git a/drivers/temperaturesensor_ths317/assets/images/large.png b/drivers/temperaturesensor_ths317/assets/images/large.png
new file mode 100644
index 0000000000..e5e67897c8
Binary files /dev/null and b/drivers/temperaturesensor_ths317/assets/images/large.png differ
diff --git a/drivers/temperaturesensor_ths317/assets/images/small.png b/drivers/temperaturesensor_ths317/assets/images/small.png
new file mode 100644
index 0000000000..e5c3cfa192
Binary files /dev/null and b/drivers/temperaturesensor_ths317/assets/images/small.png differ
diff --git a/drivers/temperaturesensor_ths317/assets/images/xlarge.png b/drivers/temperaturesensor_ths317/assets/images/xlarge.png
new file mode 100644
index 0000000000..7d1f7fefd8
Binary files /dev/null and b/drivers/temperaturesensor_ths317/assets/images/xlarge.png differ
diff --git a/drivers/temperaturesensor_ths317/assets/learnmode.svg b/drivers/temperaturesensor_ths317/assets/learnmode.svg
new file mode 100644
index 0000000000..7b4677cd9a
--- /dev/null
+++ b/drivers/temperaturesensor_ths317/assets/learnmode.svg
@@ -0,0 +1,19 @@
+
+
+
\ No newline at end of file
diff --git a/drivers/temperaturesensor_ths317/device.js b/drivers/temperaturesensor_ths317/device.js
new file mode 100644
index 0000000000..2639bb6971
--- /dev/null
+++ b/drivers/temperaturesensor_ths317/device.js
@@ -0,0 +1,101 @@
+'use strict';
+
+const { Cluster } = require('zigbee-clusters');
+const TuyaSpecificCluster = require('../../lib/TuyaSpecificCluster');
+const TuyaSpecificClusterDevice = require('../../lib/TuyaSpecificClusterDevice');
+const { V1_TEMPHUMID_SENSOR_DATA_POINTS } = require('../../lib/TuyaDataPoints');
+const { getDataValue } = require('../../lib/TuyaHelpers');
+
+// Register Tuya cluster with Zigbee
+Cluster.addCluster(TuyaSpecificCluster);
+
+class temperaturesensor_ths317 extends TuyaSpecificClusterDevice {
+
+ async onNodeInit({ zclNode }) {
+ super.onNodeInit({ zclNode });
+
+ // Enable debug logging
+ //this.enableDebug();
+
+ this.printNode();
+
+ // Initialize reporting settings from the device settings
+ this.initializeReportingSettings();
+
+ // Listen for Tuya cluster responses
+ const tuyaCluster = this.zclNode.endpoints[1].clusters.tuya;
+ if (tuyaCluster) {
+ tuyaCluster.on("response", this.onTuyaClusterMessage.bind(this));
+ } else {
+ this.error('Tuya cluster not found on endpoint 1');
+ }
+ }
+
+ initializeReportingSettings() {
+ this.temperatureOffset = this.getSetting('temperature_offset')|| 0;
+ this.batteryThreshold = this.getSetting('batteryThreshold')|| 20;
+ }
+
+ onTuyaClusterMessage(message) {
+ this.log('Tuya cluster message:', message);
+
+ try {
+ // Use helper function to parse datapoint value
+ const value = getDataValue(message);
+ const dp = message.dp;
+
+ this.log(`Datapoint ${dp} report:`, value);
+
+ // Handle different datapoints
+ switch (dp) {
+ case V1_TEMPHUMID_SENSOR_DATA_POINTS.currentTemperature:
+ this.onTemperatureReport(value);
+ break;
+ case V1_TEMPHUMID_SENSOR_DATA_POINTS.batteryLevel:
+ this.onBatteryReport(value);
+ break;
+ default:
+ this.log(`Unknown datapoint ${dp} report:`, value);
+ }
+ } catch (error) {
+ this.error('Error processing Tuya cluster report:', error);
+ }
+ }
+
+ onTemperatureReport(measuredValue) {
+ const parsedValue = measuredValue / 10;
+ this.log('measure_temperature | temperatureMeasurement - measuredValue (temperature): ', parsedValue, ' + temperature offset ', this.temperatureOffset);
+ this.setCapabilityValue('measure_temperature', parsedValue + this.temperatureOffset).catch(this.error);
+ }
+
+ onBatteryReport(batteryPercentageRemaining) {
+ this.log("measure_battery | powerConfiguration - batteryPercentageRemaining (%): ", batteryPercentageRemaining);
+ this.setCapabilityValue('measure_battery', batteryPercentageRemaining).catch(this.error);
+ this.setCapabilityValue('alarm_battery', (batteryPercentageRemaining < this.batteryThreshold) ? true : false).catch(this.error);
+ }
+
+ async onSettings({oldSettings, newSettings, changedKeys}) {
+ // Update cached settings
+ if (changedKeys.includes('temperature_offset')) {
+ this.temperatureOffset = newSettings.temperature_offset;
+ this.log(`Temperature offset changed to ${this.temperatureOffset}`);
+
+ // Update temperature capability with new offset
+ this.onTemperatureReport(this.getCapabilityValue('measure_temperature')*10);
+ }
+
+ if (changedKeys.includes('batteryThreshold')) {
+ this.batteryThreshold = newSettings.batteryThreshold;
+ this.log(`Battery threshold changed to ${this.batteryThreshold}`);
+
+ // Update battery alarm with new threshold
+ this.onBatteryReport(this.getCapabilityValue('measure_battery'));
+ }
+ }
+
+ onDeleted() {
+ this.log('Temperature sensor THS317-ET-TY removed');
+ }
+}
+
+module.exports = temperaturesensor_ths317;
\ No newline at end of file
diff --git a/drivers/temperaturesensor_ths317/driver.compose.json b/drivers/temperaturesensor_ths317/driver.compose.json
new file mode 100644
index 0000000000..01ab20a523
--- /dev/null
+++ b/drivers/temperaturesensor_ths317/driver.compose.json
@@ -0,0 +1,54 @@
+{
+ "id": "temperaturesensor_ths317",
+ "name": {
+ "en": "Temperature Sensor THS317"
+ },
+ "class": "sensor",
+ "platforms": ["local"],
+ "connectivity": ["zigbee"],
+ "capabilities": [
+ "measure_temperature",
+ "measure_battery",
+ "alarm_battery"
+ ],
+ "energy": {
+ "batteries": [
+ "AAA",
+ "AAA"
+ ]
+ },
+ "images": {
+ "small": "{{driverAssetsPath}}/images/small.png",
+ "large": "{{driverAssetsPath}}/images/large.png",
+ "xlarge": "{{driverAssetsPath}}/images/xlarge.png"
+ },
+ "zigbee": {
+ "manufacturerName": [
+ "_TZE200_iq4ygaai"
+ ],
+ "productId": [
+ "TS0201"
+ ],
+ "endpoints": {
+ "1": {
+ "clusters": [
+ 0,
+ 1,
+ 61184,
+ 1026
+ ],
+ "bindings": [
+ 1,
+ 1026,
+ 61184
+ ]
+ }
+ },
+ "learnmode": {
+ "image": "{{driverAssetsPath}}/learnmode.svg",
+ "instruction": {
+ "en": "hold button for 10 seconds to reset the device and enter learn mode"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/drivers/temperaturesensor_ths317/driver.settings.compose.json b/drivers/temperaturesensor_ths317/driver.settings.compose.json
new file mode 100644
index 0000000000..7b1ad1093d
--- /dev/null
+++ b/drivers/temperaturesensor_ths317/driver.settings.compose.json
@@ -0,0 +1,34 @@
+ [
+ {
+ "id": "temperature_offset",
+ "type": "number",
+ "label": {
+ "en": "Temperature offset (°C)"
+ },
+ "hint": {
+ "en": "Set a value to compensate a temperature offset.\nRange: -10 - 10, step size 0.1, \ndefault: 0 [°C]"
+ },
+ "value": 0,
+ "attr": {
+ "min": -10,
+ "max": 10,
+ "step": 0.1
+ }
+ },
+ {
+ "id": "batteryThreshold",
+ "type": "number",
+ "label": {
+ "en": "Battery Low Alarm Voltage Threshold (percent)"
+ },
+ "hint": {
+ "en": "This setting determines the threshold before a battery alarm is given."
+ },
+ "value": 20,
+ "attr": {
+ "step": 1,
+ "min": 10,
+ "max": 90
+ }
+ }
+ ]
\ No newline at end of file