mirror of
https://github.com/thelsing/knx.git
synced 2024-12-18 19:08:18 +01:00
Add support for Function Properties
This commit is contained in:
parent
cc1fc7d5fb
commit
86c8f359e3
@ -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)
|
||||
dataConnectedRequest(asap, priority, apdu);
|
||||
else
|
||||
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