Merge branch 'openknx-version-support' of https://github.com/thelsing/knx into openknx-version-support

This commit is contained in:
Waldemar Porscha 2022-03-02 11:24:40 +01:00
commit 39af540c49
13 changed files with 107 additions and 54 deletions

View File

@ -19,7 +19,8 @@ AddressTableObject::AddressTableObject(Memory& memory)
uint16_t AddressTableObject::entryCount() uint16_t AddressTableObject::entryCount()
{ {
if (loadState() != LS_LOADED) // after programming without GA the module hangs
if (loadState() != LS_LOADED || _groupAddresses[0] == 0xFFFF)
return 0; return 0;
return ntohs(_groupAddresses[0]); return ntohs(_groupAddresses[0]);
@ -67,6 +68,7 @@ bool AddressTableObject::contains(uint16_t addr)
void AddressTableObject::beforeStateChange(LoadState& newState) void AddressTableObject::beforeStateChange(LoadState& newState)
{ {
TableObject::beforeStateChange(newState);
if (newState != LS_LOADED) if (newState != LS_LOADED)
return; return;

View File

@ -60,6 +60,7 @@ int32_t AssociationTableObject::translateAsap(uint16_t asap)
void AssociationTableObject::beforeStateChange(LoadState& newState) void AssociationTableObject::beforeStateChange(LoadState& newState)
{ {
TableObject::beforeStateChange(newState);
if (newState != LS_LOADED) if (newState != LS_LOADED)
return; return;

View File

@ -338,3 +338,12 @@ void BusAccessUnit::propertyValueWrite(ObjectType objectType, uint8_t objectInst
uint8_t* data, uint32_t length) uint8_t* data, uint32_t length)
{ {
} }
void BusAccessUnit::beforeRestartCallback(BeforeRestartCallback func)
{
}
BeforeRestartCallback BusAccessUnit::beforeRestartCallback()
{
return 0;
}

View File

@ -3,6 +3,8 @@
#include "knx_types.h" #include "knx_types.h"
#include "interface_object.h" #include "interface_object.h"
typedef void (*BeforeRestartCallback)(void);
class BusAccessUnit class BusAccessUnit
{ {
public: public:
@ -161,4 +163,6 @@ class BusAccessUnit
virtual void propertyValueWrite(ObjectType objectType, uint8_t objectInstance, uint8_t propertyId, virtual void propertyValueWrite(ObjectType objectType, uint8_t objectInstance, uint8_t propertyId,
uint8_t& numberOfElements, uint16_t startIndex, uint8_t& numberOfElements, uint16_t startIndex,
uint8_t* data, uint32_t length); uint8_t* data, uint32_t length);
virtual void beforeRestartCallback(BeforeRestartCallback func);
virtual BeforeRestartCallback beforeRestartCallback();
}; };

View File

@ -152,6 +152,8 @@ void BauSystemB::restartRequestIndication(Priority priority, HopCountType hopTyp
if (restartType == RestartType::BasicRestart) if (restartType == RestartType::BasicRestart)
{ {
println("Basic restart requested"); println("Basic restart requested");
if (_beforeRestart != 0)
_beforeRestart();
} }
else if (restartType == RestartType::MasterReset) else if (restartType == RestartType::MasterReset)
{ {
@ -621,3 +623,13 @@ VersionCheckCallback BauSystemB::versionCheckCallback()
{ {
return _memory.versionCheckCallback(); return _memory.versionCheckCallback();
} }
void BauSystemB::beforeRestartCallback(BeforeRestartCallback func)
{
_beforeRestart = func;
}
BeforeRestartCallback BauSystemB::beforeRestartCallback()
{
return _beforeRestart;
}

View File

@ -40,6 +40,8 @@ class BauSystemB : protected BusAccessUnit
uint8_t* data, uint32_t length) override; uint8_t* data, uint32_t length) override;
void versionCheckCallback(VersionCheckCallback func); void versionCheckCallback(VersionCheckCallback func);
VersionCheckCallback versionCheckCallback(); VersionCheckCallback versionCheckCallback();
void beforeRestartCallback(BeforeRestartCallback func);
BeforeRestartCallback beforeRestartCallback();
protected: protected:
virtual ApplicationLayer& applicationLayer() = 0; virtual ApplicationLayer& applicationLayer() = 0;
@ -109,4 +111,5 @@ class BauSystemB : protected BusAccessUnit
RestartState _restartState = Idle; RestartState _restartState = Idle;
SecurityControl _restartSecurity; SecurityControl _restartSecurity;
uint32_t _restartDelay = 0; uint32_t _restartDelay = 0;
BeforeRestartCallback _beforeRestart = 0;
}; };

View File

@ -74,6 +74,10 @@ bool GroupObject::readEnable()
if (!_table) if (!_table)
return false; return false;
// we forbid reading of new (uninitialized) go
if (_commFlag == Uninitialized)
return false;
return bitRead(ntohs(_table->_tableData[_asap]), 11) > 0; return bitRead(ntohs(_table->_tableData[_asap]), 11) > 0;
} }
@ -270,5 +274,8 @@ 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)
_commFlag = Ok;
KNX_Encode_Value(value, _data, _dataLength, type); KNX_Encode_Value(value, _data, _dataLength, type);
} }

View File

@ -14,7 +14,8 @@ enum ComFlag
WriteRequest = 2, //!< Write was requested but was not processed WriteRequest = 2, //!< Write was requested but was not processed
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
}; };
class GroupObject; class GroupObject;
@ -235,7 +236,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 = Ok; ComFlag _commFlag = Uninitialized;
uint8_t* _data = 0; uint8_t* _data = 0;
uint8_t _dataLength = 0; uint8_t _dataLength = 0;
#ifndef SMALL_GROUPOBJECT #ifndef SMALL_GROUPOBJECT

View File

@ -77,6 +77,7 @@ void GroupObjectTableObject::groupObjects(GroupObject * objs, uint16_t size)
void GroupObjectTableObject::beforeStateChange(LoadState& newState) void GroupObjectTableObject::beforeStateChange(LoadState& newState)
{ {
TableObject::beforeStateChange(newState);
if (newState != LS_LOADED) if (newState != LS_LOADED)
return; return;

View File

@ -6,6 +6,19 @@
#include "callback_property.h" #include "callback_property.h"
#include "data_property.h" #include "data_property.h"
BeforeTablesUnloadCallback TableObject::_beforeTablesUnload = 0;
uint8_t TableObject::_tableUnloadCount = 0;
void TableObject::beforeTablesUnloadCallback(BeforeTablesUnloadCallback func)
{
_beforeTablesUnload = func;
}
BeforeTablesUnloadCallback TableObject::beforeTablesUnloadCallback()
{
return _beforeTablesUnload;
}
TableObject::TableObject(Memory& memory) TableObject::TableObject(Memory& memory)
: _memory(memory) : _memory(memory)
{} {}
@ -13,6 +26,19 @@ TableObject::TableObject(Memory& memory)
TableObject::~TableObject() TableObject::~TableObject()
{} {}
void TableObject::beforeStateChange(LoadState& newState)
{
if (newState == LS_LOADED && _tableUnloadCount > 0)
_tableUnloadCount--;
if (_tableUnloadCount > 0)
return;
if (newState == LS_UNLOADED) {
_tableUnloadCount++;
if (_beforeTablesUnload != 0)
_beforeTablesUnload();
}
}
LoadState TableObject::loadState() LoadState TableObject::loadState()
{ {
return _state; return _state;

View File

@ -3,6 +3,9 @@
#include "interface_object.h" #include "interface_object.h"
class Memory; class Memory;
typedef void (*BeforeTablesUnloadCallback)();
/** /**
* This class provides common functionality for interface objects that are configured by ETS with MemorWrite. * This class provides common functionality for interface objects that are configured by ETS with MemorWrite.
*/ */
@ -28,13 +31,17 @@ class TableObject: public InterfaceObject
uint8_t* save(uint8_t* buffer) override; uint8_t* save(uint8_t* buffer) override;
const uint8_t* restore(const uint8_t* buffer) override; const uint8_t* restore(const uint8_t* buffer) override;
uint16_t saveSize() override; uint16_t saveSize() override;
static void beforeTablesUnloadCallback(BeforeTablesUnloadCallback func);
static BeforeTablesUnloadCallback beforeTablesUnloadCallback();
protected: protected:
/** /**
* This method is called before the interface object enters a new ::LoadState. * This method is called before the interface object enters a new ::LoadState.
* If there is a error changing the state newState should be set to ::LS_ERROR and errorCode() * If there is a error changing the state newState should be set to ::LS_ERROR and errorCode()
* to a reason for the failure. * to a reason for the failure.
*/ */
virtual void beforeStateChange(LoadState& newState) {} virtual void beforeStateChange(LoadState& newState);
/** /**
* returns the internal data of the interface object. This pointer belongs to the TableObject class and * returns the internal data of the interface object. This pointer belongs to the TableObject class and
@ -48,6 +55,8 @@ class TableObject: public InterfaceObject
void initializeProperties(size_t propertiesSize, Property** properties) override; void initializeProperties(size_t propertiesSize, Property** properties) override;
static BeforeTablesUnloadCallback _beforeTablesUnload;
private: private:
uint32_t tableReference(); uint32_t tableReference();
bool allocTable(uint32_t size, bool doFill, uint8_t fillByte); bool allocTable(uint32_t size, bool doFill, uint8_t fillByte);
@ -68,6 +77,7 @@ class TableObject: public InterfaceObject
LoadState _state = LS_UNLOADED; LoadState _state = LS_UNLOADED;
Memory& _memory; Memory& _memory;
uint8_t *_data = 0; uint8_t *_data = 0;
static uint8_t _tableUnloadCount;
/** /**
* used to store size of data() in allocTable(), needed for calculation of crc in PID_MCB_TABLE. * used to store size of data() in allocTable(), needed for calculation of crc in PID_MCB_TABLE.

View File

@ -85,7 +85,6 @@
enum { enum {
TX_IDLE, TX_IDLE,
TX_FRAME, TX_FRAME,
TX_WAIT_ECHO,
TX_WAIT_CONN TX_WAIT_CONN
}; };
@ -138,7 +137,6 @@ void TpUartDataLinkLayer::loop()
// Loop once and repeat as long we have rx data available // Loop once and repeat as long we have rx data available
do { do {
// Signals to communicate from rx part with the tx part // Signals to communicate from rx part with the tx part
bool isEchoComplete = false; // Flag that a complete echo is received
uint8_t dataConnMsg = 0; // The DATA_CONN message just seen or 0 uint8_t dataConnMsg = 0; // The DATA_CONN message just seen or 0
#ifdef KNX_WAIT_FOR_ADDR #ifdef KNX_WAIT_FOR_ADDR
@ -296,22 +294,14 @@ void TpUartDataLinkLayer::loop()
if (_RxByteCnt == 7) if (_RxByteCnt == 7)
{ {
//Destination Address + payload available //Destination Address + payload available
//check if echo //check if echo; ignore repeat bit of control byte
if (_sendBuffer != nullptr && (!((buffer[0] ^ _sendBuffer[0]) & ~0x20) && !memcmp(buffer + _convert + 1, _sendBuffer + 1, 5))) _isEcho = (_sendBuffer != nullptr && (!((buffer[0] ^ _sendBuffer[0]) & ~0x20) && !memcmp(buffer + _convert + 1, _sendBuffer + 1, 5)));
{ //ignore repeated bit of control byte
_isEcho = true;
}
else
{
_isEcho = false;
}
//convert into Extended.ind //convert into Extended.ind
if (_convert) if (_convert)
{ {
uint8_t payloadLength = buffer[6] & 0x0F;
buffer[1] = buffer[6] & 0xF0; buffer[1] = buffer[6] & 0xF0;
buffer[6] = payloadLength; buffer[6] &= 0x0F;
} }
if (!_isEcho) if (!_isEcho)
@ -358,22 +348,10 @@ void TpUartDataLinkLayer::loop()
if (_RxByteCnt == buffer[6] + 7 + 2) if (_RxByteCnt == buffer[6] + 7 + 2)
{ {
//complete Frame received, payloadLength+1 for TCPI +1 for CRC //complete Frame received, payloadLength+1 for TCPI +1 for CRC
//check if crc is correct
if (rxByte == (uint8_t)(~_xorSum)) if (rxByte == (uint8_t)(~_xorSum))
{ {
//check if crc is correct if (!_isEcho)
if (_isEcho && _sendBuffer != NULL)
{
//check if it is realy an echo, rx_crc = tx_crc
if (rxByte == _sendBuffer[_sendBufferLength - 1])
_isEcho = true;
else
_isEcho = false;
}
if (_isEcho)
{
isEchoComplete = true;
}
else
{ {
_receiveBuffer[0] = 0x29; _receiveBuffer[0] = 0x29;
_receiveBuffer[1] = 0; _receiveBuffer[1] = 0;
@ -428,8 +406,8 @@ void TpUartDataLinkLayer::loop()
} while (_rxState == RX_L_ADDR && (stayInRx || _platform.uartAvailable())); } while (_rxState == RX_L_ADDR && (stayInRx || _platform.uartAvailable()));
// Check for spurios DATA_CONN message // Check for spurios DATA_CONN message
if (dataConnMsg && _txState != TX_WAIT_CONN && _txState != TX_WAIT_ECHO) { if (dataConnMsg && _txState != TX_WAIT_CONN) {
println("got unexpected L_DATA_CON"); println("unexpected L_DATA_CON");
} }
switch (_txState) switch (_txState)
@ -450,9 +428,9 @@ void TpUartDataLinkLayer::loop()
if (sendSingleFrameByte() == false) if (sendSingleFrameByte() == false)
{ {
_waitConfirmStartTime = millis(); _waitConfirmStartTime = millis();
_txState = TX_WAIT_ECHO; _txState = TX_WAIT_CONN;
#ifdef DBG_TRACE #ifdef DBG_TRACE
println("TX_WAIT_ECHO"); println("TX_WAIT_CONN");
#endif #endif
} }
else else
@ -461,22 +439,10 @@ void TpUartDataLinkLayer::loop()
} }
} }
break; break;
case TX_WAIT_ECHO:
case TX_WAIT_CONN: case TX_WAIT_CONN:
if (isEchoComplete) if (dataConnMsg)
{ {
_txState = TX_WAIT_CONN; dataConBytesReceived(_receiveBuffer, _RxByteCnt + 2, (dataConnMsg & SUCCESS));
#ifdef DBG_TRACE
println("TX_WAIT_CONN");
#endif
}
else if (dataConnMsg)
{
bool waitEcho = (_txState == TX_WAIT_ECHO);
if (waitEcho) {
println("L_DATA_CON without echo");
}
dataConBytesReceived(_receiveBuffer, _RxByteCnt + 2, !waitEcho && ((dataConnMsg & SUCCESS) > 0));
delete[] _sendBuffer; delete[] _sendBuffer;
_sendBuffer = 0; _sendBuffer = 0;
_sendBufferLength = 0; _sendBufferLength = 0;

View File

@ -400,7 +400,18 @@ template <class P, class B> class KnxFacade : private SaveRestore
void restart(uint16_t individualAddress) void restart(uint16_t individualAddress)
{ {
_bau.restartRequest(individualAddress); SecurityControl sc = {false, None};
_bau.restartRequest(individualAddress, sc);
}
void beforeRestartCallback(BeforeRestartCallback func)
{
_bau.beforeRestartCallback(func);
}
BeforeRestartCallback beforeRestartCallback()
{
return _bau.beforeRestartCallback();
} }
private: private: