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

Change how cover accessories are handled to match observed behavior o… #618

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
4 changes: 4 additions & 0 deletions src/accessories/CoverAccessory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ import { TuyaDevice } from "../api/response";
import { HoldPositionCharacteristic } from "./characteristics/holdPosition";

export class CoverAccessory extends BaseAccessory {
public target = 0;
public position = 0;
public motor = 2;

constructor(
platform: TuyaWebPlatform,
homebridgeAccessory: HomebridgeAccessory | undefined,
Expand Down
53 changes: 3 additions & 50 deletions src/accessories/characteristics/currentPosition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { CharacteristicGetCallback } from "homebridge";
import { TuyaWebCharacteristic } from "./base";
import { BaseAccessory } from "../BaseAccessory";
import { CoverState, DeviceState, ExtendedBoolean } from "../../api/response";
import { CoverAccessory } from "..";
import { TuyaBoolean } from "../../helpers/TuyaBoolean";

export class CurrentPositionCharacteristic extends TuyaWebCharacteristic {
Expand All @@ -16,58 +17,10 @@ export class CurrentPositionCharacteristic extends TuyaWebCharacteristic {
}

public getRemoteValue(callback: CharacteristicGetCallback): void {
this.accessory
.getDeviceState()
.then((data) => {
this.debug("[GET] %s", data?.state);
this.updateValue(data, callback);
})
.catch(this.accessory.handleError("GET", callback));
this.updateValue({}, callback);
Copy link
Owner

Choose a reason for hiding this comment

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

It looks like we are now no longer fetching the remote state 🤔

What would happen if you use another system (outside of homekit) to update the state?
It seems like homekit wouldn't update with the new state.

Copy link
Author

Choose a reason for hiding this comment

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

Yes, could be, but I'm not into the code. It is just the PR from bSr43/homebridge-tuya-web@91ef52e you asked for.
Maybe you can combine the code? Would be awesome!
Is there a way we can donate for your work?

}

updateValue(data: DeviceState, callback?: CharacteristicGetCallback): void {
this.debug(`Updating value`, data);
if (!isNaN(Number(String(data?.state)))) {
//State is a number and probably 1, 2 or 3
const state = Number(data.state);

let stateValue!: number;

switch (state) {
case CoverState.Opening:
stateValue = 50;
break;
case CoverState.Closing:
stateValue = 50;
break;
case CoverState.Stopped:
default:
if (data.target_cover_state === CoverState.Opening) {
stateValue = 100;
} else if (data.target_cover_state === CoverState.Stopped) {
stateValue = 50;
} else {
stateValue = 0;
}
}

this.accessory.setCharacteristic(
this.homekitCharacteristic,
stateValue,
!callback,
);
callback && callback(null, stateValue);
} else if (["true", "false"].includes(String(data?.state).toLowerCase())) {
const stateValue = TuyaBoolean(data.state as ExtendedBoolean) ? 100 : 0;
this.accessory.setCharacteristic(
this.homekitCharacteristic,
stateValue,
!callback,
);
callback && callback(null, stateValue);
} else {
callback &&
callback(new Error(`Unexpected state value provided: ${data?.state}`));
}
callback && callback(null, (<CoverAccessory>this.accessory).position);
}
}
13 changes: 2 additions & 11 deletions src/accessories/characteristics/positionState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { CharacteristicGetCallback } from "homebridge";
import { TuyaWebCharacteristic } from "./base";
import { BaseAccessory } from "../BaseAccessory";
import { DeviceState } from "../../api/response";
import { CoverAccessory } from "..";

export class PositionStateCharacteristic extends TuyaWebCharacteristic {
public static Title = "Characteristic.PositionState";
Expand All @@ -14,21 +15,11 @@ export class PositionStateCharacteristic extends TuyaWebCharacteristic {
return true;
}

private get PositionState() {
return this.accessory.platform.Characteristic.PositionState;
}

public getRemoteValue(callback: CharacteristicGetCallback): void {
this.updateValue({}, callback);
}

updateValue(data: DeviceState, callback?: CharacteristicGetCallback): void {
this.debug("Setting position state to stopped");
this.accessory.setCharacteristic(
this.homekitCharacteristic,
this.PositionState.STOPPED,
!callback,
);
callback && callback(null, this.PositionState.STOPPED);
callback && callback(null, (<CoverAccessory>this.accessory).motor);
}
}
105 changes: 50 additions & 55 deletions src/accessories/characteristics/targetPosition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import {
import { TuyaWebCharacteristic } from "./base";
import { BaseAccessory } from "../BaseAccessory";
import { CoverState, DeviceState, ExtendedBoolean } from "../../api/response";
import { CoverAccessory } from "../CoverAccessory";
import delay from "../../helpers/delay";
import { TuyaBoolean } from "../../helpers/TuyaBoolean";

export class TargetPositionCharacteristic extends TuyaWebCharacteristic {
Expand All @@ -33,13 +35,8 @@ export class TargetPositionCharacteristic extends TuyaWebCharacteristic {
}

public getRemoteValue(callback: CharacteristicGetCallback): void {
this.accessory
.getDeviceState()
.then((data) => {
this.debug("[GET] %s", data?.state);
this.updateValue(data, callback);
})
.catch(this.accessory.handleError("GET", callback));
const a = <CoverAccessory>this.accessory;
callback && callback(null, a.target);
}

public setRemoteValue(
Expand All @@ -48,61 +45,59 @@ export class TargetPositionCharacteristic extends TuyaWebCharacteristic {
): void {
const value = (homekitValue as number) === 0 ? 0 : 1;

const data: DeviceState = {
target_cover_state: value === 0 ? CoverState.Closing : CoverState.Opening,
state: value === 0 ? CoverState.Closing : CoverState.Opening,
};
const coverAccessory = <CoverAccessory>this.accessory;
const target = value ? 100 : 0;

this.debug("Setting targetPosition to %d", target);

this.accessory
.setDeviceState("turnOnOff", { value }, data)
.then(() => {
this.debug("[SET] %s", value);
.setDeviceState("turnOnOff", { value }, value)
.then(async () => {
this.debug("[SET] turnOnOff command sent with value %s", value);
callback();

this.debug("Setting targetPosition to %d", target);
coverAccessory.target = target;
this.accessory.setCharacteristic(
this.accessory.platform.Characteristic.TargetPosition,
target,
true
);

coverAccessory.motor = value
? this.accessory.platform.Characteristic.PositionState.INCREASING
: this.accessory.platform.Characteristic.PositionState.DECREASING;
this.accessory.setCharacteristic(
this.accessory.platform.Characteristic.PositionState,
coverAccessory.motor,
true
);

await delay(5000);

this.debug(
"Setting currentPosition to %d and positionState to STOPPED",
target
);

coverAccessory.position = target;
this.accessory.setCharacteristic(
this.accessory.platform.Characteristic.CurrentPosition,
coverAccessory.position,
true
);

coverAccessory.motor = this.accessory.platform.Characteristic.PositionState.STOPPED;
this.accessory.setCharacteristic(
this.accessory.platform.Characteristic.PositionState,
this.accessory.platform.Characteristic.PositionState.STOPPED,
true
);
})
.catch(this.accessory.handleError("SET", callback));
}

updateValue(data: DeviceState, callback?: CharacteristicGetCallback): void {
if (!isNaN(Number(String(data?.state)))) {
//State is a number and probably 1, 2 or 3
const state = Number(data.state);

let stateValue: 0 | 50 | 100;

switch (state) {
case CoverState.Opening:
stateValue = 100;
break;
case CoverState.Closing:
stateValue = 0;
break;
default:
if (data.target_cover_state === CoverState.Opening) {
stateValue = 100;
} else if (data.target_cover_state === CoverState.Stopped) {
stateValue = 50;
} else {
stateValue = 0;
}
}

this.accessory.setCharacteristic(
this.homekitCharacteristic,
stateValue,
!callback,
);
callback && callback(null, stateValue);
} else if (["true", "false"].includes(String(data?.state).toLowerCase())) {
const stateValue = TuyaBoolean(data.state as ExtendedBoolean) ? 100 : 0;
this.accessory.setCharacteristic(
this.homekitCharacteristic,
stateValue,
!callback,
);
callback && callback(null, stateValue);
} else {
callback &&
callback(new Error(`Unexpected state value provided: ${data?.state}`));
}
callback && callback(null, (<CoverAccessory>this.accessory).target);
}
}