Closed Andy-Hennah closed 2 years ago
There are some unprintable characters in the Database Entry. Should I be opening database.db with a particular encoding? The data above is with UTF-8 encoding.
This might relate to #12153 and #1551 They look like the same model ID (TS0601) but this one has a manufacturer name of _TZE200_sh1btabb
This might relate to #12153 and #1551 They look like the same model ID (TS0601) but this one has a manufacturer name of _TZE200_sh1btabb
Those are different unfortunately. I've managed to collect a few of the data points through trial and error - and they don't match with those models
I've started an integration. I don't have a hub at the moment to capture the correct messages to the device. However, it is able to read the current state and turn off the valve.
I'll try to complete it once my hub comes in and I can sniff out the correct commands to send to turn on the valve. I hoped it would just be setting a flag to turn the valve on, but it looks more complicated than that. I'm assuming it also needs a timer or water capacity value. (The valve does turn on when you sent the state to 'on' but then turns off right away)
'use strict';
const fz = require('zigbee-herdsman-converters/converters/fromZigbee');
const tz = require('zigbee-herdsman-converters/converters/toZigbee');
const exposes = require('zigbee-herdsman-converters/lib/exposes');
const reporting = require('zigbee-herdsman-converters/lib/reporting');
const extend = require('zigbee-herdsman-converters/lib/extend');
const tuya = require('zigbee-herdsman-converters/lib/tuya');
const e = exposes.presets;
const ea = exposes.access;
const giExDataPoints = {
// Confirmed
state: 2, // current state of the valve (open or not)
water_consumed: 111, // appears to be water value - reported in liter
last_run_starttime: 101, // last run start time -- reported in GMT+8 - need to figure out how to conver to local time
last_run_endtime: 102, // last run end time
last_run_duration: 114, // last run duration
// To Be Determined
battery: 108, //not sure if its this value but currently reading 100 percent
mode: 106, //?? This is something but we don't know what -- could be mode?. We know there is a mode, but don't know what the values are
//103 desired volume? --switchable?
};
const fzLocal = {
FZL1:
{
cluster: 'manuSpecificTuya',
type: ['commandDataResponse', 'commandDataReport'],
convert: (model, msg, publish, options, meta) => {
for (const dpValue of msg.data.dpValues) {
const value = tuya.getDataValue(dpValue);
const dp = dpValue.dp
meta.logger.info(`RECEIVED DP #${dp} -- VALUE = ${value}`);
switch (dp) {
case giExDataPoints.state: { //State
return {state: value ? 'ON': 'OFF'};
}
case giExDataPoints.water_consumed: {
return {water_consumed: (value).toFixed(1)};
}
case giExDataPoints.last_run_starttime: {
return {last_run_starttime: value};
}
case giExDataPoints.last_run_duration: {
// last run duration -- value reported in seconds
return {last_run_duration: value };
}
case giExDataPoints.mode: { //MODE???
if (value === 0) return {mode: 'disabled'};
else if (value === 1) return {mode: 'active'};
else return {mode: 'enabled'};
}
case giExDataPoints.last_run_endtime: {
return {last_run_endtime: value};
}
case giExDataPoints.battery: { //not sure if its this value but currently reading 100 percent
return {battery: value};
}
default: {
meta.logger.warn(`zigbee-herdsman-converters:: NOT RECOGNIZED DP ` +
`#${dp} with data ${JSON.stringify(msg.data)} VALUE = ${value}`);
}
}
}
},
},
};
const tzLocal = {
GIEX_timer:
{
key: ['timer'],
convertSet: async (entity, key, value, meta) => {
// input in minutes with maximum of 600 minutes (equals 10 hours)
const timer = 60 * Math.abs(Math.min(value, 600));
// sendTuyaDataPoint* functions take care of converting the data to proper format
await tuya.sendDataPointValue(entity, 11, timer, 'setData', 1);
return {state: {timer: value}};
},
},
GIEX_mode:
{
key: ['mode'],
convertSet: async (entity, key, value, meta) => {
let mode = 0;
if (value === 'disabled') mode = 0;
else if (value === 'active') mode = 1;
else mode = 2;
await tuya.sendDataPointEnum(entity, giExDataPoints.mode, mode);
return {state: {mode: value}};
},
},
GIEX_state: {
key: ['state'],
convertSet: async (entity, key, value, meta) => {
await tuya.sendDataPointBool(entity, giExDataPoints.state, value === 'ON');
},
},
};
const definition = {
fingerprint: [
{modelID: 'TS0601', manufacturerName: '_TZE200_sh1btabb'}
],
model: 'TS0601',
vendor: 'TuYa',
description: 'Water valve',
//onEvent: tuya.onEventSetLocalTime,
fromZigbee: [
fzLocal.FZL1,
//fz.tuya_data_point_dump,
],
toZigbee: [
tzLocal.GIEX_timer,
tzLocal.GIEX_mode,
tzLocal.GIEX_state,
tz.tuya_data_point_test,
],
exposes: [
e.battery(),
exposes.binary('state', ea.STATE_SET, 'ON', 'OFF').withDescription('State'),
exposes.numeric('last_run_starttime', ea.STATE).withUnit('GMT+8').withDescription('Last Run Start Time'),
exposes.numeric('last_run_endtime', ea.STATE).withUnit('GMT+8').withDescription('Last Run End Time'),
//exposes.enum('mode', ea.STATE_SET, ['disabled', 'active', 'enabled']),
//exposes.numeric('timer', exposes.access.STATE_SET).withValueMin(0).withValueMax(240).withUnit('min')
// .withDescription('Countdown timer in minutes'),
exposes.numeric('last_run_duration', exposes.access.STATE).withUnit('min')
.withDescription('Last Run Duration'),
exposes.numeric('water_consumed', exposes.access.STATE).withUnit('L')
.withDescription('Last Run Water Consumed (L)'),
],
};
module.exports = definition;
Hi @raf02. This is awesome, thanks. I've got a device here, it's not plumbed in but I can certainly switch it on and off from z2m. It's not turning off straight away like you are seeing but it is reverting to off after about a minute - I think that's expected behavior. I can do some more testing if you need me to.
Hi @raf02. This is awesome, thanks. I've got a device here, it's not plumbed in but I can certainly switch it on and off from z2m. It's not turning off straight away like you are seeing but it is reverting to off after about a minute - I think that's expected behavior. I can do some more testing if you need me to.
What are you using to switch it on/off?
I actually have the device too. I just don't have a hub - so I don't know what the valid commands to send it are. I'm guessing (by looking at the pictures of the app in the instructions) that you need to pass it either a timer value or an amount to water. However, I won't know what those data points are until I get a hub and can trigger the commands.
If I push the physical button on the device, I can see last_run_endtime flip to NULL and last_run_starttime goes to now (although the time is in GMT+8).
After 3 mins it hasn't switched off automatically so I pushed the button on the device again. This correctly updated last_run_endtime and last_run_duration.
If I use the z2m web interface to switch it on it switches off automatically after 1min.
I don't have a hub either I'm afraid.
So there's a few things left to figure out.
onEvent: tuya.onEventSetLocalTime
but it didn't seem to do anything. Thanks so much @raf02 :-)
Hi All,
Used the config @raf02 provided here: https://github.com/Koenkk/zigbee2mqtt/issues/12778#issuecomment-1155613836 and can switch on and off without delay unlike what @Andy-Hennah experienced.
last_run_duration and battery also seem to be updating correctly.
Thanks @raf02!
An updated version. This one supports the timer or watering capacity. The timezone issue on the start and stop times still exists, but otherwise, it functions as you'd expect.
'use strict';
const fz = require('zigbee-herdsman-converters/converters/fromZigbee');
const tz = require('zigbee-herdsman-converters/converters/toZigbee');
const exposes = require('zigbee-herdsman-converters/lib/exposes');
const reporting = require('zigbee-herdsman-converters/lib/reporting');
const extend = require('zigbee-herdsman-converters/lib/extend');
const tuya = require('zigbee-herdsman-converters/lib/tuya');
const e = exposes.presets;
const ea = exposes.access;
const giExDataPoints = {
// Confirmed
state: 2, // current state of the valve (close=0 open = 1)
mode: 1, // 0=duration 1=capacity
irrigation_target: 104, // duration in min - or capacity in liters
water_consumed: 111, // real-time water usage (liters)
irrigation_start_time: 101, // last run start time -- reported in GMT+8 - need to figure out how to conver to local time
irrigation_end_time: 102, // last run end time
last_irrigation_duration: 114, // last run duration
battery: 108, //batter percentage
// For cycle irrigation
cycle_irrigation_num_times: 103, //number of times to repeat cycle. 0=single irrigation
cycle_irrigation_interval: 105, //real-time irrigation interval (seconds)
// Other data points. Usage unclear
current_tempurature: 106, // Listed as current temp in the spec. Only see it publish value 0 once capacity mode finishes. Strange
app_start_switch: 112, // Called 'other extentions' in the spec. appear to be set to true when app triggers start
smart_weather:107, // Can be used in native app to implement rain delay
realtime_cumulative_duration: 110, //seconds
};
const fzLocal = {
FZL1:
{
cluster: 'manuSpecificTuya',
type: ['commandDataResponse', 'commandDataReport'],
convert: (model, msg, publish, options, meta) => {
for (const dpValue of msg.data.dpValues) {
const value = tuya.getDataValue(dpValue);
const dp = dpValue.dp
meta.logger.debug(`RECEIVED DP #${dp} -- VALUE = ${value}`);
switch (dp) {
case giExDataPoints.state: { //State
return {state: value ? 'ON': 'OFF'};
}
case giExDataPoints.mode: { //MODE
return {mode: value ? 'Capacity': 'Duration'};
}
case giExDataPoints.irrigation_target: {
return {irrigation_target: value };
}
case giExDataPoints.cycle_irrigation_num_times: {
return {cycle_irrigation_num_times: value };
}
case giExDataPoints.cycle_irrigation_interval: {
return {cycle_irrigation_interval: value };
}
case giExDataPoints.water_consumed: {
return {water_consumed: value};
}
case giExDataPoints.irrigation_start_time: {
return {irrigation_start_time: value};
}
case giExDataPoints.irrigation_end_time: {
return {irrigation_end_time: value};
}
case giExDataPoints.last_irrigation_duration: {
return {last_irrigation_duration: value };
}
case giExDataPoints.battery: {
return {battery: value};
}
case giExDataPoints.current_tempurature: {
return; //Do Nothing since we don't know what this value means
}
default: {
meta.logger.warn(`zigbee-herdsman-converters:: NOT RECOGNIZED DP ` +
`#${dp} with data ${JSON.stringify(msg.data)} VALUE = ${value}`);
}
}
}
},
},
};
const tzLocal = {
GIEX_mode:
{
key: ['mode'],
convertSet: async (entity, key, value, meta) => {
let mode = 0;
if (value === 'Duration') mode = 0;
else if (value === 'Capacity') mode = 1;
await tuya.sendDataPointBool(entity, giExDataPoints.mode, mode);
return {state: {mode: value}};
},
},
GIEX_timer:
{
key: ['irrigation_target'],
convertSet: async (entity, key, value, meta) => {
// input in minutes with maximum of 1440 minutes (equals 24 hours)
await tuya.sendDataPointValue(entity, giExDataPoints.irrigation_target, value);
return {state: {irrigation_target: value}};
},
},
GIEX_state: {
key: ['state'],
convertSet: async (entity, key, value, meta) => {
await tuya.sendDataPointBool(entity, giExDataPoints.state, value === 'ON');
},
},
GIEX_cycle_irrigation_times: {
key: ['cycle_irrigation_num_times'],
convertSet: async (entity, key, value, meta) => {
await tuya.sendDataPointValue(entity, giExDataPoints.cycle_irrigation_num_times, value);
return {state: {cycle_irrigation_num_times: value}};
},
},
GIEX_cycle_irrigation_interval: {
key: ['cycle_irrigation_interval'],
convertSet: async (entity, key, value, meta) => {
await tuya.sendDataPointValue(entity, giExDataPoints.cycle_irrigation_interval, value);
return {state: {cycle_irrigation_interval: value}};
},
},
};
const definition = {
fingerprint: [
{modelID: 'TS0601', manufacturerName: '_TZE200_sh1btabb'}
],
model: 'TS0601',
vendor: 'GiEX',
description: 'Water Irrigation Valve',
onEvent: tuya.onEventSetLocalTime, //onEvent: tuya.onEventSetTime,
fromZigbee: [
fzLocal.FZL1,
],
toZigbee: [
tzLocal.GIEX_timer,
tzLocal.GIEX_mode,
tzLocal.GIEX_state,
tzLocal.GIEX_cycle_irrigation_times,
tzLocal.GIEX_cycle_irrigation_interval,
tz.tuya_data_point_test,
],
exposes: [
e.battery(),
exposes.binary('state', ea.STATE_SET, 'ON', 'OFF').withDescription('State'),
exposes.enum('mode', ea.STATE_SET, ['Duration', 'Capacity']).withDescription('Irrigation Mode'),
exposes.numeric('irrigation_target', exposes.access.STATE_SET).withValueMin(0).withValueMax(1440).withUnit('min or L')
.withDescription('Irrigation Target. Duration in minutes - or Capacity in Liters (depending on mode)'),
exposes.numeric('cycle_irrigation_num_times', exposes.access.STATE_SET).withValueMin(0).withValueMax(100).withUnit('# of times')
.withDescription('Cycle Irrigation Times. Set to 0 for single cycle'),
exposes.numeric('cycle_irrigation_interval', exposes.access.STATE_SET).withValueMin(0).withValueMax(1440).withUnit('min')
.withDescription('Cycle Irrigation Interval'),
exposes.numeric('irrigation_start_time', ea.STATE).withUnit('GMT+8').withDescription('Irrigation Start Time'),
exposes.numeric('irrigation_end_time', ea.STATE).withUnit('GMT+8').withDescription('Irrigation End Time'),
exposes.numeric('last_irrigation_duration', exposes.access.STATE).withUnit('min')
.withDescription('Last Irrigation Duration'),
exposes.numeric('water_consumed', exposes.access.STATE).withUnit('L')
.withDescription('Water Consumed (L)'),
//exposes.numeric('current_tempurature', ea.STATE).withUnit('C')
// .withDescription('Current Tempurature'),
],
};
module.exports = definition;
looks good @raf02 - it's all working as expected for me.
Merged, assuming this can be closed now.
Changes will be available in the dev branch in a few hours from now. (https://www.zigbee2mqtt.io/advanced/more/switch-to-dev-branch.html)
Hello, Thank you for the update.
If water is not flowing through the valve, then the mobile app give the warning. Any idea how such reading can be captured here in the code?
Thanks,
Hello, Thank you for the update.
If water is not flowing through the valve, then the mobile app give the warning. Any idea how such reading can be captured here in the code?
Thanks,
Unfortunately, the device itself isn't emitting this warning message (as far as I can tell). I think their mobile app is deducing it based on the fact that valve is open but the water consumption isn't increasing. You'd have to do it a similar way in whatever automation platform you're using.
Thanks for the awesome support!
I just did a quick test for 1L, and I got 916ml. I'm not sure if it could be improved? Anyway, I don't need so much precision, just to let you know.
Hello guys,
The app allows users to set the schedule for irrigation, I have scheduled some irrigations and then I disconnected the device from the network.
It seems that all scheduled irrigations have been properly executed without connectivity.
Do you think that this behavior could be achieved through zigbee2mqtt?
Thanks for the awesome support!
I just did a quick test for 1L, and I got 916ml. I'm not sure if it could be improved? Anyway, I don't need so much precision, just to let you know.
I don't think the device is accurate enough to get a better reading.
Hello guys,
The app allows users to set the schedule for irrigation, I have scheduled some irrigations and then I disconnected the device from the network.
It seems that all scheduled irrigations have been properly executed without connectivity.
Do you think that this behavior could be achieved through zigbee2mqtt?
I didn't see any commands going to the device when I manipulated the scheduling settings. I assumed it was done though the app itself - or maybe through the hub? In either case, I didn't see a way it could be done in z2m, but maybe someone else has some ideas.
I suspect most people want to do scheduling through their own automation solution (eg. Home Assistant) since it would allow for much more customization (eg. based on weather, wind, moisture sensors, etc) so i didn't spend a ton of time on that feature.
Hello guys, The app allows users to set the schedule for irrigation, I have scheduled some irrigations and then I disconnected the device from the network. It seems that all scheduled irrigations have been properly executed without connectivity. Do you think that this behavior could be achieved through zigbee2mqtt?
I didn't see any commands going to the device when I manipulated the scheduling settings. I assumed it was done though the app itself - or maybe through the hub? In either case, I didn't see a way it could be done in z2m, but maybe someone else has some ideas.
I suspect most people want to do scheduling through their own automation solution (eg. Home Assistant) since it would allow for much more customization (eg. based on weather, wind, moisture sensors, etc) so i didn't spend a ton of time on that feature.
Really true that people want to use HA to schedule the watering but if you lose the connectivity and you are on a trip your plant would remain watering if the device worked in an autonomous way.
Anyway... thank a los lot for your response
Link
https://www.aliexpress.com/item/1005004208466976.html?spm=a2g0o.productlist.0.0.36d07996Jv1iry&algo_pvid=c52efdc5-808c-4e9a-945f-bf0d7fa1401a&algo_exp_id=c52efdc5-808c-4e9a-945f-bf0d7fa1401a-0&pdp_ext_f=%7B%22sku_id%22%3A%2212000028385854560%22%7D&pdp_npi=2%40dis%21USD%21%2136.12%21%21%21%21%21%402100bb5116548771413708852e549b%2112000028385854560%21sea
Database entry
{"id":40,"type":"EndDevice","ieeeAddr":"0xa4c13881f9ac0b02","nwkAddr":41578,"manufId":4417,"manufName":"_TZE200_sh1btabb","powerSource":"Battery","modelId":"TS0601","epList":[1],"endpoints":{"1":{"profId":260,"epId":1,"devId":81,"inClusterList":[4,5,61184,0],"outClusterList":[25,10],"clusters":{"genBasic":{"attributes":{"65503":"S76i�76f�76\u0012�76e","65506":54,"65508":0,"stackVersion":0,"dateCode":"","appVersion":70}}},"binds":[],"configuredReportings":[],"meta":{}}},"appVersion":70,"stackVersion":0,"hwVersion":1,"dateCode":"","zclVersion":3,"interviewCompleted":true,"meta":{},"lastSeen":1654877529881,"defaultSendRequestWhen":"immediate"}
Comments
I did try writing my own converter but it's a TuYa device and it's more complicated than adding a switch.
External converter
No response
Supported color modes
No response
Color temperature range
No response