mirror of
https://github.com/thelsing/knx.git
synced 2025-08-13 13:46:20 +02:00
Merge branch 'openknx-version-support' of https://github.com/thelsing/knx into openknx-version-support
This commit is contained in:
commit
39af540c49
@ -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;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
@ -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();
|
||||||
};
|
};
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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.
|
||||||
|
@ -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;
|
||||||
|
@ -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:
|
||||||
|
Loading…
Reference in New Issue
Block a user