From e43325e42b71920de971fa2672f8d2ab21d45547 Mon Sep 17 00:00:00 2001 From: Waldemar Porscha Date: Tue, 16 Jan 2024 00:39:26 +0100 Subject: [PATCH 1/4] New implementation of Uninitialized state for group object - old implementation is still there for compatibility reasons - new implementation reflects the case "uninitialized while transmitting" - Just states "Updated", "WriteRequest" and "Ok" remove uninitialized state --- src/knx/group_object.cpp | 29 ++++++++++++++++++++--------- src/knx/group_object.h | 19 +++++++++++++++++-- 2 files changed, 37 insertions(+), 11 deletions(-) diff --git a/src/knx/group_object.cpp b/src/knx/group_object.cpp index b7c74d8..aa75318 100644 --- a/src/knx/group_object.cpp +++ b/src/knx/group_object.cpp @@ -12,7 +12,8 @@ GroupObjectTableObject* GroupObject::_table = 0; GroupObject::GroupObject() { _data = 0; - _commFlag = Uninitialized; + _commFlagEx.uninitialized = true; + _commFlagEx.commFlag = Uninitialized; _dataLength = 0; #ifndef SMALL_GROUPOBJECT _updateHandler = 0; @@ -22,7 +23,7 @@ GroupObject::GroupObject() GroupObject::GroupObject(const GroupObject& other) { _data = new uint8_t[other._dataLength]; - _commFlag = other._commFlag; + _commFlagEx = other._commFlagEx; _dataLength = other._dataLength; _asap = other._asap; #ifndef SMALL_GROUPOBJECT @@ -75,7 +76,7 @@ bool GroupObject::readEnable() return false; // we forbid reading of new (uninitialized) go - if (_commFlag == Uninitialized) + if (_commFlagEx.uninitialized) return false; return bitRead(ntohs(_table->_tableData[_asap]), 11) > 0; @@ -157,22 +158,29 @@ size_t GroupObject::asapValueSize(uint8_t code) ComFlag GroupObject::commFlag() { - return _commFlag; + return _commFlagEx.commFlag; } void GroupObject::commFlag(ComFlag value) { - _commFlag = value; + _commFlagEx.commFlag = value; + if (value == WriteRequest || value == Updated || value == Ok) + _commFlagEx.uninitialized = false; +} + +bool GroupObject::initialized() +{ + return !_commFlagEx.uninitialized; } void GroupObject::requestObjectRead() { - _commFlag = ReadRequest; + _commFlagEx.commFlag = ReadRequest; } void GroupObject::objectWritten() { - _commFlag = WriteRequest; + _commFlagEx.commFlag = WriteRequest; } size_t GroupObject::valueSize() @@ -274,8 +282,11 @@ void GroupObject::valueNoSend(const KNXValue& value) void GroupObject::valueNoSend(const KNXValue& value, const Dpt& type) { - if (_commFlag == Uninitialized) - _commFlag = Ok; + if (_commFlagEx.uninitialized) + { + _commFlagEx.commFlag = Ok; + _commFlagEx.uninitialized = false; + } KNX_Encode_Value(value, _data, _dataLength, type); } diff --git a/src/knx/group_object.h b/src/knx/group_object.h index 7c9191b..38b8291 100644 --- a/src/knx/group_object.h +++ b/src/knx/group_object.h @@ -7,7 +7,7 @@ class GroupObjectTableObject; -enum ComFlag +enum ComFlag : uint8_t { Updated = 0, //!< Group object was updated ReadRequest = 1, //!< Read was requested but was not processed @@ -18,6 +18,16 @@ enum ComFlag Uninitialized = 6 //!< uninitialized Group Object, its value is not valid }; +// extended ComFlag: Uninitialized it not handled correctly as ComFlag +// it might be in state Transmitting during a ReadRequest on startup while value is still not valid +// we use MSB to store Uninitialized and keep the size of GroupObject the same saving memory ressources +// the old Uninitialized handling is still there for compatibility reasons. +struct ComFlagEx +{ + bool uninitialized : 1; + ComFlag commFlag : 7; +}; + class GroupObject; #ifndef HAS_FUNCTIONAL @@ -96,6 +106,11 @@ class GroupObject */ void commFlag(ComFlag value); + /** + * Check if the group object contains a valid value assigned from bus or from application program + */ + bool initialized(); + /** * Request the read of a communication object. Calling this function triggers the * sending of a read-group-value telegram, to read the value of the communication @@ -249,7 +264,7 @@ class GroupObject size_t asapValueSize(uint8_t code); size_t goSize(); uint16_t _asap = 0; - ComFlag _commFlag = Uninitialized; + ComFlagEx _commFlagEx; uint8_t* _data = 0; uint8_t _dataLength = 0; #ifndef SMALL_GROUPOBJECT From 7b8db75d5c5c04f74ca76fad1e0d647a644c2477 Mon Sep 17 00:00:00 2001 From: Waldemar Porscha Date: Thu, 18 Jan 2024 22:43:31 +0100 Subject: [PATCH 2/4] Finalize uninitialized handling --- src/knx/group_object.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/knx/group_object.cpp b/src/knx/group_object.cpp index aa75318..80865f4 100644 --- a/src/knx/group_object.cpp +++ b/src/knx/group_object.cpp @@ -175,12 +175,12 @@ bool GroupObject::initialized() void GroupObject::requestObjectRead() { - _commFlagEx.commFlag = ReadRequest; + commFlag(ReadRequest); } void GroupObject::objectWritten() { - _commFlagEx.commFlag = WriteRequest; + commFlag(WriteRequest); } size_t GroupObject::valueSize() @@ -283,10 +283,7 @@ void GroupObject::valueNoSend(const KNXValue& value) void GroupObject::valueNoSend(const KNXValue& value, const Dpt& type) { if (_commFlagEx.uninitialized) - { - _commFlagEx.commFlag = Ok; - _commFlagEx.uninitialized = false; - } + commFlag(Ok); KNX_Encode_Value(value, _data, _dataLength, type); } From 96bd0ee9eca473a5cafeb92b7e372e9a84d6969f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cornelius=20K=C3=B6pp?= Date: Mon, 22 Jan 2024 20:47:59 +0100 Subject: [PATCH 3/4] Fix for New Uninitialized-Handling --- 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 80865f4..0abbfc0 100644 --- a/src/knx/group_object.cpp +++ b/src/knx/group_object.cpp @@ -290,7 +290,7 @@ void GroupObject::valueNoSend(const KNXValue& value, const Dpt& type) bool GroupObject::valueNoSendCompare(const KNXValue& value, const Dpt& type) { - if (_commFlag == Uninitialized) + if (_commFlagEx.uninitialized) { // always set first value this->valueNoSend(value, type); From 21ab50fd009d88f44a33ffc9bc6ab9f00328a47a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cornelius=20K=C3=B6pp?= Date: Mon, 12 Feb 2024 23:11:00 +0100 Subject: [PATCH 4/4] Document ComFlagEx for Uninitialized State Handling Fix --- src/knx/group_object.h | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/knx/group_object.h b/src/knx/group_object.h index 38b8291..85975be 100644 --- a/src/knx/group_object.h +++ b/src/knx/group_object.h @@ -7,6 +7,12 @@ class GroupObjectTableObject; +/** + * LIMITATION: The differentiation between uninitialized and initialized state can NOT be represented correctly in ComFlag alone: + * It might be in state Transmitting during a ReadRequest on startup while value is still not valid. + * + * See ComFlagEx for a clear uninitialized handling. + */ enum ComFlag : uint8_t { Updated = 0, //!< Group object was updated @@ -15,13 +21,17 @@ enum ComFlag : uint8_t Transmitting = 3, //!< Group Object is processed a the moment (read or write) Ok = 4, //!< read or write request were send successfully Error = 5, //!< there was an error on processing a request - Uninitialized = 6 //!< uninitialized Group Object, its value is not valid + Uninitialized = 6 //!< uninitialized Group Object, its value is not valid; WARNING: Other Values do NOT guarantee an actual valid value! }; -// extended ComFlag: Uninitialized it not handled correctly as ComFlag -// it might be in state Transmitting during a ReadRequest on startup while value is still not valid -// we use MSB to store Uninitialized and keep the size of GroupObject the same saving memory ressources -// the old Uninitialized handling is still there for compatibility reasons. +/** + * Extended ComFlag + * Add a separate uninitialized flag to overcome the limitations of ComFlag. + * + * Implementation Note: + * We use MSB to store uninitialized state and keep the size of GroupObject the same saving memory resources. + * The old uninitialized handling is not changed for compatibility reasons. + */ struct ComFlagEx { bool uninitialized : 1;