Like many other Indigo users, I want to thank you for writing the HKLS plugin... it is truly a joy to use
I upgraded to HKLS from HomeKit Bridge effortlessly, and am now using it successfully in my home automation system with 74 devices, including two VGD devices. I can ask Siri to open, close, and check the garage doors. The HomeKit app works as well; it opens and closes the doors and shows the open/close status in the display. All of this is done using the onOffState of the VGD device which has two values ( False/off/0 -> open and True,/on/ 1 -> closed,).
The Apple HimeKit framework permits 5 door states values (see https://developer.apple.com/documentation/homekit/hmcharacteristicvaluedoorstate). These are: 0 -> open, 1 -> closed, 2 -> opening, 3 -> closing, and 4 -> stopped. The first four are obvious. The fifth (stopped) is an interrupted (perhaps obstructed) state during door opening. There is no corresponding state in the framework for interrupted (or obstructed) closing. Nevertheless, the framework includes an "ObstructionDetected" characteristic which presumably applies for both opening and closing. My desire is to modify the VGD and HKLS plugins to utilize these additional state values and characteristics. The goal is to have the HomeKit app additionally display opening and closing states and "ObstructionDetected".
I have modified the VGD plugin to include a new integer state variable named "doorState". Its values are the five HomeKit state values and an additional state value (5 -> reversing) to indicate interrupted (or obstructed) closing. It retains the same onOffState for compatibility with existing software. This versions not yet released in either GitHub or the Indigo PluginStore. It is available as the current master branch in GitHub should you want to look at it.
I have also modified a local copy of your HKLS plugin (v0.5.9) to recognize the new VGD doorState and set the GarageDoor accessory characteristics accordingly. My modified version looks for the doorState first, then if not present, the onOffState, and finally the binaryInput1 for Insteon. This should maintain compatibility with other GarageDoor devices/plugins. It then sets three GarageDoor accessory characteristics ( CurrentDoorState, TargetDoorState, and ObstructionDetected) based on rules that I determined empirically.
I have tested the modified HKLS version with my modified VGD plugin and the combination seems to work well with the HomeKit app for both normal and interrupted door operations. Nevertheless, my knowledge of the HomeKit framework is limited and I'm not sure that I captured all the subtleties of the interaction between the TargetDoorState and the CurrentDoorState. If you can help, please look at my assignment rules for the GarageDoor characteristics and let me know what you think. As I said, they work In my limited tests... but who knows if there are any side effects?
There are 5 small segments of code that changed in my modified HLKS version. Because there are so few changes, I am including them in this post for your review. Line numbers are referenced to your current GitHub version (v0.5.10). If you wish, I can provide these as a formal GitHub pull request.
Segment 1: HomeKitDevices.py, class GarageDoor, __init__ method, lines 1464-1466; remove the comment tag from these lines and correct spelling in "ObstructionDetected"
- Code: Select all
self.char_obstruction_detected = serv_garage_door.configure_char(
"ObstructionDetected", value=False
)
Segment 2: HomeKitDevices.py, class GarageDoor, _set_chars method; insert the following commented debug code after line 1509
- Code: Select all
# (VGD) debug code for papamac's Virtual Garage Door (VGD) changes
# (VGD) currentDoorState = self.char_current_state.get_value()
# (VGD) targetDoorState = self.char_target_state.get_value()
# (VGD) obstructionDetected = int(self.char_obstruction_detected.get_value())
# (VGD) chars = (currentDoorState, targetDoorState, obstructionDetected)
# (VGD) logger.warning('GarageDoor characteristics changed by HK: (c, t, o) {}'.format(chars))
Segment 3: plugin.py; insert debug method after line 1423, just before the deviceUpdated method
- Code: Select all
# (VGD) debug method for papamac's Virtual Garage Door (VGD) changes
@staticmethod
def _getGarageDoorCharacteristics(accessory):
currentDoorState = accessory.char_current_state.get_value()
targetDoorState = accessory.char_target_state.get_value()
obstructionDetected = int(accessory.char_obstruction_detected.get_value())
return currentDoorState, targetDoorState, obstructionDetected
Segment 4: plugin.py, deviceUpdated method; replace the elif clause at line 1799 with
- Code: Select all
elif str(updateddevice_subtype) == "GarageDoor":
for stateName in ("doorState", "onOffState", "binaryInput1"): # ordered by preference
# doorState: 0 -> open, 1 -> closed, 2 -> opening, 3 -> closing, 4 -> stopped, 5 -> reversing
# onOffState: 0 -> open, 1 -> closed
# binaryInput1: 0 -> open, 1 -> closed
if stateName in updated_device.states: # choose the first match
oldstate = original_device.states[stateName]
newstate = updated_device.states[stateName]
if newstate != oldstate: # state has changed
# Log Indigo device state change.
# (VGD) debug code for papamac's Virtual Garage Door (VGD) changes
# (VGD) self.logger.warning('Indigo device "{}" {} changed: {} --> {}'.format(updated_device.name, stateName, oldstate, newstate))
if self.debug2:
self.logger.debug("NewState of Device:{} & State: {} ".format(updated_device.name, newstate))
if this_is_debug_device:
self.logger.warning("NewState of Device:{} & State: {} ".format(updated_device.name, newstate))
accessory = self.device_list_internal[checkindex]["accessory"]
# (VGD) oldChars = self._getGarageDoorCharacteristics(accessory)
# Update GarageDoor characteristics based on Indigo device state change.
# CurrentDoorState must be 0 -> open, 1 -> closed, 2 -> opening, or 3 -> closing.
currentDoorState = (0, 1, 2, 3, 0, 2)[newstate]
accessory.char_current_state.set_value(currentDoorState)
# TargetDoorState must be 0 -> open or 1 -> closed
targetDoorState = (0, 1, 0, 1, 0, 0)[newstate]
accessory.char_target_state.set_value(targetDoorState)
# ObstructionDetected must be 0 -> False or 1 -> True
obstructionDetected = (None, 0, None, 0, 1, 1)[newstate]
if obstructionDetected is not None:
accessory.char_obstruction_detected.set_value(obstructionDetected)
# (VGD) newChars = self._getGarageDoorCharacteristics(accessory)
# (VGD) self.logger.warning('GarageDoor characteristics changed by HKLS (c, t, o): {} --> {}'.format(oldChars, newChars))
break
return
Segment 5: plugin.py, Plugin_getter_callback method; replace the elif clause at line 2406 with
- Code: Select all
elif statetoGet == "garageDoorState":
for stateName in ("doorState", "onOffState", "binaryInput1"): # ordered by preference
if stateName in indigodevice.states: # choose the first match
if self.debug4:
self.logger.debug("Found {} using that..".format(stateName))
return indigodevice.states[stateName]
So, thanks for listening to my story. My ask is that you review and evaluate my changes to your HKLS plugin, change them as you see fit, and incorporate their functionality into a future release of HKLS. If you have any concerns, or want to run additional test cases in my environment, please let me know. I will continue to work on an updated VGD release. My new release will work (in a limited way) without the HKLS changes, so we can work on this asynchronously. I hope that you view my suggestions positively as a win-win-win for HKLS, VGS, and Indigo users. Thanks again for your consideration.
David