Remember to charge your Bluetooth Headset (Require's Tasker on Android)

I’m rubbishing at remembering to charge my Bluetooth headsets, and up until recently Android has been a pretty poor at letting you know the battery level. In Android 8.1 this improved somewhat, but you still have to open the list of Bluetooth devices to see the level

.

Originally I thought this a job for Tasker on my phone but I then realised Home Assistant would be even better.

A post I made on Reddit gave me the hard bit (thanks /u/JustRollWithIt ) and after I received a message asking for details I thought this might be useful for some other Home Assistant fans…

So now to put the pieces together

  • Have Tasker run a script on Battery Level changes when connected to my phone
  • The last step of this task is to run some PHP on my webspace to save a JSON file with all the information
  • In Home Assistant I then add a REST sensor for each Headset polling the JSON File on my server
  • I then have an Automation which triggers when I turn my bedroom TV on (between 07:00 and 22:10 - as it turns on as far as HASS is concerned in the early hours to update I didn’t want a trigger while sleeping) - if the battery level of any Bluetooth headset is low it generates a message containing the details of all the devices which need charging and my Google Home Mini then speaks all this out.

Limitations

  • If the Bluetooth battery level changes when I have no internet connection Tasker is unable to talk to my web space. Not a massive problem as EE has such rock solid coverage round here.
  • When you charge the headset you’ll keep getting messages spoken by Hey Google until you turn the headset on again. I now take the headset off charge, turn it on, wait until it says “Connected” (all mine have voice feedback), wait a couple of seconds, and then turn off.
  • It’s a bit convoluted to setup!
  • The battery level reported by the devices is on a pretty poor scale - IME 60% is effectively 0%, you’ll soon be getting low battery warning - therefore anything below 80% is treated by me as < 50% left so time to charge - This shows the log it generated, it powered off as it hit 20%
    Untitled

Tasker XML Profile (note you’ll need to change the URL)

This triggers on a Bluetooth Battery level state change, then calls my PHP (see next step) with three parameters

  • m = The MAC Address of the Headset
  • l = The battery level
  • d = The friendly device name in Android
<TaskerData sr="" dvi="1" tv="5.1m">
<Profile sr="prof26" ve="2">
<cdate>1524766321046</cdate>
<edate>1525082086982</edate>
<id>26</id>
<mid0>45</mid0>
<nme>Bluetooth Battery</nme>
<Event sr="con0" ve="2">
<code>599</code>
<Str sr="arg0" ve="3">android.bluetooth.device.action.BATTERY_LEVEL_CHANGED</Str>
<Int sr="arg1" val="0"/>
<Int sr="arg2" val="0"/>
<Str sr="arg3" ve="3"/>
<Str sr="arg4" ve="3"/>
</Event>
</Profile>
<Task sr="task45">
<cdate>1520784385563</cdate>
<edate>1524926567515</edate>
<id>45</id>
<nme>BT Battery</nme>
<pri>100</pri>
<Action sr="act0" ve="7">
<code>664</code>
<Str sr="arg0" ve="3">adapter</Str>
<Str sr="arg1" ve="3">BluetoothAdapter</Str>
<Str sr="arg2" ve="3">getDefaultAdapter {BluetoothAdapter} ()</Str>
<Str sr="arg3" ve="3"/>
<Str sr="arg4" ve="3"/>
<Str sr="arg5" ve="3"/>
<Str sr="arg6" ve="3"/>
<Str sr="arg7" ve="3"/>
<Str sr="arg8" ve="3"/>
<Str sr="arg9" ve="3"/>
</Action>
<Action sr="act1" ve="7">
<code>664</code>
<Str sr="arg0" ve="3">device</Str>
<Str sr="arg1" ve="3">adapter</Str>
<Str sr="arg2" ve="3">getRemoteDevice {BluetoothDevice} (String)</Str>
<Str sr="arg3" ve="3">%android_bluetooth_device_extra_device</Str>
<Str sr="arg4" ve="3"/>
<Str sr="arg5" ve="3"/>
<Str sr="arg6" ve="3"/>
<Str sr="arg7" ve="3"/>
<Str sr="arg8" ve="3"/>
<Str sr="arg9" ve="3"/>
</Action>
<Action sr="act2" ve="7">
<code>664</code>
<Str sr="arg0" ve="3">%devicename</Str>
<Str sr="arg1" ve="3">device</Str>
<Str sr="arg2" ve="3">getName {String} ()</Str>
<Str sr="arg3" ve="3"/>
<Str sr="arg4" ve="3"/>
<Str sr="arg5" ve="3"/>
<Str sr="arg6" ve="3"/>
<Str sr="arg7" ve="3"/>
<Str sr="arg8" ve="3"/>
<Str sr="arg9" ve="3"/>
</Action>
<Action sr="act3" ve="7">
<code>523</code>
<Str sr="arg0" ve="3">Dev %devicename, Level %android_bluetooth_device_extra_battery_level</Str>
<Str sr="arg1" ve="3">%android_bluetooth_device_extra_battery_level</Str>
<Img sr="arg2" ve="2"/>
<Int sr="arg3" val="0"/>
<Int sr="arg4" val="0"/>
<Int sr="arg5" val="3"/>
</Action>
<Action sr="act4" ve="7">
<code>116</code>
<Str sr="arg0" ve="3">https://www.example.com</Str>
<Str sr="arg1" ve="3">/battery.php</Str>
<Str sr="arg2" ve="3">m=%android_bluetooth_device_extra_device
l=%android_bluetooth_device_extra_battery_level
d=%devicename</Str>
<Str sr="arg3" ve="3"/>
<Str sr="arg4" ve="3"/>
<Int sr="arg5" val="10"/>
<Str sr="arg6" ve="3"/>
<Str sr="arg7" ve="3"/>
<Int sr="arg8" val="0"/>
</Action>
</Task>
</TaskerData>

The PHP On my Web Server
This processes the request made by tasker and simply writes those parameters as a JSON Object to a file on the server - this file is named the MD5 hash of the devices MAC Address. For security you will want to validate the MAC is a known good one.

Based on the tasker example above this would be accessible at

https://www.example.com/battery.php
<?php

$param = array();
$param['device'] = isset($_REQUEST['d']) ? $_REQUEST['d'] : false;
$param['status'] = isset($_REQUEST['l']) ? $_REQUEST['l'] : false;
$param['mac'] = isset($_REQUEST['m']) ? $_REQUEST['m'] : false;
$param['update'] = date('Y-m-d H:i:s');

if($param['status'] >= 0)
{
    $json = json_encode($param);
    file_put_contents("states/" . md5($param['mac']).".txt",$json);
    echo $json;
}

?>

This would right to a file which would be accessible at a URL along the lines of

https://www.example.com/states/aaaaaaaaaaaaaaaaaaaaaaaaaaaa.txt

This file would contain JSON similar to the following

{"device":"WM2015AV02","status":"90","mac":"FF:FF:FF:AA:BB:CC","update":"2018-05-01 06:17:33"}

Home Assistant States Sensors

Now to create the REST sensor in Home Assistant

sensor bt_bathroom_speaker:
  - platform: rest
    name: BT - Bathroom Speaker
    json_attributes:
      - device
      - update
      - mac
    resource: https://www.example.com/states/aaaaaaaaaaaaaaaaaaaaaaaaaaaa.txt
    value_template: '{{ value_json.status }}'
    unit_of_measurement: "%"

You’d repeat for each of the Headsets you have.

Home Assistant Automation

And now for the Automation

Then in Home Assistant I have the following Automation

- id: kev_home_bt
  alias: Bluetooth Low Battery Alert
  trigger:
    platform: state
    entity_id: media_player.kevs_bedroom_lg_tv
    from: 'off'
    to: 'playing'
  condition:
    condition: and
    conditions: 
      - condition: time
        after: '07:00:00'
        before: '22:10:00'
      - condition: or
        conditions:
          - condition: numeric_state
            entity_id: sensor.bt__trekz_titanium_headset
            below: '80'
          - condition: numeric_state
            entity_id: sensor.bt__bathroom_speaker
            below: '80'
          - condition: numeric_state
            entity_id: sensor.bt__slimbuds_blue
            below: '80'
          - condition: numeric_state
            entity_id: sensor.bt__slimbuds_red
            below: '80'
  action:
    - service: tts.google_say
      data_template:
        entity_id: media_player.kevs_home_mini
        message: >
          Hey Kev, the batteries on your blue tooth devices are getting low
          {% if states.sensor.bt__trekz_titanium_headset.state | float < 80 %}
          Trekz Titanium is at {{ states.sensor.bt__trekz_titanium_headset.state }}
          {% endif %}
          {% if states.sensor.bt__bathroom_speaker.state | float < 80 %}
          Bathroom Speaker is at {{ states.sensor.bt__bathroom_speaker.state }}
          {% endif %}
          {% if states.sensor.bt__slimbuds_blue.state | float < 80 %}
          Slim Buds Blue is at {{ states.sensor.bt__slimbuds_blue.state }}
          {% endif %}
          {% if states.sensor.bt__slimbuds_red.state | float < 80 %}
          Slimbuds Red is at {{ states.sensor.bt__slimbuds_red.state }}
          {% endif %}

At a glance view in the Hass dashboard
Screenshot_2

And the history of a device throughout the day…
Screenshot_3

Enjoy!

4 Likes

Thanks for sharing. But did only work with heatsets? Or works too with any bluetooth device?

Not sure, I’d imagine it would work with any Bluetooth devices that report there battery level when connected in Android (Oreo). I only have headsets and speakers.