From a0c0f2ba5d76371e792e482bcd0c0e19a8d1e867 Mon Sep 17 00:00:00 2001 From: vihren Date: Mon, 15 Jul 2024 12:40:18 +0000 Subject: [PATCH 1/2] add support for MultiTerm ZC0101 --- src/devices/multiterm.ts | 91 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 src/devices/multiterm.ts diff --git a/src/devices/multiterm.ts b/src/devices/multiterm.ts new file mode 100644 index 0000000000000..fc27e4b0ddf10 --- /dev/null +++ b/src/devices/multiterm.ts @@ -0,0 +1,91 @@ +import fz from '../converters/fromZigbee'; +import tz from '../converters/toZigbee'; +import * as exposes from '../lib/exposes'; +import {deviceEndpoints} from '../lib/modernExtend'; +import * as reporting from '../lib/reporting'; +import {Definition, Fz, Tz} from '../lib/types'; +import * as utils from '../lib/utils'; + +const e = exposes.presets; +const ea = exposes.access; + +const endpoints = { + silent_mode: 8, + heating_cooling: 9, + electric_valve: 10, +}; + +const states = { + silent_mode: ['Inactive', 'Active'], + heating_cooling: ['Heating', 'Cooling'], + electric_valve: ['Off', 'On'], +}; + +const fzLocal = { + binary_output: { + cluster: 'genBinaryOutput', + type: ['attributeReport', 'readResponse'], + convert: (model, msg, publish, options, meta) => { + return {state: msg.data.presentValue == 1 ? msg.data.activeText : msg.data.inactiveText}; + }, + } satisfies Fz.Converter, +}; + +const tzLocal = { + fan_mode: { + ...tz.fan_mode, + convertSet: async (entity, key, value, meta) => { + if (String(value).toLowerCase() === 'on') value = 'high'; + return tz.fan_mode.convertSet(entity, key, value, meta); + }, + } satisfies Tz.Converter, + binary_output: { + key: Object.keys(endpoints), + convertSet: async (entity, key, value, meta) => { + const ep = meta.device.getEndpoint(utils.getFromLookup(key, endpoints)); + const currentStates = utils.getFromLookup(key, states); + const newState = currentStates.indexOf(String(value)); + const payload = {0x0055: {value: newState, type: 0x10}}; + await ep.write('genBinaryOutput', payload); + const state = {state: {}}; + const normalizedKey = key.replace('/', '_').replace(' ', '_').toLowerCase(); + state.state = {[normalizedKey]: value}; + return state; + }, + convertGet: async (entity, key, meta) => { + const ep = meta.device.getEndpoint(utils.getFromLookup(key, endpoints)); + await ep.read('genBinaryOutput', ['presentValue', 'activeText', 'inactiveText', 'description']); + }, + } satisfies Tz.Converter, +}; + +const definitions: Definition[] = [ + { + zigbeeModel: ['ZC0101'], + model: 'ZC0101', + vendor: 'MultiTerm', + description: 'ZeeFan Fan Coil Unit controller', + extend: [deviceEndpoints({endpoints: {'8': 8, '9': 9, '10': 10}})], + meta: {multiEndpoint: true}, + fromZigbee: [fz.fan, fzLocal.binary_output], + toZigbee: [tzLocal.fan_mode, tzLocal.binary_output], + exposes: [ + e.fan().withModes(['off', 'low', 'medium', 'high', 'on']).withLabel('Fan Control'), + e.enum('silent_mode', ea.ALL, states.silent_mode).withLabel('Silent mode').withCategory('config'), + e.enum('heating_cooling', ea.ALL, states.heating_cooling).withLabel('Heating/Cooling').withCategory('config'), + e.enum('electric_valve', ea.ALL, states.electric_valve).withLabel('Electric Valve').withCategory('config'), + ], + configure: async (device, coordinatorEndpoint, logger) => { + const fanEp = device.getEndpoint(endpoints.silent_mode); + const hcEp = device.getEndpoint(endpoints.heating_cooling); + const evEp = device.getEndpoint(endpoints.electric_valve); + await reporting.bind(fanEp, coordinatorEndpoint, ['genBinaryOutput']); + await reporting.bind(fanEp, coordinatorEndpoint, ['hvacFanCtrl']); + await reporting.bind(hcEp, coordinatorEndpoint, ['genBinaryOutput']); + await reporting.bind(evEp, coordinatorEndpoint, ['genBinaryOutput']); + }, + }, +]; + +export default definitions; +module.exports = definitions; From 7b352f39988f3301bb99a3845f5f0e2a45db7fd2 Mon Sep 17 00:00:00 2001 From: vkanev Date: Tue, 16 Jul 2024 05:07:17 +0000 Subject: [PATCH 2/2] change states to lower case --- src/devices/multiterm.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/devices/multiterm.ts b/src/devices/multiterm.ts index fc27e4b0ddf10..b6122eec3d02f 100644 --- a/src/devices/multiterm.ts +++ b/src/devices/multiterm.ts @@ -16,9 +16,9 @@ const endpoints = { }; const states = { - silent_mode: ['Inactive', 'Active'], - heating_cooling: ['Heating', 'Cooling'], - electric_valve: ['Off', 'On'], + silent_mode: ['inactive', 'active'], + heating_cooling: ['heating', 'cooling'], + electric_valve: ['off', 'on'], }; const fzLocal = { @@ -64,7 +64,7 @@ const definitions: Definition[] = [ zigbeeModel: ['ZC0101'], model: 'ZC0101', vendor: 'MultiTerm', - description: 'ZeeFan Fan Coil Unit controller', + description: 'ZeeFan fan coil unit controller', extend: [deviceEndpoints({endpoints: {'8': 8, '9': 9, '10': 10}})], meta: {multiEndpoint: true}, fromZigbee: [fz.fan, fzLocal.binary_output],