mirror of
				https://github.com/thelsing/knx.git
				synced 2025-10-26 10:26:25 +01:00 
			
		
		
		
	Merge pull request #64 from nanosonde/feat_funcprop
Add support for Function Properties
This commit is contained in:
		
						commit
						48dd76748c
					
				| @ -494,6 +494,25 @@ void ApplicationLayer::propertyValueWriteRequest(AckType ack, Priority priority, | ||||
|         startIndex, data, length); | ||||
| } | ||||
| 
 | ||||
| void ApplicationLayer::functionPropertyStateResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, | ||||
|                                                      uint8_t objectIndex, uint8_t propertyId, uint8_t* resultData, uint8_t resultLength) | ||||
| { | ||||
|     CemiFrame frame(3 + resultLength + 1); | ||||
|     APDU& apdu = frame.apdu(); | ||||
|     apdu.type(FunctionPropertyStateResponse); | ||||
|     uint8_t* data = apdu.data() + 1; | ||||
| 
 | ||||
|     data[0] = objectIndex; | ||||
|     data[1] = propertyId; | ||||
|     if (resultLength > 0) | ||||
|         memcpy(&data[2], resultData, resultLength); | ||||
| 
 | ||||
|     if (asap == _connectedTsap) | ||||
|         _transportLayer->dataConnectedRequest(asap, priority, apdu); | ||||
|     else | ||||
|         _transportLayer->dataIndividualRequest(ack, hopType, priority, asap, apdu); | ||||
| } | ||||
| 
 | ||||
| void ApplicationLayer::propertyDescriptionReadRequest(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, | ||||
|     uint8_t objectIndex, uint8_t propertyId, uint8_t propertyIndex) | ||||
| { | ||||
| @ -751,6 +770,12 @@ void ApplicationLayer::individualIndication(HopCountType hopType, Priority prior | ||||
|                 startIndex, data + 5, apdu.length() - 5); | ||||
|             break; | ||||
|         } | ||||
|         case FunctionPropertyCommand: | ||||
|             _bau.functionPropertyCommandIndication(priority, hopType, tsap, data[1], data[2], &data[3], apdu.length() - 4); //TODO: check length
 | ||||
|             break; | ||||
|         case FunctionPropertyState: | ||||
|             _bau.functionPropertyStateIndication(priority, hopType, tsap, data[1], data[2], &data[3], apdu.length() - 4); //TODO: check length
 | ||||
|             break; | ||||
|         case PropertyDescriptionRead: | ||||
|             _bau.propertyDescriptionReadIndication(priority, hopType, tsap, data[1], data[2], data[3]); | ||||
|             break; | ||||
| @ -919,4 +944,4 @@ void ApplicationLayer::individualSend(AckType ack, HopCountType hopType, Priorit | ||||
| bool ApplicationLayer::isConnected() | ||||
| { | ||||
|     return (_connectedTsap >= 0); | ||||
| } | ||||
| } | ||||
|  | ||||
| @ -105,6 +105,8 @@ class ApplicationLayer | ||||
|                                    uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t* data, uint8_t length); | ||||
|     void propertyValueWriteRequest(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex, | ||||
|                                    uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t* data, uint8_t length); | ||||
|     void functionPropertyStateResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, | ||||
|                                        uint8_t objectIndex, uint8_t propertyId, uint8_t *resultData, uint8_t resultLength); | ||||
|     void propertyDescriptionReadRequest(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, | ||||
|                                         uint8_t objectIndex, uint8_t propertyId, uint8_t propertyIndex); | ||||
|     void propertyDescriptionReadResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, | ||||
|  | ||||
| @ -106,6 +106,14 @@ void BusAccessUnit::propertyValueReadIndication(Priority priority, HopCountType | ||||
| { | ||||
| } | ||||
| 
 | ||||
| void BusAccessUnit::functionPropertyCommandIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex, uint8_t propertyId, uint8_t* data, uint8_t length) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| void BusAccessUnit::functionPropertyStateIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex, uint8_t propertyId, uint8_t* data, uint8_t length) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| void BusAccessUnit::propertyValueReadResponseConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex, uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t* data, uint8_t length, bool status) | ||||
| { | ||||
| } | ||||
|  | ||||
| @ -48,6 +48,10 @@ class BusAccessUnit | ||||
|                                                uint8_t objectIndex, uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, bool status); | ||||
|     virtual void propertyValueReadIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex, | ||||
|                                              uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex); | ||||
|     virtual void functionPropertyCommandIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex, | ||||
|                                                    uint8_t propertyId, uint8_t* data, uint8_t length); | ||||
|     virtual void functionPropertyStateIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex, | ||||
|                                                  uint8_t propertyId, uint8_t* data, uint8_t length); | ||||
|     virtual void propertyValueReadResponseConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex, | ||||
|                                                   uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t* data, uint8_t length, bool status); | ||||
|     virtual void propertyValueReadAppLayerConfirm(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex, | ||||
|  | ||||
| @ -240,6 +240,32 @@ void BauSystemB::propertyValueReadIndication(Priority priority, HopCountType hop | ||||
|         startIndex, data, size); | ||||
| } | ||||
| 
 | ||||
| void BauSystemB::functionPropertyCommandIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex, | ||||
|                                                    uint8_t propertyId, uint8_t* data, uint8_t length) | ||||
| { | ||||
|     uint8_t resultLength = 0; | ||||
|     uint8_t resultData[32]; | ||||
| 
 | ||||
|     InterfaceObject* obj = getInterfaceObject(objectIndex); | ||||
|     if(obj) | ||||
|         obj->command((PropertyID)propertyId, data, length, resultData, resultLength); | ||||
| 
 | ||||
|     _appLayer.functionPropertyStateResponse(AckRequested, priority, hopType, asap, objectIndex, propertyId, resultData, resultLength); | ||||
| } | ||||
| 
 | ||||
| void BauSystemB::functionPropertyStateIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex, | ||||
|                                                  uint8_t propertyId, uint8_t* data, uint8_t length) | ||||
| { | ||||
|     uint8_t resultLength = 0; | ||||
|     uint8_t resultData[32]; | ||||
| 
 | ||||
|     InterfaceObject* obj = getInterfaceObject(objectIndex); | ||||
|     if(obj) | ||||
|         obj->state((PropertyID)propertyId, data, length, resultData, resultLength); | ||||
| 
 | ||||
|     _appLayer.functionPropertyStateResponse(AckRequested, priority, hopType, asap, objectIndex, propertyId, resultData, resultLength); | ||||
| } | ||||
| 
 | ||||
| void BauSystemB::individualAddressReadIndication(HopCountType hopType) | ||||
| { | ||||
|     if (_deviceObj.progMode()) | ||||
| @ -433,4 +459,4 @@ void BauSystemB::propertyValueWrite(ObjectType objectType, uint8_t objectInstanc | ||||
| Memory& BauSystemB::memory() | ||||
| { | ||||
|     return _memory; | ||||
| } | ||||
| } | ||||
|  | ||||
| @ -56,6 +56,10 @@ class BauSystemB : protected BusAccessUnit | ||||
|                                       uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t* data, uint8_t length) override; | ||||
|     void propertyValueReadIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex, | ||||
|                                      uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex) override; | ||||
|     void functionPropertyCommandIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex, | ||||
|                                            uint8_t propertyId, uint8_t* data, uint8_t length); | ||||
|     void functionPropertyStateIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex, | ||||
|                                          uint8_t propertyId, uint8_t* data, uint8_t length); | ||||
|     void individualAddressReadIndication(HopCountType hopType) override; | ||||
|     void individualAddressWriteIndication(HopCountType hopType, uint16_t newaddress) override; | ||||
|     void groupValueWriteLocalConfirm(AckType ack, uint16_t asap, Priority priority, HopCountType hopType, | ||||
| @ -97,4 +101,4 @@ class BauSystemB : protected BusAccessUnit | ||||
|     bool _configured = true; | ||||
|     RestartState _restartState = Idle; | ||||
|     uint32_t _restartDelay = 0; | ||||
| }; | ||||
| }; | ||||
|  | ||||
							
								
								
									
										51
									
								
								src/knx/function_property.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								src/knx/function_property.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,51 @@ | ||||
| #pragma once | ||||
| 
 | ||||
| #include "property.h" | ||||
| 
 | ||||
| class InterfaceObject; | ||||
| 
 | ||||
| template <class T> class FunctionProperty : public Property | ||||
| { | ||||
|   public: | ||||
|     FunctionProperty(T* io, PropertyID id, uint8_t access, | ||||
|                      void (*commandCallback)(T*, uint8_t*, uint8_t, uint8_t*, uint8_t&), | ||||
|                      void (*stateCallback)(T*, uint8_t*, uint8_t, uint8_t*, uint8_t&)) | ||||
|         : Property(id, false, PDT_FUNCTION, 1, access), _interfaceObject(io), _commandCallback(commandCallback), _stateCallback(stateCallback) | ||||
|         /* max_elements is set to 1, see 3.3.7 Application Layer p.68 */ | ||||
|     {} | ||||
|      | ||||
|     virtual uint8_t read(uint16_t start, uint8_t count, uint8_t* data) const override | ||||
|     { | ||||
|         return 0; | ||||
|     } | ||||
| 
 | ||||
|     virtual uint8_t write(uint16_t start, uint8_t count, const uint8_t* data) override | ||||
|     { | ||||
|         return 0; | ||||
|     } | ||||
| 
 | ||||
|     virtual void command(uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t& resultLength) override | ||||
|     { | ||||
|         if (length == 0 || _commandCallback == nullptr ) | ||||
|         { | ||||
|             resultLength = 0; | ||||
|             return; | ||||
|         } | ||||
|         _commandCallback(_interfaceObject, data, length, resultData, resultLength); | ||||
|     } | ||||
| 
 | ||||
|     virtual void state(uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t& resultLength) override | ||||
|     { | ||||
|         if (length == 0 || _stateCallback == nullptr ) | ||||
|         { | ||||
|             resultLength = 0; | ||||
|             return; | ||||
|         } | ||||
|         _stateCallback(_interfaceObject, data, length, resultData, resultLength); | ||||
|     } | ||||
| 
 | ||||
|   private: | ||||
|     T* _interfaceObject = nullptr; | ||||
|     void (*_commandCallback)(T*, uint8_t*, uint8_t, uint8_t*, uint8_t&) = nullptr; | ||||
|     void (*_stateCallback)(T*, uint8_t*, uint8_t, uint8_t*, uint8_t&) = nullptr; | ||||
| }; | ||||
| @ -137,6 +137,30 @@ uint8_t InterfaceObject::propertySize(PropertyID id) | ||||
|     return prop->ElementSize(); | ||||
| } | ||||
| 
 | ||||
| void InterfaceObject::command(PropertyID id, uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t& resultLength) | ||||
| { | ||||
|     Property* prop = property(id); | ||||
|     if (prop == nullptr) | ||||
|     { | ||||
|         resultLength = 0; | ||||
|         return;; | ||||
|     } | ||||
| 
 | ||||
|     prop->command(data, length, resultData, resultLength); | ||||
| } | ||||
| 
 | ||||
| void InterfaceObject::state(PropertyID id, uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t resultLength) | ||||
| { | ||||
|     Property* prop = property(id); | ||||
|     if (prop == nullptr) | ||||
|     { | ||||
|         resultLength = 0; | ||||
|         return;; | ||||
|     } | ||||
| 
 | ||||
|     prop->state(data, length, resultData, resultLength); | ||||
| } | ||||
| 
 | ||||
| uint8_t InterfaceObject::propertyDescriptionCount() | ||||
| { | ||||
|     return 0; | ||||
|  | ||||
| @ -98,6 +98,34 @@ class InterfaceObject : public SaveRestore | ||||
|      * @returns the size in byte or 0 if the interface object does not have the property | ||||
|      */ | ||||
|     virtual uint8_t propertySize(PropertyID id); | ||||
|     /**
 | ||||
|      * Call command of a function property of the interface object. Property type must be PDT_FUNCTION | ||||
|      * | ||||
|      * @param id id of the property to call | ||||
|      * | ||||
|      * @param[in] length The size of the data buffer | ||||
|      * | ||||
|      * @param[in] data The argument data for the function | ||||
|      * | ||||
|      * @param[out] resultLength The size of the result data buffer | ||||
|      * | ||||
|      * @param[out] resultData The result data for the function | ||||
|      */ | ||||
|     virtual void command(PropertyID id, uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t &resultLength); | ||||
|     /**
 | ||||
|      * Get state of a function property of the interface object. Property type must be PDT_FUNCTION | ||||
|      * | ||||
|      * @param id id of the property to call | ||||
|      * | ||||
|      * @param[in] length The size of the data buffer | ||||
|      * | ||||
|      * @param[in] data The argument data for the function | ||||
|      * | ||||
|      * @param[out] resultLength The size of the result data buffer | ||||
|      * | ||||
|      * @param[out] resultData The result data for the function | ||||
|      */ | ||||
|     virtual void state(PropertyID id, uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t resultLength); | ||||
|     /**
 | ||||
|      * Read the Description of a property of the interface object. The output parameters are only valid if nuberOfElements is not zero. | ||||
|      *  | ||||
| @ -170,4 +198,4 @@ class InterfaceObject : public SaveRestore | ||||
| 
 | ||||
|     Property** _properties = nullptr; | ||||
|     uint8_t _propertyCount = 0; | ||||
| }; | ||||
| }; | ||||
|  | ||||
| @ -138,6 +138,9 @@ enum ApduType | ||||
|     UserMemoryWrite = 0x2C2, | ||||
|     UserManufacturerInfoRead = 0x2C5, | ||||
|     UserManufacturerInfoResponse = 0x2C6, | ||||
|     FunctionPropertyCommand = 0x2C7, | ||||
|     FunctionPropertyState = 0x2C8, | ||||
|     FunctionPropertyStateResponse = 0x2C9, | ||||
|     DeviceDescriptorRead = 0x300, | ||||
|     DeviceDescriptorResponse = 0x340, | ||||
|     Restart = 0x380, | ||||
|  | ||||
| @ -203,3 +203,19 @@ uint8_t Property::write(uint16_t position, uint16_t value) | ||||
|     pushWord(value, data); | ||||
|     return write(position, 1, data); | ||||
| } | ||||
| 
 | ||||
| void Property::command(uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t& resultLength) | ||||
| { | ||||
|     (void)data; | ||||
|     (void)length; | ||||
|     (void)resultData; | ||||
|     resultLength = 0; | ||||
| } | ||||
| 
 | ||||
| void Property::state(uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t &resultLength) | ||||
| { | ||||
|     (void)data; | ||||
|     (void)length; | ||||
|     (void)resultData; | ||||
|     resultLength = 0; | ||||
| } | ||||
|  | ||||
| @ -238,6 +238,8 @@ class Property : public SaveRestore | ||||
|     uint8_t ElementSize() const; | ||||
|     virtual uint8_t read(uint16_t start, uint8_t count, uint8_t* data) const = 0; | ||||
|     virtual uint8_t write(uint16_t start, uint8_t count, const uint8_t* data) = 0; | ||||
|     virtual void command(uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t& resultLength); | ||||
|     virtual void state(uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t& resultLength); | ||||
|     uint8_t read(uint8_t& value) const; | ||||
|     uint8_t read(uint16_t& value) const; | ||||
|     uint8_t read(uint32_t& value) const; | ||||
| @ -253,4 +255,4 @@ class Property : public SaveRestore | ||||
|     PropertyDataType _type; | ||||
|     uint16_t _maxElements; | ||||
|     uint8_t _access; | ||||
| }; | ||||
| }; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user