diff --git a/app.json b/app.json index 6d85d3aa..86688a7c 100644 --- a/app.json +++ b/app.json @@ -3504,8 +3504,7 @@ "_TZE202_ztc6ggyl", "_TZE203_ztc6ggyl", "_TZE204_ztc6ggyl", - "_TZE204_qasjif9e", - "_TZE204_ijxvkhd0" + "_TZE204_qasjif9e" ], "productId": [ "TS0601" @@ -3652,6 +3651,7 @@ }, "zigbee": { "manufacturerName": [ + "_TZE204_ijxvkhd0", "_TZE204_sxm7l9xa" ], "productId": [ @@ -4995,8 +4995,8 @@ "learnmode": { "image": "/drivers/smart_garden_irrigation_control/assets/icon.svg", "instruction": { - "en": "Ensure the indicator light is flashing. If the indicatore light isn't flashing: press and hold the reset button for 5 seconds until the indicator light starts to flashing.", - "it": "Assicurarsi che l'indicatore lampeggi. Se l'indicatore non lampegga: tenere premuto il pulsante di reset per 5 secondi finchè l'indicatore non inizia a lampeggiare." + "en": "Ensure the indicator light is flashing. If the indicator light isn't flashing: press and hold on/off buttons for 5 seconds until the indicator light starts to flashing.", + "it": "Accertarsi che la spia lampeggi. Se la spia non lampeggia: tenere premuti i pulsanti di accensione/spegnimento per 5 secondi finché la spia non inizia a lampeggiare" } } }, diff --git a/drivers/smart_garden_irrigation_control/device.js b/drivers/smart_garden_irrigation_control/device.js index f911efb5..045035bc 100644 --- a/drivers/smart_garden_irrigation_control/device.js +++ b/drivers/smart_garden_irrigation_control/device.js @@ -2,34 +2,71 @@ const Homey = require('homey'); const { ZigBeeDevice } = require('homey-zigbeedriver'); -const { Cluster, debug, CLUSTER } = require('zigbee-clusters'); +const { Cluster, CLUSTER } = require('zigbee-clusters'); const TuyaSpecificCluster = require('../../lib/TuyaSpecificCluster'); Cluster.addCluster(TuyaSpecificCluster); -const DEFAULT_ONOFF_DURATION = 1000 +const DEFAULT_ONOFF_DURATION = 1000; // Data point and data types definitions const dataPoints = { - batteryLevel: 101, + batteryLevel: 101, // Adjust the data point as per your device's specification }; const dataTypes = { - value: 2, // 4 byte value + raw: 0, // [ bytes ] + bool: 1, // [0/1] + value: 2, // [ 4 byte value ] + string: 3, // [ N byte string ] + enum: 4, // [ 0-255 ] + bitmap: 5, // [ 1,2,4 bytes ] as bits }; +const convertMultiByteNumberPayloadToSingleDecimalNumber = (chunks) => { + let value = 0; + + for (let i = 0; i < chunks.length; i++) { + value = value << 8; + value += chunks[i]; + } + + return value; +}; + +const getDataValue = (dpValue) => { + switch (dpValue.datatype) { + case dataTypes.raw: + return dpValue.data; + case dataTypes.bool: + return dpValue.data[0] === 1; + case dataTypes.value: + return convertMultiByteNumberPayloadToSingleDecimalNumber(dpValue.data); + case dataTypes.string: + let dataString = ''; + for (let i = 0; i < dpValue.data.length; ++i) { + dataString += String.fromCharCode(dpValue.data[i]); + } + return dataString; + case dataTypes.enum: + return dpValue.data[0]; + case dataTypes.bitmap: + return convertMultiByteNumberPayloadToSingleDecimalNumber(dpValue.data); + } +} + class IrrigationController extends ZigBeeDevice { async onNodeInit({zclNode}) { this.printNode(); - + this.registerCapability('onoff', CLUSTER.ON_OFF); this.registerCapabilityListener("onoff", async (value, options) => { this.log("Irrigation controller value " + value); this.log("Irrigation controller options " + options.duration); - if (value && options.duration != undefined) { + if (value && options.duration !== undefined) { await zclNode.endpoints[1].clusters['onOff'].setOn(); await new Promise(resolve => setTimeout(resolve, options.duration)); await zclNode.endpoints[1].clusters['onOff'].setOff(); @@ -38,50 +75,53 @@ class IrrigationController extends ZigBeeDevice { } else if (!value && options.duration === undefined) { await zclNode.endpoints[1].clusters['onOff'].setOff(); } - - // Handle Tuya-specific responses - zclNode.endpoints[1].clusters.tuya.on("response", (response) => { - this.handleTuyaResponse(response); - }); - }); - - } - handleTuyaResponse(response) { - const dp = response.dp; - const value = this.getDataValue(response); + // Tuya specific cluster info + + zclNode.endpoints[1].clusters.tuya.on("response", (value) => this.handleTuyaResponse(value)); + + zclNode.endpoints[1].clusters.tuya.on("reporting", (value) => this.handleTuyaResponse(value)); + + //zclNode.endpoints[1].clusters.tuya.on("reportingConfiguration", (value) => this.handleTuyaResponse(value)); + //zclNode.endpoints[1].clusters.tuya.on("reportingConfiguration", (value) => this.log('reportingConfiguration event received:', value)); - // Handle battery level data point - if (dp === dataPoints.batteryLevel) { - this.log("Irrigation controller battery Level: ", value); - this.updateBatteryLevel(value); - } - } + /* zclNode.endpoints[1].clusters.basic.readAttributes(['manufacturerName', 'zclVersion', 'appVersion', 'modelId', 'powerSource', 'attributeReportingStatus']) + .catch(err => { + this.error('Error when reading device attributes ', err); + }); +*/ - getDataValue(dpValue) { - // Interpret the value based on data type - if (dpValue.datatype === dataTypes.value) { - return dpValue.data[0]; - } - } - - updateBatteryLevel(value) { - // Convert and update battery level - const batteryLevel = value; - this.setCapabilityValue('measure_battery', batteryLevel).catch(this.error); - // Get the battery low threshold setting or use default - const batteryThreshold = this.getSetting('batteryThreshold') || 20; - - // Update the alarm_battery capability based on the threshold - this.setCapabilityValue('alarm_battery', batteryLevel < batteryThreshold).catch(this.error); } + async handleTuyaResponse(response) { + try { + const dp = response.dp; + const value = this.getDataValue(response); + this.log("Irrigation !!!! controller handleTuyaResponse dp: " + dp + " value: " + value); + switch (dp) { + case dataPoints.batteryLevel: + this.log("Battery: " + value); + const batteryThreshold = this.getSetting('batteryThreshold') || 20; + parsedValue = value; + this.log("measure_battery | powerConfiguration - batteryPercentageRemaining (%): ", parsedValue); + + this.setCapabilityValue('measure_battery', parsedValue).catch(this.error); + this.setCapabilityValue('alarm_battery', (parsedValue < batteryThreshold)).catch(this.error); + break; + default: + this.log('dp value', dp, value) + } + } catch (error) { + this.error('Error in handleTuyaResponse:', error); +} + } + async onDeleted() { this.log('Smart irrigation controller removed'); } } -module.exports = IrrigationController; \ No newline at end of file +module.exports = IrrigationController;