Browse Source

RPN rules (WIP)

rules-rpn
Xose Pérez 5 years ago
parent
commit
dcc3b9e0e8
6 changed files with 139 additions and 2 deletions
  1. +2
    -2
      README.md
  2. +5
    -0
      code/espurna/config/dependencies.h
  3. +13
    -0
      code/espurna/config/general.h
  4. +1
    -0
      code/espurna/ntp.ino
  5. +117
    -0
      code/espurna/rpnrules.ino
  6. +1
    -0
      code/platformio.ini

+ 2
- 2
README.md View File

@ -4,9 +4,9 @@ ESPurna ("spark" in Catalan) is a custom firmware for ESP8285/ESP8266 based smar
It uses the Arduino Core for ESP8266 framework and a number of 3rd party libraries.
[![version](https://img.shields.io/badge/version-1.13.6--dev-brightgreen.svg)](CHANGELOG.md)
[![branch](https://img.shields.io/badge/branch-dev-orange.svg)](https://github.com/xoseperez/espurna/tree/dev/)
[![branch](https://img.shields.io/badge/branch-rules--rpn-orange.svg)](https://github.com/xoseperez/espurna/tree/rules-rpn/)
[![license](https://img.shields.io/github/license/xoseperez/espurna.svg)](LICENSE)
[![travis](https://travis-ci.org/xoseperez/espurna.svg?branch=dev)](https://travis-ci.org/xoseperez/espurna)
[![travis](https://travis-ci.org/xoseperez/espurna.svg?branch=rules-rpn)](https://travis-ci.org/xoseperez/espurna)
[![codacy](https://api.codacy.com/project/badge/Grade/c9496e25cf07434cba786b462cb15f49)](https://www.codacy.com/app/xoseperez/espurna/dashboard)
[![downloads](https://img.shields.io/github/downloads/xoseperez/espurna/total.svg)](https://github.com/xoseperez/espurna/releases)
<br />


+ 5
- 0
code/espurna/config/dependencies.h View File

@ -38,6 +38,11 @@
#define BROKER_SUPPORT 1 // If Alexa enabled enable BROKER
#endif
#if RPN_RULES_SUPPORT
#undef BROKER_SUPPORT
#define BROKER_SUPPORT 1 // If RPN Rules enabled enable BROKER
#endif
#if INFLUXDB_SUPPORT
#undef BROKER_SUPPORT
#define BROKER_SUPPORT 1 // If InfluxDB enabled enable BROKER


+ 13
- 0
code/espurna/config/general.h View File

@ -843,6 +843,7 @@
#define MQTT_TOPIC_VERSION "version"
#define MQTT_TOPIC_UPTIME "uptime"
#define MQTT_TOPIC_DATETIME "datetime"
#define MQTT_TOPIC_TIMESTAMP "timestamp"
#define MQTT_TOPIC_FREEHEAP "freeheap"
#define MQTT_TOPIC_VCC "vcc"
#define MQTT_TOPIC_STATUS "status"
@ -1167,6 +1168,18 @@
#define SCHEDULER_MAX_SCHEDULES 10 // Max schedules alowed
#endif
// -----------------------------------------------------------------------------
// RPN RULES
// -----------------------------------------------------------------------------
#ifndef RPN_RULES_SUPPORT
#define RPN_RULES_SUPPORT 1 // Enable RPN Rules (?Kb)
#endif
#ifndef RPN_BUFFER_DELAY
#define RPN_BUFFER_DELAY 100 // Execute rules after 100ms without messages
#endif
// -----------------------------------------------------------------------------
// NTP
// -----------------------------------------------------------------------------


+ 1
- 0
code/espurna/ntp.ino View File

@ -135,6 +135,7 @@ void inline _ntpBroker() {
if (ntpSynced() && (minute() != last_minute)) {
last_minute = minute();
brokerPublish(BROKER_MSG_TYPE_DATETIME, MQTT_TOPIC_DATETIME, ntpDateTime().c_str());
brokerPublish(BROKER_MSG_TYPE_DATETIME, MQTT_TOPIC_TIMESTAMP, String(now()).c_str());
}
}


+ 117
- 0
code/espurna/rpnrules.ino View File

@ -0,0 +1,117 @@
/*
NTP MODULE
Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
*/
#if RPN_RULES_SUPPORT
#include "rpnlib.h"
#include <Ticker.h>
// -----------------------------------------------------------------------------
// Custom commands
// -----------------------------------------------------------------------------
rpn_context _rpn_ctxt;
bool _rpn_run = false;
unsigned long _rpn_last = 0;
// -----------------------------------------------------------------------------
bool _rpnWebSocketOnReceive(const char * key, JsonVariant& value) {
return (strncmp(key, "rpn", 3) == 0);
}
void _rpnWebSocketOnSend(JsonObject& root) {
root["rpnVisible"] = 1;
JsonArray& rules = root.createNestedArray("rpnRules");
unsigned char i = 0;
while (String rule = getSetting("rule", i, NULL)) {
rules.add(rule);
}
}
void _rpnConfigure() {
}
void _rpnBrokerCallback(const unsigned char type, const char * topic, unsigned char id, const char * payload) {
char name[32] = {0};
if (BROKER_MSG_TYPE_STATUS == type || BROKER_MSG_TYPE_SENSOR == type) {
snprintf(name, sizeof(name), "%s%d", topic, id);
} else if (BROKER_MSG_TYPE_DATETIME == type) {
strncpy(name, topic, sizeof(name));
} else {
return;
}
rpn_variable_set(_rpn_ctxt, name, atof(payload));
_rpn_last = millis();
_rpn_run = true;
}
void _rpnInit() {
// Init context
rpn_init(_rpn_ctxt);
// Add relay operator
rpn_operator_set(_rpn_ctxt, "relay", 2, [](rpn_context & ctxt) {
float a, b;
rpn_stack_pop(ctxt, b); // new status
rpn_stack_pop(ctxt, a); // relay number
relayStatus(int(a), int(b));
return true;
});
}
void _rpnRun() {
unsigned char i = 0;
while (String rule = getSetting("rule", i, NULL)) {
rpn_stack_clear(_rpn_ctxt);
rpn_process(_rpn_ctxt, rule.c_str());
}
}
void _rpnLoop() {
if (_rpn_run && (millis() - _rpn_last > RPN_BUFFER_DELAY)) {
_rpnRun();
_rpn_run = false;
}
}
void rpnSetup() {
// Init context
_rpnInit();
// Load & cache settings
_rpnConfigure();
// Websockets
#if WEB_SUPPORT
wsOnSendRegister(_rpnWebSocketOnSend);
wsOnReceiveRegister(_rpnWebSocketOnReceive);
#endif
brokerRegister(_rpnBrokerCallback);
espurnaRegisterReload(_rpnConfigure);
espurnaRegisterLoop(_rpnLoop);
}
#endif

+ 1
- 0
code/platformio.ini View File

@ -99,6 +99,7 @@ lib_deps =
PubSubClient
rc-switch
https://github.com/LowPowerLab/RFM69#1.1.3
https://github.com/xoseperez/rpnlib.git#0.0.2
https://github.com/xoseperez/Time
NewPing
https://github.com/sparkfun/SparkFun_VEML6075_Arduino_Library#V_1.0.3


Loading…
Cancel
Save