-
-
Save Koenkk/2835843081f821e0d01d5a892c5be3cf to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 ota = require('zigbee-herdsman-converters/lib/ota'); | |
const tuya = require('zigbee-herdsman-converters/lib/tuya'); | |
const utils = require('zigbee-herdsman-converters/lib/utils'); | |
const globalStore = require('zigbee-herdsman-converters/lib/store'); | |
const e = exposes.presets; | |
const ea = exposes.access; | |
const fzLocal = { | |
ZMCSW032D_cover_position: { | |
cluster: 'closuresWindowCovering', | |
type: ['attributeReport', 'readResponse'], | |
options: [ | |
exposes.options.invert_cover(), | |
exposes.numeric('time_close') | |
.withDescription(`Set the full closing time of the roller shutter (e.g. set it to 20) (value is in s).`), | |
exposes.numeric('time_open') | |
.withDescription(`Set the full opening time of the roller shutter (e.g. set it to 21) (value is in s).`), | |
], | |
convert: (model, msg, publish, options, meta) => { | |
const result = {}; | |
const timeCoverSetMiddle = 60; | |
// https://github.com/Koenkk/zigbee-herdsman-converters/pull/1336 | |
// Need to add time_close and time_open in your configuration.yaml after friendly_name (and set your time) | |
if (options.hasOwnProperty('time_close') && options.hasOwnProperty('time_open')) { | |
if (!globalStore.hasValue(msg.endpoint, 'position')) { | |
globalStore.putValue(msg.endpoint, 'position', {lastPreviousAction: -1, CurrentPosition: -1, since: false}); | |
} | |
const entry = globalStore.getValue(msg.endpoint, 'position'); | |
// ignore if first action is middle and ignore action middle if previous action is middle | |
if (msg.data.hasOwnProperty('currentPositionLiftPercentage') && msg.data['currentPositionLiftPercentage'] == 50 ) { | |
if ((entry.CurrentPosition == -1 && entry.lastPreviousAction == -1) || | |
entry.lastPreviousAction == 50 ) { | |
meta.logger.warn(`ZMCSW032D ignore action `); | |
return; | |
} | |
} | |
let currentPosition = entry.CurrentPosition; | |
const lastPreviousAction = entry.lastPreviousAction; | |
const deltaTimeSec = Math.floor((Date.now() - entry.since)/1000); // convert to sec | |
entry.since = Date.now(); | |
entry.lastPreviousAction = msg.data['currentPositionLiftPercentage']; | |
if (msg.data.hasOwnProperty('currentPositionLiftPercentage') && msg.data['currentPositionLiftPercentage'] == 50 ) { | |
if (deltaTimeSec < timeCoverSetMiddle || deltaTimeSec > timeCoverSetMiddle) { | |
if (lastPreviousAction == 100 ) { | |
// Open | |
currentPosition = currentPosition == -1 ? 0 : currentPosition; | |
currentPosition = currentPosition + ((deltaTimeSec * 100)/options.time_open); | |
} else if (lastPreviousAction == 0 ) { | |
// Close | |
currentPosition = currentPosition == -1 ? 100 : currentPosition; | |
currentPosition = currentPosition - ((deltaTimeSec * 100)/options.time_close); | |
} | |
currentPosition = currentPosition > 100 ? 100 : currentPosition; | |
currentPosition = currentPosition < 0 ? 0 : currentPosition; | |
} | |
} | |
entry.CurrentPosition = currentPosition; | |
if (msg.data.hasOwnProperty('currentPositionLiftPercentage') && msg.data['currentPositionLiftPercentage'] !== 50 ) { | |
// postion cast float to int | |
result.position = currentPosition | 0; | |
} else { | |
if (deltaTimeSec < timeCoverSetMiddle || deltaTimeSec > timeCoverSetMiddle) { | |
// postion cast float to int | |
result.position = currentPosition | 0; | |
} else { | |
entry.CurrentPosition = lastPreviousAction; | |
result.position = lastPreviousAction; | |
} | |
} | |
result.position = options.invert_cover ? 100 - result.position : result.position; | |
} else { | |
// Previous solution without time_close and time_open | |
if (msg.data.hasOwnProperty('currentPositionLiftPercentage') && msg.data['currentPositionLiftPercentage'] !== 50) { | |
const liftPercentage = msg.data['currentPositionLiftPercentage']; | |
result.position = liftPercentage; | |
result.position = options.invert_cover ? 100 - result.position : result.position; | |
} | |
} | |
// Add the state | |
if ('position' in result) { | |
result.state = result.position === 0 ? 'CLOSE' : 'OPEN'; | |
} | |
return result; | |
}, | |
} | |
} | |
const definition = { | |
zigbeeModel: ['TS0302'], | |
model: 'ZM-CSW032-D', | |
vendor: 'Zemismart', | |
description: 'Curtain/roller blind switch', | |
fromZigbee: [fz.ignore_basic_report, fzLocal.ZMCSW032D_cover_position], | |
toZigbee: [tz.cover_state, tz.ZMCSW032D_cover_position], | |
exposes: [e.cover_position()], | |
meta: {multiEndpoint: true}, | |
configure: async (device, coordinatorEndpoint, logger) => { | |
const endpoint = device.getEndpoint(1); | |
await reporting.bind(endpoint, coordinatorEndpoint, ['closuresWindowCovering']); | |
// Configure reporing of currentPositionLiftPercentage always fails. | |
// https://github.com/Koenkk/zigbee2mqtt/issues/3216 | |
}, | |
}; | |
module.exports = definition; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment