mirror of
https://github.com/thelsing/knx.git
synced 2025-09-09 17:51:55 +02:00
save work
This commit is contained in:
parent
a005e8f654
commit
9acd1537bd
@ -103,13 +103,16 @@ add_executable(knx-linux
|
||||
../../src/knx/rf_medium_object.h
|
||||
../../src/knx/rf_physical_layer.cpp
|
||||
../../src/knx/rf_physical_layer.h
|
||||
../../src/knx/router_object.cpp
|
||||
../../src/knx/router_object.h
|
||||
../../src/knx/router_object_filtertable.cpp
|
||||
../../src/knx/router_object_filtertable.h
|
||||
../../src/knx/secure_application_layer.cpp
|
||||
../../src/knx/secure_application_layer.h
|
||||
../../src/knx/security_interface_object.cpp
|
||||
../../src/knx/security_interface_object.h
|
||||
../../src/knx/simple_functional.h
|
||||
../../src/knx/simple_map.h
|
||||
../../src/knx/table_object.cpp
|
||||
../../src/knx/save_restore.h
|
||||
../../src/knx/table_object.cpp
|
||||
../../src/knx/table_object.h
|
||||
|
@ -174,6 +174,16 @@ enum PropertyID
|
||||
PID_GO_SECURITY_FLAGS = 61, // Defines the required security requirements for each group object
|
||||
PID_ROLE_TABLE = 62, // Role table
|
||||
PID_TOOL_SEQUENCE_NUMBER_SENDING = 250, // Sequence Number used for the next outgoing secure communication (Tool Access only, non-standardized!)
|
||||
|
||||
/** Router Object */
|
||||
PID_MEDIUM_STATUS = 51,
|
||||
PID_ROUTETABLE_CONTROL = 56,
|
||||
PID_COUPLER_SERVICES_CONTROL = 57,
|
||||
PID_MAX_APDU_LENGTH_ROUTER = 58,
|
||||
PID_HOP_COUNT = 61,
|
||||
PID_MEDIUM = 63,
|
||||
PID_FILTER_TABLE_USE = 67,
|
||||
PID_RF_ENABLE_SBC = 112, // Exists only if medium for this router object is RF
|
||||
};
|
||||
|
||||
enum LoadState
|
||||
|
61
src/knx/router_object.cpp
Normal file
61
src/knx/router_object.cpp
Normal file
@ -0,0 +1,61 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <cstring>
|
||||
#include "router_object.h"
|
||||
#include "bits.h"
|
||||
#include "data_property.h"
|
||||
|
||||
RouterObject::RouterObject()
|
||||
{
|
||||
initializeProperties(0, nullptr);
|
||||
}
|
||||
|
||||
void RouterObject::initializeProperties(size_t propertiesSize, Property** properties)
|
||||
{
|
||||
Property* ownProperties[] =
|
||||
{
|
||||
new DataProperty( PID_OBJECT_TYPE, false, PDT_UNSIGNED_INT, 1, ReadLv3 | WriteLv0, (uint16_t) OT_ROUTER ),
|
||||
new DataProperty( PID_OBJECT_INDEX, false, PDT_UNSIGNED_CHAR, 1, ReadLv3 | WriteLv0, (uint16_t) 0 ), // TODO
|
||||
new DataProperty( PID_MEDIUM_STATUS, false, PDT_GENERIC_01, 1, ReadLv3 | WriteLv0, (uint16_t) 0 ), // TODO
|
||||
new DataProperty( PID_MAX_APDU_LENGTH_ROUTER, false, PDT_UNSIGNED_INT, 1, ReadLv3 | WriteLv0, (uint16_t) 254 ),
|
||||
new DataProperty( PID_HOP_COUNT, false, PDT_UNSIGNED_INT, 1, ReadLv3 | WriteLv0, (uint16_t) 5),
|
||||
new DataProperty( PID_MEDIUM, false, PDT_ENUM8, 1, ReadLv3 | WriteLv0, (uint16_t) 0) , // TODO
|
||||
};
|
||||
|
||||
uint8_t ownPropertiesCount = sizeof(ownProperties) / sizeof(Property*);
|
||||
|
||||
uint8_t propertyCount = propertiesSize / sizeof(Property*);
|
||||
uint8_t allPropertiesCount = propertyCount + ownPropertiesCount;
|
||||
|
||||
Property* allProperties[allPropertiesCount];
|
||||
if (properties)
|
||||
memcpy(allProperties, properties, propertiesSize);
|
||||
memcpy(allProperties + propertyCount, ownProperties, sizeof(ownProperties));
|
||||
|
||||
InterfaceObject::initializeProperties(sizeof(allProperties), allProperties);
|
||||
}
|
||||
|
||||
void RouterObject::masterReset(EraseCode eraseCode, uint8_t channel)
|
||||
{
|
||||
if (eraseCode == FactoryReset)
|
||||
{
|
||||
// TODO handle different erase codes
|
||||
println("Factory reset of router object requested.");
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t RouterObject::getNumberOfElements(PropertyID propId)
|
||||
{
|
||||
// Get number of entries for this property
|
||||
uint16_t numElements = 0;
|
||||
|
||||
uint8_t data[sizeof(uint16_t)]; // is sizeof(_currentElements) which is uint16_t
|
||||
uint8_t count = property(propId)->read(0, 1, data);
|
||||
|
||||
if (count > 0)
|
||||
{
|
||||
popWord(numElements, data);
|
||||
}
|
||||
|
||||
return numElements;
|
||||
}
|
20
src/knx/router_object.h
Normal file
20
src/knx/router_object.h
Normal file
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "interface_object.h"
|
||||
#include "knx_types.h"
|
||||
|
||||
class RouterObject: public InterfaceObject
|
||||
{
|
||||
public:
|
||||
RouterObject();
|
||||
|
||||
virtual void masterReset(EraseCode eraseCode, uint8_t channel) override;
|
||||
|
||||
protected:
|
||||
void initializeProperties(size_t propertiesSize, Property** properties) override;
|
||||
|
||||
private:
|
||||
uint16_t getNumberOfElements(PropertyID propId);
|
||||
};
|
349
src/knx/router_object_filtertable.cpp
Normal file
349
src/knx/router_object_filtertable.cpp
Normal file
@ -0,0 +1,349 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <cstring>
|
||||
#include "router_object_filtertable.h"
|
||||
#include "bits.h"
|
||||
#include "memory.h"
|
||||
#include "data_property.h"
|
||||
#include "callback_property.h"
|
||||
#include "function_property.h"
|
||||
|
||||
RouterObjectFilterTable::RouterObjectFilterTable(Memory& memory)
|
||||
: _memory(memory)
|
||||
{
|
||||
Property* properties[] =
|
||||
{
|
||||
new CallbackProperty<RouterObjectFilterTable>(this, PID_LOAD_STATE_CONTROL, true, PDT_CONTROL, 1, ReadLv3 | WriteLv3,
|
||||
// ReadCallback of PID_LOAD_STATE_CONTROL
|
||||
[](RouterObjectFilterTable* obj, uint16_t start, uint8_t count, uint8_t* data) -> uint8_t {
|
||||
if (start == 0)
|
||||
return 1;
|
||||
|
||||
data[0] = obj->_state;
|
||||
return 1;
|
||||
},
|
||||
// WriteCallback of PID_LOAD_STATE_CONTROL
|
||||
[](RouterObjectFilterTable* obj, uint16_t start, uint8_t count, const uint8_t* data) -> uint8_t {
|
||||
obj->loadEvent(data);
|
||||
return 1;
|
||||
}),
|
||||
new CallbackProperty<RouterObjectFilterTable>(this, PID_TABLE_REFERENCE, false, PDT_UNSIGNED_LONG, 1, ReadLv3 | WriteLv0,
|
||||
[](RouterObjectFilterTable* obj, uint16_t start, uint8_t count, uint8_t* data) -> uint8_t {
|
||||
if(start == 0)
|
||||
{
|
||||
uint16_t currentNoOfElements = 1;
|
||||
pushWord(currentNoOfElements, data);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (obj->_state == LS_UNLOADED)
|
||||
pushInt(0, data);
|
||||
else
|
||||
pushInt(obj->tableReference(), data);
|
||||
return 1;
|
||||
}),
|
||||
|
||||
new DataProperty( PID_MCB_TABLE, false, PDT_GENERIC_08, 1, ReadLv3 | WriteLv0, (uint16_t) 0 ), // TODO
|
||||
|
||||
new FunctionProperty<RouterObjectFilterTable>(this, PID_ROUTETABLE_CONTROL,
|
||||
// Command Callback of PID_ROUTETABLE_CONTROL
|
||||
[](RouterObjectFilterTable* obj, uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t& resultLength) -> void {
|
||||
if (length != 3)
|
||||
{
|
||||
resultData[0] = ReturnCodes::DataVoid;
|
||||
resultLength = 1;
|
||||
return;
|
||||
}
|
||||
uint8_t id = data[1];
|
||||
uint8_t info = data[2];
|
||||
if (id == 0 && info == 0)
|
||||
{
|
||||
//obj->clearFailureLog();
|
||||
resultData[0] = ReturnCodes::Success;
|
||||
resultData[1] = id;
|
||||
resultLength = 2;
|
||||
return;
|
||||
}
|
||||
resultData[0] = ReturnCodes::GenericError;
|
||||
resultLength = 1;
|
||||
},
|
||||
// State Callback of PID_ROUTETABLE_CONTROL
|
||||
[](RouterObjectFilterTable* obj, uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t& resultLength) -> void {
|
||||
if (length != 3)
|
||||
{
|
||||
resultData[0] = ReturnCodes::DataVoid;
|
||||
resultLength = 1;
|
||||
return;
|
||||
}
|
||||
uint8_t id = data[1];
|
||||
uint8_t info = data[2];
|
||||
|
||||
// failure counters
|
||||
if (id == 0 && info == 0)
|
||||
{
|
||||
resultData[0] = ReturnCodes::Success;
|
||||
resultData[1] = id;
|
||||
resultData[2] = info;
|
||||
//obj->getFailureCounters(&resultData[3]); // Put 8 bytes in the buffer
|
||||
resultLength = 3 + 8;
|
||||
return;
|
||||
}
|
||||
// query latest failure by index
|
||||
else if(id == 1)
|
||||
{
|
||||
uint8_t maxBufferSize = resultLength; // Remember the maximum buffer size of the buffer that is provided to us
|
||||
uint8_t index = info;
|
||||
uint8_t numBytes = 0;//obj->getFromFailureLogByIndex(index, &resultData[2], maxBufferSize);
|
||||
if ( numBytes > 0)
|
||||
{
|
||||
resultData[0] = ReturnCodes::Success;
|
||||
resultData[1] = id;
|
||||
resultData[2] = index;
|
||||
resultLength += numBytes;
|
||||
resultLength = 3 + numBytes;
|
||||
return;
|
||||
}
|
||||
resultData[0] = ReturnCodes::DataVoid;
|
||||
resultData[1] = id;
|
||||
resultLength = 2;
|
||||
return;
|
||||
}
|
||||
resultData[0] = ReturnCodes::GenericError;
|
||||
resultLength = 1;
|
||||
}),
|
||||
|
||||
new DataProperty( PID_FILTER_TABLE_USE, false, PDT_BINARY_INFORMATION, 1, ReadLv3 | WriteLv0, (uint16_t) 0 ), // TODO
|
||||
/*
|
||||
new FunctionProperty<RouterObjectFilterTable>(this, PID_RF_ENABLE_SBC,
|
||||
// Command Callback of PID_RF_ENABLE_SBC
|
||||
[](RouterObjectFilterTable* obj, uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t& resultLength) -> void {
|
||||
uint8_t serviceId = data[1] & 0xff;
|
||||
if (serviceId != 0)
|
||||
{
|
||||
resultData[0] = ReturnCodes::InvalidCommand;
|
||||
resultLength = 1;
|
||||
return;
|
||||
}
|
||||
if (length == 3)
|
||||
{
|
||||
uint8_t mode = data[2];
|
||||
if (mode > 1)
|
||||
{
|
||||
resultData[0] = ReturnCodes::DataVoid;
|
||||
resultLength = 1;
|
||||
return;
|
||||
}
|
||||
//obj->setSecurityMode(mode == 1);
|
||||
resultData[0] = ReturnCodes::Success;
|
||||
resultData[1] = serviceId;
|
||||
resultLength = 2;
|
||||
return;
|
||||
}
|
||||
resultData[0] = ReturnCodes::GenericError;
|
||||
resultLength = 1;
|
||||
},
|
||||
// State Callback of PID_RF_ENABLE_SBC
|
||||
[](RouterObjectFilterTable* obj, uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t& resultLength) -> void {
|
||||
uint8_t serviceId = data[1] & 0xff;
|
||||
if (serviceId != 0)
|
||||
{
|
||||
resultData[0] = ReturnCodes::InvalidCommand;
|
||||
resultLength = 1;
|
||||
return;
|
||||
}
|
||||
if (length == 2)
|
||||
{
|
||||
resultData[0] = ReturnCodes::Success;
|
||||
resultData[1] = serviceId;
|
||||
resultData[2] = 0;//obj->isSecurityModeEnabled() ? 1 : 0;
|
||||
resultLength = 3;
|
||||
return;
|
||||
}
|
||||
resultData[0] = ReturnCodes::GenericError;
|
||||
resultLength = 1;
|
||||
}),
|
||||
*/
|
||||
};
|
||||
|
||||
RouterObject::initializeProperties(sizeof(properties), properties);
|
||||
}
|
||||
|
||||
uint8_t* RouterObjectFilterTable::save(uint8_t* buffer)
|
||||
{
|
||||
buffer = pushByte(_state, buffer);
|
||||
|
||||
if (_data)
|
||||
buffer = pushInt(_memory.toRelative(_data), buffer);
|
||||
else
|
||||
buffer = pushInt(0, buffer);
|
||||
|
||||
return RouterObject::save(buffer);
|
||||
}
|
||||
|
||||
const uint8_t* RouterObjectFilterTable::restore(const uint8_t* buffer)
|
||||
{
|
||||
uint8_t state = 0;
|
||||
buffer = popByte(state, buffer);
|
||||
_state = (LoadState)state;
|
||||
|
||||
uint32_t relativeAddress = 0;
|
||||
buffer = popInt(relativeAddress, buffer);
|
||||
|
||||
if (relativeAddress != 0)
|
||||
_data = _memory.toAbsolute(relativeAddress);
|
||||
else
|
||||
_data = 0;
|
||||
|
||||
return RouterObject::restore(buffer);
|
||||
}
|
||||
|
||||
uint16_t RouterObjectFilterTable::saveSize()
|
||||
{
|
||||
return 1 + 4 + RouterObject::saveSize();
|
||||
}
|
||||
|
||||
uint32_t RouterObjectFilterTable::tableReference()
|
||||
{
|
||||
return (uint32_t)_memory.toRelative(_data);
|
||||
}
|
||||
|
||||
bool RouterObjectFilterTable::isLoaded()
|
||||
{
|
||||
return _state == LS_LOADED;
|
||||
}
|
||||
|
||||
LoadState RouterObjectFilterTable::loadState()
|
||||
{
|
||||
return _state;
|
||||
}
|
||||
|
||||
void RouterObjectFilterTable::loadEvent(const uint8_t* data)
|
||||
{
|
||||
switch (_state)
|
||||
{
|
||||
case LS_UNLOADED:
|
||||
loadEventUnloaded(data);
|
||||
break;
|
||||
case LS_LOADING:
|
||||
loadEventLoading(data);
|
||||
break;
|
||||
case LS_LOADED:
|
||||
loadEventLoaded(data);
|
||||
break;
|
||||
case LS_ERROR:
|
||||
loadEventError(data);
|
||||
break;
|
||||
default:
|
||||
/* do nothing */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void RouterObjectFilterTable::loadEventUnloaded(const uint8_t* data)
|
||||
{
|
||||
uint8_t event = data[0];
|
||||
switch (event)
|
||||
{
|
||||
case LE_NOOP:
|
||||
case LE_LOAD_COMPLETED:
|
||||
case LE_ADDITIONAL_LOAD_CONTROLS:
|
||||
case LE_UNLOAD:
|
||||
break;
|
||||
case LE_START_LOADING:
|
||||
loadState(LS_LOADING);
|
||||
break;
|
||||
default:
|
||||
loadState(LS_ERROR);
|
||||
errorCode(E_GOT_UNDEF_LOAD_CMD);
|
||||
}
|
||||
}
|
||||
|
||||
void RouterObjectFilterTable::loadEventLoading(const uint8_t* data)
|
||||
{
|
||||
uint8_t event = data[0];
|
||||
switch (event)
|
||||
{
|
||||
case LE_NOOP:
|
||||
case LE_START_LOADING:
|
||||
break;
|
||||
case LE_LOAD_COMPLETED:
|
||||
loadState(LS_LOADED);
|
||||
break;
|
||||
case LE_UNLOAD:
|
||||
loadState(LS_UNLOADED);
|
||||
break;
|
||||
case LE_ADDITIONAL_LOAD_CONTROLS: // Not supported here
|
||||
default:
|
||||
loadState(LS_ERROR);
|
||||
errorCode(E_GOT_UNDEF_LOAD_CMD);
|
||||
}
|
||||
}
|
||||
|
||||
void RouterObjectFilterTable::loadEventLoaded(const uint8_t* data)
|
||||
{
|
||||
uint8_t event = data[0];
|
||||
switch (event)
|
||||
{
|
||||
case LE_NOOP:
|
||||
case LE_LOAD_COMPLETED:
|
||||
break;
|
||||
case LE_START_LOADING:
|
||||
loadState(LS_LOADING);
|
||||
break;
|
||||
case LE_UNLOAD:
|
||||
loadState(LS_UNLOADED);
|
||||
break;
|
||||
case LE_ADDITIONAL_LOAD_CONTROLS:
|
||||
loadState(LS_ERROR);
|
||||
errorCode(E_INVALID_OPCODE);
|
||||
break;
|
||||
default:
|
||||
loadState(LS_ERROR);
|
||||
errorCode(E_GOT_UNDEF_LOAD_CMD);
|
||||
}
|
||||
}
|
||||
|
||||
void RouterObjectFilterTable::loadEventError(const uint8_t* data)
|
||||
{
|
||||
uint8_t event = data[0];
|
||||
switch (event)
|
||||
{
|
||||
case LE_NOOP:
|
||||
case LE_LOAD_COMPLETED:
|
||||
case LE_ADDITIONAL_LOAD_CONTROLS:
|
||||
case LE_START_LOADING:
|
||||
break;
|
||||
case LE_UNLOAD:
|
||||
loadState(LS_UNLOADED);
|
||||
break;
|
||||
default:
|
||||
loadState(LS_ERROR);
|
||||
errorCode(E_GOT_UNDEF_LOAD_CMD);
|
||||
}
|
||||
}
|
||||
|
||||
void RouterObjectFilterTable::loadState(LoadState newState)
|
||||
{
|
||||
if (newState == _state)
|
||||
return;
|
||||
//beforeStateChange(newState);
|
||||
_state = newState;
|
||||
}
|
||||
|
||||
void RouterObjectFilterTable::errorCode(ErrorCode errorCode)
|
||||
{
|
||||
uint8_t data = errorCode;
|
||||
Property* prop = property(PID_ERROR_CODE);
|
||||
prop->write(data);
|
||||
}
|
||||
|
||||
void RouterObjectFilterTable::masterReset(EraseCode eraseCode, uint8_t channel)
|
||||
{
|
||||
RouterObject::masterReset(eraseCode, channel);
|
||||
|
||||
if (eraseCode == FactoryReset)
|
||||
{
|
||||
// TODO handle different erase codes
|
||||
println("Factory reset of router object with filter table requested.");
|
||||
}
|
||||
}
|
39
src/knx/router_object_filtertable.h
Normal file
39
src/knx/router_object_filtertable.h
Normal file
@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "router_object.h"
|
||||
#include "knx_types.h"
|
||||
|
||||
class Memory;
|
||||
|
||||
class RouterObjectFilterTable: public RouterObject
|
||||
{
|
||||
public:
|
||||
RouterObjectFilterTable(Memory& memory);
|
||||
|
||||
virtual void masterReset(EraseCode eraseCode, uint8_t channel) override;
|
||||
|
||||
bool isLoaded();
|
||||
|
||||
LoadState loadState();
|
||||
uint8_t* save(uint8_t* buffer) override;
|
||||
const uint8_t* restore(const uint8_t* buffer) override;
|
||||
uint16_t saveSize() override;
|
||||
|
||||
private:
|
||||
uint32_t tableReference();
|
||||
void errorCode(ErrorCode errorCode);
|
||||
|
||||
void loadEvent(const uint8_t* data);
|
||||
void loadEventUnloaded(const uint8_t* data);
|
||||
void loadEventLoading(const uint8_t* data);
|
||||
void loadEventLoaded(const uint8_t* data);
|
||||
void loadEventError(const uint8_t* data);
|
||||
|
||||
void loadState(LoadState newState);
|
||||
LoadState _state = LS_UNLOADED;
|
||||
|
||||
Memory& _memory;
|
||||
uint8_t *_data = 0;
|
||||
};
|
Loading…
Reference in New Issue
Block a user