I have a OneWheel, which is a bloody amazing piece of machinery, practically snowboarding uphill, on concrete, year round - or on trails, thing is amazing. Anyhow it exposes the battery and other settings via BLE. I’ve setup HA to have a view that shows the battery % and if it hits 100% turn off the smart plug attached. Scripts and configuration below, likely not the best way to do it, but works for me. Could be adapted to work with any BLE device and pull information into a HA sensor.
This is on a Raspberry Pi (Zero W with Raspian Stretch Lite) and HA All-In-One Installer.
#!/usr/bin/env python3
import argparse,subprocess
text = 'This program returns stats from an Onewheel BLE device'
parser = argparse.ArgumentParser(description = text)
parser.add_argument("address",help="mac address of device")
parser.add_argument("--battery", help="get battery level",action="store_true")
parser.add_argument("--total_miles", help="get total miles",action="store_true")
parser.add_argument("--firmware_version", help="get firmware version",action="store_true")
parser.add_argument("--hardware_revision", help="get hardware revision",action="store_true")
parser.add_argument("--riding_mode", help="get current riding mode",action="store_true")
args = parser.parse_args()
if __name__ == "__main__":
if args.battery:
handle = "0x0021"
elif args.total_miles:
handle = "0x0079"
elif args.hardware_revision:
handle = "0x0075"
elif args.firmware_version:
handle = "0x0059"
elif args.riding_mode:
handle = "0x001d"
else:
handle = "0x0021"
p = subprocess.Popen("/usr/bin/gatttool -b {0} --char-read --handle={1}".format(args.address,handle), stdout=subprocess.PIPE, shell=True)
try:
(output, err) = p.communicate(timeout=10)
p_status = p.wait()
p_out = output.decode('ascii').split()
if len(p_out) > 0:
r = '{0}{1}'.format(p_out[2],p_out[3])
print(int(r,16))
else:
print(p_out)
except subprocess.TimeoutExpired:
print('n/a')
And OW sensors from configuration.yaml:
sensor:
- platform: command_line
name: "OneWheel Battery Level"
command: "/home/homeassistant/.homeassistant/tools/onewheel_stats.py 50:65:83:A1:C2:53 --battery"
scan_interval: 60
unit_of_measurement: "%"
- platform: command_line
name: "OneWheel Total Miles"
command: "/home/homeassistant/.homeassistant/tools/onewheel_stats.py 50:65:83:A1:C2:53 --total_miles"
scan_interval: 1000
I’ve also got a smart plug that turns off when the OW hits 100%:
- action:
- alias: turn on onewheel smart plug
data:
entity_id: switch.onewheel_smart_plug
service: switch.turn_on
alias: 'Turn on OW charger when less than 100% '
condition: []
trigger:
- above: 0
below: 100
entity_id: sensor.onewheel_battery_level
platform: numeric_state
- action:
- alias: turn off onewheel smart plug
data:
entity_id: switch.onewheel_smart_plug
service: switch.turn_off
alias: Turn off OW charger when at 100%
condition:
- condition: state
entity_id: switch.onewheel_smart_plug
state: 'on'
trigger:
- entity_id: sensor.onewheel_battery_level
platform: state
to: '100'