Added toothbrush worker with Home Assistant support (#67)
The worker has dicts with possible brush states, modes and sectors It sends a one time retained Home Assistant autoconfig message to automatically setup a sensor with the correct topics It sends the state in a state topic and other attributes in an attribute topic
This commit is contained in:
+14
-2
@@ -68,11 +68,23 @@ manager:
|
||||
ix: 00:11:22:33:44:55
|
||||
ia: 11:22:33:44:55:66
|
||||
topic_prefix: toothbrush
|
||||
update_interval: 10
|
||||
update_interval: 10
|
||||
toothbrush_homeassistant:
|
||||
args:
|
||||
autodiscovery_prefix: homeassistant
|
||||
topic_prefix: toothbrush
|
||||
devices:
|
||||
ix:
|
||||
name: IX
|
||||
mac: 00:11:22:33:44:55
|
||||
ia:
|
||||
name: IA
|
||||
mac: 11:22:33:44:55:66
|
||||
update_interval: 10
|
||||
switchbot:
|
||||
args:
|
||||
devices:
|
||||
heater: 00:11:22:33:44:55
|
||||
heater: 00:11:22:33:44:55
|
||||
topic_prefix: switchbot/bathroom
|
||||
state_topic_prefix: switchbot/bathroom
|
||||
topic_subscription: switchbot/+/+/set
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
import time
|
||||
import json
|
||||
|
||||
from bluepy.btle import Scanner, DefaultDelegate
|
||||
from mqtt import MqttMessage
|
||||
|
||||
from workers.base import BaseWorker
|
||||
import logger
|
||||
|
||||
REQUIREMENTS = ["bluepy"]
|
||||
_LOGGER = logger.get(__name__)
|
||||
|
||||
BRUSHSTATES = {
|
||||
0: "Unknown",
|
||||
1: "Initializing",
|
||||
2: "Idle",
|
||||
3: "Running",
|
||||
4: "Charging",
|
||||
5: "Setup",
|
||||
6: "Flight Menu",
|
||||
113: "Final Test",
|
||||
114: "PCB Test",
|
||||
115: "Sleeping",
|
||||
116: "Transport"
|
||||
}
|
||||
|
||||
BRUSHMODES = {
|
||||
0: "Off",
|
||||
1: "Daily Clean",
|
||||
2: "Sensitive",
|
||||
3: "Massage",
|
||||
4: "Whitening",
|
||||
5: "Deep Clean",
|
||||
6: "Tongue Cleaning",
|
||||
7: "Turbo",
|
||||
255: "Unknown"
|
||||
}
|
||||
|
||||
BRUSHSECTORS = {
|
||||
0: "Sector 1",
|
||||
1: "Sector 2",
|
||||
2: "Sector 3",
|
||||
3: "Sector 4",
|
||||
4: "Sector 5",
|
||||
5: "Sector 6",
|
||||
7: "Sector 7",
|
||||
8: "Sector 8",
|
||||
254: "Last sector",
|
||||
255: "No sector"
|
||||
}
|
||||
|
||||
class ScanDelegate(DefaultDelegate):
|
||||
def __init__(self):
|
||||
DefaultDelegate.__init__(self)
|
||||
|
||||
def handleDiscovery(self, dev, isNewDev, isNewData):
|
||||
if isNewDev:
|
||||
_LOGGER.debug("Discovered new device: %s" % dev.addr)
|
||||
|
||||
class Toothbrush_HomeassistantWorker(BaseWorker):
|
||||
def _setup(self):
|
||||
self.autoconfCache = {}
|
||||
|
||||
def searchmac(self, devices, mac):
|
||||
for dev in devices:
|
||||
if dev.addr == mac.lower():
|
||||
return dev
|
||||
return None
|
||||
|
||||
def get_autoconf_data(self, key, name):
|
||||
if key in self.autoconfCache:
|
||||
return False
|
||||
else:
|
||||
self.autoconfCache[key] = True
|
||||
return {
|
||||
"platform": "mqtt",
|
||||
"name": name,
|
||||
"state_topic": self.topic_prefix+"/"+key+"/state",
|
||||
"availability_topic": self.topic_prefix+"/"+key+"/presence",
|
||||
"json_attributes_topic": self.topic_prefix+"/"+key+"/attributes",
|
||||
"icon": "mdi:tooth-outline"
|
||||
}
|
||||
|
||||
def get_state(self, item):
|
||||
if item in BRUSHSTATES:
|
||||
return BRUSHSTATES[item]
|
||||
else:
|
||||
return BRUSHSTATES[0]
|
||||
|
||||
def get_mode(self, item):
|
||||
if item in BRUSHMODES:
|
||||
return BRUSHMODES[item]
|
||||
else:
|
||||
return BRUSHMODES[255]
|
||||
|
||||
def get_sector(self, item):
|
||||
if item in BRUSHSECTORS:
|
||||
return BRUSHSECTORS[item]
|
||||
else:
|
||||
return BRUSHSECTORS[255]
|
||||
|
||||
def status_update(self):
|
||||
scanner = Scanner().withDelegate(ScanDelegate())
|
||||
devices = scanner.scan(5.0)
|
||||
ret = []
|
||||
|
||||
for key, item in self.devices.items():
|
||||
device = self.searchmac(devices, item['mac'])
|
||||
|
||||
rssi = 0
|
||||
presence = 0
|
||||
state = 0
|
||||
pressure = 0
|
||||
time = 0
|
||||
mode = 255
|
||||
sector = 255
|
||||
|
||||
if device is not None:
|
||||
bytes_ = bytearray.fromhex(device.getValueText(255))
|
||||
_LOGGER.debug("text: %s" % device.getValueText(255) )
|
||||
|
||||
if bytes_[5] > 0:
|
||||
rssi = device.rssi
|
||||
presence = 1
|
||||
state = bytes_[5]
|
||||
pressure = bytes_[6]
|
||||
time = bytes_[7]*60 + bytes_[8]
|
||||
mode = bytes_[9]
|
||||
sector = bytes_[10]
|
||||
|
||||
attributes = {
|
||||
"rssi": rssi,
|
||||
"pressure": pressure,
|
||||
"time": time,
|
||||
"mode": self.get_mode(mode),
|
||||
"sector": self.get_sector(sector)
|
||||
}
|
||||
presence_value = "online" if presence == 1 else "offline"
|
||||
|
||||
ret.append(MqttMessage(topic=self.format_topic(key+"/presence"), payload=presence_value))
|
||||
ret.append(MqttMessage(topic=self.format_topic(key+"/state"), payload=self.get_state(state)))
|
||||
ret.append(MqttMessage(topic=self.format_topic(key+"/attributes"), payload=json.dumps(attributes)))
|
||||
|
||||
autoconf_data = self.get_autoconf_data(key, item['name'])
|
||||
if autoconf_data != False:
|
||||
ret.append(MqttMessage(topic=self.autodiscovery_prefix+"/sensor/"+self.topic_prefix+"_"+key+"/config", payload=json.dumps(autoconf_data), retain=True))
|
||||
|
||||
return ret
|
||||
Reference in New Issue
Block a user