Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions drivers/radarLuminanceSensor/assets/distance.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions drivers/radarLuminanceSensor/assets/icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
120 changes: 120 additions & 0 deletions drivers/radarLuminanceSensor/device.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
'use strict';

const { ZigBeeDevice } = require('homey-zigbeedriver');
const { CLUSTER, Cluster, ZCLDataTypes, debug } = require('zigbee-clusters');
const TuyaSpecificCluster = require('../../lib/TuyaSpecificCluster');
const TuyaSpecificClusterDevice = require('../../lib/TuyaSpecificClusterDevice');

Cluster.addCluster(TuyaSpecificCluster);

const dataPoints = {
tshpsPresenceState: 1, // OK
tshpscSensitivity: 2, // not sure
tshpsMinimumRange: 3, // might be correct
tshpsMaximumRange: 4, // might be correct
tshpsFadingTime: 102, // OK
tshpsIlluminanceLux: 106, // Works but is also reported according Zigbee standard
tshpsBatteryPercentage: 110 // Works but is also reported according Zigbee standard
}

const dataTypes = {
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 radarLuminanceSensor extends TuyaSpecificClusterDevice {
async onNodeInit({zclNode}) {
this.printNode();

// Standaard capabilities
this.registerCapability('measure_luminance', CLUSTER.ILLUMINANCE_MEASUREMENT);
this.registerCapability('measure_battery', CLUSTER.POWER_CONFIGURATION);
// Tuya specific datapoint handling
zclNode.endpoints[1].clusters.tuya.on("response", value => this.updatePosition(value));
}

async updatePosition(data) {
const dp = data.dp;
const value = getDataValue(data);

switch (dp) {
case dataPoints.tshpsPresenceState:
this.log("presence state: "+ value)
this.setCapabilityValue('alarm_motion', Boolean(value))
break;
case dataPoints.tshpscSensitivity:
this.log("sensitivity state: "+ value)
break;

default:
this.log('dp value', dp, value)
}
}

onDeleted() {
this.log("Sensor removed")
}

onIASZoneStatusChangeNotification({zoneStatus, extendedStatus, zoneId, delay,}) {
this.log('IASZoneStatusChangeNotification received:', zoneStatus, extendedStatus, zoneId, delay);
this.setCapabilityValue('alarm_motion', zoneStatus.alarm1);
}

async onSettings({newSettings, changedKeys}) {
if (changedKeys.includes('radar_sensitivity')) {
this.writeData32(dataPoints.tshpscSensitivity, newSettings['radar_sensitivity'])
}

if (changedKeys.includes('minimum_range')) {
this.writeData32(dataPoints.tshpsMinimumRange, newSettings['minimum_range']*100)
}

if (changedKeys.includes('maximum_range')) {
this.writeData32(dataPoints.tshpsMaximumRange, newSettings['maximum_range']*100)
}

if (changedKeys.includes('fading_time')) {
this.writeData32(dataPoints.tshpsFadingTime, newSettings['fading_time'])
}

}

}

module.exports = radarLuminanceSensor;
45 changes: 45 additions & 0 deletions drivers/radarLuminanceSensor/driver.compose.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"id": "radarLiminanceSensor",
"name": {
"en": "Human Motion & Luminance Sensor"
},
"class": "sensor",
"platforms": ["local"],
"connectivity": ["zigbee"],
"capabilities": [
"measure_luminance",
"measure_battery",
"alarm_motion"
],

"energy": {
"batteries": ["AAA", "AAA"]
},

"images": {
"large": "{{driverAssetsPath}}/images/large.png",
"small": "{{driverAssetsPath}}/images/small.png"
},

"zigbee": {
"manufacturerName": [
"_TZE200_y8jijhba"
],
"productId": [
"TS0601"
],
"endpoints": {
"1": {
"clusters": [0, 1, 3, 1024, 1280, 61184],
"bindings": []
}
}
},

"learnmode": {
"instruction": {
"en": "Insert pin into hole for 5 seconds until light blinks"
}
}
}

61 changes: 61 additions & 0 deletions drivers/radarLuminanceSensor/driver.settings.compose.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
[
{
"id": "radar_sensitivity",
"type": "number",
"label": {
"en": "Radar sensitivity",
"nl": "Radar sensitiviteit"
},
"value": 12,
"min": 1,
"max": 15,
"step": 1
},
{
"id": "minimum_range",
"type": "number",
"label": {
"en": "Minimum range",
"nl": "Minimale bereik"
},
"value": 0,
"min": 0,
"max": 9.5,
"step": 0.5,
"units": {
"en": "meters",
"nl": "meters"
}
},
{
"id": "maximum_range",
"type": "number",
"label": {
"en": "Maximum range",
"nl": "Maximale bereik"
},
"value": 9.5,
"min": 0,
"max": 9.5,
"step": 0.5,
"units": {
"en": "meters",
"nl": "meters"
}
},
{
"id": "fading_time",
"type": "number",
"label": {
"en": "Fading time",
"nl": "Reset tijd"
},
"value": 30,
"min": 0,
"max": 1500,
"units": {
"en": "seconds",
"nl": "seconden"
}
}
]