Refactor Sonoff Bridge

Refactor Sonoff Bridge
This commit is contained in:
Theo Arends 2019-08-13 16:10:47 +02:00
parent 72baffdf81
commit e2040b70de
5 changed files with 95 additions and 124 deletions

View File

@ -394,6 +394,7 @@ struct TIME_T {
struct XDRVMAILBOX {
bool grpflg;
bool usridx;
uint16_t command_code;
uint32_t index;
uint32_t data_len;
int32_t payload;

View File

@ -1327,11 +1327,6 @@ void GpioInit(void)
}
#endif // USE_LIGHT
if (SONOFF_BRIDGE == my_module_type) {
Settings.flag.mqtt_serial = 0;
baudrate = 19200;
}
if (XdrvCall(FUNC_MODULE_INIT)) {
// Serviced
}

View File

@ -738,16 +738,15 @@ int GetCommandCode(char* destination, size_t destination_size, const char* needl
bool DecodeCommand(const char* haystack, void (* const MyCommand[])(void))
{
bool result = false;
GetTextIndexed(XdrvMailbox.command, CMDSZ, 0, haystack); // Get prefix if available
int prefix_length = strlen(XdrvMailbox.command);
int command_code = GetCommandCode(XdrvMailbox.command + prefix_length, CMDSZ, XdrvMailbox.topic + prefix_length, haystack);
if (command_code > 0) { // Skip prefix
MyCommand[command_code -1]();
result = true;
XdrvMailbox.command_code = command_code -1;
MyCommand[XdrvMailbox.command_code]();
return true;
}
return result;
return false;
}
int GetStateNumber(char *state_text)

View File

@ -25,23 +25,26 @@
const uint32_t SFB_TIME_AVOID_DUPLICATE = 2000; // Milliseconds
enum SonoffBridgeCommands { CMND_RFSYNC, CMND_RFLOW, CMND_RFHIGH, CMND_RFHOST, CMND_RFCODE };
enum SonoffBridgeCommands {
CMND_RFSYNC, CMND_RFLOW, CMND_RFHIGH, CMND_RFHOST, CMND_RFCODE };
const char kSonoffBridgeCommands[] PROGMEM = "|" // No prefix
D_CMND_RFSYNC "|" D_CMND_RFLOW "|" D_CMND_RFHIGH "|" D_CMND_RFHOST "|" D_CMND_RFCODE "|" D_CMND_RFKEY "|" D_CMND_RFRAW;
void (* const SonoffBridgeCommand[])(void) PROGMEM = {
&CmndRfSync, &CmndRfLow, &CmndRfHigh, &CmndRfHost, &CmndRfCode, &CmndRfKey, &CmndRfRaw };
&CmndRfBridge, &CmndRfBridge, &CmndRfBridge, &CmndRfBridge, &CmndRfBridge, &CmndRfKey, &CmndRfRaw };
uint8_t sonoff_bridge_receive_flag = 0;
uint8_t sonoff_bridge_receive_raw_flag = 0;
uint8_t sonoff_bridge_learn_key = 1;
uint8_t sonoff_bridge_learn_active = 0;
uint8_t sonoff_bridge_expected_bytes = 0;
uint32_t sonoff_bridge_last_received_id = 0;
uint32_t sonoff_bridge_last_send_code = 0;
unsigned long sonoff_bridge_last_time = 0;
unsigned long sonoff_bridge_last_learn_time = 0;
struct SONOFFBRIDGE {
uint32_t last_received_id = 0;
uint32_t last_send_code = 0;
uint32_t last_time = 0;
uint32_t last_learn_time = 0;
uint8_t receive_flag = 0;
uint8_t receive_raw_flag = 0;
uint8_t learn_key = 1;
uint8_t learn_active = 0;
uint8_t expected_bytes = 0;
} SnfBridge;
#ifdef USE_RF_FLASH
/*********************************************************************************************\
@ -230,8 +233,8 @@ void SonoffBridgeReceivedRaw(void)
void SonoffBridgeLearnFailed(void)
{
sonoff_bridge_learn_active = 0;
Response_P(S_JSON_COMMAND_INDEX_SVALUE, D_CMND_RFKEY, sonoff_bridge_learn_key, D_JSON_LEARN_FAILED);
SnfBridge.learn_active = 0;
Response_P(S_JSON_COMMAND_INDEX_SVALUE, D_CMND_RFKEY, SnfBridge.learn_key, D_JSON_LEARN_FAILED);
MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_RFKEY));
}
@ -250,21 +253,21 @@ void SonoffBridgeReceived(void)
SonoffBridgeLearnFailed();
}
else if (0xA3 == serial_in_buffer[0]) { // Learned A3 20 F8 01 18 03 3E 2E 1A 22 55
sonoff_bridge_learn_active = 0;
SnfBridge.learn_active = 0;
low_time = serial_in_buffer[3] << 8 | serial_in_buffer[4]; // Low time in uSec
high_time = serial_in_buffer[5] << 8 | serial_in_buffer[6]; // High time in uSec
if (low_time && high_time) {
for (uint32_t i = 0; i < 9; i++) {
Settings.rf_code[sonoff_bridge_learn_key][i] = serial_in_buffer[i +1];
Settings.rf_code[SnfBridge.learn_key][i] = serial_in_buffer[i +1];
}
Response_P(S_JSON_COMMAND_INDEX_SVALUE, D_CMND_RFKEY, sonoff_bridge_learn_key, D_JSON_LEARNED);
Response_P(S_JSON_COMMAND_INDEX_SVALUE, D_CMND_RFKEY, SnfBridge.learn_key, D_JSON_LEARNED);
MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_RFKEY));
} else {
SonoffBridgeLearnFailed();
}
}
else if (0xA4 == serial_in_buffer[0]) { // Received RF data A4 20 EE 01 18 03 3E 2E 1A 22 55
if (sonoff_bridge_learn_active) {
if (SnfBridge.learn_active) {
SonoffBridgeLearnFailed();
} else {
sync_time = serial_in_buffer[1] << 8 | serial_in_buffer[2]; // Sync time in uSec
@ -273,9 +276,9 @@ void SonoffBridgeReceived(void)
received_id = serial_in_buffer[7] << 16 | serial_in_buffer[8] << 8 | serial_in_buffer[9];
unsigned long now = millis();
if (!((received_id == sonoff_bridge_last_received_id) && (now - sonoff_bridge_last_time < SFB_TIME_AVOID_DUPLICATE))) {
sonoff_bridge_last_received_id = received_id;
sonoff_bridge_last_time = now;
if (!((received_id == SnfBridge.last_received_id) && (now - SnfBridge.last_time < SFB_TIME_AVOID_DUPLICATE))) {
SnfBridge.last_received_id = received_id;
SnfBridge.last_time = now;
strncpy_P(rfkey, PSTR("\"" D_JSON_NONE "\""), sizeof(rfkey));
for (uint32_t i = 1; i <= 16; i++) {
if (Settings.rf_code[i][0]) {
@ -308,8 +311,8 @@ bool SonoffBridgeSerialInput(void)
// iTead Rf Universal Transceiver Module Serial Protocol Version 1.0 (20170420)
static int8_t receive_len = 0;
if (sonoff_bridge_receive_flag) {
if (sonoff_bridge_receive_raw_flag) {
if (SnfBridge.receive_flag) {
if (SnfBridge.receive_raw_flag) {
if (!serial_in_byte_counter) {
serial_in_buffer[serial_in_byte_counter++] = 0xAA;
}
@ -321,26 +324,26 @@ bool SonoffBridgeSerialInput(void)
}
if ((!receive_len && (0x55 == serial_in_byte)) || (receive_len && (serial_in_byte_counter == receive_len))) { // 0x55 - End of text
SonoffBridgeReceivedRaw();
sonoff_bridge_receive_flag = 0;
SnfBridge.receive_flag = 0;
return 1;
}
}
else if (!((0 == serial_in_byte_counter) && (0 == serial_in_byte))) { // Skip leading 0
if (0 == serial_in_byte_counter) {
sonoff_bridge_expected_bytes = 2; // 0xA0, 0xA1, 0xA2
SnfBridge.expected_bytes = 2; // 0xA0, 0xA1, 0xA2
if (serial_in_byte >= 0xA3) {
sonoff_bridge_expected_bytes = 11; // 0xA3, 0xA4, 0xA5
SnfBridge.expected_bytes = 11; // 0xA3, 0xA4, 0xA5
}
if (serial_in_byte == 0xA6) {
sonoff_bridge_expected_bytes = 0; // 0xA6 and up supported by Portisch firmware only
SnfBridge.expected_bytes = 0; // 0xA6 and up supported by Portisch firmware only
serial_in_buffer[serial_in_byte_counter++] = 0xAA;
sonoff_bridge_receive_raw_flag = 1;
SnfBridge.receive_raw_flag = 1;
}
}
serial_in_buffer[serial_in_byte_counter++] = serial_in_byte;
if ((sonoff_bridge_expected_bytes == serial_in_byte_counter) && (0x55 == serial_in_byte)) { // 0x55 - End of text
if ((SnfBridge.expected_bytes == serial_in_byte_counter) && (0x55 == serial_in_byte)) { // 0x55 - End of text
SonoffBridgeReceived();
sonoff_bridge_receive_flag = 0;
SnfBridge.receive_flag = 0;
return 1;
}
}
@ -349,7 +352,7 @@ bool SonoffBridgeSerialInput(void)
if (0xAA == serial_in_byte) { // 0xAA - Start of text
serial_in_byte_counter = 0;
serial_in_byte = 0;
sonoff_bridge_receive_flag = 1;
SnfBridge.receive_flag = 1;
receive_len = 0;
}
return 0;
@ -409,9 +412,9 @@ void SonoffBridgeSend(uint8_t idx, uint8_t key)
void SonoffBridgeLearn(uint8_t key)
{
sonoff_bridge_learn_key = key;
sonoff_bridge_learn_active = 1;
sonoff_bridge_last_learn_time = millis();
SnfBridge.learn_key = key;
SnfBridge.learn_active = 1;
SnfBridge.last_learn_time = millis();
Serial.write(0xAA); // Start of Text
Serial.write(0xA1); // Start learning
Serial.write(0x55); // End of Text
@ -421,14 +424,14 @@ void SonoffBridgeLearn(uint8_t key)
* Commands
\*********************************************************************************************/
void SonoffBridgeCmnd(uint32_t command_code) // RfSync, RfLow, RfHigh, RfHost and RfCode
void CmndRfBridge() // RfSync, RfLow, RfHigh, RfHost and RfCode
{
char *p;
char stemp [10];
uint32_t code = 0;
uint8_t radix = 10;
uint32_t set_index = command_code *2;
uint32_t set_index = XdrvMailbox.command_code *2;
if (XdrvMailbox.data[0] == '#') {
XdrvMailbox.data++;
@ -439,8 +442,8 @@ void SonoffBridgeCmnd(uint32_t command_code) // RfSync, RfLow, RfHigh, RfHost a
if (XdrvMailbox.data_len) {
code = strtol(XdrvMailbox.data, &p, radix);
if (code) {
if (CMND_RFCODE == command_code) {
sonoff_bridge_last_send_code = code;
if (CMND_RFCODE == XdrvMailbox.command_code) {
SnfBridge.last_send_code = code;
SonoffBridgeSendCode(code);
} else {
if (1 == XdrvMailbox.payload) {
@ -455,8 +458,8 @@ void SonoffBridgeCmnd(uint32_t command_code) // RfSync, RfLow, RfHigh, RfHost a
}
}
}
if (CMND_RFCODE == command_code) {
code = sonoff_bridge_last_send_code;
if (CMND_RFCODE == XdrvMailbox.command_code) {
code = SnfBridge.last_send_code;
} else {
code = Settings.rf_code[0][set_index] << 8 | Settings.rf_code[0][set_index +1];
}
@ -468,37 +471,12 @@ void SonoffBridgeCmnd(uint32_t command_code) // RfSync, RfLow, RfHigh, RfHost a
Response_P(S_JSON_COMMAND_XVALUE, XdrvMailbox.command, stemp);
}
void CmndRfSync(void)
{
SonoffBridgeCmnd(CMND_RFSYNC);
}
void CmndRfLow(void)
{
SonoffBridgeCmnd(CMND_RFLOW);
}
void CmndRfHigh(void)
{
SonoffBridgeCmnd(CMND_RFHIGH);
}
void CmndRfHost(void)
{
SonoffBridgeCmnd(CMND_RFHOST);
}
void CmndRfCode(void)
{
SonoffBridgeCmnd(CMND_RFCODE);
}
void CmndRfKey(void)
{
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 16)) {
unsigned long now = millis();
if ((!sonoff_bridge_learn_active) || (now - sonoff_bridge_last_learn_time > 60100)) {
sonoff_bridge_learn_active = 0;
if ((!SnfBridge.learn_active) || (now - SnfBridge.last_learn_time > 60100)) {
SnfBridge.learn_active = 0;
if (2 == XdrvMailbox.payload) { // Learn RF data
SonoffBridgeLearn(XdrvMailbox.index);
ResponseCmndIdxChar(D_JSON_START_LEARNING);
@ -511,9 +489,9 @@ void CmndRfKey(void)
for (uint32_t i = 0; i < 6; i++) {
Settings.rf_code[XdrvMailbox.index][i] = Settings.rf_code[0][i];
}
Settings.rf_code[XdrvMailbox.index][6] = (sonoff_bridge_last_send_code >> 16) & 0xff;
Settings.rf_code[XdrvMailbox.index][7] = (sonoff_bridge_last_send_code >> 8) & 0xff;
Settings.rf_code[XdrvMailbox.index][8] = sonoff_bridge_last_send_code & 0xff;
Settings.rf_code[XdrvMailbox.index][6] = (SnfBridge.last_send_code >> 16) & 0xff;
Settings.rf_code[XdrvMailbox.index][7] = (SnfBridge.last_send_code >> 8) & 0xff;
Settings.rf_code[XdrvMailbox.index][8] = SnfBridge.last_send_code & 0xff;
ResponseCmndIdxChar(D_JSON_SAVED);
} else if (5 == XdrvMailbox.payload) { // Show default or learned RF data
uint8_t key = XdrvMailbox.index;
@ -540,7 +518,7 @@ void CmndRfKey(void)
}
}
} else {
Response_P(S_JSON_COMMAND_INDEX_SVALUE, XdrvMailbox.command, sonoff_bridge_learn_key, D_JSON_LEARNING_ACTIVE);
Response_P(S_JSON_COMMAND_INDEX_SVALUE, XdrvMailbox.command, SnfBridge.learn_key, D_JSON_LEARNING_ACTIVE);
}
}
}
@ -553,7 +531,7 @@ void CmndRfRaw(void)
case 0: // Receive Raw Off
SonoffBridgeSendCommand(0xA7); // Stop reading RF signals enabling iTead default RF handling
case 1: // Receive Raw On
sonoff_bridge_receive_raw_flag = XdrvMailbox.payload;
SnfBridge.receive_raw_flag = XdrvMailbox.payload;
break;
case 166: // 0xA6 - Start reading RF signals disabling iTead default RF handling
case 167: // 0xA7 - Stop reading RF signals enabling iTead default RF handling
@ -562,7 +540,7 @@ void CmndRfRaw(void)
case 177: // 0xB1 - Start sniffing
case 255: // 0xFF - Show firmware version
SonoffBridgeSendCommand(XdrvMailbox.payload);
sonoff_bridge_receive_raw_flag = 1;
SnfBridge.receive_raw_flag = 1;
break;
case 192: // 0xC0 - Beep
char beep[] = "AAC000C055\0";
@ -571,18 +549,10 @@ void CmndRfRaw(void)
}
} else {
SerialSendRaw(RemoveSpace(XdrvMailbox.data));
sonoff_bridge_receive_raw_flag = 1;
SnfBridge.receive_raw_flag = 1;
}
}
ResponseCmndStateText(sonoff_bridge_receive_raw_flag);
}
/*********************************************************************************************/
void SonoffBridgeInit(void)
{
sonoff_bridge_receive_raw_flag = 0;
SonoffBridgeSendCommand(0xA7); // Stop reading RF signals enabling iTead default RF handling
ResponseCmndStateText(SnfBridge.receive_raw_flag);
}
/*********************************************************************************************\
@ -598,12 +568,17 @@ bool Xdrv06(uint8_t function)
case FUNC_SERIAL:
result = SonoffBridgeSerialInput();
break;
case FUNC_INIT:
SonoffBridgeInit();
break;
case FUNC_COMMAND:
result = DecodeCommand(kSonoffBridgeCommands, SonoffBridgeCommand);
break;
case FUNC_INIT:
SnfBridge.receive_raw_flag = 0;
SonoffBridgeSendCommand(0xA7); // Stop reading RF signals enabling iTead default RF handling
break;
case FUNC_PRE_INIT:
Settings.flag.mqtt_serial = 0;
baudrate = 19200;
break;
}
}
return result;

View File

@ -1,5 +1,5 @@
/*
xdrv_24_buzzer.ino - buzzer support for Sonoff-Tasmota
xdrv_24_Buzzer.ino - buzzer support for Sonoff-Tasmota
Copyright (C) 2019 Theo Arends
@ -21,6 +21,7 @@
/*********************************************************************************************\
* Buzzer support
\*********************************************************************************************/
#define XDRV_24 24
struct BUZZER {
@ -32,17 +33,17 @@ struct BUZZER {
uint8_t set[2];
uint8_t duration;
uint8_t state = 0;
} buzzer;
} Buzzer;
/*********************************************************************************************/
//void BuzzerBeep(uint32_t count = 1, uint32_t on = 1, uint32_t off = 1, uint32_t tune = 0);
void BuzzerBeep(uint32_t count, uint32_t on, uint32_t off, uint32_t tune)
{
buzzer.set[0] = off;
buzzer.set[1] = on;
buzzer.duration = 1; // Start buzzer on first step
buzzer.tune = 0;
Buzzer.set[0] = off;
Buzzer.set[1] = on;
Buzzer.duration = 1; // Start buzzer on first step
Buzzer.tune = 0;
if (tune) {
uint32_t tune1 = tune;
uint32_t tune2 = tune;
@ -50,19 +51,19 @@ void BuzzerBeep(uint32_t count, uint32_t on, uint32_t off, uint32_t tune)
if (!(tune2 & 0x80000000)) {
tune2 <<= 1; // Skip leading silence
} else {
buzzer.tune <<= 1; // Add swapped tune
buzzer.tune |= tune1 & 1;
Buzzer.tune <<= 1; // Add swapped tune
Buzzer.tune |= tune1 & 1;
tune1 >>= 1;
}
}
buzzer.count = 1; // Allow tune only once
Buzzer.count = 1; // Allow tune only once
} else {
buzzer.count = count * 2; // Start buzzer
Buzzer.count = count * 2; // Start buzzer
}
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("BUZ: %d(%d),%d,%d,0x%08X(0x%08X)"), count, buzzer.count, on, off, tune, buzzer.tune);
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("BUZ: %d(%d),%d,%d,0x%08X(0x%08X)"), count, Buzzer.count, on, off, tune, Buzzer.tune);
buzzer.enable = true;
Buzzer.enable = true;
}
void BuzzerBeep(uint32_t count) {
@ -81,7 +82,7 @@ void BuzzerEnabledBeep(uint32_t count)
bool BuzzerPinState()
{
if (XdrvMailbox.index == GPIO_BUZZER_INV) {
buzzer.inverted = 1;
Buzzer.inverted = 1;
XdrvMailbox.index -= (GPIO_BUZZER_INV - GPIO_BUZZER);
return true;
}
@ -92,32 +93,32 @@ void BuzzerInit(void)
{
if (pin[GPIO_BUZZER] < 99) {
pinMode(pin[GPIO_BUZZER], OUTPUT);
digitalWrite(pin[GPIO_BUZZER], buzzer.inverted); // Buzzer Off
digitalWrite(pin[GPIO_BUZZER], Buzzer.inverted); // Buzzer Off
} else {
buzzer.active = false;
Buzzer.active = false;
}
}
void BuzzerEvery100mSec(void)
{
if (buzzer.enable) {
if (buzzer.count) {
if (buzzer.duration) {
buzzer.duration--;
if (!buzzer.duration) {
if (buzzer.tune) {
buzzer.state = buzzer.tune & 1;
buzzer.tune >>= 1;
if (Buzzer.enable) {
if (Buzzer.count) {
if (Buzzer.duration) {
Buzzer.duration--;
if (!Buzzer.duration) {
if (Buzzer.tune) {
Buzzer.state = Buzzer.tune & 1;
Buzzer.tune >>= 1;
} else {
buzzer.count--;
buzzer.state = buzzer.count & 1;
Buzzer.count--;
Buzzer.state = Buzzer.count & 1;
}
buzzer.duration = buzzer.set[buzzer.state];
Buzzer.duration = Buzzer.set[Buzzer.state];
}
}
digitalWrite(pin[GPIO_BUZZER], (buzzer.inverted) ? !buzzer.state : buzzer.state);
digitalWrite(pin[GPIO_BUZZER], (Buzzer.inverted) ? !Buzzer.state : Buzzer.state);
} else {
buzzer.enable = false;
Buzzer.enable = false;
}
}
}
@ -169,7 +170,7 @@ bool Xdrv24(uint8_t function)
{
bool result = false;
if (buzzer.active) {
if (Buzzer.active) {
switch (function) {
case FUNC_EVERY_100_MSECOND:
BuzzerEvery100mSec();