diff --git a/converters/fromZigbee.js b/converters/fromZigbee.js index 000e4f63adda4..72b5f19ef7755 100644 --- a/converters/fromZigbee.js +++ b/converters/fromZigbee.js @@ -823,6 +823,14 @@ const converters = { } }, }, + generic_temperature_change: { + cid: 'msTemperatureMeasurement', + type: 'devChange', + convert: (model, msg, publish, options) => { + const temperature = parseFloat(msg.data.data['measuredValue']) / 100.0; + return {temperature: precisionRoundOptions(temperature, options, 'temperature')}; + }, + }, xiaomi_temperature: { cid: 'msTemperatureMeasurement', type: 'attReport', @@ -4225,6 +4233,44 @@ const converters = { return {action: `${direction}`}; }, }, + cover_position: { + cid: 'genLevelCtrl', + type: 'devChange', + convert: (model, msg, publish, options) => { + const currentLevel = msg.data.data['currentLevel']; + const position = Math.round(Number(currentLevel) / 2.55).toString(); + const state = position > 0 ? 'OPEN' : 'CLOSE'; + return {state: state, position: position}; + }, + }, + cover_position_report: { + cid: 'genLevelCtrl', + type: 'attReport', + convert: (model, msg, publish, options) => { + const currentLevel = msg.data.data['currentLevel']; + const position = Math.round(Number(currentLevel) / 2.55).toString(); + const state = position > 0 ? 'OPEN' : 'CLOSE'; + return {state: state, position: position}; + }, + }, + keen_home_smart_vent_pressure: { + cid: 'msPressureMeasurement', + type: 'devChange', + convert: (model, msg, publish, options) => { + // '{"cid":"msPressureMeasurement","data":{"32":990494}}' + const pressure = parseFloat(msg.data.data['32']) / 1000.0; + return {pressure: precisionRoundOptions(pressure, options, 'pressure')}; + }, + }, + keen_home_smart_vent_pressure_report: { + cid: 'msPressureMeasurement', + type: 'attReport', + convert: (model, msg, publish, options) => { + // '{"cid":"msPressureMeasurement","data":{"32":990494}}' + const pressure = parseFloat(msg.data.data['32']) / 1000.0; + return {pressure: precisionRoundOptions(pressure, options, 'pressure')}; + }, + }, // Ignore converters (these message dont need parsing). ignore_onoff_report: { diff --git a/converters/toZigbee.js b/converters/toZigbee.js index cc8c6be34fe1a..f99cce87481e7 100644 --- a/converters/toZigbee.js +++ b/converters/toZigbee.js @@ -2359,6 +2359,55 @@ const converters = { return converters.light_colortemp.convert(key, value, message, type, postfix); }, }, + cover_open_close: { + key: ['state'], + convert: (key, value, message, type, postfix) => { + if (type === 'set') { + if (typeof value !== 'string') { + return; + } + + const positionByState = { + 'open': 100, + 'close': 0, + }; + + value = positionByState[value.toLowerCase()]; + } + + return converters.cover_position.convert(key, value, message, type, postfix); + }, + }, + cover_position: { + key: ['position'], + convert: (key, value, message, type, postfix) => { + const cid = 'genLevelCtrl'; + const attrId = 'currentLevel'; + + if (type === 'set') { + value = Math.round(Number(value) * 2.55).toString(); + return { + cid: cid, + cmd: 'moveToLevelWithOnOff', + cmdType: 'functional', + zclData: { + level: value, + transtime: 0, + }, + cfg: cfg.default, + readAfterWriteTime: 0, + }; + } else if (type === 'get') { + return { + cid: cid, + cmd: 'read', + cmdType: 'foundation', + zclData: [{attrId: zclId.attr(cid, attrId).value}], + cfg: cfg.default, + }; + } + }, + }, // Ignore converters ignore_transition: { diff --git a/devices.js b/devices.js index 0e36f90bba6d6..aa59ac81b3df3 100755 --- a/devices.js +++ b/devices.js @@ -8155,6 +8155,42 @@ const devices = [ }, }, + // Keen Home + { + zigbeeModel: ['SV01-410-MP-1.0', 'SV01-410-MP-1.4', 'SV01-410-MP-1.5'], + model: 'SV01', + vendor: 'Keen Home', + description: 'Smart vent', + supports: 'open, close, position, temperature, pressure, battery', + fromZigbee: [ + fz.cover_position, + fz.cover_position_report, + fz.generic_temperature, + fz.generic_temperature_change, + fz.generic_battery, + fz.generic_battery_change, + fz.keen_home_smart_vent_pressure, + fz.keen_home_smart_vent_pressure_report, + fz.ignore_onoff_change, + fz.ignore_onoff_report, + ], + toZigbee: [ + tz.cover_open_close, + tz.cover_position, + ], + configure: (ieeeAddr, shepherd, coordinator, callback) => { + const device = shepherd.find(ieeeAddr, 1); + const actions = [ + (cb) => device.bind('genLevelCtrl', coordinator, cb), + (cb) => device.bind('genPowerCfg', coordinator, cb), + (cb) => device.bind('msTemperatureMeasurement', coordinator, cb), + (cb) => device.bind('msPressureMeasurement', coordinator, cb), + ]; + + execute(device, actions, callback); + }, + }, + // ELKO { zigbeeModel: ['ElkoDimmerZHA'],