2626#include < boost/range/any_range.hpp>
2727#include < boost/range/functions.hpp>
2828#include < boost/range/metafunctions.hpp>
29+ #include < boost/range/numeric.hpp>
2930#include < boost/uuid/uuid.hpp>
3031#include < boost/uuid/uuid_generators.hpp>
3132#include < boost/uuid/uuid_io.hpp>
@@ -76,9 +77,8 @@ namespace mtconnect {
7677 m_context (context),
7778 m_strand(m_context),
7879 m_xmlParser(make_unique<parser::XmlParser>()),
79- m_version(
80- GetOption<string>(options, config::SchemaVersion)
81- .value_or(to_string(AGENT_VERSION_MAJOR) + "." + to_string(AGENT_VERSION_MINOR))),
80+ m_schemaVersion(
81+ GetOption<string>(options, config::SchemaVersion)),
8282 m_deviceXmlPath(deviceXmlPath),
8383 m_circularBuffer(GetOption<int >(options, config::BufferSize).value_or(17 ),
8484 GetOption<int>(options, config::CheckpointFrequency).value_or(1000 )),
@@ -102,8 +102,14 @@ namespace mtconnect {
102102 uint32_t (GetOption<int >(options, mtconnect::configuration::JsonVersion).value_or (2 ));
103103
104104 // Create the Printers
105- m_printers[" xml" ] = make_unique<printer::XmlPrinter>(m_version, m_pretty);
106- m_printers[" json" ] = make_unique<printer::JsonPrinter>(jsonVersion, m_version, m_pretty);
105+ m_printers[" xml" ] = make_unique<printer::XmlPrinter>(m_pretty);
106+ m_printers[" json" ] = make_unique<printer::JsonPrinter>(jsonVersion, m_pretty);
107+
108+ if (m_schemaVersion)
109+ {
110+ for (auto &[k, pr] : m_printers)
111+ pr->setSchemaVersion (*m_schemaVersion);
112+ }
107113 }
108114
109115 void Agent::initialize (pipeline::PipelineContextPtr context)
@@ -114,19 +120,27 @@ namespace mtconnect {
114120 m_loopback =
115121 std::make_shared<source::LoopbackSource>(" AgentSource" , m_strand, context, m_options);
116122
117- int major, minor;
118- char c;
119- stringstream vstr (m_version);
120- vstr >> major >> c >> minor;
123+ auto devices = loadXMLDeviceFile (m_deviceXmlPath);
124+ if (!m_schemaVersion)
125+ {
126+ m_schemaVersion.emplace (StrDefaultSchemaVersion ());
127+ }
128+
129+ auto version = IntSchemaVersion (*m_schemaVersion);
130+ for (auto &[k, pr] : m_printers)
131+ pr->setSchemaVersion (*m_schemaVersion);
121132
122133 auto disableAgentDevice = GetOption<bool >(m_options, config::DisableAgentDevice);
123- if (!(disableAgentDevice && *disableAgentDevice) && (major > 1 || (major == 1 && minor >= 7 ) ))
134+ if (!(disableAgentDevice && *disableAgentDevice) && version >= SCHEMA_VERSION ( 1 , 7 ))
124135 {
125136 createAgentDevice ();
126137 }
127- loadXMLDeviceFile (m_deviceXmlPath);
128- loadCachedProbe ();
138+
139+ // For the DeviceAdded event for each device
140+ for (auto device : devices)
141+ addDevice (device);
129142
143+ loadCachedProbe ();
130144 m_initialized = true ;
131145 }
132146
@@ -277,13 +291,21 @@ namespace mtconnect {
277291 }
278292 }
279293
280- void Agent::reloadDevices (const std::string &deviceFile)
294+ bool Agent::reloadDevices (const std::string &deviceFile)
281295 {
282296 try
283297 {
284298 // Load the configuration for the Agent
285299 auto devices = m_xmlParser->parseFile (
286300 deviceFile, dynamic_cast <printer::XmlPrinter *>(m_printers[" xml" ].get ()));
301+
302+ if (m_xmlParser->getSchemaVersion () &&
303+ IntSchemaVersion (*m_xmlParser->getSchemaVersion ()) != IntSchemaVersion (*m_schemaVersion))
304+ {
305+ LOG (info) << " Got version: " << *(m_xmlParser->getSchemaVersion ());
306+ LOG (warning) << " Schema version does not match agent schema version, restarting the agent" ;
307+ return false ;
308+ }
287309
288310 // Fir the DeviceAdded event for each device
289311 bool changed = false ;
@@ -293,6 +315,8 @@ namespace mtconnect {
293315 }
294316 if (changed)
295317 loadCachedProbe ();
318+
319+ return true ;
296320 }
297321 catch (runtime_error &e)
298322 {
@@ -430,7 +454,7 @@ namespace mtconnect {
430454 if (!fs::exists (backup))
431455 fs::rename (file, backup);
432456
433- printer::XmlPrinter printer (m_version, true );
457+ printer::XmlPrinter printer (true );
434458
435459 std::list<DevicePtr> list;
436460 copy_if (m_deviceIndex.begin (), m_deviceIndex.end (), back_inserter (list),
@@ -576,7 +600,7 @@ namespace mtconnect {
576600
577601 // Create the Agent Device
578602 ErrorList errors;
579- Properties ps {{" uuid" , uuid}, {" id" , id}, {" name" , " Agent" s}, {" mtconnectVersion" , m_version }};
603+ Properties ps {{" uuid" , uuid}, {" id" , id}, {" name" , " Agent" s}, {" mtconnectVersion" , *m_schemaVersion }};
580604 m_agentDevice =
581605 dynamic_pointer_cast<AgentDevice>(AgentDevice::getFactory ()->make (" Agent" , ps, errors));
582606 if (!errors.empty ())
@@ -592,7 +616,7 @@ namespace mtconnect {
592616 // Device management and Initialization
593617 // ----------------------------------------------
594618
595- void Agent::loadXMLDeviceFile (const std::string &configXmlPath)
619+ std::list<device_model::DevicePtr> Agent::loadXMLDeviceFile (const std::string &configXmlPath)
596620 {
597621 NAMED_SCOPE (" Agent::loadXMLDeviceFile" );
598622
@@ -602,9 +626,16 @@ namespace mtconnect {
602626 auto devices = m_xmlParser->parseFile (
603627 configXmlPath, dynamic_cast <printer::XmlPrinter *>(m_printers[" xml" ].get ()));
604628
605- // Fir the DeviceAdded event for each device
606- for (auto device : devices)
607- addDevice (device);
629+ if (!m_schemaVersion && m_xmlParser->getSchemaVersion ())
630+ {
631+ m_schemaVersion = m_xmlParser->getSchemaVersion ();
632+ }
633+ else if (!m_schemaVersion && !m_xmlParser->getSchemaVersion ())
634+ {
635+ m_schemaVersion = StrDefaultSchemaVersion ();
636+ }
637+
638+ return devices;
608639 }
609640 catch (runtime_error &e)
610641 {
@@ -620,14 +651,15 @@ namespace mtconnect {
620651 cerr << f.what () << endl;
621652 throw f;
622653 }
654+
655+ return {};
623656 }
624657
625658 void Agent::verifyDevice (DevicePtr device)
626659 {
627660 NAMED_SCOPE (" Agent::verifyDevice" );
628-
629- auto xmlPrinter = dynamic_cast <printer::XmlPrinter *>(m_printers[" xml" ].get ());
630- const auto &schemaVersion = xmlPrinter->getSchemaVersion ();
661+
662+ auto version = IntSchemaVersion (*m_schemaVersion);
631663
632664 // Add the devices to the device map and create availability and
633665 // asset changed events if they don't exist
@@ -644,11 +676,7 @@ namespace mtconnect {
644676 device->addDataItem (di, errors);
645677 }
646678
647- int major, minor;
648- char c;
649- stringstream ss (schemaVersion);
650- ss >> major >> c >> minor;
651- if (!device->getAssetChanged () && (major > 1 || (major == 1 && minor >= 2 )))
679+ if (!device->getAssetChanged () && version >= SCHEMA_VERSION (1 , 2 ))
652680 {
653681 entity::ErrorList errors;
654682 // Create asset change data item and add it to the device.
@@ -659,14 +687,14 @@ namespace mtconnect {
659687 device->addDataItem (di, errors);
660688 }
661689
662- if (device->getAssetChanged () && (major > 1 || (major == 1 && minor >= 5 ) ))
690+ if (device->getAssetChanged () && version >= SCHEMA_VERSION ( 1 , 5 ))
663691 {
664692 auto di = device->getAssetChanged ();
665693 if (!di->isDiscrete ())
666694 di->makeDiscrete ();
667695 }
668696
669- if (!device->getAssetRemoved () && (major > 1 || (major == 1 && minor >= 3 ) ))
697+ if (!device->getAssetRemoved () && version >= SCHEMA_VERSION ( 1 , 3 ))
670698 {
671699 // Create asset removed data item and add it to the device.
672700 entity::ErrorList errors;
@@ -677,7 +705,7 @@ namespace mtconnect {
677705 device->addDataItem (di, errors);
678706 }
679707
680- if (!device->getAssetCount () && (major >= 2 ))
708+ if (!device->getAssetCount () && version >= SCHEMA_VERSION ( 2 , 0 ))
681709 {
682710 entity::ErrorList errors;
683711 auto di = DataItem::make ({{" type" , " ASSET_COUNT" s},
0 commit comments