Skip to content

Instantly share code, notes, and snippets.

@andrey-yantsen
Last active April 1, 2020 19:54
Show Gist options
  • Save andrey-yantsen/0359bb4a74df60b73f6038ae2d87c9fc to your computer and use it in GitHub Desktop.
Save andrey-yantsen/0359bb4a74df60b73f6038ae2d87c9fc to your computer and use it in GitHub Desktop.
Workaround for openhab/openhab2-addons#3522

This script monitors openhab log for messages like Terminating homekit connection and New homekit connection and saving connection state to specified MQTT. I'm running it with following parameters:

python3 homekiter.py --mqtt_host wb.286.su --mqtt_topic_prefix /custom/homekit_connected --logfile /usr/src/logs/openhab.log

In the openhab I have created following things and items:

Thing exec:command:openhab_refresh_homekit [ command="ssh -i /openhab/conf/id_rsa openhab@localhost -p 8101 bundle:refresh org.openhab.io.homekit", interval=0, autorun=false ]
Switch refresh_homekit {channel="exec:command:openhab_refresh_homekit:run", autoupdate="false"}

Switch homekit_connected_atv (gHomekitConnected) {mqtt="<[wirenboard:/custom/homekit_connected/192.168.88.67:state:MAP(mqtt_on_off.map)]", autoupdate="false"}
Switch homekit_connected_andrey_iphone (gHomekitConnected) {mqtt="<[wirenboard:/custom/homekit_connected/192.168.88.67:state:MAP(mqtt_on_off.map)]", autoupdate="false"}
Switch homekit_connected_alina_iphone (gHomekitConnected) {mqtt="<[wirenboard:/custom/homekit_connected/192.168.88.68:state:MAP(mqtt_on_off.map)]", autoupdate="false"}
Switch homekit_connected_ipad (gHomekitConnected) {mqtt="<[wirenboard:/custom/homekit_connected/192.168.88.66:state:MAP(mqtt_on_off.map)]", autoupdate="false"}

Group:Switch:OR(ON,OFF) gHomekitConnected

And at last following rule refreshes homekit when there is no active homekit connections for few seconds:

rule "Reload homekit when no connections"
when
    Item gHomekitConnected changed to OFF
then
    createTimer(now.plusSeconds(5), [|
        if (gHomekitConnected.state == OFF) {
            refresh_homekit.sendCommand(ON)
            sendTelegram("wb286prv", "Перезапускаю HomeKit")
        }
    ])
end
import argparse
import os
import time
from paho.mqtt.publish import single as publish
def follow(name):
current = open(name, "rb")
current.seek(-1000, os.SEEK_END)
current.readline() # skip incomplete line
pos = current.tell()
current.close()
current = open(name, "r")
current.seek(pos, os.SEEK_SET)
curino = os.fstat(current.fileno()).st_ino
while True:
while True:
line = current.readline()
if not line:
break
yield line.strip()
try:
if os.stat(name).st_ino != curino:
new = open(name, "r")
current.close()
current = new
curino = os.fstat(current.fileno()).st_ino
except IOError:
pass
time.sleep(2)
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Detect if homekit client is connected.')
parser.add_argument('--mqtt_host', type=str, help='mqtt server address', required=True)
parser.add_argument('--mqtt_port', type=int, default=1883, help='mqtt server port')
parser.add_argument('--mqtt_topic_prefix', type=str, help='state will be saved into $(prefix)/$(ip)', required=True)
parser.add_argument('--ips', type=str, nargs='+', help='ips to monitor', required=False)
parser.add_argument('--logfile', type=str, help='path to log file', required=True)
args = parser.parse_args()
for line in follow(args.logfile):
if 'homekit connection' in line:
_, log = line.split(' - ')
log = log.strip().split(' ')
if log[0] == 'Terminated':
state = 0
elif log[0] == 'New':
state = 1
else:
continue
ip, _ = log[-1].split(':')
ip = ip[1:] # remove initial slash
if not args.ips or ip in args.ips:
topic = args.mqtt_topic_prefix + '/' + ip
print(f'Sending {state} to {topic}')
publish(topic, qos=1, payload=state, retain=True, hostname=args.mqtt_host, port=args.mqtt_port)
paho-mqtt==1.3.1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment