AgIsoStack++
A control-function-focused implementation of the major ISOBUS and J1939 protocols
Loading...
Searching...
No Matches
isobus_device_descriptor_object_pool_helpers.cpp
Go to the documentation of this file.
1//================================================================================================
8//================================================================================================
10
12
13namespace isobus
14{
15 DeviceDescriptorObjectPoolHelper::ObjectPoolValue::operator bool() const
16 {
17 return exists();
18 }
19
24
26 {
27 return isSettable;
28 }
29
31 {
32 return value;
33 }
34
36 {
37 return ((rateActual.dataDictionaryIdentifier != static_cast<std::uint16_t>(DataDescriptionIndex::Reserved)) ||
38 (rateDefault.dataDictionaryIdentifier != static_cast<std::uint16_t>(DataDescriptionIndex::Reserved)) ||
39 (rateMaximum.dataDictionaryIdentifier != static_cast<std::uint16_t>(DataDescriptionIndex::Reserved)) ||
40 (rateMinimum.dataDictionaryIdentifier != static_cast<std::uint16_t>(DataDescriptionIndex::Reserved)) ||
41 (rateSetpoint.dataDictionaryIdentifier != static_cast<std::uint16_t>(DataDescriptionIndex::Reserved)));
42 }
43
45 {
46 Implement retVal;
47
48 if (0 == ddop.size())
49 {
50 LOG_ERROR("[DDOP Helper]: No objects in the pool.");
51 return retVal; // Return empty object
52 }
53
54 // First, find the device object
55 for (std::uint16_t i = 0; i < ddop.size(); i++)
56 {
57 auto deviceObject = ddop.get_object_by_index(i);
58
59 if ((nullptr != deviceObject) &&
60 (task_controller_object::ObjectTypes::Device == deviceObject->get_object_type()))
61 {
62 // Track if we ever find a function. If not, the device will be the boom's root.
63 bool foundFunction = false;
64 std::shared_ptr<task_controller_object::DeviceElementObject> deviceElementObject;
65
66 // Next, iterate through all elements whose parent is the device object
67 for (std::uint16_t j = 0; j < ddop.size(); j++)
68 {
69 auto currentElementObject = ddop.get_object_by_index(j);
70
71 if ((nullptr != currentElementObject) &&
72 (task_controller_object::ObjectTypes::DeviceElement == currentElementObject->get_object_type()) &&
73 (std::static_pointer_cast<task_controller_object::DeviceElementObject>(currentElementObject)->get_parent_object() == deviceObject->get_object_id()))
74 {
75 deviceElementObject = std::static_pointer_cast<task_controller_object::DeviceElementObject>(currentElementObject);
76
77 // All the things we care about are likely in here, under the device element.
78 for (std::uint16_t k = 0; k < ddop.size(); k++)
79 {
80 auto potentialFunction = ddop.get_object_by_index(k);
81
82 if ((nullptr != potentialFunction) &&
83 (task_controller_object::ObjectTypes::DeviceElement == potentialFunction->get_object_type()) &&
84 (std::static_pointer_cast<task_controller_object::DeviceElementObject>(potentialFunction)->get_parent_object() == currentElementObject->get_object_id()) &&
85 (task_controller_object::DeviceElementObject::Type::Function == std::static_pointer_cast<task_controller_object::DeviceElementObject>(potentialFunction)->get_type()))
86 {
87 parse_element(ddop, std::static_pointer_cast<task_controller_object::DeviceElementObject>(potentialFunction), retVal);
88 foundFunction = true;
89 }
90 }
91 break;
92 }
93 }
94
95 if (!foundFunction && (nullptr != deviceElementObject))
96 {
97 // If we didn't find a function, the device element object is the root of the boom.
98 // So we'll reparse the device element object to get the sections and properties we care about.
99 parse_element(ddop, deviceElementObject, retVal);
100
101 // Search all elements whose parent is the device element object
102 // To look for bins as well, since we didn't find any functions.
103 for (std::uint16_t k = 0; k < ddop.size(); k++)
104 {
105 auto potentialBin = ddop.get_object_by_index(k);
106
107 if ((nullptr != potentialBin) &&
108 (task_controller_object::ObjectTypes::DeviceElement == potentialBin->get_object_type()) &&
109 (std::static_pointer_cast<task_controller_object::DeviceElementObject>(potentialBin)->get_parent_object() == deviceElementObject->get_object_id()) &&
110 (task_controller_object::DeviceElementObject::Type::Bin == std::static_pointer_cast<task_controller_object::DeviceElementObject>(potentialBin)->get_type()))
111 {
112 auto binInfo = parse_bin(ddop, std::static_pointer_cast<task_controller_object::DeviceElementObject>(potentialBin));
113
114 if (binInfo.is_valid() && !retVal.booms.empty())
115 {
116 retVal.booms[0].rates.push_back(binInfo);
117 }
118 }
119 }
120 }
121 return retVal;
122 }
123 }
124 LOG_ERROR("[DDOP Helper]: No device object in the pool.");
125 return retVal; // If we got here, we didn't find a device object? Return empty object
126 }
127
129 std::shared_ptr<task_controller_object::DeviceElementObject> elementObject,
130 Implement &implementToPopulate)
131 {
132 Boom boomToPopulate;
133 boomToPopulate.elementNumber = elementObject->get_element_number();
134
136 {
137 // Accumulate the number of functions under this function.
138 // Need to search the whole pool because elements have parent links, not child links, which is not very efficient.
139 for (std::uint16_t i = 0; i < ddop.size(); i++)
140 {
141 auto element = ddop.get_object_by_index(i);
142
143 if ((nullptr != element) &&
144 (task_controller_object::ObjectTypes::DeviceElement == element->get_object_type()) &&
145 (std::static_pointer_cast<task_controller_object::DeviceElementObject>(element)->get_parent_object() == elementObject->get_object_id()))
146 {
147 if (task_controller_object::DeviceElementObject::Type::Function == std::static_pointer_cast<task_controller_object::DeviceElementObject>(element)->get_type())
148 {
149 boomToPopulate.subBooms.push_back(parse_sub_boom(ddop, std::static_pointer_cast<task_controller_object::DeviceElementObject>(element)));
150 }
151 else if (task_controller_object::DeviceElementObject::Type::Bin == std::static_pointer_cast<task_controller_object::DeviceElementObject>(element)->get_type())
152 {
153 auto binInfo = parse_bin(ddop, std::static_pointer_cast<task_controller_object::DeviceElementObject>(element));
154
155 if (binInfo.is_valid())
156 {
157 boomToPopulate.rates.push_back(binInfo);
158 }
159 }
160 }
161 }
162 }
163
164 if (boomToPopulate.subBooms.empty())
165 {
166 // Find all sections in this boom
167 for (std::uint16_t i = 0; i < ddop.size(); i++)
168 {
169 auto section = ddop.get_object_by_index(i);
170
171 if ((nullptr != section) &&
172 (task_controller_object::ObjectTypes::DeviceElement == section->get_object_type()) &&
173 (task_controller_object::DeviceElementObject::Type::Section == std::static_pointer_cast<task_controller_object::DeviceElementObject>(section)->get_type()) &&
174 (std::static_pointer_cast<task_controller_object::DeviceElementObject>(section)->get_parent_object() == elementObject->get_object_id()))
175 {
176 boomToPopulate.sections.push_back(parse_section(ddop, std::static_pointer_cast<task_controller_object::DeviceElementObject>(section)));
177 }
178 }
179
180 // Find child DDIs that we care about
181 for (std::uint16_t i = 0; i < elementObject->get_number_child_objects(); i++)
182 {
183 auto child = ddop.get_object_by_id(elementObject->get_child_object_id(i));
184
185 if (nullptr != child)
186 {
187 if (task_controller_object::ObjectTypes::DeviceProperty == child->get_object_type())
188 {
189 auto property = std::static_pointer_cast<task_controller_object::DevicePropertyObject>(child);
193 }
194 else if (task_controller_object::ObjectTypes::DeviceProcessData == child->get_object_type())
195 {
196 auto processData = std::static_pointer_cast<task_controller_object::DeviceProcessDataObject>(child);
200 }
201 else if ((task_controller_object::ObjectTypes::DeviceElement == child->get_object_type()) &&
202 (task_controller_object::DeviceElementObject::Type::Bin == std::static_pointer_cast<task_controller_object::DeviceElementObject>(child)->get_type()))
203 {
204 auto binInfo = parse_bin(ddop, std::static_pointer_cast<task_controller_object::DeviceElementObject>(child));
205
206 if (binInfo.is_valid())
207 {
208 boomToPopulate.rates.push_back(binInfo);
209 }
210 }
211 }
212 }
213 }
214 else
215 {
216 // Sections are part of the sub booms
217 }
218 implementToPopulate.booms.push_back(boomToPopulate);
219 }
220
222 std::shared_ptr<task_controller_object::DeviceElementObject> elementObject)
223 {
224 Section retVal;
225
226 for (std::uint16_t i = 0; i < elementObject->get_number_child_objects(); i++)
227 {
228 auto sectionChildObject = ddop.get_object_by_id(elementObject->get_child_object_id(i));
229
230 if (nullptr != sectionChildObject)
231 {
232 if (task_controller_object::ObjectTypes::DeviceProperty == sectionChildObject->get_object_type())
233 {
234 auto property = std::static_pointer_cast<task_controller_object::DevicePropertyObject>(sectionChildObject);
239 }
240 else if (task_controller_object::ObjectTypes::DeviceProcessData == sectionChildObject->get_object_type())
241 {
242 auto processData = std::static_pointer_cast<task_controller_object::DeviceProcessDataObject>(sectionChildObject);
247 }
248 else if ((task_controller_object::ObjectTypes::DeviceElement == sectionChildObject->get_object_type()) &&
249 (task_controller_object::DeviceElementObject::Type::Bin == std::static_pointer_cast<task_controller_object::DeviceElementObject>(sectionChildObject)->get_type()))
250 {
251 auto binInfo = parse_bin(ddop, std::static_pointer_cast<task_controller_object::DeviceElementObject>(sectionChildObject));
252
253 if (binInfo.is_valid())
254 {
255 retVal.rates.push_back(binInfo);
256 }
257 }
258 }
259 }
260 retVal.elementNumber = elementObject->get_element_number();
261 return retVal;
262 }
263
265 std::shared_ptr<task_controller_object::DeviceElementObject> elementObject)
266 {
267 SubBoom retVal;
268 retVal.elementNumber = elementObject->get_element_number();
269
270 // Find all sections in this sub boom
271 // We again have to search the whole pool because elements have parent links, not child links
272 for (std::uint16_t i = 0; i < ddop.size(); i++)
273 {
274 auto section = ddop.get_object_by_index(i);
275
276 if ((nullptr != section) &&
277 (task_controller_object::ObjectTypes::DeviceElement == section->get_object_type()) &&
278 (task_controller_object::DeviceElementObject::Type::Section == std::static_pointer_cast<task_controller_object::DeviceElementObject>(section)->get_type()) &&
279 (std::static_pointer_cast<task_controller_object::DeviceElementObject>(section)->get_parent_object() == elementObject->get_object_id()))
280 {
281 retVal.sections.push_back(parse_section(ddop, std::static_pointer_cast<task_controller_object::DeviceElementObject>(section)));
282 }
283 }
284
285 // Process child DDIs of this sub boom to locate offset and width
286 for (std::uint16_t i = 0; i < elementObject->get_number_child_objects(); i++)
287 {
288 auto childObject = ddop.get_object_by_id(elementObject->get_child_object_id(i));
289
290 if (nullptr != childObject)
291 {
292 if (task_controller_object::ObjectTypes::DeviceProperty == childObject->get_object_type())
293 {
294 auto property = std::static_pointer_cast<task_controller_object::DevicePropertyObject>(childObject);
299 }
300 else if (task_controller_object::ObjectTypes::DeviceProcessData == childObject->get_object_type())
301 {
302 auto processData = std::static_pointer_cast<task_controller_object::DeviceProcessDataObject>(childObject);
307 }
308 else if ((task_controller_object::ObjectTypes::DeviceElement == childObject->get_object_type()) &&
309 (task_controller_object::DeviceElementObject::Type::Bin == std::static_pointer_cast<task_controller_object::DeviceElementObject>(childObject)->get_type()))
310 {
311 auto binInfo = parse_bin(ddop, std::static_pointer_cast<task_controller_object::DeviceElementObject>(childObject));
312
313 if (binInfo.is_valid())
314 {
315 retVal.rates.push_back(binInfo);
316 }
317 }
318 }
319 }
320 return retVal;
321 }
322
324 std::shared_ptr<task_controller_object::DeviceElementObject> elementObject)
325 {
326 // A bin is used to identify a product.
327 // We'll use this to populate the product control information.
329
330 if (task_controller_object::DeviceElementObject::Type::Bin == elementObject->get_type())
331 {
332 retVal.elementNumber = elementObject->get_element_number();
333 for (std::uint16_t i = 0; i < elementObject->get_number_child_objects(); i++)
334 {
335 auto object = ddop.get_object_by_id(elementObject->get_child_object_id(i));
336
337 if (nullptr != object)
338 {
339 if (task_controller_object::ObjectTypes::DeviceProcessData == object->get_object_type())
340 {
341 std::uint16_t ddi = std::static_pointer_cast<task_controller_object::DeviceProcessDataObject>(object)->get_ddi();
342 set_product_control_information_max_rate(retVal, object, ddi);
343 set_product_control_information_min_rate(retVal, object, ddi);
347 }
348 else if (task_controller_object::ObjectTypes::DeviceProperty == object->get_object_type())
349 {
350 std::uint16_t ddi = std::static_pointer_cast<task_controller_object::DevicePropertyObject>(object)->get_ddi();
351 set_product_control_information_max_rate(retVal, object, ddi);
352 set_product_control_information_min_rate(retVal, object, ddi);
356 }
357 }
358 }
359 }
360 return retVal;
361 }
362
364 const std::shared_ptr<task_controller_object::DevicePropertyObject> &property,
366 {
367 if (property->get_ddi() == static_cast<std::uint16_t>(ddi))
368 {
369 objectPoolValue.value = property->get_value();
370 objectPoolValue.isValuePresent = true;
371 }
372 }
373
375 const std::shared_ptr<task_controller_object::DeviceProcessDataObject> &processData,
377 {
378 if (processData->get_ddi() == static_cast<std::uint16_t>(ddi))
379 {
380 objectPoolValue.isSettable = (0 != (static_cast<std::uint8_t>(task_controller_object::DeviceProcessDataObject::PropertiesBit::Settable) & processData->get_properties_bitfield()));
381 }
382 }
383
385 const std::shared_ptr<task_controller_object::Object> &object,
386 std::uint16_t ddi)
387 {
388 switch (ddi)
389 {
390 case static_cast<std::uint16_t>(DataDescriptionIndex::MaximumApplicationRateOfAmmonium):
391 case static_cast<std::uint16_t>(DataDescriptionIndex::MaximumApplicationRateOfDryMatter):
392 case static_cast<std::uint16_t>(DataDescriptionIndex::MaximumApplicationRateOfNitrogen):
393 case static_cast<std::uint16_t>(DataDescriptionIndex::MaximumApplicationRateOfPhosphor):
394 case static_cast<std::uint16_t>(DataDescriptionIndex::MaximumApplicationRateOfPotassium):
395 case static_cast<std::uint16_t>(DataDescriptionIndex::MaximumCountPerAreaApplicationRate):
396 case static_cast<std::uint16_t>(DataDescriptionIndex::MaximumCountPerTimeApplicationRate):
397 case static_cast<std::uint16_t>(DataDescriptionIndex::MaximumMassPerAreaApplicationRate):
398 case static_cast<std::uint16_t>(DataDescriptionIndex::MaximumMassPerMassApplicationRate):
399 case static_cast<std::uint16_t>(DataDescriptionIndex::MaximumMassPerTimeApplicationRate):
400 case static_cast<std::uint16_t>(DataDescriptionIndex::MaximumVolumePerAreaApplicationRate):
401 case static_cast<std::uint16_t>(DataDescriptionIndex::MaximumVolumePerMassApplicationRate):
403 case static_cast<std::uint16_t>(DataDescriptionIndex::MaximumVolumePerTimeApplicationRate):
404 case static_cast<std::uint16_t>(DataDescriptionIndex::MaximumSpacingApplicationRate):
405 case static_cast<std::uint16_t>(DataDescriptionIndex::MaximumRevolutionsPerTime):
406 {
407 if (task_controller_object::ObjectTypes::DeviceProcessData == object->get_object_type())
408 {
409 auto processData = std::static_pointer_cast<task_controller_object::DeviceProcessDataObject>(object);
410
411 if (ddi == processData->get_ddi())
412 {
413 productControlInformation.rateMaximum.isSettable = (0 != (static_cast<std::uint8_t>(task_controller_object::DeviceProcessDataObject::PropertiesBit::Settable) & processData->get_properties_bitfield()));
414 productControlInformation.rateMaximum.objectID = processData->get_object_id();
415 productControlInformation.rateMaximum.dataDictionaryIdentifier = processData->get_ddi();
416 }
417 }
418 else if (task_controller_object::ObjectTypes::DeviceProperty == object->get_object_type())
419 {
420 auto property = std::static_pointer_cast<task_controller_object::DevicePropertyObject>(object);
421
422 if (ddi == property->get_ddi())
423 {
424 productControlInformation.rateMaximum.objectID = property->get_object_id();
425 productControlInformation.rateMaximum.isValuePresent = true;
426 productControlInformation.rateMaximum.value = property->get_value();
427 productControlInformation.rateMaximum.dataDictionaryIdentifier = property->get_ddi();
428 }
429 }
430 }
431 break;
432
433 default:
434 break;
435 }
436 }
437
439 const std::shared_ptr<task_controller_object::Object> &object,
440 std::uint16_t ddi)
441 {
442 switch (ddi)
443 {
444 case static_cast<std::uint16_t>(DataDescriptionIndex::MinimumApplicationRateOfAmmonium):
445 case static_cast<std::uint16_t>(DataDescriptionIndex::MinimumApplicationRateOfDryMatter):
446 case static_cast<std::uint16_t>(DataDescriptionIndex::MinimumApplicationRateOfNitrogen):
447 case static_cast<std::uint16_t>(DataDescriptionIndex::MinimumApplicationRateOfPhosphor):
448 case static_cast<std::uint16_t>(DataDescriptionIndex::MinimumApplicationRateOfPotassium):
449 case static_cast<std::uint16_t>(DataDescriptionIndex::MinimumCountPerAreaApplicationRate):
450 case static_cast<std::uint16_t>(DataDescriptionIndex::MinimumCountPerTimeApplicationRate):
451 case static_cast<std::uint16_t>(DataDescriptionIndex::MinimumMassPerAreaApplicationRate):
452 case static_cast<std::uint16_t>(DataDescriptionIndex::MinimumMassPerMassApplicationRate):
453 case static_cast<std::uint16_t>(DataDescriptionIndex::MinimumMassPerTimeApplicationRate):
454 case static_cast<std::uint16_t>(DataDescriptionIndex::MinimumVolumePerAreaApplicationRate):
455 case static_cast<std::uint16_t>(DataDescriptionIndex::MinimumVolumePerMassApplicationRate):
457 case static_cast<std::uint16_t>(DataDescriptionIndex::MinimumVolumePerTimeApplicationRate):
458 case static_cast<std::uint16_t>(DataDescriptionIndex::MinimumSpacingApplicationRate):
459 case static_cast<std::uint16_t>(DataDescriptionIndex::MinimumRevolutionsPerTime):
460 {
461 if (task_controller_object::ObjectTypes::DeviceProcessData == object->get_object_type())
462 {
463 auto processData = std::static_pointer_cast<task_controller_object::DeviceProcessDataObject>(object);
464
465 if (ddi == processData->get_ddi())
466 {
467 productControlInformation.rateMinimum.isSettable = (0 != (static_cast<std::uint8_t>(task_controller_object::DeviceProcessDataObject::PropertiesBit::Settable) & processData->get_properties_bitfield()));
468 productControlInformation.rateMinimum.objectID = processData->get_object_id();
469 productControlInformation.rateMinimum.dataDictionaryIdentifier = processData->get_ddi();
470 }
471 }
472 else if (task_controller_object::ObjectTypes::DeviceProperty == object->get_object_type())
473 {
474 auto property = std::static_pointer_cast<task_controller_object::DevicePropertyObject>(object);
475
476 if (ddi == property->get_ddi())
477 {
478 productControlInformation.rateMinimum.objectID = property->get_object_id();
479 productControlInformation.rateMinimum.isValuePresent = true;
480 productControlInformation.rateMinimum.value = property->get_value();
481 productControlInformation.rateMinimum.dataDictionaryIdentifier = property->get_ddi();
482 }
483 }
484 }
485 break;
486
487 default:
488 break;
489 }
490 }
491
493 const std::shared_ptr<task_controller_object::Object> &object,
494 std::uint16_t ddi)
495 {
496 switch (ddi)
497 {
498 case static_cast<std::uint16_t>(DataDescriptionIndex::DefaultRevolutionsPerTime):
499 case static_cast<std::uint16_t>(DataDescriptionIndex::DefaultCountPerAreaApplicationRate):
500 case static_cast<std::uint16_t>(DataDescriptionIndex::DefaultCountPerTimeApplicationRate):
501 case static_cast<std::uint16_t>(DataDescriptionIndex::DefaultMassPerAreaApplicationRate):
502 case static_cast<std::uint16_t>(DataDescriptionIndex::DefaultMassPerMassApplicationRate):
503 case static_cast<std::uint16_t>(DataDescriptionIndex::DefaultMassPerTimeApplicationRate):
504 case static_cast<std::uint16_t>(DataDescriptionIndex::DefaultVolumePerAreaApplicationRate):
505 case static_cast<std::uint16_t>(DataDescriptionIndex::DefaultVolumePerMassApplicationRate):
507 case static_cast<std::uint16_t>(DataDescriptionIndex::DefaultVolumePerTimeApplicationRate):
508 case static_cast<std::uint16_t>(DataDescriptionIndex::DefaultSpacingApplicationRate):
509 {
510 if (task_controller_object::ObjectTypes::DeviceProcessData == object->get_object_type())
511 {
512 auto processData = std::static_pointer_cast<task_controller_object::DeviceProcessDataObject>(object);
513
514 if (ddi == processData->get_ddi())
515 {
516 productControlInformation.rateDefault.isSettable = (0 != (static_cast<std::uint8_t>(task_controller_object::DeviceProcessDataObject::PropertiesBit::Settable) & processData->get_properties_bitfield()));
517 productControlInformation.rateDefault.objectID = processData->get_object_id();
518 productControlInformation.rateDefault.dataDictionaryIdentifier = processData->get_ddi();
519 }
520 }
521 else if (task_controller_object::ObjectTypes::DeviceProperty == object->get_object_type())
522 {
523 auto property = std::static_pointer_cast<task_controller_object::DevicePropertyObject>(object);
524
525 if (ddi == property->get_ddi())
526 {
527 productControlInformation.rateDefault.objectID = property->get_object_id();
528 productControlInformation.rateDefault.isValuePresent = true;
529 productControlInformation.rateDefault.value = property->get_value();
530 productControlInformation.rateDefault.dataDictionaryIdentifier = property->get_ddi();
531 }
532 }
533 }
534 break;
535
536 default:
537 break;
538 }
539 }
540
542 const std::shared_ptr<task_controller_object::Object> &object,
543 std::uint16_t ddi)
544 {
545 switch (ddi)
546 {
547 case static_cast<std::uint16_t>(DataDescriptionIndex::SetpointApplicationRateOfAmmonium):
548 case static_cast<std::uint16_t>(DataDescriptionIndex::SetpointApplicationRateOfDryMatter):
549 case static_cast<std::uint16_t>(DataDescriptionIndex::SetpointApplicationRateOfNitrogen):
550 case static_cast<std::uint16_t>(DataDescriptionIndex::SetpointApplicationRateOfPhosphor):
551 case static_cast<std::uint16_t>(DataDescriptionIndex::SetpointApplicationRateOfPotassium):
552 case static_cast<std::uint16_t>(DataDescriptionIndex::SetpointCountPerAreaApplicationRate):
553 case static_cast<std::uint16_t>(DataDescriptionIndex::SetpointCountPerTimeApplicationRate):
554 case static_cast<std::uint16_t>(DataDescriptionIndex::SetpointMassPerAreaApplicationRate):
555 case static_cast<std::uint16_t>(DataDescriptionIndex::SetpointMassPerMassApplicationRate):
556 case static_cast<std::uint16_t>(DataDescriptionIndex::SetpointMassPerTimeApplicationRate):
557 case static_cast<std::uint16_t>(DataDescriptionIndex::SetpointVolumePerAreaApplicationRate):
558 case static_cast<std::uint16_t>(DataDescriptionIndex::SetpointVolumePerMassApplicationRate):
560 case static_cast<std::uint16_t>(DataDescriptionIndex::SetpointVolumePerTimeApplicationRate):
561 case static_cast<std::uint16_t>(DataDescriptionIndex::SetpointSpacingApplicationRate):
563 {
564 if (task_controller_object::ObjectTypes::DeviceProcessData == object->get_object_type())
565 {
566 auto processData = std::static_pointer_cast<task_controller_object::DeviceProcessDataObject>(object);
567
568 if (ddi == processData->get_ddi())
569 {
570 productControlInformation.rateSetpoint.isSettable = (0 != (static_cast<std::uint8_t>(task_controller_object::DeviceProcessDataObject::PropertiesBit::Settable) & processData->get_properties_bitfield()));
571 productControlInformation.rateSetpoint.objectID = processData->get_object_id();
572 productControlInformation.rateSetpoint.dataDictionaryIdentifier = processData->get_ddi();
573 }
574 }
575 else if (task_controller_object::ObjectTypes::DeviceProperty == object->get_object_type())
576 {
577 auto property = std::static_pointer_cast<task_controller_object::DevicePropertyObject>(object);
578
579 if (ddi == property->get_ddi())
580 {
581 productControlInformation.rateSetpoint.objectID = property->get_object_id();
582 productControlInformation.rateSetpoint.isValuePresent = true;
583 productControlInformation.rateSetpoint.value = property->get_value();
584 productControlInformation.rateSetpoint.dataDictionaryIdentifier = property->get_ddi();
585 }
586 }
587 }
588 break;
589
590 default:
591 break;
592 }
593 }
594
596 const std::shared_ptr<task_controller_object::Object> &object,
597 std::uint16_t ddi)
598 {
599 switch (ddi)
600 {
601 case static_cast<std::uint16_t>(DataDescriptionIndex::ActualApplicationRateOfAmmonium):
602 case static_cast<std::uint16_t>(DataDescriptionIndex::ActualApplicationRateOfDryMatter):
603 case static_cast<std::uint16_t>(DataDescriptionIndex::ActualApplicationRateOfNitrogen):
604 case static_cast<std::uint16_t>(DataDescriptionIndex::ActualApplicationRateOfPhosphor):
605 case static_cast<std::uint16_t>(DataDescriptionIndex::ActualApplicationRateOfPotassium):
606 case static_cast<std::uint16_t>(DataDescriptionIndex::ActualCountPerAreaApplicationRate):
607 case static_cast<std::uint16_t>(DataDescriptionIndex::ActualCountPerTimeApplicationRate):
608 case static_cast<std::uint16_t>(DataDescriptionIndex::ActualMassPerAreaApplicationRate):
609 case static_cast<std::uint16_t>(DataDescriptionIndex::ActualMassPerMassApplicationRate):
610 case static_cast<std::uint16_t>(DataDescriptionIndex::ActualMassPerTimeApplicationRate):
611 case static_cast<std::uint16_t>(DataDescriptionIndex::ActualVolumePerAreaApplicationRate):
612 case static_cast<std::uint16_t>(DataDescriptionIndex::ActualVolumePerMassApplicationRate):
613 case static_cast<std::uint16_t>(DataDescriptionIndex::ActualVolumePerVolumeApplicationRate):
614 case static_cast<std::uint16_t>(DataDescriptionIndex::ActualVolumePerTimeApplicationRate):
615 case static_cast<std::uint16_t>(DataDescriptionIndex::ActualSpacingApplicationRate):
616 case static_cast<std::uint16_t>(DataDescriptionIndex::ActualRevolutionsPerTime):
617 {
618 if (task_controller_object::ObjectTypes::DeviceProcessData == object->get_object_type())
619 {
620 auto processData = std::static_pointer_cast<task_controller_object::DeviceProcessDataObject>(object);
621
622 if (ddi == processData->get_ddi())
623 {
624 productControlInformation.rateActual.isSettable = (0 != (static_cast<std::uint8_t>(task_controller_object::DeviceProcessDataObject::PropertiesBit::Settable) & processData->get_properties_bitfield()));
625 productControlInformation.rateActual.objectID = processData->get_object_id();
626 productControlInformation.rateActual.dataDictionaryIdentifier = processData->get_ddi();
627 }
628 }
629 else if (task_controller_object::ObjectTypes::DeviceProperty == object->get_object_type())
630 {
631 auto property = std::static_pointer_cast<task_controller_object::DevicePropertyObject>(object);
632
633 if (ddi == property->get_ddi())
634 {
635 productControlInformation.rateActual.objectID = property->get_object_id();
636 productControlInformation.rateActual.isValuePresent = true;
637 productControlInformation.rateActual.value = property->get_value();
638 productControlInformation.rateActual.dataDictionaryIdentifier = property->get_ddi();
639 }
640 }
641 }
642 break;
643
644 default:
645 break;
646 }
647 }
648} // namespace isobus
A class that acts as a logging sink. The intent is that someone could make their own derived class of...
A helper class that describes a boom This is used to describe a boom, or more generally,...
std::vector< ProductControlInformation > rates
If the boom has rates, this will contain the associated data needed to control the product.
ObjectPoolValue zOffset_mm
The z offset of the sub boom in mm. Z offsets are up+/down-.
ObjectPoolValue xOffset_mm
The x offset of the sub boom in mm. X offsets are fore+/aft-.
ObjectPoolValue yOffset_mm
The y offset of the sub boom in mm. Y offsets are left-/right+.
std::uint16_t elementNumber
The element number of the boom, which can be used to avoid further parsing of the DDOP when issuing c...
A helper class that describes an implement based on its DDOP.
A wrapper for a DDOP value which tells you if the value was actually supplied by the DDOP.
bool exists() const
Returns if this variable exists. A variable exists if it was either provided in the DDOP,...
bool isSettable
Stores if the value can be set, such as on a DPD's value.
std::int32_t get() const
Returns the value. If the value doesn't exist this will return 0.
bool editable() const
Returns if this value is editable. DPDs are editable. DPTs are not.
A helper class that groups product rate infomation together. A TC server could use this to know quick...
std::uint16_t elementNumber
The element number of the bin, which can be used to avoid further parsing of the DDOP when issuing co...
std::uint16_t dataDictionaryIdentifier
The data dictionary index of the product control rate.
A helper class that describes an individual section of a boom. This is used to describe the sections ...
ObjectPoolValue zOffset_mm
The z offset of the section in mm. Z offsets are up+/down-.
ObjectPoolValue yOffset_mm
The y offset of the section in mm. Y offsets are left-/right+.
std::vector< ProductControlInformation > rates
If the section has rates, this will contain the associated data needed to control the product.
std::uint16_t elementNumber
The element number of the section, which can be used to avoid further parsing of the DDOP when issuin...
ObjectPoolValue xOffset_mm
The x offset of the section in mm. X offsets are fore+/aft-.
A helper class that describes a sub boom (not all devices support this)
ObjectPoolValue xOffset_mm
The x offset of the sub boom in mm. X offsets are fore+/aft-.
std::uint16_t elementNumber
The element number of the sub boom , which can be used to avoid further parsing of the DDOP when issu...
ObjectPoolValue zOffset_mm
The z offset of the sub boom in mm. Z offsets are up+/down-.
ObjectPoolValue yOffset_mm
The y offset of the sub boom in mm. Y offsets are left-/right+.
std::vector< ProductControlInformation > rates
If the sub-boom has rates, this will contain the associated data needed to control the product.
static void set_product_control_information_actual_rate(ProductControlInformation &productControlInformation, const std::shared_ptr< task_controller_object::Object > &object, std::uint16_t ddi)
Sets the actual rate field of the product control information based on the supplied object if the DDI...
static void set_product_control_information_setpoint_rate(ProductControlInformation &productControlInformation, const std::shared_ptr< task_controller_object::Object > &object, std::uint16_t ddi)
Sets the setpoint rate field of the product control information based on the supplied object if the D...
static void set_value_from_property(ObjectPoolValue &objectPoolValue, const std::shared_ptr< task_controller_object::DevicePropertyObject > &property, DataDescriptionIndex ddi)
Sets the value and presence based on a DDI match.
static SubBoom parse_sub_boom(DeviceDescriptorObjectPool &ddop, std::shared_ptr< task_controller_object::DeviceElementObject > elementObject)
Parse a sub boom element of the DDOP.
static void set_product_control_information_min_rate(ProductControlInformation &productControlInformation, const std::shared_ptr< task_controller_object::Object > &object, std::uint16_t ddi)
Sets the minimum rate field of the product control information based on the supplied object if the DD...
static void parse_element(DeviceDescriptorObjectPool &ddop, std::shared_ptr< task_controller_object::DeviceElementObject > elementObject, Implement &implementToPopulate)
Parse an element of the DDOP.
static void set_editable_from_process_data(ObjectPoolValue &objectPoolValue, const std::shared_ptr< task_controller_object::DeviceProcessDataObject > &processData, DataDescriptionIndex ddi)
Sets the settable flag based on a DDI match for process data.
static void set_product_control_information_max_rate(ProductControlInformation &productControlInformation, const std::shared_ptr< task_controller_object::Object > &object, std::uint16_t ddi)
Sets the max rate field of the product control information based on the supplied object if the DDI is...
static ProductControlInformation parse_bin(DeviceDescriptorObjectPool &ddop, std::shared_ptr< task_controller_object::DeviceElementObject > elementObject)
Parses a bin element of the DDOP.
static Section parse_section(DeviceDescriptorObjectPool &ddop, std::shared_ptr< task_controller_object::DeviceElementObject > elementObject)
Parse a section element of the DDOP.
static Implement get_implement_geometry(DeviceDescriptorObjectPool &ddop)
Get the implement description from the DDOP.
static void set_product_control_information_default_rate(ProductControlInformation &productControlInformation, const std::shared_ptr< task_controller_object::Object > &object, std::uint16_t ddi)
Sets the default rate field of the product control information based on the supplied object if the DD...
std::shared_ptr< task_controller_object::Object > get_object_by_index(std::uint16_t index)
Gets an object from the DDOP by index based on object creation.
std::shared_ptr< task_controller_object::Object > get_object_by_id(std::uint16_t objectID)
Gets an object from the DDOP that corresponds to a certain object ID.
std::uint16_t size() const
Returns the number of objects in the DDOP.
@ Bin
This is, for instance, the tank of a sprayer or the bin of a seeder.
@ Function
This device element type can be used as a generic device element to define individually accessible co...
@ Section
This is, for instance, the section of a spray boom, seed toolbar, or planter toolbar.
Defines helpers for getting commonly needed information out of a DDOP. These are provided so that you...
@ DeviceProperty
A device property element.
@ DeviceProcessData
Contains a single process data variable definition.
@ DeviceElement
Subcomponent of a device. Has multiple sub-types.
@ Device
The root object. Each device shall have one single Device.
This namespace encompasses all of the ISO11783 stack's functionality to reduce global namespace pollu...
DataDescriptionIndex
Enumerates a subset of standard ISOBUS DDIs.
@ SetpointVolumePerAreaApplicationRate
Setpoint Application Rate specified as volume per area.
@ SetpointMassPerTimeApplicationRate
Setpoint Application Rate specified as mass per time.
@ MinimumCountPerAreaApplicationRate
Minimum Application Rate specified as count per area.
@ MinimumApplicationRateOfAmmonium
Minimum application rate of Ammonium specified as a mass per area.
@ MaximumVolumePerAreaApplicationRate
Maximum Application Rate specified as volume per area.
@ SetpointVolumePerMassApplicationRate
Setpoint Application Rate specified as volume per mass.
@ DefaultMassPerTimeApplicationRate
Default Application Rate specified as mass per time.
@ MaximumCountPerTimeApplicationRate
Maximum Application Rate specified as count per time.
@ MinimumMassPerTimeApplicationRate
Minimum Application Rate specified as mass per time.
@ MinimumCountPerTimeApplicationRate
Minimum Application Rate specified as count per time.
@ DefaultMassPerAreaApplicationRate
Default Application Rate specified as mass per area.
@ SetpointSpacingApplicationRate
Setpoint Application Rate specified as distance: e.g. seed spacing of a precision seeder.
@ SetpointVolumePerTimeApplicationRate
Setpoint Application Rate specified as volume per time.
@ ActualVolumePerMassApplicationRate
Actual Application Rate specified as volume per mass.
@ ActualApplicationRateOfNitrogen
Actual application rate of nitrogen specified as a mass per area.
@ MinimumApplicationRateOfPotassium
Minimum application rate of potassium specified as a mass per area.
@ DefaultVolumePerVolumeApplicationRate
Default Application Rate specified as volume per volume.
@ MaximumVolumePerVolumeApplicationRate
Maximum Application Rate specified as volume per volume.
@ MinimumVolumePerVolumeApplicationRate
Minimum Application Rate specified as volume per volume.
@ ActualRevolutionsPerTime
Actual Revolutions specified as count per time.
@ MaximumRevolutionsPerTime
Maximum Revolutions specified as count per time.
@ MaximumSpacingApplicationRate
Maximum Application Rate specified as distance: e.g. seed spacing of a precision seeder.
@ SetpointVolumePerVolumeApplicationRate
Setpoint Application Rate specified as volume per volume.
@ ActualApplicationRateOfAmmonium
Actual application rate of Ammonium specified as a mass per area.
@ DefaultVolumePerTimeApplicationRate
Default Application Rate specified as volume per time.
@ DeviceElementOffsetZ
Z direction offset of a DeviceElement relative to a Device.
@ DefaultRevolutionsPerTime
Default Revolutions specified as count per time.
@ MaximumVolumePerTimeApplicationRate
Maximum Application Rate specified as volume per time.
@ ActualMassPerMassApplicationRate
Actual Application Rate specified as mass per mass.
@ MaximumApplicationRateOfAmmonium
Maximum application rate of Ammonium specified as a mass per area.
@ SetpointCountPerAreaApplicationRate
Setpoint Application Rate specified as count per area.
@ ActualSpacingApplicationRate
Actual Application Rate specified as distance: e.g. seed spacing of a precision seeder.
@ MinimumApplicationRateOfNitrogen
Minimum application rate of nitrogen specified as a mass per area.
@ SetpointMassPerAreaApplicationRate
Setpoint Application Rate specified as mass per area.
@ MaximumApplicationRateOfDryMatter
Maximum application rate of dry matter expressed as percentage.
@ SetpointApplicationRateOfDryMatter
Setpoint application rate of dry matter expressed as percentage.
@ ActualCountPerTimeApplicationRate
Actual Application Rate specified as count per time.
@ ActualWorkingWidth
Actual Working Width of Device Element.
@ MinimumRevolutionsPerTime
Minimum Revolutions specified as count per time.
@ MaximumApplicationRateOfPotassium
Maximum application rate of potassium specified as a mass per area.
@ MaximumCountPerAreaApplicationRate
Maximum Application Rate specified as count per area.
@ DefaultVolumePerAreaApplicationRate
Default Application Rate specified as volume per area.
@ MaximumMassPerMassApplicationRate
Maximum Application Rate specified as mass per mass.
@ SetpointMassPerMassApplicationRate
Setpoint Application Rate specified as mass per mass.
@ DefaultSpacingApplicationRate
Default Application Rate specified as distance: e.g. seed spacing of a precision seeder.
@ MinimumMassPerMassApplicationRate
Minimum Application Rate specified as mass per mass.
@ DeviceElementOffsetY
Y direction offset of a DeviceElement relative to a Device.
@ MinimumMassPerAreaApplicationRate
Minimum Application Rate specified as mass per area.
@ ActualVolumePerAreaApplicationRate
Actual Application Rate specified as volume per area.
@ SetpointApplicationRateOfNitrogen
Setpoint application rate of nitrogen specified as a mass per area.
@ ActualMassPerTimeApplicationRate
Actual Application Rate specified as mass per time.
@ MinimumSpacingApplicationRate
Minimum Application Rate specified as distance: e.g. seed spacing of a precision seeder.
@ ActualVolumePerTimeApplicationRate
Actual Application Rate specified as volume per time.
@ MaximumVolumePerMassApplicationRate
Maximum Application Rate specified as volume per mass.
@ DefaultCountPerTimeApplicationRate
Default Application Rate specified as count per time.
@ MinimumApplicationRateOfDryMatter
Minimum application rate of dry matter expressed as percentage.
@ MinimumVolumePerMassApplicationRate
Minimum Application Rate specified as volume per mass.
@ MinimumVolumePerTimeApplicationRate
Minimum Application Rate specified as volume per time.
@ ActualApplicationRateOfDryMatter
Actual application rate of dry matter expressed as percentage.
@ SetpointApplicationRateOfPhosphor
Setpoint application rate of phosphor specified as a mass per area.
@ SetpointApplicationRateOfAmmonium
Setpoint application rate of Ammonium specified as a mass per area.
@ MinimumApplicationRateOfPhosphor
Minimum application rate of phosphor specified as a mass per area.
@ ActualApplicationRateOfPhosphor
Actual application rate of phosphor specified as a mass per area.
@ SetpointCountPerTimeApplicationRate
Setpoint Application Rate specified as count per time.
@ ActualVolumePerVolumeApplicationRate
Actual Application Rate specified as volume per volume.
@ ActualMassPerAreaApplicationRate
Actual Application Rate specified as mass per area.
@ DefaultCountPerAreaApplicationRate
Default Application Rate specified as count per area.
@ MaximumMassPerTimeApplicationRate
Maximum Application Rate specified as mass per time.
@ DefaultMassPerMassApplicationRate
Default Application Rate specified as mass per mass.
@ DeviceElementOffsetX
X direction offset of a DeviceElement relative to a Device.
@ MaximumMassPerAreaApplicationRate
Maximum Application Rate specified as mass per area.
@ ActualCountPerAreaApplicationRate
Actual Application Rate specified as count per area.
@ SetpointRevolutionsSpecifiedAsCountPerTime
Setpoint Revolutions specified as count per time.
@ MaximumApplicationRateOfPhosphor
Maximum application rate of phosphor specified as a mass per area.
@ ActualApplicationRateOfPotassium
Actual application rate of potassium specified as a mass per area.
@ MaximumApplicationRateOfNitrogen
Maximum application rate of nitrogen specified as a mass per area.
@ DefaultVolumePerMassApplicationRate
Default Application Rate specified as volume per mass.
@ MinimumVolumePerAreaApplicationRate
Minimum Application Rate specified as volume per area.
@ SetpointApplicationRateOfPotassium
Setpoint application rate of potassium specified as a mass per area.