mirror of https://github.com/arendst/Tasmota.git
Add Sonoff iFan02 support
Add support for Sonoff iFan02 as module 44 introducing command FanSpeed 0..3 (#2839)
This commit is contained in:
parent
8b7645b05d
commit
d3d876f030
|
@ -1,5 +1,5 @@
|
|||
/* 6.0.0b
|
||||
* Add initial support for Sonoff iFan02 - Module 44 - Command FanSpeed 0..3 - Webpage will only allow Toggle1 (#2839)
|
||||
* Add support for Sonoff iFan02 as module 44 introducing command FanSpeed 0..3 (#2839)
|
||||
* Add support for Sonoff S26 Smart Socket (#2808)
|
||||
* Add command SetOption30 to enforce Hass discovery as light group (#1784)
|
||||
* Add decimal values support for commands ADD, SUB, MULT and SCALE (#3083, #3089)
|
||||
|
|
|
@ -96,9 +96,7 @@ const char kTasmotaCommands[] PROGMEM =
|
|||
D_CMND_TELEPERIOD "|" D_CMND_RESTART "|" D_CMND_RESET "|" D_CMND_TIMEZONE "|" D_CMND_TIMESTD "|" D_CMND_TIMEDST "|" D_CMND_ALTITUDE "|" D_CMND_LEDPOWER "|" D_CMND_LEDSTATE "|"
|
||||
D_CMND_I2CSCAN "|" D_CMND_SERIALSEND "|" D_CMND_BAUDRATE "|" D_CMND_SERIALDELIMITER;
|
||||
|
||||
//const uint8_t kIFan02Speed[4][3] = {{0,0,0}, {1,0,0}, {1,1,0}, {1,0,1}};
|
||||
const uint8_t kIFan02Speed[4][3] = {{6,6,6}, {7,6,6}, {7,7,6}, {7,6,7}};
|
||||
//const uint8_t kIFan02Speed[4][3] = {{16,16,16}, {17,16,16}, {17,17,16}, {17,16,17}};
|
||||
|
||||
// Global variables
|
||||
unsigned long feature_drv1; // Compiled driver feature map
|
||||
|
@ -363,6 +361,23 @@ void SetLedPower(uint8_t state)
|
|||
digitalWrite(pin[GPIO_LED1], (bitRead(led_inverted, 0)) ? !state : state);
|
||||
}
|
||||
|
||||
uint8_t GetFanspeed()
|
||||
{
|
||||
uint8_t fanspeed = 0;
|
||||
|
||||
// if (SONOFF_IFAN02 == Settings.module) {
|
||||
/* Fanspeed is controlled by relay 2, 3 and 4 as in Sonoff 4CH.
|
||||
000x = 0
|
||||
001x = 1
|
||||
011x = 2
|
||||
101x = 3
|
||||
*/
|
||||
fanspeed = (uint8_t)(power &0xF) >> 1;
|
||||
if (fanspeed) { fanspeed = (fanspeed >> 1) +1; }
|
||||
// }
|
||||
return fanspeed;
|
||||
}
|
||||
|
||||
/********************************************************************************************/
|
||||
|
||||
void MqttDataHandler(char* topic, byte* data, unsigned int data_len)
|
||||
|
@ -507,17 +522,14 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len)
|
|||
return;
|
||||
}
|
||||
else if ((CMND_FANSPEED == command_code) && (SONOFF_IFAN02 == Settings.module)) {
|
||||
uint8_t fanspeed = (uint8_t)(power &0xF) >> 1;
|
||||
if (fanspeed) { fanspeed = (fanspeed >> 1) +1; }
|
||||
if ((payload >= 0) && (payload <= 3) && (payload != fanspeed)) {
|
||||
fanspeed = payload;
|
||||
if ((payload >= 0) && (payload <= 3) && (payload != GetFanspeed())) {
|
||||
for (byte i = 0; i < 3; i++) {
|
||||
uint8_t state = kIFan02Speed[fanspeed][i];
|
||||
// uint8_t state = pgm_read_byte(kIFan02Speed +(fanspeed *3) +i);
|
||||
ExecuteCommandPower(i +2, state, SRC_IGNORE);
|
||||
uint8_t state = kIFan02Speed[payload][i];
|
||||
// uint8_t state = pgm_read_byte(kIFan02Speed +(payload *3) +i);
|
||||
ExecuteCommandPower(i +2, state, SRC_IGNORE); // Use relay 2, 3 and 4
|
||||
}
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, fanspeed);
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, GetFanspeed());
|
||||
}
|
||||
else if (CMND_STATUS == command_code) {
|
||||
if ((payload < 0) || (payload > MAX_STATUS)) payload = 99;
|
||||
|
@ -1207,20 +1219,14 @@ void ExecuteCommandPower(byte device, byte state, int source)
|
|||
|
||||
// ShowSource(source);
|
||||
|
||||
/*
|
||||
if (SONOFF_IFAN02 == Settings.module) {
|
||||
if (state > 15) { // Only allow Fanspeed control over relay 2..4
|
||||
state -= 10;
|
||||
blink_mask &= 1;
|
||||
Settings.flag.interlock = 0;
|
||||
Settings.pulse_timer[1] = 0;
|
||||
blink_mask &= 1; // No blinking on the fan relays
|
||||
Settings.flag.interlock = 0; // No interlock mode as it is already done by the microcontroller
|
||||
Settings.pulse_timer[1] = 0; // No pulsetimers on the fan relays
|
||||
Settings.pulse_timer[2] = 0;
|
||||
Settings.pulse_timer[3] = 0;
|
||||
} else {
|
||||
device = 1; // Only allow user control over light
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
uint8_t publish_power = 1;
|
||||
if ((POWER_OFF_NO_STATE == state) || (POWER_ON_NO_STATE == state)) {
|
||||
state &= 1;
|
||||
|
@ -1447,6 +1453,10 @@ void MqttShowState()
|
|||
LightState(1);
|
||||
} else {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":\"%s\""), mqtt_data, GetPowerDevice(stemp1, i +1, sizeof(stemp1), Settings.flag.device_index_enable), GetStateText(bitRead(power, i)));
|
||||
if (SONOFF_IFAN02 == Settings.module) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_CMND_FANSPEED "\":%d"), mqtt_data, GetFanspeed());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1521,6 +1531,7 @@ void PerformEverySecond()
|
|||
if (!status_update_timer) {
|
||||
for (byte i = 1; i <= devices_present; i++) {
|
||||
MqttPublishPowerState(i);
|
||||
if (SONOFF_IFAN02 == Settings.module) { break; } // Only report status of light relay
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -838,20 +838,20 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
|
|||
0, 0, 0, 0
|
||||
},
|
||||
{ "Sonoff iFan02", // Sonoff iFan02 (ESP8285)
|
||||
GPIO_KEY1, // GPIO00 Virtual button 1
|
||||
GPIO_KEY1, // GPIO00 Virtual button 1 as feedback from RC
|
||||
GPIO_USER, // GPIO01 Serial RXD and Optional sensor
|
||||
0, // GPIO02 Optional sensor
|
||||
GPIO_USER, // GPIO03 Serial TXD and Optional sensor
|
||||
GPIO_REL3, // GPIO04 Relay 3 (0 = Off, 1 = On)
|
||||
GPIO_REL2, // GPIO05 Relay 2 (0 = Off, 1 = On)
|
||||
GPIO_REL3, // GPIO04 Relay 3 (0 = Off, 1 = On) controlling the fan
|
||||
GPIO_REL2, // GPIO05 Relay 2 (0 = Off, 1 = On) controlling the fan
|
||||
0, 0, 0, // Flash connection
|
||||
GPIO_KEY2, // GPIO09 Virtual button 2
|
||||
GPIO_KEY3, // GPIO10 Virtual button 3
|
||||
GPIO_KEY2, // GPIO09 Virtual button 2 as feedback from RC
|
||||
GPIO_KEY3, // GPIO10 Virtual button 3 as feedback from RC
|
||||
0, // Flash connection
|
||||
GPIO_REL1, // GPIO12 Relay 1 (0 = Off, 1 = On)
|
||||
GPIO_REL1, // GPIO12 Relay 1 (0 = Off, 1 = On) controlling the light
|
||||
GPIO_LED1_INV, // GPIO13 Blue Led on PCA (0 = On, 1 = Off)
|
||||
GPIO_KEY4, // GPIO14 Virtual button 4
|
||||
GPIO_REL4, // GPIO15 Relay 4 (0 = Off, 1 = On)
|
||||
GPIO_KEY4, // GPIO14 Virtual button 4 as feedback from RC
|
||||
GPIO_REL4, // GPIO15 Relay 4 (0 = Off, 1 = On) controlling the fan
|
||||
0, 0
|
||||
}
|
||||
};
|
||||
|
|
|
@ -283,8 +283,16 @@ void MqttPublishPowerState(byte device)
|
|||
char scommand[33];
|
||||
|
||||
if ((device < 1) || (device > devices_present)) { device = 1; }
|
||||
GetPowerDevice(scommand, device, sizeof(scommand), Settings.flag.device_index_enable);
|
||||
|
||||
if ((SONOFF_IFAN02 == Settings.module) && (device > 1)) { // Do not report status of fan relays
|
||||
if (GetFanspeed() < 4) {
|
||||
snprintf_P(scommand, sizeof(scommand), PSTR(D_CMND_FANSPEED));
|
||||
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());
|
||||
MqttPublish(stopic);
|
||||
}
|
||||
} else {
|
||||
GetPowerDevice(scommand, device, sizeof(scommand), Settings.flag.device_index_enable);
|
||||
GetTopic_P(stopic, STAT, mqtt_topic, (Settings.flag.mqtt_response) ? scommand : S_RSLT_RESULT);
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, scommand, GetStateText(bitRead(power, device -1)));
|
||||
MqttPublish(stopic);
|
||||
|
@ -293,6 +301,7 @@ void MqttPublishPowerState(byte device)
|
|||
snprintf_P(mqtt_data, sizeof(mqtt_data), GetStateText(bitRead(power, device -1)));
|
||||
MqttPublish(stopic, Settings.flag.mqtt_power_retain);
|
||||
}
|
||||
}
|
||||
|
||||
void MqttPublishPowerBlinkState(byte device)
|
||||
{
|
||||
|
|
|
@ -313,6 +313,9 @@ const char HTTP_END[] PROGMEM =
|
|||
"</body>"
|
||||
"</html>";
|
||||
|
||||
const char HTTP_DEVICE_CONTROL[] PROGMEM = "<td style='width:%d%%'><button onclick='la(\"?o=%d\");'>%s%s</button></td>";
|
||||
const char HTTP_DEVICE_STATE[] PROGMEM = "%s<td style='width:%d{c}%s;font-size:%dpx'>%s</div></td>"; // {c} = %'><div style='text-align:center;font-weight:
|
||||
|
||||
const char HDR_CTYPE_PLAIN[] PROGMEM = "text/plain";
|
||||
const char HDR_CTYPE_HTML[] PROGMEM = "text/html";
|
||||
const char HDR_CTYPE_XML[] PROGMEM = "text/xml";
|
||||
|
@ -553,12 +556,22 @@ void HandleRoot()
|
|||
}
|
||||
page += FPSTR(HTTP_TABLE100);
|
||||
page += F("<tr>");
|
||||
if (SONOFF_IFAN02 == Settings.module) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_DEVICE_CONTROL, 36, 1, D_BUTTON_TOGGLE, "");
|
||||
page += mqtt_data;
|
||||
for (byte i = 0; i < 4; i++) {
|
||||
snprintf_P(stemp, sizeof(stemp), PSTR("%d"), i);
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_DEVICE_CONTROL, 16, i +2, stemp, "");
|
||||
page += mqtt_data;
|
||||
}
|
||||
} else {
|
||||
for (byte idx = 1; idx <= devices_present; idx++) {
|
||||
snprintf_P(stemp, sizeof(stemp), PSTR(" %d"), idx);
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("<td style='width:%d%'><button onclick='la(\"?o=%d\");'>%s%s</button></td>"),
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_DEVICE_CONTROL,
|
||||
100 / devices_present, idx, (devices_present < 5) ? D_BUTTON_TOGGLE : "", (devices_present > 1) ? stemp : "");
|
||||
page += mqtt_data;
|
||||
}
|
||||
}
|
||||
page += F("</tr></table>");
|
||||
}
|
||||
if (SONOFF_BRIDGE == Settings.module) {
|
||||
|
@ -592,10 +605,16 @@ void HandleAjaxStatusRefresh()
|
|||
WebGetArg("o", tmp, sizeof(tmp));
|
||||
if (strlen(tmp)) {
|
||||
ShowWebSource(SRC_WEBGUI);
|
||||
if (SONOFF_IFAN02 == Settings.module) { // QandD
|
||||
uint8_t device = atoi(tmp);
|
||||
if (SONOFF_IFAN02 == Settings.module) {
|
||||
if (device < 2) {
|
||||
ExecuteCommandPower(1, POWER_TOGGLE, SRC_IGNORE);
|
||||
} else {
|
||||
ExecuteCommandPower(atoi(tmp), POWER_TOGGLE, SRC_IGNORE);
|
||||
snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_FANSPEED " %d"), device -2);
|
||||
ExecuteCommand(svalue, SRC_WEBGUI);
|
||||
}
|
||||
} else {
|
||||
ExecuteCommandPower(device, POWER_TOGGLE, SRC_IGNORE);
|
||||
}
|
||||
}
|
||||
WebGetArg("d", tmp, sizeof(tmp));
|
||||
|
@ -627,11 +646,20 @@ void HandleAjaxStatusRefresh()
|
|||
if (devices_present) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s{t}<tr>"), mqtt_data);
|
||||
uint8_t fsize = (devices_present < 5) ? 70 - (devices_present * 8) : 32;
|
||||
if (SONOFF_IFAN02 == Settings.module) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_DEVICE_STATE,
|
||||
mqtt_data, 36, (bitRead(power, 0)) ? "bold" : "normal", 54, GetStateText(bitRead(power, 0)));
|
||||
uint8_t fanspeed = GetFanspeed();
|
||||
snprintf_P(svalue, sizeof(svalue), PSTR("%d"), fanspeed);
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_DEVICE_STATE,
|
||||
mqtt_data, 64, (fanspeed) ? "bold" : "normal", 54, (fanspeed) ? svalue : GetStateText(0));
|
||||
} else {
|
||||
for (byte idx = 1; idx <= devices_present; idx++) {
|
||||
snprintf_P(svalue, sizeof(svalue), PSTR("%d"), bitRead(power, idx -1));
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s<td style='width:%d{c}%s;font-size:%dpx'>%s</div></td>"), // {c} = %'><div style='text-align:center;font-weight:
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_DEVICE_STATE,
|
||||
mqtt_data, 100 / devices_present, (bitRead(power, idx -1)) ? "bold" : "normal", fsize, (devices_present < 5) ? GetStateText(bitRead(power, idx -1)) : svalue);
|
||||
}
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s</tr></table>"), mqtt_data);
|
||||
}
|
||||
WebServer->send(200, FPSTR(HDR_CTYPE_HTML), mqtt_data);
|
||||
|
|
Loading…
Reference in New Issue