diff --git a/src/driver/drv_local.h b/src/driver/drv_local.h
index 030946e48..5fd25f70b 100644
--- a/src/driver/drv_local.h
+++ b/src/driver/drv_local.h
@@ -50,3 +50,9 @@ bool DRV_IsRunning(const char* name);
void TuyaMCU_Sensor_RunFrame();
void TuyaMCU_Sensor_Init();
+
+void DRV_Toggler_ProcessChanges(http_request_t *request);
+void DRV_Toggler_AddToHtmlPage(http_request_t *request);
+void DRV_Toggler_AppendInformationToHTTPIndexPage(http_request_t* request);
+void DRV_InitPWMToggler();
+
diff --git a/src/driver/drv_main.c b/src/driver/drv_main.c
index eb4b065f8..a1be90e16 100644
--- a/src/driver/drv_main.c
+++ b/src/driver/drv_main.c
@@ -77,6 +77,7 @@ static driver_t g_drivers[] = {
//Test drivers
{ "TESTPOWER", Test_Power_Init, Test_Power_RunFrame, BL09XX_AppendInformationToHTTPIndexPage, NULL, NULL, NULL, false },
{ "TESTLED", Test_LED_Driver_Init, Test_LED_Driver_RunFrame, NULL, NULL, NULL, Test_LED_Driver_OnChannelChanged, false },
+
#if PLATFORM_BEKEN
{ "SM16703P", SM16703P_Init, NULL, NULL, NULL, NULL, NULL, false },
@@ -85,6 +86,7 @@ static driver_t g_drivers[] = {
{ "SSDP", DRV_SSDP_Init, DRV_SSDP_RunEverySecond, NULL, DRV_SSDP_RunQuickTick, DRV_SSDP_Shutdown, NULL, false },
#endif
#if defined(PLATFORM_BEKEN) || defined(WINDOWS)
+ { "PWMToggler", DRV_InitPWMToggler, NULL, DRV_Toggler_AppendInformationToHTTPIndexPage, NULL, NULL, NULL, false },
{ "DGR", DRV_DGR_Init, DRV_DGR_RunEverySecond, NULL, DRV_DGR_RunQuickTick, DRV_DGR_Shutdown, DRV_DGR_OnChannelChanged, false },
#endif
{ "SM2135", SM2135_Init, SM2135_RunFrame, NULL, NULL, NULL, SM2135_OnChannelChanged, false },
diff --git a/src/driver/drv_pwmToggler.c b/src/driver/drv_pwmToggler.c
new file mode 100644
index 000000000..99ca99d22
--- /dev/null
+++ b/src/driver/drv_pwmToggler.c
@@ -0,0 +1,284 @@
+#include "../new_common.h"
+#include "../new_pins.h"
+#include "../new_cfg.h"
+// Commands register, execution API and cmd tokenizer
+#include "../cmnds/cmd_public.h"
+#include "../mqtt/new_mqtt.h"
+#include "../logging/logging.h"
+#include "../hal/hal_pins.h"
+#include "drv_public.h"
+#include "drv_local.h"
+#include "drv_uart.h"
+#include "../httpserver/new_http.h"
+
+/*
+PWM toggler provides you an abstraction layer over PWM channels
+and allows you to enable/disable them without losing the set PWM value.
+
+PWM toggler was created to support lamp with RGB LED and PWM laser and PWM motor.
+
+Configuration:
+- set channels 1, 2 and 3 for RGB
+- enable "force RGB mode" in General/Flags
+- set channels 4 for motor and 5 for laser
+- on web panel, create autoexec.bat with following script:
+
+ // enable toggler driver
+ startDriver PWMToggler
+ // toggler slot 0 will be channel 4
+ toggler_channel0 4
+ // toggler slot 0 display name is laser
+ toggler_name0 Laser
+
+ // toggler slot 1 will be channel 5
+ toggler_channel1 5
+ // toggler slot 1 display name is motor
+ toggler_name1 Motor
+
+- for HA, configure RGB as usual in Yaml
+- also add yaml entries for laser and motor:
+
+ - unique_id: "OpenBK7231T_760BF030_galaxy_laser"
+ name: "GenioLaser"
+ command_topic: "cmnd/obk760BF030/toggler_enable0"
+ state_topic: "obk760BF030/toggler_enable0/get"
+ payload_on: 1
+ payload_off: 0
+ brightness_command_topic: "cmnd/obk760BF030/toggler_set0"
+ brightness_scale: 100
+ brightness_state_topic: "obk760BF030/toggler_set0/get"
+ brightness_value_template: "{{value}}"
+ qos: 1
+
+
+
+
+
+*/
+
+#define MAX_ONOFF_SLOTS 6
+
+static char *g_names[MAX_ONOFF_SLOTS] = { 0 };
+static int g_channels[MAX_ONOFF_SLOTS];
+static int g_values[MAX_ONOFF_SLOTS];
+static bool g_enabled[MAX_ONOFF_SLOTS];
+
+int parsePowerArgument(const char *s);
+
+void publish_enableState(int index) {
+ char topic[32];
+ snprintf(topic, sizeof(topic), "toggler_enable%i", index);
+
+ MQTT_PublishMain_StringInt(topic, g_enabled[index]);
+}
+void publish_value(int index) {
+ char topic[32];
+ snprintf(topic, sizeof(topic), "toggler_set%i", index);
+
+ MQTT_PublishMain_StringInt(topic, g_values[index]);
+}
+void apply(int index) {
+ if (g_enabled[index]) {
+ CHANNEL_Set(g_channels[index], g_values[index], 0);
+ }
+ else {
+ CHANNEL_Set(g_channels[index], 0, 0);
+ }
+ publish_enableState(index);
+ publish_value(index);
+}
+void Toggler_Set(int index, int value) {
+ g_values[index] = value;
+ apply(index);
+}
+void Toggler_Toggle(int index) {
+ g_enabled[index] = !g_enabled[index];
+ apply(index);
+}
+commandResult_t Toggler_NameX(const void *context, const char *cmd, const char *args, int cmdFlags) {
+ const char *indexStr;
+ int index;
+ bool bEnabled;
+
+ if (args == 0 || *args == 0) {
+ addLogAdv(LOG_INFO, LOG_FEATURE_ENERGYMETER, "This command needs one argument");
+ return CMD_RES_NOT_ENOUGH_ARGUMENTS;
+ }
+
+ indexStr = cmd + strlen("toggler_name");
+ index = atoi(indexStr);
+
+ if (g_names[index])
+ free(g_names[index]);
+ g_names[index] = strdup(args);
+
+ return CMD_RES_OK;
+}
+commandResult_t Toggler_EnableX(const void *context, const char *cmd, const char *args, int cmdFlags) {
+ const char *indexStr;
+ int index;
+ bool bEnabled;
+
+ if (args == 0 || *args == 0) {
+ addLogAdv(LOG_INFO, LOG_FEATURE_ENERGYMETER, "This command needs one argument");
+ return CMD_RES_NOT_ENOUGH_ARGUMENTS;
+ }
+
+ indexStr = cmd + strlen("toggler_enable");
+ index = atoi(indexStr);
+
+ bEnabled = parsePowerArgument(args);
+ g_enabled[index] = bEnabled;
+
+ apply(index);
+
+
+ return CMD_RES_OK;
+}
+
+commandResult_t Toggler_SetX(const void *context, const char *cmd, const char *args, int cmdFlags) {
+ const char *indexStr;
+ int index;
+ bool bEnabled;
+
+ if (args == 0 || *args == 0) {
+ addLogAdv(LOG_INFO, LOG_FEATURE_ENERGYMETER, "This command needs one argument");
+ return CMD_RES_NOT_ENOUGH_ARGUMENTS;
+ }
+
+ indexStr = cmd + strlen("toggler_set");
+ index = atoi(indexStr);
+
+ g_values[index] = atoi(args);
+
+ apply(index);
+
+
+ return CMD_RES_OK;
+}
+commandResult_t Toggler_ChannelX(const void *context, const char *cmd, const char *args, int cmdFlags) {
+ const char *indexStr;
+ int index;
+ bool bEnabled;
+
+ if (args == 0 || *args == 0) {
+ addLogAdv(LOG_INFO, LOG_FEATURE_ENERGYMETER, "This command needs one argument");
+ return CMD_RES_NOT_ENOUGH_ARGUMENTS;
+ }
+
+ indexStr = cmd + strlen("toggler_channel");
+ index = atoi(indexStr);
+
+ g_channels[index] = atoi(args);
+
+ return CMD_RES_OK;
+}
+const char *Toggler_GetName(int i) {
+ const char *name = g_names[i];
+ if (name == 0)
+ name = "Unnamed";
+ return name;
+}
+void DRV_Toggler_ProcessChanges(http_request_t *request) {
+ int j;
+ int val;
+ char tmpA[8];
+
+ if (http_getArg(request->url, "togglerOn", tmpA, sizeof(tmpA))) {
+ j = atoi(tmpA);
+ const char *name = Toggler_GetName(j);
+ hprintf255(request, "Toggled %s!
", name);
+ Toggler_Toggle(j);
+ }
+ if (http_getArg(request->url, "togglerValueID", tmpA, sizeof(tmpA))) {
+ j = atoi(tmpA);
+ const char *name = Toggler_GetName(j);
+ http_getArg(request->url, "togglerValue", tmpA, sizeof(tmpA));
+ val = atoi(tmpA);
+ Toggler_Set(j, val);
+ hprintf255(request, "Set value %i for %s!
", val, name);
+ }
+
+}
+void DRV_Toggler_AddToHtmlPage(http_request_t *request) {
+ int i;
+ const char *c;
+
+ for (i = 0; i < MAX_ONOFF_SLOTS; i++) {
+ const char *name = Toggler_GetName(i);
+ int maxValue = 100;
+ if (g_channels[i] == -1)
+ continue;
+
+ //hprintf255(request, " Toggler %s
",name);
+
+ hprintf255(request, "");
+ if (g_enabled[i]) {
+ c = "bgrn";
+ }
+ else {
+ c = "bred";
+ }
+ poststr(request, " | ", c, name);
+ poststr(request, "
");
+
+ poststr(request, "| ");
+ hprintf255(request, "", name);
+ poststr(request, " |
");
+
+ }
+}
+void DRV_Toggler_AppendInformationToHTTPIndexPage(http_request_t* request) {
+ int i;
+ hprintf255(request, "Toggler: ");
+ int cnt = 0;
+ for (i = 0; i < MAX_ONOFF_SLOTS; i++) {
+ if (g_channels[i] == -1)
+ continue;
+ if (cnt != 0) {
+ hprintf255(request, ", ");
+ }
+ const char *name = Toggler_GetName(i);
+ const char *st;
+ if (g_enabled[i])
+ st = "ON";
+ else
+ st = "OFF";
+ hprintf255(request, "slot %i-%s (target %i) has value %i, state %s",
+ i, name, g_channels[i], g_values[i],st);
+ cnt++;
+ }
+ hprintf255(request, "
");
+
+}
+void DRV_InitPWMToggler() {
+ int i;
+
+ for (i = 0; i < MAX_ONOFF_SLOTS; i++) {
+ g_channels[i] = -1;
+ g_names[i] = 0;
+ }
+ // sets the given output ON or OFF
+ // handles toggler_enable0, toggler_enable1, etc
+ CMD_RegisterCommand("toggler_enable", "", Toggler_EnableX, NULL, NULL);
+ // sets the VALUE of given output
+ // handles toggler_set0, toggler_set1, etc
+ CMD_RegisterCommand("toggler_set", "", Toggler_SetX, NULL, NULL);
+ // handles toggler_channel0, toggler_channel1
+ CMD_RegisterCommand("toggler_channel", "", Toggler_ChannelX, NULL, NULL);
+ // handles toggler_name0 etc
+ CMD_RegisterCommand("toggler_name", "", Toggler_NameX, NULL, NULL);
+}
+
+
+
+
+
+
+
diff --git a/src/httpserver/http_fns.c b/src/httpserver/http_fns.c
index a75ff3aed..92b3010f0 100644
--- a/src/httpserver/http_fns.c
+++ b/src/httpserver/http_fns.c
@@ -225,6 +225,11 @@ int http_fn_index(http_request_t* request) {
http_html_start(request, NULL);
poststr(request, "");
+#if defined(PLATFORM_BEKEN) || defined(WINDOWS)
+ if (DRV_IsRunning("PWMToggler")) {
+ DRV_Toggler_ProcessChanges(request);
+ }
+#endif
if (http_getArg(request->url, "tgl", tmpA, sizeof(tmpA))) {
j = atoi(tmpA);
if (j == SPECIAL_CHANNEL_LEDPOWER) {
@@ -694,6 +699,12 @@ int http_fn_index(http_request_t* request) {
}
}
+#if defined(PLATFORM_BEKEN) || defined(WINDOWS)
+ if (DRV_IsRunning("PWMToggler")) {
+ DRV_Toggler_AddToHtmlPage(request);
+ }
+#endif
+
poststr(request, "");
#ifndef OBK_DISABLE_ALL_DRIVERS
DRV_AppendInformationToHTTPIndexPage(request);