@tunnus Kudos! I'm guessing you discovered that something like payload[config.cmd] got you where you were going with that (I'm repeating it here for future readers, since you didn't show your final result).
To your next question, first thing: I believe you said you are using local_mqtt_devices.yaml. You'll "modernize" a bit by moving your template to its own file (e.g. daikin.yaml) in config/mqtt_templates/. Within template files in that subdirectory, you can define both custom capabilities and the templates that use them. They are structured more like a package, so you can more easily share them as others here have done.
In this case, though, you probably don't need to define your own capability. While the system-defined capabilities have values for attributes and action parameters, they are not set in stone. The defined values are a reasonable subset that a lot of devices may have in common, but there would be no way for me to know the entire range of values for every device that ever was or will be, so Reactor doesn't enforce them. They are mostly hints to the UI for reasonable values it can display for the user as a starting point. You can use your own values for hvac_blower_unit.set_mode without defining your own capability; it won't be a problem as long as your implementation (template) expects those values and handles them.
You're on the right track replacing the value_sensor capability with hvac_blower_unit. Using your posted config as a guide, it may look something like below. Let's look at the attributes of the capability first:
daikin_command:
# some config here, redacted in OP's post
capabilities: [ "hvac_heating_unit", "hvac_blower_unit" ]
primary_attribute: hvac_heating_unit.setpoint
events:
"some-topic-for-status-I-assume": # topic was redacted in OP's post
# hvac_heating_unit stuff redacted for clarity/focus on hvac_blower_unit
"hvac_blower_unit.state":
json_payload: true
if_expr: '! isnull( payload?.fan )'
expr: 'payload?.fan !== "X"' # whatever expression you need here.
"hvac_blower_unit.mode":
json_payload: true
if_expr: '! isnull( payload?.fan )'
map:
A: auto
Q: quiet
1: low
2: low-medium
3: medium
4: medium-high
5: high
What I can't tell from your posts is if there's a value for payload.fan that represents fan off. That would be used to drive the state boolean attribute. You may use an expression like expr: payload?.fan !== "X" Assuming X means off, state will be false when the fan is off, and true when it's running at any speed, which is the intent of the attribute. If the fan is always running or you just don't know (i.e. the device doesn't actually report it), you can forego the if_expr and expr and just supply value: true (or perhaps value: null, meaning "I don't know"), which supplies a fixed value for that attribute that never changes.
For hvac_blower_unit.mode, you can see I've mapped the single-character values to strings. This isn't strictly necessary, but it's in keeping with the spirit of Reactor's design goals. Some of the values map to pre-defined values in the capability, and some don't, and that's just fine. It won't bother Reactor at all.
Now on the action side, we need to add:
actions:
hvac_blower_unit:
set_mode:
topic: "command/%friendly_name%"
payload:
type: json
expr: |
value = {},
value.fan =
({
"auto": "A",
"quiet": "Q",
"low": 1,
"low-medium": 2,
"medium": 3,
"medium-high": 4,
"high": 5
})[parameters.mode] ?? parameters.mode, value
This defines the set_mode action for the capability, preparing it to send a JSON payload. It first sets up an empty object in the value local variable. It then sets the fan key in the object by mapping any words given in the mode parameter to the action back to their letter equivalent for the device. If the value of the mode parameter doesn't map, it's just passed through as given (so you can still use the one-letter values directly if you don't want to use the words). Finally, the object in value is returned as the expression result (that's the , value bit at the end).
Digging in to that mapping a little more, we're creating a key-value pair object on the fly to use to look the value in parameters.mode. If it matches a key (i.e. left side of a colon), it changes it to the value (the right of the colon). If it matches nothing, the lookup results in null, which is handled by the ?? operator — when given null on its left, it returns the value of the expression on its right (i.e. if the map isn't matched, parameters.mode as given is the result). This is how you can use either the fancy strings or the one-letter values equally.
Hint: for debugging, when you run an action, MQTTController logs the exact topic and full payload being published at INFO level by default.
Finally, if you truly wanted to define your own capability, you could make your own Daikin+MQTT custom version of hvac_blower_unit by putting it in a capabilities section of your template file (this does not work in local_mqtt_devices.yaml, only in files in config/mqtt_templates/:
capabilities:
x_mqtt_daikin_moredetail: # moredetail may include device type, model number, interface type, etc.
attributes:
speed:
type: string
values:
- A
- Q
- 1
- 2
- 3
- 4
- 5
actions:
set_speed:
arguments:
speed:
type: string
values:
- A
- Q
- 1
- 2
- 3
- 4
- 5
This section can just precede the templates: section in your file. You would then adjust the capability name, attribute name, and action and parameters names accordingly in the above example to match your custom definition.
When you post snippets, please don't redact in a way that disrupts the structure. For example, you removed the topics from under events, and other data in your template. For future readers, that makes your post confusing and misleading, so other people that may find your post because they're having the same problem won't be able to follow it as easily. It would also be a courtesy to those other readers if you posted the final solution, for example the expression you finally came up with for the first problem solved.
Link to: MQTTController Documentation