mirror of
				https://github.com/thelsing/knx.git
				synced 2025-10-26 10:26:25 +01: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