Merge pull request #279 from OpenKNX/fix/ko-state-uninitialized

Fix: Group-Object `_commFlag != Uninitialized` does NOT Guarantee an Actual Initialization
This commit is contained in:
thelsing 2024-08-09 19:55:47 +02:00 committed by GitHub
commit 484e6ce888
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 46 additions and 13 deletions

View File

@ -12,7 +12,8 @@ GroupObjectTableObject* GroupObject::_table = 0;
GroupObject::GroupObject() GroupObject::GroupObject()
{ {
_data = 0; _data = 0;
_commFlag = Uninitialized; _commFlagEx.uninitialized = true;
_commFlagEx.commFlag = Uninitialized;
_dataLength = 0; _dataLength = 0;
#ifndef SMALL_GROUPOBJECT #ifndef SMALL_GROUPOBJECT
_updateHandler = 0; _updateHandler = 0;
@ -22,7 +23,7 @@ GroupObject::GroupObject()
GroupObject::GroupObject(const GroupObject& other) GroupObject::GroupObject(const GroupObject& other)
{ {
_data = new uint8_t[other._dataLength]; _data = new uint8_t[other._dataLength];
_commFlag = other._commFlag; _commFlagEx = other._commFlagEx;
_dataLength = other._dataLength; _dataLength = other._dataLength;
_asap = other._asap; _asap = other._asap;
#ifndef SMALL_GROUPOBJECT #ifndef SMALL_GROUPOBJECT
@ -75,7 +76,7 @@ bool GroupObject::readEnable()
return false; return false;
// we forbid reading of new (uninitialized) go // we forbid reading of new (uninitialized) go
if (_commFlag == Uninitialized) if (_commFlagEx.uninitialized)
return false; return false;
return bitRead(ntohs(_table->_tableData[_asap]), 11) > 0; return bitRead(ntohs(_table->_tableData[_asap]), 11) > 0;
@ -157,22 +158,29 @@ size_t GroupObject::asapValueSize(uint8_t code)
ComFlag GroupObject::commFlag() ComFlag GroupObject::commFlag()
{ {
return _commFlag; return _commFlagEx.commFlag;
} }
void GroupObject::commFlag(ComFlag value) 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() void GroupObject::requestObjectRead()
{ {
_commFlag = ReadRequest; commFlag(ReadRequest);
} }
void GroupObject::objectWritten() void GroupObject::objectWritten()
{ {
_commFlag = WriteRequest; commFlag(WriteRequest);
} }
size_t GroupObject::valueSize() size_t GroupObject::valueSize()
@ -274,15 +282,15 @@ void GroupObject::valueNoSend(const KNXValue& value)
void GroupObject::valueNoSend(const KNXValue& value, const Dpt& type) void GroupObject::valueNoSend(const KNXValue& value, const Dpt& type)
{ {
if (_commFlag == Uninitialized) if (_commFlagEx.uninitialized)
_commFlag = Ok; commFlag(Ok);
KNX_Encode_Value(value, _data, _dataLength, type); KNX_Encode_Value(value, _data, _dataLength, type);
} }
bool GroupObject::valueNoSendCompare(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 // always set first value
this->valueNoSend(value, type); this->valueNoSend(value, type);

View File

@ -7,7 +7,13 @@
class GroupObjectTableObject; class GroupObjectTableObject;
enum ComFlag /**
* 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 Updated = 0, //!< Group object was updated
ReadRequest = 1, //!< Read was requested but was not processed ReadRequest = 1, //!< Read was requested but was not processed
@ -15,7 +21,21 @@ enum ComFlag
Transmitting = 3, //!< Group Object is processed a the moment (read or write) Transmitting = 3, //!< Group Object is processed a the moment (read or write)
Ok = 4, //!< read or write request were send successfully Ok = 4, //!< read or write request were send successfully
Error = 5, //!< there was an error on processing a request 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
* 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;
ComFlag commFlag : 7;
}; };
class GroupObject; class GroupObject;
@ -96,6 +116,11 @@ class GroupObject
*/ */
void commFlag(ComFlag value); 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 * 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 * sending of a read-group-value telegram, to read the value of the communication
@ -249,7 +274,7 @@ class GroupObject
size_t asapValueSize(uint8_t code); size_t asapValueSize(uint8_t code);
size_t goSize(); size_t goSize();
uint16_t _asap = 0; uint16_t _asap = 0;
ComFlag _commFlag = Uninitialized; ComFlagEx _commFlagEx;
uint8_t* _data = 0; uint8_t* _data = 0;
uint8_t _dataLength = 0; uint8_t _dataLength = 0;
#ifndef SMALL_GROUPOBJECT #ifndef SMALL_GROUPOBJECT