tuya / tuya-homebridge

Homebridge custom plugin for controlling Powered by Tuya (PBT) devices in HomeKit. This plugin is officially maintained by the Tuya Developer Team.
MIT License
345 stars 178 forks source link

Cannot read properties of undefined (reading 'subType') #316

Closed AdamGoodApp closed 1 year ago

AdamGoodApp commented 1 year ago

I am trying to develop a new driver to add a Pet Feeder accessory.

I copied the switch_accessory.js file as a starter template and only changed the getSendParam() to include the correct code and value to be sent.

I am getting the following error from the logs:

/homebridge/node_modules/homebridge-tuya-platform-feeder/lib/feeder_accessory.js:17
      deviceData.subType
                 ^
TypeError: Cannot read properties of undefined (reading 'subType')
    at new FeederAccessory (/homebridge/node_modules/homebridge-tuya-platform-feeder/lib/feeder_accessory.js:17:18)
    at TuyaPlatform.addAccessory (/homebridge/node_modules/homebridge-tuya-platform-feeder/index.js:121:27)
    at TuyaPlatform.initTuyaSDK (/homebridge/node_modules/homebridge-tuya-platform-feeder/index.js:100:12)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)

Added new device to the addAccessory():

case 'cwwsq': //feeder
        deviceAccessory = new FeederAccessory(this, homebridgeAccessory, device);
        this.accessories.set(uuid, deviceAccessory.homebridgeAccessory);
        this.deviceAccessories.set(uuid, deviceAccessory);
        break;

My feeder_accessory.js file

const BaseAccessory = require('./base_accessory')

let Accessory;
let Service;
let Characteristic;
let UUIDGen;

class FeederAccessory extends BaseAccessory {
  constructor(platform, homebridgeAccessory, deviceConfig, deviceData) {
    ({ Accessory, Characteristic, Service } = platform.api.hap);
    super(
      platform,
      homebridgeAccessory,
      deviceConfig,
      Accessory.Categories.SWITCH,
      Service.Switch,
      deviceData.subType
    );
    this.statusArr = deviceConfig.status;
    this.subTypeArr = deviceData.subType;

    this.refreshAccessoryServiceIfNeed(this.statusArr, false);
  }

  //init Or refresh AccessoryService
  refreshAccessoryServiceIfNeed(statusArr, isRefresh) {
    this.isRefresh = isRefresh;
    if (!statusArr) {
      return;
    }

    for (var subType of this.subTypeArr) {
      var status = statusArr.find(item => item.code === subType)
      if (!status) {
        continue;
      }
      var value = status.value
      let service 
      if (this.subTypeArr.length == 1) {
        service = this.service;
        this.switchValue = status;
      }else{
        service = this.homebridgeAccessory.getService(subType);
      }
      this.setCachedState(service.displayName, value);
      if (this.isRefresh) {
        service
          .getCharacteristic(Characteristic.On)
          .updateValue(value);
      } else {
        this.getAccessoryCharacteristic(service, Characteristic.On);
      }
    }
  }

  getAccessoryCharacteristic(service, name) {
    //set  Accessory service Characteristic
    service.getCharacteristic(name)
      .on('get', callback => {
        if (this.hasValidCache()) {
          callback(null, this.getCachedState(service.displayName));
        }
      })
      .on('set', (value, callback) => {
        var param = this.getSendParam(service.displayName, value)
        this.platform.tuyaOpenApi.sendCommand(this.deviceId, param).then(() => {
          this.setCachedState(service.displayName, value);
          callback();
        }).catch((error) => {
          this.log.error('[SET][%s] Characteristic.Brightness Error: %s', this.homebridgeAccessory.displayName, error);
          this.invalidateCache();
          callback(error);
        });
      });
  }

  //get Command SendData
  getSendParam(name, value) {
    var code;
    var value;
    const isOn = value ? true : false;
    if (this.subTypeArr.length == 1) {
      code = this.switchValue.code;
    }else{
      code = name;
    }
    value = isOn;
    return {
      "commands": [
        {
          "code": 'manual_feed',
          "value": 1
        }
      ]
    };
  }

  //update device status
  updateState(data) {
    this.refreshAccessoryServiceIfNeed(data.status, true);
  }
}

module.exports = FeederAccessory;
github-actions[bot] commented 1 year ago

Thank you for your feedback, we will solve this issue soon

0x5e commented 1 year ago

Hi @AdamGoodApp , I have a fork version and completely rewritten the main logics, it will be much simpler to develop a new accessory. See this: https://github.com/0x5e/homebridge-tuya-platform/blob/develop/src/accessory/SwitchAccessory.ts

github-actions[bot] commented 1 year ago

Stale issue. we will close the issue soon. If this issue has not been resolved, please update the issue and contact us in time.