ESPHome 2026.3.0-dev
Loading...
Searching...
No Matches
light_json_schema.cpp
Go to the documentation of this file.
1#include "light_json_schema.h"
2#include "color_mode.h"
3#include "light_output.h"
5
6#ifdef USE_JSON
7
8namespace esphome::light {
9
10// See https://www.home-assistant.io/integrations/light.mqtt/#json-schema for documentation on the schema
11
12// Color mode JSON strings - packed into flash with compile-time generated offsets.
13// Indexed by ColorModeBitPolicy bit index (1-9), so index 0 maps to bit 1 ("onoff").
14PROGMEM_STRING_TABLE(ColorModeStrings, "onoff", "brightness", "white", "color_temp", "cwww", "rgb", "rgbw", "rgbct",
15 "rgbww");
16
17// Get JSON string for color mode. Returns nullptr for UNKNOWN (bit 0).
18// Returns ProgmemStr so ArduinoJson knows to handle PROGMEM strings on ESP8266.
19static ProgmemStr get_color_mode_json_str(ColorMode mode) {
20 unsigned bit = ColorModeBitPolicy::to_bit(mode);
21 if (bit == 0)
22 return nullptr;
23 // bit is 1-9 for valid modes, so bit-1 is always valid (0-8). LAST_INDEX fallback never used.
24 return ColorModeStrings::get_progmem_str(bit - 1, ColorModeStrings::LAST_INDEX);
25}
26
28 // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
29 if (state.supports_effects()) {
30 root[ESPHOME_F("effect")] = state.get_effect_name().c_str();
31 root[ESPHOME_F("effect_index")] = state.get_current_effect_index();
32 root[ESPHOME_F("effect_count")] = state.get_effect_count();
33 }
34
35 auto values = state.remote_values;
36
37 const auto color_mode = values.get_color_mode();
38 const auto *mode_str = get_color_mode_json_str(color_mode);
39 if (mode_str != nullptr) {
40 root[ESPHOME_F("color_mode")] = mode_str;
41 }
42
43 if (color_mode & ColorCapability::ON_OFF)
44 root[ESPHOME_F("state")] = (values.get_state() != 0.0f) ? "ON" : "OFF";
45 if (color_mode & ColorCapability::BRIGHTNESS)
46 root[ESPHOME_F("brightness")] = to_uint8_scale(values.get_brightness());
47
48 JsonObject color = root[ESPHOME_F("color")].to<JsonObject>();
49 if (color_mode & ColorCapability::RGB) {
50 float color_brightness = values.get_color_brightness();
51 color[ESPHOME_F("r")] = to_uint8_scale(color_brightness * values.get_red());
52 color[ESPHOME_F("g")] = to_uint8_scale(color_brightness * values.get_green());
53 color[ESPHOME_F("b")] = to_uint8_scale(color_brightness * values.get_blue());
54 }
55 if (color_mode & ColorCapability::WHITE) {
56 uint8_t white_val = to_uint8_scale(values.get_white());
57 color[ESPHOME_F("w")] = white_val;
58 root[ESPHOME_F("white_value")] = white_val; // legacy API
59 }
60 if (color_mode & ColorCapability::COLOR_TEMPERATURE) {
61 // this one isn't under the color subkey for some reason
62 root[ESPHOME_F("color_temp")] = uint32_t(values.get_color_temperature());
63 }
64 if (color_mode & ColorCapability::COLD_WARM_WHITE) {
65 color[ESPHOME_F("c")] = to_uint8_scale(values.get_cold_white());
66 color[ESPHOME_F("w")] = to_uint8_scale(values.get_warm_white());
67 }
68}
69
71 if (root[ESPHOME_F("state")].is<const char *>()) {
72 auto val = parse_on_off(root[ESPHOME_F("state")]);
73 switch (val) {
74 case PARSE_ON:
75 call.set_state(true);
76 break;
77 case PARSE_OFF:
78 call.set_state(false);
79 break;
80 case PARSE_TOGGLE:
81 call.set_state(!state.remote_values.is_on());
82 break;
83 case PARSE_NONE:
84 break;
85 }
86 }
87
88 if (root[ESPHOME_F("brightness")].is<uint8_t>()) {
89 call.set_brightness(float(root[ESPHOME_F("brightness")]) / 255.0f);
90 }
91
92 if (root[ESPHOME_F("color")].is<JsonObject>()) {
93 JsonObject color = root[ESPHOME_F("color")];
94 // HA also encodes brightness information in the r, g, b values, so extract that and set it as color brightness.
95 float max_rgb = 0.0f;
96 if (color[ESPHOME_F("r")].is<uint8_t>()) {
97 float r = float(color[ESPHOME_F("r")]) / 255.0f;
98 max_rgb = fmaxf(max_rgb, r);
99 call.set_red(r);
100 }
101 if (color[ESPHOME_F("g")].is<uint8_t>()) {
102 float g = float(color[ESPHOME_F("g")]) / 255.0f;
103 max_rgb = fmaxf(max_rgb, g);
104 call.set_green(g);
105 }
106 if (color[ESPHOME_F("b")].is<uint8_t>()) {
107 float b = float(color[ESPHOME_F("b")]) / 255.0f;
108 max_rgb = fmaxf(max_rgb, b);
109 call.set_blue(b);
110 }
111 if (color[ESPHOME_F("r")].is<uint8_t>() || color[ESPHOME_F("g")].is<uint8_t>() ||
112 color[ESPHOME_F("b")].is<uint8_t>()) {
113 call.set_color_brightness(max_rgb);
114 }
115
116 if (color[ESPHOME_F("c")].is<uint8_t>()) {
117 call.set_cold_white(float(color[ESPHOME_F("c")]) / 255.0f);
118 }
119 if (color[ESPHOME_F("w")].is<uint8_t>()) {
120 // the HA scheme is ambiguous here, the same key is used for white channel in RGBW and warm
121 // white channel in RGBWW.
122 if (color[ESPHOME_F("c")].is<uint8_t>()) {
123 call.set_warm_white(float(color[ESPHOME_F("w")]) / 255.0f);
124 } else {
125 call.set_white(float(color[ESPHOME_F("w")]) / 255.0f);
126 }
127 }
128 }
129
130 if (root[ESPHOME_F("white_value")].is<uint8_t>()) { // legacy API
131 call.set_white(float(root[ESPHOME_F("white_value")]) / 255.0f);
132 }
133
134 if (root[ESPHOME_F("color_temp")].is<uint16_t>()) {
135 call.set_color_temperature(float(root[ESPHOME_F("color_temp")]));
136 }
137}
138
141
142 if (root[ESPHOME_F("flash")].is<uint32_t>()) {
143 auto length = uint32_t(float(root[ESPHOME_F("flash")]) * 1000);
145 }
146
147 if (root[ESPHOME_F("transition")].is<uint16_t>()) {
148 auto length = uint32_t(float(root[ESPHOME_F("transition")]) * 1000);
150 }
151
152 if (root[ESPHOME_F("effect")].is<const char *>()) {
153 const char *effect = root[ESPHOME_F("effect")];
154 call.set_effect(effect, strlen(effect));
155 }
156
157 if (root[ESPHOME_F("effect_index")].is<uint32_t>()) {
158 uint32_t effect_index = root[ESPHOME_F("effect_index")];
159 call.set_effect(effect_index);
160 }
161}
162
163} // namespace esphome::light
164
165#endif
BedjetMode mode
BedJet operating mode.
This class represents a requested change in a light state.
Definition light_call.h:21
LightCall & set_color_temperature(optional< float > color_temperature)
Set the color temperature of the light in mireds for CWWW or RGBWW lights.
LightCall & set_color_brightness(optional< float > brightness)
Set the color brightness of the light from 0.0 (no color) to 1.0 (fully on)
LightCall & set_effect(optional< std::string > effect)
Set the effect of the light by its name.
LightCall & set_white(optional< float > white)
Set the white value value of the light from 0.0 to 1.0 for RGBW[W] lights.
LightCall & set_green(optional< float > green)
Set the green RGB value of the light from 0.0 to 1.0.
LightCall & set_warm_white(optional< float > warm_white)
Set the warm white value of the light from 0.0 to 1.0.
LightCall & set_blue(optional< float > blue)
Set the blue RGB value of the light from 0.0 to 1.0.
LightCall & set_flash_length(optional< uint32_t > flash_length)
Start and set the flash length of this call in milliseconds.
LightCall & set_cold_white(optional< float > cold_white)
Set the cold white value of the light from 0.0 to 1.0.
LightCall & set_red(optional< float > red)
Set the red RGB value of the light from 0.0 to 1.0.
LightCall & set_brightness(optional< float > brightness)
Set the target brightness of the light from 0.0 (fully off) to 1.0 (fully on)
LightCall & set_state(optional< bool > state)
Set the binary ON/OFF state of the light.
LightCall & set_transition_length(optional< uint32_t > transition_length)
Set the transition length of this call in milliseconds.
static void parse_color_json(LightState &state, LightCall &call, JsonObject root)
static void parse_json(LightState &state, LightCall &call, JsonObject root)
Parse the JSON state of a light to a LightCall.
static void dump_json(LightState &state, JsonObject root)
Dump the state of a light as JSON.
This class represents the communication layer between the front-end MQTT layer and the hardware outpu...
Definition light_state.h:93
bool state
Definition fan.h:2
mopeka_std_values val[4]
PROGMEM_STRING_TABLE(ColorModeHumanStrings, "Unknown", "On/Off", "Brightness", "White", "Color temperature", "Cold/warm white", "RGB", "RGBW", "RGB + color temperature", "RGB + cold/warm white")
FLAG_HAS_TRANSITION float
static float float b
ColorMode
Color modes are a combination of color capabilities that can be used at the same time.
Definition color_mode.h:49
@ ON_OFF
Light can be turned on/off.
@ BRIGHTNESS
Master brightness of the light can be controlled.
@ RGB
Color can be controlled using RGB format (includes a brightness control for the color).
@ COLOR_TEMPERATURE
Color temperature can be controlled.
@ WHITE
Brightness of white channel can be controlled separately from other channels.
@ COLD_WARM_WHITE
Brightness of cold and warm white output can be controlled.
ParseOnOffState parse_on_off(const char *str, const char *on, const char *off)
Parse a string that contains either on, off or toggle.
Definition helpers.cpp:454
@ PARSE_ON
Definition helpers.h:1436
@ PARSE_TOGGLE
Definition helpers.h:1438
@ PARSE_OFF
Definition helpers.h:1437
@ PARSE_NONE
Definition helpers.h:1435
const __FlashStringHelper * ProgmemStr
Definition progmem.h:26
static constexpr unsigned to_bit(ColorMode mode)
Definition color_mode.h:131
uint16_t length
Definition tt21100.cpp:0