zigbee2mqtt icon indicating copy to clipboard operation
zigbee2mqtt copied to clipboard

[New device support]: Zemismart Blind Motor ZM25EL

Open flybrys opened this issue 3 years ago • 6 comments

Link

https://www.zemismart.com/products/zm25el

Database entry

{"id":41,"type":"EndDevice","ieeeAddr":"0x540f57fffeffc921","nwkAddr":37223,"manufId":4098,"manufName":"_TZE200_68nvbio9","powerSource":"Battery","modelId":"TS0601","epList":[1],"endpoints":{"1":{"profId":260,"epId":1,"devId":81,"inClusterList":[0,4,5,61184],"outClusterList":[25,10],"clusters":{"genBasic":{"attributes":{"65503":"G\u0013�\u0011L\u0013�\u0011X\u0013�*\u0011","65506":31,"65508":0,"appVersion":72,"modelId":"TS0601","manufacturerName":"_TZE200_68nvbio9","powerSource":3,"zclVersion":3,"stackVersion":0,"hwVersion":1,"dateCode":""}}},"binds":[],"configuredReportings":[],"meta":{}}},"appVersion":72,"stackVersion":0,"hwVersion":1,"dateCode":"","zclVersion":3,"interviewCompleted":true,"meta":{},"lastSeen":1663710999432,"defaultSendRequestWhen":"immediate"}

Comments

Recently purchased a few of these and they work fine with the existing integration however there are a few features missing. I tried following the documentation however I got stuck on trying to use an existing converter, it wasn't all that clear to me.

Missing:

  • Battery Level. I believe this reports after each command as I've been charging it and noticing the value increasing

Received Zigbee message from 'Bedroom Blinds', type 'commandDataReport', cluster 'manuSpecificTuya', data '{"dpValues":[{"data":{"data":[0,0,0,90],"type":"Buffer"},"datatype":2,"dp":13}],"seq":256}' from endpoint 1 with groupID 0

  • Setting of top & bottom limits - Can do this in the TuYa app however unsure how to get logs for it from Zigbee2Mqtt. I have a remote on the way which allows that function so I'll see if that triggers a report somehow and post back.

In the meantime, if the battery level can be added it will help me keep them charged and maintain the WAF

External converter

No response

Supported color modes

No response

Color temperature range

No response

flybrys avatar Sep 20 '22 22:09 flybrys

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 7 days

github-actions[bot] avatar Oct 21 '22 00:10 github-actions[bot]

Bump not stale

flybrys avatar Oct 21 '22 00:10 flybrys

This works for me with external converter from https://github.com/Koenkk/zigbee2mqtt/issues/11251

Hamper avatar Oct 21 '22 08:10 Hamper

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 7 days

github-actions[bot] avatar Nov 22 '22 00:11 github-actions[bot]

This works for me with external converter from #11251

I am using the external converter from that thread as well. However, it would be awesome if setting the limits (and position to go to?) worked.

@brywithawhy has your remote arrived? I was considering ordering one as well so that I could at least use that to set the limits in the meantime.

simonwillcock avatar Nov 25 '22 00:11 simonwillcock

@simonwillcock Yes, I got the remote and set the limits with it. Once I did this the positioning features work. I recommend getting one regardless, there's some other features you can do with it like stepping to get the exact limits set.

The external converter above works for me however the battery state varies by about 30% with up and down movements. Would be good if it could average the data somehow

flybrys avatar Nov 25 '22 00:11 flybrys

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 7 days

github-actions[bot] avatar Dec 26 '22 00:12 github-actions[bot]

Hi,

I did some tweaking and copied the tuya_cover function and added the battery case statement. This gives me all the other working items, and the battery reading. The only change on the tuya_cover function is adding the function 13 (unfortunately the battery definition is 20, so I have to hard code the 13). Here is the code for my external_converter .ts file:

`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 e = exposes.presets; const ea = exposes.access; const tuya = require('zigbee-herdsman-converters/lib/tuya'); const globalStore = require('zigbee-herdsman-converters/lib/store');

const fzLocal = { ZM25EL: { cluster: 'manuSpecificTuya', type: ['commandDataReport', 'commandDataResponse'], options: [exposes.options.invert_cover()], convert: (model, msg, publish, options, meta) => {

   const result = {};

   // Iterate through dpValues in case of some zigbee models returning multiple dp values in one message
   for (const dpValue of msg.data.dpValues) {
     const dp = dpValue.dp;
     const value = tuya.getDataValue(dpValue);

     switch (dp) {
       case tuya.dataPoints.coverPosition: // Started moving to position (triggered from Zigbee)
       case tuya.dataPoints.coverArrived: { // Arrived at position
           const invert = tuya.isCoverInverted(meta.device.manufacturerName) ? !options.invert_cover : options.invert_cover;
           const position = invert ? 100 - (value & 0xff) : value & 0xff;
           const running = dp !== tuya.dataPoints.coverArrived;

           // Not all covers report coverArrived, so set running to false if device doesn't report position
           // for a few seconds
           clearTimeout(globalStore.getValue(msg.endpoint, 'running_timer'));
           if (running) {
             const timer = setTimeout(() => publish({running: false}), 3 * 1000);
             globalStore.putValue(msg.endpoint, 'running_timer', timer);
           }

           if (position > 0 && position <= 100) {
             result.running = running;
             result.position = position;
             result.state = 'OPEN';
           } else if (position == 0) {
             // Report fully closed
             result.running = running;
             result.position = position;
             result.state = 'CLOSE';
           } else {
             result.running = running; // Not calibrated yet, no position is available
           }
         }
         break;
      case tuya.dataPoints.coverSpeed: // Cover is reporting its current speed setting
         result.motor_speed = value;
         break;
      case tuya.dataPoints.state: // Ignore the cover state, it's not reliable between different covers!
         break;
      case tuya.dataPoints.coverChange: // Ignore manual cover change, it's not reliable between different covers!
         break;
      case tuya.dataPoints.config: // Returned by configuration set; ignore
         break;
  case 13:
         result.battery =  value;
         break;
      default: // Unknown code
         meta.logger.warn(`TuYa_cover_control: Unhandled DP #${dp} for ${meta.device.manufacturerName}:
                ${JSON.stringify(dpValue)}`);
    }
  }

  return result;
},

}, };

const definition = { fingerprint: [ { modelID: 'TS0601', manufacturerName: '_TZE200_68nvbio9', }, ], model: 'ZM25EL', vendor: 'TuYa', description: 'Zemismart Smart Zigbee Roller Shade Motor Built in Battery', fromZigbee: [fzLocal.ZM25EL, fz.ignore_basic_report], toZigbee: [tz.tuya_cover_control, tz.tuya_cover_options], exposes: [e.cover_position().setAccess('position', ea.STATE_SET), exposes.numeric('battery', ea.STATE).withValueMin(0).withValueMax(100).withValueStep(1).withUnit('%') ], meta: { }, };

module.exports = definition;`

mavrick01 avatar Jan 06 '23 10:01 mavrick01