Skip to content

Commit

Permalink
Rules fixes and additions
Browse files Browse the repository at this point in the history
5.14.0a
* Add rules %mem1% to %mem5% variable names storing data in flash
(#2780)
* Add rules test on %varx% or %memx% (#2780)
* Fix anomalies in rules (#2778)
  • Loading branch information
arendst committed May 20, 2018
1 parent acd4c93 commit 06258e5
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 24 deletions.
3 changes: 3 additions & 0 deletions sonoff/_releasenotes.ino
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@
* Add KNX communication enhancement (#2742)
* Add KNX energy data (#2750)
* Add python script fw-server.py in tools folder to create a simple OTA server (#2759)
* Add rules %mem1% to %mem5% variable names storing data in flash (#2780)
* Add rules test on %varx% or %memx% (#2780)
* Fix display selection of un-available GPIO options in Module Configuration webpage (#2718)
* Fix timer re-trigger within one minute after restart (#2744)
* Fix IRSend not accepting data value of 0 (#2751)
* Fix vars on rules (#2769)
* Fix bug in KNX menu (#2770)
* Fix anomalies in rules (#2778)
*
* 5.14.0 20180515
* Update language files
Expand Down
4 changes: 3 additions & 1 deletion sonoff/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -271,8 +271,9 @@ struct SYSCFG {
byte knx_GA_param[MAX_KNX_GA]; // 6E2 Type of Input (relay changed, button pressed, sensor read <-teleperiod)
byte knx_CB_param[MAX_KNX_CB]; // 6EC Type of Output (set relay, toggle relay, reply sensor value)

byte free_6f6[266]; // 6F6
byte free_6f6[216]; // 6F6

char mems[RULES_MAX_MEMS][10]; // 7CE
char rules[MAX_RULE_SIZE]; // 800 uses 512 bytes in v5.12.0m

// A00 - FFF free locations
Expand All @@ -286,6 +287,7 @@ struct RTCMEM {
unsigned long energy_kWhtotal; // 008
unsigned long pulse_counter[MAX_COUNTERS]; // 00C
power_t power; // 01C
// 020 next free location
} RtcSettings;

struct TIME_T {
Expand Down
1 change: 1 addition & 0 deletions sonoff/sonoff.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ typedef unsigned long power_t; // Power (Relay) type
#define MAX_DOMOTICZ_SNS_IDX 12 // Max number of Domoticz sensors indices
#define MAX_KNX_GA 10 // Max number of KNX Group Addresses to read that can be set
#define MAX_KNX_CB 10 // Max number of KNX Group Addresses to write that can be set
#define RULES_MAX_MEMS 5 // Max number of saved vars
#define MAX_RULE_SIZE 512 // Max number of characters in rules

#define MQTT_TOKEN_PREFIX "%prefix%" // To be substituted by mqtt_prefix[x]
Expand Down
76 changes: 53 additions & 23 deletions sonoff/xdrv_10_rules.ino
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,13 @@
#define D_CMND_RULE "Rule"
#define D_CMND_RULETIMER "RuleTimer"
#define D_CMND_EVENT "Event"
#define D_CMND_VAR "Var"
#define D_CMND_MEM "Mem"

#define D_JSON_INITIATED "Initiated"

enum RulesCommands { CMND_RULE, CMND_RULETIMER, CMND_EVENT };
const char kRulesCommands[] PROGMEM = D_CMND_RULE "|" D_CMND_RULETIMER "|" D_CMND_EVENT ;
enum RulesCommands { CMND_RULE, CMND_RULETIMER, CMND_EVENT, CMND_VAR, CMND_MEM };
const char kRulesCommands[] PROGMEM = D_CMND_RULE "|" D_CMND_RULETIMER "|" D_CMND_EVENT "|" D_CMND_VAR "|" D_CMND_MEM ;

String rules_event_value;
unsigned long rules_timer[MAX_RULE_TIMERS] = { 0 };
Expand Down Expand Up @@ -146,6 +148,7 @@ bool RulesRuleMatch(String &event, String &rule)
// rule = "INA219#CURRENT>0.100"

bool match = false;
char stemp[10];

// Step1: Analyse rule
int pos = rule.indexOf('#');
Expand Down Expand Up @@ -179,7 +182,24 @@ bool RulesRuleMatch(String &event, String &rule)
char tmp_value[CMDSZ] = { 0 };
double rule_value = 0;
if (pos > 0) {
snprintf(tmp_value, sizeof(tmp_value), rule_name.substring(pos + 1).c_str());
String rule_param = rule_name.substring(pos + 1);
for (byte i = 0; i < RULES_MAX_VARS; i++) {
snprintf_P(stemp, sizeof(stemp), PSTR("%%VAR%d%%"), i +1);
if (rule_param.startsWith(stemp)) {
rule_param = vars[i];
break;
}
}
for (byte i = 0; i < RULES_MAX_MEMS; i++) {
snprintf_P(stemp, sizeof(stemp), PSTR("%%MEM%d%%"), i +1);
if (rule_param.startsWith(stemp)) {
rule_param = Settings.mems[i];
break;
}
}
rule_param.toUpperCase();
snprintf(tmp_value, sizeof(tmp_value), rule_param.c_str());

int temp_value = GetStateNumber(tmp_value);
if (temp_value > -1) {
rule_value = temp_value;
Expand Down Expand Up @@ -288,29 +308,27 @@ bool RulesProcess()
commands.trim();
String ucommand = commands;
ucommand.toUpperCase();
if (ucommand.startsWith("VAR")) {
uint8_t idx = ucommand.charAt(3) - '1';
if ((idx >= 0) && (idx < RULES_MAX_VARS)) { snprintf(vars[idx], sizeof(vars[idx]), rules_event_value.c_str()); }
} else {
// if (!ucommand.startsWith("BACKLOG")) { commands = "backlog " + commands; } // Always use Backlog to prevent power race condition
commands.replace(F("%value%"), rules_event_value);
for (byte i = 0; i < RULES_MAX_VARS; i++) {
if (strlen(vars[i])) {
snprintf_P(stemp, sizeof(stemp), PSTR("%%var%d%%"), i +1);
commands.replace(stemp, vars[i]);
}
}
char command[commands.length() +1];
snprintf(command, sizeof(command), commands.c_str());
// if (!ucommand.startsWith("BACKLOG")) { commands = "backlog " + commands; } // Always use Backlog to prevent power race exception
if (ucommand.indexOf("EVENT ") != -1) { commands = "backlog " + commands; } // Always use Backlog with event to prevent rule event loop exception
commands.replace(F("%value%"), rules_event_value);
for (byte i = 0; i < RULES_MAX_VARS; i++) {
snprintf_P(stemp, sizeof(stemp), PSTR("%%var%d%%"), i +1);
commands.replace(stemp, vars[i]);
}
for (byte i = 0; i < RULES_MAX_MEMS; i++) {
snprintf_P(stemp, sizeof(stemp), PSTR("%%mem%d%%"), i +1);
commands.replace(stemp, Settings.mems[i]);
}
char command[commands.length() +1];
snprintf(command, sizeof(command), commands.c_str());

snprintf_P(log_data, sizeof(log_data), PSTR("RUL: %s performs \"%s\""), event_trigger.c_str(), command);
AddLog(LOG_LEVEL_INFO);
snprintf_P(log_data, sizeof(log_data), PSTR("RUL: %s performs \"%s\""), event_trigger.c_str(), command);
AddLog(LOG_LEVEL_INFO);

// snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, D_CMND_RULE, D_JSON_INITIATED);
// MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_RULE));
// snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, D_CMND_RULE, D_JSON_INITIATED);
// MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_RULE));

ExecuteCommand(command);
}
ExecuteCommand(command);
serviced = true;
}
rules_trigger_count++;
Expand Down Expand Up @@ -454,6 +472,18 @@ boolean RulesCommand()
}
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE);
}
else if ((CMND_VAR == command_code) && (index > 0) && (index <= RULES_MAX_VARS)) {
if (XdrvMailbox.data_len > 0) {
strlcpy(vars[index -1], ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data, sizeof(vars[index -1]));
}
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, vars[index -1]);
}
else if ((CMND_MEM == command_code) && (index > 0) && (index <= RULES_MAX_MEMS)) {
if (XdrvMailbox.data_len > 0) {
strlcpy(Settings.mems[index -1], ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data, sizeof(Settings.mems[index -1]));
}
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, Settings.mems[index -1]);
}
else serviced = false; // Unknown command

return serviced;
Expand Down

0 comments on commit 06258e5

Please sign in to comment.