mirror of
https://github.com/openshwprojects/OpenBK7231T_App.git
synced 2026-03-12 18:29:05 +01:00
449 lines
11 KiB
C
449 lines
11 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 "../rgb2hsv.h"
|
|
#include <ctype.h>
|
|
#include "cmd_local.h"
|
|
#include "../mqtt/new_mqtt.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 };
|
|
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 = 1;
|
|
// 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 = 0;
|
|
|
|
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_HasChannelPinWithRole(0, IOR_PWM)) {
|
|
firstChannelIndex = 0;
|
|
} else {
|
|
firstChannelIndex = 1;
|
|
}
|
|
|
|
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);
|
|
|
|
CHANNEL_Set(channelToUse, final * g_cfg_colorScaleToChannel, CHANNEL_SET_FLAG_SKIP_MQTT);
|
|
}
|
|
if(DRV_IsRunning("SM2135")) {
|
|
SM2135_Write(finalRGBCW);
|
|
}
|
|
}
|
|
static void sendColorChange() {
|
|
char s[16];
|
|
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]);
|
|
|
|
MQTT_PublishMain_StringString("led_basecolor_rgb",s);
|
|
}
|
|
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];
|
|
|
|
c[0] = (byte)(finalColors[0]);
|
|
c[1] = (byte)(finalColors[1]);
|
|
c[2] = (byte)(finalColors[2]);
|
|
|
|
sprintf(s,"%02X%02X%02X",c[0],c[1],c[2]);
|
|
|
|
MQTT_PublishMain_StringString("led_finalcolor_rgb",s);
|
|
}
|
|
static void sendDimmerChange() {
|
|
int iValue;
|
|
|
|
iValue = g_brightness / g_cfg_brightnessMult;
|
|
|
|
MQTT_PublishMain_StringInt("led_dimmer", iValue);
|
|
}
|
|
static void sendTemperatureChange(){
|
|
MQTT_PublishMain_StringInt("led_temperature", (int)led_temperature_current);
|
|
}
|
|
float LED_GetTemperature() {
|
|
return led_temperature_current;
|
|
}
|
|
int LED_GetMode() {
|
|
return g_lightMode;
|
|
}
|
|
|
|
void LED_SetTemperature(int tmpInteger, bool bApply) {
|
|
float f;
|
|
|
|
led_temperature_current = tmpInteger;
|
|
|
|
f = (tmpInteger - led_temperature_min);
|
|
f = f / (led_temperature_max - led_temperature_min);
|
|
if(f<0)
|
|
f = 0;
|
|
if(f>1)
|
|
f =1;
|
|
|
|
/// ADDLOG_INFO(LOG_FEATURE_CMD, "tasCmnd temperature frac %f",f);
|
|
|
|
baseColors[3] = (255.0f) * (1-f);
|
|
baseColors[4] = (255.0f) * f;
|
|
|
|
if(bApply) {
|
|
g_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_INFO(LOG_FEATURE_CMD, " temperature (%s) received with args %s",cmd,args);
|
|
|
|
|
|
tmp = atoi(args);
|
|
|
|
LED_SetTemperature(tmp, 1);
|
|
|
|
return 1;
|
|
//}
|
|
//return 0;
|
|
}
|
|
void LED_SetEnableAll(int bEnable) {
|
|
g_lightEnableAll = bEnable;
|
|
|
|
apply_smart_light();
|
|
|
|
DRV_DGR_OnLedEnableAllChange(bEnable);
|
|
|
|
MQTT_PublishMain_StringInt("led_enableAll",g_lightEnableAll);
|
|
}
|
|
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_INFO(LOG_FEATURE_CMD, " enableAll (%s) received with args %s",cmd,args);
|
|
|
|
bEnable = parsePowerArgument(args);
|
|
|
|
LED_SetEnableAll(bEnable);
|
|
|
|
|
|
// sendColorChange();
|
|
// sendDimmerChange();
|
|
// sendTemperatureChange();
|
|
|
|
return 1;
|
|
//}
|
|
//return 0;
|
|
}
|
|
float LED_GetDimmer() {
|
|
return g_brightness / g_cfg_brightnessMult;
|
|
}
|
|
void LED_SetDimmer(int iVal) {
|
|
|
|
g_brightness = iVal * g_cfg_brightnessMult;
|
|
|
|
DRV_DGR_OnLedDimmerChange(iVal);
|
|
|
|
apply_smart_light();
|
|
sendDimmerChange();
|
|
if(CFG_HasFlag(OBK_FLAG_MQTT_BROADCASTLEDPARAMSTOGETHER)) {
|
|
sendColorChange();
|
|
}
|
|
if(CFG_HasFlag(OBK_FLAG_MQTT_BROADCASTLEDFINALCOLOR)) {
|
|
sendFinalColor();
|
|
}
|
|
|
|
}
|
|
static int dimmer(const void *context, const char *cmd, const char *args, int cmdFlags){
|
|
//if (!wal_strnicmp(cmd, "POWERALL", 8)){
|
|
int iVal = 0;
|
|
|
|
ADDLOG_INFO(LOG_FEATURE_CMD, " dimmer (%s) received with args %s",cmd,args);
|
|
|
|
iVal = parsePowerArgument(args);
|
|
|
|
LED_SetDimmer(iVal);
|
|
|
|
return 1;
|
|
//}
|
|
//return 0;
|
|
}
|
|
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) {
|
|
g_lightMode = Light_All;
|
|
} else {
|
|
g_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){
|
|
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)) {
|
|
sendDimmerChange();
|
|
}
|
|
if(CFG_HasFlag(OBK_FLAG_MQTT_BROADCASTLEDFINALCOLOR)) {
|
|
sendFinalColor();
|
|
}
|
|
|
|
|
|
if (!(*c)){
|
|
ADDLOG_DEBUG(LOG_FEATURE_CMD, "BASECOLOR arg ended");
|
|
}
|
|
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_INFO(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_INFO(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 setSaturation(const void *context, const char *cmd, const char *args, int cmdFlags){
|
|
float f;
|
|
|
|
f = atof(args);
|
|
|
|
// input is in 0-100 range
|
|
f *= 0.01f;
|
|
|
|
led_setSaturation(f);
|
|
|
|
return 1;
|
|
}
|
|
static int setHue(const void *context, const char *cmd, const char *args, int cmdFlags){
|
|
float f;
|
|
|
|
f = atof(args);
|
|
|
|
led_setHue(f);
|
|
|
|
return 1;
|
|
}
|
|
|
|
int NewLED_InitCommands(){
|
|
CMD_RegisterCommand("led_dimmer", "", dimmer, "set output dimmer 0..100", NULL);
|
|
CMD_RegisterCommand("led_enableAll", "", enableAll, "qqqq", NULL);
|
|
CMD_RegisterCommand("led_basecolor_rgb", "", basecolor_rgb, "set PWN color using #RRGGBB", NULL);
|
|
CMD_RegisterCommand("led_basecolor_rgbcw", "", basecolor_rgbcw, "set PWN color using #RRGGBB[cw][ww]", NULL);
|
|
CMD_RegisterCommand("led_temperature", "", temperature, "set qqqq", NULL);
|
|
CMD_RegisterCommand("led_brightnessMult", "", brightnessMult, "set qqqq", NULL);
|
|
CMD_RegisterCommand("led_colorMult", "", colorMult, "set qqqq", NULL);
|
|
CMD_RegisterCommand("led_saturation", "", setSaturation, "set qqqq", NULL);
|
|
CMD_RegisterCommand("led_hue", "", setHue, "set qqqq", NULL);
|
|
|
|
// set, but do not apply
|
|
LED_SetTemperature(250,0);
|
|
|
|
// "cmnd/obk8D38570E/led_dimmer_get""
|
|
return 0;
|
|
}
|