save work

This commit is contained in:
Nanosonde 2020-07-14 17:37:03 +02:00
parent a005e8f654
commit 9acd1537bd
6 changed files with 483 additions and 1 deletions

View File

@ -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

View File

@ -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
View 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
View 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);
};

View 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.");
}
}

View 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;
};