Request for help: Charge a Dyson Vacuum without killing the battery

Hello all,

I have a Dyson vacuum where the battery died within a few years, because it was always plugged into its wall charger.
I now have an idea, but I need help from people with experience to make it happen:

My idea:

  • Use an Athom smart plug to power on the Dyson charger
  • Keep it powered off by default
  • Every hour or so, power it on, wait 5 minutes, then check the power draw
    • If the power draw is over xxx watts, the vacuum is charging and the plug should stay on
    • Else, turn off the power
  • If someone uses the vacuum, they can simply press the button on the Smart Plug to charge it now and the ā€œhourlyā€ cycle should pick it up (I assume powering on a plug that is already powered on has no ill side-effects

What I Have:

  • HomeAssistant running directly on a NUC i5something, running:
    • Home Assistant 2022.12.8
    • Supervisor 2022.12.1
    • Operating System 9.4
    • Frontend 20221213.1 - latest
  • Dyson V8 Animal+
  • Athom Smart Plug, running:
    • smart-plug-v2
    • by athom
    • Firmware: 2022.11.2 (Nov 23 2022, 12:18:11)
    • Hardware: 1.1
  • Decent knowledge of Yaml and Bash, AWK and other basic scripting languages
  • A bit of HA experience: Already set up integrations with Ikea Tradfri, Tuya, eWelink plugs, Solar and Split-unit Mitsubishi Heavy A/C

What I don’t have:

  • In-depth HA knowledge of how to script monitoring or other events in HA
    • I barely managed to set up my own morning ā€œsunriseā€ light, after figuring out how to set up weekdays.

I will try to do some homewok tomorrow, to see if I can tell if the vacuum is charging after use.

Any assistance is appreciated.
I don’t mind doing some homeork, but my brain is not firing on all cylinders and I have a feeling I might be biting off more than I can chew, with only 2 weeks play-time on HA.

1 Like

I assume the smart plug has power monitoring capability?

if so then I manage my Ryobi 40V battery charging in a similar manner.

That said…what have you tried? I usually suggest that it’s better to at least try to figure something out before asking for help. Then if it doesn’t work you can tell us what you tried and what didn’t work as expected so we can give better specific help.

But since it’s new years day I’ll give you a new years gift. :partying_face: :wink:

I first create an input_datetime to hold when the charger was last turned off:

input_datetime:
  charger_1_off_time:
    name: Charger 1 Turned Off At
    has_date: true
    has_time: true

then I create an automation to check the charging status based on power draw of the outlet and if it’s less than 3 watts I turn off the outlet, announce the charge is done and set the time that the charger turned off:

automation:
  - alias: Garage Power Charger 1 Check Charging
    trigger:
      - platform: state
        entity_id: switch.garage_power_strip_switch_1
        to: 'on'
        for:
          minutes: 5
      - platform: numeric_state
        entity_id: sensor.garage_power_strip_power_1
        below: 3.0
        for:
          minutes: 5
    condition:
      - condition: template
        value_template: '{{ states("sensor.garage_power_strip_power_1") | float < 3.0 }}'
      - condition: state
        entity_id: switch.garage_power_strip_switch_1
        state: 'on'
    action:
      - service: switch.turn_off
        entity_id: switch.garage_power_strip_switch_1
      - condition: time
        before: '20:00:00'
      - condition: time
        after: '10:00:00'
      - service: notify.alexa_media
        data:
          target: 
            - media_player.garage_dot
            - media_player.kitchen_dot
          data:
            type: tts 
          message: "Charger number 1 has either completed charging or doesn't have a battery connected and it has been turned off."
      - service: input_datetime.set_datetime
        data:
          entity_id: input_datetime.charger_1_off_time
          timestamp: "{{ now().timestamp() }}"

then i set up another automation to recharge the battery every 7 days to keep it topped off:

  - alias: Garage Power Chargers Refresh Battery Charge
    id: garage_power_chargers_refresh_battery_charge
    mode: parallel
    trigger:
      - platform: template
        value_template: "{{ as_timestamp(now()) - state_attr('input_datetime.charger_1_off_time', 'timestamp') | int > 86400 * 7 }}"
    action:
      - service: switch.turn_on
        entity_id: switch.garage_power_strip_switch_1

I’ve simplified these since I have 4 or 5 chargers I manage with the same automations.

Obviously you will need to modify the above to meet your requirements but it should get you started.

2 Likes

Oh, wow, thanks!
TBH, I haven’t really tried anything yet, as I’m still getting used to HA’s terminology.
I have found out that the Dyson charger seems to take 0W when idle and around 20W when charging, so that should work.

I have tried setting it up with a little help from the visual editor, in order to get the correct entity ID’s:

In configuration.yaml:

# Input for Dyson charging
input_datetime:
  dyson_charger_off_time:
    name: Dyson Charger Turned Off At
    has_date: true
    has_time: true

In Automations.yaml

- id: '1672687184040'
  alias: Dyson smart charging
  description: ''
  trigger:
  - platform: state
    entity_id:
    - switch.athom_smart_plug_v2_4
    to: 'on'
    for:
      hours: 0
      minutes: 5
      seconds: 0
  condition:
  - condition: template
    value_template: '{{ states("sensor.athom_smart_plug_v2_power_4") | float < 3.0
      }}'
  - condition: state
    entity_id: sensor.athom_smart_plug_v2_power_4
    state: 'on'
  action:
  - service: switch.turn_off
    data: {}
    target:
      device_id: 1c74bf182aec2eff1b2e03fcf6c3fdc8
  - condition: time
    before: '21:00:00'
    after: '11:00:00'
  - service: notify.mobile_app_op8kit
    data:
      message: Turned off Dyson charger
  - service: input_datetime.set_datetime
    data:
      timestamp: '{{ now().timestamp() }}'
  mode: single
- id: '1672688122581'
  alias: Dyson weekly charge
  description: ''
  trigger:
  - platform: template
    value_template: '"{{ as_timestamp(now()) - state_attr(''input_datetime.dyson_charger_off_time'',
      ''timestamp'') | int > 86400 * 7 }}"'
  condition: []
  action:
  - service: switch.turn_on
    data: {}
    target:
      device_id: 1c74bf182aec2eff1b2e03fcf6c3fdc8
  mode: parallel
  max: 10

I must have some something wrong, because the plug is still on, even though it has 0W power draw.
Oddly enough, my phone did get a notification that the charger is turned off (which is not true)

The Trace tells me:

Triggered by the state of switch.athom_smart_plug_v2_4 at January 2, 2023 at 8:34:29 PM
template condition
Confirm Smart-Plug-Dyson-Power is on
Stopped because a condition failed at January 2, 2023 at 8:34:29 PM (runtime: 0.00 seconds)

Can you help me figure out what I did wrong?

This is a numeric sensor for power use, so it isn’t on? You check it twice, once as a number and once for ā€œonā€. It can’t be both. But always when you have this: Check the trace, it also tells you the expected value vs the actual one. Only not for template conditions. But you could easily convert that one to a numerical state check. Then the trace is way more descriptive.

what Edwin said is correct.

change this:

  - condition: state
    entity_id: sensor.athom_smart_plug_v2_power_4
    state: 'on'

to:

  - condition: state
    entity_id: switch.athom_smart_plug_v2_4
    state: 'on'

in addition to the above you left out important data in the following service call:

  - service: input_datetime.set_datetime
    data:
      timestamp: '{{ now().timestamp() }}'

you didn’t tell it the entity_id of the input_datetime to set.

it should be:

  - service: input_datetime.set_datetime
    entity_id: input_datetime.dyson_charger_off_time
    data:
      timestamp: '{{ now().timestamp() }}'

you also left out the charging power check trigger.

if you don’t have that then when you turn on the switch to charge the battery if after 5 minutes the power is still higher than 3.0 then there is no other trigger to turn it off once it does actually get below 3.0.

you need both.

Thanksk for the clarifications!
I tried setting it up first using the GUI and then modifying the YAML, once the basics were in place.
(to make sure it complies with the formatting it expects)

I believe I have added everything mentioned, this is the relevant section of automations.yaml.
I think I have everything in there, now…

When running the automation, it seems to throw 2 errors:
Logger: homeassistant.components.homeassistant.triggers.numeric_state
Source: components/homeassistant/triggers/numeric_state.py:182
Integration: Home Assistant Core Integration (documentation, issues)
First occurred: 11:20:20 PM (2 occurrences)
Last logged: 11:20:20 PM

  • Error in ā€˜Dyson smart charging’ trigger: In ā€˜numeric_state’ condition: entity switch.athom_smart_plug_v2_4 state ā€˜off’ cannot be processed as a number
  • Error in ā€˜websocket_api’ trigger: In ā€˜numeric_state’ condition: entity switch.athom_smart_plug_v2_4 state ā€˜off’ cannot be processed as a number

My guess is:

yaml.scanner.ScannerError: mapping values are not allowed here
  in "/config/automations.yaml", line 392, column 18

homeassistant.exceptions.HomeAssistantError: mapping values are not allowed here
  in "/config/automations.yaml", line 392, column 18

For reference, line 392 is the middle one of these 3:

  - platform: numeric_state
    entity_id: switch.athom_smart_plug_v2_4
    below: 3.0

Oddly enough, the autoamtion seems to perform exactly as planned:
I powered it on 31:20
It completed charging 23:20 and powered off soon after that.

Turned off triggered by automation Dyson smart charging triggered

23:20:20 - 10 minutes ago
Turned off triggered by automation Dyson smart charging triggered

Turned on
23:09:54 - 20 minutes ago

- id: '1672687184040'
  alias: Dyson smart charging
  description: 'Try not to kill the battery of the Dyson vacuum'
  trigger:
  - platform: state
    entity_id: switch.athom_smart_plug_v2_4
    to: 'on'
    for:
      minutes: 5
  - platform: numeric_state
    entity_id: switch.athom_smart_plug_v2_4
    below: 3.0
    for:
      minutes: 5
  condition:
  - condition: template
    value_template: '{{ states("sensor.athom_smart_plug_v2_power_4") | float < 3.0
      }}'
  - condition: state
    entity_id: switch.athom_smart_plug_v2_power_4
    state: 'on'
  action:
  - service: switch.turn_off
    data: {}
    target:
      device_id: 1c74bf182aec2eff1b2e03fcf6c3fdc8
  - condition: time
    before: '21:00:00'
    after: '11:00:00'
  - service: notify.mobile_app_op8kit
    data:
      message: Turned off Dyson charger
  - service: input_datetime.set_datetime
    entity_id: input_datetime.dyson_charger_off_time
    data:
      timestamp: '{{ now().timestamp() }}'
  mode: single
- id: '1672688122581'
  alias: Dyson weekly charge
  description: ''
  trigger:
  - platform: template
    value_template: '"{{ as_timestamp(now()) - state_attr(''input_datetime.dyson_charger_off_time'',
      ''timestamp'') | int > 86400 * 7 }}"'
  condition: []
  action:
  - service: switch.turn_on
    data: {}
    target:
      device_id: 1c74bf182aec2eff1b2e03fcf6c3fdc8
  mode: parallel
  max: 10

now you changed the numeric state trigger to the wrong entity_id. The switch doesn’t have a numeric state.

should be:

trigger:
  - platform: state
    entity_id: switch.athom_smart_plug_v2_4
    to: 'on'
    for:
      minutes: 5
  - platform: numeric_state
    entity_id: sensor.athom_smart_plug_v2_power_4
    below: 3.0
    for:
      minutes: 5

and you used the wrong entity_id for the condition of the switch (I think):

shouldn’t it be this?:

condition:
  - condition: template
    value_template: '{{ states("sensor.athom_smart_plug_v2_power_4") | float < 3.0
      }}'
  - condition: state
    entity_id: switch.athom_smart_plug_v2_4
    state: 'on'

I personally would use the entity_id of the switch instead of the device_id. But I assume it will work either way.

the benefit of using the entity_id is that if you ever change the plug (because it dies or whatever) then you can just rename the new entity to the same as the old entity and all of your stuff still works.

you have no control over the device_id so if you use that you will need to go thru every piece of code you have and replace the old device_id with the new device_id to get things running again. PITA.

Also you need to move the setting of the input_datetime to before the time condition in the action.

If not then if the actions run between 9pm and 11am then the datetime never gets set since it’s after the condition check.

so all of that said the action for the first one should be:

action:
  - service: switch.turn_off
    data: {}
    target:
      entity_id: switch.athom_smart_plug_v2_4
  - service: input_datetime.set_datetime
    entity_id: input_datetime.dyson_charger_off_time
    data:
      timestamp: '{{ now().timestamp() }}'
  - condition: time
    before: '21:00:00'
    after: '11:00:00'
  - service: notify.mobile_app_op8kit
    data:
      message: Turned off Dyson charger    

and for the second it should be:

action:
  - service: switch.turn_on
    data: {}
    target:
      entity_id: switch.athom_smart_plug_v2_4

other than all of that it looks OK.

:wink:

1 Like

Wow, you’re quick!
I didn’t even manage to finish my edit (it seems to work…)

Oooohhhhh, now I get it…
I guess switch is a property of athom_smart_plug_v2_4, but the power itself is sensor.athom_smart_plug_v2_power_4.
This is not at all confusing :wink:
I think I found another ā€œcrossed referenceā€, maybe check my format :sweat_smile:

Names make a lot more sense to me than numbers.
I was not aware what was supposed to be what, so I simply went with whatever the GUI tool picked for me :innocent:

Also, I have no idea how HA decodes the YAML into any form of code flow, so I tried copy-pasting as well as I could…

- id: '1672687184040'
  alias: Dyson smart charging
  description: 'Try not to kill the battery of the Dyson vacuum'
  trigger:
  - platform: state
    entity_id: switch.athom_smart_plug_v2_4
    to: 'on'
    for:
      minutes: 5
  - platform: numeric_state
    entity_id: sensor.athom_smart_plug_v2_power_4
    below: 3.0
    for:
      minutes: 5
  condition:
  - condition: template
    value_template: '{{ states("sensor.athom_smart_plug_v2_power_4") | float < 3.0
      }}'
  - condition: state
    entity_id: switch.athom_smart_plug_v2_4
    state: 'on'
  action:
  - service: switch.turn_off
    data: {}
    target:
      entity_id: switch.athom_smart_plug_v2_4
  - service: input_datetime.set_datetime
    entity_id: input_datetime.dyson_charger_off_time
    data:
      timestamp: '{{ now().timestamp() }}'
  - condition: time
    before: '21:00:00'
    after: '11:00:00'
  - service: notify.mobile_app_op8kit
    data:
      message: Turned off Dyson charger
  mode: single
- id: '1672688122581'
  alias: Dyson weekly charge
  description: ''
  trigger:
  - platform: template
    value_template: '"{{ as_timestamp(now()) - state_attr(''input_datetime.dyson_charger_off_time'',
      ''timestamp'') | int > 86400 * 7 }}"'
  condition: []
  action:
  - service: switch.turn_on
    data: {}
    target:
      entity_id: switch.athom_smart_plug_v2_4
  mode: parallel
  max: 10

Thank you for sticking with me through this! :muscle:

I will only be able to test it with a proper load, so I guess It’s back to vacuuming :laughing:

2 Likes

Hey I think you got!

:partying_face:

(at least I’m pretty sure…)

:laughing:

1 Like

It worked like an absolute champ!
No errors in the logs and it turned off 3 minuutes after the last blip of power draw.

1 Like

You can use a door sensor to detect when the vacuum was removed from the base (you probably can install the sensor only in the base, as it have some parts moving when you connect the vacuum).
Once you have finished charging (detected by power consumption) you don’t have to try powering again until that door/window sensor detects a change.
With this, it might happen that you have a false trigger when the Dyson is removed from the charging station, but in that case it would be fine if you try to charge for a few seconds until you detect (based on power consumption) that the device is not charging… the same logic for stop charging will work here.
The advantage of this approach is that you don’t try to charge a little bit every hour as it is in your proposed approach, which will help a bit more with the battery life.

1 Like

Just curious since I’m definitely stealing repurposing this code , but for the second automation, does it turn the plug on weekly or hourly? And for how long? Also, does it realize when the Dyson actually needs to charge and turns the plug on automatically? I also have a Dyson and I’ve noticed that the battery is not lasting as long as it was, so I love this idea!

1 Like

86400 seconds is one day. Times 7 is one week.

So it turns it on weekly if it hasn’t been charged for that long.

How long it charges depends on the charger and how you have the off automation set up.

It should charge until that automation turns it off

1 Like

For what it’s worth, I have added a simple Tuya door sensor that automatically turns on the charger and it works like a charm!

1 Like