Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix switch accessory & add support for Smart IR (wnykq) #115

Merged
merged 3 commits into from
Nov 24, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/accessory/AccessoryFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ export default class AccessoryFactory {
case 'co2bj':
handler = new CarbonDioxideSensorAccessory(platform, accessory);
break;
case 'wnykq':
case 'wsdcg':
handler = new TemperatureHumiditySensorAccessory(platform, accessory);
0x5e marked this conversation as resolved.
Show resolved Hide resolved
break;
Expand Down
2 changes: 1 addition & 1 deletion src/accessory/SwitchAccessory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export default class SwitchAccessory extends BaseAccessory {
this.accessory.removeService(oldService);
}

const schema = this.device.schema.filter((schema) => schema.code.startsWith('switch') && schema.type !== TuyaDeviceSchemaType.Boolean);
const schema = this.device.schema.filter((schema) => schema.code.startsWith('switch') && schema.type === TuyaDeviceSchemaType.Boolean);
for (const _schema of schema) {
const name = (schema.length === 1) ? this.device.name : _schema.code;
this.configureSwitch(_schema, name);
Expand Down
15 changes: 11 additions & 4 deletions src/device/TuyaDeviceManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ import EventEmitter from 'events';
import TuyaOpenAPI from '../core/TuyaOpenAPI';
import TuyaOpenMQ from '../core/TuyaOpenMQ';
import Logger, { PrefixLogger } from '../util/Logger';
import TuyaDevice, { TuyaDeviceSchema, TuyaDeviceSchemaMode, TuyaDeviceSchemaProperty, TuyaDeviceStatus } from './TuyaDevice';
import TuyaDevice, {
TuyaDeviceSchema, TuyaDeviceSchemaMode, TuyaDeviceSchemaProperty, TuyaDeviceSchemaType, TuyaDeviceStatus,
} from './TuyaDevice';

enum Events {
DEVICE_ADD = 'DEVICE_ADD',
Expand Down Expand Up @@ -91,10 +93,11 @@ export default class TuyaDeviceManager extends EventEmitter {

// Combine functions and status together, as it used to be.
const schemas = new Map<string, TuyaDeviceSchema>();
for (const { code, type, values } of [...res.result.status, ...res.result.functions]) {
for (const { code, type: rawType, values } of [...res.result.status, ...res.result.functions]) {
if (schemas[code]) {
continue;
}
const type = rawType.charAt(0).toUpperCase() + rawType.slice(1).toLowerCase();
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My IR device spec is like this:

path = /v1.0/devices/6c66dfa384bdc2bbb2yqql/specifications
data = {
  "result": {
    "category": "infrared_ac",
    "functions": [
      {
        "code": "F",
        "type": "ENUM",
        "values": "{\"min\":0,\"max\":3,\"scale\":0,\"step\":1,\"type\":\"Integer\"}"
      },
      {
        "code": "M",
        "type": "ENUM",
        "values": "{\"min\":0,\"max\":4,\"scale\":0,\"step\":1,\"type\":\"Integer\"}"
      },
      {
        "code": "PowerOff",
        "type": "STRING",
        "values": "PowerOff"
      },
      {
        "code": "PowerOn",
        "type": "STRING",
        "values": "PowerOn"
      },
      {
        "code": "T",
        "type": "ENUM",
        "values": "{\"min\":16,\"max\":30,\"scale\":0,\"step\":1,\"type\":\"Integer\"}"
      }
    ],
    "status": [
      {
        "code": "wind",
        "type": "ENUM",
        "values": "{\"min\":0,\"max\":3,\"scale\":0,\"step\":1,\"type\":\"Integer\"}"
      },
      {
        "code": "mode",
        "type": "ENUM",
        "values": "{\"min\":0,\"max\":4,\"scale\":0,\"step\":1,\"type\":\"Integer\"}"
      },
      {
        "code": "power",
        "type": "BOOLEAN",
        "values": "{}"
      },
      {
        "code": "temp",
        "type": "ENUM",
        "values": "{\"min\":16,\"max\":30,\"scale\":0,\"step\":1,\"type\":\"Integer\"}"
      }
    ]
  },
  "success": true,
  "t": 1667552909972,
  "tid": "3fde5b005c2011ed9f2b629ef151a136"
}

The ENUM actually is Integer, the STRING is like a Enum type with 1 range, BOOLEAN is same as Boolean. They have to be some dirty code to convert this :(

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for explaining, I will revert this code for now and we can discuss it further what is the best approach here

const read = (res.result.status).find(schema => schema.code === code) !== undefined;
const write = (res.result.functions).find(schema => schema.code === code) !== undefined;
let mode = TuyaDeviceSchemaMode.UNKNOWN;
Expand All @@ -107,7 +110,11 @@ export default class TuyaDeviceManager extends EventEmitter {
}
let property: TuyaDeviceSchemaProperty;
try {
property = JSON.parse(values);
if (type === TuyaDeviceSchemaType.String) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

STRING value is a string, but String value is a json object string like {\"maxlen\":255} defines the max length.

property = values;
} else {
property = JSON.parse(values);
}
schemas[code] = { code, mode, type, property };
} catch (error) {
this.log.error(error);
Expand All @@ -125,7 +132,7 @@ export default class TuyaDeviceManager extends EventEmitter {


async onMQTTMessage(topic: string, protocol: TuyaMQTTProtocol, message) {
switch(protocol) {
switch (protocol) {
case TuyaMQTTProtocol.DEVICE_STATUS_UPDATE: {
const { devId, status } = message;
const device = this.getDevice(devId);
Expand Down
6 changes: 3 additions & 3 deletions src/platform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -256,10 +256,10 @@ export class TuyaPlatform implements DynamicPlatformPlugin {
this.log.info(`Got home_id=${home_id}, name=${name}`);
if (this.options.homeWhitelist) {
if (this.options.homeWhitelist.includes(home_id)) {
this.log.info(`Found home_id=${home_id} in whitelist; including devices from this home.`);
homeIDList.push(home_id);
this.log.info(`Found home_id=${home_id} in whitelist; including devices from this home.`);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've noticed this and I don't know why npm run lint not return warnings for me and github actions, but ./node_modules/.bin/eslint src/**/**.ts --max-warnings=0 works. Do you know why?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my case, using eslint directly also works:

❯ ./node_modules/.bin/eslint src/**/**.ts --max-warnings=0
❯ echo $?
0

Do you have some additional global config specified? Or some prettier rules if you are using VSCode?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldnt it be

eslint src/**/*.ts --max-warnings=0

? with one asterisk before .ts

Besides this, no clue why it wouldnt return errors in actions.

homeIDList.push(home_id);
} else {
this.log.info(`Did not find home_id=${home_id} in whitelist; excluding devices from this home.`);
this.log.info(`Did not find home_id=${home_id} in whitelist; excluding devices from this home.`);
}
} else {
homeIDList.push(home_id);
Expand Down