Sharing this trick in case it would be helpful to someone who also was using Tasmota’s DevGroups.
I have 4 monochromatic lights that were running Tasmota and were linked to behave as one light (as far as Google Home, et al, were concerned) using Tasmota’s DevGroup feature.
In ESPHome, lights don’t fire triggers other than on/off, but I needed dimming to track, too.
AFAICT there’s no simple equivalent for DevGroups in ESPH, and since lights don’t trigger on the needed events, I automated using the technique below…
The logger feature does have an on_message trigger. And the dimming events were emitting log messages. Aha - Found my needed trigger!
So, with an if block to filter on WiFi being connected and ensuring only to act on messages from the light, I parse out the needed data and then send the equivalent command to the other modules in the group using http_request.post to their Web API.
Works like a charm. The config code looks a mess, but it does the trick.
I will be happy to supply details if anyone needs them.
Here’s the relevant config section.
The 4 lights in my case are lighting panels named, creatively, panel-1…panel-4.
I use a node_name substitution which you’ll see is included in the lambda. I do that because I use a shell-script to build the 4 images with one command, and node_name differentiates them.
My HomeAssistant scripts/scenes/whatever send commands only to panel-1, and that node then brings the other 3 along.
The semi-tricky part of the code is the lambda that acts on the ‘Brightness’ log message. My C++ is rustier than anything, having not been used for at least 2 decades, so my code in that lambda may evoke laughter. I’d love to see it made more efficient and readable (and be a more accurate parser), if anyone cares to do so.
And I just noticed as I posted this that I should have cascaded the ‘if’ logic, so unnecessary tests are avoided. But (because YAML) I’m terrified to even try, lest I destroy the whole thing.
This would all have been so much easier if ‘light’ had more triggers (e.g., on_change, in which I could just replicate all relevant attributes to the other lights), and if there was a simple way to determine the light’s current brightness and other current attributes. (two feature requests I am considering submitting, whose absence led me to this solution).
(Oh, and the Web REST API isn’t linked-to by anything I could find in the docs, but found it only from the webpage of the device itself. That’d be another suggested improvement to the docs.)
# for panel-1 only, this will control the other 3 to match its state changes
# Look for three specific log messages from the 'light', and send commands to the other panels
# Brightness messages look like this "[D][light:278]: Brightness: 24%"
http_request:
globals:
- id: my_panel_brightness
type: int
restore_value: no
initial_value: '0'
logger:
logs:
light: DEBUG
on_message:
level: DEBUG
then:
- if:
condition:
- lambda: |-
return !strcmp("${node_name}", "panel-1");
- wifi.connected:
then:
- if:
condition:
- lambda: |-
return !strcmp(tag, "light") && strstr(message, "State: ON");
then:
- http_request.post: !lambda |-
return ((std::string) "http://panel-2/light/panel-2/turn_on").c_str();
- http_request.post: !lambda |-
return ((std::string) "http://panel-3/light/panel-3/turn_on").c_str();
- http_request.post: !lambda |-
return ((std::string) "http://panel-4/light/panel-4/turn_on").c_str();
- if:
condition:
- lambda: |-
return !strcmp(tag, "light") && strstr(message, "State: OFF");
then:
- http_request.post: !lambda |-
return ((std::string) "http://panel-2/light/panel-2/turn_off").c_str();
- http_request.post: !lambda |-
return ((std::string) "http://panel-3/light/panel-3/turn_off").c_str();
- http_request.post: !lambda |-
return ((std::string) "http://panel-4/light/panel-4/turn_off").c_str();
- if:
condition:
- lambda: |-
return !strcmp(tag, "light") && strstr(message, "Brightness");
then:
- lambda: |-
sscanf( &message[37], "%u", &id(my_panel_brightness) ); id(my_panel_brightness) = id(my_panel_brightness)*255/100;
- http_request.post: !lambda |-
return ((std::string) "http://panel-2/light/panel-2/turn_on?brightness=" + to_string(id(my_panel_brightness)) ).c_str();
- http_request.post: !lambda |-
return ((std::string) "http://panel-3/light/panel-3/turn_on?brightness=" + to_string(id(my_panel_brightness)) ).c_str();
- http_request.post: !lambda |-
return ((std::string) "http://panel-4/light/panel-4/turn_on?brightness=" + to_string(id(my_panel_brightness)) ).c_str();
Hi, thanks for the code! Just started with esphome and devgrouptie/share is the one feature I’m missing with tasmota.
Have you also tried this with rgb bulbs/strips to sync the colors? Do you have example for that?
Because I was clumsy in my understanding of the api at the C++ level, and could not find an after-the-fact hook.
That ESPHome trigger fires before the brightness gets changed, so the script ended up setting the other lights to this one’s previous value, not the new one.
By waiting for the log entry to arrive, I could harvest the new states of this light as the values to set the others with.
If the on_turn_on/off triggers arrive before the light has assumed the commanded state, the problem would remain that the light’s state hasn’t yet changed, so you don’t yet know the new brightness.
But hopefully they trigger after the change (which would have saved me a lot of work parsing the log).
I’m not using this code anymore, so won’t be testing it using on_turn_on/off triggers, but I suggest anyone planning to do this try them instead of the log-driven approach.