zigbee2mqtt / hassio-zigbee2mqtt

Official Zigbee2MQTT Home Assistant add-on
https://www.zigbee2mqtt.io
Apache License 2.0
1.16k stars 417 forks source link

Version 1.30.2-1 does not work #471

Closed dankarization closed 1 year ago

dankarization commented 1 year ago

Description of the issue

After updating to the last version I constantly get this error, 1.30-1.1 works fine for me

Addon version

1.30.2-1

Platform

Home Assistant 2023.3.1 Supervisor 2023.01.1 Frontend 20230302.0 - latest I am running supervised install on armbian

Logs of the issue (if applicable)

[11:49:47] INFO: Preparing to start... [11:49:49] INFO: Socat not enabled [11:49:58] INFO: Starting Zigbee2MQTT... /app/node_modules/zigbee-herdsman-converters/index.js:91 if (converter.options) { ^ TypeError: Cannot read properties of undefined (reading 'options') at Object.addDefinition [as addDeviceDefinition] (/app/node_modules/zigbee-herdsman-converters/index.js:91:23) at new ExternalConverters (/app/lib/extension/externalConverters.ts:15:17) at new Controller (/app/lib/controller.ts:84:58) at start (/app/index.js:106:18)

Koenkk commented 1 year ago

You are using an external converter which is not compatible with the latest z2m version. Update your external converter or post it here so I can integrate it for out-of-the-box support.

dankarization commented 1 year ago

How can I at least check whaat converter from all I have is not compatible?

dankarization commented 1 year ago

Will post all my converters anyway

dankarization commented 1 year ago
const {
    fromZigbeeConverters,
    toZigbeeConverters,
    exposes
} = require('zigbee-herdsman-converters');

const e = exposes.presets;
const fz = fromZigbeeConverters;
const tz = toZigbeeConverters;

const defaulPumpRuntime = 30;

const ACCESS_STATE = 0b001, ACCESS_WRITE = 0b010, ACCESS_READ = 0b100;
// get object property name (key) by it's value
const getKey = (object, value) => {
    for (const key in object) {
        if (object[key]==value) return key;
    }
};

const getOptions = (definition, entity) => {
    const result = {};
    const allowed = ['disableDefaultResponse', 'manufacturerCode', 'timeout'];
    if (definition && definition.meta) {
        for (const key of Object.keys(definition.meta)) {
            if (allowed.includes(key)) {
                const value = definition.meta[key];
                result[key] = typeof value === 'function' ? value(entity) : value;
            }
        }
    }
    console.log(result);
    return result;
};

const myFZ = {
  flower_ws_output: {
      cluster: 'genOnOff',
      type: ['attributeReport', 'readResponse'],
      convert: (model, msg, publish, options, meta) => {
          //console.log(msg);
          if (msg.endpoint.ID < 5) {
              const key = `pump_${msg.endpoint.ID-1}`;
              const payload = {};
              payload[key] = msg.data['onOff'] === 1 ? 'ON' : 'OFF';
              return payload;
          }
          if (msg.endpoint.ID == 6) {
              const key = `water_leak`;
              const payload = {};
              payload[key] = msg.data['onOff'] === 1 ? 'true' : 'false';
              return payload;
          }
          if (msg.endpoint.ID == 7) {
              const key = `water_low_level`;
              const payload = {};
              payload[key] = msg.data['onOff'] === 1 ? 'true' : 'false';
              return payload;
          }
      },
  },
};

const myTZ = {
  flower_ws_on_off: {
      key: ['pump_1'],
      key2: ['state'],
      convertSet: async (entity, key2, value, meta) => {
          await entity.command('genOnOff', value.toLowerCase(), {}, getOptions(meta.mapped, entity));
          if (value.toLowerCase() === 'toggle') {
              const currentState = meta.state[`state${meta.endpoint_name ? `_${meta.endpoint_name}` : ''}`];
              return currentState ? {state: {state: currentState === 'OFF' ? 'ON' : 'OFF'}} : {};
          } else {
              return {state: {state: value.toUpperCase()}};
          }
      },
      convertGet: async (entity, key2, meta) => {
          await entity.read('genOnOff', ['onOff']);
      },
  },
  flower_ws_pump_trigger: {
      key: ['trigger'],
      convertSet: async (entity, key, value, meta) => {
          value = parseInt(value);
          if (!value) {
              return;
          }

          await entity.command('genOnOff', 'onWithTimedOff', {ctrlbits: 0, ontime: Math.round(value*10), offwaittime: 0});

      },
  },
};

const hass = {
  pump_1: {
     type: 'switch',
     object_id: 'pump_1',
     discovery_payload: {
         payload_off: 'OFF',
         payload_on: 'ON',
         value_template: '{{ value_json.state_l2 }}',
         command_topic: true,
         command_topic_prefix: 'l2',
     }
 },
 pump_1_timer: {
     type: 'switch',
     object_id: 'pump_1_timer',
     discovery_payload: {
         payload_off: 'OFF',
         payload_on: '{"trigger": 10}',
         value_template: '{{ value_json.state_l2 }}',
         command_topic: true,
         command_topic_prefix: 'l2',
     }
 },
 pump_2: {
     type: 'switch',
     object_id: 'pump_2',
     discovery_payload: {
         payload_off: 'OFF',
         payload_on: 'ON',
         value_template: '{{ value_json.state_l3 }}',
         command_topic: true,
         command_topic_prefix: 'l3',
     }
 },
 pump_2_timer: {
     type: 'switch',
     object_id: 'pump_2_timer',
     discovery_payload: {
         payload_off: 'OFF',
         payload_on: '{"trigger": 10}',
         value_template: '{{ value_json.state_l3 }}',
         command_topic: true,
         command_topic_prefix: 'l3',
     }
 },
 pump_3: {
     type: 'switch',
     object_id: 'pump_3',
     discovery_payload: {
         payload_off: 'OFF',
         payload_on: 'ON',
         value_template: '{{ value_json.state_l4 }}',
         command_topic: true,
         command_topic_prefix: 'l4',
     }
 },
 pump_3_timer: {
     type: 'switch',
     object_id: 'pump_3_timer',
     discovery_payload: {
         payload_off: 'OFF',
         payload_on: '{"trigger": 10}',
         value_template: '{{ value_json.state_l4 }}',
         command_topic: true,
         command_topic_prefix: 'l4',
     }
 },
 buzzer: {
     type: 'switch',
     object_id: 'buzzer',
     discovery_payload: {
         payload_off: 'OFF',
         payload_on: 'ON',
         value_template: '{{ value_json.state_l5 }}',
         command_topic: true,
         command_topic_prefix: 'l5',
     }
 },
 water_leak: {
     type: 'binary_sensor',
     object_id: 'water_leak',
     discovery_payload: {
         device_class: 'moisture',
         payload_off: 'OFF',
         payload_on: 'ON',
         value_template: '{{ value_json.state_l6 }}',
     }
 },
 water_low_level: {
     type: 'binary_sensor',
     object_id: 'water_low_level',
     discovery_payload: {
         device_class: 'battery',
         payload_off: 'OFF',
         payload_on: 'ON',
         value_template: '{{ value_json.state_l7 }}',
     }
 },
}
const device =  {
      zigbeeModel: ['DIYRuZ_Flower_WS'],
      model: 'DIYRuZ_Flower_WS',
      vendor: 'modkam.ru',
      description: '[Flower Water Station](https://modkam.ru/)',
      homeassistant: [
          hass.pump_1, hass.pump_1_timer,
          hass.pump_2, hass.pump_2_timer,
          hass.pump_3, hass.pump_3_timer,
          hass.buzzer,
          hass.water_leak, hass.water_low_level,
      ],
      fromZigbee: [
          myFZ.flower_ws_output, fz.on_off//, fz.ptvo_multistate_action, fz.legacy_ptvo_switch_buttons, fz.ptvo_switch_uart,
          //fz.ptvo_switch_analog_input, fz.brightness, fz.ignore_basic_report, 
      ],
      toZigbee: [
          tz.on_off, myTZ.flower_ws_pump_trigger//myTZ.flower_ws_on_off, tz.ptvo_switch_trigger,
      ],
      exposes: [
          exposes.binary('state', ACCESS_STATE | ACCESS_WRITE | ACCESS_READ, 'ON', 'OFF').withEndpoint('l2').withDescription('Pump 1'),
          exposes.numeric('trigger', ACCESS_WRITE).withEndpoint('l2').withDescription('On time').withUnit('seconds'),
          exposes.binary('state', ACCESS_STATE | ACCESS_WRITE | ACCESS_READ, 'ON', 'OFF').withEndpoint('l3').withDescription('Pump 2'),
          exposes.numeric('trigger', ACCESS_WRITE).withEndpoint('l3').withDescription('On time').withUnit('seconds'),
          exposes.binary('state', ACCESS_STATE | ACCESS_WRITE | ACCESS_READ, 'ON', 'OFF').withEndpoint('l4').withDescription('Pump 3'),
          exposes.numeric('trigger', ACCESS_WRITE).withEndpoint('l4').withDescription('On time').withUnit('seconds'),
          exposes.binary('state', ACCESS_STATE | ACCESS_WRITE | ACCESS_READ, 'ON', 'OFF').withEndpoint('l5').withDescription('Buzzer'),
          exposes.binary('state', ACCESS_STATE, 'ON', 'OFF').withEndpoint('l6').withDescription('Water leak'),
          exposes.binary('state', ACCESS_STATE, 'ON', 'OFF').withEndpoint('l7').withDescription('Low level'),

          exposes.numeric('interval', exposes.access.SET).withEndpoint('l8').withDescription('Report interval').withUnit('seconds'),

          //exposes.numeric('threshold1', ACCESS_STATE | ACCESS_WRITE | ACCESS_READ).withUnit('ppm'),
          //e.switch().withEndpoint('l2'), e.switch().withEndpoint('l3'), e.switch().withEndpoint('l4'),
          //e.switch().withEndpoint('l5').withDescription('buzzer'),// e.switch().withEndpoint('l6'), e.switch().withEndpoint('l7'),
          //e.sos().withState('water_low_level', true, 'water low level').withEndpoint('l7'),
          //e.action(['OFF', 'ON']).withEndpoint('l7'),
          //e.action(['OFF', 'ON']).withEndpoint('l6'),
          //e.water_leak().withState('water_leak', true, 'water leak').withEndpoint('l6'),
          //water_leak: () => new Binary('water_leak', access.STATE, true, false).withDescription('Indicates whether the device detected a water leak').withEndpoint('l6'),s
          //e.battery_low(),
          //e.switch(),

      ],
      meta: {multiEndpoint: true},
      endpoint: (device) => {
          return {
              'l1': 1, 'l2': 2, 'l3': 3, 'l4': 4, 'l5': 5, 'l6': 6, 'l7': 7, 'l8': 8,
              'action': 1,
          };
      },
    };

module.exports = device;
dankarization commented 1 year ago
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 globalStore = require('zigbee-herdsman-converters/lib/store');
const e = exposes.presets;
const ea = exposes.access;

const definition = {
        fingerprint: [{modelID: 'TS0505B', manufacturerName: '_TZ3210_s9lumfhn'},
            {modelID: 'TS0505B', manufacturerName: '_TZ3210_s9lumfhn'}],
        model: 'ZLD-RCW',
        vendor: 'Moes',
        description: 'RGB+CCT Zigbee LED Downlight',
        toZigbee: extend.light_onoff_brightness_colortemp_color().toZigbee.concat([
            tz.tuya_do_not_disturb, tz.tuya_color_power_on_behavior,
        ]),
        meta: {applyRedFix: true, enhancedHue: false},
        fromZigbee: extend.light_onoff_brightness_colortemp_color().fromZigbee,
        exposes: extend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500], disableColorTempStartup: true,
            disablePowerOnBehavior: true}).exposes.concat([
            exposes.binary('do_not_disturb', ea.STATE_SET, true, false)
                .withDescription('Do not disturb mode'),
            exposes.enum('color_power_on_behavior', ea.STATE_SET, ['initial', 'previous', 'cutomized'])
                .withDescription('Power on behavior state'),
        ]),
};

module.exports = definition;
dankarization commented 1 year ago
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 globalStore = require('zigbee-herdsman-converters/lib/store');
const e = exposes.presets;
const ea = exposes.access;

const definition = {
        fingerprint: [{modelID: 'TS0505B', manufacturerName: '_TZ3210_r5afgmkl'},
            {modelID: 'TS0505B', manufacturerName: '_TZ3210_r5afgmkl'}],
        model: 'TS0505B',
        vendor: 'Tuya',
        description: 'RGB+CCT Zigbee E27 LightBulb',
        toZigbee: extend.light_onoff_brightness_colortemp_color().toZigbee.concat([
            tz.tuya_do_not_disturb, tz.tuya_color_power_on_behavior,
        ]),
        meta: {applyRedFix: true, enhancedHue: false},
        fromZigbee: extend.light_onoff_brightness_colortemp_color().fromZigbee,
        exposes: extend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500], disableColorTempStartup: true,
            disablePowerOnBehavior: true}).exposes.concat([
            exposes.binary('do_not_disturb', ea.STATE_SET, true, false)
                .withDescription('Do not disturb mode'),
            exposes.enum('color_power_on_behavior', ea.STATE_SET, ['initial', 'previous', 'cutomized'])
                .withDescription('Power on behavior state'),
        ]),
};

module.exports = definition;
dankarization commented 1 year ago
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 globalStore = require('zigbee-herdsman-converters/lib/store');
const e = exposes.presets;
const ea = exposes.access;

const definition = {
        zigbeeModel: ['ZB-DL01'],
        model: 'YSR-MINI-01_dimmer',
        vendor: 'YSRSAI',
        description: 'Zigbee LED controller (Dimmer)',
        toZigbee: extend.light_onoff_brightness().toZigbee.concat([
            tz.tuya_do_not_disturb, 
        ]),
        meta: {applyRedFix: true, enhancedHue: false},
        fromZigbee: extend.light_onoff_brightness().fromZigbee,
        exposes: extend.light_onoff_brightness({disablePowerOnBehavior: true}).exposes.concat([
            exposes.binary('do_not_disturb', ea.STATE_SET, true, false)
                .withDescription('Do not disturb mode')
        ]),

        extend: extend.light_onoff_brightness(),
};

module.exports = definition;
dankarization commented 1 year ago

3 of 4 devices from these converters here are working out of the box, but lack some functions. These converters add them

Koenkk commented 1 year ago

I see some of these functions have been added, can you let me know what functions are still missing when not using an external converter?

dankarization commented 1 year ago

All the lights lack do not disturb mode

Koenkk commented 1 year ago

This has been added recently, so it should work in z2m 1.30.2

dankarization commented 1 year ago

I was creating last converter like only a month before, but I will try delete them and see what functions I get on the last version

dankarization commented 1 year ago

Before image After image

This was 4th converter Also, 1st one was adding support for a new device, which does not work without it (this one). Other 2- yep, they are fine without converters now. Please add 1 and 4th to the next update (or tell me how to change converters for a new version)

Koenkk commented 1 year ago
dankarization commented 1 year ago

Why not just add support for it using my converter? :)

Koenkk commented 1 year ago

In order to add support for this, English instructions on how to create the device has to be available.

dankarization commented 1 year ago

image But links for all other his devices are going to russian instructions, and some other DIY devices like this don't have a link at all

Koenkk commented 1 year ago

This is indeed not good, therefore instructions should be available for any new devices that are added.

github-actions[bot] commented 1 year ago

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