diff --git a/src/hasp/hasp_dispatch.cpp b/src/hasp/hasp_dispatch.cpp index 1d5a0cd9..548b37b5 100644 --- a/src/hasp/hasp_dispatch.cpp +++ b/src/hasp/hasp_dispatch.cpp @@ -212,51 +212,32 @@ static void dispatch_gpio(const char* topic, const char* payload) uint8_t pin; if(topic == strstr_P(topic, PSTR("relay"))) { - if(strlen(payload) == 0) { - // val = gpio_get_relay_value(pin); - } else { - topic += 5; - if(Parser::is_only_digits(topic)) { - pin = atoi(topic); - val = Parser::is_true(payload); - // gpio_set_relay_value(pin, val); - return; - } - // invalid pin - } + topic += 5; + val = Parser::is_true(payload); } else if(topic == strstr_P(topic, PSTR("led"))) { - if(strlen(payload) == 0) { - } else { - topic += 3; - if(Parser::is_only_digits(topic)) { - pin = atoi(topic); - val = Parser::is_true(payload); - // gpio_set_led_value(pin, val); - return; - } - // invalid pin - } + topic += 3; + val = atoi(payload); } else if(topic == strstr_P(topic, PSTR("pwm"))) { - if(strlen(payload) == 0) { - - } else { - topic += 3; - if(Parser::is_only_digits(topic)) { - pin = atoi(topic); - val = Parser::is_true(payload); - // gpio_set_pwm_value(pin, val); - return; - } - // invalid pin - } + topic += 3; + val = atoi(payload); } else { - LOG_WARNING(TAG_MSGR, F("Invalid gpio type %s"), topic); + LOG_WARNING(TAG_MSGR, F("Invalid gpio %s"), topic); return; } - LOG_WARNING(TAG_MSGR, F("Invalid pin number %s"), topic); + + if(Parser::is_only_digits(topic)) { + pin = atoi(topic); + if(strlen(payload) > 0) { + gpio_set_value(pin, val); + } else { + gpio_get_value(pin); + } + } else { + LOG_WARNING(TAG_MSGR, F("Invalid pin %s"), topic); + } } // objectattribute=value @@ -521,19 +502,6 @@ static void dispatch_config(const char* topic, const char* payload) } #endif // HASP_USE_CONFIG -/********************************************** Input Events *******************************************/ -#if HASP_USE_GPIO > 0 -void dispatch_gpio_output_value(const char* gpiotype, uint8_t pin, int16_t val) -{ - char payload[16]; - char topic[16]; - snprintf_P(topic, sizeof(topic), PSTR("%s%d"), gpiotype, pin); - snprintf_P(payload, sizeof(payload), PSTR("%d"), val); - - dispatch_state_subtopic(topic, payload); -} -#endif - /********************************************** Output States ******************************************/ /* static inline void dispatch_state_msg(const __FlashStringHelper* subtopic, const char* payload) @@ -595,7 +563,7 @@ void dispatch_screenshot(const char*, const char* filename) } #else - LOG_WARNING(TAG_MSGR, "Failed to save %s, no storage", filename); + LOG_WARNING(TAG_MSGR, D_FILE_SAVE_FAILED, filename); #endif } diff --git a/src/hasp/hasp_dispatch.h b/src/hasp/hasp_dispatch.h index 1ecb9fc0..21f634b9 100644 --- a/src/hasp/hasp_dispatch.h +++ b/src/hasp/hasp_dispatch.h @@ -64,7 +64,6 @@ void dispatch_current_state(); void dispatch_output_current_page(); void dispatch_gpio_input_event(uint8_t pin, uint8_t group, uint8_t eventid); -void dispatch_gpio_output_value(const char* gpiotype, uint8_t pin, int16_t val); void dispatch_object_value_changed(lv_obj_t* obj, int16_t state); diff --git a/src/sys/gpio/hasp_gpio.cpp b/src/sys/gpio/hasp_gpio.cpp index 3b237db2..738bed7d 100644 --- a/src/sys/gpio/hasp_gpio.cpp +++ b/src/sys/gpio/hasp_gpio.cpp @@ -24,6 +24,8 @@ hasp_gpio_config_t gpioConfig[HASP_NUM_GPIO_CONFIG] = { }; #if defined(ARDUINO_ARCH_ESP32) +#include "driver/uart.h" + class TouchConfig : public ButtonConfig { public: TouchConfig(); @@ -90,6 +92,16 @@ static void gpio_event_handler(AceButton* button, uint8_t eventType, uint8_t but dispatch_normalized_group_value(gpioConfig[btnid].group, NULL, state, HASP_EVENT_OFF, HASP_EVENT_ON); } +/* ********************************* GPIO Setup *************************************** */ + +void gpio_log_serial_dimmer(const char* command) +{ + char buffer[32]; + snprintf_P(buffer, sizeof(buffer), PSTR("Dimmer: %02x %02x %02x %02x"), command[0], command[1], command[2], + command[3]); + LOG_VERBOSE(TAG_GPIO, buffer); +} + void aceButtonSetup(void) { ButtonConfig* buttonConfig = ButtonConfig::getSystemButtonConfig(); @@ -269,6 +281,16 @@ void gpioSetup() ledcSetup(gpioConfig[i].group, 20000, 12); // attach the channel to the GPIO to be controlled ledcAttachPin(gpioConfig[i].pin, gpioConfig[i].group); +#endif + break; + + case HASP_GPIO_SERIAL_DIMMER: +#if defined(ARDUINO_ARCH_ESP32) + Serial2.begin(115200, SERIAL_8N1, UART_PIN_NO_CHANGE, gpioConfig[i].pin); + delay(20); + const char command[5] = "\xEF\x01\x4D\xA3"; // Start Lanbon Dimmer + Serial2.print(command); + gpio_log_serial_dimmer(command); #endif break; } @@ -276,6 +298,97 @@ void gpioSetup() } /* ********************************* State Setters *************************************** */ + +void gpio_get_value(hasp_gpio_config_t gpio) +{ + char payload[32]; + char topic[12]; + snprintf_P(topic, sizeof(topic), PSTR("gpio%d"), gpio.pin); + snprintf_P(payload, sizeof(payload), PSTR("%d"), gpio.val); + + dispatch_state_subtopic(topic, payload); +} + +void gpio_get_value(uint8_t pin) +{ + for(uint8_t i = 0; i < HASP_NUM_GPIO_CONFIG; i++) { + if(gpioConfig[i].pin == pin) return gpio_get_value(gpioConfig[i]); + } + LOG_WARNING(TAG_GPIO, F(D_BULLET "Pin %d is not configured"), pin); +} + +void gpio_set_value(hasp_gpio_config_t gpio, int16_t val) +{ + bool inverted = false; + + switch(gpio.type) { + case HASP_GPIO_RELAY_INVERTED: + inverted = true; + case HASP_GPIO_RELAY: + gpio.val = val > 0 ? HIGH : LOW; + digitalWrite(gpio.pin, inverted ? gpio.val : !gpio.val); + break; + + case HASP_GPIO_LED_INVERTED: + case HASP_GPIO_LED_R_INVERTED: + case HASP_GPIO_LED_G_INVERTED: + case HASP_GPIO_LED_B_INVERTED: + inverted = true; + case HASP_GPIO_LED: + case HASP_GPIO_LED_R: + case HASP_GPIO_LED_G: + case HASP_GPIO_LED_B: + gpio.val = val >= 255 ? 255 : val > 0 ? val : 0; +#if defined(ARDUINO_ARCH_ESP32) + ledcWrite(gpio.group, gpio.val); // ledChannel and value +#else + analogWrite(gpio.pin, gpio.val); // 1023 +#endif + break; + + case HASP_GPIO_PWM_INVERTED: + inverted = true; + case HASP_GPIO_PWM: + gpio.val = val >= 4095 ? 4095 : val > 0 ? val : 0; +#if defined(ARDUINO_ARCH_ESP32) + ledcWrite(gpio.group, inverted ? 4095 - gpio.val : gpio.val); // ledChannel and value +#else + analogWrite(gpio.pin, (inverted ? 4095 - gpio.val : gpio.val) >> 2); // 1023 +#endif + break; + + case HASP_GPIO_SERIAL_DIMMER: { + gpio.val = val >= 100 ? 100 : val > 0 ? val : 0; +#if defined(ARDUINO_ARCH_ESP32) + char command[5] = "\xEF\x02\x00\xED"; + if(gpio.val == 0) { + command[2] = 0x20; + } else { + command[2] = (uint8_t)gpio.val; + command[3] ^= command[2]; + } + Serial2.print(command); + gpio_log_serial_dimmer(command); + +#endif + break; + } + + default: + return; + } + gpio_get_value(gpio); + LOG_VERBOSE(TAG_GPIO, F("Group %d - Pin %d = %d"), gpio.group, gpio.pin, gpio.val); +} + +void gpio_set_value(uint8_t pin, int16_t val) +{ + for(uint8_t i = 0; i < HASP_NUM_GPIO_CONFIG; i++) { + if(gpioConfig[i].pin == pin) return gpio_set_value(gpioConfig[i], val); + } + LOG_WARNING(TAG_GPIO, F(D_BULLET "Pin %d is not configured"), pin); +} + void gpio_set_normalized_value(hasp_gpio_config_t gpio, int16_t val, int16_t min, int16_t max) { if(min == max) { @@ -283,73 +396,35 @@ void gpio_set_normalized_value(hasp_gpio_config_t gpio, int16_t val, int16_t min return; } + int16_t newval; switch(gpio.type) { case HASP_GPIO_RELAY: - gpio.val = val > min ? HIGH : LOW; - digitalWrite(gpio.pin, gpio.val); - dispatch_gpio_output_value("relay", gpio.pin, gpio.val); - break; - case HASP_GPIO_RELAY_INVERTED: - gpio.val = val > min ? LOW : HIGH; - digitalWrite(gpio.pin, gpio.val); - dispatch_gpio_output_value("relay", gpio.pin, gpio.val); + newval = val > min ? HIGH : LOW; break; case HASP_GPIO_LED: case HASP_GPIO_LED_R: case HASP_GPIO_LED_G: case HASP_GPIO_LED_B: -#if defined(ARDUINO_ARCH_ESP32) - gpio.val = map(val, min, max, 0, 4095); - ledcWrite(gpio.group, gpio.val); // ledChannel and value -#else - gpio.val = map(val, min, max, 0, 1023); - analogWrite(gpio.pin, gpio.val); -#endif - dispatch_gpio_output_value("led", gpio.pin, gpio.val); - break; - 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: -#if defined(ARDUINO_ARCH_ESP32) - gpio.val = map(val, min, max, 0, 4095); - ledcWrite(gpio.group, gpio.val); // ledChannel and value -#else - gpio.val = map(val, min, max, 0, 1023); - analogWrite(gpio.pin, gpio.val); -#endif - dispatch_gpio_output_value("led", gpio.pin, gpio.val); + newval = map(val, min, max, 0, 255); break; case HASP_GPIO_PWM: -#if defined(ARDUINO_ARCH_ESP32) - gpio.val = map(val, min, max, 0, 4095); - ledcWrite(gpio.group, gpio.val); // ledChannel and value -#else - gpio.val = map(val, min, max, 0, 1023); - analogWrite(gpio.pin, gpio.val); -#endif - dispatch_gpio_output_value("pwm", gpio.pin, gpio.val); + case HASP_GPIO_PWM_INVERTED: + newval = map(val, min, max, 0, 4095); break; default: return; } - LOG_VERBOSE(TAG_GPIO, F(D_BULLET "Group %d - Pin %d = %d"), gpio.group, gpio.pin, gpio.val); -} -// void gpio_set_group_onoff(uint8_t groupid, bool ison) -// { -// for(uint8_t i = 0; i < HASP_NUM_GPIO_CONFIG; i++) { -// if(gpioConfig[i].group == groupid) { -// gpio_set_value(gpioConfig[i], ison ? gpioConfig[i].max : 0); -// } -// } -// } + gpio_set_value(gpio, newval); +} void gpio_set_normalized_group_value(uint8_t groupid, int16_t val, int16_t min, int16_t max) { @@ -389,18 +464,6 @@ void gpio_set_moodlight(uint8_t r, uint8_t g, uint8_t b) } } -// not used -// void gpio_set_gpio_value(uint8_t pin, uint16_t state) -// { -// // bool state = Parser::get_event_state(eventid); -// for(uint8_t i = 0; i < HASP_NUM_GPIO_CONFIG; i++) { -// if(gpioConfig[i].pin == pin) { -// gpio_set_value(gpioConfig[i], state); -// return; -// } -// } -// } - bool gpioIsSystemPin(uint8_t gpio) { if((gpio >= NUM_DIGITAL_PINS) // invalid pins diff --git a/src/sys/gpio/hasp_gpio.h b/src/sys/gpio/hasp_gpio.h index a19674e0..4e114da4 100644 --- a/src/sys/gpio/hasp_gpio.h +++ b/src/sys/gpio/hasp_gpio.h @@ -26,6 +26,8 @@ void gpioEvery5Seconds(void); // void gpio_set_group_onoff(uint8_t groupid, bool ison); void gpio_set_normalized_group_value(uint8_t groupid, int16_t val, int16_t min, int16_t max); // void gpio_set_gpio_state(uint8_t pin, uint16_t state); +void gpio_get_value(uint8_t pin); +void gpio_set_value(uint8_t pin, int16_t val); 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); @@ -80,6 +82,7 @@ bool gpioSetConfig(const JsonObject& settings); #define HASP_GPIO_DAC_INVERTED 0x51 #define HASP_GPIO_ADC 0x52 #define HASP_GPIO_ADC_INVERTED 0x53 +#define HASP_GPIO_SERIAL_DIMMER 0x60 #define HASP_GPIO_USER 0xFF #ifdef __cplusplus diff --git a/src/sys/svc/hasp_http.cpp b/src/sys/svc/hasp_http.cpp index de87977b..506e35f1 100644 --- a/src/sys/svc/hasp_http.cpp +++ b/src/sys/svc/hasp_http.cpp @@ -1456,6 +1456,9 @@ void webHandleGpioConfig() // case HASP_GPIO_PWM_INVERTED: httpMessage += F("PWM"); break; + case HASP_GPIO_SERIAL_DIMMER: + httpMessage += F("Serial Dimmer"); + break; default: httpMessage += F("Unknown"); } @@ -1577,6 +1580,9 @@ void webHandleGpioOptions() selected = (conf.type == HASP_GPIO_RELAY) || (conf.type == HASP_GPIO_RELAY_INVERTED); httpMessage += getOption(HASP_GPIO_RELAY, F("Relay"), selected); + selected = (conf.type == HASP_GPIO_SERIAL_DIMMER); + httpMessage += getOption(HASP_GPIO_SERIAL_DIMMER, F("Serial Dimmer"), selected); + if(digitalPinHasPWM(webServer.arg(0).toInt())) { selected = (conf.type == HASP_GPIO_PWM) || (conf.type == HASP_GPIO_PWM_INVERTED); httpMessage += getOption(HASP_GPIO_PWM, F("PWM"), selected);