From 1eb4a797a571a60830168629f38a4da736a1db78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cornelius=20K=C3=B6pp?= Date: Sun, 13 Aug 2023 22:01:45 +0200 Subject: [PATCH 1/9] Allow Updating ComObject with Sending On Modification Only --- src/knx/group_object.cpp | 15 +++++++++++++++ src/knx/group_object.h | 10 ++++++++++ 2 files changed, 25 insertions(+) diff --git a/src/knx/group_object.cpp b/src/knx/group_object.cpp index 6898ba5b..432dfd67 100644 --- a/src/knx/group_object.cpp +++ b/src/knx/group_object.cpp @@ -279,3 +279,18 @@ void GroupObject::valueNoSend(const KNXValue& value, const Dpt& type) KNX_Encode_Value(value, _data, _dataLength, type); } + +void GroupObject::valueSendChangedOnly(const KNXValue& value, const Dpt& type) +{ + // save current value + const uint8_t oldLength = _dataLength; + uint8_t* old = new uint8_t[_dataLength]; + memcpy(old, _data, oldLength); + + // update value in com-object, without sending to bus + valueNoSend(value, type); + + // only when raw data differs trigger sending + if (oldLength!=_dataLength || memcmp(old, _data, oldLength)!=0) + objectWritten(); +} \ No newline at end of file diff --git a/src/knx/group_object.h b/src/knx/group_object.h index 88ce274f..657446f0 100644 --- a/src/knx/group_object.h +++ b/src/knx/group_object.h @@ -166,6 +166,16 @@ class GroupObject * The parameters must fit the group object. Otherwise it will stay unchanged. */ void valueNoSend(const KNXValue& value, const Dpt& type); + + /** + * set the current value of the group object and only when resulting value differes, changes the state of the group object to ::WriteRequest. + * @param value the value the group object is set to + * @param type the datapoint type used for the conversion. + * + * The parameters must fit the group object. Otherwise it will stay unchanged. + */ + void valueSendChangedOnly(const KNXValue& value, const Dpt& type); + /** * set the current value of the group object. * @param value the value the group object is set to From fbc9b42395b926af329a08218cf1499d1211e621 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cornelius=20K=C3=B6pp?= Date: Sun, 13 Aug 2023 22:08:19 +0200 Subject: [PATCH 2/9] Sending on Modification Only: Return if Value was Changed and Send to Bus is Triggered --- src/knx/group_object.cpp | 7 +++++-- src/knx/group_object.h | 4 +++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/knx/group_object.cpp b/src/knx/group_object.cpp index 432dfd67..8282c5a9 100644 --- a/src/knx/group_object.cpp +++ b/src/knx/group_object.cpp @@ -280,7 +280,7 @@ void GroupObject::valueNoSend(const KNXValue& value, const Dpt& type) KNX_Encode_Value(value, _data, _dataLength, type); } -void GroupObject::valueSendChangedOnly(const KNXValue& value, const Dpt& type) +bool GroupObject::valueSendChangedOnly(const KNXValue& value, const Dpt& type) { // save current value const uint8_t oldLength = _dataLength; @@ -291,6 +291,9 @@ void GroupObject::valueSendChangedOnly(const KNXValue& value, const Dpt& type) valueNoSend(value, type); // only when raw data differs trigger sending - if (oldLength!=_dataLength || memcmp(old, _data, oldLength)!=0) + const bool dataChanged = oldLength!=_dataLength || memcmp(old, _data, oldLength)!=0; + if (dataChanged) objectWritten(); + + return dataChanged; } \ No newline at end of file diff --git a/src/knx/group_object.h b/src/knx/group_object.h index 657446f0..50c5d314 100644 --- a/src/knx/group_object.h +++ b/src/knx/group_object.h @@ -173,8 +173,10 @@ class GroupObject * @param type the datapoint type used for the conversion. * * The parameters must fit the group object. Otherwise it will stay unchanged. + * + * @returns true if the value of the group object has changed (and send was triggered) */ - void valueSendChangedOnly(const KNXValue& value, const Dpt& type); + bool valueSendChangedOnly(const KNXValue& value, const Dpt& type); /** * set the current value of the group object. From db8782eb2215ab5cead4d119deed83195d18bf3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cornelius=20K=C3=B6pp?= Date: Sun, 13 Aug 2023 22:10:36 +0200 Subject: [PATCH 3/9] `valueSendChangedOnly`: Rename to `valueModifiedSend` analoge to `valueNoSend` --- src/knx/group_object.cpp | 2 +- src/knx/group_object.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/knx/group_object.cpp b/src/knx/group_object.cpp index 8282c5a9..076a65ac 100644 --- a/src/knx/group_object.cpp +++ b/src/knx/group_object.cpp @@ -280,7 +280,7 @@ void GroupObject::valueNoSend(const KNXValue& value, const Dpt& type) KNX_Encode_Value(value, _data, _dataLength, type); } -bool GroupObject::valueSendChangedOnly(const KNXValue& value, const Dpt& type) +bool GroupObject::valueModifiedSend(const KNXValue& value, const Dpt& type) { // save current value const uint8_t oldLength = _dataLength; diff --git a/src/knx/group_object.h b/src/knx/group_object.h index 50c5d314..29405784 100644 --- a/src/knx/group_object.h +++ b/src/knx/group_object.h @@ -176,7 +176,7 @@ class GroupObject * * @returns true if the value of the group object has changed (and send was triggered) */ - bool valueSendChangedOnly(const KNXValue& value, const Dpt& type); + bool valueModifiedSend(const KNXValue& value, const Dpt& type); /** * set the current value of the group object. From 96a535df1b855e7bd6b7b93b91e3fe0736cd2f5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cornelius=20K=C3=B6pp?= Date: Thu, 7 Sep 2023 23:43:04 +0200 Subject: [PATCH 4/9] Always Send the First Value Set --- src/knx/group_object.cpp | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/src/knx/group_object.cpp b/src/knx/group_object.cpp index 076a65ac..9df890be 100644 --- a/src/knx/group_object.cpp +++ b/src/knx/group_object.cpp @@ -282,18 +282,27 @@ void GroupObject::valueNoSend(const KNXValue& value, const Dpt& type) bool GroupObject::valueModifiedSend(const KNXValue& value, const Dpt& type) { - // save current value - const uint8_t oldLength = _dataLength; - uint8_t* old = new uint8_t[_dataLength]; - memcpy(old, _data, oldLength); + if (_commFlag == Uninitialized) + { + // always send first value + this->value(value, type); + return true; + } + else + { + // save current value + const uint8_t oldLength = _dataLength; + uint8_t* old = new uint8_t[_dataLength]; + memcpy(old, _data, oldLength); - // update value in com-object, without sending to bus - valueNoSend(value, type); + // update value in com-object, without sending to bus + valueNoSend(value, type); - // only when raw data differs trigger sending - const bool dataChanged = oldLength!=_dataLength || memcmp(old, _data, oldLength)!=0; - if (dataChanged) - objectWritten(); + // only when raw data differs trigger sending + const bool dataChanged = oldLength!=_dataLength || memcmp(old, _data, oldLength)!=0; + if (dataChanged) + objectWritten(); - return dataChanged; + return dataChanged; + } } \ No newline at end of file From 5c20621406868d4e76fd49ce8c762cfd86a38f14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cornelius=20K=C3=B6pp?= Date: Thu, 7 Sep 2023 23:47:11 +0200 Subject: [PATCH 5/9] Fix: Free Memory of Old Value --- src/knx/group_object.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/knx/group_object.cpp b/src/knx/group_object.cpp index 9df890be..6dd27b47 100644 --- a/src/knx/group_object.cpp +++ b/src/knx/group_object.cpp @@ -300,6 +300,7 @@ bool GroupObject::valueModifiedSend(const KNXValue& value, const Dpt& type) // only when raw data differs trigger sending const bool dataChanged = oldLength!=_dataLength || memcmp(old, _data, oldLength)!=0; + delete[] old; if (dataChanged) objectWritten(); From 2400da45ee09734cc5df7a9ccef7440e022f9ea8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cornelius=20K=C3=B6pp?= Date: Thu, 7 Sep 2023 23:58:12 +0200 Subject: [PATCH 6/9] Allow Forced Sending, independent of Change --- src/knx/group_object.cpp | 4 ++-- src/knx/group_object.h | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/knx/group_object.cpp b/src/knx/group_object.cpp index 6dd27b47..3605edf3 100644 --- a/src/knx/group_object.cpp +++ b/src/knx/group_object.cpp @@ -280,7 +280,7 @@ void GroupObject::valueNoSend(const KNXValue& value, const Dpt& type) KNX_Encode_Value(value, _data, _dataLength, type); } -bool GroupObject::valueModifiedSend(const KNXValue& value, const Dpt& type) +bool GroupObject::valueModifiedSend(const KNXValue& value, const Dpt& type, const bool forceSend /*= false*/) { if (_commFlag == Uninitialized) { @@ -301,7 +301,7 @@ bool GroupObject::valueModifiedSend(const KNXValue& value, const Dpt& type) // only when raw data differs trigger sending const bool dataChanged = oldLength!=_dataLength || memcmp(old, _data, oldLength)!=0; delete[] old; - if (dataChanged) + if (dataChanged || forceSend) objectWritten(); return dataChanged; diff --git a/src/knx/group_object.h b/src/knx/group_object.h index 29405784..a4f05142 100644 --- a/src/knx/group_object.h +++ b/src/knx/group_object.h @@ -171,12 +171,13 @@ class GroupObject * set the current value of the group object and only when resulting value differes, changes the state of the group object to ::WriteRequest. * @param value the value the group object is set to * @param type the datapoint type used for the conversion. + * @param forceSend (optional) trigger sending independend of value change. Use e.g. for repeated sending. * * The parameters must fit the group object. Otherwise it will stay unchanged. * * @returns true if the value of the group object has changed (and send was triggered) */ - bool valueModifiedSend(const KNXValue& value, const Dpt& type); + bool valueModifiedSend(const KNXValue& value, const Dpt& type, const bool forceSend = false); /** * set the current value of the group object. From c05276b4af13a9de24ec61cb4c4c94b907681cb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cornelius=20K=C3=B6pp?= Date: Fri, 8 Sep 2023 18:27:01 +0200 Subject: [PATCH 7/9] Optimize valueModifiedSend: Copy on Changes Only --- src/knx/group_object.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/knx/group_object.cpp b/src/knx/group_object.cpp index 3605edf3..f4cf65f4 100644 --- a/src/knx/group_object.cpp +++ b/src/knx/group_object.cpp @@ -290,17 +290,16 @@ bool GroupObject::valueModifiedSend(const KNXValue& value, const Dpt& type, cons } else { - // save current value - const uint8_t oldLength = _dataLength; - uint8_t* old = new uint8_t[_dataLength]; - memcpy(old, _data, oldLength); + // convert new value to given dtp + uint8_t newData[_dataLength]; + KNX_Encode_Value(value, newData, _dataLength, type); - // update value in com-object, without sending to bus - valueNoSend(value, type); + // check for change in converted value / update value on change only + const bool dataChanged = memcmp(_data, newData, _dataLength); + if (dataChanged) + memcpy(_data, newData, _dataLength); - // only when raw data differs trigger sending - const bool dataChanged = oldLength!=_dataLength || memcmp(old, _data, oldLength)!=0; - delete[] old; + // trigger sending if (dataChanged || forceSend) objectWritten(); From d53bbf307f7b7ba0e63e95b91dd38afe747e1b61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cornelius=20K=C3=B6pp?= Date: Mon, 18 Sep 2023 18:56:46 +0200 Subject: [PATCH 8/9] Make Comparison Independent of Sending --- src/knx/group_object.cpp | 10 +++------- src/knx/group_object.h | 7 +++---- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/src/knx/group_object.cpp b/src/knx/group_object.cpp index f4cf65f4..5a973ca4 100644 --- a/src/knx/group_object.cpp +++ b/src/knx/group_object.cpp @@ -280,12 +280,12 @@ void GroupObject::valueNoSend(const KNXValue& value, const Dpt& type) KNX_Encode_Value(value, _data, _dataLength, type); } -bool GroupObject::valueModifiedSend(const KNXValue& value, const Dpt& type, const bool forceSend /*= false*/) +bool GroupObject::valueNoSendCompare(const KNXValue& value, const Dpt& type) { if (_commFlag == Uninitialized) { - // always send first value - this->value(value, type); + // always set first value + this->valueNoSend(value, type); return true; } else @@ -299,10 +299,6 @@ bool GroupObject::valueModifiedSend(const KNXValue& value, const Dpt& type, cons if (dataChanged) memcpy(_data, newData, _dataLength); - // trigger sending - if (dataChanged || forceSend) - objectWritten(); - return dataChanged; } } \ No newline at end of file diff --git a/src/knx/group_object.h b/src/knx/group_object.h index a4f05142..ca79c985 100644 --- a/src/knx/group_object.h +++ b/src/knx/group_object.h @@ -168,16 +168,15 @@ class GroupObject void valueNoSend(const KNXValue& value, const Dpt& type); /** - * set the current value of the group object and only when resulting value differes, changes the state of the group object to ::WriteRequest. + * check if the value (after conversion to dpt) will differ from current value of the group object and update if necessary. * @param value the value the group object is set to * @param type the datapoint type used for the conversion. - * @param forceSend (optional) trigger sending independend of value change. Use e.g. for repeated sending. * * The parameters must fit the group object. Otherwise it will stay unchanged. * - * @returns true if the value of the group object has changed (and send was triggered) + * @returns true if the value of the group object has changed */ - bool valueModifiedSend(const KNXValue& value, const Dpt& type, const bool forceSend = false); + bool valueNoSendCompare(const KNXValue& value, const Dpt& type); /** * set the current value of the group object. From f1327a7e6c47f6c4790cc86abce0b1bfb4a7c928 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cornelius=20K=C3=B6pp?= Date: Mon, 18 Sep 2023 20:23:06 +0200 Subject: [PATCH 9/9] Fix: Prevent False-Positive Change-Detection from Undefined Bits in (at least) DPT1 --- src/knx/group_object.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/knx/group_object.cpp b/src/knx/group_object.cpp index 5a973ca4..3ade6c51 100644 --- a/src/knx/group_object.cpp +++ b/src/knx/group_object.cpp @@ -291,7 +291,7 @@ bool GroupObject::valueNoSendCompare(const KNXValue& value, const Dpt& type) else { // convert new value to given dtp - uint8_t newData[_dataLength]; + uint8_t newData[_dataLength] = {0}; KNX_Encode_Value(value, newData, _dataLength, type); // check for change in converted value / update value on change only