357 if ((
nullptr != binaryPool) && (0 != binaryPoolSizeBytes))
359 LOG_DEBUG(
"[DDOP]: Attempting to deserialize a binary object pool with size %u.", binaryPoolSizeBytes);
364 while (0 != binaryPoolSizeBytes)
367 if (binaryPoolSizeBytes > 3)
369 std::string xmlNameSpace;
370 xmlNameSpace.push_back(
static_cast<char>(binaryPool[0]));
371 xmlNameSpace.push_back(
static_cast<char>(binaryPool[1]));
372 xmlNameSpace.push_back(
static_cast<char>(binaryPool[2]));
374 if (
"DVC" == xmlNameSpace)
377 std::uint8_t numberDesignatorBytes = 0;
378 std::uint8_t numberSoftwareVersionBytes = 0;
379 std::uint8_t numberDeviceSerialNumberBytes = 0;
380 std::uint8_t numberExtendedStructureLabelBytes = 0;
382 if ((binaryPoolSizeBytes >= 6) &&
383 (binaryPool[5] < 128))
385 numberDesignatorBytes = binaryPool[5];
389 LOG_ERROR(
"[DDOP]: Binary device object designator has invalid length.");
393 if ((binaryPoolSizeBytes >=
static_cast<std::uint32_t
>(7 + numberDesignatorBytes)) &&
394 (binaryPool[6 + numberDesignatorBytes] < 128))
396 numberSoftwareVersionBytes = binaryPool[6 + numberDesignatorBytes];
400 LOG_ERROR(
"[DDOP]: Binary device object software version has invalid length.");
404 if ((binaryPoolSizeBytes >=
static_cast<std::uint32_t
>(16 + numberDesignatorBytes + numberSoftwareVersionBytes)) &&
405 (binaryPool[15 + numberDesignatorBytes + numberSoftwareVersionBytes] < 128))
407 numberDeviceSerialNumberBytes = binaryPool[15 + numberDesignatorBytes + numberSoftwareVersionBytes];
411 LOG_ERROR(
"[DDOP]: Binary device object serial number has invalid length.");
417 if ((binaryPoolSizeBytes >=
static_cast<std::uint32_t
>(31 + numberDeviceSerialNumberBytes + numberDesignatorBytes + numberSoftwareVersionBytes)) &&
418 (binaryPool[30 + numberDeviceSerialNumberBytes + numberDesignatorBytes + numberSoftwareVersionBytes] <= 32))
420 numberExtendedStructureLabelBytes = binaryPool[30 + numberDeviceSerialNumberBytes + numberDesignatorBytes + numberSoftwareVersionBytes];
424 LOG_ERROR(
"[DDOP]: Binary device object with version 4 contains invalid extended structure label length.");
429 std::uint32_t expectedSize = (31 + numberDeviceSerialNumberBytes + numberDesignatorBytes + numberSoftwareVersionBytes + numberExtendedStructureLabelBytes);
436 if ((binaryPoolSizeBytes >= expectedSize) && retVal)
438 std::string deviceDesignator;
439 std::string deviceSoftwareVersion;
440 std::string deviceSerialNumber;
441 std::string deviceStructureLabel;
442 std::array<std::uint8_t, 7> localizationLabel;
443 std::vector<std::uint8_t> extendedStructureLabel;
444 std::uint64_t ddopClientNAME = 0;
446 for (std::uint16_t i = 0; i < numberDesignatorBytes; i++)
448 deviceDesignator.push_back(binaryPool[6 + i]);
451 for (std::uint16_t i = 0; i < numberSoftwareVersionBytes; i++)
453 deviceSoftwareVersion.push_back(binaryPool[7 + numberDesignatorBytes + i]);
456 for (std::uint8_t i = 0; i < 8; i++)
458 std::uint64_t currentNameByte = binaryPool[7 + numberDesignatorBytes + numberSoftwareVersionBytes + i];
459 ddopClientNAME |= (currentNameByte << (8 * i));
464 LOG_ERROR(
"[DDOP]: Failed adding deserialized device object. DDOP NAME doesn't match client's actual NAME.");
472 for (std::uint16_t i = 0; i < numberDeviceSerialNumberBytes; i++)
474 deviceSerialNumber.push_back(binaryPool[16 + numberDesignatorBytes + numberSoftwareVersionBytes + i]);
477 for (std::uint16_t i = 0; i < 7; i++)
479 deviceStructureLabel.push_back(binaryPool[16 + numberDeviceSerialNumberBytes + numberDesignatorBytes + numberSoftwareVersionBytes + i]);
482 for (std::uint16_t i = 0; i < 7; i++)
484 localizationLabel.at(i) = (binaryPool[23 + numberDeviceSerialNumberBytes + numberDesignatorBytes + numberSoftwareVersionBytes + i]);
487 for (std::uint16_t i = 0; i < numberExtendedStructureLabelBytes; i++)
489 extendedStructureLabel.push_back(binaryPool[31 + numberDeviceSerialNumberBytes + numberDesignatorBytes + numberSoftwareVersionBytes + i]);
492 if (
add_device(deviceDesignator, deviceSoftwareVersion, deviceSerialNumber, deviceStructureLabel, localizationLabel, extendedStructureLabel, clientNAME.
get_full_name()))
494 binaryPoolSizeBytes -= expectedSize;
495 binaryPool += expectedSize;
499 LOG_ERROR(
"[DDOP]: Failed adding deserialized device object. DDOP schema is not valid.");
505 LOG_ERROR(
"[DDOP]: Not enough binary DDOP data left to parse device object. DDOP schema is not valid");
509 else if (
"DET" == xmlNameSpace)
512 std::uint8_t numberDesignatorBytes = 0;
513 std::uint8_t numberOfObjectIDs = 0;
515 if (binaryPoolSizeBytes >= 7)
517 numberDesignatorBytes = binaryPool[6];
521 LOG_ERROR(
"[DDOP]: Binary device element object has invalid length.");
525 if (binaryPoolSizeBytes >=
static_cast<std::uint32_t
>(12 + numberDesignatorBytes))
527 numberOfObjectIDs = binaryPool[11 + numberDesignatorBytes];
531 LOG_ERROR(
"[DDOP]: Binary device element object has invalid length to process referenced object IDs.");
537 LOG_ERROR(
"[DDOP]: Binary device element object has invalid element type.");
541 std::uint32_t expectedSize = (13 + (2 * numberOfObjectIDs) + numberDesignatorBytes);
543 if ((binaryPoolSizeBytes >= expectedSize) && retVal)
545 std::string deviceElementDesignator;
546 std::uint16_t parentObject =
static_cast<std::uint16_t
>(
static_cast<std::uint16_t
>(binaryPool[9 + numberDesignatorBytes]) | (
static_cast<std::uint16_t
>(binaryPool[10 + numberDesignatorBytes]) << 8));
547 std::uint16_t uniqueID =
static_cast<std::uint16_t
>(
static_cast<std::uint16_t
>(binaryPool[3]) | (
static_cast<std::uint16_t
>(binaryPool[4]) << 8));
548 std::uint16_t elementNumber =
static_cast<std::uint16_t
>(binaryPool[7 + numberDesignatorBytes]) | (
static_cast<std::uint16_t
>(binaryPool[8 + numberDesignatorBytes]) << 8);
551 for (std::uint16_t i = 0; i < numberDesignatorBytes; i++)
553 deviceElementDesignator.push_back(binaryPool[7 + i]);
556 if (
add_device_element(deviceElementDesignator, elementNumber, parentObject, type, uniqueID))
558 auto DETObject = std::static_pointer_cast<task_controller_object::DeviceElementObject>(
get_object_by_id(uniqueID));
560 if (
nullptr != DETObject)
562 for (std::uint8_t i = 0; i < numberOfObjectIDs; i++)
564 std::uint16_t childID =
static_cast<std::uint16_t
>(
static_cast<std::uint16_t
>(binaryPool[13 + (2 * i) + numberDesignatorBytes]) | (
static_cast<std::uint16_t
>(binaryPool[14 + (2 * i) + numberDesignatorBytes]) << 8));
565 DETObject->add_reference_to_child_object(childID);
569 binaryPoolSizeBytes -= expectedSize;
570 binaryPool += expectedSize;
574 LOG_ERROR(
"[DDOP]: Failed adding deserialized device element object. DDOP schema is not valid.");
580 LOG_ERROR(
"[DDOP]: Not enough binary DDOP data left to parse device element object. DDOP schema is not valid");
584 else if (
"DPD" == xmlNameSpace)
587 std::uint8_t numberDesignatorBytes = 0;
589 if ((binaryPoolSizeBytes >= 10) &&
590 (binaryPool[9] < 128))
592 numberDesignatorBytes = binaryPool[9];
596 LOG_ERROR(
"[DDOP]: Binary device process data object has invalid length.");
600 std::uint32_t expectedSize = (12 + numberDesignatorBytes);
602 if ((binaryPoolSizeBytes >= expectedSize) && retVal)
604 std::string processDataDesignator;
605 std::uint16_t DDI =
static_cast<std::uint16_t
>(
static_cast<std::uint16_t
>(binaryPool[5]) | (
static_cast<std::uint16_t
>(binaryPool[6]) << 8));
606 std::uint16_t uniqueID =
static_cast<std::uint16_t
>(
static_cast<std::uint16_t
>(binaryPool[3]) | (
static_cast<std::uint16_t
>(binaryPool[4]) << 8));
607 std::uint16_t presentationObjectID =
static_cast<std::uint16_t
>(
static_cast<std::uint16_t
>(binaryPool[10 + numberDesignatorBytes]) | (
static_cast<std::uint16_t
>(binaryPool[11 + numberDesignatorBytes]) << 8));
609 for (std::uint16_t i = 0; i < numberDesignatorBytes; i++)
611 processDataDesignator.push_back(binaryPool[10 + i]);
614 if (
add_device_process_data(processDataDesignator, DDI, presentationObjectID, binaryPool[7], binaryPool[8], uniqueID))
616 binaryPoolSizeBytes -= expectedSize;
617 binaryPool += expectedSize;
621 LOG_ERROR(
"[DDOP]: Failed adding deserialized device process data object. DDOP schema is not valid.");
627 LOG_ERROR(
"[DDOP]: Not enough binary DDOP data left to parse device process data object. DDOP schema is not valid");
631 else if (
"DPT" == xmlNameSpace)
633 std::uint8_t numberDesignatorBytes = 0;
635 if ((binaryPoolSizeBytes >= 12) &&
636 (binaryPool[11] < 128))
638 numberDesignatorBytes = binaryPool[11];
642 LOG_ERROR(
"[DDOP]: Binary device property object has invalid length.");
646 std::uint32_t expectedSize = (14 + numberDesignatorBytes);
648 if ((binaryPoolSizeBytes >= expectedSize) && retVal)
650 std::string designator;
651 std::int32_t propertyValue =
static_cast<std::int32_t
>(binaryPool[7]) |
652 (
static_cast<std::int32_t
>(binaryPool[8]) << 8) |
653 (
static_cast<std::int32_t
>(binaryPool[9]) << 16) |
654 (
static_cast<std::int32_t
>(binaryPool[10]) << 24);
655 std::uint16_t DDI =
static_cast<std::uint16_t
>(
static_cast<std::uint16_t
>(binaryPool[5]) | (
static_cast<std::uint16_t
>(binaryPool[6]) << 8));
656 std::uint16_t uniqueID =
static_cast<std::uint16_t
>(
static_cast<std::uint16_t
>(binaryPool[3]) | (
static_cast<std::uint16_t
>(binaryPool[4]) << 8));
657 std::uint16_t presentationObjectID =
static_cast<std::uint16_t
>(
static_cast<std::uint16_t
>(binaryPool[12 + numberDesignatorBytes]) | (
static_cast<std::uint16_t
>(binaryPool[13 + numberDesignatorBytes]) << 8));
659 for (std::uint16_t i = 0; i < numberDesignatorBytes; i++)
661 designator.push_back(binaryPool[12 + i]);
666 binaryPoolSizeBytes -= expectedSize;
667 binaryPool += expectedSize;
671 LOG_ERROR(
"[DDOP]: Failed adding deserialized device property object. DDOP schema is not valid.");
677 LOG_ERROR(
"[DDOP]: Not enough binary DDOP data left to parse device property object. DDOP schema is not valid");
681 else if (
"DVP" == xmlNameSpace)
683 std::uint8_t numberDesignatorBytes = 0;
685 if ((binaryPoolSizeBytes >= 15) &&
686 (binaryPool[14] < 128))
688 numberDesignatorBytes = binaryPool[14];
692 LOG_ERROR(
"[DDOP]: Binary device value presentation object has invalid length.");
696 std::uint32_t expectedSize = (15 + numberDesignatorBytes);
698 if ((binaryPoolSizeBytes >= expectedSize) && retVal)
700 std::string designator;
701 std::int32_t offset =
static_cast<std::int32_t
>(binaryPool[5]) |
702 (
static_cast<std::int32_t
>(binaryPool[6]) << 8) |
703 (
static_cast<std::int32_t
>(binaryPool[7]) << 16) |
704 (
static_cast<std::int32_t
>(binaryPool[8]) << 24);
705 std::array<std::uint8_t,
sizeof(float)> scaleBytes = {
712 std::uint16_t uniqueID =
static_cast<std::uint16_t
>(
static_cast<std::uint16_t
>(binaryPool[3]) | (
static_cast<std::uint16_t
>(binaryPool[4]) << 8));
716 std::reverse(scaleBytes.begin(), scaleBytes.end());
719 memcpy(&scale, scaleBytes.data(),
sizeof(
float));
721 for (std::uint16_t i = 0; i < numberDesignatorBytes; i++)
723 designator.push_back(binaryPool[15 + i]);
728 binaryPoolSizeBytes -= expectedSize;
729 binaryPool += expectedSize;
733 LOG_ERROR(
"[DDOP]: Failed adding deserialized device value presentation object. DDOP schema is not valid.");
739 LOG_ERROR(
"[DDOP]: Not enough binary DDOP data left to parse device value presentation object. DDOP schema is not valid");
745 LOG_ERROR(
"[DDOP]: Cannot process an unknown XML namespace from binary DDOP. DDOP schema is invalid.");
756 LOG_ERROR(
"[DDOP]: Binary DDOP deserialization aborted.");
764 LOG_ERROR(
"[DDOP]: Cannot deserialize a DDOP with zero length.");
811 resultantString.clear();
815 LOG_WARNING(
"[DDOP]: An XML DDOP is being generated for a TC version that is unsupported. This may cause issues.");
820 std::ostringstream xmlOutput;
821 std::ios initialStreamFormat(NULL);
822 std::size_t numberOfDevices = 1;
823 std::size_t numberOfElements = 1;
824 initialStreamFormat.copyfmt(xmlOutput);
827 xmlOutput <<
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
828 xmlOutput <<
"<ISO11783_TaskData VersionMajor=\"3\" VersionMinor=\"0\" DataTransferOrigin=\"1\">" << std::endl;
831 for (std::size_t i = 0; i <
size(); i++)
835 if ((
nullptr != currentObject) &&
839 auto rootDevice = std::static_pointer_cast<task_controller_object::DeviceObject>(currentObject);
840 xmlOutput <<
"<DVC A=\"DVC-" <<
static_cast<int>(numberOfDevices);
842 xmlOutput <<
"\" B=\"" << rootDevice->get_designator();
843 xmlOutput <<
"\" C=\"" << rootDevice->get_software_version();
844 xmlOutput <<
"\" D=\"" << std::uppercase << std::hex << std::setfill('0') << std::setw(16) << static_cast<unsigned long long int>(rootDevice->get_iso_name());
845 xmlOutput.copyfmt(initialStreamFormat);
846 xmlOutput <<
"\" E=\"" << rootDevice->get_serial_number();
847 xmlOutput <<
"\" F=\"";
849 auto lStructureLabel = rootDevice->get_structure_label();
850 for (std::uint8_t j = 0; j < 7; j++)
852 std::uint8_t structureByte =
static_cast<std::uint8_t
>(lStructureLabel.at(6 - j));
853 xmlOutput << std::uppercase << std::hex << std::setfill('0') << std::setw(2) << static_cast<unsigned int>(structureByte);
856 xmlOutput <<
"\" G=\"";
858 for (std::uint_fast8_t j = 0; j < 7; j++)
860 xmlOutput << std::uppercase << std::hex << std::setfill('0') << std::setw(2) << static_cast<unsigned int>(rootDevice->get_localization_label().at(6 - j));
862 xmlOutput.copyfmt(initialStreamFormat);
863 xmlOutput <<
"\">" << std::endl;
866 for (std::size_t j = 0; j < this->
size(); j++)
870 if ((
nullptr != currentSubObject) &&
873 auto deviceElement = std::static_pointer_cast<task_controller_object::DeviceElementObject>(currentSubObject);
875 xmlOutput <<
"\t<DET A=\"DET-" <<
static_cast<int>(numberOfElements);
877 xmlOutput <<
"\" B=\"" <<
static_cast<int>(deviceElement->get_object_id());
878 xmlOutput <<
"\" C=\"" <<
static_cast<int>(deviceElement->get_type());
879 xmlOutput <<
"\" D=\"" << deviceElement->get_designator();
880 xmlOutput <<
"\" E=\"" <<
static_cast<int>(deviceElement->get_element_number());
881 xmlOutput <<
"\" F=\"" <<
static_cast<int>(deviceElement->get_parent_object());
883 if (deviceElement->get_number_child_objects() > 0)
885 xmlOutput <<
"\">" << std::endl;
888 for (std::uint16_t k = 0; k < deviceElement->get_number_child_objects(); k++)
890 xmlOutput <<
"\t\t<DOR A=\"" <<
static_cast<int>(deviceElement->get_child_object_id(k)) <<
"\"/>" << std::endl;
892 xmlOutput <<
"\t</DET>" << std::endl;
896 xmlOutput <<
"\"/>" << std::endl;
902 for (std::size_t j = 0; j < this->
size(); j++)
906 if ((
nullptr != currentSubObject) &&
909 auto deviceProcessData = std::static_pointer_cast<task_controller_object::DeviceProcessDataObject>(currentSubObject);
911 xmlOutput <<
"\t<DPD A=\"" <<
static_cast<int>(deviceProcessData->get_object_id());
912 xmlOutput <<
"\" B=\"" << std::uppercase << std::hex << std::setfill('0') << std::setw(4) << static_cast<int>(deviceProcessData->get_ddi());
913 xmlOutput.copyfmt(initialStreamFormat);
914 xmlOutput <<
"\" C=\"" <<
static_cast<int>(deviceProcessData->get_properties_bitfield());
915 xmlOutput <<
"\" D=\"" <<
static_cast<int>(deviceProcessData->get_trigger_methods_bitfield());
916 xmlOutput <<
"\" E=\"" << deviceProcessData->get_designator();
917 if (0xFFFF != deviceProcessData->get_device_value_presentation_object_id())
919 xmlOutput <<
"\" F=\"" <<
static_cast<int>(deviceProcessData->get_device_value_presentation_object_id());
921 xmlOutput <<
"\"/>" << std::endl;
926 for (std::size_t j = 0; j < this->
size(); j++)
930 if ((
nullptr != currentSubObject) &&
933 auto deviceProperty = std::static_pointer_cast<task_controller_object::DevicePropertyObject>(currentSubObject);
935 xmlOutput <<
"\t<DPT A=\"" <<
static_cast<int>(deviceProperty->get_object_id());
936 xmlOutput <<
"\" B=\"" << std::uppercase << std::hex << std::setfill('0') << std::setw(4) << static_cast<int>(deviceProperty->get_ddi());
937 xmlOutput.copyfmt(initialStreamFormat);
938 xmlOutput <<
"\" C=\"" <<
static_cast<int>(deviceProperty->get_value());
939 xmlOutput <<
"\" D=\"" << deviceProperty->get_designator();
940 if (0xFFFF != deviceProperty->get_device_value_presentation_object_id())
942 xmlOutput <<
"\" E=\"" <<
static_cast<int>(deviceProperty->get_device_value_presentation_object_id());
944 xmlOutput <<
"\"/>" << std::endl;
949 for (std::size_t j = 0; j < this->
size(); j++)
953 if ((
nullptr != currentSubObject) &&
956 auto deviceValuePresentation = std::static_pointer_cast<task_controller_object::DeviceValuePresentationObject>(currentSubObject);
958 xmlOutput <<
"\t<DVP A=\"" <<
static_cast<int>(deviceValuePresentation->get_object_id());
959 xmlOutput <<
"\" B=\"" <<
static_cast<int>(deviceValuePresentation->get_offset());
960 xmlOutput <<
"\" C=\"" << std::fixed << std::setprecision(6) << deviceValuePresentation->get_scale();
961 xmlOutput.copyfmt(initialStreamFormat);
962 xmlOutput <<
"\" D=\"" <<
static_cast<int>(deviceValuePresentation->get_number_of_decimals());
963 xmlOutput <<
"\" E=\"" << deviceValuePresentation->get_designator();
964 xmlOutput <<
"\"/>" << std::endl;
969 xmlOutput <<
"</DVC>" << std::endl;
970 xmlOutput <<
"</ISO11783_TaskData>" << std::endl;
971 resultantString = xmlOutput.str();
972 LOG_DEBUG(
"[DDOP]: Generated ISO XML DDOP data OK");
979 LOG_ERROR(
"[DDOP]: Failed to resolve all object IDs in DDOP. Your DDOP contains invalid object references.");