Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
* Added support for Namron Touch Termostat model 4512737

New device from Namron supported https://www.namron.com/products/namron-zigbee-touch-termostat-16a-hvit/

* Removed duplicated code

* Update namron.js

* Added support for Namron Touch Termostat model 4512737

New device from Namron supported https://www.namron.com/products/namron-zigbee-touch-termostat-16a-hvit/

* Removed duplicated code

* Update namron.js

* Added basic support for Connecte thermostat

Added fromzigbee support

* Cleaned up exposes and fromzigbee

Fixed exposes and some attributes

* Fixing exposes take 2

Need to comment out preset and sensor until i get tozigbee working.

* Added support for Connecte Smart Thermostat

* Fixed failing unittests

* Update connecte.js

Co-authored-by: Koen Kanters <[email protected]>
  • Loading branch information
owangen and Koenkk authored Apr 7, 2022
1 parent 65c362c commit 2fe8e40
Show file tree
Hide file tree
Showing 4 changed files with 175 additions and 0 deletions.
49 changes: 49 additions & 0 deletions converters/fromZigbee.js
Original file line number Diff line number Diff line change
Expand Up @@ -4272,6 +4272,55 @@ const converters = {
}
},
},
connecte_thermostat: {
cluster: 'manuSpecificTuya',
type: ['commandDataResponse', 'commandDataReport'],
convert: (model, msg, publish, options, meta) => {
const dpValue = tuya.firstDpValue(msg, meta, 'connecte_thermostat');
const dp = dpValue.dp;
const value = tuya.getDataValue(dpValue);

switch (dp) {
case tuya.dataPoints.connecteState:
return {state: value ? 'ON' : 'OFF'};
case tuya.dataPoints.connecteMode:
switch (value) {
case 0: // manual
return {system_mode: 'heat', away_mode: 'OFF'};
case 1: // home (auto)
return {system_mode: 'auto', away_mode: 'OFF'};
case 2: // away (auto)
return {system_mode: 'auto', away_mode: 'ON'};
}
break;
case tuya.dataPoints.connecteHeatingSetpoint:
return {current_heating_setpoint: value};
case tuya.dataPoints.connecteLocalTemp:
return {local_temperature: value};
case tuya.dataPoints.connecteTempCalibration:
return {local_temperature_calibration: value};
case tuya.dataPoints.connecteChildLock:
return {child_lock: value ? 'LOCK' : 'UNLOCK'};
case tuya.dataPoints.connecteTempFloor:
return {external_temperature: value};
case tuya.dataPoints.connecteSensorType:
return {sensor: {0: 'internal', 1: 'external', 2: 'both'}[value]};
case tuya.dataPoints.connecteHysteresis:
return {hysteresis: value};
case tuya.dataPoints.connecteRunningState:
return {running_state: value ? 'heat' : 'idle'};
case tuya.dataPoints.connecteTempProgram:
break;
case tuya.dataPoints.connecteOpenWindow:
return {window_detection: value ? 'ON' : 'OFF'};
case tuya.dataPoints.connecteMaxProtectTemp:
return {max_temperature_protection: value};
default:
meta.logger.warn(`zigbee-herdsman-converters:connecte_thermostat: Unrecognized DP #${
dp} with data ${JSON.stringify(dpValue)}`);
}
},
},
saswell_thermostat: {
cluster: 'manuSpecificTuya',
type: ['commandDataResponse', 'commandDataReport'],
Expand Down
62 changes: 62 additions & 0 deletions converters/toZigbee.js
Original file line number Diff line number Diff line change
Expand Up @@ -3005,6 +3005,68 @@ const converters = {
await entity.read('closuresWindowCovering', [isPosition ? 'currentPositionLiftPercentage' : 'currentPositionTiltPercentage']);
},
},
connecte_thermostat: {
key: [
'child_lock', 'current_heating_setpoint', 'local_temperature_calibration', 'max_temperature_protection', 'window_detection',
'hysteresis', 'state', 'away_mode', 'sensor', 'system_mode',
],
convertSet: async (entity, key, value, meta) => {
switch (key) {
case 'state':
await tuya.sendDataPointBool(entity, tuya.dataPoints.connecteState, value === 'ON');
break;
case 'child_lock':
await tuya.sendDataPointBool(entity, tuya.dataPoints.connecteChildLock, value === 'LOCK');
break;
case 'local_temperature_calibration':
if (value < 0) value = 0xFFFFFFFF + value + 1;
await tuya.sendDataPointValue(entity, tuya.dataPoints.connecteTempCalibration, value);
break;
case 'hysteresis':
// value = Math.round(value * 10);
await tuya.sendDataPointValue(entity, tuya.dataPoints.connecteHysteresis, value);
break;
case 'max_temperature_protection':
await tuya.sendDataPointValue(entity, tuya.dataPoints.connecteMaxProtectTemp, Math.round(value));
break;
case 'current_heating_setpoint':
await tuya.sendDataPointValue(entity, tuya.dataPoints.connecteHeatingSetpoint, value);
break;
case 'sensor':
await tuya.sendDataPointEnum(
entity,
tuya.dataPoints.connecteSensorType,
{'internal': 0, 'external': 1, 'both': 2}[value]);
break;
case 'system_mode':
switch (value) {
case 'heat':
await tuya.sendDataPointEnum(entity, tuya.dataPoints.connecteMode, 0 /* manual */);
break;
case 'auto':
await tuya.sendDataPointEnum(entity, tuya.dataPoints.connecteMode, 1 /* auto */);
break;
}
break;
case 'away_mode':
switch (value) {
case 'ON':
await tuya.sendDataPointEnum(entity, tuya.dataPoints.connecteMode, 2 /* auto */);
break;
case 'OFF':
await tuya.sendDataPointEnum(entity, tuya.dataPoints.connecteMode, 0 /* manual */);
break;
}
break;
case 'window_detection':
await tuya.sendDataPointBool(entity, tuya.dataPoints.connecteOpenWindow, value === 'ON');
break;
default: // Unknown key
throw new Error(`Unhandled key toZigbee.connecte_thermostat ${key}`);
}
},
},

moes_thermostat_child_lock: {
key: ['child_lock'],
convertSet: async (entity, key, value, meta) => {
Expand Down
50 changes: 50 additions & 0 deletions devices/connecte.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
const exposes = require('../lib/exposes');
const fz = {...require('../converters/fromZigbee'), legacy: require('../lib/legacy').fromZigbee};
const tz = require('../converters/toZigbee');
const tuya = require('../lib/tuya');
const e = exposes.presets;
const ea = exposes.access;

module.exports = [
{
fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_4hbx5cvx'}],
model: '4500994',
vendor: 'Connecte',
description: 'Smart thermostat',
fromZigbee: [fz.connecte_thermostat],
toZigbee: [tz.connecte_thermostat],
onEvent: tuya.onEventSetTime,
configure: async (device, coordinatorEndpoint, logger) => {
const endpoint = device.getEndpoint(1);
// Do a "magic" read on the basic cluster to trigger the thermostat start reporting.
await endpoint.read('genBasic', ['manufacturerName', 'zclVersion', 'appVersion', 'modelId', 'powerSource', 0xfffe]);
},
exposes: [
exposes.binary('state', ea.STATE_SET, 'ON', 'OFF')
.withDescription('On/off state of the switch'),
e.child_lock(),
e.window_detection(),
exposes.climate()
.withSetpoint('current_heating_setpoint', 5, 35, 1, ea.STATE_SET)
.withLocalTemperature(ea.STATE)
.withLocalTemperatureCalibration(-9, 9, 1, ea.STATE_SET)
.withSystemMode(['heat', 'auto'], ea.STATE_SET)
.withRunningState(['idle', 'heat'], ea.STATE)
.withAwayMode()
.withSensor(['internal', 'external', 'both']),
exposes.numeric('external_temperature', ea.STATE)
.withUnit('°C')
.withDescription('Current temperature measured on the external sensor (floor)'),
exposes.numeric('hysteresis', ea.STATE_SET)
.withDescription('The difference between the temperature at which the thermostat switches off, ' +
'and the temperature at which it switches on again.')
.withValueMin(1)
.withValueMax(9),
exposes.numeric('max_temperature_protection', ea.STATE_SET)
.withUnit('°C')
.withDescription('Max guarding temperature')
.withValueMin(20)
.withValueMax(95),
],
},
];
14 changes: 14 additions & 0 deletions lib/tuya.js
Original file line number Diff line number Diff line change
Expand Up @@ -645,6 +645,20 @@ const dataPoints = {
// Moes switch with optional neutral
moesSwitchPowerOnBehavior: 14,
moesSwitchIndicateLight: 15,
// Connecte thermostat
connecteState: 1,
connecteMode: 2,
connecteHeatingSetpoint: 16,
connecteLocalTemp: 24,
connecteTempCalibration: 28,
connecteChildLock: 30,
connecteTempFloor: 101,
connecteSensorType: 102,
connecteHysteresis: 103,
connecteRunningState: 104,
connecteTempProgram: 105,
connecteOpenWindow: 106,
connecteMaxProtectTemp: 107,
};

const thermostatWeekFormat = {
Expand Down

0 comments on commit 2fe8e40

Please sign in to comment.