mirror of https://github.com/arendst/Tasmota.git
Add Domoticz Selector for Fanspeed
Add support for iFan02 Fanspeed in Domoticz using a selector (#4517)
This commit is contained in:
parent
10483a40a6
commit
dfa0d2ef11
|
@ -3,6 +3,7 @@
|
||||||
* Add command SetOption60 0/1 to select dynamic sleep (0) or sleep (1) (#4497)
|
* Add command SetOption60 0/1 to select dynamic sleep (0) or sleep (1) (#4497)
|
||||||
* Update SR-04 driver to use NewPing library (#4488)
|
* Update SR-04 driver to use NewPing library (#4488)
|
||||||
* Add support for GPIO02 for newer Sonoff Basic (#4518)
|
* Add support for GPIO02 for newer Sonoff Basic (#4518)
|
||||||
|
* Add support for iFan02 Fanspeed in Domoticz using a selector (#4517)
|
||||||
*
|
*
|
||||||
* 6.3.0.14 20181127
|
* 6.3.0.14 20181127
|
||||||
* Add Command CalcRes to set number of decimals (0 - 7) used in commands ADD, SUB, MULT and SCALE (#4420)
|
* Add Command CalcRes to set number of decimals (0 - 7) used in commands ADD, SUB, MULT and SCALE (#4420)
|
||||||
|
|
|
@ -74,6 +74,8 @@ typedef unsigned long power_t; // Power (Relay) type
|
||||||
#define MAX_RULE_TIMERS 8 // Max number of rule timers (4 bytes / timer)
|
#define MAX_RULE_TIMERS 8 // Max number of rule timers (4 bytes / timer)
|
||||||
#define MAX_RULE_VARS 5 // Max number of rule variables (10 bytes / variable)
|
#define MAX_RULE_VARS 5 // Max number of rule variables (10 bytes / variable)
|
||||||
|
|
||||||
|
#define MAX_FAN_SPEED 4 // Max number of iFan02 fan speeds (0 .. 3)
|
||||||
|
|
||||||
#define MQTT_TOKEN_PREFIX "%prefix%" // To be substituted by mqtt_prefix[x]
|
#define MQTT_TOKEN_PREFIX "%prefix%" // To be substituted by mqtt_prefix[x]
|
||||||
#define MQTT_TOKEN_TOPIC "%topic%" // To be substituted by mqtt_topic, mqtt_grptopic, mqtt_buttontopic, mqtt_switchtopic
|
#define MQTT_TOKEN_TOPIC "%topic%" // To be substituted by mqtt_topic, mqtt_grptopic, mqtt_buttontopic, mqtt_switchtopic
|
||||||
#define MQTT_TOKEN_HOSTNAME "%hostname%" // To be substituted by mqtt_topic, mqtt_grptopic, mqtt_buttontopic, mqtt_switchtopic
|
#define MQTT_TOKEN_HOSTNAME "%hostname%" // To be substituted by mqtt_topic, mqtt_grptopic, mqtt_buttontopic, mqtt_switchtopic
|
||||||
|
@ -245,12 +247,14 @@ enum XsnsFunctions {FUNC_SETTINGS_OVERRIDE, FUNC_MODULE_INIT, FUNC_PRE_INIT, FUN
|
||||||
FUNC_RULES_PROCESS, FUNC_SERIAL, FUNC_FREE_MEM, FUNC_BUTTON_PRESSED,
|
FUNC_RULES_PROCESS, FUNC_SERIAL, FUNC_FREE_MEM, FUNC_BUTTON_PRESSED,
|
||||||
FUNC_WEB_ADD_BUTTON, FUNC_WEB_ADD_MAIN_BUTTON, FUNC_WEB_ADD_HANDLER};
|
FUNC_WEB_ADD_BUTTON, FUNC_WEB_ADD_MAIN_BUTTON, FUNC_WEB_ADD_HANDLER};
|
||||||
|
|
||||||
const uint8_t kDefaultRfCode[9] PROGMEM = { 0x21, 0x16, 0x01, 0x0E, 0x03, 0x48, 0x2E, 0x1A, 0x00 };
|
|
||||||
|
|
||||||
enum CommandSource { SRC_IGNORE, SRC_MQTT, SRC_RESTART, SRC_BUTTON, SRC_SWITCH, SRC_BACKLOG, SRC_SERIAL, SRC_WEBGUI, SRC_WEBCOMMAND, SRC_WEBCONSOLE, SRC_PULSETIMER,
|
enum CommandSource { SRC_IGNORE, SRC_MQTT, SRC_RESTART, SRC_BUTTON, SRC_SWITCH, SRC_BACKLOG, SRC_SERIAL, SRC_WEBGUI, SRC_WEBCOMMAND, SRC_WEBCONSOLE, SRC_PULSETIMER,
|
||||||
SRC_TIMER, SRC_RULE, SRC_MAXPOWER, SRC_MAXENERGY, SRC_LIGHT, SRC_KNX, SRC_DISPLAY, SRC_WEMO, SRC_HUE, SRC_RETRY, SRC_MAX };
|
SRC_TIMER, SRC_RULE, SRC_MAXPOWER, SRC_MAXENERGY, SRC_LIGHT, SRC_KNX, SRC_DISPLAY, SRC_WEMO, SRC_HUE, SRC_RETRY, SRC_MAX };
|
||||||
const char kCommandSource[] PROGMEM = "I|MQTT|Restart|Button|Switch|Backlog|Serial|WebGui|WebCommand|WebConsole|PulseTimer|Timer|Rule|MaxPower|MaxEnergy|Light|Knx|Display|Wemo|Hue|Retry";
|
const char kCommandSource[] PROGMEM = "I|MQTT|Restart|Button|Switch|Backlog|Serial|WebGui|WebCommand|WebConsole|PulseTimer|Timer|Rule|MaxPower|MaxEnergy|Light|Knx|Display|Wemo|Hue|Retry";
|
||||||
|
|
||||||
|
const uint8_t kDefaultRfCode[9] PROGMEM = { 0x21, 0x16, 0x01, 0x0E, 0x03, 0x48, 0x2E, 0x1A, 0x00 };
|
||||||
|
|
||||||
|
const uint8_t kIFan02Speed[MAX_FAN_SPEED][3] = {{6,6,6}, {7,6,6}, {7,7,6}, {7,6,7}}; // Do not use PROGMEM as it fails
|
||||||
|
|
||||||
/*********************************************************************************************\
|
/*********************************************************************************************\
|
||||||
* Extern global variables
|
* Extern global variables
|
||||||
\*********************************************************************************************/
|
\*********************************************************************************************/
|
||||||
|
|
|
@ -91,8 +91,6 @@ const char kTasmotaCommands[] PROGMEM =
|
||||||
|
|
||||||
const char kSleepMode[] PROGMEM = "Dynamic|Normal";
|
const char kSleepMode[] PROGMEM = "Dynamic|Normal";
|
||||||
|
|
||||||
const uint8_t kIFan02Speed[4][3] = {{6,6,6}, {7,6,6}, {7,7,6}, {7,6,7}};
|
|
||||||
|
|
||||||
// Global variables
|
// Global variables
|
||||||
SerialConfig serial_config = SERIAL_8N1; // Serial interface configuration 8 data bits, No parity, 1 stop bit
|
SerialConfig serial_config = SERIAL_8N1; // Serial interface configuration 8 data bits, No parity, 1 stop bit
|
||||||
|
|
||||||
|
@ -390,7 +388,7 @@ uint8_t GetFanspeed(void)
|
||||||
|
|
||||||
void SetFanspeed(uint8_t fanspeed)
|
void SetFanspeed(uint8_t fanspeed)
|
||||||
{
|
{
|
||||||
for (byte i = 0; i < 3; i++) {
|
for (byte i = 0; i < MAX_FAN_SPEED -1; i++) {
|
||||||
uint8_t state = kIFan02Speed[fanspeed][i];
|
uint8_t state = kIFan02Speed[fanspeed][i];
|
||||||
// uint8_t state = pgm_read_byte(kIFan02Speed +(speed *3) +i);
|
// uint8_t state = pgm_read_byte(kIFan02Speed +(speed *3) +i);
|
||||||
ExecuteCommandPower(i +2, state, SRC_IGNORE); // Use relay 2, 3 and 4
|
ExecuteCommandPower(i +2, state, SRC_IGNORE); // Use relay 2, 3 and 4
|
||||||
|
@ -566,14 +564,14 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len)
|
||||||
if (data_len > 0) {
|
if (data_len > 0) {
|
||||||
if ('-' == dataBuf[0]) {
|
if ('-' == dataBuf[0]) {
|
||||||
payload = (int16_t)GetFanspeed() -1;
|
payload = (int16_t)GetFanspeed() -1;
|
||||||
if (payload < 0) { payload = 3; }
|
if (payload < 0) { payload = MAX_FAN_SPEED -1; }
|
||||||
}
|
}
|
||||||
else if ('+' == dataBuf[0]) {
|
else if ('+' == dataBuf[0]) {
|
||||||
payload = GetFanspeed() +1;
|
payload = GetFanspeed() +1;
|
||||||
if (payload > 3) { payload = 0; }
|
if (payload > MAX_FAN_SPEED -1) { payload = 0; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((payload >= 0) && (payload <= 3) && (payload != GetFanspeed())) {
|
if ((payload >= 0) && (payload < MAX_FAN_SPEED) && (payload != GetFanspeed())) {
|
||||||
SetFanspeed(payload);
|
SetFanspeed(payload);
|
||||||
}
|
}
|
||||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, GetFanspeed());
|
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, GetFanspeed());
|
||||||
|
|
|
@ -628,7 +628,7 @@ void HandleRoot(void)
|
||||||
if (SONOFF_IFAN02 == Settings.module) {
|
if (SONOFF_IFAN02 == Settings.module) {
|
||||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_DEVICE_CONTROL, 36, 1, D_BUTTON_TOGGLE, "");
|
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_DEVICE_CONTROL, 36, 1, D_BUTTON_TOGGLE, "");
|
||||||
page += mqtt_data;
|
page += mqtt_data;
|
||||||
for (byte i = 0; i < 4; i++) {
|
for (byte i = 0; i < MAX_FAN_SPEED; i++) {
|
||||||
snprintf_P(stemp, sizeof(stemp), PSTR("%d"), i);
|
snprintf_P(stemp, sizeof(stemp), PSTR("%d"), i);
|
||||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_DEVICE_CONTROL, 16, i +2, stemp, "");
|
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_DEVICE_CONTROL, 16, i +2, stemp, "");
|
||||||
page += mqtt_data;
|
page += mqtt_data;
|
||||||
|
|
|
@ -334,7 +334,7 @@ void MqttPublishPowerState(byte device)
|
||||||
if ((device < 1) || (device > devices_present)) { device = 1; }
|
if ((device < 1) || (device > devices_present)) { device = 1; }
|
||||||
|
|
||||||
if ((SONOFF_IFAN02 == Settings.module) && (device > 1)) {
|
if ((SONOFF_IFAN02 == Settings.module) && (device > 1)) {
|
||||||
if (GetFanspeed() < 4) { // 4 occurs when fanspeed is 3 and RC button 2 is pressed
|
if (GetFanspeed() < MAX_FAN_SPEED) { // 4 occurs when fanspeed is 3 and RC button 2 is pressed
|
||||||
snprintf_P(scommand, sizeof(scommand), PSTR(D_CMND_FANSPEED));
|
snprintf_P(scommand, sizeof(scommand), PSTR(D_CMND_FANSPEED));
|
||||||
GetTopic_P(stopic, STAT, mqtt_topic, (Settings.flag.mqtt_response) ? scommand : S_RSLT_RESULT);
|
GetTopic_P(stopic, STAT, mqtt_topic, (Settings.flag.mqtt_response) ? scommand : S_RSLT_RESULT);
|
||||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, scommand, GetFanspeed());
|
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, scommand, GetFanspeed());
|
||||||
|
|
|
@ -73,17 +73,26 @@ int DomoticzRssiQuality(void)
|
||||||
|
|
||||||
void MqttPublishDomoticzPowerState(byte device)
|
void MqttPublishDomoticzPowerState(byte device)
|
||||||
{
|
{
|
||||||
char sdimmer[8];
|
char svalue[8]; // Dimmer or Fanspeed value
|
||||||
|
|
||||||
if ((device < 1) || (device > devices_present)) {
|
if (Settings.flag.mqtt_enabled) {
|
||||||
device = 1;
|
if ((device < 1) || (device > devices_present)) { device = 1; }
|
||||||
}
|
if ((SONOFF_IFAN02 == Settings.module) && Settings.domoticz_relay_idx[1] && (device > 1)) { // device (relay) 1 handled below
|
||||||
if (Settings.flag.mqtt_enabled && Settings.domoticz_relay_idx[device -1]) {
|
if (4 == device) { // Wait for device (relay) 4 to get valid GetFanspeed
|
||||||
snprintf_P(sdimmer, sizeof(sdimmer), PSTR("%d"), Settings.light_dimmer);
|
uint8_t fan_speed = GetFanspeed();
|
||||||
|
snprintf_P(svalue, sizeof(svalue), PSTR("%d"), (int)fan_speed * 10);
|
||||||
snprintf_P(mqtt_data, sizeof(mqtt_data), DOMOTICZ_MESSAGE,
|
snprintf_P(mqtt_data, sizeof(mqtt_data), DOMOTICZ_MESSAGE,
|
||||||
Settings.domoticz_relay_idx[device -1], (power & (1 << (device -1))) ? 1 : 0, (light_type) ? sdimmer : "", DomoticzBatteryQuality(), DomoticzRssiQuality());
|
Settings.domoticz_relay_idx[1], (0 == fan_speed) ? 0 : 2, svalue, DomoticzBatteryQuality(), DomoticzRssiQuality());
|
||||||
MqttPublish(domoticz_in_topic);
|
MqttPublish(domoticz_in_topic);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else if (Settings.domoticz_relay_idx[device -1]) {
|
||||||
|
snprintf_P(svalue, sizeof(svalue), PSTR("%d"), Settings.light_dimmer);
|
||||||
|
snprintf_P(mqtt_data, sizeof(mqtt_data), DOMOTICZ_MESSAGE,
|
||||||
|
Settings.domoticz_relay_idx[device -1], (power & (1 << (device -1))) ? 1 : 0, (light_type) ? svalue : "", DomoticzBatteryQuality(), DomoticzRssiQuality());
|
||||||
|
MqttPublish(domoticz_in_topic);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DomoticzUpdatePowerState(byte device)
|
void DomoticzUpdatePowerState(byte device)
|
||||||
|
@ -182,7 +191,18 @@ boolean DomoticzMqttData(void)
|
||||||
if (idx == Settings.domoticz_relay_idx[i]) {
|
if (idx == Settings.domoticz_relay_idx[i]) {
|
||||||
bool iscolordimmer = strcmp_P(domoticz["dtype"],PSTR("Color Switch")) == 0;
|
bool iscolordimmer = strcmp_P(domoticz["dtype"],PSTR("Color Switch")) == 0;
|
||||||
snprintf_P(stemp1, sizeof(stemp1), PSTR("%d"), i +1);
|
snprintf_P(stemp1, sizeof(stemp1), PSTR("%d"), i +1);
|
||||||
if (iscolordimmer && 10 == nvalue) { // Color_SetColor
|
if ((SONOFF_IFAN02 == Settings.module) && (1 == i)) { // Idx 2 is fanspeed
|
||||||
|
int16_t svalue = 0;
|
||||||
|
if (domoticz.containsKey("svalue1")) {
|
||||||
|
svalue = domoticz["svalue1"];
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_FANSPEED));
|
||||||
|
snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), (nvalue == 2) ? svalue / 10 : 0);
|
||||||
|
found = 1;
|
||||||
|
}
|
||||||
|
else if (iscolordimmer && 10 == nvalue) { // Color_SetColor
|
||||||
JsonObject& color = domoticz["Color"];
|
JsonObject& color = domoticz["Color"];
|
||||||
uint16_t level = nvalue = domoticz["svalue1"];
|
uint16_t level = nvalue = domoticz["svalue1"];
|
||||||
uint16_t r = color["r"]; r = r * level / 100;
|
uint16_t r = color["r"]; r = r * level / 100;
|
||||||
|
@ -193,7 +213,8 @@ boolean DomoticzMqttData(void)
|
||||||
snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_COLOR));
|
snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_COLOR));
|
||||||
snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%02x%02x%02x%02x%02x"), r, g, b, cw, ww);
|
snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%02x%02x%02x%02x%02x"), r, g, b, cw, ww);
|
||||||
found = 1;
|
found = 1;
|
||||||
} else if ((!iscolordimmer && 2 == nvalue) || // gswitch_sSetLevel
|
}
|
||||||
|
else if ((!iscolordimmer && 2 == nvalue) || // gswitch_sSetLevel
|
||||||
(iscolordimmer && 15 == nvalue)) { // Color_SetBrightnessLevel
|
(iscolordimmer && 15 == nvalue)) { // Color_SetBrightnessLevel
|
||||||
if (domoticz.containsKey("svalue1")) {
|
if (domoticz.containsKey("svalue1")) {
|
||||||
nvalue = domoticz["svalue1"];
|
nvalue = domoticz["svalue1"];
|
||||||
|
@ -206,7 +227,8 @@ boolean DomoticzMqttData(void)
|
||||||
snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_DIMMER));
|
snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_DIMMER));
|
||||||
snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), nvalue);
|
snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), nvalue);
|
||||||
found = 1;
|
found = 1;
|
||||||
} else if (1 == nvalue || 0 == nvalue) {
|
}
|
||||||
|
else if (1 == nvalue || 0 == nvalue) {
|
||||||
if (((power >> i) &1) == (power_t)nvalue) {
|
if (((power >> i) &1) == (power_t)nvalue) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -422,6 +444,7 @@ void HandleDomoticzConfiguration(void)
|
||||||
page.replace("{4", String((int)Settings.domoticz_switch_idx[i]));
|
page.replace("{4", String((int)Settings.domoticz_switch_idx[i]));
|
||||||
}
|
}
|
||||||
page.replace("{1", String(i +1));
|
page.replace("{1", String(i +1));
|
||||||
|
if ((SONOFF_IFAN02 == Settings.module) && (1 == i)) { break; }
|
||||||
}
|
}
|
||||||
for (int i = 0; i < DZ_MAX_SENSORS; i++) {
|
for (int i = 0; i < DZ_MAX_SENSORS; i++) {
|
||||||
page += FPSTR(HTTP_FORM_DOMOTICZ_SENSOR);
|
page += FPSTR(HTTP_FORM_DOMOTICZ_SENSOR);
|
||||||
|
|
Loading…
Reference in New Issue