Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

notify multiple HomeKit Apps when switch state has changed #427

Open
th0u opened this issue Nov 29, 2022 · 6 comments
Open

notify multiple HomeKit Apps when switch state has changed #427

th0u opened this issue Nov 29, 2022 · 6 comments

Comments

@th0u
Copy link

th0u commented Nov 29, 2022

Hi,
I use your HAP Lib (4.5.0) and implemented a simple accessory (on-off switch) to be included in the bridge and into Homekit.
Thanks to some samples and clear documentation... an easy one.
The accessory has setter and getter_callback to set or get the state. Basically it works well as expected.

The remote controllable switch can also be switched on/off manually and the switch does not self publish state changes. This is basically no problem in my scenario, as whenever I open the HomeKit app, the Bridge infrastructure is triggered to call the getter_callback which synchronizes the state from switch to the accessory instance and so HomeKit shows the current state.
Synchronizing the state within HomeKit also works "live" e.g. when opening HomeKit app on two different Devices and when I toggle the switch on one device then the change is reflected in HomeKit App on other device virtually instantly.

I have these use cases:
#1 Switch toggled using HomeKit
Expected behavior:

  • (a) Remote Switch state changes
  • (b) Switch-representation in Homekit App used to toggle the switch is updated to the new state
  • (c) On second Device, Switch-representation in HomeKit App in foreground is updated to the new state

Observed behavior:
(a), (b), (c). All OK!

#2 Remote Switch toggled manually while HomeKit apps are not in foreground on iOS
Expected behavior:

  • (a) The Remote Switch state changes. Bridge is not notified of state change, because remote Switch can not do this by its own
  • (b) After opening HomeKit App on iOS the switch-representation shows “updating”, while the getter_callback synchronizes the remote switch state into accessory instance and finally the switch representation in HomeKit app shows the proper state.

Observed behavior:
(a), (b). All OK!

Now the unexpected outcome:
#3 Remote switch toggled manually, while HomeKit App#1 on iOS Device #1 is in background and HomeKit App #2 on device #2 is in foreground.
Expected behavior:

  • (a) The Remote Switch state changes. Bridge is not notified of state change, because remote Switch can not do this by its own.
  • (b) HomekitApp#2 does not reflect the change, because Bridge is not informed of state change by remote switch.
  • (c) When opening HomekitApp#1, the switch-representation shows “updating”, while the getter_callback synchronizes the remote switch state into accessory instance and finally the switch representation in HomeKit app#1 shows the proper state.
  • (d) HomeKit App#2 should update as well because the bridge has updated the Switch State using getter_callback when HomeKit-App#1 was opened.

Observed Behavoir:
(a), (b), (c). Missing (d).

So the missing one is (d) in Use case #3. The bridge updated itself while opening HomekitApp#1 but the update is not propagated to Homekit App#2. As this is working in use case #2, I have the hope that this could also work for use case #3.

So, is there a way to notify all active Homekit Apps the update their state view?

Thnx , T

@th0u th0u changed the title notify HomeKit Apps when switch state has changed notify multiple HomeKit Apps when switch state has changed Nov 29, 2022
@Pythonaire
Copy link

I think, the "HomeKit apps" will not be notified generally. The brigde is connected to the HomeKit and send/receive states.
The App connect the HomeKit an send/receive the states to/from the HomeKit. The Homekit mediates only. It seems to me, the second app have no reliable connection to the homekit. Can the second App switch and the first App see the action?

@th0u
Copy link
Author

th0u commented Nov 29, 2022

The effect is the same in Use case #3 even when switching the roles of Device/Homekit App #1 and #2. I can rule out connectivity issues.

@Pythonaire
Copy link

Pythonaire commented Nov 30, 2022

The effect is the same in Use case #3 even when switching the roles of Device/Homekit App #1 and #2. I can rule out connectivity issues.

Question: both clients Device/Homekit App #1 and #2 are on the same iOS release? And if you swipe down on the Device/Homekit (try refresh the view) nothing changed?

I have an equal use case, but using HTTPServer (example: /accessories/Http.py) to get the device state in reverse. If i'm switching manually, the device send {"aid":XXX,"services": {"Switch": {"On": true}}}' or false to the bridge. It works as expected.

@th0u
Copy link
Author

th0u commented Nov 30, 2022

@Pythonaire : Yes, both devices are on same iOS. I observed this behaviour during after multiple test/wipe/test iterations.

The http example hint is unfortunately still not an option, as said in my initial post, the switch does not have the capabilities to send something back.

@Pythonaire
Copy link

@Pythonaire : Yes, both devices are on same iOS. I observed this behaviour during after multiple test/wipe/test iterations.

The http example hint is unfortunately still not an option, as said in my initial post, the switch does not have the capabilities to send something back.

could you try additional notify() in conjunction with get_value()?

@Pythonaire
Copy link

Pythonaire commented Nov 30, 2022

That's my switch, with setter_callback and getter_callback, it works as expected.

class TestSwitch(Accessory):
    category = CATEGORY_SWITCH
    def __init__(self, *args, **kwargs): 
        super().__init__(*args, **kwargs)
        self.set_info_service(firmware_revision='0.0.3', model='XXX', manufacturer= 'XXX', serial_number="XXX")
        switch = self.add_preload_service('Switch', chars=['On'])
        self.UnitState = switch.configure_char('On') # bool needed
        self.UnitState.set_value(self.getState())
        self.UnitState.setter_callback = self.setState
        self.UnitState.getter_callback = self.getState()
        
    def getState(self):
        try:
            state = requests.get(url).json() # return int
        except ConnectTimeout as e:
            logging.info('**** request to {0} timed out: {1}'.format(url, e)) 
            state = 0
        return bool(state)

    def setState(self, value): # value is bool
        state = int(value)
        try:
            requests.post(url, data = str(value)) # need str
        except ConnectTimeout as e:
            state = 0
            logging.info('**** request.post got exception {0}'.format(e)) 
        return bool(state)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants