<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:discourse="http://discourse.org/rss/modules/discourse/"><channel><title>Nuno Nunes on DevBlog</title><link>https://devblog.criticalmanufacturing.com/author/nuno-nunes/</link><description>Recent content in Nuno Nunes on DevBlog</description><image><url>https://devblog.criticalmanufacturing.com/uploads/og.webp</url><link>https://devblog.criticalmanufacturing.com/uploads/og.webp</link></image><generator>Hugo -- gohugo.io</generator><language>en-us</language><copyright>A template by [Heksagon](https://www.heksagon.net). Implemented for [Critical Manufacturing](https://www.criticalmanufacturing.com/).</copyright><lastBuildDate>Tue, 05 Dec 2023 00:00:00 +0000</lastBuildDate><atom:link href="https://devblog.criticalmanufacturing.com/author/nuno-nunes/index.xml" rel="self" type="application/rss+xml"/><item><title>Quick &amp; Easy File Integration</title><link>https://devblog.criticalmanufacturing.com/blog/20231205_iot_generic_file_integration/</link><pubDate>Tue, 05 Dec 2023 00:00:00 +0000</pubDate><dc:creator>Nuno Nunes</dc:creator><guid>https://devblog.criticalmanufacturing.com/blog/20231205_iot_generic_file_integration/</guid><description>IoT File Integration for Dummies</description><content:encoded><![CDATA[<p>On this blog post we will implement a generic file integration: some file will be read from some folder and it&rsquo;s contents will be read and passed on to some DEE Action.</p>
<h2 id="common-package">COMMON Package</h2>
<p>For this integration we will use a <code>COMMON</code> Feature package: <a href="https://tfs-projects.cmf.criticalmanufacturing.com/ImplementationProjects/COMMON/_git/Packages?path=%2FFeatures%2FIoT-GenericFileIntegration" target="_blank" rel="noopener">Cmf.Custom.IoT-GenericFileIntegration</a></p>
<p><strong>Feature Packages</strong>: <code>COMMON</code> is a repository where projects can implement features that can be shared and reused. This serves to mitigate having to implement the same code throughout different projects. The features are posted to <code>COMMON</code> and every project is free to import it, use it and contributing back to make it even more robust.</p>
<h2 id="using-this-package-on-my-project">Using this package on my project</h2>
<p>To use this package on your project, you simply add to your <code>cmfpackage.json</code> file:</p>
<p>
<img src="/blogPosts/IoT/20231205_iot_generic_file_integration/addtoprojectsamemesversion.png" alt="Adding to Project - Same MES Version (9.1.11)" />

</p>
<p><strong>Important</strong>: If your project is using a different patch version than the one this package was prepared for (9.1.11), please use the components unrooted:</p>
<p>
<img src="/blogPosts/IoT/20231205_iot_generic_file_integration/addtoprojectdifferentmesversion.png" alt="Adding to Project - Different MES Version" />

</p>
<h2 id="creating-a-controller-instance">Creating a Controller Instance</h2>
<p>After the release process, the environment will have a new automation manager, <code>GenericFileIntegration_Manager</code>, and a new controller, <code>GenericFileIntegration_Controller</code>.
To use it, just create a controller instance by connecting this controller to a Resource.</p>
<h2 id="feature-configuration">Feature Configuration</h2>
<p>Available package options are described on package <a href="https://tfs-projects.cmf.criticalmanufacturing.com/ImplementationProjects/COMMON/_git/Packages?path=%2FFeatures%2FIoT-GenericFileIntegration%2FREADME.md&amp;_a=preview" target="_blank" rel="noopener">README.md</a>.</p>
<p>Configuration is orchestrated on a smart table <code>&lt;ST&gt;IoTMetaDataDefinition</code> by name/value pairs. Minimal configuration is:</p>
<table>
<thead>
<tr>
<th>Name</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>FileRaw_filePath</td>
<td>c:\iot\Shares\Incoming</td>
<td>Incoming folder (where file are created)</td>
</tr>
<tr>
<td>FileRaw_SuccessArchiveFilePath</td>
<td>c:\iot\Shares\Success</td>
<td>Where to store the files on DEE Action Success</td>
</tr>
<tr>
<td>FileRaw_ErrorArchiveFilePath</td>
<td>c:\iot\Shares\Error</td>
<td>Where to store the files on DEE Action Error</td>
</tr>
<tr>
<td>FileRaw_DEEActionName</td>
<td>CustomSendNotificationOnDisconnected</td>
<td>DEE to execute</td>
</tr>
<tr>
<td>FileRaw_InputParameterName</td>
<td>ErrorMessage</td>
<td>Input parameter name on DEE/Service</td>
</tr>
</tbody>
</table>
<p>We can reuse the blog post <a href="../20230606_iot_sending_notification/">Send a Notification in Connect IoT</a> as a DEE example (<code>CustomSendNotificationOnDisconnected</code>).
With this example, whenever a new file is put on the incoming folder, a new notification is created with the content of the file.</p>
<h2 id="execution-time">Execution time!</h2>
<p>Download the manager from MES GUI:</p>
<p>
<img src="/blogPosts/IoT/20231205_iot_generic_file_integration/download_manager.png" alt="Download manager" />

</p>
<p>Unzip and run it (<code>as Administrator</code> to be able to mount network files):</p>
<p>
<img src="/blogPosts/IoT/20231205_iot_generic_file_integration/runit.png" alt="Run It" />

</p>
<p>Now, drop a file with some content on the incoming folder:</p>
<p>
<img src="/blogPosts/IoT/20231205_iot_generic_file_integration/somefileonincoming.png" alt="File on Incoming" />

</p>
<p>A new notification should be created:</p>
<p>
<img src="/blogPosts/IoT/20231205_iot_generic_file_integration/notificationcreated.png" alt="Notification Created" />

</p>
<p>and the file should be moved to a timestamped subfolder on `Success`` folder:</p>
<p>
<img src="/blogPosts/IoT/20231205_iot_generic_file_integration/movedtosuccess.png" alt="Moved to Success" />

</p>
<p>Great Success!</p>
<h2 id="things-to-consider">Things to consider</h2>
<h3 id="multiple-files-being-dropped-at-the-same-time-on-the-incoming-folder">Multiple files being dropped at the same time on the incoming folder</h3>
<p>If you would need to handle multiple files at the same time, please add to your manager <code>config.json</code>: <code>&quot;controller&quot;: {&quot;useClassicEngine&quot;: false}</code>.</p>
<h3 id="error-calling-deeservice">Error calling DEE/Service</h3>
<p>If DEE fails, file is moved to the Error folder (with some date timestamp) and the received error is also stored on a <code>.log</code> file:
This is very helpfull to debug whithout the need to check IoT logs.</p>
<p>
<img src="/blogPosts/IoT/20231205_iot_generic_file_integration/logfileonerror.png" alt="Log file on Error" />

</p>
<p><br></br></p>
<hr>
<p><br></br></p>
<h2 id="author">Author</h2>
<h3 id="hello-my-name-is-nuno-nunes">Hello my name is Nuno Nunes</h3>
<p>I am an IoT Lead for the SMT area
You can visit me at <a href="https://www.linkedin.com/in/nunones" target="_blank" rel="noopener">LinkedIn</a></p>
<p>Skills: Connect IoT

<figure class="text-center">
  <img
    src="/blogPosts/contributors/blogger_nuno_nunes.jpg"
    alt="Nuno Nunes"
    title="IoT Lead"
  />
  <figcaption style="text-align: center">IoT Lead</figcaption>
</figure>

</p>
]]></content:encoded></item><item><title>IPC-CFX Environment Configuration &amp; Testing</title><link>https://devblog.criticalmanufacturing.com/blog/20230920_iot_ipccfx/</link><pubDate>Wed, 20 Sep 2023 00:00:00 +0000</pubDate><dc:creator>Nuno Nunes</dc:creator><guid>https://devblog.criticalmanufacturing.com/blog/20230920_iot_ipccfx/</guid><description>How-To create a development and testing environment for IPC-CFX interface</description><content:encoded><![CDATA[<p>Goal of this guide is to have a working environment where IPC-CFX developments and manual tests can be made</p>
<h2 id="pre-requisites">Pre-Requisites</h2>
<ul>
<li>Have a local environment with MES/Connect IoT ready.</li>
<li>Optional (but recommended): Project with support for IPC-CFX Feature Package/SMT Template</li>
</ul>
<h1 id="what-is-ipc-cfx-">What is IPC-CFX ?</h1>
<p><em>IPC-CFX is an industry-developed open international standard forming the foundation/backbone of Factory of the Future applications. IPC-CFX is a plug-and-play solution that simplifies and standardizes machine-to-machine communication while also facilitating machine-to-business and business-to-machine applications.</em>
(from <a href="https://www.ipc.org/about-ipc-cfx-and-your-path-ipc-cfx-success" target="_blank" rel="noopener">IPC.org</a> .)</p>
<p>We use this driver on SMT/eletronics area to interface with several SMT machine types, mainly, but not limited, to inspection machines.</p>
<p>IPC-CFX consists of M2M (Machine to Machine) communication and brokered communication (through a message routing system - <em>broker</em>),</p>
<p>
<img src="/blogPosts/IoT/20230920_iot_ipccfx/iot_ipccfx_messagerouting.png" alt="IPC-CFX Message Routing" />

</p>
<p>Our IPC-CFX IoT driver and IPC-CFX simulator support all communication methods.</p>
<h2 id="ei-integration">EI integration</h2>
<p>On your MES local environment create:</p>
<ul>
<li>An automation protocol using IPCCFX driver,</li>
<li>Empty driver definition using a Resource entity type (no properties, events or commands),</li>
<li>An automation controller (with the default Setup workflow)</li>
<li>An automation manager with a connected instance</li>
</ul>
<p>Change <code>OnEquipmentSetup</code> task on <code>Setup</code> workflow with the following configurations:</p>
<table>
<thead>
<tr>
<th>Config</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr>
<td>TransportProtocol</td>
<td>&lsquo;AMQP&rsquo;</td>
</tr>
<tr>
<td>DriverHandle</td>
<td>&lsquo;CMF.Line1.ICTMachineHandler1&rsquo;</td>
</tr>
<tr>
<td>DriverEndPoint</td>
<td>&lsquo;amqp://0.0.0.0:4682&rsquo;</td>
</tr>
<tr>
<td>DriverAddress</td>
<td>&rsquo;test'</td>
</tr>
<tr>
<td>BrokerEndpoint</td>
<td>&lsquo;amqp://127.0.0.1:5672&rsquo;</td>
</tr>
<tr>
<td>BrokerExchange</td>
<td>&lsquo;/queue/testQueue&rsquo;</td>
</tr>
<tr>
<td>DurableQueue</td>
<td>&lsquo;false&rsquo;</td>
</tr>
<tr>
<td>TargetHandle</td>
<td>&lsquo;keysight.i3070.i30704CE9310MC8.MY59250157.L1&rsquo;</td>
</tr>
<tr>
<td>TargetEndPoint</td>
<td>&lsquo;amqp://10.20.204.229:4683&rsquo;</td>
</tr>
<tr>
<td>LogMessagesFromOtherSources</td>
<td>&lsquo;True&rsquo;</td>
</tr>
</tbody>
</table>
<p>That configuration allows both M2M and brokered communication (we will use both methods on this guide).
In your project, you might have just brokered messages or just M2M.</p>
<h2 id="first-time-boot">First time boot</h2>
<p>When executing the manager, you should get the error:
<code>error: [AMQP] Unable to validate Publish channel '/queue/testQueue' at 'ExchangePublisher' 'amqp://127.0.0.1:5672/': One or more errors occurred. (No connection could be made because the target machine actively refused it)</code>
because no broker is installed yet.</p>
<h2 id="broker-installation">Broker installation</h2>
<p>So, let&rsquo;s install <a href="https://www.rabbitmq.com/getstarted.html" target="_blank" rel="noopener">RabbitMQ</a> as a broker.
Please note: This is something that we will do here, as a development/test exercice but it&rsquo;s not a task or responsability in our projects: to install or to configure an AMQP broker (we don&rsquo;t actually recommend RabbitMQ or any other).</p>
<p><code>cd c:\Work\amqp</code>
<code>git clone  https://github.com/it-herz/docker-rabbitmq.git .</code>
<code>docker build -t amqp .</code>
<code>docker run -d --publish 1883:1883 --publish 4369:4369 --publish 5672:5672 --publish 15672:15672 amqp</code></p>
<p>With this you should have a running container with <a href="https://www.rabbitmq.com/getstarted.html" target="_blank" rel="noopener">RabbitMQ</a>.
You now should have LISTENING ports on 5672 (RabbitMQ) and 15672 (RabbitMQAdmin) on your system.</p>
<p><code>c:\Work\amqp&gt;netstat /an | findstr 5672</code>
<code>TCP    127.0.0.1:5672         0.0.0.0:0              LISTENING</code>
<code>TCP    127.0.0.1:15672        0.0.0.0:0              LISTENING</code></p>
<p>When opening RabbitMQ Admin web interface <a href="http://127.0.0.1:15672" target="_blank" rel="noopener">http://127.0.0.1:15672</a> you can use &ldquo;guest/guest&rdquo; user/password.</p>
<p>If you run the manager now, the automation should be able to go in to <code>communicating</code> state (able to connect to the broker) and create automaticaly <code>testQueue</code> Queue.</p>
<p>
<img src="/blogPosts/IoT/20230920_iot_ipccfx/iot_ipccfx_managerrunning.png" alt="Connection established to Broker" />

</p>
<h2 id="configure-broker">Configure Broker</h2>
<p>Open RabbitMQAdmin web interface and create an exchange with the following properties:</p>
<p><code>{&quot;name&quot;: &quot;testExchange&quot;,&quot;vhost&quot;: &quot;/&quot;,&quot;type&quot;: &quot;fanout&quot;, &quot;durable&quot;: true, &quot;auto_delete&quot;: false, &quot;internal&quot;: false, &quot;arguments&quot;: {} }</code>

<img src="/blogPosts/IoT/20230920_iot_ipccfx/iot_ipccfx_createexchange.png" alt="Create Exchange" />

</p>
<p>Let&rsquo;s create a binding from the Exchange to the newly created Queue:</p>
<p>
<img src="/blogPosts/IoT/20230920_iot_ipccfx/iot_ipccfx_createbinding.png" alt="Create Binding" />

</p>
<h2 id="use-ipc-cfx-simulator">Use IPC-CFX Simulator</h2>
<p>When the driver is in communicating status, we should be able to use <a href="https://tfs-product.cmf.criticalmanufacturing.com/Products/Product/_git/IoMT?path=%2Fsrc%2Fdriver-ipccfx%2Ftest%2Ftools%2FIPC-CFX%20Simulator" target="_blank" rel="noopener">IPC-CFX Simulator</a> to send test messages and check automation logs.</p>
<h3 id="sending-message-to-the-broker">Sending message to the broker</h3>
<p>
<img src="/blogPosts/IoT/20230920_iot_ipccfx/iot_ipccfx_sendstatechangetobroker.png" alt="Sending State Change to Broker" />

</p>
<p>For first test, we can send a <a href="http://www.connectedfactoryexchange.com/CFXDemo/sdk/html/T_CFX_ResourcePerformance_StationStateChanged.htm" target="_blank" rel="noopener">CFX.ResourcePerformance.StationStateChanged</a>
with some test content
<code>{ &quot;OldState&quot;: 2200, &quot;OldStateDuration&quot;: &quot;00:01:25&quot;, &quot;NewState&quot;: 1100, &quot;RelatedFault&quot;: null }</code>
to the broker exchange.
Since we have created a bind from the testExchange to our testQueue we should receive it on our ConnectIoT automation.
CFX.Heartbeat are being sent whenever IPC-CFX Simulator is running.</p>
<p>Notice the log from automation:
<code>debug: &lt;&lt; [0e310c9c-5c66-4f88-886a-fe9abc19d759] Received Event: of type 'CFX.Heartbeat' from 'keysight.i3070.i30704CE9310MC8.MY59250157.L1' occurred at '2023-09-21T11:27:56.9493357+01:00'</code>
Since we haven&rsquo;t registered any logic for this event, it is being ignored.
<code>debug: &lt;&lt; [c31dce12-5cf7-444e-9349-44ad458fd412] Ignoring Handle Request not Registered by Controller: type 'CFX.ResourcePerformance.StationStateChanged'  occurred at '2023-09-21T11:28:03.3442859+01:00'</code></p>
<p>Since we don&rsquo;t registered any logic for this event, is being ignored for now.</p>
<h3 id="sending-messages-directly-to-connectiot-endpoint">Sending messages directly to ConnectIoT endpoint</h3>
<p>Let&rsquo;s try to send a M2M message <a href="http://www.connectedfactoryexchange.com/CFXDemo/sdk/html/T_CFX_InformationSystem_UnitValidation_ValidateUnitsRequest.htm" target="_blank" rel="noopener">CFX.InformationSystem.UnitValidation.ValidateUnitsRequest</a> using the IPC-CFX Simulator:</p>
<p><code>{ &quot;Validations&quot;: [ &quot;UnitRouteValidation&quot;, &quot;UnitStatusValidation&quot; ], &quot;PrimaryIdentifier&quot;: &quot;CARRIER2342&quot;, &quot;Units&quot;: [ { &quot;UnitIdentifier&quot;: &quot;CARRIER5566&quot;, &quot;PositionNumber&quot;: 1, &quot;PositionName&quot;: &quot;CIRCUIT1&quot;, &quot;X&quot;: 50.45, &quot;Y&quot;: 80.66, &quot;Rotation&quot;: 0.0, &quot;FlipX&quot;: false, &quot;FlipY&quot;: false } ] }</code></p>
<p>
<img src="/blogPosts/IoT/20230920_iot_ipccfx/iot_ipccfx_sendm2mvalidateunits.png" alt="Sending ValidateUnits" />

</p>
<p>Again, we have not registered this request on controller workflows, so no valid answer is returned.
<code>debug: &lt;&lt; [bfa55cb9-7048-4a44-8228-70ba5e7aae43] request: [REQUEST-901722b8-b3e7-42aa-a3b6-3f85c824146f] Ignoring Handle Request not Registered by Controller: type 'CFX.InformationSystem.UnitValidation.ValidateUnitsRequest'  occurred at '2023-09-21T11:45:31.2527854+01:00'</code></p>
<h2 id="using-common-ipc-cfx-feature-package">Using COMMON IPC-CFX Feature Package</h2>
<p>We can start from scratch, but, we have already a full featured SMT implementation, using IPCCFX, available.
Well.. there are always features missing. See &ldquo;WIP&rdquo; section.
It&rsquo;s outside the scope of this guide to show how to import a Feature Package or Product SMT Template onto your project. Please check the links on extra reference documentation (hint: <code>Equipment Integration on DS SMT Template</code>, slide #4).
Please note that this will be ported onto Product <a href="https://tfs-product.cmf.criticalmanufacturing.com/Products/Product/_git/SMTTemplate?path=%2FIoT-Features%2FIoT-IPC-CFX" target="_blank" rel="noopener">SMT Template repository</a> in the future (so please check that repository also).</p>
<p>After having this imported on your project, you can explore features and fine tune to the actual tests/developments needed.</p>
<p>Current developped logic supports:</p>
<ul>
<li>Station State Change</li>
<li>TrackIn &amp; TrackOut materials</li>
<li>Post to Material Defects and Post to DC on UnitsTested/Inspected</li>
<li>Material Interlocking</li>
</ul>
<h2 id="further-testing">Further testing</h2>
<p>To add support to our logic to specific messages we use <a href="https://help.criticalmanufacturing.com/9.1/UserGuide/business_data%3Eautomation_controller%3Etasks%3Eipccfx" target="_blank" rel="noopener">connect-iot-controller-engine-ipccfx-tasks</a> tasks package.
This allows adding support to any IPCCFX (other than the ones already preconfigured) by specifying Message Full Name and Inputs/Outputs on Cfx Task.</p>
<p>
<img src="/blogPosts/IoT/20230920_iot_ipccfx/iot_ipccfx_messagefullname.png" alt="Message Full Name on Cfx Event Task" />



<img src="/blogPosts/IoT/20230920_iot_ipccfx/iot_ipccfx_messageoutputs.png" alt="Outputs on Cfx Event Task" />

</p>
<p>
<img src="/blogPosts/IoT/20230920_iot_ipccfx/iot_ipccfx_unitsarrivedworkflow.png" alt="UnitsArrived Controller Workflow Page" />

</p>
<p>Now, on execution, this controller workflow will register support for these messages on driver:
<code>info: Registering custom event 'CFX.Production.UnitsArrived_0lydj8iruxch', for topic 'CFX.Production.UnitsArrived', associated with '5' properties</code>
<code>info: Registered event 'CFX.Production.UnitsArrived' with success!</code></p>
<p>So when sending message on IPC-CFX simulator:</p>
<p>
<img src="/blogPosts/IoT/20230920_iot_ipccfx/iot_ipccfx_sendingunitsarrived.png" alt="Sending UnitsArrived" />

</p>
<p>We should receive and handle it on controller:
<code>info: [5d3b3364|workflow_3076|task_4039|onCfxEvent] Received a 'CFX.Production.UnitsArrived' event from 'keysight.i3070.i30704CE9310MC8.MY59250157.L1'.</code>
<code>info: [5d3b3364|workflow_3076|task_4039|onCfxEvent] Successfully updated task's outputs after received event 'CFX.Production.UnitsArrived' from 'keysight.i3070.i30704CE9310MC8.MY59250157.L1'.</code>
<code>info: [5d3b3364|workflow_3076|task_4424|logMessage] {&quot;messageId&quot;:&quot;ffe7c697-4e14-4e6a-ba21-b0f83946a789&quot;,&quot;sourceId&quot;:&quot;keysight.i3070.i30704CE9310MC8.MY59250157.L1&quot;,&quot;eventId&quot;:&quot;CFX.Production.UnitsArrived&quot;,&quot;requestId&quot;:null,&quot;occurrenceTimeStamp&quot;:&quot;2023-09-22T08:59:12.543Z&quot;,&quot;emitTimeStamp&quot;:&quot;2023-09-22T08:59:12.547Z&quot;,&quot;values&quot;:{&quot;Lane&quot;:1,&quot;PrimaryIdentifier&quot;:&quot;123456789&quot;,&quot;UnitCount&quot;:1,&quot;Units&quot;:[{&quot;UnitIdentifier&quot;:&quot;1234567890A&quot;,&quot;PositionNumber&quot;:1,&quot;PositionName&quot;:&quot;CIRCUIT1&quot;,&quot;X&quot;:0,&quot;Y&quot;:0,&quot;Rotation&quot;:0,&quot;FlipX&quot;:false,&quot;FlipY&quot;:false,&quot;$id&quot;:&quot;5&quot;}],&quot;$id&quot;:&quot;4&quot;},&quot;$id&quot;:&quot;3&quot;}</code></p>
<h2 id="wip">WIP</h2>
<p>Some enhancements are being developed:</p>
<ul>
<li><a href="http://www.connectedfactoryexchange.com/CFXDemo/sdk/html/T_CFX_Production_Processing_UnitsProcessed.htm" target="_blank" rel="noopener">UnitsProcessed for Reflow Ovens/Selective Soldering/Reflow Profiling Devices)</a> (Update: already implemented)</li>
<li>Using TransactionID as context key</li>
</ul>
<h2 id="extra-resources">Extra Resources</h2>
<ul>
<li><a href="https://tfs-projects.cmf.criticalmanufacturing.com/ImplementationProjects/COMMON/_git/EI?path=%2FIoT%20Guidelines%2FDrivers%2FIPC-CFXSimulator.md" target="_blank" rel="noopener">IPCCFX Simulator</a></li>
<li><a href="https://tfs-projects.cmf.criticalmanufacturing.com/ImplementationProjects/COMMON/_git/EI?path=%2FIoT%20Guidelines%2FDrivers%2FIPC-CFXBootstrap.md" target="_blank" rel="noopener">IPCCFX Bootstrap</a></li>
<li><a href="https://criticalmfg.sharepoint.com/:p:/r/sites/SMTTemplate/_layouts/15/Doc.aspx?sourcedoc=%7BDCC68F98-CD3D-4EA6-9AA4-12F197F9D7AE%7D&amp;file=SMT%20Template%20-%20Equipment%20Integration.pptx&amp;action=edit&amp;mobileredirect=true" target="_blank" rel="noopener">Equipment Integration on DS SMT Template</a></li>
</ul>
<p><br></br></p>
<hr>
<p><br></br></p>
<h2 id="author">Author</h2>
<h3 id="hello-my-name-is-nuno-nunes">Hello my name is Nuno Nunes</h3>
<p>I am an IoT Lead for the SMT area
You can visit me at <a href="https://www.linkedin.com/in/nunones" target="_blank" rel="noopener">LinkedIn</a></p>
<p>Skills: Connect IoT

<figure class="text-center">
  <img
    src="/blogPosts/contributors/blogger_nuno_nunes.jpg"
    alt="Nuno Nunes"
    title="IoT Lead"
  />
  <figcaption style="text-align: center">IoT Lead</figcaption>
</figure>

</p>
]]></content:encoded></item></channel></rss>