tomasmcguinness / homeassistant-mixergy

Add support for Mixergy's smart water tank into Home Assistant
MIT License
37 stars 8 forks source link

trying to call mixergy_set_charge and getting data type errors #14

Closed elflewis closed 8 months ago

elflewis commented 1 year ago

Hi Tomas,

Trying to set an automation to increase the charge level . As a first step, I've created a button, and trying to get it to set the charge level to the current level +5%. The idea is to figure out how the service call works, once its ok I'll set up some logic around it to not increase again is the tank is currently heating up etc.

Have set up a button with the following code:

type: button tap_action: action: call-service service: mixergy.mixergy_set_charge data: charge: '{{ states.sensor.current_charge.state | int + 5 }}' entity: sensor.current_charge show_state: true

as the "charge:" line has a single quote around it, it returns as a string and I get a data error when executing the code. If I remove the single ticks in the visual yaml editor, the yaml changes to: charge: '[object Object]': null

Im unsure whats going wrong here, but I cant seem to make it work. Any ideas what Im doing wrong?

Elf

elflewis commented 1 year ago

sorry about the indentation BTW - its correct on my side tbut the github editor culled all the indentation!

elflewis commented 1 year ago

Ok, I changed the charge: field to be text by changing the selector: number: field to be selector: text:

I then added a test to make sure the charge: value is an int or float, and is a valid number between 0 and 100 into init.py

It now works fine,I can programmatically add 5% to the current tank value, and it ups the tank charge. Next step is to add a check in case the tank is already charging, and if so not execute.

In theory, with my CT scanner on the outgoing power in the house, I can now set the tank to automatically heat up in 5% increments as long as there is excess solar being generated - so kind of a hacky solar diverter without the extra mixergy solar kit.

My code is likely terrible, but if you want to see it, and possibly add it to your code if its good enough, how would I do this? Ive never used git before, so am unsure how to send you my changes.

NigelGreenslade commented 1 year ago

I'm fairly new to yaml. Could you please show your updated code, after you've changed the charge field to test.

Thanks

NigelGreenslade commented 1 year ago

text

elflewis commented 1 year ago

Hi Nigel, Will try explaining here, hopefully the formatting wont be too broken, and you can follow my instructions! First, in services.yaml, i changed the mixergy_set_charge selector field from number to text, like this:


mixergy_set_charge: name: Set Charge description: Sets the desired charge of your Mixergy tank. fields: charge: name: Charge description: The charge you want the tank to reach. example: 25 required: true selector: text: # number: # min: 0 # max: 100 mixergy_set_target_temperature:

Then, as this field is not text instead of a number, i added a few validation steps in init.py. Not sure if this is 100% necessary, but wanted to be sure it didnt break if i passed a non numerical charachter to the integration. I did this step (please excuse my crap code, Im not a programmer!) by changing the " async def mixergy_set_charge(call):" in the def _register_services block to this:


async def mixergy_set_charge(call):

    charge = call.data[ATTR_CHARGE]
    if type(charge) == int or type(charge) == float:
        if float(charge) < 0:
            _LOGGER.warning("The request to charge the tank did not succeed as a negative value was entered")
        elif float(charge) > 100:
            charge = "100"
            tasks = [
                tank.set_target_charge(charge)
                for tank in hass.data[DOMAIN].values()
                if isinstance(tank, Tank)
            ]
            results = await asyncio.gather(*tasks)
            # Note that we'll get a "None" value for a successful call
            if None not in results:
                _LOGGER.warning("The request to charge the tank did not succeed")
        else:
            tasks = [
                tank.set_target_charge(charge)
                for tank in hass.data[DOMAIN].values()
                if isinstance(tank, Tank)
            ]
            results = await asyncio.gather(*tasks)
            # Note that we'll get a "None" value for a successful call
            if None not in results:
                _LOGGER.warning("The request to charge the tank did not succeed")
    else:
        _LOGGER.warning("The request to charge the tank did not succeedi as a non numerical value was entered")
async def mixergy_set_target_temperature(call):

Apologiess if the formatting gets mangled, hopefully this gives you something to start off with. it works fine for me now. Im about to go away for 2 weeks, if you cant make it work I'll have another look when i return and maybe email you my code as a zip file, if that helps.

Good luck!

elflewis commented 1 year ago

Ok, the second bit of code is fine, the first has become mangled. Im puzzled as to why! Just make sure the "text:" line near the bottom is tabbed to the same position as the "number:" line that it replaces, and then comment out "number:" and the next 2 lines after it, and you should be fine. The second block looks correct from my end. Hope this helps! Elf

NigelGreenslade commented 1 year ago

appreciated! I'll have a play and let you know how I get on.

tomasmcguinness commented 1 year ago

Hi. You shouldn’t have needed to change the parameter type as you’re working with a number. I’ll have a closer look this weekend. I think you’re probably just needing to cast the result to an int in the template.

elflewis commented 1 year ago

In homeassistant it only seems to work if the value is text. My fix works, but if theres a cleaner way of doing it that would be great!

Thanks a lot

On Sat, 22 Jul 2023 at 11:32, Tomas McGuinness @.***> wrote:

Hi. You shouldn’t have needed to change the parameter type as you’re working with a number. I’ll have a closer look this weekend. I think you’re probably just needing to cast the result to an int in the template.

— Reply to this email directly, view it on GitHub https://github.com/tomasmcguinness/homeassistant-mixergy/issues/14#issuecomment-1646552867, or unsubscribe https://github.com/notifications/unsubscribe-auth/AGLFOKNZ2TUK6OVLENTDGFDXROT2VANCNFSM6AAAAAAYBCR36M . You are receiving this because you authored the thread.Message ID: @.***>

tomasmcguinness commented 1 year ago

I haven't forgotten this thread. I will try and get a sample working with a home assistant automation and share that as soon as I can!

tomasmcguinness commented 1 year ago

I have this a go by setting up an automation with this and it works as expected:

alias: Add 10%
description: Test
trigger: []
condition: []
action:
  - service: mixergy.mixergy_set_charge
    data:
      charge: "{{ states.sensor.mixergy_current_charge.state | int + 10 }}"
mode: single

Single quotes and double quotes work.

How are you setting up the button?

NigelGreenslade commented 1 year ago

Thanks. could you please give an example of how to set up the button?

tomasmcguinness commented 1 year ago

I’m not familiar with setting up buttons. Are you adding a helper?

NigelGreenslade commented 1 year ago

No worries about the button, I'll see what I can work out. I did set up the automation as per your code and pressed the 'run' button on the Automation GUI. It didn't change the mixergy charge and looking at the HA logbook, it details the following error.

Error: Error rendering data template: UndefinedError: 'None' has no attribute 'state'

Any ideas?

tomasmcguinness commented 1 year ago

None I'm afraid. That error is a little too vague. Do you know where (file name and line number) it occurred?

tomasmcguinness commented 8 months ago

Closing this due as it's stale. Please reopen if this is still an issue.