iRayanKhan / homebridge-tuya-platform

This plugin has moved. Check: https://github.com/iRayankhan/homebridge-tuya
Https://Twitter.com/iRayanKhan
MIT License
9 stars 1 forks source link

smart blinds #9

Open Lestercity opened 4 years ago

Lestercity commented 4 years ago

first of all thanks for continuing this plugin, really appreciated. Finally got my way through getting the id and keys for my smart blinds controller through the uCoven Home app. Both controllers are discovered in Homebridge and show up in Home App. Unfortunately the status of them in Homebridge isn't correct and can't get them to control in Home App. Message in homebridge:

[TuyaAccessory] Sending first query to Rolluik Badkamer (3.3) [TuyaAccessory] Odd message from Rolluik Badkamer with command 10: � ˑ�|�ɝ��p�//B�0�g}(n�� [TuyaAccessory] Raw message from Rolluik Badkamer (3.3) with command 10: 000055aa000000010000000a0000002c00000001c90c1ccb9112967c02b218c99def1786709b2f2f42bc30fd1f677d28186e93eef627500b0000aa55

what I was wondering about the devices "id" and "key"; is the key dedicated standard for each device or is variable according to what app is used? Because I used to control them with the Smart Life app, but since the id and key couldn't be retrieved using that app I deleted the devices from the SmartLife app and added them to the uCoven app. After retrieving the id and key from the uCoven app, I added them back to SmartLife. Was wondering if that would be the issue? Should the app that was used to get the id and key be running in order to get them to work in Homebridge Home App? Thanks again.

Hendriks046 commented 4 years ago

I think it's in node_modules?

iRayanKhan commented 4 years ago

Yeah it should be in there

Lestercity commented 4 years ago
image
Lestercity commented 4 years ago
image
iRayanKhan commented 4 years ago

one last thing you can try (that I can think of, off the top of my head).

Move the new version of the plugin to your desktop. Then install the plugin normally using NPM, then swap the old version with the new version by dragging the files.

Lestercity commented 4 years ago
image
iRayanKhan commented 4 years ago

What time zone are you in @Lestercity?

Lestercity commented 4 years ago

:-) Europe the Netherlands it is 2100hr at this moment.

iRayanKhan commented 4 years ago

Could I screen share into your Mac?

macOS has a built in tool (in spotlight search: Screen Sharing).

To connect I just need your Apple ID, you can email me it at rayankhan04 [@] iCloud.com

Lestercity commented 4 years ago

off course, happy if you do.

On 21 Feb 2020, at 21:03, Rayan A. Khan notifications@github.com wrote:

Could I screen share into your Mac?

macOS has a built in tool (in spotlight search: Screen Sharing).

To connect I just need your Apple ID, you can email me it at rayankhan04 [@] iCloud.com

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/iRayanKhan/homebridge-tuya-platform/issues/9?email_source=notifications&email_token=AF7YHNKF7WOBA2SWUZT2RGLREAXPPA5CNFSM4KRN6352YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEMT5NAQ#issuecomment-589813378, or unsubscribe https://github.com/notifications/unsubscribe-auth/AF7YHNI7SP7YPQMLXWTESCTREAXPPANCNFSM4KRN635Q.

Hendriks046 commented 4 years ago

I cannot even get the id and key with the: tuya-lan-find. Keep getting this error messages: Error: { Error: socket hang up at TLSSocket.onSocketClose (_tls_wrap.js:761:23) at TLSSocket.emit (events.js:194:15) at _handle.close (net.js:597:12) at Socket.done (_tls_wrap.js:388:7) at Object.onceWrapper (events.js:277:13) at Socket.emit (events.js:189:13) at TCP._handle.close (net.js:597:12) code: 'ECONNRESET' }

Hendriks046 commented 4 years ago

Please keep me updated.

iRayanKhan commented 4 years ago

@Hendriks046 Try the uCoven home app to get the keys

Hendriks046 commented 4 years ago

I did.

iRayanKhan commented 4 years ago

Are you using hoobs too?

Hendriks046 commented 4 years ago

I installed the tuya-lan plugin on my macbook without ssh into Hoobs. When i try tuya-lan-find into Hoobs, it sees two networks.

iRayanKhan commented 4 years ago

See #4

Lestercity commented 4 years ago

I am accepting your request but it isn't working right?

Lestercity commented 4 years ago

I see the request and accept full control

Lestercity commented 4 years ago

then a screen pops up with your id and then it goes.

iRayanKhan commented 4 years ago

I wonder if it may be blocked at school. Are you on the latest version of macOS?

Lestercity commented 4 years ago
image
Hendriks046 commented 4 years ago

@iRayanKhan I managed to delete the file, and reinstall it with sudo gitclone. Now i'm trying your advice for getting the id/key

Lestercity commented 4 years ago
image
Lestercity commented 4 years ago

this is looking okay right

Lestercity commented 4 years ago

should I adjust something within the tuya platform folder

Lestercity commented 4 years ago
image
Lestercity commented 4 years ago

this is the config for the tuya part

Hendriks046 commented 4 years ago

changed the port to: 8001. when I type tuya-lan-find. this is the error. /usr/local/lib/node_modules/homebridge-tuya-lan/bin/cli.js:175 let {address, port} = proxy.httpServer.address(); ^

TypeError: Cannot read property 'address' of undefined at /usr/local/lib/node_modules/homebridge-tuya-lan/bin/cli.js:175:44 at /usr/local/lib/node_modules/homebridge-tuya-lan/node_modules/http-mitm-proxy/lib/proxy.js:62:14 at /usr/local/lib/node_modules/homebridge-tuya-lan/node_modules/http-mitm-proxy/lib/ca.js:130:14 at /usr/local/lib/node_modules/homebridge-tuya-lan/node_modules/http-mitm-proxy/node_modules/async/dist/async.js:3888:9 at /usr/local/lib/node_modules/homebridge-tuya-lan/node_modules/http-mitm-proxy/node_modules/async/dist/async.js:473:16 at iterateeCallback (/usr/local/lib/node_modules/homebridge-tuya-lan/node_modules/http-mitm-proxy/node_modules/async/dist/async.js:988:17) at /usr/local/lib/node_modules/homebridge-tuya-lan/node_modules/http-mitm-proxy/node_modules/async/dist/async.js:969:16 at /usr/local/lib/node_modules/homebridge-tuya-lan/node_modules/http-mitm-proxy/node_modules/async/dist/async.js:3885:13 at /usr/local/lib/node_modules/homebridge-tuya-lan/node_modules/mkdirp/index.js:47:53 at FSReqCallback.oncomplete (fs.js:158:21)

Lestercity commented 4 years ago

one last thing you can try (that I can think of, off the top of my head).

Move the new version of the plugin to your desktop. Then install the plugin normally using NPM, then swap the old version with the new version by dragging the files.

So should I take all the files and folders within the homebridge-tuya-platform folder to my desktop, then install the 'normal' version. And paste back all the files and folders from my desktop?

Lestercity commented 4 years ago

So I pasted all the files and folders of the new beta version to my Desktop. After I installed the original version that was without error messages within Terminal. Then I pasted the files and folder back to the Tuya-Platform folder within the npm/node folder as you suggested. But Terminal is still giving the same error message after starting Homebridge: plugin not registered etc etc.

Hendriks046 commented 4 years ago

@Lestercity ik heb begrepen dat de modules van Shelly 2.5 wel prima werken. En ook goed werken met homebridge.

Lestercity commented 4 years ago

Daar zat ik ook eerst naar te kijken. Alleen nadat ik me daar verder in verdiept heb begreep ik dat daarmee de kans bestaat dat je de motor verbrandt van je rolluiken. Omdat je ze niet goed kan calibreren.

Mvg Lester

vrijdag 21 februari 2020 22:25 +0100 van notifications@github.com notifications@github.com:

@Lestercity ik heb begrepen dat de modules van Shelly 2.5 wel prima werken. En ook goed werken met homebridge. — You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub , or unsubscribe .

Lestercity commented 4 years ago

Was t al gelukt om id en key te achterhalen? Ik zat daar ook eerst mee te stoeien.

Mvg Lester

vrijdag 21 februari 2020 22:25 +0100 van notifications@github.com notifications@github.com:

@Lestercity ik heb begrepen dat de modules van Shelly 2.5 wel prima werken. En ook goed werken met homebridge. — You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub , or unsubscribe .

iRayanKhan commented 4 years ago

Yeah the request kept timing out. If you want to, can you email me your unreacted config? And let me know I time I can test an open blinds test. I think somethings not happening correctly when you clone, so if it works for me, then I'd publish it to NPM so you can install it normally.

Lestercity commented 4 years ago

Hi Rayan. Did you receive my config?

Lestercity commented 4 years ago

Hi Rayan. Was wondering could a tuya alarmsystem be integrated in the plugin? It got 3 modes; arm, disarm and home.

iRayanKhan commented 4 years ago

Hi @Lestercity I didn't get your email of your config, if you don't mind resending it I'd appreciate it. Secondly, I can try to get tuna alarm system in, but I want to get the blinds first, then humidifier, then alarm system. The alarm system seems trickier as I've never tinkered with the Alarm Controller accessory in HomeKit.

Lestercity commented 4 years ago

Hi Rayan. Great to hear you also doing the humidifier, since I own one of those too :-). For now I have added it as a simple light and it turns on and off, but would be great to control the lights/colours also and the strength of the mist. As for the blinds, below my config. And as for the alarm system will be patient, but would be great and appreciated. Thanks for the hard work.

{ "bridge": { "name": "Homebridge", "username": “XXXXXXXXXXX", "port": 49991, "pin": "031-45-154" }, "description": "Homebridge", "accessories": [

], "platforms": [{ "platform": "TuyaLan", "devices": [{ "name": "Rolluik Badkamer", "type": "SimpleBlinds", "manufacturer": "HomeCube", "model": "Smart Wifi Blinds", "id": "4160452084f3ebf9b47a", "key": "24395eea7cf3d653" }, { "name": "Rolluik Slaapkamer", "type": "SimpleBlinds", "manufacturer": "HomeCube", "model": "Smart Wifi Blinds", "id": "33813048ecfabcb5d276", "key": "ee419394f125d393" }, { "name": "Aroma Diffuser", "type": "SimpleLight", "manufacturer": "GX", "model": "Smart Aroma Diffuser", "id": "87066605b4e62d79d17b", "key": "4c4c7633caffa497" }] }, { "platform": "Ring", "refreshToken": "eyJhbGciOiJIUzUxMiIsImprdSI6Ii9vYXV0aC9pbnRlcm5hbC9qd2tzIiwia2lkIjoiZGVmYXVsdCIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE1ODMyNzUzNjgsInJlZnJlc2hfY2lkIjoicmluZ19vZmZpY2lhbF9hbmRyb2lkIiwicmVmcmVzaF9zY29wZXMiOlsiY2xpZW50Il0sInJlZnJlc2hfdXNlcl9pZCI6MzEyOTY1NjMsInJuZCI6IkttWDZzZXl5SmpIRFFRIiwidHlwZSI6InJlZnJlc2gtdG9rZW4ifQ._NXaLu0PzGpeOjp_1Ch1jXntk4Q6tDSFQRGW3sHi6iaDS7dDJWhEx_Ol1WshOJV7oLaza20DqlfpS5XfgKejGw" }, { "platform": "BroadlinkRM", "name": "Broadlink RM", "accessories": [{ "name": "Openhaard-", "type": "switch", "enableAutoOff": true, "onDuration": 0.3, "data": { "on": "b21830000913140a0a140a140a14140a140a140a0a150a14140a140a140a140a0a130a14140a140a140a140a140a0a141400025e0000000000000000", "off": "b21830000913140a0a140a140a14140a140a140a0a150a14140a140a140a140a0a130a14140a140a140a140a140a0a141400025e0000000000000000" } }, { "name": "Openhaard+", "type": "switch", "enableAutoOff": true, "onDuration": 0.3, "data": { "on": "b20b30000913140a0a140a140a14140a140a140a0a140a14140b140a140a140a0a140a14140a140a140a140a0a14140a1400025f0000000000000000", "off": "b20b30000913140a0a140a140a14140a140a140a0a140a14140b140a140a140a0a140a14140a140a140a140a0a14140a1400025f0000000000000000" } }, { "name": "PowerTV", "type": "switch", "data": { "on": "2600460094931337133713371312131213121312131213371337133713121312131213121213131213371337131213121337143613371337131213121436143614111411131214000d050000", "off": "2600460094931337133713371312131213121312131213371337133713121312131213121213131213371337131213121337143613371337131213121436143614111411131214000d050000" }

          },
          {
              "name": "Volume Up",
              "type": "switch",
              "enableAutoOff": true,
              "onDuration": 0.3,
              "onSendCount": 2,
              "data": {
                  "on": "26008c009492143514351337131114111411131114101337133613361411131114111312131113361336133614111312131114111311141113111411133613361435133614351300061494921336143513371311131213111411131113361435143613111411141014111410133713361237141113111411131114111312131114111237123713361336133612000d05000000000000000000000000",
                  "off": ""
              }

          },
          {
              "name": "Volume Down",
              "type": "switch",
              "enableAutoOff": true,
              "onDuration": 0.3,
              "onSendCount": 2,
              "data": {
                  "on": "26008c009492123713361336141113121311141113111336143513371311141113111411141013371336131113371311141113111411131213111237141013371237123713361300061394921436123712371411131114111312131112371435133614111312131114111311133614361311133614111410141114111311141111381410133613361436123712000d05000000000000000000000000",
                  "off": ""
              }

          },
          {
              "name": "TV Left",
              "type": "switch",
              "enableAutoOff": true,
              "onDuration": 0.3,
              "data": {
                  "on": "26007c00591c100c110e0f1c101b2e1b100d110c110d100d100d100d100c201b1f1c100a221b100d100d110c1f1c100d100d100d100e1e1b1f0d101c1f1b100008e3591b110c110d101b111b2d1c100d100d100c110d110d100d100d1e1c1f1b100d1f1c100d100d100d1f1b110d100d100d100d1f1b1f0d101b1f1c10000d05000000000000000000000000",
                  "off": ""
              }

          },
          {
              "name": "TV Right",
              "type": "switch",
              "enableAutoOff": true,
              "onDuration": 0.3,
              "data": {
                  "on": "26007800591c100d100d101c101c2d1b100d110d100d100d100d100d100d1f1c1e1c100d1f1b1f1b110d1e1c100d100d100d0f0e1f1c1d0e101c1f0d0f0008eb571e0e0f0e0f0e1e0e1e2b1e0e0f0e0f0e0f0e0f0e0f0e0f0e101c1e1c1e0e0f1d1d1d1e0e0f1c1e0e0f0e0f0e0f0f0f1c1e1d0f0e1d1d0f0e000d05",
                  "off": ""
              }
          },
          {
              "name": "TV Up",
              "type": "switch",
              "enableAutoOff": true,
              "onDuration": 0.3,
              "data": {
                  "on": "26007c005b1a110c110c111b111b2e1b110c100d100d100d110c110c110d1f1b201a110c201a201b100d201a110c110c110c110d201a200c101b110c110d100008e25a1a110d100d101b111b2f1a100d100d110c110c110d100d100c211a201a110d1f1b201a100d201a110d100d100d100d1f1b200c101c100d100c11000d05000000000000000000000000",
                  "off": ""
              }
          },
          {
              "name": "TV Down",
              "type": "switch",
              "enableAutoOff": true,
              "onDuration": 0.3,
              "data": {
                  "on": "26007c005b1a110c110c111b101c2e1b100d100d100d100d110c110c110d1f1b201a100d201a110d100c110d201a110c110c110d100d201a200c101b110c200008ea5a1b100d100d101c101b2f1a110c110c110d100d100d100d100c211a201b100d201a100d110b120c201b100d100d100d110c201a200c111b100d20000d05000000000000000000000000",
                  "off": ""
              }
          },
          {
              "name": "TV OK",
              "type": "switch",
              "enableAutoOff": true,
              "onDuration": 0.3,
              "data": {
                  "on": "26007c005a1b100d100d111b101b2f1a110c110d100d100d100d100d110c201a201b110c201a201a110d201a100d100d110b120c201b200b110d101b110c110008e25a1a110d100d101b111b2f1a110c110c110c110c110d100d100d201a201a110c201b201a110c201a110c110d100d100d201a200c100d111b100d10000d05000000000000000000000000",
                  "off": ""
              }

          },
          {
              "name": "TV Source",
              "type": "switch",
              "enableAutoOff": true,
              "onDuration": 0.3,
              "data": {
                  "on": "2600460093931336133613361411131213111411131113361435133713111411131114111410133713111411141014111411131114111311143513371336123712371237133613000d050000",
                  "off": ""
              }

          },
          {
              "name": "TV Source OK",
              "type": "switch",
              "enableAutoOff": true,
              "onDuration": 0.3,
              "data": {
                  "on": "2600460094921435143514361311141114111311141112371237123714111311141113121311141113111411133613111336143613111336143513371311143613111411133612000d050000",
                  "off": ""
              }

          },
          {
              "name": "PowerQacoustics",
              "type": "switch",
              "data": {
                  "on": "260048001d1d3a3b3a1d1e1c1e1d1d1d1e1c1e3a1d1d3b1d1d000bae1e1d3a3a3a1e1d1d1e1c1e1d1d1d1d3b1c1e3b1c1f000bae1e1d3a3a3b1d1d1d1d1e1c1e1d1d1d3b1c1e3a1e1d000d05",
                  "off": "260048001d1d3a3b3a1d1e1c1e1d1d1d1e1c1e3a1d1d3b1d1d000bae1e1d3a3a3a1e1d1d1e1c1e1d1d1d1d3b1c1e3b1c1f000bae1e1d3a3a3b1d1d1d1d1e1c1e1d1d1d3b1c1e3a1e1d000d05"
              }

          },
          {
              "name": "QacousticsSource",
              "type": "switch",
              "enableAutoOff": true,
              "onDuration": 0.3,
              "data": {
                  "on": "26008c001e1d1c1e1d1d3a1e1e1c1c1e1d3b1d1d1e1d1e1c1d1e1d1d1e000b941e1d1d1d1e1d3a1d1e1d1c1e1e3a1d1d1d1e1c1e1d1e1d1d1e000b961e1e1b1e1e1d3a1e1d1d1e1c1f391e1c1e1d1e1c1e1d1d1e1c000b981c1e1d1e1e1c3b1d1e1d1d1e1b3b1d1e1c1e1d1e1d1d1f1d1c000b941d1f1c1d1e1d391e1e1c1d1e1c3b1e1c1e1d1d1e1d1d1e1c1d000d05000000000000000000000000",
                  "off": ""
              }

          },

          {
              "name": "Openhaard",
              "type": "switch",
              "data": {
                  "on": "b20e30000914130b0a140a140a14140a140a140a0a140a15140b130a140a140a0a140a14140a130b130b0a140a14140a1400025f0000000000000000",
                  "off": "b20830000914130b0a140a140a14130b140a140a0a140a14130a140a140b130b0a140a14140b130a140a0a14130b130b140002600000000000000000"
              }
          }
      ]
  }

] }On 3 Mar 2020, at 23:30, Rayan A. Khan notifications@github.com wrote:

Hi @Lestercity https://github.com/Lestercity I didn't get your email of your config, if you don't mind resending it I'd appreciate it. Secondly, I can try to get tuna alarm system in, but I want to get the blinds first, then humidifier, then alarm system. The alarm system seems trickier as I've never tinkered with the Alarm Controller accessory in HomeKit.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/iRayanKhan/homebridge-tuya-platform/issues/9?email_source=notifications&email_token=AF7YHNJGOTYKQJ33RMAIZ3LRFWAJ5A5CNFSM4KRN6352YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOENVNSDI#issuecomment-594204941, or unsubscribe https://github.com/notifications/unsubscribe-auth/AF7YHNPAXL5PZOD5PQWO3MLRFWAJ5ANCNFSM4KRN635Q.

Lestercity commented 4 years ago

And this how the SimpleBlindsAcc.json looks like:

const BaseAccessory = require('./BaseAccessory');

const BLINDS_OPENING = 'opening'; const BLINDS_CLOSING = 'closing'; const BLINDS_STOPPED = 'stopped';

const BLINDS_OPEN = 100; const BLINDS_CLOSED = 0;

class SimpleBlindsAccessory extends BaseAccessory { static getCategory(Categories) { return Categories.WINDOW_COVERING; }

constructor(...props) {
    super(...props);
}

_registerPlatformAccessory() {
    const {Service} = this.hap;

    this.accessory.addService(Service.WindowCovering, this.device.context.name);

    super._registerPlatformAccessory();
}

_registerCharacteristics(dps) {
    const {Service, Characteristic} = this.hap;
    const service = this.accessory.getService(Service.WindowCovering);
    this._checkServiceName(service, this.device.context.name);

    this.dpAction = this._getCustomDP(this.device.context.dpAction) || '1';

    let _cmdOpen = '1';
    if (this.device.context.cmdOpen) {
        _cmdOpen = ('' + this.device.context.cmdOpen).trim();
    }

    let _cmdClose = '2';
    if (this.device.context.cmdClose) {
        _cmdClose = ('' + this.device.context.cmdClose).trim();
    }

    this.cmdStop = '3';
    if (this.device.context.cmdStop) {
        this.cmdStop = ('' + this.device.context.cmdStop).trim();
    }

    this.cmdOpen = _cmdOpen;
    this.cmdClose = _cmdClose;
    if (!!this.device.context.flipState) {
        this.cmdOpen = _cmdClose;
        this.cmdClose = _cmdOpen;
    }

    this.duration = parseInt(this.device.context.timeToOpen) || 45;
    const endingDuration = parseInt(this.device.context.timeToTighten) || 0;
    this.minPosition = endingDuration ? Math.round(endingDuration * -100 / (this.duration - endingDuration)) : BLINDS_CLOSED;

    // If the blinds are closed, note it; if not, assume open because there is no way to know where it is
    this.assumedPosition = dps[this.dpAction] === this.cmdClose ? this.minPosition : BLINDS_OPEN;
    this.assumedState = BLINDS_STOPPED;
    this.changeTime = this.targetPosition = false;

    const characteristicCurrentPosition = service.getCharacteristic(Characteristic.CurrentPosition)
        .updateValue(this._getCurrentPosition(dps[this.dpAction]))
        .on('get', this.getCurrentPosition.bind(this));

    const characteristicTargetPosition = service.getCharacteristic(Characteristic.TargetPosition)
        .updateValue(this._getTargetPosition(dps[this.dpAction]))
        .on('get', this.getTargetPosition.bind(this))
        .on('set', this.setTargetPosition.bind(this));

    const characteristicPositionState = service.getCharacteristic(Characteristic.PositionState)
        .updateValue(this._getPositionState())
        .on('get', this.getPositionState.bind(this));

    this.device.on('change', changes => {
        console.log("[TuyaAccessory] Blinds saw change to " + changes[this.dpAction]);
        if (changes.hasOwnProperty(this.dpAction)) {
            switch (changes[this.dpAction]) {
                case this.cmdOpen:  // Starting to open
                    this.assumedState = BLINDS_OPENING;
                    characteristicPositionState.updateValue(Characteristic.PositionState.INCREASING);

                    // Only if change was external or someone internally asked for open
                    if (this.targetPosition === false || this.targetPosition === BLINDS_OPEN) {
                        this.targetPosition = false;

                        const durationToOpen = Math.abs(this.assumedPosition - BLINDS_OPEN) * this.duration * 10;
                        this.changeTime = Date.now() - durationToOpen;

                        console.log("[TuyaAccessory] Blinds will be marked open in " + durationToOpen + "ms");

                        if (this.changeTimeout) clearTimeout(this.changeTimeout);
                        this.changeTimeout = setTimeout(() => {
                            characteristicCurrentPosition.updateValue(BLINDS_OPEN);
                            characteristicPositionState.updateValue(Characteristic.PositionState.STOPPED);
                            this.changeTime = false;
                            this.assumedPosition = BLINDS_OPEN;
                            this.assumedState = BLINDS_STOPPED;
                            console.log("[TuyaAccessory] Blinds marked open");
                        }, durationToOpen);
                    }
                    break;

                case this.cmdClose:  // Starting to close
                    this.assumedState = BLINDS_CLOSING;
                    characteristicPositionState.updateValue(Characteristic.PositionState.DECREASING);

                    // Only if change was external or someone internally asked for close
                    if (this.targetPosition === false || this.targetPosition === BLINDS_CLOSED) {
                        this.targetPosition = false;

                        const durationToClose = Math.abs(this.assumedPosition - BLINDS_CLOSED) * this.duration * 10;
                        this.changeTime = Date.now() - durationToClose;

                        console.log("[TuyaAccessory] Blinds will be marked closed in " + durationToClose + "ms");

                        if (this.changeTimeout) clearTimeout(this.changeTimeout);
                        this.changeTimeout = setTimeout(() => {
                            characteristicCurrentPosition.updateValue(BLINDS_CLOSED);
                            characteristicPositionState.updateValue(Characteristic.PositionState.STOPPED);
                            this.changeTime = false;
                            this.assumedPosition = this.minPosition;
                            this.assumedState = BLINDS_STOPPED;
                            console.log("[TuyaAccessory] Blinds marked closed");
                        }, durationToClose);
                    }
                    break;

                case this.cmdStop:  // Stopped in middle
                    if (this.changeTimeout) clearTimeout(this.changeTimeout);

                    console.log("[TuyaAccessory] Blinds last change was " + this.changeTime + "; " + (Date.now() - this.changeTime) + 'ms ago');

                    if (this.changeTime) {
                        /*
                        this.assumedPosition = Math.min(100 - this.minPosition, Math.max(0, Math.round((Date.now() - this.changeTime) / (10 * this.duration))));
                        if (this.assumedState === BLINDS_CLOSING) this.assumedPosition = 100 - this.assumedPosition;
                        else this.assumedPosition += this.minPosition;
                         */
                        const disposition = ((Date.now() - this.changeTime) / (10 * this.duration));
                        if (this.assumedState === BLINDS_CLOSING) {
                            this.assumedPosition = BLINDS_OPEN - disposition;
                        } else {
                            this.assumedPosition = this.minPosition + disposition;
                        }
                    }

                    const adjustedPosition = Math.max(0, Math.round(this.assumedPosition));
                    characteristicCurrentPosition.updateValue(adjustedPosition);
                    characteristicTargetPosition.updateValue(adjustedPosition);
                    characteristicPositionState.updateValue(Characteristic.PositionState.STOPPED);
                    console.log("[TuyaAccessory] Blinds marked stopped at " + adjustedPosition + "; assumed to be at " + this.assumedPosition);

                    this.changeTime = this.targetPosition = false;
                    this.assumedState = BLINDS_STOPPED;
                    break;
            }
        }
    });
}

getCurrentPosition(callback) {
    this.getState(this.dpAction, (err, dp) => {
        if (err) return callback(err);

        callback(null, this._getCurrentPosition(dp));
    });
}

_getCurrentPosition(dp) {
    switch (dp) {
        case this.cmdOpen:
            return BLINDS_OPEN;

        case this.cmdClose:
            return BLINDS_CLOSED;

        default:
            return Math.max(BLINDS_CLOSED, Math.round(this.assumedPosition));
    }
}

getTargetPosition(callback) {
    this.getState(this.dpAction, (err, dp) => {
        if (err) return callback(err);

        callback(null, this._getTargetPosition(dp));
    });
}

_getTargetPosition(dp) {
    switch (dp) {
        case this.cmdOpen:
            return BLINDS_OPEN;

        case this.cmdClose:
            return BLINDS_CLOSED;

        default:
            return Math.max(BLINDS_CLOSED, Math.round(this.assumedPosition));
    }
}

setTargetPosition(value, callback) {
    console.log('[TuyaAccessory] Blinds asked to move from ' + this.assumedPosition + ' to ' + value);

    if (this.changeTimeout) clearTimeout(this.changeTimeout);
    this.targetPosition = value;

    if (this.changeTime !== false) {
        console.log("[TuyaAccessory] Blinds " + (this.assumedState === BLINDS_CLOSING ? 'closing' : 'opening') + " had started " + this.changeTime + "; " + (Date.now() - this.changeTime) + 'ms ago');
        const disposition = ((Date.now() - this.changeTime) / (10 * this.duration));
        if (this.assumedState === BLINDS_CLOSING) {
            this.assumedPosition = BLINDS_OPEN - disposition;
        } else {
            this.assumedPosition = this.minPosition + disposition;
        }
        console.log("[TuyaAccessory] Blinds' adjusted assumedPosition is " + this.assumedPosition);
    }

    const duration = Math.abs(this.assumedPosition - value) * this.duration * 10;

    if (Math.abs(value - this.assumedPosition) < 1) {
        return this.setState(this.dpAction, this.cmdStop, callback);
    } else if (value > this.assumedPosition) {
        this.assumedState = BLINDS_OPENING;
        this.setState(this.dpAction, this.cmdOpen, callback);
        this.changeTime = Date.now() -  Math.abs(this.assumedPosition - this.minPosition) * this.duration * 10;
    } else {
        this.assumedState = BLINDS_CLOSING;
        this.setState(this.dpAction, this.cmdClose, callback);
        this.changeTime = Date.now() -  Math.abs(this.assumedPosition - BLINDS_OPEN) * this.duration * 10;
    }

    if (value !== BLINDS_OPEN && value !== BLINDS_CLOSED) {
        console.log("[TuyaAccessory] Blinds will stop in " + duration + "ms");
        console.log("[TuyaAccessory] Blinds assumed started " + this.changeTime + "; " + (Date.now() - this.changeTime) + 'ms ago');
        this.changeTimeout = setTimeout(() => {
            console.log("[TuyaAccessory] Blinds asked to stop");
            this.setState(this.dpAction, this.cmdStop);
        }, duration);
    }
}

getPositionState(callback) {
    const state = this._getPositionState();
    process.nextTick(() => {
        callback(null, state);
    });
}

_getPositionState() {
    const {Characteristic} = this.hap;

    switch (this.assumedState) {
        case BLINDS_OPENING:
            return Characteristic.PositionState.INCREASING;

        case BLINDS_CLOSING:
            return Characteristic.PositionState.DECREASING;

        default:
            return Characteristic.PositionState.STOPPED;
    }
}

}

module.exports = SimpleBlindsAccessory; On 3 Mar 2020, at 23:30, Rayan A. Khan notifications@github.com wrote:

Hi @Lestercity https://github.com/Lestercity I didn't get your email of your config, if you don't mind resending it I'd appreciate it. Secondly, I can try to get tuna alarm system in, but I want to get the blinds first, then humidifier, then alarm system. The alarm system seems trickier as I've never tinkered with the Alarm Controller accessory in HomeKit.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/iRayanKhan/homebridge-tuya-platform/issues/9?email_source=notifications&email_token=AF7YHNJGOTYKQJ33RMAIZ3LRFWAJ5A5CNFSM4KRN6352YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOENVNSDI#issuecomment-594204941, or unsubscribe https://github.com/notifications/unsubscribe-auth/AF7YHNPAXL5PZOD5PQWO3MLRFWAJ5ANCNFSM4KRN635Q.

Lestercity commented 4 years ago

Did you get the configs?

On 4 Mar 2020, at 00:37, Lesley van Taanom lestercity14@gmail.com wrote:

And this how the SimpleBlindsAcc.json looks like:

const BaseAccessory = require('./BaseAccessory');

const BLINDS_OPENING = 'opening'; const BLINDS_CLOSING = 'closing'; const BLINDS_STOPPED = 'stopped';

const BLINDS_OPEN = 100; const BLINDS_CLOSED = 0;

class SimpleBlindsAccessory extends BaseAccessory { static getCategory(Categories) { return Categories.WINDOW_COVERING; }

constructor(...props) {
    super(...props);
}

_registerPlatformAccessory() {
    const {Service} = this.hap;

    this.accessory.addService(Service.WindowCovering, this.device.context.name);

    super._registerPlatformAccessory();
}

_registerCharacteristics(dps) {
    const {Service, Characteristic} = this.hap;
    const service = this.accessory.getService(Service.WindowCovering);
    this._checkServiceName(service, this.device.context.name);

    this.dpAction = this._getCustomDP(this.device.context.dpAction) || '1';

    let _cmdOpen = '1';
    if (this.device.context.cmdOpen) {
        _cmdOpen = ('' + this.device.context.cmdOpen).trim();
    }

    let _cmdClose = '2';
    if (this.device.context.cmdClose) {
        _cmdClose = ('' + this.device.context.cmdClose).trim();
    }

    this.cmdStop = '3';
    if (this.device.context.cmdStop) {
        this.cmdStop = ('' + this.device.context.cmdStop).trim();
    }

    this.cmdOpen = _cmdOpen;
    this.cmdClose = _cmdClose;
    if (!!this.device.context.flipState) {
        this.cmdOpen = _cmdClose;
        this.cmdClose = _cmdOpen;
    }

    this.duration = parseInt(this.device.context.timeToOpen) || 45;
    const endingDuration = parseInt(this.device.context.timeToTighten) || 0;
    this.minPosition = endingDuration ? Math.round(endingDuration * -100 / (this.duration - endingDuration)) : BLINDS_CLOSED;

    // If the blinds are closed, note it; if not, assume open because there is no way to know where it is
    this.assumedPosition = dps[this.dpAction] === this.cmdClose ? this.minPosition : BLINDS_OPEN;
    this.assumedState = BLINDS_STOPPED;
    this.changeTime = this.targetPosition = false;

    const characteristicCurrentPosition = service.getCharacteristic(Characteristic.CurrentPosition)
        .updateValue(this._getCurrentPosition(dps[this.dpAction]))
        .on('get', this.getCurrentPosition.bind(this));

    const characteristicTargetPosition = service.getCharacteristic(Characteristic.TargetPosition)
        .updateValue(this._getTargetPosition(dps[this.dpAction]))
        .on('get', this.getTargetPosition.bind(this))
        .on('set', this.setTargetPosition.bind(this));

    const characteristicPositionState = service.getCharacteristic(Characteristic.PositionState)
        .updateValue(this._getPositionState())
        .on('get', this.getPositionState.bind(this));

    this.device.on('change', changes => {
        console.log("[TuyaAccessory] Blinds saw change to " + changes[this.dpAction]);
        if (changes.hasOwnProperty(this.dpAction)) {
            switch (changes[this.dpAction]) {
                case this.cmdOpen:  // Starting to open
                    this.assumedState = BLINDS_OPENING;
                    characteristicPositionState.updateValue(Characteristic.PositionState.INCREASING);

                    // Only if change was external or someone internally asked for open
                    if (this.targetPosition === false || this.targetPosition === BLINDS_OPEN) {
                        this.targetPosition = false;

                        const durationToOpen = Math.abs(this.assumedPosition - BLINDS_OPEN) * this.duration * 10;
                        this.changeTime = Date.now() - durationToOpen;

                        console.log("[TuyaAccessory] Blinds will be marked open in " + durationToOpen + "ms");

                        if (this.changeTimeout) clearTimeout(this.changeTimeout);
                        this.changeTimeout = setTimeout(() => {
                            characteristicCurrentPosition.updateValue(BLINDS_OPEN);
                            characteristicPositionState.updateValue(Characteristic.PositionState.STOPPED);
                            this.changeTime = false;
                            this.assumedPosition = BLINDS_OPEN;
                            this.assumedState = BLINDS_STOPPED;
                            console.log("[TuyaAccessory] Blinds marked open");
                        }, durationToOpen);
                    }
                    break;

                case this.cmdClose:  // Starting to close
                    this.assumedState = BLINDS_CLOSING;
                    characteristicPositionState.updateValue(Characteristic.PositionState.DECREASING);

                    // Only if change was external or someone internally asked for close
                    if (this.targetPosition === false || this.targetPosition === BLINDS_CLOSED) {
                        this.targetPosition = false;

                        const durationToClose = Math.abs(this.assumedPosition - BLINDS_CLOSED) * this.duration * 10;
                        this.changeTime = Date.now() - durationToClose;

                        console.log("[TuyaAccessory] Blinds will be marked closed in " + durationToClose + "ms");

                        if (this.changeTimeout) clearTimeout(this.changeTimeout);
                        this.changeTimeout = setTimeout(() => {
                            characteristicCurrentPosition.updateValue(BLINDS_CLOSED);
                            characteristicPositionState.updateValue(Characteristic.PositionState.STOPPED);
                            this.changeTime = false;
                            this.assumedPosition = this.minPosition;
                            this.assumedState = BLINDS_STOPPED;
                            console.log("[TuyaAccessory] Blinds marked closed");
                        }, durationToClose);
                    }
                    break;

                case this.cmdStop:  // Stopped in middle
                    if (this.changeTimeout) clearTimeout(this.changeTimeout);

                    console.log("[TuyaAccessory] Blinds last change was " + this.changeTime + "; " + (Date.now() - this.changeTime) + 'ms ago');

                    if (this.changeTime) {
                        /*
                        this.assumedPosition = Math.min(100 - this.minPosition, Math.max(0, Math.round((Date.now() - this.changeTime) / (10 * this.duration))));
                        if (this.assumedState === BLINDS_CLOSING) this.assumedPosition = 100 - this.assumedPosition;
                        else this.assumedPosition += this.minPosition;
                         */
                        const disposition = ((Date.now() - this.changeTime) / (10 * this.duration));
                        if (this.assumedState === BLINDS_CLOSING) {
                            this.assumedPosition = BLINDS_OPEN - disposition;
                        } else {
                            this.assumedPosition = this.minPosition + disposition;
                        }
                    }

                    const adjustedPosition = Math.max(0, Math.round(this.assumedPosition));
                    characteristicCurrentPosition.updateValue(adjustedPosition);
                    characteristicTargetPosition.updateValue(adjustedPosition);
                    characteristicPositionState.updateValue(Characteristic.PositionState.STOPPED);
                    console.log("[TuyaAccessory] Blinds marked stopped at " + adjustedPosition + "; assumed to be at " + this.assumedPosition);

                    this.changeTime = this.targetPosition = false;
                    this.assumedState = BLINDS_STOPPED;
                    break;
            }
        }
    });
}

getCurrentPosition(callback) {
    this.getState(this.dpAction, (err, dp) => {
        if (err) return callback(err);

        callback(null, this._getCurrentPosition(dp));
    });
}

_getCurrentPosition(dp) {
    switch (dp) {
        case this.cmdOpen:
            return BLINDS_OPEN;

        case this.cmdClose:
            return BLINDS_CLOSED;

        default:
            return Math.max(BLINDS_CLOSED, Math.round(this.assumedPosition));
    }
}

getTargetPosition(callback) {
    this.getState(this.dpAction, (err, dp) => {
        if (err) return callback(err);

        callback(null, this._getTargetPosition(dp));
    });
}

_getTargetPosition(dp) {
    switch (dp) {
        case this.cmdOpen:
            return BLINDS_OPEN;

        case this.cmdClose:
            return BLINDS_CLOSED;

        default:
            return Math.max(BLINDS_CLOSED, Math.round(this.assumedPosition));
    }
}

setTargetPosition(value, callback) {
    console.log('[TuyaAccessory] Blinds asked to move from ' + this.assumedPosition + ' to ' + value);

    if (this.changeTimeout) clearTimeout(this.changeTimeout);
    this.targetPosition = value;

    if (this.changeTime !== false) {
        console.log("[TuyaAccessory] Blinds " + (this.assumedState === BLINDS_CLOSING ? 'closing' : 'opening') + " had started " + this.changeTime + "; " + (Date.now() - this.changeTime) + 'ms ago');
        const disposition = ((Date.now() - this.changeTime) / (10 * this.duration));
        if (this.assumedState === BLINDS_CLOSING) {
            this.assumedPosition = BLINDS_OPEN - disposition;
        } else {
            this.assumedPosition = this.minPosition + disposition;
        }
        console.log("[TuyaAccessory] Blinds' adjusted assumedPosition is " + this.assumedPosition);
    }

    const duration = Math.abs(this.assumedPosition - value) * this.duration * 10;

    if (Math.abs(value - this.assumedPosition) < 1) {
        return this.setState(this.dpAction, this.cmdStop, callback);
    } else if (value > this.assumedPosition) {
        this.assumedState = BLINDS_OPENING;
        this.setState(this.dpAction, this.cmdOpen, callback);
        this.changeTime = Date.now() -  Math.abs(this.assumedPosition - this.minPosition) * this.duration * 10;
    } else {
        this.assumedState = BLINDS_CLOSING;
        this.setState(this.dpAction, this.cmdClose, callback);
        this.changeTime = Date.now() -  Math.abs(this.assumedPosition - BLINDS_OPEN) * this.duration * 10;
    }

    if (value !== BLINDS_OPEN && value !== BLINDS_CLOSED) {
        console.log("[TuyaAccessory] Blinds will stop in " + duration + "ms");
        console.log("[TuyaAccessory] Blinds assumed started " + this.changeTime + "; " + (Date.now() - this.changeTime) + 'ms ago');
        this.changeTimeout = setTimeout(() => {
            console.log("[TuyaAccessory] Blinds asked to stop");
            this.setState(this.dpAction, this.cmdStop);
        }, duration);
    }
}

getPositionState(callback) {
    const state = this._getPositionState();
    process.nextTick(() => {
        callback(null, state);
    });
}

_getPositionState() {
    const {Characteristic} = this.hap;

    switch (this.assumedState) {
        case BLINDS_OPENING:
            return Characteristic.PositionState.INCREASING;

        case BLINDS_CLOSING:
            return Characteristic.PositionState.DECREASING;

        default:
            return Characteristic.PositionState.STOPPED;
    }
}

}

module.exports = SimpleBlindsAccessory; On 3 Mar 2020, at 23:30, Rayan A. Khan <notifications@github.com mailto:notifications@github.com> wrote:

Hi @Lestercity https://github.com/Lestercity I didn't get your email of your config, if you don't mind resending it I'd appreciate it. Secondly, I can try to get tuna alarm system in, but I want to get the blinds first, then humidifier, then alarm system. The alarm system seems trickier as I've never tinkered with the Alarm Controller accessory in HomeKit.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/iRayanKhan/homebridge-tuya-platform/issues/9?email_source=notifications&email_token=AF7YHNJGOTYKQJ33RMAIZ3LRFWAJ5A5CNFSM4KRN6352YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOENVNSDI#issuecomment-594204941, or unsubscribe https://github.com/notifications/unsubscribe-auth/AF7YHNPAXL5PZOD5PQWO3MLRFWAJ5ANCNFSM4KRN635Q.

Lestercity commented 4 years ago

Here you have the schema I retrieved by using tuya-lan-find—schema:

Found 3 devices: [ { name: 'Diffuser', id: '87066605b4e62d79d17b', key: '4c4c7633caffa497', def: { schema: '[{"mode":"rw","code":"switch_spray","name":"\u55b7\u96fe\u5f00\u5173","property":{"type":"bool"},"iconname":"icon-dp_power2","id":1,"type":"obj","desc":""},{"mode":"rw","code":"mode","name":"\u5de5\u4f5c\u6a21\u5f0f","property":{"range":["low","high"],"type":"enum"},"iconname":"icon-dp_box","id":2,"type":"obj","desc":""},{"mode":"rw","code":"countdown","name":"\u5012\u8ba1\u65f6","property":{"range":["1","3","6","cancel"],"type":"enum"},"iconname":"icon-dp_time2","id":3,"type":"obj","desc":""},{"mode":"ro","code":"countdown_left","name":"\u5012\u8ba1\u65f6\u5269\u4f59\u65f6\u95f4","property":{"unit":"min","min":0,"max":360,"scale":0,"step":1,"type":"value"},"iconname":"icon-dp_time2","id":4,"type":"obj","desc":""},{"mode":"rw","code":"switch_led","name":"Diffuser light","property":{"type":"bool"},"iconname":"icon-dp_power2","id":5,"type":"obj","desc":""},{"mode":"rw","code":"work_mode","name":"\u706f\u5149\u6a21\u5f0f","property":{"range":["colour","colourful1"],"type":"enum"},"iconname":"icon-dp_direction","id":6,"type":"obj","desc":""},{"mode":"rw","code":"colour_data","name":"\u5f69\u5149\u503c","property":{"type":"string","maxlen":255},"iconname":"icon-yanse","id":8,"type":"obj","desc":""},{"mode":"ro","code":"fault","scope":"fault","name":"\u6545\u969c\u544a\u8b66","property":{"label":["lack_water"],"type":"bitmap","maxlen":1},"iconname":"icon-yanse","id":9,"type":"obj","desc":""}]', extras: '[{"id":4,"inputStyle":"","inputType":""}]', }, }, { name: 'Rolluik Badkamer', id: '4160452084f3ebf9b47a', key: '24395eea7cf3d653', def: { schema: '[{"mode":"rw","code":"switch_control","name":"\u5f00\u5173\u63a7\u5236","property":{"range":["on","stop","off"],"type":"enum"},"id":1,"type":"obj","desc":""},{"mode":"rw","code":"tr_timecon","name":"\u884c\u7a0b\u65f6\u95f4\u914d\u7f6e","property":{"unit":"s","min":10,"max":120,"scale":0,"step":1,"type":"value"},"iconname":"icon-dp_time2","id":9,"type":"obj","desc":""},{"mode":"rw","code":"BlackLight","name":"\u80cc\u5149\u5f00\u5173","property":{"type":"bool"},"id":101,"type":"obj","desc":"\u80cc\u5149\u53ef\u63a7"}]', }, }, { name: 'Rolluik Slaapkamer', id: '33813048ecfabcb5d276', key: 'ee419394f125d393', def: { schema: '[{"mode":"rw","code":"switch_control","name":"\u5f00\u5173\u63a7\u5236","property":{"range":["on","stop","off"],"type":"enum"},"id":1,"type":"obj","desc":""},{"mode":"rw","code":"tr_timecon","name":"\u884c\u7a0b\u65f6\u95f4\u914d\u7f6e","property":{"unit":"s","min":10,"max":120,"scale":0,"step":1,"type":"value"},"iconname":"icon-dp_time2","id":9,"type":"obj","desc":""},{"mode":"rw","code":"BlackLight","name":"\u80cc\u5149\u5f00\u5173","property":{"type":"bool"},"id":101,"type":"obj","desc":"\u80cc\u5149\u53ef\u63a7"}]', }, }, ] On 4 Mar 2020, at 00:37, Lesley van Taanom lestercity14@gmail.com wrote:

And this how the SimpleBlindsAcc.json looks like:

const BaseAccessory = require('./BaseAccessory');

const BLINDS_OPENING = 'opening'; const BLINDS_CLOSING = 'closing'; const BLINDS_STOPPED = 'stopped';

const BLINDS_OPEN = 100; const BLINDS_CLOSED = 0;

class SimpleBlindsAccessory extends BaseAccessory { static getCategory(Categories) { return Categories.WINDOW_COVERING; }

constructor(...props) {
    super(...props);
}

_registerPlatformAccessory() {
    const {Service} = this.hap;

    this.accessory.addService(Service.WindowCovering, this.device.context.name);

    super._registerPlatformAccessory();
}

_registerCharacteristics(dps) {
    const {Service, Characteristic} = this.hap;
    const service = this.accessory.getService(Service.WindowCovering);
    this._checkServiceName(service, this.device.context.name);

    this.dpAction = this._getCustomDP(this.device.context.dpAction) || '1';

    let _cmdOpen = '1';
    if (this.device.context.cmdOpen) {
        _cmdOpen = ('' + this.device.context.cmdOpen).trim();
    }

    let _cmdClose = '2';
    if (this.device.context.cmdClose) {
        _cmdClose = ('' + this.device.context.cmdClose).trim();
    }

    this.cmdStop = '3';
    if (this.device.context.cmdStop) {
        this.cmdStop = ('' + this.device.context.cmdStop).trim();
    }

    this.cmdOpen = _cmdOpen;
    this.cmdClose = _cmdClose;
    if (!!this.device.context.flipState) {
        this.cmdOpen = _cmdClose;
        this.cmdClose = _cmdOpen;
    }

    this.duration = parseInt(this.device.context.timeToOpen) || 45;
    const endingDuration = parseInt(this.device.context.timeToTighten) || 0;
    this.minPosition = endingDuration ? Math.round(endingDuration * -100 / (this.duration - endingDuration)) : BLINDS_CLOSED;

    // If the blinds are closed, note it; if not, assume open because there is no way to know where it is
    this.assumedPosition = dps[this.dpAction] === this.cmdClose ? this.minPosition : BLINDS_OPEN;
    this.assumedState = BLINDS_STOPPED;
    this.changeTime = this.targetPosition = false;

    const characteristicCurrentPosition = service.getCharacteristic(Characteristic.CurrentPosition)
        .updateValue(this._getCurrentPosition(dps[this.dpAction]))
        .on('get', this.getCurrentPosition.bind(this));

    const characteristicTargetPosition = service.getCharacteristic(Characteristic.TargetPosition)
        .updateValue(this._getTargetPosition(dps[this.dpAction]))
        .on('get', this.getTargetPosition.bind(this))
        .on('set', this.setTargetPosition.bind(this));

    const characteristicPositionState = service.getCharacteristic(Characteristic.PositionState)
        .updateValue(this._getPositionState())
        .on('get', this.getPositionState.bind(this));

    this.device.on('change', changes => {
        console.log("[TuyaAccessory] Blinds saw change to " + changes[this.dpAction]);
        if (changes.hasOwnProperty(this.dpAction)) {
            switch (changes[this.dpAction]) {
                case this.cmdOpen:  // Starting to open
                    this.assumedState = BLINDS_OPENING;
                    characteristicPositionState.updateValue(Characteristic.PositionState.INCREASING);

                    // Only if change was external or someone internally asked for open
                    if (this.targetPosition === false || this.targetPosition === BLINDS_OPEN) {
                        this.targetPosition = false;

                        const durationToOpen = Math.abs(this.assumedPosition - BLINDS_OPEN) * this.duration * 10;
                        this.changeTime = Date.now() - durationToOpen;

                        console.log("[TuyaAccessory] Blinds will be marked open in " + durationToOpen + "ms");

                        if (this.changeTimeout) clearTimeout(this.changeTimeout);
                        this.changeTimeout = setTimeout(() => {
                            characteristicCurrentPosition.updateValue(BLINDS_OPEN);
                            characteristicPositionState.updateValue(Characteristic.PositionState.STOPPED);
                            this.changeTime = false;
                            this.assumedPosition = BLINDS_OPEN;
                            this.assumedState = BLINDS_STOPPED;
                            console.log("[TuyaAccessory] Blinds marked open");
                        }, durationToOpen);
                    }
                    break;

                case this.cmdClose:  // Starting to close
                    this.assumedState = BLINDS_CLOSING;
                    characteristicPositionState.updateValue(Characteristic.PositionState.DECREASING);

                    // Only if change was external or someone internally asked for close
                    if (this.targetPosition === false || this.targetPosition === BLINDS_CLOSED) {
                        this.targetPosition = false;

                        const durationToClose = Math.abs(this.assumedPosition - BLINDS_CLOSED) * this.duration * 10;
                        this.changeTime = Date.now() - durationToClose;

                        console.log("[TuyaAccessory] Blinds will be marked closed in " + durationToClose + "ms");

                        if (this.changeTimeout) clearTimeout(this.changeTimeout);
                        this.changeTimeout = setTimeout(() => {
                            characteristicCurrentPosition.updateValue(BLINDS_CLOSED);
                            characteristicPositionState.updateValue(Characteristic.PositionState.STOPPED);
                            this.changeTime = false;
                            this.assumedPosition = this.minPosition;
                            this.assumedState = BLINDS_STOPPED;
                            console.log("[TuyaAccessory] Blinds marked closed");
                        }, durationToClose);
                    }
                    break;

                case this.cmdStop:  // Stopped in middle
                    if (this.changeTimeout) clearTimeout(this.changeTimeout);

                    console.log("[TuyaAccessory] Blinds last change was " + this.changeTime + "; " + (Date.now() - this.changeTime) + 'ms ago');

                    if (this.changeTime) {
                        /*
                        this.assumedPosition = Math.min(100 - this.minPosition, Math.max(0, Math.round((Date.now() - this.changeTime) / (10 * this.duration))));
                        if (this.assumedState === BLINDS_CLOSING) this.assumedPosition = 100 - this.assumedPosition;
                        else this.assumedPosition += this.minPosition;
                         */
                        const disposition = ((Date.now() - this.changeTime) / (10 * this.duration));
                        if (this.assumedState === BLINDS_CLOSING) {
                            this.assumedPosition = BLINDS_OPEN - disposition;
                        } else {
                            this.assumedPosition = this.minPosition + disposition;
                        }
                    }

                    const adjustedPosition = Math.max(0, Math.round(this.assumedPosition));
                    characteristicCurrentPosition.updateValue(adjustedPosition);
                    characteristicTargetPosition.updateValue(adjustedPosition);
                    characteristicPositionState.updateValue(Characteristic.PositionState.STOPPED);
                    console.log("[TuyaAccessory] Blinds marked stopped at " + adjustedPosition + "; assumed to be at " + this.assumedPosition);

                    this.changeTime = this.targetPosition = false;
                    this.assumedState = BLINDS_STOPPED;
                    break;
            }
        }
    });
}

getCurrentPosition(callback) {
    this.getState(this.dpAction, (err, dp) => {
        if (err) return callback(err);

        callback(null, this._getCurrentPosition(dp));
    });
}

_getCurrentPosition(dp) {
    switch (dp) {
        case this.cmdOpen:
            return BLINDS_OPEN;

        case this.cmdClose:
            return BLINDS_CLOSED;

        default:
            return Math.max(BLINDS_CLOSED, Math.round(this.assumedPosition));
    }
}

getTargetPosition(callback) {
    this.getState(this.dpAction, (err, dp) => {
        if (err) return callback(err);

        callback(null, this._getTargetPosition(dp));
    });
}

_getTargetPosition(dp) {
    switch (dp) {
        case this.cmdOpen:
            return BLINDS_OPEN;

        case this.cmdClose:
            return BLINDS_CLOSED;

        default:
            return Math.max(BLINDS_CLOSED, Math.round(this.assumedPosition));
    }
}

setTargetPosition(value, callback) {
    console.log('[TuyaAccessory] Blinds asked to move from ' + this.assumedPosition + ' to ' + value);

    if (this.changeTimeout) clearTimeout(this.changeTimeout);
    this.targetPosition = value;

    if (this.changeTime !== false) {
        console.log("[TuyaAccessory] Blinds " + (this.assumedState === BLINDS_CLOSING ? 'closing' : 'opening') + " had started " + this.changeTime + "; " + (Date.now() - this.changeTime) + 'ms ago');
        const disposition = ((Date.now() - this.changeTime) / (10 * this.duration));
        if (this.assumedState === BLINDS_CLOSING) {
            this.assumedPosition = BLINDS_OPEN - disposition;
        } else {
            this.assumedPosition = this.minPosition + disposition;
        }
        console.log("[TuyaAccessory] Blinds' adjusted assumedPosition is " + this.assumedPosition);
    }

    const duration = Math.abs(this.assumedPosition - value) * this.duration * 10;

    if (Math.abs(value - this.assumedPosition) < 1) {
        return this.setState(this.dpAction, this.cmdStop, callback);
    } else if (value > this.assumedPosition) {
        this.assumedState = BLINDS_OPENING;
        this.setState(this.dpAction, this.cmdOpen, callback);
        this.changeTime = Date.now() -  Math.abs(this.assumedPosition - this.minPosition) * this.duration * 10;
    } else {
        this.assumedState = BLINDS_CLOSING;
        this.setState(this.dpAction, this.cmdClose, callback);
        this.changeTime = Date.now() -  Math.abs(this.assumedPosition - BLINDS_OPEN) * this.duration * 10;
    }

    if (value !== BLINDS_OPEN && value !== BLINDS_CLOSED) {
        console.log("[TuyaAccessory] Blinds will stop in " + duration + "ms");
        console.log("[TuyaAccessory] Blinds assumed started " + this.changeTime + "; " + (Date.now() - this.changeTime) + 'ms ago');
        this.changeTimeout = setTimeout(() => {
            console.log("[TuyaAccessory] Blinds asked to stop");
            this.setState(this.dpAction, this.cmdStop);
        }, duration);
    }
}

getPositionState(callback) {
    const state = this._getPositionState();
    process.nextTick(() => {
        callback(null, state);
    });
}

_getPositionState() {
    const {Characteristic} = this.hap;

    switch (this.assumedState) {
        case BLINDS_OPENING:
            return Characteristic.PositionState.INCREASING;

        case BLINDS_CLOSING:
            return Characteristic.PositionState.DECREASING;

        default:
            return Characteristic.PositionState.STOPPED;
    }
}

}

module.exports = SimpleBlindsAccessory; On 3 Mar 2020, at 23:30, Rayan A. Khan <notifications@github.com mailto:notifications@github.com> wrote:

Hi @Lestercity https://github.com/Lestercity I didn't get your email of your config, if you don't mind resending it I'd appreciate it. Secondly, I can try to get tuna alarm system in, but I want to get the blinds first, then humidifier, then alarm system. The alarm system seems trickier as I've never tinkered with the Alarm Controller accessory in HomeKit.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/iRayanKhan/homebridge-tuya-platform/issues/9?email_source=notifications&email_token=AF7YHNJGOTYKQJ33RMAIZ3LRFWAJ5A5CNFSM4KRN6352YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOENVNSDI#issuecomment-594204941, or unsubscribe https://github.com/notifications/unsubscribe-auth/AF7YHNPAXL5PZOD5PQWO3MLRFWAJ5ANCNFSM4KRN635Q.

iRayanKhan commented 4 years ago

What time would like me to not tamper with your blinds? I can test it tonight.

Lestercity commented 4 years ago

Whenever you ready. Just let me know what to do!

Mvg Lester

donderdag 5 maart 2020 15:54 +0100 van notifications@github.com notifications@github.com:

What time would like me to not tamper with your blinds? I can test it tonight. — You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub , or unsubscribe .

Lestercity commented 4 years ago

Hi Rayan. Are you there?:-)

Lestercity commented 4 years ago

I took your advise and obtained a rpi Zero W. Installed Raspbian fine, but having some issues with Docker. It is running and homebridge shows up in Home App. But I am having issues with the plugins installing through the Docker Homebridge UI. They seem to install fine, but after the confirmation of the install some don't show up in the list of plugins. For example, I installed tuya plugin, ring plugin and broadlink rm plugin. Only tuya and broadlink show up in list. Then after restarting the rpi, I needed to do that because I replaced it to another outlet, and then after starting the UI again only the Tuya plugin is still in the list. The Broadlink plugin is also gone. How is that possible? Another issue I came across, but I think it is due to my knowledge level, is when I delete Homebridge from Home App and adding it back again it says accessory already added. I know this is common behaviour because I had that also when running it from my Mac, but then I could delete the persist folder from Homebridge folder on my Mac and all was running again like it should, but how can I delete persist folder from rpi homebridge folder? I am running headless, so everything should be done from Terminal SSH.

Lestercity commented 4 years ago

Hi Rayan. So I managed to setup my new rip zero W with Homebridge. Everything is running the way it was with Homebridge on my Mac, so that is looking good so far. Thanks for the advise, now I have a dedicated server. I installed your beta tuya-platform plugin and it is running. Only when I change the SimpleBlinds to NewSimpleBlinds the blinds can't be discovered. When I change them back to SimpleBlinds they are discovered again, so I left them in the config as SimpleBlinds. But still aint getting them to control my blinds.

Lestercity commented 4 years ago

Could you guide through adjust the schema through Terminal?

iRayanKhan commented 4 years ago

I will try a separate patch I guess 'cuz I don't get why it wouldn't work. Sorry for the delayed responses, I have stuff going on What time zone are you in again?

Lestercity commented 4 years ago

Time Zone Amsterdam. It is 6.10pm now:-). I installed the Homebridge-Tuya-Platform plugin from your github. The humidifier works fine on/off. The Blinds are discovered when named SimpleBlinds, when changed to NewSimpleBlinds they dont. What I was wondering, a few weeks ago you pointed me to a fork of rcrdcst, he changed the SimpleBlindsAccessory.js. Changed 1,2,3 with Open,Close and Stop. Because he said that was the way the new 4th gen Blinds work. Is that the reason my blinds dont react? Or is it something else? Thanks again for your effort!

Mvg Lester

zondag 8 maart 2020 18:08 +0100 van notifications@github.com notifications@github.com:

I will try a separate patch I guess 'cuz I don't get why it wouldn't work. Sorry for the delayed responses, I have stuff going on What time zone are you in again? — You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub , or unsubscribe .