itchannel / apex-ha

Local Neptune Apex HA Integration (Aquarium Controller)
GNU General Public License v3.0
19 stars 3 forks source link

Base variables are reported as a switch #11

Open brettonw opened 1 year ago

brettonw commented 1 year ago

I have a Kessil H80 exported through one of the base variable controllers with two variables for color and intensity. The HA integration brings these variables in as on/off switches. The Apex actually presents these as a three-way witch on/off/auto, where auto runs some script or schedule. Is there any way to bring in the actual base variable value? I see the rest interface reports these as variable types.

itchannel commented 1 year ago

Unfortunately HA doesn't support 3 way switches which would be ideal in this situation. You can use a custom slider and call the "set_output" service which allows setting the variable to OFF/ON/AUTO. Also the actual state is in the sensors attributes which can be used for templates etc.

Could you provide a copy of your status.json so I can see the format and see if there's a better way I can represent the data. Unfortunately I have a fairly standard Apex controller so it will take a while to add in all the different addons etc people have so any help is appreciated.

brettonw commented 1 year ago

status.json.txt

The status seems to use AON/AOFF/ON/OFF as the set of possible values (the A indicating it is in auto mode and then either on or off, even though the underlying variable may be numeric. Maybe it's worth exposing this as two separate controls?

Can you show me an example of what you mean for the set output service? I see that service, but can you show what the setting might look like?

itchannel commented 1 year ago

image The service allows you to set the output AUTO, ON or OFF where as the normal switch only allows the state ON/OFF. It was the easiest way I could think of dealing with the 3 possible states for the output. The actual switch entity itself will just convert AUTO/ON to ON state and OFF to OFF state. I really wish HA supported 3 way buttons.

brettonw commented 1 year ago

Ah, so there's no way to set the variable to, say, a percent?

itchannel commented 1 year ago

Not with the current version of the integration. That service is just designed for setting AUTO/OFF/ON.

Now I know some outputs can accept a speed/percentage variable I will look at adding that functionality as well.

brettonw commented 1 year ago

Similar to the IOTA interface, the rest call to set a base variable is...

Request URL: http://apex.local/rest/config/oconf/base_Var2 Request Method: PUT

Payload: { "name": "K_Intensity", "icon": "Left/Right Arrows", "ctype": "Advanced", "log": false, "inuse": true, "type": "variable", "did": "base_Var2", "gid": "", "gtype": "0", "ID": "1", "prog": "Set 75\n", "extra": {} }

The prog only runs on the Apex if the switch is set to AUTO, so one way to proceed here may just be to boilerplate the set command as the result of calling the service with a value tag?

behold81 commented 1 year ago

Variables are unable to be set in APEX with out coding the Auto mode. on is 100% and off is 0. Auto looks at the code that can set a speed. If Apex had a slider then it might expose a number rather than AON. I think this is a limitation to Apex that means its not exposable in HA. Unless you can recode Auto code from the API

itchannel commented 1 year ago

image So I can modify/code variables using the rest API and could add in the ability for a service to allow you to write code to the controller.

I think for now though nice functionality would be just to be able to use "Set 70" to modify the speed of devices like pumps etc from HA. Then you could have a slider in HA which when changed just writes "Set value" to the controller like @brettonw suggested

itchannel commented 1 year ago

So there is no validation on the Apex side so if you mess up your code or json format it kills your Apex lol. Now to recover it.

itchannel commented 1 year ago

image image

Ok I have a working service now, have put in a check which prevents the service being called on variables that aren't marked as "Advanced" to prevent corruption.

brettonw commented 1 year ago

This is exactly what I hoped for. Sorry you bricked your apex. I’m pretty sure the “advanced” value can be set. Looking at other “types” in one part of the rest interface they were just a way to specify the program as a template, everything has an underlying program.

brettonw commented 1 year ago

So I think it might be simpler than this.

On the Apex, a variable (like the sicce pump or a base variable) has possible values off (0), on (100), or auto (the result of running the prog).

If you want to manage an Apex variable in home assistant you could say (for simplicity sake) the variable will no longer be managed in ApexFusion. If you accept that limitation, you can just set the "ctype" to "advanced", "setting" to "auto", expose a numeric variable to HA whose range is 0..100%, and send a "prog" value of "set XX".

When you read the result back as a sensor (which you should do), map "off" to 0, "on" to 100, and otherwise look for a "prog" value of "set XX". If the prog value is not a simple set statement, or some other configuration error occurs, it's because somebody tried to manage it in Apex Fusion. In that case you should just set it back to some default (and log the error). Most Apex variables have a "default to" field, I think.

Am I being clear?

itchannel commented 1 year ago

So for generic variables then a standard sensor rather than a switch sounds like the sensible way to go and as you said mapping the values to a percentage which shows as the sensor state. If it can't be mapped the sensor will just set itself to either a default for the state or a Not supported message and can then show the actual code it retrieved in the sensors attributes box for easy debugging.

More specialist devices like your IOT pump I think we can use the intensity parameter and map it to a fan entity which would give better control over the device like changing the percentage from the HA dashboard.

brettonw commented 1 year ago

Looking at the http://apex.local/rest/config values, I see that the sicce pump is configured exactly the same way a base variable is (with a little bit of "extra"):

{ name: "Sicce_Return", icon: "Up/Down Arrows", ctype: "Advanced", log: false, inuse: true, type: "iotaPump|Sicce|Syncra", did: "3_1", gid: "", gtype: "0", ID: "19", prog: "Set 75 ", extra: { temperature: true, gph: { min: 0, max: 0 }, modes: [ { id: 0, name: "Constant" }, { id: 1, name: "Lagoonal ripple" }, { id: 2, name: "Sharp break" }, { id: 3, name: "Reef crest" }, { id: 4, name: "Slow current" }, { id: 5, name: "Fast current" } ] } } ],

vs

{ name: "Base_Var4", icon: "Up/Down Arrows", ctype: "Advanced", log: false, inuse: true, type: "variable", did: "base_Var4", gid: "", gtype: "0", ID: "3", prog: "Set 100 ", extra: { } }

itchannel commented 1 year ago

I've pushed 1.09 currently as a pre-release for people to try. It adds in functionality for parsing variables as sensors as well as adding the set_variable service.

brettonw commented 1 year ago

This is working. I haven't fully exercised the set_variable service yet, but I have confirmed the variables report as both a sensor and a switch. I wonder if variables like this should be brought in as an input_number entity instead of a switch (or maybe there is a better value)? For now, I have to create a helper to track the value I want to send, and basically ignore the sensor value.

brettonw commented 1 year ago

Calling set_variable service works if the switch has already been set to AUTO. Do you need to set the config to AON when setting the variable?

brettonw commented 1 year ago

I configured an input_number helper with a range of 0-100, and an automation when the value changes to set the apex variable to "Set (the slider value)".

alias: Update Refugium Intensity
trigger:
  - platform: state
    entity_id:
      - input_number.refugium_intensity
action:
  - service: apex.set_output
    data:
      did: base_Var2
      setting: AUTO
  - service: apex.set_variable
    data:
      did: base_Var2
      code: Set {{ trigger.to_state.state | int }}
mode: single

And this works as expected.

You could leave this as the status quo, and I'd be happy. BUT - the HA user has to do a lot of boilerplate for each variable they want to control. If you created the boilerplate as part of loading the integration, such as by making the "sensor" an input_number with the attached automation (does HA allow an automation entity to be created from an integration like that?), it would be much easier to use.

itchannel commented 1 year ago

This is working. I haven't fully exercised the set_variable service yet, but I have confirmed the variables report as both a sensor and a switch. I wonder if variables like this should be brought in as an input_number entity instead of a switch (or maybe there is a better value)? For now, I have to create a helper to track the value I want to send, and basically ignore the sensor value.

So I still want to try mapping certain devices like a pump to a less generic sensor type like a fan. As the fan entity allows off/on and percentage control so would work perfectly for a pump and the user can then easily change the intensity without messing with scripts.

The service retrieves the current config of the device and then just edits the PROG part to prevent any potential bricking, so if AON is set it will stay the same I could add the ability to change the AUTO/AON status down the line just trying to see what works best.

itchannel commented 1 year ago

I configured an input_number helper with a range of 0-100, and an automation when the value changes to set the apex variable to "Set (the slider value)".

alias: Update Refugium Intensity
trigger:
  - platform: state
    entity_id:
      - input_number.refugium_intensity
action:
  - service: apex.set_output
    data:
      did: base_Var2
      setting: AUTO
  - service: apex.set_variable
    data:
      did: base_Var2
      code: Set {{ trigger.to_state.state | int }}
mode: single

And this works as expected.

You could leave this as the status quo, and I'd be happy. BUT - the HA user has to do a lot of boilerplate for each variable they want to control. If you created the boilerplate as part of loading the integration, such as by making the "sensor" an input_number with the attached automation (does HA allow an automation entity to be created from an integration like that?), it would be much easier to use.

Looks good. Nice simple way of doing.

I agree be nice to make this more user friendly for beginners. I need to have a better look into appropriate HA types for this. Unfortunately I'm on the road for a few weeks after today so updates will be more sporadic.