Files
OpenBK7231T_App/src/cmnds/cmd_newLEDDriver.c
2022-11-21 19:21:39 +00:00

967 lines
27 KiB
C

#include "../logging/logging.h"
#include "../new_pins.h"
#include "../new_cfg.h"
#include "cmd_public.h"
#include "../obk_config.h"
#include "../driver/drv_public.h"
#include "../hal/hal_flashVars.h"
#include "../rgb2hsv.h"
#include <ctype.h>
#include "cmd_local.h"
#include "../mqtt/new_mqtt.h"
#include "../cJSON/cJSON.h"
#ifdef BK_LITTLEFS
#include "../littlefs/our_lfs.h"
#endif
// My HA config for system below:
/*
- platform: mqtt
name: obk8D38570E
rgb_command_template: "{{ '#%02x%02x%02x0000' | format(red, green, blue)}}"
rgb_state_topic: "cmnd/obk8D38570E/led_basecolor_rgb"
rgb_command_topic: "cmnd/obk8D38570E/led_basecolor_rgb"
command_topic: "cmnd/obk8D38570E/led_enableAll"
availability_topic: "obk8D38570E/connected"
payload_on: 1
payload_off: 0
brightness_command_topic: "cmnd/obk8D38570E/led_dimmer"
brightness_scale: 100
brightness_value_template: "{{ value_json.Dimmer }}"
color_temp_command_topic: "cmnd/obk8D38570E/led_temperature"
color_temp_state_topic: "cmnd/obk8D38570E/ctr"
color_temp_value_template: "{{ value_json.CT }}"
// TODO: state return topics
*/
// NOTE: there are 2 customization commands
// They are not storing the config in flash, if you use them,
// please put them in autoexec.bat from LittleFS.
// Command 1: led_brightnessMult [floatVal]
// It sets the multipler for the dimming
// Command 2: g_cfg_colorScaleToChannel [floatVal]
// It sets the multipler for converting 0-255 range RGB to 0-100 channel value
int parsePowerArgument(const char *s);
int g_lightMode = Light_RGB;
// Those are base colors, normalized, without brightness applied
float baseColors[5] = { 255, 255, 255, 255, 255 };
// Those have brightness included
float finalColors[5] = { 255, 255, 255, 255, 255 };
float g_hsv_h = 0; // 0 to 360
float g_hsv_s = 0; // 0 to 1
float g_hsv_v = 1; // 0 to 1
// By default, colors are in 255 to 0 range, while our channels accept 0 to 100 range
float g_cfg_colorScaleToChannel = 100.0f/255.0f;
int g_numBaseColors = 5;
float g_brightness = 1.0f;
// NOTE: in this system, enabling/disabling whole led light bulb
// is not changing the stored channel and brightness values.
// They are kept intact so you can reenable the bulb and keep your color setting
int g_lightEnableAll = 0;
// config only stuff
float g_cfg_brightnessMult = 0.01f;
// the slider control in the UI emits values
//in the range from 154-500 (defined
//in homeassistant/util/color.py as HASS_COLOR_MIN and HASS_COLOR_MAX).
float led_temperature_min = HASS_TEMPERATURE_MIN;
float led_temperature_max = HASS_TEMPERATURE_MAX;
float led_temperature_current = HASS_TEMPERATURE_MIN;
bool LED_IsLedDriverChipRunning()
{
#ifndef OBK_DISABLE_ALL_DRIVERS
return DRV_IsRunning("SM2135") || DRV_IsRunning("BP5758D") || DRV_IsRunning("TESTLED");
#else
return false;
#endif
}
bool LED_IsLEDRunning()
{
int pwmCount;
if (LED_IsLedDriverChipRunning())
return true;
pwmCount = PIN_CountPinsWithRoleOrRole(IOR_PWM, IOR_PWM_n);
if (pwmCount > 0)
return true;
return false;
}
int isCWMode() {
int pwmCount;
pwmCount = PIN_CountPinsWithRoleOrRole(IOR_PWM, IOR_PWM_n);
if(pwmCount == 2)
return 1;
return 0;
}
int shouldSendRGB() {
int pwmCount;
// forced RGBCW means 'send rgb'
// This flag should be set for SM2315 and BP5758
// This flag also could be used for dummy Device Groups driver-module
if(CFG_HasFlag(OBK_FLAG_LED_FORCESHOWRGBCWCONTROLLER))
return 1;
pwmCount = PIN_CountPinsWithRoleOrRole(IOR_PWM, IOR_PWM_n);
// single colors and CW don't send rgb
if(pwmCount <= 2)
return 0;
return 1;
}
// One user requested ability to broadcast full RGBCW
static void sendFullRGBCW_IfEnabled() {
char s[16];
byte c[5];
if(CFG_HasFlag(OBK_FLAG_LED_BROADCAST_FULL_RGBCW) == false) {
return;
}
c[0] = (byte)(finalColors[0]);
c[1] = (byte)(finalColors[1]);
c[2] = (byte)(finalColors[2]);
c[3] = (byte)(finalColors[3]);
c[4] = (byte)(finalColors[4]);
snprintf(s, sizeof(s),"%02X%02X%02X%02X%02X",c[0],c[1],c[2],c[3],c[4]);
MQTT_PublishMain_StringString_DeDuped(DEDUP_LED_FINALCOLOR_RGBCW,DEDUP_EXPIRE_TIME,"led_finalcolor_rgbcw",s, 0);
}
float led_rawLerpCurrent[5] = { 0 };
float Mathf_MoveTowards(float cur, float tg, float dt) {
float rem = tg - cur;
if(abs(rem) < dt) {
return tg;
}
if(rem < 0) {
return cur - dt;
}
return cur + dt;
}
// Colors are in 0-255 range.
// This value determines how fast color can change.
// 100 means that in one second color will go from 0 to 100
// 200 means that in one second color will go from 0 to 200
float led_lerpSpeedUnitsPerSecond = 200.f;
float led_current_value_brightness = 0;
float led_current_value_cold_or_warm = 0;
void LED_RunQuickColorLerp(int deltaMS) {
int i;
int firstChannelIndex;
float deltaSeconds;
byte finalRGBCW[5];
deltaSeconds = deltaMS * 0.001f;
// The color order is RGBCW.
// some people set RED to channel 0, and some of them set RED to channel 1
// Let's detect if there is a PWM on channel 0
if(CHANNEL_HasChannelPinWithRoleOrRole(0, IOR_PWM, IOR_PWM_n)) {
firstChannelIndex = 0;
} else {
firstChannelIndex = 1;
}
for(i = 0; i < 5; i++) {
// This is the most silly and primitive approach, but it works
// In future we might implement better lerp algorithms, use HUE, etc
led_rawLerpCurrent[i] = Mathf_MoveTowards(led_rawLerpCurrent[i],finalColors[i], deltaSeconds * led_lerpSpeedUnitsPerSecond);
}
if(isCWMode() && CFG_HasFlag(OBK_FLAG_LED_ALTERNATE_CW_MODE)) {
// OBK_FLAG_LED_ALTERNATE_CW_MODE means we have a driver that takes one PWM for brightness and second for temperature
int target_value_brightness = 0;
int target_value_cold_or_warm = 0;
target_value_cold_or_warm = LED_GetTemperature0to1Range() * 100.0f;
target_value_brightness = g_brightness * 100.0f;
led_current_value_brightness = Mathf_MoveTowards(led_current_value_brightness, target_value_brightness, deltaSeconds * led_lerpSpeedUnitsPerSecond);
led_current_value_cold_or_warm = Mathf_MoveTowards(led_current_value_cold_or_warm, target_value_cold_or_warm, deltaSeconds * led_lerpSpeedUnitsPerSecond);
CHANNEL_Set(firstChannelIndex, led_current_value_cold_or_warm, CHANNEL_SET_FLAG_SKIP_MQTT | CHANNEL_SET_FLAG_SILENT);
CHANNEL_Set(firstChannelIndex+1, led_current_value_brightness, CHANNEL_SET_FLAG_SKIP_MQTT | CHANNEL_SET_FLAG_SILENT);
} else {
if(isCWMode()) {
// In CW mode, user sets just two PWMs. So we have: PWM0 and PWM1 (or maybe PWM1 and PWM2)
// But we still have RGBCW internally
// So, we need to map. Map component 3 of RGBCW to first channel, and component 4 to second.
CHANNEL_Set(firstChannelIndex + 0, led_rawLerpCurrent[3] * g_cfg_colorScaleToChannel, CHANNEL_SET_FLAG_SKIP_MQTT | CHANNEL_SET_FLAG_SILENT);
CHANNEL_Set(firstChannelIndex + 1, led_rawLerpCurrent[4] * g_cfg_colorScaleToChannel, CHANNEL_SET_FLAG_SKIP_MQTT | CHANNEL_SET_FLAG_SILENT);
} else {
// This should work for both RGB and RGBCW
// This also could work for a SINGLE COLOR strips
for(i = 0; i < 5; i++) {
finalRGBCW[i] = led_rawLerpCurrent[i];
CHANNEL_Set(firstChannelIndex + i, led_rawLerpCurrent[i] * g_cfg_colorScaleToChannel, CHANNEL_SET_FLAG_SKIP_MQTT | CHANNEL_SET_FLAG_SILENT);
}
}
}
#ifndef OBK_DISABLE_ALL_DRIVERS
if(DRV_IsRunning("SM2135")) {
SM2135_Write(finalRGBCW);
}
if(DRV_IsRunning("BP5758D")) {
BP5758D_Write(finalRGBCW);
}
if(DRV_IsRunning("BP1658CJ")) {
BP1658CJ_Write(finalRGBCW);
}
#endif
}
void apply_smart_light() {
int i;
int firstChannelIndex;
int channelToUse;
byte finalRGBCW[5];
// The color order is RGBCW.
// some people set RED to channel 0, and some of them set RED to channel 1
// Let's detect if there is a PWM on channel 0
if(CHANNEL_HasChannelPinWithRoleOrRole(0, IOR_PWM, IOR_PWM_n)) {
firstChannelIndex = 0;
} else {
firstChannelIndex = 1;
}
if(isCWMode() && CFG_HasFlag(OBK_FLAG_LED_ALTERNATE_CW_MODE)) {
int value_brightness = 0;
int value_cold_or_warm = 0;
for(i = 0; i < 5; i++) {
finalColors[i] = 0;
finalRGBCW[i] = 0;
}
if(g_lightEnableAll) {
value_cold_or_warm = LED_GetTemperature0to1Range() * 100.0f;
value_brightness = g_brightness * 100.0f;
for(i = 3; i < 5; i++) {
finalColors[i] = baseColors[i] * g_brightness;
finalRGBCW[i] = baseColors[i] * g_brightness;
}
}
if(CFG_HasFlag(OBK_FLAG_LED_SMOOTH_TRANSITIONS) == false) {
CHANNEL_Set(firstChannelIndex, value_cold_or_warm, CHANNEL_SET_FLAG_SKIP_MQTT | CHANNEL_SET_FLAG_SILENT);
CHANNEL_Set(firstChannelIndex+1, value_brightness, CHANNEL_SET_FLAG_SKIP_MQTT | CHANNEL_SET_FLAG_SILENT);
}
} else {
for(i = 0; i < 5; i++) {
float raw, final;
raw = baseColors[i];
if(g_lightEnableAll) {
final = raw * g_brightness;
} else {
final = 0;
}
if(g_lightMode == Light_Temperature) {
// skip channels 0, 1, 2
// (RGB)
if(i < 3)
{
final = 0;
}
} else if(g_lightMode == Light_RGB) {
// skip channels 3, 4
if(i >= 3)
{
final = 0;
}
} else {
}
finalColors[i] = final;
finalRGBCW[i] = final;
channelToUse = firstChannelIndex + i;
// log printf with %f crashes N platform?
//ADDLOG_INFO(LOG_FEATURE_CMD, "apply_smart_light: ch %i raw is %f, bright %f, final %f, enableAll is %i",
// channelToUse,raw,g_brightness,final,g_lightEnableAll);
if(CFG_HasFlag(OBK_FLAG_LED_SMOOTH_TRANSITIONS) == false) {
if(isCWMode()) {
// in CW mode, we have only set two channels
// We don't have RGB channels
// so, do simple mapping
if(i == 3) {
CHANNEL_Set(firstChannelIndex+0, final * g_cfg_colorScaleToChannel, CHANNEL_SET_FLAG_SKIP_MQTT | CHANNEL_SET_FLAG_SILENT);
} else if(i == 4) {
CHANNEL_Set(firstChannelIndex+1, final * g_cfg_colorScaleToChannel, CHANNEL_SET_FLAG_SKIP_MQTT | CHANNEL_SET_FLAG_SILENT);
}
} else {
CHANNEL_Set(channelToUse, final * g_cfg_colorScaleToChannel, CHANNEL_SET_FLAG_SKIP_MQTT | CHANNEL_SET_FLAG_SILENT);
}
}
}
}
if(CFG_HasFlag(OBK_FLAG_LED_SMOOTH_TRANSITIONS) == false) {
#ifndef OBK_DISABLE_ALL_DRIVERS
if(DRV_IsRunning("SM2135")) {
SM2135_Write(finalRGBCW);
}
if(DRV_IsRunning("BP5758D")) {
BP5758D_Write(finalRGBCW);
}
if(DRV_IsRunning("BP1658CJ")) {
BP1658CJ_Write(finalRGBCW);
}
#endif
}
if(CFG_HasFlag(OBK_FLAG_LED_REMEMBERLASTSTATE)) {
HAL_FlashVars_SaveLED(g_lightMode,g_brightness / g_cfg_brightnessMult, led_temperature_current,baseColors[0],baseColors[1],baseColors[2],g_lightEnableAll);
}
// I am not sure if it's the best place to do it
// NOTE: this will broadcast MQTT only if a flag is set
sendFullRGBCW_IfEnabled();
}
static OBK_Publish_Result sendColorChange() {
char s[16];
byte c[3];
if(shouldSendRGB()==0) {
return OBK_PUBLISH_WAS_NOT_REQUIRED;
}
c[0] = (byte)(baseColors[0]);
c[1] = (byte)(baseColors[1]);
c[2] = (byte)(baseColors[2]);
snprintf(s, sizeof(s), "%02X%02X%02X",c[0],c[1],c[2]);
return MQTT_PublishMain_StringString_DeDuped(DEDUP_LED_BASECOLOR_RGB,DEDUP_EXPIRE_TIME,"led_basecolor_rgb",s, 0);
}
void LED_GetBaseColorString(char * s) {
byte c[3];
c[0] = (byte)(baseColors[0]);
c[1] = (byte)(baseColors[1]);
c[2] = (byte)(baseColors[2]);
sprintf(s, "%02X%02X%02X",c[0],c[1],c[2]);
}
static void sendFinalColor() {
char s[16];
byte c[3];
if(shouldSendRGB()==0) {
return;
}
c[0] = (byte)(finalColors[0]);
c[1] = (byte)(finalColors[1]);
c[2] = (byte)(finalColors[2]);
snprintf(s, sizeof(s),"%02X%02X%02X",c[0],c[1],c[2]);
MQTT_PublishMain_StringString_DeDuped(DEDUP_LED_FINALCOLOR_RGB,DEDUP_EXPIRE_TIME,"led_finalcolor_rgb",s, 0);
}
OBK_Publish_Result LED_SendDimmerChange() {
int iValue;
iValue = g_brightness / g_cfg_brightnessMult;
return MQTT_PublishMain_StringInt_DeDuped(DEDUP_LED_DIMMER,DEDUP_EXPIRE_TIME,"led_dimmer", iValue, 0);
}
static OBK_Publish_Result sendTemperatureChange(){
return MQTT_PublishMain_StringInt_DeDuped(DEDUP_LED_TEMPERATURE,DEDUP_EXPIRE_TIME,"led_temperature", (int)led_temperature_current,0);
}
float LED_GetTemperature() {
return led_temperature_current;
}
int LED_GetMode() {
return g_lightMode;
}
const char *GetLightModeStr(int mode) {
if(mode == Light_All)
return "all";
if(mode == Light_Temperature)
return "cw";
if(mode == Light_RGB)
return "rgb";
return "er";
}
void SET_LightMode(int newMode) {
if(g_lightMode != newMode) {
ADDLOG_DEBUG(LOG_FEATURE_CMD, "Changing LightMode from %s to %s",
GetLightModeStr(g_lightMode),
GetLightModeStr(newMode));
g_lightMode = newMode;
}
}
OBK_Publish_Result LED_SendCurrentLightMode() {
if(g_lightMode == Light_Temperature) {
return sendTemperatureChange();
} else if(g_lightMode == Light_RGB) {
return sendColorChange();
}
return OBK_PUBLISH_WAS_NOT_REQUIRED;
}
void LED_SetTemperature0to1Range(float f) {
led_temperature_current = led_temperature_min + (led_temperature_max-led_temperature_min) * f;
}
float LED_GetTemperature0to1Range() {
float f;
f = (led_temperature_current - led_temperature_min);
f = f / (led_temperature_max - led_temperature_min);
if(f<0)
f = 0;
if(f>1)
f =1;
return f;
}
void LED_SetTemperature(int tmpInteger, bool bApply) {
float f;
led_temperature_current = tmpInteger;
f = LED_GetTemperature0to1Range();
baseColors[3] = (255.0f) * (1-f);
baseColors[4] = (255.0f) * f;
if(bApply) {
// set g_lightMode
SET_LightMode(Light_Temperature);
sendTemperatureChange();
apply_smart_light();
}
}
static int temperature(const void *context, const char *cmd, const char *args, int cmdFlags){
int tmp;
//if (!wal_strnicmp(cmd, "POWERALL", 8)){
ADDLOG_DEBUG(LOG_FEATURE_CMD, " temperature (%s) received with args %s",cmd,args);
tmp = atoi(args);
LED_SetTemperature(tmp, 1);
return 1;
//}
//return 0;
}
OBK_Publish_Result LED_SendEnableAllState() {
return MQTT_PublishMain_StringInt_DeDuped(DEDUP_LED_ENABLEALL,DEDUP_EXPIRE_TIME,"led_enableAll",g_lightEnableAll,0);
}
void LED_ToggleEnabled() {
LED_SetEnableAll(!g_lightEnableAll);
}
void LED_SetEnableAll(int bEnable) {
g_lightEnableAll = bEnable;
apply_smart_light();
#ifndef OBK_DISABLE_ALL_DRIVERS
DRV_DGR_OnLedEnableAllChange(bEnable);
#endif
LED_SendEnableAllState();
}
int LED_GetEnableAll() {
return g_lightEnableAll;
}
static int enableAll(const void *context, const char *cmd, const char *args, int cmdFlags){
//if (!wal_strnicmp(cmd, "POWERALL", 8)){
int bEnable;
ADDLOG_DEBUG(LOG_FEATURE_CMD, " enableAll (%s) received with args %s",cmd,args);
Tokenizer_TokenizeString(args, 0);
bEnable = Tokenizer_GetArgInteger(0);
LED_SetEnableAll(bEnable);
// sendColorChange();
// sendDimmerChange();
// sendTemperatureChange();
return 1;
//}
//return 0;
}
int LED_IsRunningDriver() {
if(PIN_CountPinsWithRoleOrRole(IOR_PWM,IOR_PWM_n))
return 1;
if(CFG_HasFlag(OBK_FLAG_LED_FORCESHOWRGBCWCONTROLLER))
return 1;
return 0;
}
float LED_GetDimmer() {
return g_brightness / g_cfg_brightnessMult;
}
void LED_AddDimmer(int iVal, bool wrapAroundInsteadOfClamp, int minValue) {
float cur;
cur = g_brightness / g_cfg_brightnessMult;
cur += iVal;
if(wrapAroundInsteadOfClamp == 0) {
if(cur < minValue)
cur = minValue;
if(cur > 100)
cur = 100;
} else {
if(cur < minValue)
cur = 100;
if(cur > 100)
cur = minValue;
}
LED_SetDimmer(cur);
}
void LED_NextDimmerHold() {
// dimmer hold will use some kind of min value,
// because it's easy to get confused if we set accidentally dimmer to 0
// and then are unable to turn on the bulb (because despite of led_enableAll 1
// the dimmer is 0 and anyColor * 0 gives 0)
LED_AddDimmer(10, true, 2);
}
void LED_SetDimmer(int iVal) {
g_brightness = iVal * g_cfg_brightnessMult;
#ifndef OBK_DISABLE_ALL_DRIVERS
DRV_DGR_OnLedDimmerChange(iVal);
#endif
apply_smart_light();
LED_SendDimmerChange();
if(shouldSendRGB()) {
if(CFG_HasFlag(OBK_FLAG_MQTT_BROADCASTLEDPARAMSTOGETHER)) {
sendColorChange();
}
if(CFG_HasFlag(OBK_FLAG_MQTT_BROADCASTLEDFINALCOLOR)) {
sendFinalColor();
}
}
}
static int add_dimmer(const void *context, const char *cmd, const char *args, int cmdFlags){
int iVal = 0;
iVal = atoi(args);
LED_AddDimmer(iVal, 0, 0);
return 1;
}
static int dimmer(const void *context, const char *cmd, const char *args, int cmdFlags){
//if (!wal_strnicmp(cmd, "POWERALL", 8)){
int iVal = 0;
ADDLOG_DEBUG(LOG_FEATURE_CMD, " dimmer (%s) received with args %s",cmd,args);
// according to Elektroda.com users, domoticz sends following string:
// {"brightness":52,"state":"ON"}
if(args[0] == '{') {
cJSON *json;
const cJSON *brightness = NULL;
const cJSON *state = NULL;
json = cJSON_Parse(args);
if(json == 0) {
ADDLOG_INFO(LOG_FEATURE_CMD, "Dimmer - failed cJSON_Parse");
} else {
brightness = cJSON_GetObjectItemCaseSensitive(json, "brightness");
if (brightness != 0 && cJSON_IsNumber(brightness))
{
ADDLOG_INFO(LOG_FEATURE_CMD, "Dimmer - cJSON_Parse says brightness is %i",brightness->valueint);
LED_SetDimmer(brightness->valueint);
}
state = cJSON_GetObjectItemCaseSensitive(json, "state");
if (state != 0 && cJSON_IsString(state) && (state->valuestring != NULL))
{
ADDLOG_INFO(LOG_FEATURE_CMD, "Dimmer - cJSON_Parse says state is %s",state->valuestring);
if(!stricmp(state->valuestring,"ON")) {
LED_SetEnableAll(true);
} else if(!stricmp(state->valuestring,"OFF")) {
LED_SetEnableAll(false);
} else {
}
}
cJSON_Delete(json);
}
} else {
Tokenizer_TokenizeString(args, 0);
iVal = Tokenizer_GetArgInteger(0);
LED_SetDimmer(iVal);
}
return 1;
//}
//return 0;
}
void LED_SetFinalRGBCW(byte *rgbcw) {
if(rgbcw[0] == 0 && rgbcw[1] == 0 && rgbcw[2] == 0 && rgbcw[3] == 0 && rgbcw[4] == 0) {
}
if(rgbcw[3] == 0 && rgbcw[4] == 0) {
LED_SetFinalRGB(rgbcw[0],rgbcw[1],rgbcw[2]);
} else {
LED_SetFinalCW(rgbcw[3],rgbcw[4]);
}
}
void LED_GetFinalChannels100(byte *rgbcw) {
rgbcw[0] = finalColors[0] * (100.0f / 255.0f);
rgbcw[1] = finalColors[1] * (100.0f / 255.0f);
rgbcw[2] = finalColors[2] * (100.0f / 255.0f);
rgbcw[3] = finalColors[3] * (100.0f / 255.0f);
rgbcw[4] = finalColors[4] * (100.0f / 255.0f);
}
void LED_GetFinalHSV(int *hsv) {
hsv[0] = g_hsv_h;
hsv[1] = g_hsv_s;
hsv[2] = g_hsv_v;
}
void LED_GetFinalRGBCW(byte *rgbcw) {
rgbcw[0] = finalColors[0];
rgbcw[1] = finalColors[1];
rgbcw[2] = finalColors[2];
rgbcw[3] = finalColors[3];
rgbcw[4] = finalColors[4];
}
void LED_SetFinalCW(byte c, byte w) {
float tmp;
SET_LightMode(Light_Temperature);
// TODO: finish the calculation,
// the Device Group sent as White and Cool values in byte range,
// we need to get back Temperature value
tmp = c / 255.0f;
LED_SetTemperature0to1Range(tmp);
baseColors[3] = c;
baseColors[4] = w;
apply_smart_light();
}
void LED_SetFinalRGB(byte r, byte g, byte b) {
SET_LightMode(Light_RGB);
baseColors[0] = r;
baseColors[1] = g;
baseColors[2] = b;
RGBtoHSV(baseColors[0]/255.0f, baseColors[1]/255.0f, baseColors[2]/255.0f, &g_hsv_h, &g_hsv_s, &g_hsv_v);
apply_smart_light();
// TODO
if(0) {
sendColorChange();
if(CFG_HasFlag(OBK_FLAG_MQTT_BROADCASTLEDPARAMSTOGETHER)) {
LED_SendDimmerChange();
}
if(CFG_HasFlag(OBK_FLAG_MQTT_BROADCASTLEDFINALCOLOR)) {
sendFinalColor();
}
}
}
int LED_SetBaseColor(const void *context, const char *cmd, const char *args, int bAll){
// support both '#' prefix and not
const char *c = args;
int val = 0;
ADDLOG_DEBUG(LOG_FEATURE_CMD, " BASECOLOR got %s", args);
// some people prefix colors with #
if(c[0] == '#')
c++;
if(bAll) {
SET_LightMode(Light_All);
} else {
SET_LightMode(Light_RGB);
}
g_numBaseColors = 0;
if(!stricmp(c,"rand")) {
baseColors[0] = rand()%255;
baseColors[1] = rand()%255;
baseColors[2] = rand()%255;
if(bAll){
baseColors[3] = rand()%255;
baseColors[4] = rand()%255;
}
} else {
while (*c && g_numBaseColors < 5){
char tmp[3];
int r;
tmp[0] = *(c++);
if (!*c)
break;
tmp[1] = *(c++);
tmp[2] = '\0';
r = sscanf(tmp, "%x", &val);
if (!r) {
ADDLOG_ERROR(LOG_FEATURE_CMD, "BASECOLOR no sscanf hex result from %s", tmp);
break;
}
//ADDLOG_DEBUG(LOG_FEATURE_CMD, "BASECOLOR found chan %d -> val255 %d (from %s)", g_numBaseColors, val, tmp);
baseColors[g_numBaseColors] = val;
// baseColorChannels[g_numBaseColors] = channel;
g_numBaseColors++;
}
// keep hsv in sync
}
RGBtoHSV(baseColors[0]/255.0f, baseColors[1]/255.0f, baseColors[2]/255.0f, &g_hsv_h, &g_hsv_s, &g_hsv_v);
apply_smart_light();
sendColorChange();
if(CFG_HasFlag(OBK_FLAG_MQTT_BROADCASTLEDPARAMSTOGETHER)) {
LED_SendDimmerChange();
}
if(CFG_HasFlag(OBK_FLAG_MQTT_BROADCASTLEDFINALCOLOR)) {
sendFinalColor();
}
return 1;
// }
// return 0;
}
static int basecolor_rgb(const void *context, const char *cmd, const char *args, int cmdFlags){
return LED_SetBaseColor(context,cmd,args,0);
}
static int basecolor_rgbcw(const void *context, const char *cmd, const char *args, int cmdFlags){
return LED_SetBaseColor(context,cmd,args,1);
}
// CONFIG-ONLY command!
static int colorMult(const void *context, const char *cmd, const char *args, int cmdFlags){
ADDLOG_DEBUG(LOG_FEATURE_CMD, " g_cfg_colorScaleToChannel (%s) received with args %s",cmd,args);
g_cfg_colorScaleToChannel = atof(args);
return 1;
//}
//return 0;
}
// CONFIG-ONLY command!
static int brightnessMult(const void *context, const char *cmd, const char *args, int cmdFlags){
ADDLOG_DEBUG(LOG_FEATURE_CMD, " brightnessMult (%s) received with args %s",cmd,args);
g_cfg_brightnessMult = atof(args);
return 1;
//}
//return 0;
}
static void onHSVChanged() {
float r, g, b;
HSVtoRGB(&r,&g,&b, g_hsv_h,g_hsv_s,g_hsv_v);
baseColors[0] = r * 255.0f;
baseColors[1] = g * 255.0f;
baseColors[2] = b * 255.0f;
sendColorChange();
apply_smart_light();
if(CFG_HasFlag(OBK_FLAG_MQTT_BROADCASTLEDFINALCOLOR)) {
sendFinalColor();
}
}
static void led_setSaturation(float sat){
g_hsv_s = sat;
onHSVChanged();
}
static void led_setHue(float hue){
g_hsv_h = hue;
onHSVChanged();
}
static int nextColor(const void *context, const char *cmd, const char *args, int cmdFlags){
LED_NextColor();
return 1;
}
static int lerpSpeed(const void *context, const char *cmd, const char *args, int cmdFlags){
// Use tokenizer, so we can use variables (eg. $CH11 as variable)
Tokenizer_TokenizeString(args, 0);
led_lerpSpeedUnitsPerSecond = Tokenizer_GetArgFloat(0);
return 1;
}
static int setSaturation(const void *context, const char *cmd, const char *args, int cmdFlags){
float f;
// Use tokenizer, so we can use variables (eg. $CH11 as variable)
Tokenizer_TokenizeString(args, 0);
f = Tokenizer_GetArgFloat(0);
// input is in 0-100 range
f *= 0.01f;
led_setSaturation(f);
return 1;
}
float LED_GetSaturation() {
return g_hsv_s * 100.0f;
}
static int setHue(const void *context, const char *cmd, const char *args, int cmdFlags){
float f;
// Use tokenizer, so we can use variables (eg. $CH11 as variable)
Tokenizer_TokenizeString(args, 0);
f = Tokenizer_GetArgFloat(0);
led_setHue(f);
return 1;
}
float LED_GetHue() {
return g_hsv_h;
}
void NewLED_InitCommands(){
// set, but do not apply (force a refresh)
LED_SetTemperature(led_temperature_current,0);
//cmddetail:{"name":"led_dimmer","args":"",
//cmddetail:"descr":"set output dimmer 0..100",
//cmddetail:"fn":"dimmer","file":"cmnds/cmd_newLEDDriver.c","requires":"",
//cmddetail:"examples":""}
CMD_RegisterCommand("led_dimmer", "", dimmer, NULL, NULL);
//cmddetail:{"name":"add_dimmer","args":"",
//cmddetail:"descr":"set output dimmer 0..100",
//cmddetail:"fn":"add_dimmer","file":"cmnds/cmd_newLEDDriver.c","requires":"",
//cmddetail:"examples":""}
CMD_RegisterCommand("add_dimmer", "", add_dimmer, NULL, NULL);
//cmddetail:{"name":"led_enableAll","args":"",
//cmddetail:"descr":"qqqq",
//cmddetail:"fn":"enableAll","file":"cmnds/cmd_newLEDDriver.c","requires":"",
//cmddetail:"examples":""}
CMD_RegisterCommand("led_enableAll", "", enableAll, NULL, NULL);
//cmddetail:{"name":"led_basecolor_rgb","args":"",
//cmddetail:"descr":"set PWN color using #RRGGBB",
//cmddetail:"fn":"basecolor_rgb","file":"cmnds/cmd_newLEDDriver.c","requires":"",
//cmddetail:"examples":""}
CMD_RegisterCommand("led_basecolor_rgb", "", basecolor_rgb, NULL, NULL);
//cmddetail:{"name":"led_basecolor_rgbcw","args":"",
//cmddetail:"descr":"set PWN color using #RRGGBB[cw][ww]",
//cmddetail:"fn":"basecolor_rgbcw","file":"cmnds/cmd_newLEDDriver.c","requires":"",
//cmddetail:"examples":""}
CMD_RegisterCommand("led_basecolor_rgbcw", "", basecolor_rgbcw, NULL, NULL);
//cmddetail:{"name":"led_temperature","args":"",
//cmddetail:"descr":"set qqqq",
//cmddetail:"fn":"temperature","file":"cmnds/cmd_newLEDDriver.c","requires":"",
//cmddetail:"examples":""}
CMD_RegisterCommand("led_temperature", "", temperature, NULL, NULL);
//cmddetail:{"name":"led_brightnessMult","args":"",
//cmddetail:"descr":"set qqqq",
//cmddetail:"fn":"brightnessMult","file":"cmnds/cmd_newLEDDriver.c","requires":"",
//cmddetail:"examples":""}
CMD_RegisterCommand("led_brightnessMult", "", brightnessMult, NULL, NULL);
//cmddetail:{"name":"led_colorMult","args":"",
//cmddetail:"descr":"set qqqq",
//cmddetail:"fn":"colorMult","file":"cmnds/cmd_newLEDDriver.c","requires":"",
//cmddetail:"examples":""}
CMD_RegisterCommand("led_colorMult", "", colorMult, NULL, NULL);
//cmddetail:{"name":"led_saturation","args":"",
//cmddetail:"descr":"set qqqq",
//cmddetail:"fn":"setSaturation","file":"cmnds/cmd_newLEDDriver.c","requires":"",
//cmddetail:"examples":""}
CMD_RegisterCommand("led_saturation", "", setSaturation, NULL, NULL);
//cmddetail:{"name":"led_hue","args":"",
//cmddetail:"descr":"set qqqq",
//cmddetail:"fn":"setHue","file":"cmnds/cmd_newLEDDriver.c","requires":"",
//cmddetail:"examples":""}
CMD_RegisterCommand("led_hue", "", setHue, NULL, NULL);
//cmddetail:{"name":"led_nextColor","args":"",
//cmddetail:"descr":"set qqqq",
//cmddetail:"fn":"nextColor","file":"cmnds/cmd_newLEDDriver.c","requires":"",
//cmddetail:"examples":""}
CMD_RegisterCommand("led_nextColor", "", nextColor, NULL, NULL);
//cmddetail:{"name":"led_lerpSpeed","args":"",
//cmddetail:"descr":"set qqqq",
//cmddetail:"fn":"lerpSpeed","file":"cmnds/cmd_newLEDDriver.c","requires":"",
//cmddetail:"examples":""}
CMD_RegisterCommand("led_lerpSpeed", "", lerpSpeed, NULL, NULL);
}
void NewLED_RestoreSavedStateIfNeeded() {
if(CFG_HasFlag(OBK_FLAG_LED_REMEMBERLASTSTATE)) {
short brig;
short tmp;
byte rgb[3];
byte mod;
byte bEnableAll;
HAL_FlashVars_ReadLED(&mod, &brig, &tmp, rgb, &bEnableAll);
g_lightEnableAll = bEnableAll;
SET_LightMode(mod);
g_brightness = brig * g_cfg_brightnessMult;
LED_SetTemperature(tmp,0);
baseColors[0] = rgb[0];
baseColors[1] = rgb[1];
baseColors[2] = rgb[2];
apply_smart_light();
} else {
}
// "cmnd/obk8D38570E/led_dimmer_get""
}