knx
ETS configurable knx-stack
tp_frame.h
Go to the documentation of this file.
1 #pragma once
2 #pragma GCC optimize("O3")
3 
4 #include "cemi_frame.h"
5 #include <cstring>
6 #include <stdint.h>
7 #include <string>
8 
9 // Means that the frame is invalid
10 #define TP_FRAME_FLAG_INVALID 0b10000000
11 
12 // Means that the frame is an extended frame
13 #define TP_FRAME_FLAG_EXTENDED 0b01000000
14 
15 // Means that the frame has been repeated
16 #define TP_FRAME_FLAG_REPEATED 0b00100000
17 
18 // Means that the frame comes from the device itself
19 #define TP_FRAME_FLAG_ECHO 0b00010000
20 
21 // Means that the frame is processed by this device
22 #define TP_FRAME_FLAG_ADDRESSED 0b00001000
23 
24 // Means that the frame has been acked with BUSY
25 #define TP_FRAME_FLAG_ACK_BUSY 0b00000100
26 
27 // Means that the frame has been acked with NACK
28 #define TP_FRAME_FLAG_ACK_NACK 0b00000010
29 
30 // Means that the frame has been acked
31 #define TP_FRAME_FLAG_ACK 0b00000001
32 
33 class TpFrame
34 {
35  private:
36  uint8_t* _data;
37  uint16_t _size;
38  uint16_t _maxSize;
39  uint8_t _flags = 0;
40 
41  /*
42  * Sets a few flags based on the control byte
43  */
44  inline void presetFlags()
45  {
46  if (isExtended())
47  addFlags(TP_FRAME_FLAG_EXTENDED);
48 
49  if (isRepeated())
50  addFlags(TP_FRAME_FLAG_REPEATED);
51  }
52 
53  public:
54  /*
55  * Convert a CemiFrame into a TpFrame
56  */
57  TpFrame(CemiFrame& cemiFrame)
58  {
59  _size = cemiFrame.telegramLengthtTP();
60  _maxSize = cemiFrame.telegramLengthtTP();
61  _data = (uint8_t*)malloc(cemiFrame.telegramLengthtTP());
62  cemiFrame.fillTelegramTP(_data);
63  presetFlags();
64  }
65 
66  /*
67  * Create a TpFrame with a reserved space.
68  * Used for incoming parsing.
69  */
70  TpFrame(uint16_t maxSize = 263)
71  : _maxSize(maxSize)
72  {
73  _data = (uint8_t*)malloc(_maxSize);
74  _size = 0;
75  }
76 
77  /*
78  * Free the data area
79  */
81  {
82  free(_data);
83  }
84 
85  /*
86  * Add a byte at end.
87  * Used for incoming parsing.
88  */
89  inline void addByte(uint8_t byte)
90  {
91  if (!isFull())
92  {
93  _data[_size] = byte;
94  _size++;
95  }
96 
97  // Read meta data for flags
98  if (_size == 1)
99  presetFlags();
100  }
101 
102  /*
103  * Current frame size. This may differ from the actual size as long as the frame is not complete.
104  */
105  inline uint16_t size()
106  {
107  return _size;
108  }
109 
110  /*
111  * Returns the assigned flags
112  */
113  inline uint16_t flags()
114  {
115  return _flags;
116  }
117 
118  /*
119  * Adds one or more flags
120  */
121  inline void addFlags(uint8_t flags)
122  {
123  _flags |= flags;
124  }
125 
126  /*
127  * Returns a pointer to the data
128  */
129  inline uint8_t* data()
130  {
131  return _data;
132  }
133 
134  /*
135  * Returns the byte corresponding to the specified position
136  */
137  inline uint8_t data(uint16_t pos)
138  {
139  return _data[pos];
140  }
141 
142  /*
143  * Resets the internal values to refill the frame.
144  */
145  inline void reset()
146  {
147  _size = 0;
148  _flags = 0;
149  // It is important to fill the _data with zeros so that the length is 0 as long as the value has not yet been read in.
150  memset(_data, 0x0, _maxSize);
151  }
152 
153  /*
154  * Checks whether the frame has been imported completely
155  */
156  inline bool isFull()
157  {
158  return _size >= (_size >= 7 ? fullSize() : _maxSize);
159  }
160 
161  /*
162  * Returns is the frame exteneded or not
163  */
164  inline bool isExtended()
165  {
166  return (_data[0] & 0xD3) == 0x10;
167  }
168 
169  /*
170  * Returns the source
171  * Assumes that enough data has been imported.
172  */
173  inline uint16_t source()
174  {
175  return isExtended() ? (_data[2] << 8) + _data[3] : (_data[1] << 8) + _data[2];
176  }
177 
178  inline std::string humanSource()
179  {
180  uint16_t value = source();
181  char buffer[10];
182  sprintf(buffer, "%02i.%02i.%03i", (value >> 12 & 0b1111), (value >> 8 & 0b1111), (value & 0b11111111));
183  return buffer;
184  }
185 
186  inline std::string humanDestination()
187  {
188  uint16_t value = destination();
189  char buffer[10];
190 
191  if (isGroupAddress())
192  sprintf(buffer, "%02i/%02i/%03i", (value >> 11 & 0b1111), (value >> 8 & 0b111), (value & 0b11111111));
193  else
194  sprintf(buffer, "%02i.%02i.%03i", (value >> 12 & 0b1111), (value >> 8 & 0b1111), (value & 0b11111111));
195 
196  return buffer;
197  }
198 
199  /*
200  * Returns the destination
201  * Assumes that enough data has been imported.
202  */
203  inline uint16_t destination()
204  {
205  return isExtended() ? (_data[4] << 8) + _data[5] : (_data[3] << 8) + _data[4];
206  }
207 
208  /*
209  * Returns the payload size (with checksum)
210  * Assumes that enough data has been imported.
211  */
212  inline uint8_t payloadSize()
213  {
214  return isExtended() ? _data[6] : _data[5] & 0b1111;
215  }
216 
217  /*
218  * Returns the header size
219  */
220  inline uint8_t headerSize()
221  {
222  return isExtended() ? 9 : 8;
223  }
224 
225  /*
226  * Returns the frame size based on header and payload size.
227  * Assumes that enough data has been imported.
228  */
229  inline uint16_t fullSize()
230  {
231  return headerSize() + payloadSize();
232  }
233 
234  /*
235  * Returns if the destination is a group address
236  * Assumes that enough data has been imported.
237  */
238  inline bool isGroupAddress()
239  {
240  return isExtended() ? (_data[1] >> 7) & 0b1 : (_data[5] >> 7) & 0b1;
241  }
242 
243  /*
244  * Calculates the size of a CemiFrame. A CemiFrame has 2 additional bytes at the beginning.
245  * An additional byte is added to a standard frame, as this still has to be converted into an extendend.
246  */
247  uint16_t cemiSize()
248  {
249  return fullSize() + (isExtended() ? 2 : 3) - 1; // -1 without CRC
250  }
251 
256  uint8_t* cemiData()
257  {
258  uint8_t* cemiBuffer = (uint8_t*)malloc(cemiSize());
259 
260  // Das CEMI erwartet die Daten im Extended format inkl. zwei zusätzlicher Bytes am Anfang.
261  cemiBuffer[0] = 0x29;
262  cemiBuffer[1] = 0x0;
263  cemiBuffer[2] = _data[0];
264 
265  if (isExtended())
266  {
267  memcpy(cemiBuffer + 2, _data, fullSize() - 1); // -1 without CRC
268  }
269  else
270  {
271  cemiBuffer[3] = _data[5] & 0xF0;
272  memcpy(cemiBuffer + 4, _data + 1, 4);
273  cemiBuffer[8] = _data[5] & 0x0F;
274  memcpy(cemiBuffer + 9, _data + 6, cemiBuffer[8] + 2 - 1); // -1 without CRC
275  }
276 
277  return cemiBuffer;
278  }
279 
280  /*
281  * Checks whether the frame is complete and valid.
282  */
283  inline bool isValid()
284  {
285  if (!isComplete())
286  return false;
287 
288  uint8_t sum = 0;
289  const uint16_t s = fullSize() - 1;
290 
291  for (uint16_t i = 0; i < s; i++)
292  sum ^= _data[i];
293 
294  return _data[s] == (uint8_t)~sum;
295  }
296 
297  /*
298  * Checks whether the frame is long enough to match the length specified in the frame
299  */
300  inline bool isComplete()
301  {
302  return _size == fullSize();
303  }
304 
305  inline bool isRepeated()
306  {
307  return !(_data[0] & 0b100000);
308  }
309 };
void fillTelegramTP(uint8_t *data)
Definition: cemi_frame.cpp:149
uint16_t telegramLengthtTP() const
Definition: cemi_frame.cpp:141
bool isGroupAddress()
Definition: tp_frame.h:238
std::string humanDestination()
Definition: tp_frame.h:186
TpFrame(CemiFrame &cemiFrame)
Definition: tp_frame.h:57
uint16_t source()
Definition: tp_frame.h:173
bool isFull()
Definition: tp_frame.h:156
uint8_t * cemiData()
Creates a buffer and converts the TpFrame into a CemiFrame.
Definition: tp_frame.h:256
bool isRepeated()
Definition: tp_frame.h:305
uint16_t cemiSize()
Definition: tp_frame.h:247
uint8_t payloadSize()
Definition: tp_frame.h:212
uint16_t flags()
Definition: tp_frame.h:113
void addByte(uint8_t byte)
Definition: tp_frame.h:89
uint8_t * data()
Definition: tp_frame.h:129
std::string humanSource()
Definition: tp_frame.h:178
bool isValid()
Definition: tp_frame.h:283
TpFrame(uint16_t maxSize=263)
Definition: tp_frame.h:70
~TpFrame()
Definition: tp_frame.h:80
uint8_t headerSize()
Definition: tp_frame.h:220
uint8_t data(uint16_t pos)
Definition: tp_frame.h:137
bool isComplete()
Definition: tp_frame.h:300
void addFlags(uint8_t flags)
Definition: tp_frame.h:121
uint16_t destination()
Definition: tp_frame.h:203
void reset()
Definition: tp_frame.h:145
uint16_t fullSize()
Definition: tp_frame.h:229
uint16_t size()
Definition: tp_frame.h:105
bool isExtended()
Definition: tp_frame.h:164