andersonshatch / soma-ctrl

Node util for controlling SOMA smart shade via MQTT or HTTP
MIT License
21 stars 6 forks source link

Homekit helpers - target position and opening/closing state #79

Open andersonshatch opened 5 years ago

andersonshatch commented 5 years ago

Will address #76 @markob100 would appreciate your feedback on this after some testing.

markob100 commented 5 years ago

Thanks for this! I will have a look at the weekend.

Sent from my iPad

On 30 Aug 2019, at 17:37, Josh Anderson notifications@github.com wrote:

Will address #76 @markob100 would appreciate your feedback on this after some testing.

You can view, comment on, or merge this pull request online at:

https://github.com/andersonshatch/soma-ctrl/pull/79

Commit Summary

Keep a target position attribute Set opening/closing in addition to open/closed File Changes

M src/SomaShade.js (15) Patch Links:

https://github.com/andersonshatch/soma-ctrl/pull/79.patch https://github.com/andersonshatch/soma-ctrl/pull/79.diff — You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or mute the thread.

markob100 commented 5 years ago

I've had this running for a few days. Stable, but doesn't seem to add the enhancement.

targetPosition

Expected: targetPosition (as displayed on the JSON generated by the GET command) to change immediately on receipt of POST 'move to x' command to 'x'. What happens: both targetPosition and Position stay at initial position until blind has settled at 'x'. Example: Blind was at 100. I sent POST command to move to 47. Blind started moving. Both tP and P stayed at 100 (looking at it both in the repeatedly-refreshed browser window and in HK which pulls the data from the webpage JSON) until blind had stopped moving at 47, then both tP and P updated simultaneously to 57.

state Expected: state (as displayed on the JSON generated by the GET command) to change to 'opening' or 'closing' (as appropriate) when blind is moving from Position to targetPosition. Then to read 'open' if Position is not 0, and to read 'closed' is Position is 0 (existing behaviour). What happens: State doesn’t seem to change from ‘open’ - I don’t see ‘opening’ or ‘closing’ in the JSON when the blind is moving.

Am I missing something obvious? I've definitely got the right branch installed - I do see 'targetPosition' in the JSON, it just seems to match Position at all times.

Thanks for your work on this - much appreciated, and this is already much more functional than SomaConnect!

andersonshatch commented 5 years ago

I think there was essentially a race sometimes between whether you'd get the targetPosition of what you requested, or the one from the previous state. And state opening/closing I was not changing until the callback from the BTLE write succeeded, so it was definitely after the state is retrieved to be returned with the POST.

I've now moved these to happen earlier, which means they're set on the assumption that the state write succeeds (no error with BTLE comms); sometimes this will not be true, but you should at least see the states more frequently this way. LMK how it looks! :)

markob100 commented 5 years ago

Thanks for this - interesting behaviour! If I POST a new TargetPosition, the GET endpoint correctly updates both TargetPosition and State immediately. However, it quickly reverts to mirroring the original Position in TargetPosition and mirroring the original State.

In other words: it works as expected at first but then (whilst the blind is still moving) the behaviour reverts to that described previously.

Sent from my iPad

On 7 Sep 2019, at 19:57, Josh Anderson notifications@github.com wrote:

I think there was essentially a race sometimes between whether you'd get the targetPosition of what you requested, or the one from the previous state. And state opening/closing I was not changing until the callback from the BTLE write succeeded, so it was definitely after the state is retrieved to be returned with the POST.

I've now moved these to happen earlier, which means they're set on the assumption that the state write succeeds (no error with BTLE comms); sometimes this will not be true, but you should at least see the states more frequently this way. LMK how it looks! :)

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or mute the thread.

andersonshatch commented 5 years ago

Does it get disconnected and subsequently reconnect whilst moving to your target position? That would reset the states, and I’m not sure if it makes sense to restore them, especially if reconnecting is not instant.

On 8 Sep 2019, at 21:32, markob100 notifications@github.com wrote:

Thanks for this - interesting behaviour! If I POST a new TargetPosition, the GET endpoint correctly updates both TargetPosition and State immediately. However, it quickly reverts to mirroring the original Position in TargetPosition and mirroring the original State.

In other words: it works as expected at first but then (whilst the blind is still moving) the behaviour reverts to that described previously.

Sent from my iPad

On 7 Sep 2019, at 19:57, Josh Anderson notifications@github.com wrote:

I think there was essentially a race sometimes between whether you'd get the targetPosition of what you requested, or the one from the previous state. And state opening/closing I was not changing until the callback from the BTLE write succeeded, so it was definitely after the state is retrieved to be returned with the POST.

I've now moved these to happen earlier, which means they're set on the assumption that the state write succeeds (no error with BTLE comms); sometimes this will not be true, but you should at least see the states more frequently this way. LMK how it looks! :)

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or mute the thread. — You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or mute the thread.

markob100 commented 5 years ago

You’re right - it does. See log excerpt below.

I don’t know why I wouldn’t want it to restore rather than reset states on reconnect, though? What’s the downside of ‘restoring’ on reconnect?

soma:d12b7e625b6e connected! +0ms

soma:d12b7e625b6e position 100 +1s

soma:d12b7e625b6e group: Kitchen +32ms

soma:d12b7e625b6e name: Kitchen2 +27ms

soma:d12b7e625b6e battery at 57% +60ms

soma:d12b7e625b6e disconnected +14s

soma:d12b7e625b6e connected for 15.683 seconds +1ms

soma:d12b7e625b6e flagging disconnect after timeout +15s

soma:d12b7e625b6e connected! +646ms

soma:d12b7e625b6e position 100 +2s

soma:d12b7e625b6e battery at 57% +180ms

soma:d12b7e625b6e requesting move to 64 +10s

soma:d12b7e625b6e battery at 40% +167ms

soma:d12b7e625b6e battery at 49% +240ms

soma:d12b7e625b6e battery at 51% +149ms

soma:d12b7e625b6e disconnected +3s

soma:d12b7e625b6e connected for 15.645 seconds +1ms

soma:d12b7e625b6e flagging disconnect after timeout +15s

soma:d12b7e625b6e connected! +734ms

soma:d12b7e625b6e position 100 +2s

soma:d12b7e625b6e battery at 49% +150ms

soma:d12b7e625b6e battery at 51% +120ms

soma:d12b7e625b6e battery at 49% +195ms

soma:d12b7e625b6e battery at 51% +510ms

soma:d12b7e625b6e battery at 49% +120ms

soma:d12b7e625b6e battery at 51% +600ms

soma:d12b7e625b6e battery at 49% +180ms

soma:d12b7e625b6e battery at 51% +900ms

soma:d12b7e625b6e battery at 49% +120ms

soma:d12b7e625b6e battery at 51% +480ms

soma:d12b7e625b6e battery at 49% +301ms

soma:d12b7e625b6e battery at 51% +404ms

soma:d12b7e625b6e battery at 49% +195ms

soma:d12b7e625b6e battery at 51% +900ms

soma:d12b7e625b6e battery at 49% +120ms

soma:d12b7e625b6e battery at 51% +780ms

soma:d12b7e625b6e battery at 49% +120ms

soma:d12b7e625b6e battery at 51% +375ms

soma:d12b7e625b6e battery at 49% +210ms

soma:d12b7e625b6e battery at 51% +2s

soma:d12b7e625b6e battery at 49% +315ms

soma:d12b7e625b6e battery at 51% +1s

soma:d12b7e625b6e battery at 49% +180ms

soma:d12b7e625b6e battery at 51% +135ms

soma:d12b7e625b6e battery at 49% +165ms

soma:d12b7e625b6e battery at 51% +900ms

soma:d12b7e625b6e battery at 49% +120ms

soma:d12b7e625b6e disconnected +2s

soma:d12b7e625b6e connected for 15.705 seconds +0ms

Sent from my iPad

On 8 Sep 2019, at 21:58, Josh Anderson notifications@github.com wrote:

Does it get disconnected and subsequently reconnect whilst moving to your target position? That would reset the states, and I’m not sure if it makes sense to restore them, especially if reconnecting is not instant.

On 8 Sep 2019, at 21:32, markob100 notifications@github.com wrote:

Thanks for this - interesting behaviour! If I POST a new TargetPosition, the GET endpoint correctly updates both TargetPosition and State immediately. However, it quickly reverts to mirroring the original Position in TargetPosition and mirroring the original State.

In other words: it works as expected at first but then (whilst the blind is still moving) the behaviour reverts to that described previously.

Sent from my iPad

On 7 Sep 2019, at 19:57, Josh Anderson notifications@github.com wrote:

I think there was essentially a race sometimes between whether you'd get the targetPosition of what you requested, or the one from the previous state. And state opening/closing I was not changing until the callback from the BTLE write succeeded, so it was definitely after the state is retrieved to be returned with the POST.

I've now moved these to happen earlier, which means they're set on the assumption that the state write succeeds (no error with BTLE comms); sometimes this will not be true, but you should at least see the states more frequently this way. LMK how it looks! :)

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or mute the thread. — You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or mute the thread. — You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or mute the thread.

markob100 commented 5 years ago

@andersonshatch any thoughts on the above? Question is 'What’s the downside of ‘restoring’ on reconnect?'

andersonshatch commented 5 years ago

Haven't had a chance to verify this yet, but I think there will be an issue if the opening/closing state is restored on reconnect, but in fact, the device has already stopped moving.

This is down to the current position characteristic -- which I subscribe to and read on (re-)connect -- only getting updated when the device stops moving. Whilst it is moving to the target position, we hear nothing from the device, so can only infer that it's stopped moving if there was no reconnect when we next get a current position value.

I think there could be a workaround for that, which is if we're in opening/closing state, check when we get a value for current position and switch to open/closed if it is equal to the target position (or within a few points of it, as sometimes they'll stop before reaching the target position)

Hopefully can verify this in the not too distant future.

markob100 commented 5 years ago

I see, and thanks for sticking with this!

That workaround makes sense but I wonder if it’ll run into another issue I have (let me know if you want me to open a separate ‘enhancement’ issue for this): the Soma units cut out after 5 minutes of activity. We have large roman blinds and it takes ~7 minutes to open and close them fully. So I have to send the ‘open’ command twice.

Using SomaCtrl this is fine - blinds are at 100, I send ‘move to 0’, off they go, after 5 minutes they stop and are at 23. SomaCtrl updates and the position of 23 gets passed through to HK no problem. I just send ‘move to 0’ again and they move the last 23%. But if SomaCtrl ‘knows’ TargetPosition is 0 and it then compares CurrentPosition of 23 with TargetPosition of 0, would the workaround you’re proposing mean it assumes it’s in ‘closing’ state even when stopped at 23? (Also note that on reconnect TargetPosition seems to update to mirror CurrentPosition rather than the last POSTed TargetPosition.)

Perhaps I should be focusing instead on why I get disconnects every 15 seconds. Any idea? Wondering about trying a Bluetooth USB dongle instead of the on-board rPi radio.

Separately, though, I have been wondering about the 5-minute issue. Would it be possible to re-purpose the workaround you describe above for SomaCtrl to do something like this:

What do you think?

Here, by the way, is the btmon log showing the BT disconnect and reconnect:

> HCI Event: Disconnect Complete (0x05) plen 4                            #133 [hci0] 40.140877
        Status: Success (0x00)
        Handle: 64
        Reason: Unacceptable Connection Parameters (0x3b)
@ MGMT Event: Device Disconnected (0x000c) plen 8                     {0x0003} [hci0] 40.140930
        LE Address: D1:2B:7E:62:5B:6E (Static)
        Reason: Unspecified (0x00)
@ MGMT Event: Device Disconnected (0x000c) plen 8                     {0x0001} [hci0] 40.140930
        LE Address: D1:2B:7E:62:5B:6E (Static)
        Reason: Unspecified (0x00)
< HCI Command: LE Create Connection (0x08|0x000d) plen 25                 #134 [hci0] 40.232883
        Scan interval: 60.000 msec (0x0060)
        Scan window: 30.000 msec (0x0030)
        Filter policy: White list is not used (0x00)
        Peer address type: Random (0x01)
        Peer address: D1:2B:7E:62:5B:6E (Static)
        Own address type: Public (0x00)
        Min connection interval: 7.50 msec (0x0006)
        Max connection interval: 15.00 msec (0x000c)
        Connection latency: 0 (0x0000)
        Supervision timeout: 2000 msec (0x00c8)
        Min connection length: 2.500 msec (0x0004)
        Max connection length: 3.750 msec (0x0006)
> HCI Event: Command Status (0x0f) plen 4                                 #135 [hci0] 40.235908
      LE Create Connection (0x08|0x000d) ncmd 1
        Status: Success (0x00)