Add moodlight command

This commit is contained in:
fvanroie 2021-02-05 02:56:22 +01:00
parent beddba6daf
commit d73d6b19d5
6 changed files with 107 additions and 17 deletions

View File

@ -333,7 +333,8 @@ static void my_btnmatrix_map_create(lv_obj_t * obj, const char * payload)
DeserializationError jsonError = deserializeJson(map_doc, payload); DeserializationError jsonError = deserializeJson(map_doc, payload);
if(jsonError) { // Couldn't parse incoming JSON payload if(jsonError) { // Couldn't parse incoming JSON payload
return Log.warning(TAG_ATTR, F("JSON: Failed to parse incoming button map with error: %s"), jsonError.c_str()); dispatch_json_error(TAG_ATTR, jsonError);
return;
} }
JsonArray arr = map_doc.as<JsonArray>(); // Parse payload JsonArray arr = map_doc.as<JsonArray>(); // Parse payload
@ -404,7 +405,8 @@ static void line_set_points(lv_obj_t * obj, const char * payload)
DeserializationError jsonError = deserializeJson(doc, payload); DeserializationError jsonError = deserializeJson(doc, payload);
if(jsonError) { // Couldn't parse incoming JSON payload if(jsonError) { // Couldn't parse incoming JSON payload
return Log.warning(TAG_ATTR, F("JSON: Failed to parse incoming line points with error: %s"), jsonError.c_str()); dispatch_json_error(TAG_ATTR, jsonError);
return;
} }
JsonArray arr = doc.as<JsonArray>(); // Parse payload JsonArray arr = doc.as<JsonArray>(); // Parse payload
@ -441,7 +443,7 @@ static inline lv_color_t haspLogColor(lv_color_t color)
} }
// OK // OK
static bool haspPayloadToColor(const char * payload, lv_color_t & color) bool haspPayloadToColor(const char * payload, lv_color_t & color)
{ {
/* HEX format #rrggbb or #rrggbbaa */ /* HEX format #rrggbb or #rrggbbaa */
char pattern[4]; char pattern[4];

View File

@ -27,6 +27,8 @@ void line_clear_points(lv_obj_t * obj);
void hasp_process_obj_attribute(lv_obj_t * obj, const char * attr_p, const char * payload, bool update); void hasp_process_obj_attribute(lv_obj_t * obj, const char * attr_p, const char * payload, bool update);
bool hasp_process_obj_attribute_val(lv_obj_t * obj, const char * attr, const char * payload, bool update); bool hasp_process_obj_attribute_val(lv_obj_t * obj, const char * attr, const char * payload, bool update);
bool haspPayloadToColor(const char * payload, lv_color_t & color);
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */
#endif #endif

View File

@ -8,6 +8,7 @@
#include "hasp_object.h" #include "hasp_object.h"
#include "hasp.h" #include "hasp.h"
#include "hasp_utilities.h" #include "hasp_utilities.h"
#include "hasp_attribute.h"
#if HASP_USE_DEBUG > 0 #if HASP_USE_DEBUG > 0
#include "StringStream.h" #include "StringStream.h"
@ -35,7 +36,14 @@ extern unsigned long debugLastMillis; // UpdateStatus timer
extern uint8_t hasp_sleep_state; extern uint8_t hasp_sleep_state;
uint8_t nCommands = 0; uint8_t nCommands = 0;
haspCommand_t commands[16]; haspCommand_t commands[17];
struct moodlight_t
{
byte power;
byte r, g, b;
};
moodlight_t moodlight;
static void dispatch_config(const char * topic, const char * payload); static void dispatch_config(const char * topic, const char * payload);
// void dispatch_group_value(uint8_t groupid, int16_t state, lv_obj_t * obj); // void dispatch_group_value(uint8_t groupid, int16_t state, lv_obj_t * obj);
@ -77,6 +85,11 @@ bool dispatch_factory_reset()
return formated && erased; return formated && erased;
} }
void dispatch_json_error(uint8_t tag, DeserializationError & jsonError)
{
Log.error(tag, F("JSON parsing failed: %s"), jsonError.c_str());
}
// p[x].b[y].attr=value // p[x].b[y].attr=value
inline bool dispatch_process_button_attribute(const char * topic_p, const char * payload) inline bool dispatch_process_button_attribute(const char * topic_p, const char * payload)
{ {
@ -330,7 +343,7 @@ static void dispatch_config(const char * topic, const char * payload)
} else { } else {
DeserializationError jsonError = deserializeJson(doc, payload); DeserializationError jsonError = deserializeJson(doc, payload);
if(jsonError) { // Couldn't parse incoming JSON command if(jsonError) { // Couldn't parse incoming JSON command
Log.warning(TAG_MSGR, F("JSON: Failed to parse incoming JSON command with error: %s"), jsonError.c_str()); dispatch_json_error(TAG_MSGR, jsonError);
return; return;
} }
settings = doc.as<JsonObject>(); settings = doc.as<JsonObject>();
@ -568,7 +581,7 @@ void dispatch_parse_json(const char *, const char * payload)
json.shrinkToFit(); json.shrinkToFit();
if(jsonError) { // Couldn't parse incoming JSON command if(jsonError) { // Couldn't parse incoming JSON command
Log.warning(TAG_MSGR, F("Failed to parse incoming JSON command with error: %s"), jsonError.c_str()); dispatch_json_error(TAG_MSGR, jsonError);
} else if(json.is<JsonArray>()) { // handle json as an array of commands } else if(json.is<JsonArray>()) { // handle json as an array of commands
JsonArray arr = json.as<JsonArray>(); JsonArray arr = json.as<JsonArray>();
@ -718,6 +731,55 @@ void dispatch_dim(const char *, const char * level)
dispatch_state_msg(F("dim"), payload); dispatch_state_msg(F("dim"), payload);
} }
void dispatch_moodlight(const char * topic, const char * payload)
{
// Set the current state
if(strlen(payload) != 0) {
size_t maxsize = (128u * ((strlen(payload) / 128) + 1)) + 512;
DynamicJsonDocument json(maxsize);
// Note: Deserialization needs to be (const char *) so the objects WILL be copied
// this uses more memory but otherwise the mqtt receive buffer can get overwritten by the send buffer !!
DeserializationError jsonError = deserializeJson(json, payload);
json.shrinkToFit();
if(jsonError) { // Couldn't parse incoming JSON command
dispatch_json_error(TAG_MSGR, jsonError);
} else {
if(!json[F("power")].isNull()) moodlight.power = hasp_util_is_true(json[F("power")].as<String>().c_str());
if(!json[F("r")].isNull()) moodlight.r = json[F("r")].as<uint8_t>();
if(!json[F("g")].isNull()) moodlight.r = json[F("g")].as<uint8_t>();
if(!json[F("b")].isNull()) moodlight.r = json[F("b")].as<uint8_t>();
if(!json[F("color")].isNull()) {
lv_color16_t color;
if(haspPayloadToColor(json[F("color")].as<String>().c_str(), color)) {
lv_color32_t c32;
c32.full = lv_color_to32(color);
moodlight.r = c32.ch.red;
moodlight.g = c32.ch.green;
moodlight.b = c32.ch.blue;
}
}
if(moodlight.power)
gpio_set_moodlight(moodlight.r, moodlight.g, moodlight.b);
else
gpio_set_moodlight(0, 0, 0);
}
}
// Return the current state
char buffer[128];
snprintf_P(buffer, sizeof(buffer),
PSTR("{\"power\":\"%u\",\"color\":\"#%02x%02x%02x\",\"r\":%u,\"g\":%u,\"b\":%u}"), moodlight.power,
moodlight.r, moodlight.g, moodlight.b, moodlight.r, moodlight.g, moodlight.b);
dispatch_state_msg(F("moodlight"), buffer);
}
void dispatch_backlight(const char *, const char * payload) void dispatch_backlight(const char *, const char * payload)
{ {
// Set the current state // Set the current state
@ -867,6 +929,7 @@ void dispatchSetup()
dispatch_add_command(PSTR("dim"), dispatch_dim); dispatch_add_command(PSTR("dim"), dispatch_dim);
dispatch_add_command(PSTR("brightness"), dispatch_dim); dispatch_add_command(PSTR("brightness"), dispatch_dim);
dispatch_add_command(PSTR("light"), dispatch_backlight); dispatch_add_command(PSTR("light"), dispatch_backlight);
dispatch_add_command(PSTR("moodlight"), dispatch_moodlight);
dispatch_add_command(PSTR("calibrate"), dispatch_calibrate); dispatch_add_command(PSTR("calibrate"), dispatch_calibrate);
dispatch_add_command(PSTR("update"), dispatch_web_update); dispatch_add_command(PSTR("update"), dispatch_web_update);
dispatch_add_command(PSTR("reboot"), dispatch_reboot); dispatch_add_command(PSTR("reboot"), dispatch_reboot);

View File

@ -32,6 +32,7 @@ void dispatch_topic_payload(const char * topic, const char * payload);
void dispatch_text_line(const char * cmnd); void dispatch_text_line(const char * cmnd);
void dispatch_parse_jsonl(Stream & stream); void dispatch_parse_jsonl(Stream & stream);
void dispatch_clear_page(const char * page); void dispatch_clear_page(const char * page);
void dispatch_json_error(uint8_t tag, DeserializationError & jsonError);
// void dispatchPage(uint8_t page); // void dispatchPage(uint8_t page);
void dispatch_page_next(); void dispatch_page_next();

View File

@ -261,8 +261,8 @@ void gpioSetup()
pinMode(gpioConfig[i].pin, OUTPUT); pinMode(gpioConfig[i].pin, OUTPUT);
break; break;
case HASP_GPIO_LED: case HASP_GPIO_LED ... HASP_GPIO_LED_CW_INVERTED:
case HASP_GPIO_LED_INVERTED: // case HASP_GPIO_LED_INVERTED:
case HASP_GPIO_PWM: case HASP_GPIO_PWM:
case HASP_GPIO_PWM_INVERTED: case HASP_GPIO_PWM_INVERTED:
// case HASP_GPIO_BACKLIGHT: // case HASP_GPIO_BACKLIGHT:
@ -290,27 +290,31 @@ void gpio_set_normalized_value(hasp_gpio_config_t gpio, uint16_t state)
gpio.val = state >= 0x8000U ? LOW : HIGH; gpio.val = state >= 0x8000U ? LOW : HIGH;
digitalWrite(gpio.pin, gpio.val); digitalWrite(gpio.pin, gpio.val);
break; break;
#if defined(ARDUINO_ARCH_ESP32)
case HASP_GPIO_LED: case HASP_GPIO_LED:
case HASP_GPIO_LED_R:
case HASP_GPIO_LED_G:
case HASP_GPIO_LED_B:
case HASP_GPIO_PWM: case HASP_GPIO_PWM:
#if defined(ARDUINO_ARCH_ESP32)
gpio.val = map(state, 0, 0xFFFFU, 0, 4095); gpio.val = map(state, 0, 0xFFFFU, 0, 4095);
ledcWrite(gpio.group, gpio.val); // ledChannel and value ledcWrite(gpio.group, gpio.val); // ledChannel and value
#else
analogWrite(gpio.pin, map(state, 0, 0xFFFFU, 0, 1023));
#endif
break; break;
case HASP_GPIO_LED_INVERTED: case HASP_GPIO_LED_INVERTED:
case HASP_GPIO_LED_R_INVERTED:
case HASP_GPIO_LED_G_INVERTED:
case HASP_GPIO_LED_B_INVERTED:
case HASP_GPIO_PWM_INVERTED: case HASP_GPIO_PWM_INVERTED:
#if defined(ARDUINO_ARCH_ESP32)
gpio.val = map(0xFFFFU - state, 0, 0xFFFFU, 0, 4095); gpio.val = map(0xFFFFU - state, 0, 0xFFFFU, 0, 4095);
ledcWrite(gpio.group, gpio.val); // ledChannel and value ledcWrite(gpio.group, gpio.val); // ledChannel and value
break;
#else #else
case HASP_GPIO_LED:
case HASP_GPIO_PWM:
analogWrite(gpio.pin, map(state, 0, 0xFFFFU, 0, 1023));
break;
case HASP_GPIO_LED_INVERTED:
case HASP_GPIO_PWM_INVERTED:
analogWrite(gpio.pin, map(0xFFFFU - state, 0, 0xFFFFU, 0, 1023)); analogWrite(gpio.pin, map(0xFFFFU - state, 0, 0xFFFFU, 0, 1023));
break;
#endif #endif
break;
default: default:
return; return;
} }
@ -336,6 +340,23 @@ void gpio_set_normalized_group_value(uint8_t groupid, uint16_t state)
} }
} }
void gpio_set_moodlight(uint8_t r, uint8_t g, uint8_t b)
{
for(uint8_t i = 0; i < HASP_NUM_GPIO_CONFIG; i++) {
switch(gpioConfig[i].type & 0xfe) {
case HASP_GPIO_LED_R:
gpio_set_normalized_value(gpioConfig[i], map(r, 0, 0xFF, 0, 0xFFFFU));
break;
case HASP_GPIO_LED_G:
gpio_set_normalized_value(gpioConfig[i], map(g, 0, 0xFF, 0, 0xFFFFU));
break;
case HASP_GPIO_LED_B:
gpio_set_normalized_value(gpioConfig[i], map(b, 0, 0xFF, 0, 0xFFFFU));
break;
}
}
}
// not used // not used
// void gpio_set_gpio_value(uint8_t pin, uint16_t state) // void gpio_set_gpio_value(uint8_t pin, uint16_t state)
// { // {

View File

@ -26,6 +26,7 @@ void gpioEvery5Seconds(void);
// void gpio_set_group_onoff(uint8_t groupid, bool ison); // void gpio_set_group_onoff(uint8_t groupid, bool ison);
void gpio_set_normalized_group_value(uint8_t groupid, uint16_t state); void gpio_set_normalized_group_value(uint8_t groupid, uint16_t state);
// void gpio_set_gpio_state(uint8_t pin, uint16_t state); // void gpio_set_gpio_state(uint8_t pin, uint16_t state);
void gpio_set_moodlight(uint8_t r, uint8_t g, uint8_t b);
bool gpioSavePinConfig(uint8_t config_num, uint8_t pin, uint8_t type, uint8_t group, uint8_t pinfunc); bool gpioSavePinConfig(uint8_t config_num, uint8_t pin, uint8_t type, uint8_t group, uint8_t pinfunc);
bool gpioIsSystemPin(uint8_t gpio); bool gpioIsSystemPin(uint8_t gpio);