AgIsoStack++
A control-function-focused implementation of the major ISOBUS and J1939 protocols
Loading...
Searching...
No Matches
isobus_functionalities.cpp
Go to the documentation of this file.
1//================================================================================================
8//================================================================================================
12
13#include <algorithm>
14#include <cassert>
15#include <limits>
16
17namespace isobus
18{
19 ControlFunctionFunctionalities::ControlFunctionFunctionalities(std::shared_ptr<InternalControlFunction> sourceControlFunction) :
20 myControlFunction(sourceControlFunction),
21 txFlags(static_cast<std::uint32_t>(TransmitFlags::NumberOfFlags), process_flags, this)
22 {
23 set_functionality_is_supported(Functionalities::MinimumControlFunction, 1, true); // Support the absolute minimum by default
24
25 if (auto pgnRequestProtocol = sourceControlFunction->get_pgn_request_protocol().lock())
26 {
27 pgnRequestProtocol->register_pgn_request_callback(static_cast<std::uint32_t>(CANLibParameterGroupNumber::ControlFunctionFunctionalities), pgn_request_handler, this);
28 }
29 else
30 {
31 LOG_ERROR("[DP]: Failed to register PGN request callback for ControlFunctionFunctionalities due to the protocol being expired");
32 }
33 }
34
36 {
37 if (auto pgnRequestProtocol = myControlFunction->get_pgn_request_protocol().lock())
38 {
39 pgnRequestProtocol->remove_pgn_request_callback(static_cast<std::uint32_t>(CANLibParameterGroupNumber::ControlFunctionFunctionalities), pgn_request_handler, this);
40 }
41 }
42
43 void ControlFunctionFunctionalities::set_functionality_is_supported(Functionalities functionality, std::uint8_t functionalityGeneration, bool isSupported)
44 {
45 LOCK_GUARD(Mutex, functionalitiesMutex);
46
47 auto existingFunctionality = get_functionality(functionality);
48
49 if ((supportedFunctionalities.end() == existingFunctionality) && isSupported)
50 {
51 FunctionalityData newFunctionality(functionality);
52 newFunctionality.configure_default_data();
53 newFunctionality.generation = functionalityGeneration;
54 supportedFunctionalities.emplace_back(newFunctionality);
55 }
56 else if ((supportedFunctionalities.end() != existingFunctionality) && (!isSupported))
57 {
58 if (Functionalities::MinimumControlFunction == functionality)
59 {
60 LOG_WARNING("[DP]: You are disabling minimum control function functionality reporting! This is not recommended.");
61 }
62 supportedFunctionalities.erase(existingFunctionality);
63 }
64 }
65
67 {
68 bool retVal = false;
69 LOCK_GUARD(Mutex, functionalitiesMutex);
70
71 auto existingFunctionality = get_functionality(functionality);
72
73 if (supportedFunctionalities.end() != existingFunctionality)
74 {
75 retVal = true;
76 }
77 return retVal;
78 }
79
81 {
82 std::uint8_t retVal = 0;
83
84 auto existingFunctionality = get_functionality(functionality);
85
86 if (supportedFunctionalities.end() != existingFunctionality)
87 {
88 retVal = existingFunctionality->generation;
89 }
90 return retVal;
91 }
92
94 {
95 LOCK_GUARD(Mutex, functionalitiesMutex);
96
97 auto existingFunctionality = get_functionality(Functionalities::MinimumControlFunction);
98
99 if ((supportedFunctionalities.end() != existingFunctionality) &&
100 (option < MinimumControlFunctionOptions::Reserved))
101 {
102 existingFunctionality->set_bit_in_option(0, static_cast<std::uint8_t>(option), optionState);
103 }
104 }
105
107 {
108 return get_functionality_byte_option(Functionalities::MinimumControlFunction, 0, static_cast<std::uint8_t>(option));
109 }
110
112 {
113 LOCK_GUARD(Mutex, functionalitiesMutex);
114
115 auto existingFunctionality = get_functionality(Functionalities::AuxOInputs);
116
117 if ((supportedFunctionalities.end() != existingFunctionality) &&
118 (option < AuxOOptions::Reserved))
119 {
120 existingFunctionality->set_bit_in_option(0, static_cast<std::uint8_t>(option), optionState);
121 }
122 }
123
125 {
126 return get_functionality_byte_option(Functionalities::AuxOInputs, 0, static_cast<std::uint8_t>(option));
127 }
128
130 {
131 LOCK_GUARD(Mutex, functionalitiesMutex);
132
133 auto existingFunctionality = get_functionality(Functionalities::AuxOFunctions);
134
135 if ((supportedFunctionalities.end() != existingFunctionality) &&
136 (option < AuxOOptions::Reserved))
137 {
138 existingFunctionality->set_bit_in_option(0, static_cast<std::uint8_t>(option), optionState);
139 }
140 }
141
143 {
144 return get_functionality_byte_option(Functionalities::AuxOFunctions, 0, static_cast<std::uint8_t>(option));
145 }
146
148 {
149 LOCK_GUARD(Mutex, functionalitiesMutex);
150
151 auto existingFunctionality = get_functionality(Functionalities::AuxNInputs);
152
153 if ((supportedFunctionalities.end() != existingFunctionality) &&
154 (option < AuxNOptions::Reserved))
155 {
156 existingFunctionality->set_bit_in_option(option > AuxNOptions::SupportsType7Function ? 1 : 0,
157 option > AuxNOptions::SupportsType7Function ? static_cast<std::uint8_t>(static_cast<std::uint16_t>(option) >> 8) : static_cast<std::uint8_t>(option),
158 optionState);
159 }
160 }
161
163 {
164 return get_functionality_byte_option(Functionalities::AuxNInputs, 0, static_cast<std::uint8_t>(option));
165 }
166
168 {
169 LOCK_GUARD(Mutex, functionalitiesMutex);
170
171 auto existingFunctionality = get_functionality(Functionalities::AuxNFunctions);
172
173 if ((supportedFunctionalities.end() != existingFunctionality) &&
174 (option < AuxNOptions::Reserved))
175 {
176 existingFunctionality->set_bit_in_option(option > AuxNOptions::SupportsType7Function ? 1 : 0,
177 option > AuxNOptions::SupportsType7Function ? static_cast<std::uint8_t>(static_cast<std::uint16_t>(option) >> 8) : static_cast<std::uint8_t>(option),
178 optionState);
179 }
180 }
181
183 {
184 return get_functionality_byte_option(Functionalities::AuxNFunctions, 0, static_cast<std::uint8_t>(option));
185 }
186
188 {
189 LOCK_GUARD(Mutex, functionalitiesMutex);
190
191 auto existingFunctionality = get_functionality(Functionalities::TaskControllerGeoServer);
192
193 if ((supportedFunctionalities.end() != existingFunctionality) &&
194 (option < TaskControllerGeoServerOptions::Reserved))
195 {
196 existingFunctionality->set_bit_in_option(0, static_cast<std::uint8_t>(option), optionState);
197 }
198 }
199
201 {
202 return get_functionality_byte_option(Functionalities::TaskControllerGeoServer, 0, static_cast<std::uint8_t>(option));
203 }
204
206 {
207 LOCK_GUARD(Mutex, functionalitiesMutex);
208
209 auto existingFunctionality = get_functionality(Functionalities::TaskControllerGeoClient);
210
211 if ((supportedFunctionalities.end() != existingFunctionality) &&
212 (numberOfControlChannels > 0))
213 {
214 existingFunctionality->serializedValue.at(0) = numberOfControlChannels;
215 }
216 }
217
219 {
220 LOCK_GUARD(Mutex, functionalitiesMutex);
221 auto existingFunctionality = get_functionality(Functionalities::TaskControllerGeoClient);
222 std::uint8_t retVal = 0;
223
224 if (supportedFunctionalities.end() != existingFunctionality)
225 {
226 retVal = existingFunctionality->serializedValue.at(0);
227 }
228 return retVal;
229 }
230
231 void ControlFunctionFunctionalities::set_task_controller_section_control_server_option_state(std::uint8_t numberOfSupportedBooms, std::uint8_t numberOfSupportedSections)
232 {
233 LOCK_GUARD(Mutex, functionalitiesMutex);
234
235 auto existingFunctionality = get_functionality(Functionalities::TaskControllerSectionControlServer);
236
237 if ((supportedFunctionalities.end() != existingFunctionality) &&
238 (numberOfSupportedBooms > 0) &&
239 (numberOfSupportedSections > 0))
240 {
241 existingFunctionality->serializedValue.at(0) = numberOfSupportedBooms;
242 existingFunctionality->serializedValue.at(1) = numberOfSupportedSections;
243 }
244 }
245
247 {
248 LOCK_GUARD(Mutex, functionalitiesMutex);
249 auto existingFunctionality = get_functionality(Functionalities::TaskControllerSectionControlServer);
250 std::uint8_t retVal = 0;
251
252 if (supportedFunctionalities.end() != existingFunctionality)
253 {
254 retVal = existingFunctionality->serializedValue.at(0);
255 }
256 return retVal;
257 }
258
260 {
261 LOCK_GUARD(Mutex, functionalitiesMutex);
262 auto existingFunctionality = get_functionality(Functionalities::TaskControllerSectionControlServer);
263 std::uint8_t retVal = 0;
264
265 if (supportedFunctionalities.end() != existingFunctionality)
266 {
267 retVal = existingFunctionality->serializedValue.at(1);
268 }
269 return retVal;
270 }
271
272 void ControlFunctionFunctionalities::set_task_controller_section_control_client_option_state(std::uint8_t numberOfSupportedBooms, std::uint8_t numberOfSupportedSections)
273 {
274 LOCK_GUARD(Mutex, functionalitiesMutex);
275
276 auto existingFunctionality = get_functionality(Functionalities::TaskControllerSectionControlClient);
277
278 if ((supportedFunctionalities.end() != existingFunctionality) &&
279 (numberOfSupportedBooms > 0) &&
280 (numberOfSupportedSections > 0))
281 {
282 existingFunctionality->serializedValue.at(0) = numberOfSupportedBooms;
283 existingFunctionality->serializedValue.at(1) = numberOfSupportedSections;
284 }
285 }
286
288 {
289 LOCK_GUARD(Mutex, functionalitiesMutex);
290 auto existingFunctionality = get_functionality(Functionalities::TaskControllerSectionControlClient);
291 std::uint8_t retVal = 0;
292
293 if (supportedFunctionalities.end() != existingFunctionality)
294 {
295 retVal = existingFunctionality->serializedValue.at(0);
296 }
297 return retVal;
298 }
299
301 {
302 LOCK_GUARD(Mutex, functionalitiesMutex);
303 auto existingFunctionality = get_functionality(Functionalities::TaskControllerSectionControlClient);
304 std::uint8_t retVal = 0;
305
306 if (supportedFunctionalities.end() != existingFunctionality)
307 {
308 retVal = existingFunctionality->serializedValue.at(1);
309 }
310 return retVal;
311 }
312
314 {
315 LOCK_GUARD(Mutex, functionalitiesMutex);
316
317 auto existingFunctionality = get_functionality(Functionalities::BasicTractorECUServer);
318
319 if ((supportedFunctionalities.end() != existingFunctionality) &&
320 (option < BasicTractorECUOptions::Reserved))
321 {
322 existingFunctionality->set_bit_in_option(0, static_cast<std::uint8_t>(option), optionState);
323 }
324 }
325
327 {
328 bool retVal = false;
329
330 // This one is handled differently to handle the 0 value
331 if (BasicTractorECUOptions::TECUNotMeetingCompleteClass1Requirements == option)
332 {
333 LOCK_GUARD(Mutex, functionalitiesMutex);
334 auto existingFunctionality = get_functionality(Functionalities::BasicTractorECUServer);
335
336 if (supportedFunctionalities.end() != existingFunctionality)
337 {
338 retVal = (0 == existingFunctionality->serializedValue.at(0));
339 }
340 }
341 else
342 {
343 retVal = get_functionality_byte_option(Functionalities::BasicTractorECUServer, 0, static_cast<std::uint8_t>(option));
344 }
345 return retVal;
346 }
347
349 {
350 LOCK_GUARD(Mutex, functionalitiesMutex);
351
352 auto existingFunctionality = get_functionality(Functionalities::BasicTractorECUImplementClient);
353
354 if ((supportedFunctionalities.end() != existingFunctionality) &&
355 (option < BasicTractorECUOptions::Reserved))
356 {
357 existingFunctionality->set_bit_in_option(0, static_cast<std::uint8_t>(option), optionState);
358 }
359 }
360
362 {
363 bool retVal = false;
364
365 // This one is handled differently to handle the 0 value
366 if (BasicTractorECUOptions::TECUNotMeetingCompleteClass1Requirements == option)
367 {
368 LOCK_GUARD(Mutex, functionalitiesMutex);
369 auto existingFunctionality = get_functionality(Functionalities::BasicTractorECUImplementClient);
370
371 if (supportedFunctionalities.end() != existingFunctionality)
372 {
373 retVal = (0 == existingFunctionality->serializedValue.at(0));
374 }
375 }
376 else
377 {
378 retVal = get_functionality_byte_option(Functionalities::BasicTractorECUImplementClient, 0, static_cast<std::uint8_t>(option));
379 }
380 return retVal;
381 }
382
384 {
385 LOCK_GUARD(Mutex, functionalitiesMutex);
386
387 auto existingFunctionality = get_functionality(Functionalities::TractorImplementManagementServer);
388
389 if (supportedFunctionalities.end() != existingFunctionality)
390 {
391 if (TractorImplementManagementOptions::NoOptions != option)
392 {
393 existingFunctionality->set_bit_in_option(get_tim_option_byte_index(option), 1 << get_tim_option_bit_index(option), optionState);
394 }
395 else
396 {
397 LOG_DEBUG("[DP]: Can't set the No Options TIM option, disable the other ones instead.");
398 }
399 }
400 }
401
403 {
404 bool retVal = true;
405
406 if (TractorImplementManagementOptions::NoOptions == option)
407 {
408 LOCK_GUARD(Mutex, functionalitiesMutex);
409 auto existingFunctionality = get_functionality(Functionalities::TractorImplementManagementServer);
410
411 if (supportedFunctionalities.end() != existingFunctionality)
412 {
413 for (const auto &currentByte : existingFunctionality->serializedValue)
414 {
415 retVal &= (0 == currentByte);
416 }
417 }
418 }
419 else
420 {
421 retVal = get_functionality_byte_option(Functionalities::TractorImplementManagementServer, get_tim_option_byte_index(option), 1 << get_tim_option_bit_index(option));
422 }
423 return retVal;
424 }
425
426 void ControlFunctionFunctionalities::set_tractor_implement_management_server_aux_valve_option(std::uint8_t auxValveIndex, bool stateSupported, bool flowSupported)
427 {
428 LOCK_GUARD(Mutex, functionalitiesMutex);
429
430 auto existingFunctionality = get_functionality(Functionalities::TractorImplementManagementServer);
431
432 if ((supportedFunctionalities.end() != existingFunctionality) && (auxValveIndex < NUMBER_TIM_AUX_VALVES))
433 {
434 existingFunctionality->set_bit_in_option(auxValveIndex / 4, 1 << (2 * (auxValveIndex % 4)), stateSupported);
435 existingFunctionality->set_bit_in_option(auxValveIndex / 4, 1 << (2 * (auxValveIndex % 4) + 1), flowSupported);
436 }
437 }
438
440 {
441 LOCK_GUARD(Mutex, functionalitiesMutex);
442 bool retVal = false;
443
444 auto existingFunctionality = get_functionality(Functionalities::TractorImplementManagementServer);
445
446 if ((supportedFunctionalities.end() != existingFunctionality) && (auxValveIndex < NUMBER_TIM_AUX_VALVES))
447 {
448 retVal = existingFunctionality->get_bit_in_option(auxValveIndex / 4, 1 << (2 * (auxValveIndex % 4)));
449 }
450 return retVal;
451 }
452
454 {
455 LOCK_GUARD(Mutex, functionalitiesMutex);
456 bool retVal = false;
457
458 auto existingFunctionality = get_functionality(Functionalities::TractorImplementManagementServer);
459
460 if ((supportedFunctionalities.end() != existingFunctionality) && (auxValveIndex < NUMBER_TIM_AUX_VALVES))
461 {
462 retVal = existingFunctionality->get_bit_in_option(auxValveIndex / 4, 1 << (2 * (auxValveIndex % 4) + 1));
463 }
464 return retVal;
465 }
466
468 {
469 LOCK_GUARD(Mutex, functionalitiesMutex);
470
471 auto existingFunctionality = get_functionality(Functionalities::TractorImplementManagementClient);
472
473 if (supportedFunctionalities.end() != existingFunctionality)
474 {
475 existingFunctionality->set_bit_in_option(get_tim_option_byte_index(option), 1 << get_tim_option_bit_index(option), optionState);
476 }
477 }
478
480 {
481 bool retVal = true;
482
483 if (TractorImplementManagementOptions::NoOptions == option)
484 {
485 LOCK_GUARD(Mutex, functionalitiesMutex);
486 auto existingFunctionality = get_functionality(Functionalities::TractorImplementManagementClient);
487
488 if (supportedFunctionalities.end() != existingFunctionality)
489 {
490 for (const auto &currentByte : existingFunctionality->serializedValue)
491 {
492 retVal &= (0 == currentByte);
493 }
494 }
495 }
496 else
497 {
498 std::uint8_t optionBit = get_tim_option_bit_index(option);
499
500 if (optionBit < std::numeric_limits<std::uint8_t>::digits)
501 {
502 retVal = get_functionality_byte_option(Functionalities::TractorImplementManagementClient, get_tim_option_byte_index(option), 1 << get_tim_option_bit_index(option));
503 }
504 else
505 {
506 // This should be impossible, if you see this please report a bug on our GitHub.
507 // Generally this means that a new TIM option was added but not considered in get_tim_option_bit_index.
508 assert(false);
509 retVal = false;
510 }
511 }
512 return retVal;
513 }
514
515 void ControlFunctionFunctionalities::set_tractor_implement_management_client_aux_valve_option(std::uint8_t auxValveIndex, bool stateSupported, bool flowSupported)
516 {
517 LOCK_GUARD(Mutex, functionalitiesMutex);
518 auto existingFunctionality = get_functionality(Functionalities::TractorImplementManagementClient);
519
520 if ((supportedFunctionalities.end() != existingFunctionality) && (auxValveIndex < NUMBER_TIM_AUX_VALVES))
521 {
522 existingFunctionality->set_bit_in_option(auxValveIndex / 4, 1 << (2 * (auxValveIndex % 4)), stateSupported);
523 existingFunctionality->set_bit_in_option(auxValveIndex / 4, 1 << (2 * (auxValveIndex % 4) + 1), flowSupported);
524 }
525 }
526
528 {
529 LOCK_GUARD(Mutex, functionalitiesMutex);
530 bool retVal = false;
531
532 auto existingFunctionality = get_functionality(Functionalities::TractorImplementManagementClient);
533
534 if ((supportedFunctionalities.end() != existingFunctionality) && (auxValveIndex < NUMBER_TIM_AUX_VALVES))
535 {
536 retVal = existingFunctionality->get_bit_in_option(auxValveIndex / 4, 1 << (2 * (auxValveIndex % 4)));
537 }
538 return retVal;
539 }
540
542 {
543 LOCK_GUARD(Mutex, functionalitiesMutex);
544 bool retVal = false;
545
546 auto existingFunctionality = get_functionality(Functionalities::TractorImplementManagementClient);
547
548 if ((supportedFunctionalities.end() != existingFunctionality) && (auxValveIndex < NUMBER_TIM_AUX_VALVES))
549 {
550 retVal = existingFunctionality->get_bit_in_option(auxValveIndex / 4, 1 << (2 * (auxValveIndex % 4) + 1));
551 }
552 return retVal;
553 }
554
556 {
557 txFlags.process_all_flags();
558 }
559
561 functionality(functionalityToStore)
562 {
563 }
564
566 {
567 switch (functionality)
568 {
569 case Functionalities::MinimumControlFunction:
570 case Functionalities::UniversalTerminalServer:
571 case Functionalities::UniversalTerminalWorkingSet:
572 case Functionalities::AuxOInputs:
573 case Functionalities::AuxOFunctions:
574 case Functionalities::TaskControllerBasicServer:
575 case Functionalities::TaskControllerBasicClient:
576 case Functionalities::TaskControllerGeoServer:
577 case Functionalities::TaskControllerGeoClient:
578 case Functionalities::BasicTractorECUServer:
579 case Functionalities::BasicTractorECUImplementClient:
580 case Functionalities::FileServer:
581 case Functionalities::FileServerClient:
582 {
583 serializedValue.resize(1);
584 serializedValue.at(0) = 0x00; // No options
585 }
586 break;
587
588 case Functionalities::AuxNInputs:
589 case Functionalities::AuxNFunctions:
590 {
591 serializedValue.resize(2);
592 serializedValue.at(0) = 0x00; // No options
593 serializedValue.at(1) = 0x00; // No options
594 }
595 break;
596
597 case Functionalities::TaskControllerSectionControlServer:
598 case Functionalities::TaskControllerSectionControlClient:
599 {
600 serializedValue.resize(2);
601 serializedValue.at(0) = 0x01; // 1 Boom supported (1 is the minimum)
602 serializedValue.at(1) = 0x01; // 1 Section Supported (1 is the minimum)
603 }
604 break;
605
606 case Functionalities::TractorImplementManagementServer:
607 case Functionalities::TractorImplementManagementClient:
608 {
609 LOG_WARNING("[DP]: You have configured TIM as a CF functionality, but the library doesn't support TIM at this time. Do you have an external TIM implementation?");
610 serializedValue.resize(15); // TIM has a lot of options. https://www.isobus.net/isobus/option
611 std::fill(serializedValue.begin(), serializedValue.end(), 0x00); // Support nothing by default
612 }
613 break;
614
615 default:
616 {
617 LOG_ERROR("[DP]: An invalid control function functionality was added. It's values will be ignored.");
618 }
619 break;
620 }
621 }
622
623 void ControlFunctionFunctionalities::FunctionalityData::set_bit_in_option(std::uint8_t byteIndex, std::uint8_t bit, bool value)
624 {
625 if ((byteIndex < serializedValue.size()) && (bit < std::numeric_limits<std::uint8_t>::max()))
626 {
627 if (value)
628 {
629 serializedValue.at(byteIndex) = (serializedValue.at(byteIndex) | bit);
630 }
631 else
632 {
633 serializedValue.at(byteIndex) = (serializedValue.at(byteIndex) & ~(bit));
634 }
635 }
636 }
637
638 bool ControlFunctionFunctionalities::FunctionalityData::get_bit_in_option(std::uint8_t byteIndex, std::uint8_t bit)
639 {
640 bool retVal = false;
641
642 if ((byteIndex < serializedValue.size()) && (bit < std::numeric_limits<std::uint8_t>::max()))
643 {
644 retVal = (0 != (serializedValue.at(byteIndex) & (bit)));
645 }
646 return retVal;
647 }
648
649 std::list<ControlFunctionFunctionalities::FunctionalityData>::iterator ControlFunctionFunctionalities::get_functionality(Functionalities functionalityToRetrieve)
650 {
651 return std::find_if(supportedFunctionalities.begin(), supportedFunctionalities.end(), [functionalityToRetrieve](const FunctionalityData &currentFunctionality) { return currentFunctionality.functionality == functionalityToRetrieve; });
652 }
653
654 bool ControlFunctionFunctionalities::get_functionality_byte_option(Functionalities functionality, std::uint8_t byteIndex, std::uint8_t option)
655 {
656 LOCK_GUARD(Mutex, functionalitiesMutex);
657 bool retVal = false;
658
659 auto existingFunctionality = get_functionality(functionality);
660
661 if (supportedFunctionalities.end() != existingFunctionality)
662 {
663 retVal = existingFunctionality->get_bit_in_option(byteIndex, option);
664 }
665 return retVal;
666 }
667
668 void ControlFunctionFunctionalities::get_message_content(std::vector<std::uint8_t> &messageData)
669 {
670 LOCK_GUARD(Mutex, functionalitiesMutex);
671 messageData.clear();
672 messageData.reserve(supportedFunctionalities.size() * 4); // Approximate, but pretty close unless you have TIM.
673 messageData.push_back(0xFF); // Each control function shall respond with byte 1 set to FF
674 messageData.push_back(static_cast<std::uint8_t>(supportedFunctionalities.size()));
675
676 for (const auto &functionality : supportedFunctionalities)
677 {
678 messageData.push_back(static_cast<std::uint8_t>(functionality.functionality));
679 messageData.push_back(functionality.generation);
680 messageData.push_back(static_cast<std::uint8_t>(functionality.serializedValue.size()));
681
682 for (const auto &dataByte : functionality.serializedValue)
683 {
684 messageData.push_back(dataByte);
685 }
686 }
687
688 while (messageData.size() < CAN_DATA_LENGTH)
689 {
690 messageData.push_back(0xFF);
691 }
692 }
693
695 {
696 std::uint8_t retVal = 0xFF;
697
698 switch (option)
699 {
700 case TractorImplementManagementOptions::FrontPTODisengagementIsSupported:
701 case TractorImplementManagementOptions::FrontPTOEngagementCCWIsSupported:
702 case TractorImplementManagementOptions::FrontPTOengagementCWIsSupported:
703 case TractorImplementManagementOptions::FrontPTOspeedCCWIsSupported:
704 case TractorImplementManagementOptions::FrontPTOspeedCWIsSupported:
705 {
706 retVal = 9;
707 }
708 break;
709
710 case TractorImplementManagementOptions::RearPTODisengagementIsSupported:
711 case TractorImplementManagementOptions::RearPTOEngagementCCWIsSupported:
712 case TractorImplementManagementOptions::RearPTOEngagementCWIsSupported:
713 case TractorImplementManagementOptions::RearPTOSpeedCCWIsSupported:
714 case TractorImplementManagementOptions::RearPTOSpeedCWIsSupported:
715 {
716 retVal = 10;
717 }
718 break;
719
720 case TractorImplementManagementOptions::FrontHitchMotionIsSupported:
721 case TractorImplementManagementOptions::FrontHitchPositionIsSupported:
722 {
723 retVal = 11;
724 }
725 break;
726
727 case TractorImplementManagementOptions::RearHitchMotionIsSupported:
728 case TractorImplementManagementOptions::RearHitchPositionIsSupported:
729 {
730 retVal = 12;
731 }
732 break;
733
734 case TractorImplementManagementOptions::VehicleSpeedInForwardDirectionIsSupported:
735 case TractorImplementManagementOptions::VehicleSpeedInReverseDirectionIsSupported:
736 case TractorImplementManagementOptions::VehicleSpeedStartMotionIsSupported:
737 case TractorImplementManagementOptions::VehicleSpeedStopMotionIsSupported:
738 case TractorImplementManagementOptions::VehicleSpeedForwardSetByServerIsSupported:
739 case TractorImplementManagementOptions::VehicleSpeedReverseSetByServerIsSupported:
740 case TractorImplementManagementOptions::VehicleSpeedChangeDirectionIsSupported:
741 {
742 retVal = 13;
743 }
744 break;
745
746 case TractorImplementManagementOptions::GuidanceCurvatureIsSupported:
747 {
748 retVal = 14;
749 }
750 break;
751
752 default:
753 {
754 // Option not handled. This is normal for NoOption but others should be considered.
755 }
756 break;
757 }
758 return retVal;
759 }
760
762 {
763 std::uint8_t retVal = 0xFF;
764
765 switch (option)
766 {
767 case TractorImplementManagementOptions::FrontPTODisengagementIsSupported:
768 case TractorImplementManagementOptions::RearPTODisengagementIsSupported:
769 case TractorImplementManagementOptions::FrontHitchMotionIsSupported:
770 case TractorImplementManagementOptions::RearHitchMotionIsSupported:
771 case TractorImplementManagementOptions::VehicleSpeedInForwardDirectionIsSupported:
772 case TractorImplementManagementOptions::GuidanceCurvatureIsSupported:
773 {
774 retVal = 0;
775 }
776 break;
777
778 case TractorImplementManagementOptions::FrontPTOEngagementCCWIsSupported:
779 case TractorImplementManagementOptions::RearPTOEngagementCCWIsSupported:
780 case TractorImplementManagementOptions::VehicleSpeedInReverseDirectionIsSupported:
781 {
782 retVal = 1;
783 }
784 break;
785
786 case TractorImplementManagementOptions::FrontHitchPositionIsSupported:
787 case TractorImplementManagementOptions::RearHitchPositionIsSupported:
788 case TractorImplementManagementOptions::VehicleSpeedStartMotionIsSupported:
789 {
790 retVal = 2;
791 }
792 break;
793
794 case TractorImplementManagementOptions::FrontPTOengagementCWIsSupported:
795 case TractorImplementManagementOptions::RearPTOEngagementCWIsSupported:
796 case TractorImplementManagementOptions::VehicleSpeedStopMotionIsSupported:
797 {
798 retVal = 3;
799 }
800 break;
801
802 case TractorImplementManagementOptions::FrontPTOspeedCCWIsSupported:
803 case TractorImplementManagementOptions::RearPTOSpeedCCWIsSupported:
804 case TractorImplementManagementOptions::VehicleSpeedForwardSetByServerIsSupported:
805 {
806 retVal = 4;
807 }
808 break;
809
810 case TractorImplementManagementOptions::FrontPTOspeedCWIsSupported:
811 case TractorImplementManagementOptions::RearPTOSpeedCWIsSupported:
812 case TractorImplementManagementOptions::VehicleSpeedReverseSetByServerIsSupported:
813 {
814 retVal = 5;
815 }
816 break;
817
818 case TractorImplementManagementOptions::VehicleSpeedChangeDirectionIsSupported:
819 {
820 retVal = 6;
821 }
822 break;
823
824 default:
825 {
826 // Option not handled. This is normal for NoOption but others should be considered.
827 }
828 break;
829 }
830 return retVal;
831 }
832
833 bool ControlFunctionFunctionalities::pgn_request_handler(std::uint32_t parameterGroupNumber,
834 std::shared_ptr<ControlFunction>,
835 bool &acknowledge,
837 void *parentPointer)
838 {
839 assert(nullptr != parentPointer);
840 auto targetInterface = static_cast<ControlFunctionFunctionalities *>(parentPointer);
841 bool retVal = false;
842
843 if (static_cast<std::uint32_t>(CANLibParameterGroupNumber::ControlFunctionFunctionalities) == parameterGroupNumber)
844 {
845 acknowledge = false;
846 targetInterface->txFlags.set_flag(static_cast<std::uint32_t>(TransmitFlags::ControlFunctionFunctionalitiesMessage));
847 retVal = true;
848 }
849 return retVal;
850 }
851
852 void ControlFunctionFunctionalities::process_flags(std::uint32_t flag, void *parentPointer)
853 {
854 assert(nullptr != parentPointer);
855 auto targetInterface = static_cast<ControlFunctionFunctionalities *>(parentPointer);
856 bool transmitSuccessful = true;
857
858 if (static_cast<std::uint32_t>(TransmitFlags::ControlFunctionFunctionalitiesMessage) == flag)
859 {
860 std::vector<std::uint8_t> messageBuffer;
861 targetInterface->get_message_content(messageBuffer);
862 transmitSuccessful = CANNetworkManager::CANNetwork.send_can_message(static_cast<std::uint32_t>(CANLibParameterGroupNumber::ControlFunctionFunctionalities),
863 messageBuffer.data(),
864 messageBuffer.size(),
865 targetInterface->myControlFunction,
866 nullptr);
867 }
868
869 if (!transmitSuccessful)
870 {
871 targetInterface->txFlags.set_flag(flag);
872 }
873 }
874} // namespace isobus
Defines some PGNs that are used in the library or are very common.
A class that acts as a logging sink. The intent is that someone could make their own derived class of...
static CANNetworkManager CANNetwork
Static singleton of the one network manager. Use this to access stack functionality.
bool send_can_message(std::uint32_t parameterGroupNumber, const std::uint8_t *dataBuffer, std::uint32_t dataLength, std::shared_ptr< InternalControlFunction > sourceControlFunction, std::shared_ptr< ControlFunction > destinationControlFunction=nullptr, CANIdentifier::CANPriority priority=CANIdentifier::CANPriority::PriorityDefault6, TransmitCompleteCallback txCompleteCallback=nullptr, void *parentPointer=nullptr, DataChunkCallback frameChunkCallback=nullptr)
This is the main way to send a CAN message of any length.
Stores the raw byte data associated with a functionality based on what the user has enabled and what ...
void configure_default_data()
Sets up default data associated to the functionality the object is representing.
bool get_bit_in_option(std::uint8_t byteIndex, std::uint8_t bit)
A helper function to get a particular bit's value in the specified option byte.
void set_bit_in_option(std::uint8_t byteIndex, std::uint8_t bit, bool value)
A helper function to set a particular option bit to some value within an option byte.
FunctionalityData(Functionalities functionalityToStore)
Constructor for a FunctionalityData object.
std::uint8_t generation
The generation of the functionality supported.
Manages the control function functionalities message.
void set_tractor_implement_management_client_option_state(TractorImplementManagementOptions option, bool optionState)
Sets a tractor implement management (TIM) client functionality option to a new state.
TractorImplementManagementOptions
This parameter reports which TIM options are supported by a TIM server or an implement working set ma...
bool get_functionality_is_supported(Functionalities functionality)
Returns if a functionality was previously configured with set_functionality_is_supported.
BasicTractorECUOptions
This parameter reports which tractor ECU class and functionality options are supported by an implemen...
std::uint8_t get_task_controller_section_control_client_number_supported_sections()
Gets the number of supported sections for the TC section control client functionality.
ProcessingFlags txFlags
Handles retries for sending the CF functionalities message.
std::list< FunctionalityData >::iterator get_functionality(Functionalities functionalityToRetrieve)
Checks for the existence of a functionality in the list of previously configured functionalities and ...
std::list< FunctionalityData > supportedFunctionalities
A list of all configured functionalities and their data.
TaskControllerGeoServerOptions
This option byte reports which task controller geo functionality options are supported by an implemen...
void set_functionality_is_supported(Functionalities functionality, std::uint8_t functionalityGeneration, bool isSupported)
Adds or removes a supported functionality.
std::uint8_t get_task_controller_section_control_client_number_supported_booms()
Gets the number of supported booms for the TC section control client functionality.
void set_basic_tractor_ECU_server_option_state(BasicTractorECUOptions option, bool optionState)
Sets a tractor ECU server functionality option to a new state.
static void process_flags(std::uint32_t flag, void *parentPointer)
Processes set transmit flags to send messages.
void set_task_controller_section_control_client_option_state(std::uint8_t numberOfSupportedBooms, std::uint8_t numberOfSupportedSections)
Sets a task controller section control client's options.
static bool pgn_request_handler(std::uint32_t parameterGroupNumber, std::shared_ptr< ControlFunction > requestingControlFunction, bool &acknowledge, AcknowledgementType &acknowledgeType, void *parentPointer)
Handles PGN requests for the control function functionalities message.
bool get_tractor_implement_management_client_option_state(TractorImplementManagementOptions option)
Gets the state of a TIM client functionality option.
bool get_functionality_byte_option(Functionalities functionality, std::uint8_t byteIndex, std::uint8_t option)
A wrapper to to get an option from the first byte of a functionalities' data.
bool get_aux_N_inputs_option_state(AuxNOptions option)
Gets the state of an AUX-N inputs functionality option.
bool get_tractor_implement_management_server_aux_valve_flow_supported(std::uint8_t auxValveIndex)
Returns if a particular aux valve's flow control is supported in the TIM server functionality.
void set_aux_O_inputs_option_state(AuxOOptions option, bool optionState)
Sets an AUX-O inputs functionality option to a new state.
std::uint8_t get_task_controller_section_control_server_number_supported_sections()
Gets the number of supported sections for the TC section control server functionality.
bool get_basic_tractor_ECU_server_option_state(BasicTractorECUOptions option)
Gets the state of a basic tractor ECU server functionality option.
std::uint8_t get_tim_option_byte_index(TractorImplementManagementOptions option) const
Returns the byte index of the specified TIM option in the CF Functionalities message data associated ...
void set_task_controller_geo_client_option(std::uint8_t numberOfControlChannels)
Sets a task controller geo client's only functionality option, which is the number of control channel...
bool get_aux_N_functions_option_state(AuxNOptions option)
Gets the state of an AUX-N functions functionality option.
void set_aux_N_functions_option_state(AuxNOptions option, bool optionState)
Sets an AUX-N functions functionality option to a new state.
void set_tractor_implement_management_client_aux_valve_option(std::uint8_t auxValveIndex, bool stateSupported, bool flowSupported)
Sets a tractor implement management (TIM) client aux valve's functionality options to a new state.
std::uint8_t get_task_controller_geo_client_option()
Gets the state of the only TC GEO client functionality option, which is the number of control channel...
Mutex functionalitiesMutex
Since messages come in on a different thread than the main app (probably), this mutex protects the fu...
Functionalities
Enumerates the different functionalities that an ISOBUS ECU can report in the control function functi...
std::uint8_t get_tim_option_bit_index(TractorImplementManagementOptions option) const
Returns the bit offset of a specified TIM functionality option into the TIM client and server functio...
void set_tractor_implement_management_server_aux_valve_option(std::uint8_t auxValveIndex, bool stateSupported, bool flowSupported)
Sets a tractor implement management (TIM) server aux valve's functionality options to a new state.
void set_task_controller_section_control_server_option_state(std::uint8_t numberOfSupportedBooms, std::uint8_t numberOfSupportedSections)
Sets a task controller section control server's options.
static constexpr std::uint8_t NUMBER_TIM_AUX_VALVES
The max number of TIM aux valves.
ControlFunctionFunctionalities(std::shared_ptr< InternalControlFunction > sourceControlFunction)
Constructor for a ControlFunctionFunctionalities object.
bool get_tractor_implement_management_server_aux_valve_state_supported(std::uint8_t auxValveIndex)
Returns if a particular aux valve's state control is supported in the TIM server functionality.
bool get_aux_O_functions_option_state(AuxOOptions option)
Gets the state of an AUX-O functions functionality option.
std::shared_ptr< InternalControlFunction > myControlFunction
The control function to send messages as.
bool get_tractor_implement_management_client_aux_valve_state_supported(std::uint8_t auxValveIndex)
Returns if a particular aux valve's state control is supported in the TIM client functionality.
bool get_tractor_implement_management_client_aux_valve_flow_supported(std::uint8_t auxValveIndex)
Returns if a particular aux valve's flow control is supported in the TIM client functionality.
bool get_minimum_control_function_option_state(MinimumControlFunctionOptions option)
Returns the current state of the specified minimum control function functionality option.
void set_task_controller_geo_server_option_state(TaskControllerGeoServerOptions option, bool optionState)
Sets a task controller geo server functionality option to a new state.
std::uint8_t get_task_controller_section_control_server_number_supported_booms()
Gets the number of supported booms for the TC section control server functionality.
void set_minimum_control_function_option_state(MinimumControlFunctionOptions option, bool optionState)
Sets a minimum control function functionality option to a new state.
bool get_basic_tractor_ECU_implement_client_option_state(BasicTractorECUOptions option)
Gets the state of a basic tractor ECU implement client functionality option.
MinimumControlFunctionOptions
This parameter reports which minimum control function functionality options are supported.
~ControlFunctionFunctionalities()
Destructor for a ControlFunctionFunctionalities object.
AuxNOptions
This parameter reports which auxiliary control type 2 functionality type functions are supported by a...
bool get_aux_O_inputs_option_state(AuxOOptions option)
Gets the state of an AUX-O inputs functionality option.
bool get_tractor_implement_management_server_option_state(TractorImplementManagementOptions option)
Gets the state of a basic tractor implement management client functionality option.
void set_basic_tractor_ECU_implement_client_option_state(BasicTractorECUOptions option, bool optionState)
Sets a tractor ECU client functionality option to a new state.
void set_aux_O_functions_option_state(AuxOOptions option, bool optionState)
Sets an AUX-O functions functionality option to a new state.
void set_tractor_implement_management_server_option_state(TractorImplementManagementOptions option, bool optionState)
Sets a tractor implement management (TIM) server functionality option to a new state.
void get_message_content(std::vector< std::uint8_t > &messageData)
Populates a vector with the message data needed to send PGN 0xFC8E.
AuxOOptions
This parameter reports which auxiliary control type 1 functionality type functions are supported by a...
std::uint8_t get_functionality_generation(Functionalities functionality)
Returns the generation that was set for the specified functionality when set_functionality_is_support...
void set_aux_N_inputs_option_state(AuxNOptions option, bool optionState)
Sets an AUX-N inputs functionality option to a new state.
void update()
The diagnostic protocol will call this update function, make sure to call DiagnosticProtocol::update(...
bool get_task_controller_geo_server_option_state(TaskControllerGeoServerOptions option)
Gets the state of a TC GEO server functionality option.
TransmitFlags
Enumerates a set of flags representing messages to be transmitted by this interfaces.
@ ControlFunctionFunctionalitiesMessage
A flag to send the CF Functionalities message.
Defines a class that manages the control function functionalities message data. (PGN 64654,...
This namespace encompasses all of the ISO11783 stack's functionality to reduce global namespace pollu...
constexpr std::uint8_t CAN_DATA_LENGTH
The length of a classical CAN frame.
AcknowledgementType
The types of acknowledgement that can be sent in the Ack PGN.