diff --git a/src/_P094_CULReader.ino b/src/_P094_CULReader.ino index ec12d8738..aaeb656e2 100644 --- a/src/_P094_CULReader.ino +++ b/src/_P094_CULReader.ino @@ -321,67 +321,81 @@ void P094_html_show_matchForms(struct EventStruct *event) { } - byte lineNr = 0; + byte filterNr = 0; uint32_t optional = 0; P094_Filter_Value_Type capture = P094_Filter_Value_Type::P094_packet_length; P094_Filter_Comp comparator = P094_Filter_Comp::P094_Equal_OR; String filter; - for (byte varNr = P094_FIRST_FILTER_POS; varNr < P94_Nlines; ++varNr) + for (byte lineNr = 0; lineNr < P094_NR_FILTERS; ++lineNr) { - String id = getPluginCustomArgName(varNr); + // Filter parameter number on a filter line. + bool newLine = (lineNr % P094_AND_FILTER_BLOCK) == 0; - switch ((varNr - P094_FIRST_FILTER_POS) % P094_ITEMS_PER_FILTER) { - case 0: - { - // Label + first parameter - filter = P094_data->getFilter(lineNr, capture, optional, comparator); - ++lineNr; - String label; - label = F("Filter "); - label += String(lineNr); - addRowLabel_tr_id(label, id); + for (byte filterLinePar = 0; filterLinePar < P094_ITEMS_PER_FILTER; ++filterLinePar) + { + String id = getPluginCustomArgName(P094_data_struct::P094_Get_filter_base_index(lineNr) + filterLinePar); - // Combo box with filter types + switch (filterLinePar) { + case 0: { - String options[P094_FILTER_VALUE_Type_NR_ELEMENTS]; - int optionValues[P094_FILTER_VALUE_Type_NR_ELEMENTS]; + filter = P094_data->getFilter(lineNr, capture, optional, comparator); - for (int i = 0; i < P094_FILTER_VALUE_Type_NR_ELEMENTS; ++i) { - P094_Filter_Value_Type filterValueType = static_cast(i); - options[i] = P094_data_struct::P094_FilterValueType_toString(filterValueType); - optionValues[i] = filterValueType; + if (newLine) { + // Label + first parameter + ++filterNr; + String label; + label = F("Filter "); + label += String(filterNr); + addRowLabel_tr_id(label, id); + } else { + addHtml(F("AND")); + html_BR(); } - addSelector(id, P094_FILTER_VALUE_Type_NR_ELEMENTS, options, optionValues, NULL, capture, false, ""); - } + ++lineNr; - break; - } - case 1: - { - // Optional numerical value - addNumericBox(id, optional, 0, 1024); - break; - } - case 2: - { - // Comparator - String options[P094_FILTER_COMP_NR_ELEMENTS]; - int optionValues[P094_FILTER_COMP_NR_ELEMENTS]; - for (int i = 0; i < P094_FILTER_COMP_NR_ELEMENTS; ++i) { - P094_Filter_Comp enumValue = static_cast(i); - options[i] = P094_data_struct::P094_FilterComp_toString(enumValue); - optionValues[i] = enumValue; + // Combo box with filter types + { + String options[P094_FILTER_VALUE_Type_NR_ELEMENTS]; + int optionValues[P094_FILTER_VALUE_Type_NR_ELEMENTS]; + + for (int i = 0; i < P094_FILTER_VALUE_Type_NR_ELEMENTS; ++i) { + P094_Filter_Value_Type filterValueType = static_cast(i); + options[i] = P094_data_struct::P094_FilterValueType_toString(filterValueType); + optionValues[i] = filterValueType; + } + addSelector(id, P094_FILTER_VALUE_Type_NR_ELEMENTS, options, optionValues, NULL, capture, false, ""); + } + + break; + } + case 1: + { + // Optional numerical value + addNumericBox(id, optional, 0, 1024); + break; + } + case 2: + { + // Comparator + String options[P094_FILTER_COMP_NR_ELEMENTS]; + int optionValues[P094_FILTER_COMP_NR_ELEMENTS]; + + for (int i = 0; i < P094_FILTER_COMP_NR_ELEMENTS; ++i) { + P094_Filter_Comp enumValue = static_cast(i); + options[i] = P094_data_struct::P094_FilterComp_toString(enumValue); + optionValues[i] = enumValue; + } + addSelector(id, P094_FILTER_COMP_NR_ELEMENTS, options, optionValues, NULL, comparator, false, ""); + break; + } + case 3: + { + // Compare with + addTextBox(id, filter, 8, false, false, "", ""); + break; } - addSelector(id, P094_FILTER_COMP_NR_ELEMENTS, options, optionValues, NULL, comparator, false, ""); - break; - } - case 3: - { - // Compare with - addTextBox(id, filter, 8, false, false, "", ""); - break; } } } diff --git a/src/_Plugin_Helper.cpp b/src/_Plugin_Helper.cpp index e6cdfa90c..3a6694bfa 100644 --- a/src/_Plugin_Helper.cpp +++ b/src/_Plugin_Helper.cpp @@ -63,7 +63,7 @@ bool pluginTaskData_initialized(taskIndex_t taskIndex) { } String getPluginCustomArgName(int varNr) { - String argName = F("plugin_custom_arg"); + String argName = F("pc_arg"); argName += varNr + 1; return argName; } diff --git a/src/src/PluginStructs/P094_data_struct.cpp b/src/src/PluginStructs/P094_data_struct.cpp index e5c91a536..feb41d4fa 100644 --- a/src/src/PluginStructs/P094_data_struct.cpp +++ b/src/src/PluginStructs/P094_data_struct.cpp @@ -37,7 +37,7 @@ void P094_data_struct::post_init() { } for (uint8_t i = 0; i < P094_NR_FILTERS; ++i) { - size_t lines_baseindex = get_filter_base_index(i); + size_t lines_baseindex = P094_Get_filter_base_index(i); int index = _lines[lines_baseindex].toInt(); int tmp_filter_comp = _lines[lines_baseindex + 2].toInt(); const bool filter_string_notempty = _lines[lines_baseindex + 3].length() > 0; @@ -176,14 +176,22 @@ bool P094_data_struct::invertMatch() const { return false; } -String P094_data_struct::getFilter(uint8_t lineNr, P094_Filter_Value_Type& filterValueType, uint32_t& optional, P094_Filter_Comp& comparator) const +bool P094_data_struct::filterUsed(uint8_t lineNr) const { - uint8_t varNr = get_filter_base_index(lineNr); + if (valueType_index[lineNr] == P094_Filter_Value_Type::P094_not_used) { return false; } + uint8_t varNr = P094_Get_filter_base_index(lineNr); + return _lines[varNr + 3].length() > 0; +} + +String P094_data_struct::getFilter(uint8_t lineNr, P094_Filter_Value_Type& filterValueType, uint32_t& optional, + P094_Filter_Comp& comparator) const +{ + uint8_t varNr = P094_Get_filter_base_index(lineNr); filterValueType = P094_Filter_Value_Type::P094_not_used; if (varNr >= P94_Nlines) { return ""; } - optional = _lines[varNr + 1].toInt(); + optional = _lines[varNr + 1].toInt(); filterValueType = valueType_index[lineNr]; comparator = filter_comp[lineNr]; @@ -267,6 +275,12 @@ bool P094_data_struct::parsePacket(String& received) const { addLog(LOG_LEVEL_INFO, log); } + bool filter_matches[P094_NR_FILTERS]; + + for (unsigned int f = 0; f < P094_NR_FILTERS; ++f) { + filter_matches[f] = false; + } + // Do not check for "not used" (0) for (unsigned int i = 1; i < P094_FILTER_VALUE_Type_NR_ELEMENTS; ++i) { if (valueType_used[i]) { @@ -310,11 +324,11 @@ bool P094_data_struct::parsePacket(String& received) const { switch (comparator) { case P094_Filter_Comp::P094_Equal_OR: - if (match) { match_result = true; } + if (match) { filter_matches[f] = true; } break; case P094_Filter_Comp::P094_NotEqual_OR: - if (!match) { match_result = true; } + if (!match) { filter_matches[f] = true; } break; case P094_Filter_Comp::P094_Equal_MUST: @@ -328,6 +342,28 @@ bool P094_data_struct::parsePacket(String& received) const { } } } + + // Now we have to check if all rows per filter line in filter_matches[f] are true or not used. + int nrMatches = 0; + int nrNotUsed = 0; + + for (unsigned int f = 0; !match_result && f < P094_NR_FILTERS; ++f) { + if (f % P094_AND_FILTER_BLOCK == 0) { + if ((nrMatches > 0) && ((nrMatches + nrNotUsed) == P094_AND_FILTER_BLOCK)) { + match_result = true; + } + nrMatches = 0; + nrNotUsed = 0; + } + + if (filter_matches[f]) { + ++nrMatches; + } else { + if (!filterUsed(f)) { + ++nrNotUsed; + } + } + } } else { switch (received[0]) { case 'C': // CMODE @@ -388,7 +424,7 @@ bool P094_data_struct::max_length_reached() const { return sentence_part.length() >= max_length; } -size_t P094_data_struct::get_filter_base_index(size_t filterLine) const { +size_t P094_data_struct::P094_Get_filter_base_index(size_t filterLine) { return filterLine * P094_ITEMS_PER_FILTER + P094_FIRST_FILTER_POS; } diff --git a/src/src/PluginStructs/P094_data_struct.h b/src/src/PluginStructs/P094_data_struct.h index 9d5c1e500..c93faf863 100644 --- a/src/src/PluginStructs/P094_data_struct.h +++ b/src/src/PluginStructs/P094_data_struct.h @@ -8,15 +8,16 @@ # include -# define P094_REGEX_POS 0 -# define P094_NR_CHAR_USE_POS 1 +# define P094_REGEX_POS 0 +# define P094_NR_CHAR_USE_POS 1 # define P094_FILTER_OFF_WINDOW_POS 2 -# define P094_MATCH_TYPE_POS 3 +# define P094_MATCH_TYPE_POS 3 # define P094_FIRST_FILTER_POS 10 -# define P094_NR_FILTERS 10 -# define P094_ITEMS_PER_FILTER 12 +# define P094_ITEMS_PER_FILTER 4 +# define P094_AND_FILTER_BLOCK 3 +# define P094_NR_FILTERS (7 * P094_AND_FILTER_BLOCK) # define P94_Nlines (P094_FIRST_FILTER_POS + (P094_ITEMS_PER_FILTER * (P094_NR_FILTERS))) # define P94_Nchars 128 # define P94_MAX_CAPTURE_INDEX 32 @@ -30,14 +31,14 @@ enum P094_Match_Type { # define P094_Match_Type_NR_ELEMENTS 3 enum P094_Filter_Value_Type { - P094_not_used = 0, - P094_packet_length = 1, - P094_unknown1 = 2, - P094_manufacturer = 3, - P094_serial_number = 4, - P094_unknown2 = 5, - P094_meter_type = 6, - P094_rssi = 7 + P094_not_used = 0, + P094_packet_length = 1, + P094_unknown1 = 2, + P094_manufacturer = 3, + P094_serial_number = 4, + P094_unknown2 = 5, + P094_meter_type = 6, + P094_rssi = 7 }; # define P094_FILTER_VALUE_Type_NR_ELEMENTS 8 @@ -51,7 +52,6 @@ enum P094_Filter_Comp { # define P094_FILTER_COMP_NR_ELEMENTS 4 - struct P094_data_struct : public PluginTaskData_base { public: @@ -79,10 +79,10 @@ public: uint32_t& error, uint32_t& length_last) const; - void setMaxLength(uint16_t maxlenght); + void setMaxLength(uint16_t maxlenght); - void setLine(byte varNr, - const String& line); + void setLine(byte varNr, + const String& line); uint32_t getFilterOffWindowTime() const; @@ -91,15 +91,16 @@ public: bool invertMatch() const; + bool filterUsed(uint8_t lineNr) const; - String getFilter(uint8_t lineNr, + String getFilter(uint8_t lineNr, P094_Filter_Value_Type& capture, - uint32_t& optional, - P094_Filter_Comp& comparator) const; + uint32_t & optional, + P094_Filter_Comp & comparator) const; - void setDisableFilterWindowTimer(); + void setDisableFilterWindowTimer(); - bool disableFilterWindowActive() const; + bool disableFilterWindowActive() const; bool parsePacket(String& received) const; @@ -111,10 +112,11 @@ public: // Made public so we don't have to copy the values when loading/saving. String _lines[P94_Nlines]; + static size_t P094_Get_filter_base_index(size_t filterLine); + private: bool max_length_reached() const; - size_t get_filter_base_index(size_t filterLine) const; ESPeasySerial *easySerial = nullptr; String sentence_part; @@ -124,11 +126,9 @@ private: uint32_t length_last_received = 0; unsigned long disable_filter_window = 0; - bool valueType_used[P094_FILTER_VALUE_Type_NR_ELEMENTS]; + bool valueType_used[P094_FILTER_VALUE_Type_NR_ELEMENTS]; P094_Filter_Value_Type valueType_index[P094_NR_FILTERS]; - P094_Filter_Comp filter_comp[P094_NR_FILTERS]; - - + P094_Filter_Comp filter_comp[P094_NR_FILTERS]; };