convert CallbackProperty to template

This commit is contained in:
Thomas Kunze 2019-12-12 01:42:56 +01:00
parent 71448efdad
commit e128debabb
12 changed files with 150 additions and 216 deletions

View File

@ -24,7 +24,6 @@ add_executable(knx-linux
../src/knx/bau_systemB.h
../src/knx/bits.cpp
../src/knx/bits.h
../src/knx/callback_property.cpp
../src/knx/callback_property.h
../src/knx/cemi_frame.cpp
../src/knx/cemi_frame.h

View File

@ -136,7 +136,6 @@
<ClCompile Include="..\src\knx\bau57B0.cpp" />
<ClCompile Include="..\src\knx\bau_systemB.cpp" />
<ClCompile Include="..\src\knx\bits.cpp" />
<ClCompile Include="..\src\knx\callback_property.cpp" />
<ClCompile Include="..\src\knx\cemi_frame.cpp" />
<ClCompile Include="..\src\knx\cemi_server.cpp" />
<ClCompile Include="..\src\knx\cemi_server_object.cpp" />

View File

@ -301,8 +301,5 @@
<ClCompile Include="..\src\knx\data_property.cpp">
<Filter>Source files\knx</Filter>
</ClCompile>
<ClCompile Include="..\src\knx\callback_property.cpp">
<Filter>Source files\knx</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@ -1,29 +0,0 @@
#include "callback_property.h"
CallbackProperty::CallbackProperty(PropertyID id, bool writeEnable, PropertyDataType type,
uint16_t maxElements, uint8_t access,
PropertyCallback readCallback, PropertyCallback writeCallback)
: Property(id, writeEnable, type, maxElements, access), _readCallback(), _writeCallback()
{}
CallbackProperty::CallbackProperty(PropertyID id, bool writeEnable, PropertyDataType type,
uint16_t maxElements, uint8_t access,
PropertyCallback readCallback)
: Property(id, writeEnable, type, maxElements, access), _readCallback()
{}
uint8_t CallbackProperty::read(uint16_t start, uint8_t count, uint8_t* data)
{
if (count == 0 || _readCallback == nullptr)
return 0;
return _readCallback(start, count, data);
}
uint8_t CallbackProperty::write(uint16_t start, uint8_t count, uint8_t* data)
{
if (count == 0 || start > _maxElements || !_writeEnable || start + count > _maxElements + 1
|| _writeCallback == nullptr)
return 0;
return _writeCallback(start, count, data);
}

View File

@ -2,18 +2,37 @@
#include "property.h"
typedef uint8_t (*PropertyCallback)(uint16_t start, uint8_t count, uint8_t* data);
class InterfaceObject;
class CallbackProperty : public Property
template <class T> class CallbackProperty : public Property
{
public:
CallbackProperty(PropertyID id, bool writeEnable, PropertyDataType type, uint16_t maxElements,
uint8_t access, PropertyCallback readCallback, PropertyCallback writeCallback);
CallbackProperty(PropertyID id, bool writeEnable, PropertyDataType type, uint16_t maxElements,
uint8_t access, PropertyCallback readCallback);
virtual uint8_t read(uint16_t start, uint8_t count, uint8_t* data) override;
virtual uint8_t write(uint16_t start, uint8_t count, uint8_t* data) override;
CallbackProperty(T* io, PropertyID id, bool writeEnable, PropertyDataType type, uint16_t maxElements,
uint8_t access, uint8_t (*readCallback)(T*, uint16_t, uint8_t, uint8_t*),
uint8_t (*writeCallback)(T*, uint16_t, uint8_t, uint8_t*))
: Property(id, writeEnable, type, maxElements, access),
_interfaceObject(io), _readCallback(readCallback), _writeCallback(writeCallback)
{}
CallbackProperty(T* io, PropertyID id, bool writeEnable, PropertyDataType type, uint16_t maxElements,
uint8_t access, uint8_t (*readCallback)(T*, uint16_t, uint8_t, uint8_t*))
: Property(id, writeEnable, type, maxElements, access), _interfaceObject(io), _readCallback(readCallback)
{}
virtual uint8_t read(uint16_t start, uint8_t count, uint8_t* data) override
{
if (count == 0 || _readCallback == nullptr || start > _maxElements || start + count > _maxElements + 1)
return 0;
return _readCallback(_interfaceObject, start, count, data);
}
virtual uint8_t write(uint16_t start, uint8_t count, uint8_t* data) override
{
if (count == 0 || start > _maxElements || !_writeEnable || start + count > _maxElements + 1 || _writeCallback == nullptr)
return 0;
return _writeCallback(_interfaceObject, start, count, data);
}
private:
PropertyCallback _readCallback = nullptr;
PropertyCallback _writeCallback = nullptr;
T* _interfaceObject = nullptr;
uint8_t (*_readCallback)(T*, uint16_t, uint8_t, uint8_t*) = nullptr;
uint8_t (*_writeCallback)(T*, uint16_t, uint8_t, uint8_t*) = nullptr;
};

View File

@ -81,3 +81,16 @@ DataProperty::~DataProperty()
if (_data)
delete[] _data;
}
DataProperty::DataProperty(PropertyID id, bool writeEnable, PropertyDataType type,
uint16_t maxElements, uint8_t access, uint16_t value)
: Property(id, writeEnable, type, maxElements, access)
{
uint8_t elementSize = ElementSize();
if (elementSize == 2)
{
uint8_t data[elementSize];
pushWord(value, data);
write(1, 1, data);
}
}

View File

@ -6,6 +6,7 @@ class DataProperty : public Property
{
public:
DataProperty(PropertyID id, bool writeEnable, PropertyDataType type, uint16_t maxElements, uint8_t access);
DataProperty(PropertyID id, bool writeEnable, PropertyDataType type, uint16_t maxElements, uint8_t access, uint16_t value);
virtual ~DataProperty() override;
virtual uint8_t read(uint16_t start, uint8_t count, uint8_t* data) override;
virtual uint8_t write(uint16_t start, uint8_t count, uint8_t* data) override;

View File

@ -56,21 +56,37 @@ void InterfaceObject::readPropertyDescription(uint8_t& propertyId, uint8_t& prop
void InterfaceObject::readProperty(PropertyID id, uint16_t start, uint8_t& count, uint8_t* data)
{
// Set number of elements to zero as we are in the end of the call chain
// Nobody processed the property before.
count = 0;
Property* prop = property(id);
if (prop == nullptr)
{
count = 0;
return;
}
count = prop->read(start, count, data);
}
void InterfaceObject::writeProperty(PropertyID id, uint16_t start, uint8_t* data, uint8_t& count)
{
// Set number of elements to zero as we are in the end of the call chain
// Nobody processed the property before.
count = 0;
Property* prop = property(id);
if (prop == nullptr)
{
count = 0;
return;
}
count = prop->write(start, count, data);
}
uint8_t InterfaceObject::propertySize(PropertyID id)
{
return 0;
Property* prop = property(id);
if (prop == nullptr)
{
return 0;
}
return prop->ElementSize();
}
uint8_t InterfaceObject::propertyDescriptionCount()
@ -100,3 +116,47 @@ Property* InterfaceObject::property(PropertyID id)
return nullptr;
}
uint8_t* InterfaceObject::save(uint8_t* buffer)
{
for (int i = 0; i < _propertyCount; i++)
{
Property* prop = _properties[i];
if (!prop->WriteEnable())
continue;
buffer = prop->save(buffer);
}
return buffer;
}
uint8_t* InterfaceObject::restore(uint8_t* buffer)
{
for (int i = 0; i < _propertyCount; i++)
{
Property* prop = _properties[i];
if (!prop->WriteEnable())
continue;
buffer = prop->restore(buffer);
}
return buffer;
}
uint16_t InterfaceObject::saveSize()
{
uint16_t size = 0;
for (int i = 0; i < _propertyCount; i++)
{
Property* prop = _properties[i];
if (!prop->WriteEnable())
continue;
size += prop->saveSize();
}
return size;
}

View File

@ -131,6 +131,10 @@ class InterfaceObject : public SaveRestore
*/
Property* property(PropertyID id);
virtual uint8_t* save(uint8_t* buffer) override;
virtual uint8_t* restore(uint8_t* buffer) override;
virtual uint16_t saveSize() override;
protected:
/**
* Returns the number of properties the interface object has.

View File

@ -2,6 +2,8 @@
#include "device_object.h"
#include "platform.h"
#include "bits.h"
#include "data_property.h"
#include "callback_property.h"
//224.0.23.12
#define DEFAULT_MULTICAST_ADDR 0xE000170C
@ -11,27 +13,41 @@ IpParameterObject::IpParameterObject(DeviceObject& deviceObject, Platform& platf
{
Property* properties[] =
{
new DataProperty(PID_OBJECT_TYPE, false, PDT_UNSIGNED_INT, 1, ReadLv3 | WriteLv0)
new DataProperty(PID_OBJECT_TYPE, false, PDT_UNSIGNED_INT, 1, ReadLv3 | WriteLv0, OT_IP_PARAMETER),
new DataProperty(PID_PROJECT_INSTALLATION_ID, true, PDT_UNSIGNED_INT, 1, ReadLv3 | WriteLv3),
new CallbackProperty<IpParameterObject>(this, PID_KNX_INDIVIDUAL_ADDRESS, true, PDT_UNSIGNED_INT, 1, ReadLv3 | WriteLv3,
[](IpParameterObject* io, uint16_t start, uint8_t count, uint8_t* data) -> uint8_t
{
pushWord(io->_deviceObject.induvidualAddress(), data);
return 1;
},
[](IpParameterObject* io, uint16_t start, uint8_t count, uint8_t* data) -> uint8_t
{
io->_deviceObject.induvidualAddress(getWord(data));
return 1;
}),
//55 PID_IP_ASSIGNMENT_METHOD 3 / 3
//56 PID_IP_CAPABILITIES 3 / 1
//57 PID_CURRENT_IP_ADDRESS 3 / x
//58 PID_CURRENT_SUBNET_MASK 3 / x
//59 PID_CURRENT_DEFAULT_GATEWAY 3 / x
//60 PID_IP_ADDRESS 3 / 3
//61 PID_SUBNET_MASK 3 / 3
//62 PID_DEFAULT_GATEWAY 3 / 3
//64 PID_MAC_ADDRESS 3 / x
//65 PID_SYSTEM_SETUP_MULTICAST_ADDRESS 3 / x
//66 PID_ROUTING_MULTICAST_ADDRESS 3 / 3
//67 PID_TTL 3 / 3
//68 PID_KNXNETIP_DEVICE_CAPABILITIES 3 / x
//76 PID_FRIENDLY_NAME 3 / 3
};
initializeProperties(sizeof(properties), properties);
initializeProperties(sizeof(properties), properties);
}
void IpParameterObject::readProperty(PropertyID propertyId, uint16_t start, uint8_t& count, uint8_t* data)
{
switch (propertyId)
{
case PID_LOAD_STATE_CONTROL:
data[0] = _state;
break;
case PID_OBJECT_TYPE:
pushWord(OT_IP_PARAMETER, data);
break;
case PID_PROJECT_INSTALLATION_ID:
pushWord(_projectInstallationId, data);
break;
case PID_KNX_INDIVIDUAL_ADDRESS:
pushWord(_deviceObject.induvidualAddress(), data);
break;
case PID_IP_ASSIGNMENT_METHOD:
data[0] = _ipAssignmentMethod;
break;
@ -80,7 +96,7 @@ void IpParameterObject::readProperty(PropertyID propertyId, uint16_t start, uint
data[i-start] = _friendlyName[i-1];
break;
default:
count = 0;
InterfaceObject::readProperty(propertyId, start, count, data);
break;
}
}
@ -89,15 +105,6 @@ void IpParameterObject::writeProperty(PropertyID id, uint16_t start, uint8_t* da
{
switch (id)
{
case PID_LOAD_STATE_CONTROL:
loadEvent(data);
break;
case PID_PROJECT_INSTALLATION_ID:
_projectInstallationId = getWord(data);
break;
case PID_KNX_INDIVIDUAL_ADDRESS:
_deviceObject.induvidualAddress(getWord(data));
break;
case PID_IP_ASSIGNMENT_METHOD:
_ipAssignmentMethod = data[0];
break;
@ -121,7 +128,7 @@ void IpParameterObject::writeProperty(PropertyID id, uint16_t start, uint8_t* da
_friendlyName[i-1] = data[i - start];
break;
default:
count = 0;
InterfaceObject::writeProperty(id, start, data, count);
break;
}
}
@ -137,8 +144,6 @@ uint8_t IpParameterObject::propertySize(PropertyID id)
case PID_KNXNETIP_DEVICE_CAPABILITIES:
case PID_FRIENDLY_NAME:
return 1;
case PID_OBJECT_TYPE:
case PID_PROJECT_INSTALLATION_ID:
case PID_KNX_INDIVIDUAL_ADDRESS:
return 2;
case PID_CURRENT_IP_ADDRESS:
@ -153,7 +158,7 @@ uint8_t IpParameterObject::propertySize(PropertyID id)
case PID_MAC_ADDRESS:
return 6;
}
return 0;
return InterfaceObject::propertySize(id);
}
uint8_t* IpParameterObject::save(uint8_t* buffer)
@ -194,125 +199,6 @@ uint32_t IpParameterObject::multicastAddress() const
return _multicastAddress;
}
void IpParameterObject::loadEvent(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;
}
}
void IpParameterObject::loadState(LoadState newState)
{
if (newState == _state)
return;
//beforeStateChange(newState);
_state = newState;
}
void IpParameterObject::loadEventUnloaded(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 IpParameterObject::loadEventLoading(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:
additionalLoadControls(data);
break;
default:
loadState(LS_ERROR);
_errorCode = E_GOT_UNDEF_LOAD_CMD;
}
}
void IpParameterObject::loadEventLoaded(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 IpParameterObject::loadEventError(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 IpParameterObject::additionalLoadControls(uint8_t* data)
{
loadState(LS_ERROR);
_errorCode = E_INVALID_OPCODE;
return;
}
static PropertyDescription _propertyDescriptions[] =
{
{ PID_OBJECT_TYPE, false, PDT_UNSIGNED_INT, 1, ReadLv3 | WriteLv0 },
@ -334,4 +220,4 @@ PropertyDescription* IpParameterObject::propertyDescriptions()
uint16_t IpParameterObject::saveSize()
{
return 51;
}
}

View File

@ -1,7 +1,6 @@
#pragma once
#include "interface_object.h"
#include "data_property.h"
#include "device_object.h"
#include "platform.h"
@ -40,17 +39,4 @@ class IpParameterObject : public InterfaceObject
char _friendlyName[30] = {0};
DeviceObject& _deviceObject;
Platform& _platform;
void loadEvent(uint8_t* data);
void loadEventUnloaded(uint8_t* data);
void loadEventLoading(uint8_t* data);
void loadEventLoaded(uint8_t* data);
void loadEventError(uint8_t* data);
void additionalLoadControls(uint8_t* data);
void loadState(LoadState newState);
LoadState _state = LS_UNLOADED;
ErrorCode _errorCode = E_NO_FAULT;
Property** _properties = nullptr;
uint8_t _propertyCount = 0;
};

View File

@ -10,6 +10,7 @@
#pragma once
#include <stdint.h>
#include "save_restore.h"
/** The data type of a property. */
enum PropertyDataType
@ -224,9 +225,7 @@ struct PropertyDescription
uint8_t Access;
};
typedef uint8_t (*PropertyCallback)(uint16_t start, uint8_t count, uint8_t* data);
class Property
class Property : public SaveRestore
{
public:
Property(PropertyID id, bool writeEnable, PropertyDataType type, uint16_t maxElements, uint8_t access);