mirror of
https://github.com/letscontrolit/ESPEasy.git
synced 2026-07-27 19:57:38 +00:00
[Serial Proxy] Use capture filtering
This commit is contained in:
@@ -599,6 +599,21 @@ char * MatchState::GetCapture (char * s, const int n) const
|
||||
return s;
|
||||
} // end of MatchState::GetCapture
|
||||
|
||||
String MatchState::GetCapture (const int n) const
|
||||
{
|
||||
if (result != REGEXP_MATCHED || n >= level || capture [n].len <= 0)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
String s;
|
||||
s.reserve(capture [n].len);
|
||||
for (int i = 0; i < capture [n].len; ++i)
|
||||
{
|
||||
s += capture [n].init[i];
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
// match repeatedly on a string, return count of matches
|
||||
unsigned int MatchState::MatchCount (const char * pattern)
|
||||
{
|
||||
|
||||
@@ -15,12 +15,14 @@
|
||||
Version 1.0 - 30th April 2011 : initial release.
|
||||
Version 1.1 - 1st May 2011 : added some helper functions, made more modular.
|
||||
Version 1.2 - 19th May 2011 : added more helper functions for replacing etc.
|
||||
Version 1.2a - 12th March 2020 : TD-er: Added functions to get String captures + proper init of vars.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
// Maximum of captures we can return.
|
||||
// Increase if you need more, decrease to save memory.
|
||||
@@ -112,6 +114,7 @@ public:
|
||||
char * GetMatch (char * s) const;
|
||||
// return capture string n
|
||||
char * GetCapture (char * s, const int n) const;
|
||||
String GetCapture (const int n) const;
|
||||
// get result of previous match
|
||||
char GetResult () const { return result; }
|
||||
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
#define P087_DEFAULT_BAUDRATE 38400
|
||||
|
||||
|
||||
|
||||
// Plugin settings:
|
||||
// Validate:
|
||||
// - [0..9]
|
||||
@@ -130,40 +129,12 @@ boolean Plugin_087(byte function, struct EventStruct *event, String& string) {
|
||||
|
||||
case PLUGIN_WEBFORM_LOAD: {
|
||||
serialHelper_webformLoad(event);
|
||||
|
||||
/*
|
||||
P087_data_struct *P087_data =
|
||||
static_cast<P087_data_struct *>(getPluginTaskData(event->TaskIndex));
|
||||
if (nullptr != P087_data && P087_data->isInitialized()) {
|
||||
String detectedString = F("Detected: ");
|
||||
detectedString += String(P087_data->P087_easySerial->baudRate());
|
||||
addUnit(detectedString);
|
||||
*/
|
||||
|
||||
addFormNumericBox(F("Baudrate"), P087_BAUDRATE_LABEL, P087_BAUDRATE, 2400, 115200);
|
||||
addUnit(F("baud"));
|
||||
|
||||
/*
|
||||
{
|
||||
// In a separate scope to free memory of String array as soon as possible
|
||||
sensorTypeHelper_webformLoad_header();
|
||||
String options[P087_NR_OUTPUT_OPTIONS];
|
||||
|
||||
for (int i = 0; i < P087_NR_OUTPUT_OPTIONS; ++i) {
|
||||
options[i] = Plugin_087_valuename(i, true);
|
||||
}
|
||||
|
||||
for (byte i = 0; i < P087_NR_OUTPUT_VALUES; ++i) {
|
||||
const byte pconfigIndex = i + P087_QUERY1_CONFIG_POS;
|
||||
sensorTypeHelper_loadOutputSelector(event, pconfigIndex, i, P087_NR_OUTPUT_OPTIONS, options);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
addFormSubHeader(F("Filtering"));
|
||||
P087_html_show_matchForms(event);
|
||||
|
||||
|
||||
addFormSubHeader(F("Statistics"));
|
||||
P087_html_show_stats(event);
|
||||
|
||||
@@ -204,6 +175,7 @@ boolean Plugin_087(byte function, struct EventStruct *event, String& string) {
|
||||
|
||||
if (P087_data->init(serial_rx, serial_tx, P087_BAUDRATE)) {
|
||||
LoadCustomTaskSettings(event->TaskIndex, P087_data->_lines, P87_Nlines, 0);
|
||||
P087_data->post_init();
|
||||
success = true;
|
||||
|
||||
if (loglevelActiveFor(LOG_LEVEL_DEBUG)) {
|
||||
@@ -367,7 +339,7 @@ void P087_html_show_matchForms(struct EventStruct *event) {
|
||||
label += String(lineNr);
|
||||
addRowLabel_tr_id(label, id);
|
||||
|
||||
addNumericBox(id, capture, 0, 99);
|
||||
addNumericBox(id, capture, -1, P87_MAX_CAPTURE_INDEX);
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
|
||||
@@ -4,16 +4,16 @@
|
||||
#ifdef USES_P087
|
||||
|
||||
|
||||
P087_data_struct::P087_data_struct() : P087_easySerial(nullptr) {}
|
||||
P087_data_struct::P087_data_struct() : easySerial(nullptr) {}
|
||||
|
||||
P087_data_struct::~P087_data_struct() {
|
||||
reset();
|
||||
}
|
||||
|
||||
void P087_data_struct::reset() {
|
||||
if (P087_easySerial != nullptr) {
|
||||
delete P087_easySerial;
|
||||
P087_easySerial = nullptr;
|
||||
if (easySerial != nullptr) {
|
||||
delete easySerial;
|
||||
easySerial = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,24 +22,46 @@ bool P087_data_struct::init(const int16_t serial_rx, const int16_t serial_tx, un
|
||||
return false;
|
||||
}
|
||||
reset();
|
||||
P087_easySerial = new ESPeasySerial(serial_rx, serial_tx);
|
||||
easySerial = new ESPeasySerial(serial_rx, serial_tx);
|
||||
|
||||
if (isInitialized()) {
|
||||
P087_easySerial->begin(baudrate);
|
||||
easySerial->begin(baudrate);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void P087_data_struct::post_init() {
|
||||
for (uint8_t i = 0; i < P87_MAX_CAPTURE_INDEX; ++i) {
|
||||
capture_index_used[i] = false;
|
||||
}
|
||||
String log = F("P087_post_init:");
|
||||
for (uint8_t i = 0; i < P087_NR_FILTERS; ++i) {
|
||||
// Create some quick lookup table to see if we have a filter for the specific index
|
||||
capture_index_must_not_match[i] = _lines[i * 3 + P087_FIRST_FILTER_POS + 1].toInt() == P087_Filter_Comp::NotEqual;
|
||||
int index = _lines[i * 3 + P087_FIRST_FILTER_POS].toInt();
|
||||
// Index is negative when not used.
|
||||
if (index >= 0 && index < P87_MAX_CAPTURE_INDEX && _lines[i * 3 + P087_FIRST_FILTER_POS + 1].length() > 0) {
|
||||
log += ' ';
|
||||
log += String(i);
|
||||
log += ':';
|
||||
log += String(index);
|
||||
capture_index[i] = index;
|
||||
capture_index_used[index] = true;
|
||||
}
|
||||
}
|
||||
addLog(LOG_LEVEL_DEBUG, log);
|
||||
}
|
||||
|
||||
bool P087_data_struct::isInitialized() const {
|
||||
return P087_easySerial != nullptr;
|
||||
return easySerial != nullptr;
|
||||
}
|
||||
|
||||
void P087_data_struct::sendString(const String& data) {
|
||||
if (isInitialized()) {
|
||||
if (data.length() > 0) {
|
||||
setDisableFilterWindowTimer();
|
||||
P087_easySerial->write(data.c_str());
|
||||
easySerial->write(data.c_str());
|
||||
|
||||
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
|
||||
String log = F("Proxy: Sending: ");
|
||||
@@ -56,16 +78,16 @@ bool P087_data_struct::loop() {
|
||||
}
|
||||
bool fullSentenceReceived = false;
|
||||
|
||||
if (P087_easySerial != nullptr) {
|
||||
int available = P087_easySerial->available();
|
||||
if (easySerial != nullptr) {
|
||||
int available = easySerial->available();
|
||||
|
||||
while (available > 0 && !fullSentenceReceived) {
|
||||
// Look for end marker
|
||||
char c = P087_easySerial->read();
|
||||
char c = easySerial->read();
|
||||
--available;
|
||||
|
||||
if (available == 0) {
|
||||
available = P087_easySerial->available();
|
||||
available = easySerial->available();
|
||||
delay(0);
|
||||
}
|
||||
|
||||
@@ -207,19 +229,12 @@ static std::vector<capture_tuple> capture_vector;
|
||||
// called for each match
|
||||
void P087_data_struct::match_callback(const char *match, const unsigned int length, const MatchState& ms)
|
||||
{
|
||||
char cap[10]; // must be large enough to hold captures
|
||||
|
||||
Serial.print("Matched: ");
|
||||
Serial.write((byte *)match, length);
|
||||
Serial.println();
|
||||
|
||||
for (byte i = 0; i < ms.level; i++)
|
||||
{
|
||||
Serial.print("Capture ");
|
||||
Serial.print(i, DEC);
|
||||
Serial.print(" = ");
|
||||
ms.GetCapture(cap, i);
|
||||
Serial.println(cap);
|
||||
capture_tuple tuple;
|
||||
tuple.first = 1;
|
||||
tuple.second = ms.GetCapture(i);
|
||||
capture_vector.push_back(tuple);
|
||||
} // end of for each capture
|
||||
}
|
||||
|
||||
@@ -243,8 +258,40 @@ bool P087_data_struct::matchRegexp(String& received) const {
|
||||
bool match_result = false;
|
||||
|
||||
if (globalMatch()) {
|
||||
unsigned long count = ms.GlobalMatch(_lines[P087_REGEX_POS].c_str(), match_callback);
|
||||
match_result = count != 0;
|
||||
capture_vector.clear();
|
||||
ms.GlobalMatch(_lines[P087_REGEX_POS].c_str(), match_callback);
|
||||
const uint8_t vectorlength = capture_vector.size();
|
||||
for (uint8_t i = 0; i < vectorlength; ++i) {
|
||||
if (capture_vector[i].first < P87_MAX_CAPTURE_INDEX && capture_index_used[capture_vector[i].first]) {
|
||||
for (uint8_t n = 0; n < P087_NR_FILTERS; ++n) {
|
||||
if (capture_index[n] == capture_vector[i].first) {
|
||||
String log;
|
||||
log.reserve(32);
|
||||
log = F("P087: Index: ");
|
||||
log += capture_vector[i].first;
|
||||
log += F(" Found ");
|
||||
log += capture_vector[i].second;
|
||||
// Found a Capture Filter with this capture index.
|
||||
if (capture_vector[i].second == _lines[n * 3 + P087_FIRST_FILTER_POS + 2]) {
|
||||
log += F(" Matches");
|
||||
// Found a match. Now check if it is supposed to be one or not.
|
||||
if (capture_index_must_not_match[n]) {
|
||||
log += F(" (!=)");
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
return false;
|
||||
} else {
|
||||
match_result = true;
|
||||
log += F(" (==)");
|
||||
}
|
||||
} else {
|
||||
log += F(" No Match");
|
||||
}
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
capture_vector.clear();
|
||||
} else {
|
||||
char result = ms.Match(_lines[P087_REGEX_POS].c_str());
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
# define P087_NR_FILTERS 10
|
||||
# define P87_Nlines (P087_FIRST_FILTER_POS + 3 * (P087_NR_FILTERS))
|
||||
# define P87_Nchars 128
|
||||
# define P87_MAX_CAPTURE_INDEX 32
|
||||
|
||||
|
||||
enum P087_Filter_Comp {
|
||||
@@ -45,6 +46,10 @@ public:
|
||||
const int16_t serial_tx,
|
||||
unsigned long baudrate);
|
||||
|
||||
// Called after loading the config from the settings.
|
||||
// Will interpret some data and load caches.
|
||||
void post_init();
|
||||
|
||||
bool isInitialized() const;
|
||||
|
||||
void sendString(const String& data);
|
||||
@@ -82,7 +87,7 @@ public:
|
||||
|
||||
bool disableFilterWindowActive() const;
|
||||
|
||||
// called for each match
|
||||
// called for each match when calling Global_Match
|
||||
static void match_callback(const char *match,
|
||||
const unsigned int length,
|
||||
const MatchState & ms);
|
||||
@@ -97,13 +102,18 @@ private:
|
||||
|
||||
bool max_length_reached() const;
|
||||
|
||||
ESPeasySerial *P087_easySerial = nullptr;
|
||||
ESPeasySerial *easySerial = nullptr;
|
||||
String sentence_part;
|
||||
uint16_t max_length = 550;
|
||||
uint32_t sentences_received = 0;
|
||||
uint32_t sentences_received_error = 0;
|
||||
uint32_t length_last_received = 0;
|
||||
unsigned long disable_filter_window = 0;
|
||||
|
||||
uint8_t capture_index[P87_MAX_CAPTURE_INDEX] = {0};
|
||||
|
||||
bool capture_index_used[P87_MAX_CAPTURE_INDEX];
|
||||
bool capture_index_must_not_match[P87_MAX_CAPTURE_INDEX];
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user