Open main menu

DAVE Developer's Wiki β

Changes

Introduction
==Introduction==
In essence, this Technical Note (TN) is very similar to [[MISC-TN-024: Automated test equipment (ATE) monitoring with SBCSPG gateway and ThingsBoard IoT platform|this one''MISC-TN-024: Automated test equipment (ATE) monitoring with SBCSPG gateway and ThingsBoard IoT platform'']]. There is a noticeable difference, however, as a different software stack was used on the edge device. In this case, [https://www.lfedge.org/projects/fledge/ LF EdgeFledge] was utilized.
==Testbed==
===Enabling the connection to the PLC===
As described in [[MISC-TN-024: Automated test equipment (ATE) monitoring with SBCSPG gateway and ThingsBoard IoT platform|''MISC-TN-024'']], the PLC we want to talk to is connected to a different subnet, namely 192.168.30.0/24. For testing the connection to the PLC, after adding the required subnet configuration, the <code>modbus</code> command line tool was used, which is provided by the <code>modbus_cli</code> package. In the following example, the register mapped ad the address 300 is read.
<pre class="board-terminal">
=== Enabling the connection to ThingsBoard IoT platform ===
In order to upload collected data to ThingsBoard platform, a simple North plugin was developed. To this end, the Microsoft Azure plugin was used as reference. The following box shows the code. The ThingsBoard South North plugin is minimalist and '''unfit for a real-world production environment'''. Nevertheless, it was enough to perform the basic tests described in this TNdocument. Before testing this new plugin, the <code>mosquitto-clients </code> package was installed as the plugin invokes the <code>mosquitto_pub</code> command line tool.  
<pre class="board-terminal">
root@sbcspg:/usr/local/fledge/python/fledge/plugins/north# apt install mosquitto mosquitto-clients
Reading package lists... Done
Created symlink /etc/systemd/system/multi-user.target.wants/mosquitto.service → /lib/systemd/system/mosquitto.service.
Processing triggers for libc-bin (2.31-13+deb11u5) ...
</pre>
The following box shows the code of the ThingsBoard plugin.
<syntaxhighlight lang="python" class"mw-collapsible="" mw-collapsed"="">
# -*- coding: utf-8 -*-
""" ThingsBoard North plugin"""
import asyncio
import time
import json
import sys
import os
You can think about this This Technical Note (TN) as an evolution of the article "[[MISC-TN-021: SBCSPG and ThingsBoard IoT]]". The use case described here is a real-world application based on the same elements:
* [[MISC-TN-004: Running Debian (armbian) on SBCSPG#The hardware platform|The ''SBCSPG'' industrial gateway]]
* [https://thingsboard.io/docs/ ''ThingsBoard IoT platform'']
* [https://thingsboard.io/docs/iot-gateway/what-is-iot-gateway/ ''ThingsBoard IoT gateway''].
The application is to monitor robotized DAVE Embedded Systems' ATEs like the one shown [https://youtu.be/OoNiKgJXq00?t=409 here].
== Implementation ==from fledge.common import loggerThe implementation is suitable for a production environmentfrom fledge.plugins. Unlike what we did for [[MISC-TN-021: SBCSPG and ThingsBoard IoT|this TN]], in this case the ThingsBoard IoT platform was installed on the cloud, specifically on an AWS EC2 instance running Ubuntu Linuxnorth. The following diagram shows the complete solutioncommon.common import *
[[File:ATE monitoring SBCSPG ThingsBoard__author__ = "Andrea Marson"__copyright__ = "Copyright (c) 2023 DAVE Srl"__license__ = "Apache 2.png|center|thumb|1000x1000px]]0"__version__ = "${VERSION}"
Technically, the gateway can communicate with the ATE using different physical links and protocols_LOGGER = logger. In the example under discussion, the physical link is Ethernet and the protocol is Modbus/TCP. The gateway retrieves periodically some data regarding the robotic arm used to move the device under test setup(DUT__name__). These data are [https://www.universal-robots.com/articles/ur/interface-communication/modbus-server/ exposed by the PLC governing the arm] and are documented in detail [https://s3-eu-west-1.amazonaws.com/ur-support-site/16377/ModBus%20server%20data.pdf here].
_CONFIG_CATEGORY_NAME ="THINGSBOARD"_CONFIG_CATEGORY_DESCRIPTION == ThingsBoard IoT configuration ===To install "ThingsBoard IoT platform on an EC2 instance, [https://thingsboard.io/docs/user-guide/install/cluster/aws-self-hosted-setup/ these instructions] were followed. Python North Plugin"
_DEFAULT_CONFIG === ThingsBoard IoT gateway configuration ===To run this esample, the most important module to configure was the [https://thingsboard.io/docs/iot-gateway/config/modbus/ Modbus connector]. The following box shows the resulting configuration file needed to poll some variables of the arm's joints (namely temperatures and currents).<syntaxhighlight lang="json">armbian@sbcspg:~$ cat /etc/thingsboard-gateway/config/modbus.json{ "master"'plugin': { "slaves" 'description': [ { "host": "192.168.30.42"'ThingsBoard North Plugin', "port": 502, " 'type"': "tcp"'string', "method" 'default': "socket"'thingsboard', "timeout": 35, "byteOrder": "BIG", "retries" 'readonly': 'true,' "retryOnEmpty": true }, "retryOnInvalidtb_iot_platform_host": true,{ "pollPerioddescription": 5000, "unitIdThingsBoard IoT platform host.": 1, "deviceNametype": "UR5string", "sendDataOnlyOnChangedefault": true, "connectAttemptTimeMsput the public name of your host here": 5000, "connectAttemptCountorder": 5, "waitAfterFailedAttemptsMs2": 300000, "timeseries": [ { "tagdisplayName": "base_joint_temperature_deg_CThingsBoard IoT platform host", "type": "16int" }, "functionCodetb_mqtt_topic": 3,{ "objectsCountdescription": 1, "addressMQTT topic": 300 }, { "tag": "shoulder_joint_temperature_deg_C", "type": "16intstring", "functionCodedefault": 3, "objectsCount": 1, v1/devices/me/telemetry"address": 301 }, { "tagorder": "base_joint_current_mA", "type": "16int", "functionCode": 3, "objectsCount": 1, "address": 290 }, { "tagdisplayName": "shoulder_joint_current_mAMQTT topic", "type" 'readonly': "16int",'true' "functionCode": 3 }, "objectsCounttb_device_access_token": 1, "address": 291 },{ { "tagdescription": "elbow_joint_current_mADevice's access token.", "type": "16intstring", "functionCodedefault": 3, "objectsCountput your device's token here": 1, "address": 292 }, { "tagorder": "wrist1_joint_current_mA4", "typedisplayName": "16intDevice's access token", "functionCode": 3 }, "objectsCountsource": 1, "address": 293 },{ { "tagdescription": "wrist2_joint_current_mASource of data to be sent on the stream.", "type": "16intenumeration", "functionCodedefault": 3, "objectsCountreadings": 1, "address": 294 }, { "tagoptions": ["wrist3_joint_current_mAreadings"], "typeorder": "16int5", "functionCodedisplayName": 3, "objectsCountSource": 1, "address" 'readonly': 295 } ] } ]'true'
}
def plugin_info(): return { 'name': 'thingsboard', 'version': '2.1.0', 'type': 'north', 'interface': '1.0', 'config': _DEFAULT_CONFIG } def plugin_init(data): _LOGGER.info('Initializing ThingsBoard North Python Plugin') global thingsboard_north, config thingsboard_north = ThingsBoardNorthPlugin() config = data _LOGGER.info(f'config = {config}') return config """Example of payload [{'reading': {'base_joint_temperature_deg_C': 34, 'base_joint_current_mA': 2042}, 'asset_code': 'Modbus TCP', 'id': 35613, 'ts': '2023-02-22 16:33:49.961000+00:00', 'user_ts': '2023-02-22 16:33:47.126849+00:00'}, {'reading': {'base_joint_temperature_deg_C': 34, 'base_joint_current_mA': 2045}, 'asset_code': 'Modbus TCP', 'id': 35614, 'ts': '2023-02-22 16:33:49.961000+00:00', 'user_ts': '2023-02-22 16:33:48.126817+00:00'}, {'reading': {'base_joint_temperature_deg_C': 34, 'base_joint_current_mA': 2060}, 'asset_code': 'Modbus TCP', 'id': 35615, 'ts': '2023-02-22 16:33:49.961000+00:00', 'user_ts': '2023-02-22 16:33:49.126827+00:00'}] Example of upload mosquitto_pub -d -q 1 -h "$THINGSBOARD_HOST_NAME" -t "v1/devices/me/telemetry" -u "$ACCESS_TOKEN" -m '{"base_joint_temperature_deg_C":33}'"""async def plugin_send(data, payload, stream_id): try: _LOGGER.info(f'ThingsBoard North Python - plugin_send: {stream_id}') _LOGGER.info(f'data = {data}') _LOGGER.info(f'payload = {payload}') _LOGGER.info(f'host = {data["tb_iot_platform_host"]["value"]}') for reading in payload: _LOGGER.info(f'reading = {reading}') _LOGGER.info(f'reading[reading] = {reading["reading"]}') s = 'mosquitto_pub -d -q 1 -h "' + data["tb_iot_platform_host"]["value"] + '" -t "' + data["tb_mqtt_topic"]["value"] + '" -u "' + data["tb_device_access_token"]["value"] + '" -m \'' + str(reading["reading"]) + "\'" _LOGGER.info(f's = {s}') os.system(s) except asyncio.CancelledError as ex: _LOGGER.exception(f'Exception occurred in plugin_send: {ex}') else: _LOGGER.info('payload sent successfully') return True, payload[len(payload-1)]["id"], len(payload) def plugin_shutdown(data): pass # TODO: North plugin can not be reconfigured? (per callback mechanism)def plugin_reconfigure(): pass class ThingsBoardNorthPlugin(object): """ North ThingsBoard Plugin """  
</syntaxhighlight>
 == Dashboards Visualization of uploaded data ==ThingsBoard IoT allows Similarly to create easily custom dashboards to visualize data. At what we did in [[http://ec2-15-160-47-190.euMISC-southTN-1.compute.amazonaws.com024:8080/dashboard/1178fb20Automated test equipment (ATE) monitoring with SBCSPG gateway and ThingsBoard IoT platform|''MISC-e56dTN-11ec-8592-e3cb29424137?publicId=28967df0-e56d-11ec-8592-e3cb29424137 this link024'']] such , we created a simple dashboard is available showing some temperatures and currents of to visualize in real-time on cloud side collected data as shown in the arm's jointsfollowing example.[[File:ATE monitoring SBCSPG ThingsBoard dashboard1-Fledge-8.png|center|thumb|600x600px|Visualization of uploaded data.]]
4,650
edits