yenoiwesa / homebridge-connexoon

A homebridge plugin to integrate Somfy blinds with the Connexoon RTS hub
Apache License 2.0
27 stars 2 forks source link

Questions regarding Connexoon setup and features #34

Closed Kositch closed 3 years ago

Kositch commented 3 years ago

Hello,

I have Somfy RTS blinds, I have purchased Somfy Connexoon RTS module, activated it with account creation (used VPN, because in our country - Czech republic Somfy Connexoon RTS is not already officially supported what I have found out after the purchase of the unit - Somfy wants to push its Tahoma solution in our country), I have added two of my blinds using PRG and SEL buttons on Somfy Connexoon RTS unit, blinds moved UP/DN confirming that windows blind was added to the unit. I tested Connexoon RTS unit and paired blinds for control using PRG+SEL buttons and it correctly controls paired blinds. I can not test it using iOS app, because it is not available in appstore for our region. I have installed this plugin, entered login information and in config changed "service" to Connexoon (with ConnexoonRTS service plugin was unable to login). It successfully discovered my Connexoon RTS unit even PIN is correct in device properties in Home app, it shows all two paired blinds in Home app, but when I try to control my blind, nothing happens and there are these errors in HB log (I have masked last 4 digits of PIN with XXXX). I am not sure if it can somehow check that I live in unsupported region, but when plugin is able to log in to serveres, i dont think so.

HB log when trying to control blind via Home app here:

[25/06/2021, 15:14:23] [Connexoon] Failed to exec command {
  errorCode: 'UNSUPPORTED_OPERATION',
  error: 'No such command : open on device rts://0407-9481-XXXX/16736319 (rts:UnknowRTSComponent)'
}
[25/06/2021, 15:14:23] [Connexoon] StatusCodeError: 400 - {"errorCode":"UNSUPPORTED_OPERATION","error":"No such command : open on device rts://0407-9481-XXXX/16736319 (rts:UnknowRTSComponent)"}
    at new StatusCodeError (/usr/local/lib/node_modules/homebridge-connexoon/node_modules/request-promise-core/lib/errors.js:32:15)
    at Request.plumbing.callback (/usr/local/lib/node_modules/homebridge-connexoon/node_modules/request-promise-core/lib/plumbing.js:104:33)
    at Request.RP$callback [as _callback] (/usr/local/lib/node_modules/homebridge-connexoon/node_modules/request-promise-core/lib/plumbing.js:46:31)
    at Request.self.callback (/usr/local/lib/node_modules/homebridge-connexoon/node_modules/request/request.js:185:22)
    at Request.emit (events.js:376:20)
    at Request.<anonymous> (/usr/local/lib/node_modules/homebridge-connexoon/node_modules/request/request.js:1154:10)
    at Request.emit (events.js:376:20)
    at IncomingMessage.<anonymous> (/usr/local/lib/node_modules/homebridge-connexoon/node_modules/request/request.js:1076:12)
    at Object.onceWrapper (events.js:482:28)
    at IncomingMessage.emit (events.js:388:22)
    at endReadableNT (internal/streams/readable.js:1336:12)
    at processTicksAndRejections (internal/process/task_queues.js:82:21) {
  statusCode: 400,
  error: {
    errorCode: 'UNSUPPORTED_OPERATION',
    error: 'No such command : open on device rts://0407-9481-XXXX/16736319 (rts:UnknowRTSComponent)'
  },
  options: {
    auth: {
      bearer: 'NmQ0MmEwZDA4ZTlkZGE5OTc0MTBiNDE5MDRmY2UzOTQ2YWRhNDllNTU5YzAxMDM5NTNiNGFjMDlhYjE3MDkzOA'
    },
    url: 'https://tahomalink.com/enduser-mobile-web/enduserAPI/exec/apply',
    json: true,
    body: Execution {
      label: 'RTS (16736319) - Open - HomeKit',
      actions: [Array]
    },
    method: 'POST',
    callback: [Function: RP$callback],
    transform: undefined,
    simple: true,
    resolveWithFullResponse: false,
    transform2xxOnly: false
  },
  response: <ref *1> IncomingMessage {
    _readableState: ReadableState {
      objectMode: false,
      highWaterMark: 16384,
      buffer: BufferList { head: null, tail: null, length: 0 },
      length: 0,
      pipes: [],
      flowing: true,
      ended: true,
      endEmitted: true,
      reading: false,
      sync: true,
      needReadable: false,
      emittedReadable: false,
      readableListening: false,
      resumeScheduled: false,
      errorEmitted: false,
      emitClose: true,
      autoDestroy: false,
      destroyed: false,
      errored: null,
      closed: false,
      closeEmitted: false,
      defaultEncoding: 'utf8',
      awaitDrainWriters: null,
      multiAwaitDrain: false,
      readingMore: true,
      decoder: null,
      encoding: null,
      [Symbol(kPaused)]: false
    },
    _events: [Object: null prototype] {
      end: [Array],
      close: [Array],
      data: [Function (anonymous)],
      error: [Function (anonymous)]
    },
    _eventsCount: 4,
    _maxListeners: undefined,
    socket: TLSSocket {
      _tlsOptions: [Object],
      _secureEstablished: true,
      _securePending: false,
      _newSessionPending: false,
      _controlReleased: true,
      secureConnecting: false,
      _SNICallback: null,
      servername: 'tahomalink.com',
      alpnProtocol: false,
      authorized: true,
      authorizationError: null,
      encrypted: true,
      _events: [Object: null prototype],
      _eventsCount: 10,
      connecting: false,
      _hadError: false,
      _parent: null,
      _host: 'tahomalink.com',
      _readableState: [ReadableState],
      _maxListeners: undefined,
      _writableState: [WritableState],
      allowHalfOpen: false,
      _sockname: null,
      _pendingData: null,
      _pendingEncoding: '',
      server: undefined,
      _server: null,
      ssl: [TLSWrap],
      _requestCert: true,
      _rejectUnauthorized: true,
      parser: null,
      _httpMessage: [ClientRequest],
      [Symbol(res)]: [TLSWrap],
      [Symbol(verified)]: true,
      [Symbol(pendingSession)]: null,
      [Symbol(async_id_symbol)]: 37396,
      [Symbol(kHandle)]: [TLSWrap],
      [Symbol(kSetNoDelay)]: false,
      [Symbol(lastWriteQueueSize)]: 0,
      [Symbol(timeout)]: null,
      [Symbol(kBuffer)]: null,
      [Symbol(kBufferCb)]: null,
      [Symbol(kBufferGen)]: null,
      [Symbol(kCapture)]: false,
      [Symbol(kBytesRead)]: 0,
      [Symbol(kBytesWritten)]: 0,
      [Symbol(connect-options)]: [Object],
      [Symbol(RequestTimeout)]: undefined
    },
    httpVersionMajor: 1,
    httpVersionMinor: 1,
    httpVersion: '1.1',
    complete: true,
    headers: {
      date: 'Fri, 25 Jun 2021 13:14:22 GMT',
      server: 'overkiz',
      'strict-transport-security': 'max-age=31536000; includeSubDomains',
      'content-type': 'application/json;charset=UTF-8',
      connection: 'close',
      'transfer-encoding': 'chunked'
    },
    rawHeaders: [
      'Date',
      'Fri, 25 Jun 2021 13:14:22 GMT',
      'Server',
      'overkiz',
      'Strict-Transport-Security',
      'max-age=31536000; includeSubDomains',
      'Content-Type',
      'application/json;charset=UTF-8',
      'Connection',
      'close',
      'Transfer-Encoding',
      'chunked'
    ],
    trailers: {},
    rawTrailers: [],
    aborted: false,
    upgrade: false,
    url: '',
    method: null,
    statusCode: 400,
    statusMessage: '',
    client: TLSSocket {
      _tlsOptions: [Object],
      _secureEstablished: true,
      _securePending: false,
      _newSessionPending: false,
      _controlReleased: true,
      secureConnecting: false,
      _SNICallback: null,
      servername: 'tahomalink.com',
      alpnProtocol: false,
      authorized: true,
      authorizationError: null,
      encrypted: true,
      _events: [Object: null prototype],
      _eventsCount: 10,
      connecting: false,
      _hadError: false,
      _parent: null,
      _host: 'tahomalink.com',
      _readableState: [ReadableState],
      _maxListeners: undefined,
      _writableState: [WritableState],
      allowHalfOpen: false,
      _sockname: null,
      _pendingData: null,
      _pendingEncoding: '',
      server: undefined,
      _server: null,
      ssl: [TLSWrap],
      _requestCert: true,
      _rejectUnauthorized: true,
      parser: null,
      _httpMessage: [ClientRequest],
      [Symbol(res)]: [TLSWrap],
      [Symbol(verified)]: true,
      [Symbol(pendingSession)]: null,
      [Symbol(async_id_symbol)]: 37396,
      [Symbol(kHandle)]: [TLSWrap],
      [Symbol(kSetNoDelay)]: false,
      [Symbol(lastWriteQueueSize)]: 0,
      [Symbol(timeout)]: null,
      [Symbol(kBuffer)]: null,
      [Symbol(kBufferCb)]: null,
      [Symbol(kBufferGen)]: null,
      [Symbol(kCapture)]: false,
      [Symbol(kBytesRead)]: 0,
      [Symbol(kBytesWritten)]: 0,
      [Symbol(connect-options)]: [Object],
      [Symbol(RequestTimeout)]: undefined
    },
    _consuming: false,
    _dumped: false,
    req: ClientRequest {
      _events: [Object: null prototype],
      _eventsCount: 5,
      _maxListeners: undefined,
      outputData: [],
      outputSize: 0,
      writable: true,
      destroyed: false,
      _last: true,
      chunkedEncoding: false,
      shouldKeepAlive: false,
      _defaultKeepAlive: true,
      useChunkedEncodingByDefault: true,
      sendDate: false,
      _removedConnection: false,
      _removedContLen: false,
      _removedTE: false,
      _contentLength: null,
      _hasBody: true,
      _trailer: '',
      finished: true,
      _headerSent: true,
      socket: [TLSSocket],
      _header: 'POST /enduser-mobile-web/enduserAPI/exec/apply HTTP/1.1\r\n' +
        'host: tahomalink.com\r\n' +
        'authorization: Bearer NmQ0MmEwZDA4ZTlkZGE5OTc0MTBiNDE5MDRmY2UzOTQ2YWRhNDllNTU5YzAxMDM5NTNiNGFjMDlhYjE3MDkzOA\r\n' +
        'accept: application/json\r\n' +
        'content-type: application/json\r\n' +
        'content-length: 155\r\n' +
        'Connection: close\r\n' +
        '\r\n',
      _keepAliveTimeout: 0,
      _onPendingData: [Function: noopPendingOutput],
      agent: [Agent],
      socketPath: undefined,
      method: 'POST',
      maxHeaderSize: undefined,
      insecureHTTPParser: undefined,
      path: '/enduser-mobile-web/enduserAPI/exec/apply',
      _ended: true,
      res: [Circular *1],
      aborted: false,
      timeoutCb: null,
      upgradeOrConnect: false,
      parser: null,
      maxHeadersCount: null,
      reusedSocket: false,
      host: 'tahomalink.com',
      protocol: 'https:',
      [Symbol(kCapture)]: false,
      [Symbol(kNeedDrain)]: false,
      [Symbol(corked)]: 0,
      [Symbol(kOutHeaders)]: [Object: null prototype]
    },
    request: Request {
      _events: [Object: null prototype],
      _eventsCount: 5,
      _maxListeners: undefined,
      body: '{"label":"RTS (16736319) - Open - HomeKit","actions":[{"deviceURL":"rts://0407-9481-XXXX/16736319","commands":[{"type":1,"name":"open","parameters":[]}]}]}',
      method: 'POST',
      readable: true,
      writable: true,
      explicitMethod: true,
      _qs: [Querystring],
      _auth: [Auth],
      _oauth: [OAuth],
      _multipart: [Multipart],
      _redirect: [Redirect],
      _tunnel: [Tunnel],
      _rp_resolve: [Function (anonymous)],
      _rp_reject: [Function (anonymous)],
      _rp_promise: [Promise],
      _rp_callbackOrig: undefined,
      callback: [Function (anonymous)],
      _rp_options: [Object],
      headers: [Object],
      setHeader: [Function (anonymous)],
      hasHeader: [Function (anonymous)],
      getHeader: [Function (anonymous)],
      removeHeader: [Function (anonymous)],
      localAddress: undefined,
      pool: {},
      dests: [],
      __isRequestRequest: true,
      _callback: [Function: RP$callback],
      uri: [Url],
      proxy: null,
      tunnel: true,
      setHost: true,
      originalCookieHeader: undefined,
      _disableCookies: true,
      _jar: undefined,
      port: 443,
      host: 'tahomalink.com',
      path: '/enduser-mobile-web/enduserAPI/exec/apply',
      _json: true,
      httpModule: [Object],
      agentClass: [Function: Agent],
      agent: [Agent],
      _started: true,
      href: 'https://tahomalink.com/enduser-mobile-web/enduserAPI/exec/apply',
      req: [ClientRequest],
      ntick: true,
      response: [Circular *1],
      originalHost: 'tahomalink.com',
      originalHostHeaderName: 'host',
      responseContent: [Circular *1],
      _destdata: true,
      _ended: true,
      _callbackCalled: true,
      [Symbol(kCapture)]: false
    },
    toJSON: [Function: responseToJSON],
    caseless: Caseless { dict: [Object] },
    body: {
      errorCode: 'UNSUPPORTED_OPERATION',
      error: 'No such command : open on device rts://0407-9481-XXXX/16736319 (rts:UnknowRTSComponent)'
    },
    [Symbol(kCapture)]: false,
    [Symbol(RequestTimeout)]: undefined
  }
}
Kositch commented 3 years ago

It works now - I have emulated Android .apk Connexoon Window RTS, logged to my account (becaus iOS app is not available in our country as I wrote before) and added roller sutters there via app and now it works using this plugin.

But I have two questions:

1) I have configured device control to Close, My, Open. But when I select 50% in Home app it does not go to My position, it goes to etc. 10% and I have My position around 75% when pressed on original remote controller.

2) I don't know how to perform Stop when roller shutter moves and I want to stop it at specific position - on remote controller I click on button My position when it moves and it stops, but when I click on 50% when shutter moves it does not stop.

yenoiwesa commented 3 years ago

Hi @Kositch,

I am not a Somfy employee or expert so I can't really help with the Connexoon configuration itself. My understanding is that your RTS device needs to be assigned a class to be fully recognised as a Window Covering device, and that can only happen through the smartphone app setup flow.

Now regarding your questions:

I have configured device control to Close, My, Open. But when I select 50% in Home app it does not go to My position, it goes to etc. 10% and I have My position around 75% when pressed on original remote controller.

This is not something the plugin has control over, it purely sends open, my and close commands to the Connexoon API, your local box does the rest. I don't think it's possible to have a mismatch between the My position assigned through the remote controller, and any other RTS controller, because the My position is actually recorded in the blind motor itself, and I don't think it allows to have a controller specific value. In your case, it goes to a specific position through the Connexoon app (10%), which differs from the controller one, so I would probably try entirely resetting the blind to factory setting, then redo the remote controller setup, and finally redo the Connexoon setup via your Android APK.

I don't know how to perform Stop when roller shutter moves and I want to stop it at specific position - on remote controller I click on button My position when it moves and it stops, but when I click on 50% when shutter moves it does not stop.

That is not a supported feature of this plugin. Siri/HomeKit doesn't support asking to stop the Window Covering from moving. That's because HomeKit normally asks the device to go to a specific position but that's not possible with RTS blinds. See #11.

Hope that answers your question.

Kositch commented 3 years ago

Thanks, now I have removed the configuration: close, my, open and just left only [] to show only devices I want. It works for Close position, now, but I dont know why - when shutter is closed (blinds are covering the window) when I click Open from the Home app it goes to My position from closed - in log it correctly shows "Set Bedrrom target position success: 100" which should completely roll my blind up, but it stops at My position, which is strange. When I tested in Connexoon RTS app it works without any problem (I have selected typ of devices as Roller shutters in Connexoon app when adding them). Also when I click to 50% in Home app it tells in HB log "Set Bedrrom target position success: 50" but it goes to some other position then is My position, when I test in Connexoon app, it goes correctly to My position when I click My. It seems that the positions are somehow strangely converted when sent from plugin to Connexoon.

Update: Mystery solved, I have found out that when there is delay between commands it works, somehow it needs about 30s between each command to be executed properly.

yenoiwesa commented 3 years ago

Thanks, now I have removed the configuration: close, my, open and just left only [] to show only devices I want.

I am not sure what you mean by that but that sounds incorrect. If you still want to specifically list your devices (for the exclusion rule) but not have a custom values for the commands, you can just do it with an empty object:

"devices": {
    "Bedroom Blind": {}
}

But avoid having "commands": [].

Update: Mystery solved, I have found out that when there is delay between commands it works, somehow it needs about 30s between each command to be executed properly.

Good to know, and yes there is a delay until a command is considered finished on the Somfy server side. That's not something I can control. However it should normally still have sent the command to reach your correct final destination (and cancelled the ongoing one). So your problem doesn't seem like expected behaviour.

Make sure that your configuration JSON is correct, and let me know.

Kositch commented 3 years ago

This is my current working configuration - I want shutters to go to My position when "opened" in home app and it works in this setup:

{
            "platform": "Connexoon",
            "name": "Connexoon",
            "username": "...",
            "password": "...",
            "service": "Connexoon",
            "useListedDevicesOnly": true,
            "devices": {
                "Pokojicek": {
                    "commands": [
                        "my",
                        "open"
                    ]
                },
                "Pracovna": {
                    "commands": [
                        "my",
                        "open"
                    ]
                },
                "Loznice": {
                    "commands": [
                        "my",
                        "open"
                    ]
                },
                "Obyvak": {
                    "commands": [
                        "my",
                        "open"
                    ]
                },
                "Hosti": {
                    "commands": [
                        "my",
                        "open"
                    ]
                }
            }
        }
yenoiwesa commented 3 years ago

If you want the shutters to go from My and Closed you should have ["my", "close"] (or the reverse array depending on how your blind is mounted). Why have open in it?

Kositch commented 3 years ago

I am not sure, if I understood open vs. close correctly - I want to have My position as closed (window is covered with shutters) - meaning when I click on shutter in Home app it goes to My position instead of to close position (completely covering the window) and when I click again on shutter icon it opens the shutter (meaning shutters goes up and the window is not covered). Mayby I confused open vs. closed, but in this config it does what I want :-) Is it possible to have completely closed position (window is covered with shutters) as a 50% in Home app?

UPDATE: I was able to have it opened to 100% (meaning covering the window with shutter) when clicking on 50% by this final config: "open","close", "my". I have verified that when it sends command "close" the shutter goes all the way down to completely covering the window, which is strange, because based on that what you said, "close" command should roll up the shutter (meaning not covering the window).

yenoiwesa commented 3 years ago

I have verified that when it sends command "close" the shutter goes all the way down to completely covering the window, which is strange, because based on that what you said, "close" command should roll up the shutter (meaning not covering the window).

Sorry what? I never said that lol. Close means the blind will end up in the closed position meaning there will be the least amount of light coming through. Open means maximum amount of light coming through.

Either way, it seems that you have managed to achieve the configuration you desired so I will be closing this ticket now.

Cheers.