knx
ETS configurable knx-stack
bau_systemB.cpp
Go to the documentation of this file.
1 #include "bau_systemB.h"
2 #include "bits.h"
3 #include <string.h>
4 #include <stdio.h>
5 
7 {
12 };
13 
14 static constexpr auto kFunctionPropertyResultBufferMaxSize = 0xFF;
15 static constexpr auto kRestartProcessTime = 3;
16 
17 BauSystemB::BauSystemB(Platform& platform): _memory(platform, _deviceObj),
18  _appProgram(_memory),
19  _platform(platform)
20 {
22 }
23 
25 {
27 }
28 
30 {
32 }
33 
35 {
36  return _platform;
37 }
38 
40 {
41  return _appProgram;
42 }
43 
45 {
46  return _deviceObj;
47 }
48 
49 uint8_t BauSystemB::checkmasterResetValidity(EraseCode eraseCode, uint8_t channel)
50 {
51  static constexpr uint8_t successCode = 0x00; // Where does this come from? It is the code for "success".
52  static constexpr uint8_t invalidEraseCode = 0x02; // Where does this come from? It is the error code for "unspported erase code".
53 
54  switch (eraseCode)
55  {
57  {
58  println("Confirmed restart requested.");
59  return successCode;
60  }
61 
62  case EraseCode::ResetAP:
63  {
64  // TODO: increase download counter except for confirmed restart (PID_DOWNLOAD_COUNTER)
65  println("ResetAP requested. Not implemented yet.");
66  return successCode;
67  }
68 
69  case EraseCode::ResetIA:
70  {
71  // TODO: increase download counter except for confirmed restart (PID_DOWNLOAD_COUNTER)
72  println("ResetIA requested. Not implemented yet.");
73  return successCode;
74  }
75 
77  {
78  // TODO: increase download counter except for confirmed restart (PID_DOWNLOAD_COUNTER)
79  println("ResetLinks requested. Not implemented yet.");
80  return successCode;
81  }
82 
84  {
85  // TODO: increase download counter except for confirmed restart (PID_DOWNLOAD_COUNTER)
86  println("ResetParam requested. Not implemented yet.");
87  return successCode;
88  }
89 
91  {
92  // TODO: increase download counter except for confirmed restart (PID_DOWNLOAD_COUNTER)
93  println("Factory reset requested. type: with IA");
94  return successCode;
95  }
96 
98  {
99  // TODO: increase download counter except for confirmed restart (PID_DOWNLOAD_COUNTER)
100  println("Factory reset requested. type: without IA");
101  return successCode;
102  }
103 
104  default:
105  {
106  print("Unhandled erase code: ");
107  println(eraseCode, HEX);
108  return invalidEraseCode;
109  }
110  }
111 }
112 
113 void BauSystemB::deviceDescriptorReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl, uint8_t descriptorType)
114 {
115  if (descriptorType != 0)
116  descriptorType = 0x3f;
117 
118  uint8_t data[2];
120  applicationLayer().deviceDescriptorReadResponse(AckRequested, priority, hopType, asap, secCtrl, descriptorType, data);
121 }
122 void BauSystemB::memoryRouterWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl, uint8_t number,
123  uint16_t memoryAddress, uint8_t* data)
124 {
125  print("Writing memory at: ");
126  print(memoryAddress, HEX);
127  print(" length: ");
128  print(number);
129  print(" data: ");
130  printHex("=>", data, number);
131  _memory.writeMemory(memoryAddress, number, data);
132 
133  if (_deviceObj.verifyMode())
134  {
135  print("Sending Read indication");
136  memoryRouterReadIndication(priority, hopType, asap, secCtrl, number, memoryAddress, data);
137  }
138 }
139 
140 void BauSystemB::memoryRouterReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl, uint8_t number,
141  uint16_t memoryAddress, uint8_t* data)
142 {
143  applicationLayer().memoryRouterReadResponse(AckRequested, priority, hopType, asap, secCtrl, number, memoryAddress, data);
144 }
145 
146 void BauSystemB::memoryRoutingTableReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl, uint8_t number, uint16_t memoryAddress, uint8_t* data)
147 {
148  applicationLayer().memoryRoutingTableReadResponse(AckRequested, priority, hopType, asap, secCtrl, number, memoryAddress, data);
149 }
150 void BauSystemB::memoryRoutingTableReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl, uint8_t number, uint16_t memoryAddress)
151 {
152  memoryRoutingTableReadIndication(priority, hopType, asap, secCtrl, number, memoryAddress, _memory.toAbsolute(memoryAddress));
153 }
154 
155 void BauSystemB::memoryRoutingTableWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl, uint8_t number, uint16_t memoryAddress, uint8_t* data)
156 {
157  print("Writing memory at: ");
158  print(memoryAddress, HEX);
159  print(" length: ");
160  print(number);
161  print(" data: ");
162  printHex("=>", data, number);
163  _memory.writeMemory(memoryAddress, number, data);
164 
165  if (_deviceObj.verifyMode())
166  memoryRoutingTableReadIndication(priority, hopType, asap, secCtrl, number, memoryAddress, data);
167 }
168 
169 void BauSystemB::memoryWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl, uint8_t number,
170  uint16_t memoryAddress, uint8_t* data)
171 {
172  _memory.writeMemory(memoryAddress, number, data);
173 
174  if (_deviceObj.verifyMode())
175  memoryReadIndication(priority, hopType, asap, secCtrl, number, memoryAddress, data);
176 }
177 
178 void BauSystemB::memoryReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl, uint8_t number,
179  uint16_t memoryAddress, uint8_t* data)
180 {
181  applicationLayer().memoryReadResponse(AckRequested, priority, hopType, asap, secCtrl, number, memoryAddress, data);
182 }
183 
184 void BauSystemB::memoryReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl, uint8_t number,
185  uint16_t memoryAddress)
186 {
187  applicationLayer().memoryReadResponse(AckRequested, priority, hopType, asap, secCtrl, number, memoryAddress,
188  _memory.toAbsolute(memoryAddress));
189 }
190 
191 void BauSystemB::memoryExtWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl, uint8_t number, uint32_t memoryAddress, uint8_t* data)
192 {
193  _memory.writeMemory(memoryAddress, number, data);
194 
195  applicationLayer().memoryExtWriteResponse(AckRequested, priority, hopType, asap, secCtrl, ReturnCodes::Success, number, memoryAddress, _memory.toAbsolute(memoryAddress));
196 }
197 
198 void BauSystemB::memoryExtReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl, uint8_t number, uint32_t memoryAddress)
199 {
200  applicationLayer().memoryExtReadResponse(AckRequested, priority, hopType, asap, secCtrl, ReturnCodes::Success, number, memoryAddress, _memory.toAbsolute(memoryAddress));
201 }
202 
203 void BauSystemB::doMasterReset(EraseCode eraseCode, uint8_t channel)
204 {
205  _deviceObj.masterReset(eraseCode, channel);
206  _appProgram.masterReset(eraseCode, channel);
207 }
208 
209 void BauSystemB::restartRequestIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl, RestartType restartType, EraseCode eraseCode, uint8_t channel)
210 {
211  if (restartType == RestartType::BasicRestart)
212  {
213  println("Basic restart requested");
214 
215  if (_beforeRestart != 0)
216  _beforeRestart();
217  }
218  else if (restartType == RestartType::MasterReset)
219  {
220  uint8_t errorCode = checkmasterResetValidity(eraseCode, channel);
221  // We send the restart response now before actually applying the reset values
222  // Processing time is kRestartProcessTime (example 3 seconds) that we require for the applying the master reset with restart
223  applicationLayer().restartResponse(AckRequested, priority, hopType, secCtrl, errorCode, (errorCode == 0) ? kRestartProcessTime : 0);
224  doMasterReset(eraseCode, channel);
225  }
226  else
227  {
228  // Cannot happen as restartType is just one bit
229  println("Unhandled restart type.");
231  }
232 
233  // Flush the EEPROM before resetting
235  _platform.restart();
236 }
237 
238 void BauSystemB::authorizeIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl, uint32_t key)
239 {
240  applicationLayer().authorizeResponse(AckRequested, priority, hopType, asap, secCtrl, 0);
241 }
242 
243 void BauSystemB::userMemoryReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl, uint8_t number, uint32_t memoryAddress)
244 {
245  applicationLayer().userMemoryReadResponse(AckRequested, priority, hopType, asap, secCtrl, number, memoryAddress,
246  _memory.toAbsolute(memoryAddress));
247 }
248 
249 void BauSystemB::userMemoryWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl, uint8_t number, uint32_t memoryAddress, uint8_t* data)
250 {
251  _memory.writeMemory(memoryAddress, number, data);
252 
253  if (_deviceObj.verifyMode())
254  userMemoryReadIndication(priority, hopType, asap, secCtrl, number, memoryAddress);
255 }
256 
257 void BauSystemB::propertyDescriptionReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl, uint8_t objectIndex,
258  uint8_t propertyId, uint8_t propertyIndex)
259 {
260  uint8_t pid = propertyId;
261  bool writeEnable = false;
262  uint8_t type = 0;
263  uint16_t numberOfElements = 0;
264  uint8_t access = 0;
265  InterfaceObject* obj = getInterfaceObject(objectIndex);
266 
267  if (obj)
268  obj->readPropertyDescription(pid, propertyIndex, writeEnable, type, numberOfElements, access);
269 
270  applicationLayer().propertyDescriptionReadResponse(AckRequested, priority, hopType, asap, secCtrl, objectIndex, pid, propertyIndex,
271  writeEnable, type, numberOfElements, access);
272 }
273 
274 void BauSystemB::propertyExtDescriptionReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl,
275  uint16_t objectType, uint16_t objectInstance, uint16_t propertyId, uint8_t descriptionType, uint16_t propertyIndex)
276 {
277  uint8_t pid = propertyId;
278  uint8_t pidx = propertyIndex;
279 
280  if (propertyId > 0xFF || propertyIndex > 0xFF)
281  {
282  println("BauSystemB::propertyExtDescriptionReadIndication: propertyId or Idx > 256 are not supported");
283  return;
284  }
285 
286  if (descriptionType != 0)
287  {
288  println("BauSystemB::propertyExtDescriptionReadIndication: only descriptionType 0 supported");
289  return;
290  }
291 
292  bool writeEnable = false;
293  uint8_t type = 0;
294  uint16_t numberOfElements = 0;
295  uint8_t access = 0;
296  InterfaceObject* obj = getInterfaceObject((ObjectType)objectType, objectInstance);
297 
298  if (obj)
299  obj->readPropertyDescription(pid, pidx, writeEnable, type, numberOfElements, access);
300 
301  applicationLayer().propertyExtDescriptionReadResponse(AckRequested, priority, hopType, asap, secCtrl, objectType, objectInstance, propertyId, propertyIndex,
302  descriptionType, writeEnable, type, numberOfElements, access);
303 }
304 
305 void BauSystemB::propertyValueWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl, uint8_t objectIndex,
306  uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t* data, uint8_t length)
307 {
308  InterfaceObject* obj = getInterfaceObject(objectIndex);
309 
310  if (obj)
311  obj->writeProperty((PropertyID)propertyId, startIndex, data, numberOfElements);
312 
313  propertyValueReadIndication(priority, hopType, asap, secCtrl, objectIndex, propertyId, numberOfElements, startIndex);
314 }
315 
316 void BauSystemB::propertyValueExtWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl, ObjectType objectType, uint8_t objectInstance,
317  uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t* data, uint8_t length, bool confirmed)
318 {
319  uint8_t returnCode = ReturnCodes::Success;
320 
321  InterfaceObject* obj = getInterfaceObject(objectType, objectInstance);
322 
323  if (obj)
324  obj->writeProperty((PropertyID)propertyId, startIndex, data, numberOfElements);
325  else
326  returnCode = ReturnCodes::AddressVoid;
327 
328  if (confirmed)
329  {
330  applicationLayer().propertyValueExtWriteConResponse(AckRequested, priority, hopType, asap, secCtrl, objectType, objectInstance, propertyId, numberOfElements, startIndex, returnCode);
331  }
332 }
333 
334 void BauSystemB::propertyValueReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl, uint8_t objectIndex,
335  uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex)
336 {
337  uint8_t size = 0;
338  uint8_t elementCount = numberOfElements;
339 #ifdef LOG_KNX_PROP
340  print("propertyValueReadIndication: ObjIdx ");
341  print(objectIndex);
342  print(" propId ");
343  print(propertyId);
344  print(" num ");
345  print(numberOfElements);
346  print(" start ");
347  print(startIndex);
348 #endif
349 
350  InterfaceObject* obj = getInterfaceObject(objectIndex);
351 
352  if (obj)
353  {
354  uint8_t elementSize = obj->propertySize((PropertyID)propertyId);
355 
356  if (startIndex > 0)
357  size = elementSize * numberOfElements;
358  else
359  size = sizeof(uint16_t); // size of property array entry 0 which contains the current number of elements
360  }
361  else
362  elementCount = 0;
363 
364  uint8_t data[size];
365 
366  if (obj)
367  obj->readProperty((PropertyID)propertyId, startIndex, elementCount, data);
368 
369  if (elementCount == 0)
370  size = 0;
371 
372  applicationLayer().propertyValueReadResponse(AckRequested, priority, hopType, asap, secCtrl, objectIndex, propertyId, elementCount,
373  startIndex, data, size);
374 }
375 
376 void BauSystemB::propertyValueExtReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl, ObjectType objectType, uint8_t objectInstance,
377  uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex)
378 {
379  uint8_t size = 0;
380  uint8_t elementCount = numberOfElements;
381  InterfaceObject* obj = getInterfaceObject(objectType, objectInstance);
382 
383  if (obj)
384  {
385  uint8_t elementSize = obj->propertySize((PropertyID)propertyId);
386 
387  if (startIndex > 0)
388  size = elementSize * numberOfElements;
389  else
390  size = sizeof(uint16_t); // size of propert array entry 0 which is the size
391  }
392  else
393  elementCount = 0;
394 
395  uint8_t data[size];
396 
397  if (obj)
398  obj->readProperty((PropertyID)propertyId, startIndex, elementCount, data);
399 
400  if (elementCount == 0)
401  size = 0;
402 
403  applicationLayer().propertyValueExtReadResponse(AckRequested, priority, hopType, asap, secCtrl, objectType, objectInstance, propertyId, elementCount,
404  startIndex, data, size);
405 }
406 
407 void BauSystemB::functionPropertyCommandIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl, uint8_t objectIndex,
408  uint8_t propertyId, uint8_t* data, uint8_t length)
409 {
410  uint8_t resultData[kFunctionPropertyResultBufferMaxSize];
411  uint8_t resultLength = sizeof(resultData); // tell the callee the maximum size of the buffer
412 
413  bool handled = false;
414 
415  InterfaceObject* obj = getInterfaceObject(objectIndex);
416 
417  if (obj)
418  {
419  if (obj->property((PropertyID)propertyId)->Type() == PDT_FUNCTION)
420  {
421  obj->command((PropertyID)propertyId, data, length, resultData, resultLength);
422  handled = true;
423  }
424  else
425  {
426  if (_functionProperty != 0)
427  if (_functionProperty(objectIndex, propertyId, length, data, resultData, resultLength))
428  handled = true;
429  }
430  }
431  else
432  {
433  if (_functionProperty != 0)
434  if (_functionProperty(objectIndex, propertyId, length, data, resultData, resultLength))
435  handled = true;
436  }
437 
438  //only return a value it was handled by a property or function
439  if (handled)
440  applicationLayer().functionPropertyStateResponse(AckRequested, priority, hopType, asap, secCtrl, objectIndex, propertyId, resultData, resultLength);
441 }
442 
443 void BauSystemB::functionPropertyStateIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl, uint8_t objectIndex,
444  uint8_t propertyId, uint8_t* data, uint8_t length)
445 {
446  uint8_t resultData[kFunctionPropertyResultBufferMaxSize];
447  uint8_t resultLength = sizeof(resultData); // tell the callee the maximum size of the buffer
448 
449  bool handled = true;
450 
451  InterfaceObject* obj = getInterfaceObject(objectIndex);
452 
453  if (obj)
454  {
455  if (obj->property((PropertyID)propertyId)->Type() == PDT_FUNCTION)
456  {
457  obj->state((PropertyID)propertyId, data, length, resultData, resultLength);
458  handled = true;
459  }
460  else
461  {
462  if (_functionPropertyState != 0)
463  if (_functionPropertyState(objectIndex, propertyId, length, data, resultData, resultLength))
464  handled = true;
465  }
466  }
467  else
468  {
469  if (_functionPropertyState != 0)
470  if (_functionPropertyState(objectIndex, propertyId, length, data, resultData, resultLength))
471  handled = true;
472  }
473 
474  //only return a value it was handled by a property or function
475  if (handled)
476  applicationLayer().functionPropertyStateResponse(AckRequested, priority, hopType, asap, secCtrl, objectIndex, propertyId, resultData, resultLength);
477 }
478 
479 void BauSystemB::functionPropertyExtCommandIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl, ObjectType objectType, uint8_t objectInstance,
480  uint8_t propertyId, uint8_t* data, uint8_t length)
481 {
482  uint8_t resultData[kFunctionPropertyResultBufferMaxSize];
483  uint8_t resultLength = 1; // we always have to include the return code at least
484 
485  InterfaceObject* obj = getInterfaceObject(objectType, objectInstance);
486 
487  if (obj)
488  {
489  PropertyDataType propType = obj->property((PropertyID)propertyId)->Type();
490 
491  if (propType == PDT_FUNCTION)
492  {
493  // The first byte is reserved and 0 for PDT_FUNCTION
494  uint8_t reservedByte = data[0];
495 
496  if (reservedByte != 0x00)
497  {
498  resultData[0] = ReturnCodes::DataVoid;
499  }
500  else
501  {
502  resultLength = sizeof(resultData); // tell the callee the maximum size of the buffer
503  obj->command((PropertyID)propertyId, data, length, resultData, resultLength);
504  // resultLength was modified by the callee
505  }
506  }
507  else if (propType == PDT_CONTROL)
508  {
509  uint8_t count = 1;
510  // write the event
511  obj->writeProperty((PropertyID)propertyId, 1, data, count);
512 
513  if (count == 1)
514  {
515  // Read the current state (one byte only) for the response
516  obj->readProperty((PropertyID)propertyId, 1, count, &resultData[1]);
517  resultLength = count ? 2 : 1;
518  resultData[0] = count ? ReturnCodes::Success : ReturnCodes::DataVoid;
519  }
520  else
521  {
522  resultData[0] = ReturnCodes::AddressVoid;
523  }
524  }
525  else
526  {
527  resultData[0] = ReturnCodes::DataTypeConflict;
528  }
529  }
530  else
531  {
532  resultData[0] = ReturnCodes::GenericError;
533  }
534 
535  applicationLayer().functionPropertyExtStateResponse(AckRequested, priority, hopType, asap, secCtrl, objectType, objectInstance, propertyId, resultData, resultLength);
536 }
537 
538 void BauSystemB::functionPropertyExtStateIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl, ObjectType objectType, uint8_t objectInstance,
539  uint8_t propertyId, uint8_t* data, uint8_t length)
540 {
541  uint8_t resultData[kFunctionPropertyResultBufferMaxSize];
542  uint8_t resultLength = sizeof(resultData); // tell the callee the maximum size of the buffer
543 
544  InterfaceObject* obj = getInterfaceObject(objectType, objectInstance);
545 
546  if (obj)
547  {
548  PropertyDataType propType = obj->property((PropertyID)propertyId)->Type();
549 
550  if (propType == PDT_FUNCTION)
551  {
552  // The first byte is reserved and 0 for PDT_FUNCTION
553  uint8_t reservedByte = data[0];
554 
555  if (reservedByte != 0x00)
556  {
557  resultData[0] = ReturnCodes::DataVoid;
558  }
559  else
560  {
561  resultLength = sizeof(resultData); // tell the callee the maximum size of the buffer
562  obj->state((PropertyID)propertyId, data, length, resultData, resultLength);
563  // resultLength was modified by the callee
564  }
565  }
566  else if (propType == PDT_CONTROL)
567  {
568  uint8_t count = 1;
569  // Read the current state (one byte only) for the response
570  obj->readProperty((PropertyID)propertyId, 1, count, &resultData[1]);
571  resultLength = count ? 2 : 1;
572  resultData[0] = count ? ReturnCodes::Success : ReturnCodes::DataVoid;
573  }
574  else
575  {
576  resultData[0] = ReturnCodes::DataTypeConflict;
577  }
578  }
579  else
580  {
581  resultData[0] = ReturnCodes::GenericError;
582  }
583 
584  applicationLayer().functionPropertyExtStateResponse(AckRequested, priority, hopType, asap, secCtrl, objectType, objectInstance, propertyId, resultData, resultLength);
585 }
586 
588 {
589  if (_deviceObj.progMode())
591 }
592 
593 void BauSystemB::individualAddressWriteIndication(HopCountType hopType, const SecurityControl& secCtrl, uint16_t newaddress)
594 {
595  if (_deviceObj.progMode())
596  _deviceObj.individualAddress(newaddress);
597 }
598 
599 void BauSystemB::individualAddressSerialNumberWriteIndication(Priority priority, HopCountType hopType, const SecurityControl& secCtrl, uint16_t newIndividualAddress,
600  uint8_t* knxSerialNumber)
601 {
602  // If the received serial number matches our serial number
603  // then store the received new individual address in the device object
604  if (!memcmp(knxSerialNumber, _deviceObj.propertyData(PID_SERIAL_NUMBER), 6))
605  _deviceObj.individualAddress(newIndividualAddress);
606 }
607 
608 void BauSystemB::individualAddressSerialNumberReadIndication(Priority priority, HopCountType hopType, const SecurityControl& secCtrl, uint8_t* knxSerialNumber)
609 {
610  // If the received serial number matches our serial number
611  // then send a response with the serial number. The domain address is set to 0 for closed media.
612  // An open medium BAU has to override this method and provide a proper domain address.
613  if (!memcmp(knxSerialNumber, _deviceObj.propertyData(PID_SERIAL_NUMBER), 6))
614  {
615  uint8_t emptyDomainAddress[2] = {0x00};
616  applicationLayer().IndividualAddressSerialNumberReadResponse(priority, hopType, secCtrl, emptyDomainAddress, knxSerialNumber);
617  }
618 }
619 
621 {
622  _memory.addSaveRestore(obj);
623 }
624 
625 bool BauSystemB::restartRequest(uint16_t asap, const SecurityControl secCtrl)
626 {
627  if (applicationLayer().isConnected())
628  return false;
629 
630  _restartState = Connecting; // order important, has to be set BEFORE connectRequest
631  _restartSecurity = secCtrl;
634  return true;
635 }
636 
637 void BauSystemB::connectConfirm(uint16_t tsap)
638 {
639  if (_restartState == Connecting)
640  {
641  /* restart connection is confirmed, go to the next state */
643  _restartDelay = millis();
644  }
645  else
646  {
648  }
649 }
650 
652 {
653  switch (_restartState)
654  {
655  case Idle:
656  /* inactive state, do nothing */
657  break;
658 
659  case Connecting:
660  /* wait for connection, we do nothing here */
661  break;
662 
663  case Connected:
664 
665  /* connection confirmed, we send restartRequest, but we wait a moment (sending ACK etc)... */
666  if (millis() - _restartDelay > 30)
667  {
670  _restartDelay = millis();
671  }
672 
673  break;
674 
675  case Restarted:
676 
677  /* restart is finished, we send a disconnect */
678  if (millis() - _restartDelay > 30)
679  {
682  }
683 
684  default:
685  break;
686  }
687 }
688 
689 void BauSystemB::systemNetworkParameterReadIndication(Priority priority, HopCountType hopType, const SecurityControl& secCtrl, uint16_t objectType,
690  uint16_t propertyId, uint8_t* testInfo, uint16_t testInfoLength)
691 {
692  uint8_t operand;
693 
694  popByte(operand, testInfo + 1); // First byte (+ 0) contains only 4 reserved bits (0)
695 
696  // See KNX spec. 3.5.2 p.33 (Management Procedures: Procedures with A_SystemNetworkParameter_Read)
697  switch ((NmReadSerialNumberType)operand)
698  {
699  case NM_Read_SerialNumber_By_ProgrammingMode: // NM_Read_SerialNumber_By_ProgrammingMode
700 
701  // Only send a reply if programming mode is on
702  if (_deviceObj.progMode() && (objectType == OT_DEVICE) && (propertyId == PID_SERIAL_NUMBER))
703  {
704  // Send reply. testResult data is KNX serial number
705  applicationLayer().systemNetworkParameterReadResponse(priority, hopType, secCtrl, objectType, propertyId,
706  testInfo, testInfoLength, (uint8_t*)_deviceObj.propertyData(PID_SERIAL_NUMBER), 6);
707  }
708 
709  break;
710 
711  case NM_Read_SerialNumber_By_ExFactoryState: // NM_Read_SerialNumber_By_ExFactoryState
712  break;
713 
714  case NM_Read_SerialNumber_By_PowerReset: // NM_Read_SerialNumber_By_PowerReset
715  break;
716 
717  case NM_Read_SerialNumber_By_ManufacturerSpecific: // Manufacturer specific use of A_SystemNetworkParameter_Read
718  break;
719  }
720 }
721 
722 void BauSystemB::systemNetworkParameterReadLocalConfirm(Priority priority, HopCountType hopType, const SecurityControl& secCtrl, uint16_t objectType,
723  uint16_t propertyId, uint8_t* testInfo, uint16_t testInfoLength, bool status)
724 {
725 }
726 
727 void BauSystemB::propertyValueRead(ObjectType objectType, uint8_t objectInstance, uint8_t propertyId,
728  uint8_t& numberOfElements, uint16_t startIndex,
729  uint8_t** data, uint32_t& length)
730 {
731  uint32_t size = 0;
732  uint8_t elementCount = numberOfElements;
733 
734  InterfaceObject* obj = getInterfaceObject(objectType, objectInstance);
735 
736  if (obj)
737  {
738  uint8_t elementSize = obj->propertySize((PropertyID)propertyId);
739 
740  if (startIndex > 0)
741  size = elementSize * numberOfElements;
742  else
743  size = sizeof(uint16_t); // size of property array entry 0 which contains the current number of elements
744 
745  *data = new uint8_t [size];
746  obj->readProperty((PropertyID)propertyId, startIndex, elementCount, *data);
747  }
748  else
749  {
750  elementCount = 0;
751  *data = nullptr;
752  }
753 
754  numberOfElements = elementCount;
755  length = size;
756 }
757 
758 void BauSystemB::propertyValueWrite(ObjectType objectType, uint8_t objectInstance, uint8_t propertyId,
759  uint8_t& numberOfElements, uint16_t startIndex,
760  uint8_t* data, uint32_t length)
761 {
762  InterfaceObject* obj = getInterfaceObject(objectType, objectInstance);
763 
764  if (obj)
765  obj->writeProperty((PropertyID)propertyId, startIndex, data, numberOfElements);
766  else
767  numberOfElements = 0;
768 }
769 
771 {
772  return _memory;
773 }
774 
776 {
778 }
779 
781 {
782  return _memory.versionCheckCallback();
783 }
784 
786 {
787  _beforeRestart = func;
788 }
789 
791 {
792  return _beforeRestart;
793 }
794 
796 {
797  _functionProperty = func;
798 }
799 
801 {
802  return _functionProperty;
803 }
805 {
806  _functionPropertyState = func;
807 }
808 
810 {
811  return _functionPropertyState;
812 }
void print(const char *s)
void println(const char *s)
void(* BeforeRestartCallback)(void)
Definition: bau.h:6
bool(* FunctionPropertyCallback)(uint8_t objectIndex, uint8_t propertyId, uint8_t length, uint8_t *data, uint8_t *resultData, uint8_t &resultLength)
Definition: bau.h:7
NmReadSerialNumberType
Definition: bau_systemB.cpp:7
@ NM_Read_SerialNumber_By_PowerReset
Definition: bau_systemB.cpp:10
@ NM_Read_SerialNumber_By_ProgrammingMode
Definition: bau_systemB.cpp:8
@ NM_Read_SerialNumber_By_ManufacturerSpecific
Definition: bau_systemB.cpp:11
@ NM_Read_SerialNumber_By_ExFactoryState
Definition: bau_systemB.cpp:9
const uint8_t * popByte(uint8_t &b, const uint8_t *data)
Definition: bits.cpp:4
void printHex(const char *suffix, const uint8_t *data, size_t length, bool newline)
Definition: bits.cpp:12
uint8_t * pushWord(uint16_t w, uint8_t *data)
Definition: bits.cpp:64
uint32_t millis()
void propertyDescriptionReadResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t objectIndex, uint8_t propertyId, uint8_t propertyIndex, bool writeEnable, uint8_t type, uint16_t maxNumberOfElements, uint8_t access)
void individualAddressReadResponse(AckType ack, HopCountType hopType, const SecurityControl &secCtrl)
void functionPropertyStateResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t objectIndex, uint8_t propertyId, uint8_t *resultData, uint8_t resultLength)
void propertyValueExtReadResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint16_t objectType, uint8_t objectInstance, uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t *data, uint8_t length)
void memoryExtReadResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, ReturnCodes code, uint8_t number, uint32_t memoryAddress, uint8_t *data)
void propertyExtDescriptionReadResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint16_t objectType, uint16_t objectInstance, uint16_t propertyId, uint16_t propertyIndex, uint8_t descriptionType, bool writeEnable, uint8_t type, uint16_t maxNumberOfElements, uint8_t access)
void memoryExtWriteResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, ReturnCodes code, uint8_t number, uint32_t memoryAddress, uint8_t *memoryData)
void deviceDescriptorReadResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t descriptorType, uint8_t *deviceDescriptor)
void memoryReadResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint16_t memoryAddress, uint8_t *data)
void authorizeResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t level)
void functionPropertyExtStateResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint16_t objectType, uint8_t objectInstance, uint16_t propertyId, uint8_t *resultData, uint8_t resultLength)
void deviceDescriptorReadRequest(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t descriptorType)
void propertyValueReadResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t objectIndex, uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t *data, uint8_t length)
void systemNetworkParameterReadResponse(Priority priority, HopCountType hopType, const SecurityControl &secCtrl, uint16_t objectType, uint16_t propertyId, uint8_t *testInfo, uint16_t testInfoLength, uint8_t *testResult, uint16_t testResultLength)
void memoryRouterReadResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint16_t memoryAddress, uint8_t *data)
void IndividualAddressSerialNumberReadResponse(Priority priority, HopCountType hopType, const SecurityControl &secCtrl, const uint8_t *domainAddress, const uint8_t *knxSerialNumber)
void restartRequest(AckType ack, Priority priority, HopCountType hopType, const SecurityControl &secCtrl)
void connectRequest(uint16_t destination, Priority priority)
void disconnectRequest(Priority priority)
void memoryRoutingTableReadResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint16_t memoryAddress, uint8_t *data)
void userMemoryReadResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint32_t memoryAddress, uint8_t *memoryData)
void propertyValueExtWriteConResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint16_t objectType, uint8_t objectInstance, uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t returnCode)
void restartResponse(AckType ack, Priority priority, HopCountType hopType, const SecurityControl &secCtrl, uint8_t errorCode, uint16_t processTime)
VersionCheckCallback versionCheckCallback()
Memory & memory()
void memoryExtWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint32_t memoryAddress, uint8_t *data) override
FunctionPropertyCallback functionPropertyStateCallback()
void individualAddressSerialNumberReadIndication(Priority priority, HopCountType hopType, const SecurityControl &secCtrl, uint8_t *knxSerialNumber) override
FunctionPropertyCallback functionPropertyCallback()
void propertyValueExtReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, ObjectType objectType, uint8_t objectInstance, uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex) override
void memoryRouterReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint16_t memoryAddress, uint8_t *data)
void addSaveRestore(SaveRestore *obj)
void memoryRouterWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint16_t memoryAddress, uint8_t *data)
BeforeRestartCallback _beforeRestart
Definition: bau_systemB.h:130
void propertyValueExtWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, ObjectType objectType, uint8_t objectInstance, uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t *data, uint8_t length, bool confirmed)
void nextRestartState()
void systemNetworkParameterReadIndication(Priority priority, HopCountType hopType, const SecurityControl &secCtrl, uint16_t objectType, uint16_t propertyId, uint8_t *testInfo, uint16_t testinfoLength) override
virtual void doMasterReset(EraseCode eraseCode, uint8_t channel)
void functionPropertyCommandIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t objectIndex, uint8_t propertyId, uint8_t *data, uint8_t length) override
Memory _memory
Definition: bau_systemB.h:123
void memoryWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint16_t memoryAddress, uint8_t *data) override
void individualAddressSerialNumberWriteIndication(Priority priority, HopCountType hopType, const SecurityControl &secCtrl, uint16_t newIndividualAddress, uint8_t *knxSerialNumber) override
void memoryReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint16_t memoryAddress) override
void propertyValueWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t objectIndex, uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t *data, uint8_t length) override
void functionPropertyExtCommandIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, ObjectType objectType, uint8_t objectInstance, uint8_t propertyId, uint8_t *data, uint8_t length) override
uint8_t checkmasterResetValidity(EraseCode eraseCode, uint8_t channel)
Definition: bau_systemB.cpp:49
ApplicationProgramObject _appProgram
Definition: bau_systemB.h:125
void systemNetworkParameterReadLocalConfirm(Priority priority, HopCountType hopType, const SecurityControl &secCtrl, uint16_t objectType, uint16_t propertyId, uint8_t *testInfo, uint16_t testInfoLength, bool status) override
void readMemory()
Definition: bau_systemB.cpp:24
void individualAddressReadIndication(HopCountType hopType, const SecurityControl &secCtrl) override
ApplicationProgramObject & parameters()
Definition: bau_systemB.cpp:39
SecurityControl _restartSecurity
Definition: bau_systemB.h:128
Platform & _platform
Definition: bau_systemB.h:126
FunctionPropertyCallback _functionPropertyState
Definition: bau_systemB.h:132
void memoryExtReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint32_t memoryAddress) override
void propertyValueReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t objectIndex, uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex) override
void propertyDescriptionReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t objectIndex, uint8_t propertyId, uint8_t propertyIndex) override
void propertyValueRead(ObjectType objectType, uint8_t objectInstance, uint8_t propertyId, uint8_t &numberOfElements, uint16_t startIndex, uint8_t **data, uint32_t &length) override
void restartRequestIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, RestartType restartType, EraseCode eraseCode, uint8_t channel) override
Platform & platform()
Definition: bau_systemB.cpp:34
RestartState _restartState
Definition: bau_systemB.h:127
void authorizeIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint32_t key) override
void userMemoryWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint32_t memoryAddress, uint8_t *memoryData) override
void connectConfirm(uint16_t tsap) override
void memoryRoutingTableWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint16_t memoryAddress, uint8_t *data)
void propertyExtDescriptionReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint16_t objectType, uint16_t objectInstance, uint16_t propertyId, uint8_t descriptionType, uint16_t propertyIndex) override
void userMemoryReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint32_t memoryAddress) override
uint32_t _restartDelay
Definition: bau_systemB.h:129
BauSystemB(Platform &platform)
Definition: bau_systemB.cpp:17
DeviceObject _deviceObj
Definition: bau_systemB.h:124
virtual InterfaceObject * getInterfaceObject(uint8_t idx)=0
void functionPropertyStateIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t objectIndex, uint8_t propertyId, uint8_t *data, uint8_t length) override
void writeMemory()
Definition: bau_systemB.cpp:29
void functionPropertyExtStateIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, ObjectType objectType, uint8_t objectInstance, uint8_t propertyId, uint8_t *data, uint8_t length) override
BeforeRestartCallback beforeRestartCallback()
void individualAddressWriteIndication(HopCountType hopType, const SecurityControl &secCtrl, uint16_t newaddress) override
bool restartRequest(uint16_t asap, const SecurityControl secCtrl)
void memoryRoutingTableReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint16_t memoryAddress, uint8_t *data)
void propertyValueWrite(ObjectType objectType, uint8_t objectInstance, uint8_t propertyId, uint8_t &numberOfElements, uint16_t startIndex, uint8_t *data, uint32_t length) override
virtual ApplicationLayer & applicationLayer()=0
FunctionPropertyCallback _functionProperty
Definition: bau_systemB.h:131
DeviceObject & deviceObject()
Definition: bau_systemB.cpp:44
void deviceDescriptorReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t descriptorType) override
uint16_t maskVersion()
uint16_t individualAddress()
This class represents and interface object.
const uint8_t * propertyData(PropertyID id)
void readPropertyDescription(uint8_t &propertyId, uint8_t &propertyIndex, bool &writeEnable, uint8_t &type, uint16_t &numberOfElements, uint8_t &access)
Read the Description of a property of the interface object.
virtual void masterReset(EraseCode eraseCode, uint8_t channel)
virtual void command(PropertyID id, uint8_t *data, uint8_t length, uint8_t *resultData, uint8_t &resultLength)
Call command of a function property of the interface object.
virtual void writeProperty(PropertyID id, uint16_t start, uint8_t *data, uint8_t &count)
Write property of the interface object.
virtual uint8_t propertySize(PropertyID id)
Gets the size of of property in bytes.
virtual void readProperty(PropertyID id, uint16_t start, uint8_t &count, uint8_t *data)
Read a property of the interface object.
virtual void state(PropertyID id, uint8_t *data, uint8_t length, uint8_t *resultData, uint8_t &resultLength)
Get state of a function property of the interface object.
Property * property(PropertyID id)
Gets property with PropertyID id if it exists and nullptr otherwise.
Definition: memory.h:37
void versionCheckCallback(VersionCheckCallback func)
Definition: memory.cpp:544
uint8_t * toAbsolute(uint32_t relativeAddress)
Definition: memory.cpp:326
void addSaveRestore(SaveRestore *obj)
Definition: memory.cpp:209
void readMemory()
Definition: memory.cpp:14
void writeMemory()
Definition: memory.cpp:137
virtual void fatalError()=0
virtual void restart()=0
PropertyDataType Type() const
Definition: property.cpp:16
Interface for classes that can save and restore data from a buffer.
Definition: save_restore.h:8
ObjectType
Enum for the type of an interface object.
@ OT_DEVICE
Device object.
HopCountType
Definition: knx_types.h:124
@ NetworkLayerParameter
use NetworkLayer::hopCount as NPDU::hopCount
Definition: knx_types.h:126
Priority
Definition: knx_types.h:10
@ SystemPriority
Mainly used by ETS for device programming.
Definition: knx_types.h:14
EraseCode
Definition: knx_types.h:242
@ ResetIA
Definition: knx_types.h:246
@ ResetParam
Definition: knx_types.h:248
@ FactoryReset
Definition: knx_types.h:245
@ ResetAP
Definition: knx_types.h:247
@ FactoryResetWithoutIA
Definition: knx_types.h:250
@ ConfirmedRestart
Definition: knx_types.h:244
@ ResetLinks
Definition: knx_types.h:249
RestartType
Definition: knx_types.h:236
@ MasterReset
Definition: knx_types.h:238
@ BasicRestart
Definition: knx_types.h:237
@ AckRequested
We want a DataLinkLayer acknowledgement.
Definition: knx_types.h:20
@ DataVoid
Definition: knx_types.h:93
@ DataTypeConflict
Definition: knx_types.h:99
@ AddressVoid
Definition: knx_types.h:98
@ GenericError
Definition: knx_types.h:100
@ Success
Definition: knx_types.h:83
VersionCheckResult(* VersionCheckCallback)(uint16_t manufacturerId, uint8_t *hardwareType, uint16_t version)
Definition: memory.h:34
PropertyID
Definition: property.h:70
@ PID_SERIAL_NUMBER
Definition: property.h:78
PropertyDataType
The data type of a property.
Definition: property.h:17
@ PDT_CONTROL
length: 1 read, 10 write
Definition: property.h:18
@ PDT_FUNCTION
length: 3
Definition: property.h:65