reimplement dpt1 and dpt9

This commit is contained in:
Thomas Kunze 2024-09-12 22:16:35 +02:00
parent d1bdc6ef51
commit 60b414bab2
21 changed files with 658 additions and 534 deletions

View File

@ -71,10 +71,13 @@ set(${PROJECT_NAME}_SOURCES
../../src/knx/interface_object/data_property.h ../../src/knx/interface_object/data_property.h
../../src/knx/interface_object/device_object.cpp ../../src/knx/interface_object/device_object.cpp
../../src/knx/interface_object/device_object.h ../../src/knx/interface_object/device_object.h
../../src/knx/group_object/dpt.cpp ../../src/knx/group_object/dpt/dpt.cpp
../../src/knx/group_object/dpt.h ../../src/knx/group_object/dpt/dpt.h
../../src/knx/group_object/dptconvert.cpp ../../src/knx/group_object/dpt/dptconvert.cpp
../../src/knx/group_object/dptconvert.h ../../src/knx/group_object/dpt/dptconvert.h
../../src/knx/group_object/dpt/dpt1.cpp
../../src/knx/group_object/dpt/dpt1.h
../../src/knx/group_object/dpt/dpts.h
../../src/knx/interface_object/function_property.h ../../src/knx/interface_object/function_property.h
../../src/knx/group_object/group_object.cpp ../../src/knx/group_object/group_object.cpp
../../src/knx/group_object/group_object.h ../../src/knx/group_object/group_object.h

View File

@ -40,25 +40,25 @@ void measureTemp()
currentValue *= 100 * 100; currentValue *= 100 * 100;
// write new value to groupobject // write new value to groupobject
goCurrent.value(currentValue); goCurrent.value<Dpt9>(currentValue);
if (currentValue > maxValue) if (currentValue > maxValue)
{ {
maxValue = currentValue; maxValue = currentValue;
goMax.value(maxValue); goMax.value<Dpt9>(maxValue);
} }
if (currentValue < minValue) if (currentValue < minValue)
{ {
minValue = currentValue; minValue = currentValue;
goMin.value(minValue); goMin.value<Dpt9>(minValue);
} }
} }
// callback from reset-GO // callback from reset-GO
void handler(GroupObject& go) void handler(GroupObject& go)
{ {
if (go == goReset && go.value()) if (go == goReset && go.value<Dpt1>())
{ {
maxValue = 0; maxValue = 0;
minValue = 10000; minValue = 10000;
@ -86,11 +86,6 @@ void setup()
// print values of parameters if device is already configured // print values of parameters if device is already configured
if (knx.configured()) if (knx.configured())
{ {
goReset.dataPointType(DPT_Trigger);
goCurrent.dataPointType(DPT_Value_Temp);
goMin.dataPointType(DPT_Value_Temp);
goMax.dataPointType(DPT_Value_Temp);
Serial.print("Startverzögerung s: "); Serial.print("Startverzögerung s: ");
Serial.println(knx.paramByte(0)); Serial.println(knx.paramByte(0));
Serial.print("Aenderung senden (*0.1K): "); Serial.print("Aenderung senden (*0.1K): ");

View File

@ -6,6 +6,8 @@
#include "knx/interface_object/group_object_table_object.h" #include "knx/interface_object/group_object_table_object.h"
#include "knx/bits.h" #include "knx/bits.h"
#include "knx/group_object/dpt/dpts.h"
#include <time.h> #include <time.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
@ -61,28 +63,28 @@ void measureTemp()
lastsend = now; lastsend = now;
int r = rand(); int r = rand();
double currentValue = (r * 1.0) / (RAND_MAX * 1.0); float currentValue = (r * 1.0f) / (RAND_MAX * 1.0f);
currentValue *= 100; currentValue *= 100;
currentValue -= 50; currentValue -= 50;
// currentValue *= (670433.28 + 273); // currentValue *= (670433.28 + 273);
// currentValue -= 273; // currentValue -= 273;
LOGGER.info("current value: %f",currentValue); LOGGER.info("current value: %f",currentValue);
GO_CURR.value(currentValue); GO_CURR.value<Dpt9>(currentValue);
double max = GO_MAX.value(); float max = GO_MAX.value<Dpt9>();
if (currentValue > max) if (currentValue > max)
GO_MAX.value(currentValue); GO_MAX.value<Dpt9>(currentValue);
if (currentValue < (double)GO_MIN.value()) if (currentValue < GO_MIN.value<Dpt9>())
GO_MIN.value(currentValue); GO_MIN.value<Dpt9>(currentValue);
} }
void handler(GroupObject& go) void handler(GroupObject& go)
{ {
if (go == GO_RESET && go.value()) if (go == GO_RESET && go.value<Dpt1>())
{ {
GO_MAX.valueNoSend(-273.0); GO_MAX.valueNoSend<Dpt9>(-273.0f);
GO_MIN.valueNoSend(670433.28); GO_MIN.valueNoSend<Dpt9>(670433.28f);
} }
} }
@ -110,12 +112,8 @@ void setup()
if (knx.configured()) if (knx.configured())
{ {
GO_CURR.dataPointType(Dpt(9, 1)); GO_MIN.value<Dpt9>(670433.28f);
GO_MIN.dataPointType(Dpt(9, 1)); GO_MAX.valueNoSend<Dpt9>(-273.0f);
GO_MIN.value(670433.28);
GO_MAX.dataPointType(Dpt(9, 1));
GO_MAX.valueNoSend(-273.0);
GO_RESET.dataPointType(Dpt(1, 15));
LOGGER.info("Startverzögerung s: %d", knx.paramByte(0)); LOGGER.info("Startverzögerung s: %d", knx.paramByte(0));
LOGGER.info("Aenderung senden (*0.1K): %d", knx.paramByte(1)); LOGGER.info("Aenderung senden (*0.1K): %d", knx.paramByte(1));
LOGGER.info("Zykl. senden min: %d", knx.paramByte(2)); LOGGER.info("Zykl. senden min: %d", knx.paramByte(2));

View File

@ -85,8 +85,6 @@ void setup(void)
cyclSend = knx.paramInt(0); cyclSend = knx.paramInt(0);
Serial1.print("Zykl. send:"); Serial1.print("Zykl. send:");
Serial1.println(cyclSend); Serial1.println(cyclSend);
goTemperature.dataPointType(Dpt(9, 1));
goHumidity.dataPointType(Dpt(9, 1));
} }
// start the framework. // start the framework.
@ -123,8 +121,8 @@ void loop(void)
{ {
sendCounter = 0; sendCounter = 0;
goTemperature.value(temp); goTemperature.value<Dpt9>(temp);
goHumidity.value(humi); goHumidity.value<Dpt9>(humi);
} }
} }

View File

@ -38,12 +38,15 @@ set(SOURCES
./knx/data_secure/secure_application_layer.h ./knx/data_secure/secure_application_layer.h
./knx/data_secure/security_interface_object.cpp ./knx/data_secure/security_interface_object.cpp
./knx/data_secure/security_interface_object.h ./knx/data_secure/security_interface_object.h
./knx/group_object/datapoint_types.cpp ./knx/group_object/dpt/dpts.h
./knx/group_object/datapoint_types.h ./knx/group_object/dpt/dpt.cpp
./knx/group_object/dpt.cpp ./knx/group_object/dpt/dpt.h
./knx/group_object/dpt.h ./knx/group_object/dpt/dpt1.cpp
./knx/group_object/dptconvert.cpp ./knx/group_object/dpt/dpt1.h
./knx/group_object/dptconvert.h ./knx/group_object/dpt/dpt9.cpp
./knx/group_object/dpt/dpt9.h
./knx/group_object/dpt/dptconvert.cpp
./knx/group_object/dpt/dptconvert.h
./knx/group_object/group_object.cpp ./knx/group_object/group_object.cpp
./knx/group_object/group_object.h ./knx/group_object/group_object.h
./knx/group_object/knx_value.cpp ./knx/group_object/knx_value.cpp

View File

@ -246,4 +246,5 @@ knx-->Platform
*/ */
#include "knx/knx_facade.h" #include "knx/knx_facade.h"
#include "knx/group_object/dpt/dpts.h"
using namespace Knx; using namespace Knx;

View File

@ -1,68 +0,0 @@
/*
* datapoint_types.h - Conversion functions for datapoint types.
*
* Copyright (c) 2014 Stefan Taferner <stefan.taferner@gmx.at>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*/
#include "datapoint_types.h"
#include <stdint.h>
namespace Knx
{
// Sign for a negative DPT9 float value
#define DPT_FLOAT_NEG_SIGN 0x8000
uint16_t dptToFloat(int32_t value)
{
uint16_t exp = 0;
if (value < -67108864 || value > 67076096)
return 0x7fff;
if (value < 0)
{
while (value < -2048)
{
value >>= 1;
++exp;
}
return DPT_FLOAT_NEG_SIGN | (((int32_t) value) & 2047) | (exp << 11);
}
else
{
while (value > 2047)
{
value >>= 1;
++exp;
}
return value | (exp << 11);
}
}
int32_t dptFromFloat(uint16_t dptValue)
{
uint16_t exp = (dptValue >> 11) & 15;
int32_t value;
if (dptValue == 0x7fff)
return INVALID_DPT_FLOAT;
if (dptValue >= 0x8000)
value = dptValue | (-1L & ~2047);
else
value = dptValue & 2047;
for (; exp; --exp)
value <<= 1;
return value;
}
}

View File

@ -1,41 +0,0 @@
/*
* datapoint_types.h - Conversion functions for datapoint types.
*
* Copyright (c) 2014 Stefan Taferner <stefan.taferner@gmx.at>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*/
#pragma once
#include <stdint.h>
namespace Knx
{
/**
* An invalid 2 uint8_t float (DPT9/EIS5).
* To be used for dptToFloat() and dptFromFloat().
*/
#define INVALID_DPT_FLOAT 2147483647U
/**
* Convert a value from uint32_t to 2 uint8_t float (DPT9/EIS5). The possible range
* of the values is -67108864 to 67076096.
*
* @param value - the value to convert.
* Use INVALID_DPT_FLOAT for the DPT9 "invalid data" value.
* @return The 2 uint8_t float (DPT9/EIS5).
*/
uint16_t dptToFloat(int32_t value);
/**
* Convert a value from 2 uint8_t float (DPT9/EIS5) to integer.
*
* @param dptValue - the 2 uint8_t float (DPT9/EIS5) to convert
* @return The value as integer, or INVALID_DPT_FLOAT for the
* DPT9 "invalid data" value.
*/
int32_t dptFromFloat(uint16_t dptValue);
}

View File

@ -1,7 +1,7 @@
#include "dpt.h" #include "dpt.h"
#include "../util/logger.h" #include "../../util/logger.h"
#include "../bits.h" #include "../../bits.h"
#define LOGGER Logger::logger("Dpt") #define LOGGER Logger::logger("Dpt")
@ -16,14 +16,4 @@ namespace Knx
if (subGroup == 0) if (subGroup == 0)
println("WARNING: You used and invalid Dpt *.0"); println("WARNING: You used and invalid Dpt *.0");
} }
bool Dpt::operator==(const Dpt& other) const
{
return other.mainGroup == mainGroup && other.subGroup == subGroup && other.index == index;
}
bool Dpt::operator!=(const Dpt& other) const
{
return !(other == *this);
}
} }

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include "../group_object.h"
namespace Knx namespace Knx
{ {
#define DPT_Switch Dpt(1, 1) #define DPT_Switch Dpt(1, 1)
@ -367,12 +368,14 @@ namespace Knx
public: public:
Dpt(); Dpt();
Dpt(short mainGroup, short subGroup, short index = 0); Dpt(short mainGroup, short subGroup, short index = 0);
virtual ~Dpt() {}
unsigned short mainGroup; unsigned short mainGroup;
unsigned short subGroup; unsigned short subGroup;
unsigned short index; unsigned short index;
bool operator==(const Dpt& other) const;
bool operator!=(const Dpt& other) const;
virtual Go_SizeCode size() const = 0;
virtual void encode(uint8_t* data) const = 0;
virtual void decode(uint8_t* data) = 0;
}; };
} }

View File

@ -0,0 +1,44 @@
#include "dpt1.h"
#include "dptconvert.h"
Knx::Dpt1::Dpt1() {}
Knx::Dpt1::Dpt1(bool value) : _value(value) {}
Knx::Go_SizeCode Knx::Dpt1::size() const
{
return Go_1_Bit;
}
void Knx::Dpt1::encode(uint8_t* data) const
{
bitToPayload(data, 7, _value);
}
void Knx::Dpt1::decode(uint8_t* data)
{
_value = bitFromPayload(data, 7);
}
void Knx::Dpt1::value(bool value)
{
_value = value;
}
bool Knx::Dpt1::value()
{
return _value;
}
Knx::Dpt1::operator bool() const
{
return _value;
}
Knx::Dpt1& Knx::Dpt1::operator=(const bool value)
{
_value = value;
return *this;
}

View File

@ -0,0 +1,22 @@
#pragma once
#include "dpt.h"
namespace Knx
{
class Dpt1: public Dpt
{
public:
Dpt1();
Dpt1(bool value);
Go_SizeCode size() const override;
virtual void encode(uint8_t* data) const override;
virtual void decode(uint8_t* data) override;
void value(bool value);
bool value();
operator bool() const;
Dpt1& operator=(const bool value);
private:
bool _value;
};
}

View File

@ -0,0 +1,47 @@
#include "dpt9.h"
#include "dptconvert.h"
Knx::Dpt9::Dpt9() {}
Knx::Dpt9::Dpt9(float value) : _value(value) {}
Knx::Go_SizeCode Knx::Dpt9::size() const
{
return Go_1_Bit;
}
void Knx::Dpt9::encode(uint8_t* data) const
{
float16ToPayload(data, 0, _value, 0xFFFF);
}
void Knx::Dpt9::decode(uint8_t* data)
{
if (unsigned16FromPayload(data, 0) == 0x7FFF)
return;
_value = float16FromPayload(data, 0);
}
void Knx::Dpt9::value(float value)
{
_value = value;
}
bool Knx::Dpt9::value()
{
return _value;
}
Knx::Dpt9::operator float() const
{
return _value;
}
Knx::Dpt9& Knx::Dpt9::operator=(const float value)
{
_value = value;
return *this;
}

View File

@ -0,0 +1,22 @@
#pragma once
#include "dpt.h"
namespace Knx
{
class Dpt9: public Dpt
{
public:
Dpt9();
Dpt9(float value);
Go_SizeCode size() const override;
virtual void encode(uint8_t* data) const override;
virtual void decode(uint8_t* data) override;
void value(float value);
bool value();
operator float() const;
Dpt9& operator=(const float value);
private:
float _value;
};
}

View File

@ -1,6 +1,6 @@
#include "dptconvert.h" #include "dptconvert.h"
#include "../bits.h" #include "../../bits.h"
#include <cmath> #include <cmath>
#include <cstdlib> #include <cstdlib>
@ -18,11 +18,7 @@ namespace Knx
{ {
if (payload_length > 0) if (payload_length > 0)
{ {
// DPT 1.* - Binary // DPT 2.* - Binary Control
if (datatype.mainGroup == 1 && datatype.subGroup >= 1 && datatype.subGroup <= 23 && datatype.subGroup != 20 && !datatype.index)
{
return busValueToBinary(payload, payload_length, datatype, value);
} // DPT 2.* - Binary Control
if (datatype.mainGroup == 2 && datatype.subGroup >= 1 && datatype.subGroup <= 12 && datatype.index <= 1) if (datatype.mainGroup == 2 && datatype.subGroup >= 1 && datatype.subGroup <= 12 && datatype.index <= 1)
return busValueToBinaryControl(payload, payload_length, datatype, value); return busValueToBinaryControl(payload, payload_length, datatype, value);
@ -63,10 +59,6 @@ namespace Knx
if (datatype.mainGroup == 8 && datatype.subGroup >= 2 && datatype.subGroup <= 7 && !datatype.index) if (datatype.mainGroup == 8 && datatype.subGroup >= 2 && datatype.subGroup <= 7 && !datatype.index)
return busValueToTimeDelta(payload, payload_length, datatype, value); return busValueToTimeDelta(payload, payload_length, datatype, value);
// DPT 9.* - 16 Bit Float
if (datatype.mainGroup == 9 && ((datatype.subGroup >= 1 && datatype.subGroup <= 11) || (datatype.subGroup >= 20 && datatype.subGroup <= 29)) && !datatype.index)
return busValueToFloat16(payload, payload_length, datatype, value);
// DPT 10.* - Time and Weekday // DPT 10.* - Time and Weekday
if (datatype.mainGroup == 10 && datatype.subGroup == 1 && datatype.index <= 1) if (datatype.mainGroup == 10 && datatype.subGroup == 1 && datatype.index <= 1)
return busValueToTime(payload, payload_length, datatype, value); return busValueToTime(payload, payload_length, datatype, value);
@ -181,8 +173,6 @@ namespace Knx
int KNX_Encode_Value(const KNXValue& value, uint8_t* payload, size_t payload_length, const Dpt& datatype) int KNX_Encode_Value(const KNXValue& value, uint8_t* payload, size_t payload_length, const Dpt& datatype)
{ {
if (datatype.mainGroup == 1 && datatype.subGroup >= 1 && datatype.subGroup <= 23 && datatype.subGroup != 20 && !datatype.index)
return valueToBusValueBinary(value, payload, payload_length, datatype);
// DPT 2.* - Binary Control // DPT 2.* - Binary Control
if (datatype.mainGroup == 2 && datatype.subGroup >= 1 && datatype.subGroup <= 12 && datatype.index <= 1) if (datatype.mainGroup == 2 && datatype.subGroup >= 1 && datatype.subGroup <= 12 && datatype.index <= 1)
@ -224,10 +214,6 @@ namespace Knx
if (datatype.mainGroup == 8 && datatype.subGroup >= 2 && datatype.subGroup <= 7 && !datatype.index) if (datatype.mainGroup == 8 && datatype.subGroup >= 2 && datatype.subGroup <= 7 && !datatype.index)
return valueToBusValueTimeDelta(value, payload, payload_length, datatype); return valueToBusValueTimeDelta(value, payload, payload_length, datatype);
// DPT 9.* - 16 Bit Float
if (datatype.mainGroup == 9 && ((datatype.subGroup >= 1 && datatype.subGroup <= 11 ) || (datatype.subGroup >= 20 && datatype.subGroup <= 29)) && !datatype.index)
return valueToBusValueFloat16(value, payload, payload_length, datatype);
// DPT 10.* - Time and Weekday // DPT 10.* - Time and Weekday
if (datatype.mainGroup == 10 && datatype.subGroup == 1 && datatype.index <= 1) if (datatype.mainGroup == 10 && datatype.subGroup == 1 && datatype.index <= 1)
return valueToBusValueTime(value, payload, payload_length, datatype); return valueToBusValueTime(value, payload, payload_length, datatype);
@ -339,13 +325,6 @@ namespace Knx
return false; return false;
} }
int busValueToBinary(const uint8_t* payload, size_t payload_length, const Dpt& datatype, KNXValue& value)
{
ASSERT_PAYLOAD(1);
value = bitFromPayload(payload, 7);
return true;
}
int busValueToBinaryControl(const uint8_t* payload, size_t payload_length, const Dpt& datatype, KNXValue& value) int busValueToBinaryControl(const uint8_t* payload, size_t payload_length, const Dpt& datatype, KNXValue& value)
{ {
ASSERT_PAYLOAD(1); ASSERT_PAYLOAD(1);
@ -496,16 +475,6 @@ namespace Knx
return true; return true;
} }
int busValueToFloat16(const uint8_t* payload, size_t payload_length, const Dpt& datatype, KNXValue& value)
{
ASSERT_PAYLOAD(2);
if (unsigned16FromPayload(payload, 0) == 0x7FFF)
return false;
value = float16FromPayload(payload, 0);
return true;
}
int busValueToTime(const uint8_t* payload, size_t payload_length, const Dpt& datatype, KNXValue& value) int busValueToTime(const uint8_t* payload, size_t payload_length, const Dpt& datatype, KNXValue& value)
{ {
@ -1019,22 +988,16 @@ namespace Knx
//------------------------------------------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------------------------------------------
int valueToBusValueBinary(const KNXValue& value, uint8_t* payload, size_t payload_length, const Dpt& datatype)
{
bitToPayload(payload, payload_length, 7, value);
return true;
}
int valueToBusValueBinaryControl(const KNXValue& value, uint8_t* payload, size_t payload_length, const Dpt& datatype) int valueToBusValueBinaryControl(const KNXValue& value, uint8_t* payload, size_t payload_length, const Dpt& datatype)
{ {
switch (datatype.index) switch (datatype.index)
{ {
case 0: case 0:
bitToPayload(payload, payload_length, 6, value); bitToPayload(payload, 6, value);
break; break;
case 1: case 1:
bitToPayload(payload, payload_length, 7, value); bitToPayload(payload, 7, value);
break; break;
default: default:
@ -1049,7 +1012,7 @@ namespace Knx
switch (datatype.index) switch (datatype.index)
{ {
case 0: case 0:
bitToPayload(payload, payload_length, 4, value); bitToPayload(payload, 4, value);
break; break;
case 1: case 1:
@ -1057,7 +1020,7 @@ namespace Knx
if ((int64_t)value < INT64_C(0) || (int64_t)value > INT64_C(7)) if ((int64_t)value < INT64_C(0) || (int64_t)value > INT64_C(7))
return false; return false;
unsigned8ToPayload(payload, payload_length, 0, (uint64_t)value, 0x07); unsigned8ToPayload(payload, 0, (uint64_t)value, 0x07);
} }
break; break;
@ -1073,7 +1036,7 @@ namespace Knx
if ((uint64_t)value > INT64_C(255) || (datatype.subGroup == 1 && (uint64_t)value > INT64_C(127))) if ((uint64_t)value > INT64_C(255) || (datatype.subGroup == 1 && (uint64_t)value > INT64_C(127)))
return false; return false;
unsigned8ToPayload(payload, payload_length, 0, (uint64_t)value, 0xFF); unsigned8ToPayload(payload, 0, (uint64_t)value, 0xFF);
return true; return true;
} }
@ -1089,7 +1052,7 @@ namespace Knx
if ((double)value > 100.0) if ((double)value > 100.0)
return false; return false;
unsigned8ToPayload(payload, payload_length, 0, round((double)value * 255.0 / 100.0), 0xFF); unsigned8ToPayload(payload, 0, round((double)value * 255.0 / 100.0), 0xFF);
break; break;
} }
@ -1098,7 +1061,7 @@ namespace Knx
if ((double)value > 360.0) if ((double)value > 360.0)
return false; return false;
unsigned8ToPayload(payload, payload_length, 0, round((double)value * 255.0 / 360.0), 0xFF); unsigned8ToPayload(payload, 0, round((double)value * 255.0 / 360.0), 0xFF);
break; break;
} }
@ -1107,7 +1070,7 @@ namespace Knx
if ((int64_t)value > INT64_C(254)) if ((int64_t)value > INT64_C(254))
return false; return false;
unsigned8ToPayload(payload, payload_length, 0, (uint64_t)value, 0xFF); unsigned8ToPayload(payload, 0, (uint64_t)value, 0xFF);
break; break;
} }
@ -1116,7 +1079,7 @@ namespace Knx
if ((int64_t)value > INT64_C(255)) if ((int64_t)value > INT64_C(255))
return false; return false;
unsigned8ToPayload(payload, payload_length, 0, (uint64_t)value, 0xFF); unsigned8ToPayload(payload, 0, (uint64_t)value, 0xFF);
} }
} }
@ -1128,20 +1091,20 @@ namespace Knx
if ((int64_t)value < INT64_C(-128) || (int64_t)value > INT64_C(127)) if ((int64_t)value < INT64_C(-128) || (int64_t)value > INT64_C(127))
return false; return false;
signed8ToPayload(payload, payload_length, 0, (uint64_t)value, 0xFF); signed8ToPayload(payload, 0, (uint64_t)value, 0xFF);
return true; return true;
} }
int valueToBusValueStatusAndMode(const KNXValue& value, uint8_t* payload, size_t payload_length, const Dpt& datatype) int valueToBusValueStatusAndMode(const KNXValue& value, uint8_t* payload, size_t payload_length, const Dpt& datatype)
{ {
if (datatype.index < 5) if (datatype.index < 5)
bitToPayload(payload, payload_length, datatype.index, value); bitToPayload(payload, datatype.index, value);
else if (datatype.index == 5) else if (datatype.index == 5)
{ {
if ((int64_t)value < INT64_C(0) || (int64_t)value > INT64_C(7)) if ((int64_t)value < INT64_C(0) || (int64_t)value > INT64_C(7))
return false; return false;
unsigned8ToPayload(payload, payload_length, 0, (uint64_t)value, 0x07); unsigned8ToPayload(payload, 0, (uint64_t)value, 0x07);
} }
else else
return false; return false;
@ -1154,7 +1117,7 @@ namespace Knx
if ((int64_t)value < INT64_C(0) || (int64_t)value > INT64_C(65535)) if ((int64_t)value < INT64_C(0) || (int64_t)value > INT64_C(65535))
return false; return false;
unsigned16ToPayload(payload, payload_length, 0, (uint64_t)value, 0xFFFF); unsigned16ToPayload(payload, 0, (uint64_t)value, 0xFFFF);
return true; return true;
} }
@ -1166,7 +1129,7 @@ namespace Knx
if (timeSinceEpoch < INT64_C(0) || timeSinceEpoch > INT64_C(65535)) if (timeSinceEpoch < INT64_C(0) || timeSinceEpoch > INT64_C(65535))
return false; return false;
unsigned16ToPayload(payload, payload_length, 0, timeSinceEpoch, 0xFFFF); unsigned16ToPayload(payload, 0, timeSinceEpoch, 0xFFFF);
return true; return true;
} }
@ -1180,10 +1143,10 @@ namespace Knx
if ((double)value < -327.68 || (double)value > 327.67) if ((double)value < -327.68 || (double)value > 327.67)
return false; return false;
signed16ToPayload(payload, payload_length, 0, (int16_t)((double)value * 100.0), 0xFFFF); signed16ToPayload(payload, 0, (int16_t)((double)value * 100.0), 0xFFFF);
} }
else else
signed16ToPayload(payload, payload_length, 0, (uint64_t)value, 0xffff); signed16ToPayload(payload, 0, (uint64_t)value, 0xffff);
return true; return true;
} }
@ -1196,66 +1159,11 @@ namespace Knx
if (timeSinceEpoch < INT64_C(-32768) || timeSinceEpoch > INT64_C(32767)) if (timeSinceEpoch < INT64_C(-32768) || timeSinceEpoch > INT64_C(32767))
return false; return false;
signed16ToPayload(payload, payload_length, 0, timeSinceEpoch, 0xFFFF); signed16ToPayload(payload, 0, timeSinceEpoch, 0xFFFF);
return true; return true;
} }
int valueToBusValueFloat16(const KNXValue& value, uint8_t* payload, size_t payload_length, const Dpt& datatype)
{
double numValue = value;
// bigger values like 670760.0 result in 0x7FFF which denotes invalid data.
// I'm not sure if the GO shouldn't be updated to this value instead
if (numValue > 670433.28)
return false;
if (numValue < -671088.64)
return false;
switch (datatype.subGroup)
{
case 1:
if (numValue < -273.0)
return false;
break;
case 2:
case 3:
case 10:
case 11:
case 20:
case 21:
case 22:
case 23:
case 24:
case 25:
if (numValue < -670760.0)
return false;
break;
case 4:
case 5:
case 6:
case 7:
case 8:
case 28:
if (numValue < 0.0)
return false;
break;
case 27:
if (numValue < -459.6)
return false;
break;
}
float16ToPayload(payload, payload_length, 0, numValue, 0xFFFF);
return true;
}
int valueToBusValueTime(const KNXValue& value, uint8_t* payload, size_t payload_length, const Dpt& datatype) int valueToBusValueTime(const KNXValue& value, uint8_t* payload, size_t payload_length, const Dpt& datatype)
{ {
@ -1267,16 +1175,16 @@ namespace Knx
return false; return false;
ENSURE_PAYLOAD(3); ENSURE_PAYLOAD(3);
unsigned8ToPayload(payload, payload_length, 0, (uint64_t)value << 5, 0xE0); unsigned8ToPayload(payload, 0, (uint64_t)value << 5, 0xE0);
break; break;
} }
case 1: case 1:
{ {
struct tm tmp = value; struct tm tmp = value;
unsigned8ToPayload(payload, payload_length, 0, tmp.tm_hour, 0x1F); unsigned8ToPayload(payload, 0, tmp.tm_hour, 0x1F);
unsigned8ToPayload(payload, payload_length, 1, tmp.tm_min, 0x3F); unsigned8ToPayload(payload, 1, tmp.tm_min, 0x3F);
unsigned8ToPayload(payload, payload_length, 2, tmp.tm_sec, 0x3F); unsigned8ToPayload(payload, 2, tmp.tm_sec, 0x3F);
break; break;
} }
@ -1294,9 +1202,9 @@ namespace Knx
if (tmp.tm_year < 1990 || tmp.tm_year > 2089) if (tmp.tm_year < 1990 || tmp.tm_year > 2089)
return false; return false;
unsigned8ToPayload(payload, payload_length, 0, tmp.tm_mday, 0x1F); unsigned8ToPayload(payload, 0, tmp.tm_mday, 0x1F);
unsigned8ToPayload(payload, payload_length, 1, tmp.tm_mon, 0x0F); unsigned8ToPayload(payload, 1, tmp.tm_mon, 0x0F);
unsigned8ToPayload(payload, payload_length, 2, tmp.tm_year % 100, 0x7F); unsigned8ToPayload(payload, 2, tmp.tm_year % 100, 0x7F);
return true; return true;
} }
@ -1305,7 +1213,7 @@ namespace Knx
if ((int64_t)value < INT64_C(0) || (int64_t)value > INT64_C(4294967295)) if ((int64_t)value < INT64_C(0) || (int64_t)value > INT64_C(4294967295))
return false; return false;
unsigned32ToPayload(payload, payload_length, 0, (uint64_t)value, 0xFFFFFFFF); unsigned32ToPayload(payload, 0, (uint64_t)value, 0xFFFFFFFF);
return true; return true;
} }
@ -1314,7 +1222,7 @@ namespace Knx
if ((int64_t)value < INT64_C(-2147483648) || (int64_t)value > INT64_C(2147483647)) if ((int64_t)value < INT64_C(-2147483648) || (int64_t)value > INT64_C(2147483647))
return false; return false;
signed32ToPayload(payload, payload_length, 0, (uint64_t)value, 0xFFFFFFFF); signed32ToPayload(payload, 0, (uint64_t)value, 0xFFFFFFFF);
return true; return true;
} }
@ -1323,7 +1231,7 @@ namespace Knx
if ((int64_t)value < INT64_C(-2147483648) || (int64_t)value > INT64_C(2147483647)) if ((int64_t)value < INT64_C(-2147483648) || (int64_t)value > INT64_C(2147483647))
return false; return false;
signed32ToPayload(payload, payload_length, 0, (uint64_t)value, 0xFFFFFFFF); signed32ToPayload(payload, 0, (uint64_t)value, 0xFFFFFFFF);
return true; return true;
} }
@ -1334,7 +1242,7 @@ namespace Knx
if (numValue < (-8388608.0 * pow(2, 255)) || numValue > (8388607.0 * pow(2, 255))) if (numValue < (-8388608.0 * pow(2, 255)) || numValue > (8388607.0 * pow(2, 255)))
return false; return false;
float32ToPayload(payload, payload_length, 0, numValue, 0xFFFFFFFF); float32ToPayload(payload, 0, numValue, 0xFFFFFFFF);
return true; return true;
} }
@ -1350,7 +1258,7 @@ namespace Knx
ENSURE_PAYLOAD(4); ENSURE_PAYLOAD(4);
for (int n = 0, factor = 100000; n < 6; ++n, factor /= 10) for (int n = 0, factor = 100000; n < 6; ++n, factor /= 10)
bcdToPayload(payload, payload_length, n, ((uint64_t)value / factor) % 10); bcdToPayload(payload, n, ((uint64_t)value / factor) % 10);
break; break;
} }
@ -1359,7 +1267,7 @@ namespace Knx
case 2: case 2:
case 3: case 3:
case 4: case 4:
bitToPayload(payload, payload_length, 23 + datatype.index, value); bitToPayload(payload, 23 + datatype.index, value);
break; break;
case 5: case 5:
@ -1367,7 +1275,7 @@ namespace Knx
if ((uint64_t)value > INT64_C(15)) if ((uint64_t)value > INT64_C(15))
return false; return false;
bcdToPayload(payload, payload_length, 7, (uint64_t)value); bcdToPayload(payload, 7, (uint64_t)value);
break; break;
} }
@ -1388,7 +1296,7 @@ namespace Knx
if (val) if (val)
val = strValue[n]; //string terminator 0x00 will stop further assignments and init the remainig payload with zero val = strValue[n]; //string terminator 0x00 will stop further assignments and init the remainig payload with zero
unsigned8ToPayload(payload, payload_length, n, val, 0xff); unsigned8ToPayload(payload, n, val, 0xff);
} }
return true; return true;
@ -1399,7 +1307,7 @@ namespace Knx
if ((int64_t)value < INT64_C(0) || (int64_t)value > INT64_C(63)) if ((int64_t)value < INT64_C(0) || (int64_t)value > INT64_C(63))
return false; return false;
unsigned8ToPayload(payload, payload_length, 0, (uint64_t)value, 0xFF); unsigned8ToPayload(payload, 0, (uint64_t)value, 0xFF);
return true; return true;
} }
@ -1408,7 +1316,7 @@ namespace Knx
switch (datatype.index) switch (datatype.index)
{ {
case 0: case 0:
bitToPayload(payload, payload_length, 0, value); bitToPayload(payload, 0, value);
break; break;
case 1: case 1:
@ -1416,7 +1324,7 @@ namespace Knx
if ((int64_t)value < INT64_C(0) || (int64_t)value > INT64_C(63)) if ((int64_t)value < INT64_C(0) || (int64_t)value > INT64_C(63))
return false; return false;
unsigned8ToPayload(payload, payload_length, 0, (int64_t)value, 0x3F); unsigned8ToPayload(payload, 0, (int64_t)value, 0x3F);
break; break;
} }
@ -1432,7 +1340,7 @@ namespace Knx
switch (datatype.index) switch (datatype.index)
{ {
case 0: case 0:
bitToPayload(payload, payload_length, 1, value); bitToPayload(payload, 1, value);
break; break;
case 1: case 1:
@ -1440,7 +1348,7 @@ namespace Knx
if ((int64_t)value < INT64_C(0) || (int64_t)value > INT64_C(63)) if ((int64_t)value < INT64_C(0) || (int64_t)value > INT64_C(63))
return false; return false;
unsigned8ToPayload(payload, payload_length, 0, (int64_t)value, 0x3F); unsigned8ToPayload(payload, 0, (int64_t)value, 0x3F);
break; break;
} }
@ -1460,13 +1368,13 @@ namespace Knx
if ((int64_t)value < INT64_C(0) || (int64_t)value > INT64_C(63)) if ((int64_t)value < INT64_C(0) || (int64_t)value > INT64_C(63))
return false; return false;
unsigned8ToPayload(payload, payload_length, 0, (int64_t)value, 0x3F); unsigned8ToPayload(payload, 0, (int64_t)value, 0x3F);
break; break;
} }
case 1: case 1:
case 2: case 2:
bitToPayload(payload, payload_length, 2 - datatype.index, value); bitToPayload(payload, 2 - datatype.index, value);
break; break;
default: default:
@ -1490,16 +1398,16 @@ namespace Knx
ENSURE_PAYLOAD(8); ENSURE_PAYLOAD(8);
struct tm tmp = value; struct tm tmp = value;
bitToPayload(payload, payload_length, 51, false); bitToPayload(payload, 51, false);
bitToPayload(payload, payload_length, 52, false); bitToPayload(payload, 52, false);
unsigned8ToPayload(payload, payload_length, 0, tmp.tm_year - 1900, 0xFF); unsigned8ToPayload(payload, 0, tmp.tm_year - 1900, 0xFF);
unsigned8ToPayload(payload, payload_length, 1, tmp.tm_mon, 0x0F); unsigned8ToPayload(payload, 1, tmp.tm_mon, 0x0F);
unsigned8ToPayload(payload, payload_length, 2, tmp.tm_mday, 0x1F); unsigned8ToPayload(payload, 2, tmp.tm_mday, 0x1F);
bitToPayload(payload, payload_length, 54, false); bitToPayload(payload, 54, false);
unsigned8ToPayload(payload, payload_length, 3, tmp.tm_hour, 0x1F); unsigned8ToPayload(payload, 3, tmp.tm_hour, 0x1F);
unsigned8ToPayload(payload, payload_length, 4, tmp.tm_min, 0x3F); unsigned8ToPayload(payload, 4, tmp.tm_min, 0x3F);
unsigned8ToPayload(payload, payload_length, 5, tmp.tm_sec, 0x3F); unsigned8ToPayload(payload, 5, tmp.tm_sec, 0x3F);
break; break;
} }
@ -1508,11 +1416,11 @@ namespace Knx
ENSURE_PAYLOAD(8); ENSURE_PAYLOAD(8);
if ((int64_t)value < INT64_C(0) || (int64_t)value > INT64_C(7)) if ((int64_t)value < INT64_C(0) || (int64_t)value > INT64_C(7))
bitToPayload(payload, payload_length, 53, true); bitToPayload(payload, 53, true);
else else
{ {
bitToPayload(payload, payload_length, 53, false); bitToPayload(payload, 53, false);
unsigned8ToPayload(payload, payload_length, 3, (int64_t)value << 5, 0xE0); unsigned8ToPayload(payload, 3, (int64_t)value << 5, 0xE0);
} }
break; break;
@ -1521,28 +1429,28 @@ namespace Knx
case 2: case 2:
{ {
ENSURE_PAYLOAD(8); ENSURE_PAYLOAD(8);
bitToPayload(payload, payload_length, 49, value); bitToPayload(payload, 49, value);
bitToPayload(payload, payload_length, 50, false); bitToPayload(payload, 50, false);
break; break;
} }
case 3: case 3:
{ {
ENSURE_PAYLOAD(8); ENSURE_PAYLOAD(8);
bitToPayload(payload, payload_length, 48, value); bitToPayload(payload, 48, value);
break; break;
} }
case 9: case 9:
{ {
ENSURE_PAYLOAD(8); ENSURE_PAYLOAD(8);
bitToPayload(payload, payload_length, 55, value); bitToPayload(payload, 55, value);
break; break;
} }
case 10: case 10:
{ {
bitToPayload(payload, payload_length, 56, value); bitToPayload(payload, 56, value);
break; break;
} }
@ -1561,7 +1469,7 @@ namespace Knx
int valueToBusValueSigned64(const KNXValue& value, uint8_t* payload, size_t payload_length, const Dpt& datatype) int valueToBusValueSigned64(const KNXValue& value, uint8_t* payload, size_t payload_length, const Dpt& datatype)
{ {
signed64ToPayload(payload, payload_length, 0, (int64_t)value, UINT64_C(0xFFFFFFFFFFFFFFFF)); signed64ToPayload(payload, 0, (int64_t)value, UINT64_C(0xFFFFFFFFFFFFFFFF));
return true; return true;
} }
@ -1575,7 +1483,7 @@ namespace Knx
return false; return false;
ENSURE_PAYLOAD(6); ENSURE_PAYLOAD(6);
unsigned8ToPayload(payload, payload_length, 1, (int64_t)value, 0xFF); unsigned8ToPayload(payload, 1, (int64_t)value, 0xFF);
break; break;
} }
@ -1587,7 +1495,7 @@ namespace Knx
return false; return false;
ENSURE_PAYLOAD(6); ENSURE_PAYLOAD(6);
unsigned8ToPayload(payload, payload_length, datatype.index, (int64_t)value, 0xFF); unsigned8ToPayload(payload, datatype.index, (int64_t)value, 0xFF);
break; break;
} }
@ -1597,7 +1505,7 @@ namespace Knx
case 7: case 7:
{ {
ENSURE_PAYLOAD(6); ENSURE_PAYLOAD(6);
bitToPayload(payload, payload_length, 43 - datatype.index, value); bitToPayload(payload, 43 - datatype.index, value);
break; break;
} }
@ -1606,7 +1514,7 @@ namespace Knx
case 10: case 10:
{ {
ENSURE_PAYLOAD(6); ENSURE_PAYLOAD(6);
bitToPayload(payload, payload_length, 55 - datatype.index, value); bitToPayload(payload, 55 - datatype.index, value);
break; break;
} }
@ -1627,7 +1535,7 @@ namespace Knx
return false; return false;
ENSURE_PAYLOAD(6); ENSURE_PAYLOAD(6);
unsigned16ToPayload(payload, payload_length, 0, (int64_t)value, 0xFFFF); unsigned16ToPayload(payload, 0, (int64_t)value, 0xFFFF);
break; break;
} }
@ -1637,7 +1545,7 @@ namespace Knx
return false; return false;
ENSURE_PAYLOAD(6); ENSURE_PAYLOAD(6);
unsigned32ToPayload(payload, payload_length, 2, (int64_t)value, 0xFFFF); unsigned32ToPayload(payload, 2, (int64_t)value, 0xFFFF);
break; break;
} }
@ -1658,7 +1566,7 @@ namespace Knx
return false; return false;
ENSURE_PAYLOAD(2); ENSURE_PAYLOAD(2);
unsigned8ToPayload(payload, payload_length, 0, (int64_t)value << 3, 0xF8); unsigned8ToPayload(payload, 0, (int64_t)value << 3, 0xF8);
break; break;
} }
@ -1667,7 +1575,7 @@ namespace Knx
if ((int64_t)value < INT64_C(0) || (int64_t)value > INT64_C(31)) if ((int64_t)value < INT64_C(0) || (int64_t)value > INT64_C(31))
return false; return false;
unsigned16ToPayload(payload, payload_length, 0, (int64_t)value << 6, 0x07C0); unsigned16ToPayload(payload, 0, (int64_t)value << 6, 0x07C0);
break; break;
} }
@ -1676,7 +1584,7 @@ namespace Knx
if ((int64_t)value < INT64_C(0) || (int64_t)value > INT64_C(63)) if ((int64_t)value < INT64_C(0) || (int64_t)value > INT64_C(63))
return false; return false;
unsigned8ToPayload(payload, payload_length, 1, (int64_t)value, 0x3F); unsigned8ToPayload(payload, 1, (int64_t)value, 0x3F);
break; break;
} }
@ -1699,7 +1607,7 @@ namespace Knx
return false; return false;
ENSURE_PAYLOAD(3); ENSURE_PAYLOAD(3);
unsigned16ToPayload(payload, payload_length, 0, duration, 0xFFFF); unsigned16ToPayload(payload, 0, duration, 0xFFFF);
return true; return true;
} }
@ -1708,7 +1616,7 @@ namespace Knx
if ((double)value < 0.0 || (double)value > 100.0) if ((double)value < 0.0 || (double)value > 100.0)
return false; return false;
unsigned8ToPayload(payload, payload_length, 2, round((double)value * 255.0 / 100.0), 0xff); unsigned8ToPayload(payload, 2, round((double)value * 255.0 / 100.0), 0xff);
break; break;
} }
} }
@ -1728,7 +1636,7 @@ namespace Knx
return false; return false;
ENSURE_PAYLOAD(3); ENSURE_PAYLOAD(3);
unsigned16ToPayload(payload, payload_length, 0, duration, 0xFFFF); unsigned16ToPayload(payload, 0, duration, 0xFFFF);
return true; return true;
} }
@ -1737,7 +1645,7 @@ namespace Knx
if ((int64_t)value < INT64_C(0) || (int64_t)value > INT64_C(254)) if ((int64_t)value < INT64_C(0) || (int64_t)value > INT64_C(254))
return false; return false;
unsigned8ToPayload(payload, payload_length, 2, (int64_t)value, 0xff); unsigned8ToPayload(payload, 2, (int64_t)value, 0xff);
break; break;
} }
} }
@ -1755,8 +1663,8 @@ namespace Knx
if (!datatype.index || (datatype.mainGroup == 231 && datatype.index == 1)) if (!datatype.index || (datatype.mainGroup == 231 && datatype.index == 1))
{ {
ENSURE_PAYLOAD(datatype.mainGroup == 231 ? 4 : 2); ENSURE_PAYLOAD(datatype.mainGroup == 231 ? 4 : 2);
unsigned8ToPayload(payload, payload_length, datatype.index * 2, ((const char*)value)[0], 0xff); unsigned8ToPayload(payload, datatype.index * 2, ((const char*)value)[0], 0xff);
unsigned8ToPayload(payload, payload_length, datatype.index * 2 + 1, ((const char*)value)[1], 0xff); unsigned8ToPayload(payload, datatype.index * 2 + 1, ((const char*)value)[1], 0xff);
return true; return true;
} }
@ -1770,8 +1678,8 @@ namespace Knx
unsigned int rgb = (int64_t)value; unsigned int rgb = (int64_t)value;
unsigned16ToPayload(payload, payload_length, 0, rgb / 256, 0xffff); unsigned16ToPayload(payload, 0, rgb / 256, 0xffff);
unsigned8ToPayload(payload, payload_length, 2, rgb % 256, 0xff); unsigned8ToPayload(payload, 2, rgb % 256, 0xff);
return true; return true;
} }
@ -1782,12 +1690,12 @@ namespace Knx
case 0: // RGBW case 0: // RGBW
{ {
uint32_t rgbw = (uint32_t)value; uint32_t rgbw = (uint32_t)value;
unsigned32ToPayload(payload, payload_length, 0, rgbw, 0xffffffff); // RGBW unsigned32ToPayload(payload, 0, rgbw, 0xffffffff); // RGBW
} }
break; break;
case 1: // Mask bits case 1: // Mask bits
unsigned8ToPayload(payload, payload_length, 5, (uint8_t)value, 0x0f); unsigned8ToPayload(payload, 5, (uint8_t)value, 0x0f);
break; break;
} }
@ -1804,12 +1712,12 @@ namespace Knx
return false; return false;
ENSURE_PAYLOAD(2); ENSURE_PAYLOAD(2);
unsigned8ToPayload(payload, payload_length, 0, round((double)value * 255.0 / 100.0), 0xff); unsigned8ToPayload(payload, 0, round((double)value * 255.0 / 100.0), 0xff);
break; break;
} }
case 1: case 1:
bitToPayload(payload, payload_length, 15, value); bitToPayload(payload, 15, value);
break; break;
default: default:
@ -1829,7 +1737,7 @@ namespace Knx
return false; return false;
ENSURE_PAYLOAD(6); ENSURE_PAYLOAD(6);
signed32ToPayload(payload, payload_length, 0, (int64_t)value, 0xffffffff); signed32ToPayload(payload, 0, (int64_t)value, 0xffffffff);
break; break;
} }
@ -1839,13 +1747,13 @@ namespace Knx
return false; return false;
ENSURE_PAYLOAD(6); ENSURE_PAYLOAD(6);
unsigned8ToPayload(payload, payload_length, 4, (int64_t)value, 0xff); unsigned8ToPayload(payload, 4, (int64_t)value, 0xff);
break; break;
} }
case 2: case 2:
case 3: case 3:
bitToPayload(payload, payload_length, datatype.index + 44, value); bitToPayload(payload, datatype.index + 44, value);
break; break;
default: default:
@ -1899,14 +1807,14 @@ namespace Knx
((((uint64_t)payload[index + 6]) << 8) & 0x000000000000FF00) | ((((uint64_t)payload[index + 6]) << 8) & 0x000000000000FF00) |
(((uint64_t)payload[index + 7]) & 0x00000000000000FF); (((uint64_t)payload[index + 7]) & 0x00000000000000FF);
} }
double float16FromPayload(const uint8_t* payload, int index) float float16FromPayload(const uint8_t* payload, int index)
{ {
uint16_t mantissa = unsigned16FromPayload(payload, index) & 0x87FF; uint16_t mantissa = unsigned16FromPayload(payload, index) & 0x87FF;
if (mantissa & 0x8000) if (mantissa & 0x8000)
return ((~mantissa & 0x07FF) + 1.0) * -0.01 * (1 << ((payload[index] >> 3) & 0x0F)); return ((~mantissa & 0x07FF) + 1.0) * -0.01 * (1 << ((payload[index] >> 3) & 0x0F));
return mantissa * 0.01 * (1 << ((payload[index] >> 3) & 0x0F)); return mantissa * 0.01f * (1 << ((payload[index] >> 3) & 0x0F));
} }
float float32FromPayload(const uint8_t* payload, int index) float float32FromPayload(const uint8_t* payload, int index)
{ {
@ -1947,34 +1855,34 @@ namespace Knx
return (uint8_t)((payload[index / 2] >> 4) & 0x0F); return (uint8_t)((payload[index / 2] >> 4) & 0x0F);
} }
void bitToPayload(uint8_t* payload, size_t payload_length, int index, bool value) void bitToPayload(uint8_t* payload, int index, bool value)
{ {
ENSURE_PAYLOAD(index / 8 + 1); ENSURE_PAYLOAD(index / 8 + 1);
payload[index / 8] = (payload[index / 8] & ~(1 << (7 - (index % 8)))) | (value ? (1 << (7 - (index % 8))) : 0); payload[index / 8] = (payload[index / 8] & ~(1 << (7 - (index % 8)))) | (value ? (1 << (7 - (index % 8))) : 0);
} }
void unsigned8ToPayload(uint8_t* payload, size_t payload_length, int index, uint8_t value, uint8_t mask) void unsigned8ToPayload(uint8_t* payload, int index, uint8_t value, uint8_t mask)
{ {
ENSURE_PAYLOAD(index + 1); ENSURE_PAYLOAD(index + 1);
payload[index] = (payload[index] & ~mask) | (value & mask); payload[index] = (payload[index] & ~mask) | (value & mask);
} }
void signed8ToPayload(uint8_t* payload, size_t payload_length, int index, int8_t value, uint8_t mask) void signed8ToPayload(uint8_t* payload, int index, int8_t value, uint8_t mask)
{ {
ENSURE_PAYLOAD(index + 1); ENSURE_PAYLOAD(index + 1);
payload[index] = (payload[index] & ~mask) | (value & mask); payload[index] = (payload[index] & ~mask) | (value & mask);
} }
void unsigned16ToPayload(uint8_t* payload, size_t payload_length, int index, uint16_t value, uint16_t mask) void unsigned16ToPayload(uint8_t* payload, int index, uint16_t value, uint16_t mask)
{ {
ENSURE_PAYLOAD(index + 2); ENSURE_PAYLOAD(index + 2);
payload[index] = (payload[index] & (~mask >> 8)) | ((value >> 8) & (mask >> 8)); payload[index] = (payload[index] & (~mask >> 8)) | ((value >> 8) & (mask >> 8));
payload[index + 1] = (payload[index + 1] & ~mask) | (value & mask); payload[index + 1] = (payload[index + 1] & ~mask) | (value & mask);
} }
void signed16ToPayload(uint8_t* payload, size_t payload_length, int index, int16_t value, uint16_t mask) void signed16ToPayload(uint8_t* payload, int index, int16_t value, uint16_t mask)
{ {
ENSURE_PAYLOAD(index + 2); ENSURE_PAYLOAD(index + 2);
payload[index] = (payload[index] & (~mask >> 8)) | ((value >> 8) & (mask >> 8)); payload[index] = (payload[index] & (~mask >> 8)) | ((value >> 8) & (mask >> 8));
payload[index + 1] = (payload[index + 1] & ~mask) | (value & mask); payload[index + 1] = (payload[index + 1] & ~mask) | (value & mask);
} }
void unsigned32ToPayload(uint8_t* payload, size_t payload_length, int index, uint32_t value, uint32_t mask) void unsigned32ToPayload(uint8_t* payload, int index, uint32_t value, uint32_t mask)
{ {
ENSURE_PAYLOAD(index + 4); ENSURE_PAYLOAD(index + 4);
payload[index] = (payload[index] & (~mask >> 24)) | ((value >> 24) & (mask >> 24)); payload[index] = (payload[index] & (~mask >> 24)) | ((value >> 24) & (mask >> 24));
@ -1982,7 +1890,7 @@ namespace Knx
payload[index + 2] = (payload[index + 2] & (~mask >> 8)) | ((value >> 8) & (mask >> 8)); payload[index + 2] = (payload[index + 2] & (~mask >> 8)) | ((value >> 8) & (mask >> 8));
payload[index + 3] = (payload[index + 3] & ~mask) | (value & mask); payload[index + 3] = (payload[index + 3] & ~mask) | (value & mask);
} }
void signed32ToPayload(uint8_t* payload, size_t payload_length, int index, int32_t value, uint32_t mask) void signed32ToPayload(uint8_t* payload, int index, int32_t value, uint32_t mask)
{ {
ENSURE_PAYLOAD(index + 4); ENSURE_PAYLOAD(index + 4);
payload[index] = (payload[index] & (~mask >> 24)) | ((value >> 24) & (mask >> 24)); payload[index] = (payload[index] & (~mask >> 24)) | ((value >> 24) & (mask >> 24));
@ -1991,7 +1899,7 @@ namespace Knx
payload[index + 3] = (payload[index + 3] & ~mask) | (value & mask); payload[index + 3] = (payload[index + 3] & ~mask) | (value & mask);
} }
void float16ToPayload(uint8_t* payload, size_t payload_length, int index, double value, uint16_t mask) void float16ToPayload(uint8_t* payload, int index, float value, uint16_t mask)
{ {
bool wasNegative = false; bool wasNegative = false;
@ -2021,10 +1929,10 @@ namespace Knx
// println(mantissa); // println(mantissa);
signed16ToPayload(payload, payload_length, index, mantissa, mask); signed16ToPayload(payload, index, mantissa, mask);
unsigned8ToPayload(payload, payload_length, index, exponent << 3, 0x78 & (mask >> 8)); unsigned8ToPayload(payload, index, exponent << 3, 0x78 & (mask >> 8));
} }
void float32ToPayload(uint8_t* payload, size_t payload_length, int index, double value, uint32_t mask) void float32ToPayload(uint8_t* payload, int index, float value, uint32_t mask)
{ {
union union
{ {
@ -2032,9 +1940,9 @@ namespace Knx
uint32_t i; uint32_t i;
} num; } num;
num.f = value; num.f = value;
unsigned32ToPayload(payload, payload_length, index, num.i, mask); unsigned32ToPayload(payload, index, num.i, mask);
} }
void signed64ToPayload(uint8_t* payload, size_t payload_length, int index, int64_t value, uint64_t mask) void signed64ToPayload(uint8_t* payload, int index, int64_t value, uint64_t mask)
{ {
ENSURE_PAYLOAD(index + 8); ENSURE_PAYLOAD(index + 8);
payload[index] = (payload[index] & (~mask >> 56)) | ((value >> 56) & (mask >> 56)); payload[index] = (payload[index] & (~mask >> 56)) | ((value >> 56) & (mask >> 56));
@ -2046,7 +1954,7 @@ namespace Knx
payload[index + 6] = (payload[index + 6] & (~mask >> 8)) | ((value >> 8) & (mask >> 8)); payload[index + 6] = (payload[index + 6] & (~mask >> 8)) | ((value >> 8) & (mask >> 8));
payload[index + 7] = (payload[index + 7] & ~mask) | (value & mask); payload[index + 7] = (payload[index + 7] & ~mask) | (value & mask);
} }
void bcdToPayload(uint8_t* payload, size_t payload_length, int index, uint8_t value) void bcdToPayload(uint8_t* payload, int index, uint8_t value)
{ {
ENSURE_PAYLOAD(index / 2 + 1); ENSURE_PAYLOAD(index / 2 + 1);

View File

@ -29,7 +29,7 @@
#pragma once #pragma once
#include "dpt.h" #include "dpt.h"
#include "knx_value.h" #include "../knx_value.h"
#include <cstdint> #include <cstdint>
@ -47,7 +47,6 @@ namespace Knx
int KNX_Encode_Value(const KNXValue& value, uint8_t* payload, size_t payload_length, const Dpt& datatype); int KNX_Encode_Value(const KNXValue& value, uint8_t* payload, size_t payload_length, const Dpt& datatype);
//KNX to internal //KNX to internal
int busValueToBinary(const uint8_t* payload, size_t payload_length, const Dpt& datatype, KNXValue& value);
int busValueToBinaryControl(const uint8_t* payload, size_t payload_length, const Dpt& datatype, KNXValue& value); int busValueToBinaryControl(const uint8_t* payload, size_t payload_length, const Dpt& datatype, KNXValue& value);
int busValueToStepControl(const uint8_t* payload, size_t payload_length, const Dpt& datatype, KNXValue& value); int busValueToStepControl(const uint8_t* payload, size_t payload_length, const Dpt& datatype, KNXValue& value);
int busValueToCharacter(const uint8_t* payload, size_t payload_length, const Dpt& datatype, KNXValue& value); int busValueToCharacter(const uint8_t* payload, size_t payload_length, const Dpt& datatype, KNXValue& value);
@ -58,7 +57,6 @@ namespace Knx
int busValueToTimePeriod(const uint8_t* payload, size_t payload_length, const Dpt& datatype, KNXValue& value); int busValueToTimePeriod(const uint8_t* payload, size_t payload_length, const Dpt& datatype, KNXValue& value);
int busValueToSigned16(const uint8_t* payload, size_t payload_length, const Dpt& datatype, KNXValue& value); int busValueToSigned16(const uint8_t* payload, size_t payload_length, const Dpt& datatype, KNXValue& value);
int busValueToTimeDelta(const uint8_t* payload, size_t payload_length, const Dpt& datatype, KNXValue& value); int busValueToTimeDelta(const uint8_t* payload, size_t payload_length, const Dpt& datatype, KNXValue& value);
int busValueToFloat16(const uint8_t* payload, size_t payload_length, const Dpt& datatype, KNXValue& value);
int busValueToTime(const uint8_t* payload, size_t payload_length, const Dpt& datatype, KNXValue& value); int busValueToTime(const uint8_t* payload, size_t payload_length, const Dpt& datatype, KNXValue& value);
int busValueToDate(const uint8_t* payload, size_t payload_length, const Dpt& datatype, KNXValue& value); int busValueToDate(const uint8_t* payload, size_t payload_length, const Dpt& datatype, KNXValue& value);
int busValueToUnsigned32(const uint8_t* payload, size_t payload_length, const Dpt& datatype, KNXValue& value); int busValueToUnsigned32(const uint8_t* payload, size_t payload_length, const Dpt& datatype, KNXValue& value);
@ -86,7 +84,6 @@ namespace Knx
int busValueToActiveEnergy(const uint8_t* payload, size_t payload_length, const Dpt& datatype, KNXValue& value); int busValueToActiveEnergy(const uint8_t* payload, size_t payload_length, const Dpt& datatype, KNXValue& value);
//Internal to KNX //Internal to KNX
int valueToBusValueBinary(const KNXValue& value, uint8_t* payload, size_t payload_length, const Dpt& datatype);
int valueToBusValueBinaryControl(const KNXValue& value, uint8_t* payload, size_t payload_length, const Dpt& datatype); int valueToBusValueBinaryControl(const KNXValue& value, uint8_t* payload, size_t payload_length, const Dpt& datatype);
int valueToBusValueStepControl(const KNXValue& value, uint8_t* payload, size_t payload_length, const Dpt& datatype); int valueToBusValueStepControl(const KNXValue& value, uint8_t* payload, size_t payload_length, const Dpt& datatype);
int valueToBusValueCharacter(const KNXValue& value, uint8_t* payload, size_t payload_length, const Dpt& datatype); int valueToBusValueCharacter(const KNXValue& value, uint8_t* payload, size_t payload_length, const Dpt& datatype);
@ -97,7 +94,6 @@ namespace Knx
int valueToBusValueTimePeriod(const KNXValue& value, uint8_t* payload, size_t payload_length, const Dpt& datatype); int valueToBusValueTimePeriod(const KNXValue& value, uint8_t* payload, size_t payload_length, const Dpt& datatype);
int valueToBusValueSigned16(const KNXValue& value, uint8_t* payload, size_t payload_length, const Dpt& datatype); int valueToBusValueSigned16(const KNXValue& value, uint8_t* payload, size_t payload_length, const Dpt& datatype);
int valueToBusValueTimeDelta(const KNXValue& value, uint8_t* payload, size_t payload_length, const Dpt& datatype); int valueToBusValueTimeDelta(const KNXValue& value, uint8_t* payload, size_t payload_length, const Dpt& datatype);
int valueToBusValueFloat16(const KNXValue& value, uint8_t* payload, size_t payload_length, const Dpt& datatype);
int valueToBusValueTime(const KNXValue& value, uint8_t* payload, size_t payload_length, const Dpt& datatype); int valueToBusValueTime(const KNXValue& value, uint8_t* payload, size_t payload_length, const Dpt& datatype);
int valueToBusValueDate(const KNXValue& value, uint8_t* payload, size_t payload_length, const Dpt& datatype); int valueToBusValueDate(const KNXValue& value, uint8_t* payload, size_t payload_length, const Dpt& datatype);
int valueToBusValueUnsigned32(const KNXValue& value, uint8_t* payload, size_t payload_length, const Dpt& datatype); int valueToBusValueUnsigned32(const KNXValue& value, uint8_t* payload, size_t payload_length, const Dpt& datatype);
@ -133,21 +129,21 @@ namespace Knx
uint32_t unsigned32FromPayload(const uint8_t* payload, int index); uint32_t unsigned32FromPayload(const uint8_t* payload, int index);
int32_t signed32FromPayload(const uint8_t* payload, int index); int32_t signed32FromPayload(const uint8_t* payload, int index);
uint64_t unsigned64FromPayload(const uint8_t* payload, int index); uint64_t unsigned64FromPayload(const uint8_t* payload, int index);
double float16FromPayload(const uint8_t* payload, int index); float float16FromPayload(const uint8_t* payload, int index);
float float32FromPayload(const uint8_t* payload, int index); float float32FromPayload(const uint8_t* payload, int index);
double float64FromPayload(const uint8_t* payload, int index); double float64FromPayload(const uint8_t* payload, int index);
int64_t signed64FromPayload(const uint8_t* payload, int index); int64_t signed64FromPayload(const uint8_t* payload, int index);
uint8_t bcdFromPayload(const uint8_t* payload, int index); uint8_t bcdFromPayload(const uint8_t* payload, int index);
void bitToPayload(uint8_t* payload, size_t payload_length, int index, bool value); void bitToPayload(uint8_t* payload, int index, bool value);
void unsigned8ToPayload(uint8_t* payload, size_t payload_length, int index, uint8_t value, uint8_t mask); //mask 0xFF void unsigned8ToPayload(uint8_t* payload, int index, uint8_t value, uint8_t mask); //mask 0xFF
void signed8ToPayload(uint8_t* payload, size_t payload_length, int index, int8_t value, uint8_t mask); //mask 0xFF void signed8ToPayload(uint8_t* payload, int index, int8_t value, uint8_t mask); //mask 0xFF
void unsigned16ToPayload(uint8_t* payload, size_t payload_length, int index, uint16_t value, uint16_t mask); //mask 0xFFFF void unsigned16ToPayload(uint8_t* payload, int index, uint16_t value, uint16_t mask); //mask 0xFFFF
void signed16ToPayload(uint8_t* payload, size_t payload_length, int index, int16_t value, uint16_t mask); //mask 0xFFFF void signed16ToPayload(uint8_t* payload, int index, int16_t value, uint16_t mask); //mask 0xFFFF
void unsigned32ToPayload(uint8_t* payload, size_t payload_length, int index, uint32_t value, uint32_t mask); //mask = 0xFFFFFFFF void unsigned32ToPayload(uint8_t* payload, int index, uint32_t value, uint32_t mask); //mask = 0xFFFFFFFF
void signed32ToPayload(uint8_t* payload, size_t payload_length, int index, int32_t value, uint32_t mask); //mask = 0xFFFFFFFF void signed32ToPayload(uint8_t* payload, int index, int32_t value, uint32_t mask); //mask = 0xFFFFFFFF
void float16ToPayload(uint8_t* payload, size_t payload_length, int index, double value, uint16_t mask); //mask = 0xFFFF void float16ToPayload(uint8_t* payload, int index, float value, uint16_t mask); //mask = 0xFFFF
void float32ToPayload(uint8_t* payload, size_t payload_length, int index, double value, uint32_t mask); //mask = 0xFFFFFFFF void float32ToPayload(uint8_t* payload, int index, float value, uint32_t mask); //mask = 0xFFFFFFFF
void signed64ToPayload(uint8_t* payload, size_t payload_length, int index, int64_t value, uint64_t mask); //mask = UINT64_C(0xFFFFFFFFFFFFFFFF) void signed64ToPayload(uint8_t* payload, int index, int64_t value, uint64_t mask); //mask = UINT64_C(0xFFFFFFFFFFFFFFFF)
void bcdToPayload(uint8_t* payload, size_t payload_length, int index, uint8_t value); void bcdToPayload(uint8_t* payload, int index, uint8_t value);
} }

View File

@ -0,0 +1,4 @@
#pragma once
#include "dpt1.h"
#include "dpt9.h"

View File

@ -1,6 +1,5 @@
#include "group_object.h" #include "group_object.h"
#include "datapoint_types.h"
#include "../interface_object/group_object_table_object.h" #include "../interface_object/group_object_table_object.h"
#include "../util/logger.h" #include "../util/logger.h"
#include "../bits.h" #include "../bits.h"
@ -101,6 +100,11 @@ namespace Knx
return _asap; return _asap;
} }
Go_SizeCode GroupObject::sizeCode() const
{
return (Go_SizeCode)lowByte(ntohs(_table->_tableData[_asap]));
}
size_t GroupObject::goSize() size_t GroupObject::goSize()
{ {
size_t size = sizeInTelegram(); size_t size = sizeInTelegram();
@ -220,105 +224,6 @@ namespace Knx
_updateHandlerStatic(go); _updateHandlerStatic(go);
} }
void GroupObject::value(const KNXValue& value, const Dpt& type)
{
valueNoSend(value, type);
objectWritten();
}
KNXValue GroupObject::value(const Dpt& type)
{
KNXValue value = "";
KNX_Decode_Value(_data, _dataLength, type, value);
return value;
}
bool GroupObject::tryValue(KNXValue& value, const Dpt& type)
{
return KNX_Decode_Value(_data, _dataLength, type, value);
}
#ifndef SMALL_GROUPOBJECT
void GroupObject::dataPointType(Dpt value)
{
_datapointType = value;
}
Dpt GroupObject::dataPointType()
{
return _datapointType;
}
bool GroupObject::tryValue(KNXValue& value)
{
return tryValue(value, _datapointType);
}
void GroupObject::value(const KNXValue& value)
{
this->value(value, _datapointType);
}
KNXValue GroupObject::value()
{
return value(_datapointType);
}
void GroupObject::valueNoSend(const KNXValue& value)
{
valueNoSend(value, _datapointType);
}
#endif
void GroupObject::valueNoSend(const KNXValue& value, const Dpt& type)
{
if (_uninitialized)
commFlag(Ok);
KNX_Encode_Value(value, _data, _dataLength, type);
}
bool GroupObject::valueNoSendCompare(const KNXValue& value, const Dpt& type)
{
if (_uninitialized)
{
// always set first value
this->valueNoSend(value, type);
return true;
}
else
{
// convert new value to given dtp
uint8_t newData[_dataLength];
memset(newData, 0, _dataLength);
KNX_Encode_Value(value, newData, _dataLength, type);
// check for change in converted value / update value on change only
const bool dataChanged = memcmp(_data, newData, _dataLength);
if (dataChanged)
memcpy(_data, newData, _dataLength);
return dataChanged;
}
}
bool GroupObject::valueCompare(const KNXValue& value, const Dpt& type)
{
if (valueNoSendCompare(value, type))
{
objectWritten();
return true;
}
return false;
}
bool operator==(const GroupObject& lhs, const GroupObject& rhs) bool operator==(const GroupObject& lhs, const GroupObject& rhs)
{ {
return lhs.asap() == rhs.asap(); return lhs.asap() == rhs.asap();

View File

@ -1,7 +1,6 @@
#pragma once #pragma once
#include "../knx_types.h" #include "../knx_types.h"
#include "dptconvert.h"
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
@ -38,6 +37,266 @@ namespace Knx
Uninitialized = 6 //!< uninitialized Group Object, its value is not valid Uninitialized = 6 //!< uninitialized Group Object, its value is not valid
}; };
enum Go_SizeCode
{
Go_1_Bit = 0,
Go_2_Bit = 1,
Go_3_Bit = 2,
Go_4_Bit = 3,
Go_5_Bit = 4,
Go_6_Bit = 5,
Go_7_Bit = 6,
Go_1_Octet = 7,
Go_2_Octets = 8,
Go_3_Octets = 9,
Go_4_Octets = 10,
Go_6_Octets = 11,
Go_8_Octets = 12,
Go_10_Octets = 13,
Go_14_Octets = 14,
Go_5_Octets = 15,
Go_7_Octets = 16,
Go_9_Octets = 17,
Go_11_Octets = 18,
Go_12_Octets = 19,
Go_13_Octets = 20,
Go_15_Octets = 21,
Go_16_Octets = 22,
Go_17_Octets = 23,
Go_18_Octets = 24,
Go_19_Octets = 25,
Go_20_Octets = 26,
Go_21_Octets = 27,
Go_22_Octets = 28,
Go_23_Octets = 29,
Go_24_Octets = 30,
Go_25_Octets = 31,
Go_26_Octets = 32,
Go_27_Octets = 33,
Go_28_Octets = 34,
Go_29_Octets = 35,
Go_30_Octets = 36,
Go_31_Octets = 37,
Go_32_Octets = 38,
Go_33_Octets = 39,
Go_34_Octets = 40,
Go_35_Octets = 41,
Go_36_Octets = 42,
Go_37_Octets = 43,
Go_38_Octets = 44,
Go_39_Octets = 45,
Go_40_Octets = 46,
Go_41_Octets = 47,
Go_42_Octets = 48,
Go_43_Octets = 49,
Go_44_Octets = 50,
Go_45_Octets = 51,
Go_46_Octets = 52,
Go_47_Octets = 53,
Go_48_Octets = 54,
Go_49_Octets = 55,
Go_50_Octets = 56,
Go_51_Octets = 57,
Go_52_Octets = 58,
Go_53_Octets = 59,
Go_54_Octets = 60,
Go_55_Octets = 61,
Go_56_Octets = 62,
Go_57_Octets = 63,
Go_58_Octets = 64,
Go_59_Octets = 65,
Go_60_Octets = 66,
Go_61_Octets = 67,
Go_62_Octets = 68,
Go_63_Octets = 69,
Go_64_Octets = 70,
Go_65_Octets = 71,
Go_66_Octets = 72,
Go_67_Octets = 73,
Go_68_Octets = 74,
Go_69_Octets = 75,
Go_70_Octets = 76,
Go_71_Octets = 77,
Go_72_Octets = 78,
Go_73_Octets = 79,
Go_74_Octets = 80,
Go_75_Octets = 81,
Go_76_Octets = 82,
Go_77_Octets = 83,
Go_78_Octets = 84,
Go_79_Octets = 85,
Go_80_Octets = 86,
Go_81_Octets = 87,
Go_82_Octets = 88,
Go_83_Octets = 89,
Go_84_Octets = 90,
Go_85_Octets = 91,
Go_86_Octets = 92,
Go_87_Octets = 93,
Go_88_Octets = 94,
Go_89_Octets = 95,
Go_90_Octets = 96,
Go_91_Octets = 97,
Go_92_Octets = 98,
Go_93_Octets = 99,
Go_94_Octets = 100,
Go_95_Octets = 101,
Go_96_Octets = 102,
Go_97_Octets = 103,
Go_98_Octets = 104,
Go_99_Octets = 105,
Go_100_Octets = 106,
Go_101_Octets = 107,
Go_102_Octets = 108,
Go_103_Octets = 109,
Go_104_Octets = 110,
Go_105_Octets = 111,
Go_106_Octets = 112,
Go_107_Octets = 113,
Go_108_Octets = 114,
Go_109_Octets = 115,
Go_110_Octets = 116,
Go_111_Octets = 117,
Go_112_Octets = 118,
Go_113_Octets = 119,
Go_114_Octets = 120,
Go_115_Octets = 121,
Go_116_Octets = 122,
Go_117_Octets = 123,
Go_118_Octets = 124,
Go_119_Octets = 125,
Go_120_Octets = 126,
Go_121_Octets = 127,
Go_122_Octets = 128,
Go_123_Octets = 129,
Go_124_Octets = 130,
Go_125_Octets = 131,
Go_126_Octets = 132,
Go_127_Octets = 133,
Go_128_Octets = 134,
Go_129_Octets = 135,
Go_130_Octets = 136,
Go_131_Octets = 137,
Go_132_Octets = 138,
Go_133_Octets = 139,
Go_134_Octets = 140,
Go_135_Octets = 141,
Go_136_Octets = 142,
Go_137_Octets = 143,
Go_138_Octets = 144,
Go_139_Octets = 145,
Go_140_Octets = 146,
Go_141_Octets = 147,
Go_142_Octets = 148,
Go_143_Octets = 149,
Go_144_Octets = 150,
Go_145_Octets = 151,
Go_146_Octets = 152,
Go_147_Octets = 153,
Go_148_Octets = 154,
Go_149_Octets = 155,
Go_150_Octets = 156,
Go_151_Octets = 157,
Go_152_Octets = 158,
Go_153_Octets = 159,
Go_154_Octets = 160,
Go_155_Octets = 161,
Go_156_Octets = 162,
Go_157_Octets = 163,
Go_158_Octets = 164,
Go_159_Octets = 165,
Go_160_Octets = 166,
Go_161_Octets = 167,
Go_162_Octets = 168,
Go_163_Octets = 169,
Go_164_Octets = 170,
Go_165_Octets = 171,
Go_166_Octets = 172,
Go_167_Octets = 173,
Go_168_Octets = 174,
Go_169_Octets = 175,
Go_170_Octets = 176,
Go_171_Octets = 177,
Go_172_Octets = 178,
Go_173_Octets = 179,
Go_174_Octets = 180,
Go_175_Octets = 181,
Go_176_Octets = 182,
Go_177_Octets = 183,
Go_178_Octets = 184,
Go_179_Octets = 185,
Go_180_Octets = 186,
Go_181_Octets = 187,
Go_182_Octets = 188,
Go_183_Octets = 189,
Go_184_Octets = 190,
Go_185_Octets = 191,
Go_186_Octets = 192,
Go_187_Octets = 193,
Go_188_Octets = 194,
Go_189_Octets = 195,
Go_190_Octets = 196,
Go_191_Octets = 197,
Go_192_Octets = 198,
Go_193_Octets = 199,
Go_194_Octets = 200,
Go_195_Octets = 201,
Go_196_Octets = 202,
Go_197_Octets = 203,
Go_198_Octets = 204,
Go_199_Octets = 205,
Go_200_Octets = 206,
Go_201_Octets = 207,
Go_202_Octets = 208,
Go_203_Octets = 209,
Go_204_Octets = 210,
Go_205_Octets = 211,
Go_206_Octets = 212,
Go_207_Octets = 213,
Go_208_Octets = 214,
Go_209_Octets = 215,
Go_210_Octets = 216,
Go_211_Octets = 217,
Go_212_Octets = 218,
Go_213_Octets = 219,
Go_214_Octets = 220,
Go_215_Octets = 221,
Go_216_Octets = 222,
Go_217_Octets = 223,
Go_218_Octets = 224,
Go_219_Octets = 225,
Go_220_Octets = 226,
Go_221_Octets = 227,
Go_222_Octets = 228,
Go_223_Octets = 229,
Go_224_Octets = 230,
Go_225_Octets = 231,
Go_226_Octets = 232,
Go_227_Octets = 233,
Go_228_Octets = 234,
Go_229_Octets = 235,
Go_230_Octets = 236,
Go_231_Octets = 237,
Go_232_Octets = 238,
Go_233_Octets = 239,
Go_234_Octets = 240,
Go_235_Octets = 241,
Go_236_Octets = 242,
Go_237_Octets = 243,
Go_238_Octets = 244,
Go_239_Octets = 245,
Go_240_Octets = 246,
Go_241_Octets = 247,
Go_242_Octets = 248,
Go_243_Octets = 249,
Go_244_Octets = 250,
Go_245_Octets = 251,
Go_246_Octets = 252,
Go_247_Octets = 253,
Go_248_Octets = 254,
Go_252_Octets = 255
};
/** /**
* This class represents a single group object. In german they are called "Kommunikationsobjekt" or "KO". * This class represents a single group object. In german they are called "Kommunikationsobjekt" or "KO".
*/ */
@ -140,18 +399,22 @@ namespace Knx
uint16_t asap() const; uint16_t asap() const;
/** /**
* return the current value of the group object. * returns The size of the group object encoded as the size code. See knxspec 3.5.1 p. 178.
* @param type the datapoint type used for the conversion. If this doesn't fit to the group object the returned value is invalid.
*/ */
KNXValue value(const Dpt& type); Go_SizeCode sizeCode() const;
/**
* return the current value of the group object.
* If the DPT class doesn't fit to the group object size the returned value is invalid.
*/
template<class DPT> DPT value();
/** /**
* set the current value of the group object and changes the state of the group object to ::WriteRequest. * set the current value of the group object and changes the state of the group object to ::WriteRequest.
* @param value the value the group object is set to * @param value the value the group object is set to.
* @param type the datapoint type used for the conversion.
* *
* The parameters must fit the group object. Otherwise it will stay unchanged. * The parameters must fit the group object. Otherwise it will stay unchanged.
*/ */
void value(const KNXValue& value, const Dpt& type); template<class DPT> void value(const DPT& value);
/** /**
* Check if the value (after conversion to dpt) will differ from current value of the group object and changes the state of the group object to ::WriteRequest if different. * Check if the value (after conversion to dpt) will differ from current value of the group object and changes the state of the group object to ::WriteRequest if different.
@ -163,79 +426,37 @@ namespace Knx
* *
* @returns true if the value of the group object has changed * @returns true if the value of the group object has changed
*/ */
bool valueCompare(const KNXValue& value, const Dpt& type); template<class DPT> bool valueCompare(const DPT& value);
/** /**
* set the current value of the group object. * set the current value of the group object.
* @param value the value the group object is set to * @param value the value the group object is set to
* @param type the datapoint type used for the conversion.
* *
* The parameters must fit the group object. Otherwise it will stay unchanged. * The parameters must fit size of the group object. Otherwise it will stay unchanged.
*/ */
void valueNoSend(const KNXValue& value, const Dpt& type); template<class DPT> void valueNoSend(const DPT& value);
/** /**
* Check if the value (after conversion to dpt) will differ from current value of the group object and update if necessary. * Check if the value (after conversion to dpt) will differ from current value of the group object and update if necessary.
* Use this method only, when the value change is relevant, otherwise valueNoSend(const KNXValue&, const Dpt&) will do the same (without overhead for comparing) * Use this method only, when the value change is relevant, otherwise valueNoSend(...) will do the same (without overhead for comparing)
* @param value the value the group object is set to * @param value the value the group object is set to.
* @param type the datapoint type used for the conversion.
* *
* The parameters must fit the group object. Otherwise it will stay unchanged. * The parameters must fit the size of the group object. Otherwise it will stay unchanged.
* *
* @returns true if the value of the group object has changed * @returns true if the value of the group object has changed
*/ */
bool valueNoSendCompare(const KNXValue& value, const Dpt& type); template<class DPT> bool valueNoSendCompare(const DPT& value);
/** /**
* set the current value of the group object. * set the current value of the group object.
* @param value the value the group object is set to * @param value the value the group object is set to
* @param type the datapoint type used for the conversion.
* *
* The parameters must fit the group object. Otherwise it will stay unchanged. * The parameters must fit the group object. Otherwise it will stay unchanged.
* *
* @returns true if the value of the group object was changed successfully. * @returns true if the value of the group object was changed successfully.
*/ */
bool tryValue(KNXValue& value, const Dpt& type); template<class DPT> bool tryValue(const DPT& value);
#ifndef SMALL_GROUPOBJECT
/**
* return the current value of the group object. The datapoint type must be set with dataPointType(). Otherwise the returned
* value is invalid.
*/
KNXValue value();
/**
* set the current value of the group object and changes the state of the group object to ::WriteRequest.
* @param value the value the group object is set to
*
* The parameters must fit the group object and dhe datapoint type must be set with dataPointType(). Otherwise it will stay unchanged.
*/
void value(const KNXValue& value);
/**
* set the current value of the group object.
* @param value the value the group object is set to
*
* The parameters must fit the group object and dhe datapoint type must be set with dataPointType(). Otherwise it will stay unchanged.
*/
void valueNoSend(const KNXValue& value);
/**
* set the current value of the group object.
* @param value the value the group object is set to
*
* The parameters must fit the group object and dhe datapoint type must be set with dataPointType(). Otherwise it will stay unchanged.
*
* @returns true if the value of the group object was changed successfully.
*/
bool tryValue(KNXValue& value);
/**
* returns the currently configured datapoint type.
*/
Dpt dataPointType();
/**
* sets the datapoint type of the group object.
*/
void dataPointType(Dpt value);
#endif
/** /**
* Callback processing: register one global callback for all group object. * Callback processing: register one global callback for all group object.
* The registered callback will be called if any group object was changed from the bus. * The registered callback will be called if any group object was changed from the bus.
@ -257,10 +478,83 @@ namespace Knx
ComFlag _commFlag : 7; ComFlag _commFlag : 7;
uint8_t* _data = 0; uint8_t* _data = 0;
uint8_t _dataLength = 0; uint8_t _dataLength = 0;
#ifndef SMALL_GROUPOBJECT
Dpt _datapointType;
#endif
}; };
bool operator==(const GroupObject& lhs, const GroupObject& rhs); bool operator==(const GroupObject& lhs, const GroupObject& rhs);
template<class DPT> void GroupObject::value(const DPT& value)
{
valueNoSend(value);
objectWritten();
}
template<class DPT> DPT GroupObject::value()
{
DPT dpt;
if (dpt.size() != sizeCode())
return dpt;
dpt.decode(_data);
return dpt;
}
template<class DPT> bool GroupObject::tryValue(const DPT& value)
{
if (value.size() != sizeCode())
return false;
value.decode(_data);
return true;
}
template<class DPT> void GroupObject::valueNoSend(const DPT& value)
{
if (value.size() != sizeCode())
return;
if (_uninitialized)
commFlag(Ok);
value.encode(_data);
}
template<class DPT> bool GroupObject::valueNoSendCompare(const DPT& value)
{
if (value.size() != sizeCode())
return false;
if (_uninitialized)
{
// always set first value
this->valueNoSend(value);
return true;
}
else
{
// convert new value to given dtp
uint8_t newData[_dataLength];
memset(newData, 0, _dataLength);
value.encode(newData);
// check for change in converted value / update value on change only
const bool dataChanged = memcmp(_data, newData, _dataLength);
if (dataChanged)
memcpy(_data, newData, _dataLength);
return dataChanged;
}
}
template<class DPT> bool GroupObject::valueCompare(const DPT& value)
{
if (valueNoSendCompare(value))
{
objectWritten();
return true;
}
return false;
}
} }

View File

@ -1,6 +1,6 @@
#include "application_program_object.h" #include "application_program_object.h"
#include "../group_object/dptconvert.h" #include "../group_object/dpt/dptconvert.h"
#include "../util/logger.h" #include "../util/logger.h"
#include "../bits.h" #include "../bits.h"

View File

@ -33,8 +33,8 @@ namespace Knx
{ {
public: public:
enum LogType { Info, Warning, Error, Critical, Exception, Disabled}; enum LogType { Info, Warning, Error, Critical, Exception, Disabled};
static Logger& logger(const loggername_t name); static Logger& logger(loggername_t name);
static void logLevel(const loggername_t name, LogType level); static void logLevel(loggername_t name, LogType level);
void info(const char* message, IPrintable& object) void info(const char* message, IPrintable& object)
{ {
if (!log(LogType::Info)) if (!log(LogType::Info))