介绍
Azure IoT运行时,您可以远程收集信息并在边缘设备上执行命令。安装在E-RT3 Plus上时,可以利用E-RT3 Plus和Azure运行时环境的功能执行各种操作。
这是五部分系列的第二部分,该系列演示了如何使用E-RT3 Plus使用Azure运行时环境。在previous article中,我们创建了一个Python模块,该模块将数据从模拟温度传感器模块发送到IoT Hub。在本文中,我们创建了一个python iot边缘数据收集模块,该模块从模拟输入模块(F3AD08-6R)收集数据并将其上传到IoT Hub。
。本文系列的最终目标是演示如何:
- 创建一个Python数据收集模块来收集数据,处理并将其上传到IoT Hub
- 创建一个用于将数据写入边缘设备 的Python模块
- 使用Azure App服务和Power BI 可视化收集的数据
硬件模块
下图显示了用于此演示的硬件模块。
下表描述了本文中使用的硬件模块。
模块 | 描述 |
---|---|
e-rt3加上F3RP70-2L(CPU模块,Ubuntu 18.04 32-位) | e-rt3加控制完整的模块集。它从CPU模块访问每个模块以读取和写数据。 armhf 架构包在此设备上运行。 |
F3AD08-6R(模拟输入模块) | 模拟输入模块将收到的外部模拟数据转换为数字数据。 |
F3BU05-0D(基本模块) | 这是连接每个模块的基础。它照顾了连接到它的模块之间的电源和通信。 |
F3PU20-0S(电源模块) | 用于电源,电源模块连接在基本模块上。 |
有关硬件模块的更多信息,请参阅this page。
注意:在Windows 10上执行IoT Edge模块开发和设备操作。
先决条件
完成本文的先决条件与previous article中提到的先决条件相同。此外,您必须满足列出的硬件要求。
入门
要将数据从E-RT3 Plus发送到IoT Hub并查看接收到的数据,我们必须完成以下步骤:
模块创建
创建一个用于从模拟输入模块收集数据并将其发送到IoT中心的模块,我们使用Visual Studio Code创建一个新的Python项目,然后修改代码以适合我们的要求。
Python IoT Edge数据收集模块必须从模拟输入模块的所有通道中收集数据,并将收集的数据发送到IoT Hub。此外,您必须能够从模块Twin配置数据收集频率。
创建新项目
在Visual Studio代码中创建新的Python模块的步骤与the previous article的步骤2和4中所述。
在此演示中,我们创建了一个带有以下详细信息的项目:
- 解决方案名称:ERT3D2C
- 模块模板:Python模块
- 模块名称:ERT3D2CMODULE
- 目标体系结构:ARM32V7
修改代码
创建项目后,将main.py
的内容重写如下:
import os
import json
import subprocess
import signal
import datetime
import ctypes
from azure.iot.device import IoTHubModuleClient
from azure.iot.device import Message
DESIRED_KEY = 'desired'
ERT3ADD2C_KEY = 'ert3add2c'
INTERVALSEC_KEY = 'interval_sec'
STATUS_KEY = 'status'
FAM3AD_CHNUM = {'AD04': 4, 'AD08': 8}
UNIT = 0
SLOT = 2
DEFAULT_INTERVAL_SEC = 2.0
LDCONFIGEXEC = 'ldconfig'
M3LIB_PATH = '/usr/local/lib/libm3.so.1'
DEVICE_ID = os.environ['IOTEDGE_DEVICEID']
OUTPUT_NAME = os.environ['IOTEDGE_MODULEID'] + 'ToIoTHub'
class AdD2C():
"""
Class implemented by each function that collects data from the AD module.
"""
def __init__(self, module_client, unit, slot):
"""
Contructor.
"""
self.__module_client = module_client
self.__unit = unit
self.__slot = slot
self.__message_no = 1
self.__libc = ctypes.cdll.LoadLibrary(M3LIB_PATH)
self.__libc.getM3IoName.restype = ctypes.c_char_p
self.__chnum = self.__get_m3ad_ch_num()
signal.signal(signal.SIGALRM, self.__signal_handler)
def __get_m3ad_ch_num(self):
"""
Decide on either AD08 or AD04.
"""
namebytes = self.__libc.getM3IoName(
ctypes.c_int(self.__unit), ctypes.c_int(self.__slot))
num = 0
if namebytes is not None:
num = FAM3AD_CHNUM.get(namebytes.decode(), 0)
return num
def __read_m3ad_ch_datas(self):
"""
Obtain data from all channels of AD module.
"""
short_arr = ctypes.c_short * self.__chnum
ch_datas = short_arr()
self.__libc.readM3IoRegister(
ctypes.c_int(self.__unit),
ctypes.c_int(self.__slot),
ctypes.c_int(1),
ctypes.c_int(self.__chnum),
ch_datas)
return ch_datas
def __signal_handler(self, signum, frame):
"""
Create message and send to edgeHub module.
"""
bodyDict = dict(
messageID=self.__message_no,
deviceID=DEVICE_ID,
datetime=datetime.datetime.utcnow().isoformat() + 'Z'
)
ch_datas = self.__read_m3ad_ch_datas()
for index, ch_value in enumerate(ch_datas):
bodyDict['ch' + str(index + 1)] = ch_value
bodyStr = json.dumps(bodyDict)
msg = Message(bodyStr, output_name=OUTPUT_NAME)
self.__module_client.send_message(msg)
print(bodyStr)
self.__message_no = self.__message_no + 1
def set_condition(self, desired):
"""
Configure the data collection frequency settings.
"""
if ERT3ADD2C_KEY not in desired:
return {STATUS_KEY: False}
interval_sec = desired[ERT3ADD2C_KEY].get(INTERVALSEC_KEY,
DEFAULT_INTERVAL_SEC)
reported = dict()
reported[ERT3ADD2C_KEY] = desired[ERT3ADD2C_KEY]
if interval_sec < 0.0:
reported[ERT3ADD2C_KEY][STATUS_KEY] = False
else:
signal.setitimer(signal.ITIMER_REAL, interval_sec, interval_sec)
reported[ERT3ADD2C_KEY][STATUS_KEY] = True
return reported
def send_ad_data():
"""
Call each function.
Monitor the changes in the module twin.
"""
module_client = IoTHubModuleClient.create_from_edge_environment()
module_client.connect()
twin = module_client.get_twin()
add2c = AdD2C(module_client, UNIT, SLOT)
reported = add2c.set_condition(twin.get(DESIRED_KEY, {}))
module_client.patch_twin_reported_properties(reported)
while True:
reported = add2c.set_condition(
module_client.receive_twin_desired_properties_patch()
)
module_client.patch_twin_reported_properties(reported)
module_client.disconnect()
if __name__ == "__main__":
subprocess.run([LDCONFIGEXEC])
send_ad_data()
注意:代码流作为代码中的注释解释。有关代码的其他信息在Python code details中描述。
构建和推动模块
重写main.py
并保存代码后,您必须将Python IoT Edge Data Collection模块推到容器注册表中。
按照以下步骤构建并将Python IoT Edge数据收集模块推向容器注册表:
- 在Visual Studio代码窗口的左窗格上,在项目文件夹中找到
deployment.template.json
文件。 -
右键单击
deployment.template.json
文件,然后选择构建并按下IoT Edge解决方案。Python IoT Edge数据收集模块是构建并将其推向容器注册表的。命令执行和执行结果的进度显示在窗口底部的终端窗格上。
注意:如果未正确配置代理设置,将Python IoT Edge数据收集模块推向容器注册表将失败。有关配置Visual Studio代码和Docker桌面代理设置的更多信息,请参考Proxy settings。
部署模块
构建Python IoT Edge数据收集模块并将其推到容器注册表后,我们必须在E-RT3 Plus设备上部署。
按照以下步骤部署python iot edge数据收集模块在e-rt3 plus上,来自Azure Portal:
- Open Azure Portal.
- 导航到您创建的物联网。
- 在左窗格上,在设备管理下部分,单击 IoT Edge 。
-
从显示的设备ID中,选择要部署模块的目标设备的ID。
出现设备信息。
-
单击设置模块。
-
在容器注册表凭据节中,确保配置凭据。有关配置凭据的更多信息,请参阅Creating a new project的步骤7。
注意:显示previous article中配置的
。PythonModule
和SimulatedTemperatureSensor
模块,请单击右侧的 delete 图标,将它们删除。 -
要配置Python IoT Edge数据收集模块的设置,请单击+add ,然后从下拉列表中选择 IoT Edge模块。
-
如下表所述配置IoT边缘模块的参数,然后单击 add 。
设置 要输入的信息 模块名称 模块名称 图像uri 从容器注册表的存储库中获得的图像URI。有关如何获取图像URI的信息,请参阅Image URI。 重新启动策略 始终(保留默认设置) 所需状态 跑步(保留默认设置) 图像拉策略 空(保留默认设置) -
单击容器创建选项选项卡,并在编辑器中指定选项如下。
{ "HostConfig": { "Binds": [ "/usr/local/lib/libm3.so.1.0.1:/usr/local/lib/libm3.so.1.0.1" ], "Devices": [ { "PathOnHost": "/dev/m3io", "PathInContainer": "/dev/m3io", "CgroupPermissions": "rwm" }, { "PathOnHost": "/dev/m3sysctl", "PathInContainer": "/dev/m3sysctl", "CgroupPermissions": "rwm" }, { "PathOnHost": "/dev/m3cpu", "PathInContainer": "/dev/m3cpu", "CgroupPermissions": "rwm" }, { "PathOnHost": "/dev/m3mcom", "PathInContainer": "/dev/m3mcom", "CgroupPermissions": "rwm" }, { "PathOnHost": "/dev/m3dev", "PathInContainer": "/dev/m3dev", "CgroupPermissions": "rwm" }, { "PathOnHost": "/dev/m3ras", "PathInContainer": "/dev/m3ras", "CgroupPermissions": "rwm" }, { "PathOnHost": "/dev/m3wdt", "PathInContainer": "/dev/m3wdt", "CgroupPermissions": "rwm" } ] } }
有关容器创建选项的更多信息,请参阅official documentation。
有关可以配置的设置的信息,请参阅Docker documentation。
注::库信息在
Binds
标签中指定,设备信息在Devices
标签中指定。 -
单击模块Twin设置选项卡并指定设置如下:
{ "ert3add2c": { "interval_sec": 2 } }
在这里,我们配置了2秒的间隔。这将配置Python模块,以在两秒钟的时间间隔内从模拟输入模块的所有通道收集数据。
-
单击应用。
-
单击路由选项卡,并按照下表所述配置详细信息。
名称 value yourmoduletoiothub 来自/消息/模块/ <yourModule>
/outputs/* to $ upstream在这里,我们配置了将数据从Python IoT Edge Data Collection模块发送到IoT Hub的路由。
注意:如果显示previous article中配置的路线,请单击右侧的 delete 图标,将它们删除。
-
单击评论 +创建并验证配置信息。
在屏幕的左上角,显示消息“验证”。
-
在验证配置信息后,在页面的左下角,单击 create 。
出现设备设置页面,并显示带有每个模块状态的模块列表。
-
验证以下信息:
- IoT Edge运行时响应必须显示为
200 - OK
。 - 所有模块的运行时状态([Edgeagent],[EdgeHub]和您部署的模块[yourmodule])必须显示为
running
。
注意:通常需要一些时间来查看部署的状态。如果不满足上述任何条件,请单击刷新查看最新信息。
- IoT Edge运行时响应必须显示为
验证模块操作
要验证模块操作,我们必须观察到以下结果:
-
View telemetry data in IoT Hub
验证在IoT Hub中收到Python IoT Edge数据收集模块发送的遥测数据。
-
View changes in operation corresponding to Module twin updates
要验证对模块Twin的更新反映在IoT Hub接收到的消息中,我们执行以下操作:
- 增加数据收集的频率并观察IoT中心处的相应变化。
- 将数据收集的频率设置为零。这停止了数据传输。
查看遥测数据
您可以以previous article中描述的方式验证Python IoT Edge数据收集模块的操作。
如果收到的遥测数据的格式如下,则Python IoT Edge数据收集模块正常运行。
{
"body": {
"messageID": 2034,
"deviceID": "test_ert3_f3rp70",
"datetime": "2021-01-26T03:50:58.445146Z",
"ch1": -1,
"ch2": 8,
"ch3": 1,
"ch4": 2,
"ch5": 0,
"ch6": 1,
"ch7": 3,
"ch8": 1
},
"enqueuedTime": "2021-01-26T03:50:58.476Z",
"properties": {}
}
注意:当使用8通道F3AD08时,传输了8个通道的数据。
更新模块twin并验证操作
我们可以从Azure Portal更新模块Twin,并验证模块操作是否相应地更改。
请按照以下步骤更新模块twin:
- 打开Azure portal并导航到您创建的IoT中心。
- 在左窗格上,在设备管理下部分,单击 IoT Edge 。
-
从显示的设备ID中,选择要部署模块的设备的ID。
出现设备信息。
-
单击设置模块,选择要修改的IoT边缘模块。
出现IoT边缘模块屏幕。
-
单击模块双设置选项卡。
显示模块的双信息。
-
根据需要在文本框中更新模块双信息。验证更新的信息,如果没有问题,请单击评论 +创建。
-
修改数据收集的频率
更新
interval_sec
的值以更改数据收集的频率。例如,我们将数据收集频率更新为5秒钟,如下所示:
{
"ert3add2c": {
"interval_sec": 5
}
}
-
停止数据收集
如果
interval_sec
的值设置为零,则停止数据收集,并且不会将消息发送到IoT Hub。
{
"ert3add2c": {
"interval_sec": 0
}
}
使用更新创建并部署该模块。部署完成后,请按以下方式验证操作:
1.如果您增加或降低了数据收集频率,则在物联网中心收到的遥测数据会发生相应的变化。
2.如果您停止数据收集,则在IoT中心未收到任何消息。
注意:如果要重新启动数据收集,请将
interval_sec
的值更改为大于1的值。
结论
来自模拟输入模块的数据是由E-RT3 Plus设备中部署的Python模块接收的。随后,可以在Azure IoT Hub中查看相同的数据,证明创建的Python模块是按预期运行的。在下一篇文章中,我们将创建一个物联网边缘模块,该模块将数据写入连接到E-RT3 Plus设备的模拟输出模块中。
附录
图像URI
要获得图像URI,请按照以下步骤:
- 打开Azure Portal并导航到容器注册表。
- 在左窗格上,在服务下类别,单击存储库。
- 从显示的存储库列表中,单击要部署的存储库ID。
-
从显示的标签中,单击要部署的标签。
注意:标签以
<version_number>-<target_device>
格式显示。 -
确认标签中的目标设备显示为
arm32v7
。显示存储库详细信息。在 docker pull命令框中,
main.py
之后显示的内容是图像uri。注意:图像URI处于格式
<registry name>.azurecr.io/<module name>:<tag>
。
Python代码详细信息
代码的流程在Python代码中的注释中被解释为注释。在这里,我们描述了其他详细信息:
库
以下库是导入的:
-
ctypes
ctypes
库提供C兼容的数据类型,并允许在DLL或共享库中调用功能。由于E-RT3 Plus设备在C语言上运行的功能,我们导入ctypes
库。
import ctypes
-
IoTHubModuleClient
IoTHubModuleClient
库是Azure IoT Hub SDK的一部分。这是一个同步模块客户端,可连接到Azure IoT轮毂或Azure IoT Edge实例。有关IoTHubModuleClient
库的更多信息,请单击here。
from azure.iot.device import IoTHubModuleClient
-
Message
Message
库是Azure IoT Hub SDK的一部分。它代表了与Iothub或来自Iothub的消息。有关Message
库的更多信息,请单击here。
from azure.iot.device import Message
-
访问模拟输入模块的库不包含在Python Iot Edge数据集模块中,而是绑定到CPU模块(host)库并使用的。
定义
以下定义提供了python ioT边缘数据收集模块中e-rt3 plus的符号链接的值。
M3LIB_PATH = '/usr/local/lib/libm3.so.1'
E-RT3加上功能
Python模块使用以下E-RT3加上功能:
-
getM3IoName
此功能通过指定单元和插槽ID来获得模块ID。
函数定义如下:
char* getM3IoName (int unit, int slot);
-
readM3IoRegister
此函数通过指定单元,插槽,频道读取I/O寄存器的数据,您需要从中读取数据,要读取的频道数量以及数据存储位置。
函数定义如下:
int readM3IoRegister(int unit, int slot, int pos, int num, unsigned short *data);
其他功能
subprocess.run([LDCONFIGEXEC])
此功能用于将F3RP70-2L的/usr/local/lib/libm3.so.1.0.1
绑定到Python IoT边缘数据收集模块的/usr/local/lib/libm3.so.1.0.1
。
它生成了库的符号链接,并在主函数的开头调用,以在部署python iot edge数据集合模块时在e-rt3 plus中使用库。
。有效载荷格式
以下格式创建了发送数据的有效载荷:
{
"body": {
"messageID": 1,
"deviceID": "{deviceID}",
"datetime": "2020-01-01T00:00:00.000Z",
"ch1": 123,
"ch2": 234,
"ch3": 345,
"ch4": 456,
"ch5": 567,
"ch6": 678,
"ch7": 789,
"ch8": 890
}
}
在这里,
messageID
是消息的ID。消息ID是从1开始的数字序列生成的。
deviceID
是指部署Python IoT Edge数据收集模块的目标设备的ID,
datetime
是指CPU模块获取数据的时间,
ch1
-ch8
是指从每个通道中获取的数据。
参考
- Real-time OS controller e-RT3 Plus F3RP70-2L
- Azure Certified Device catalog
- Visualize real-time sensor data from your Azure IoT hub in a web application
- Tutorial: Visualize real-time sensor data from Azure IoT Hub using Power BI
- Tutorial: Develop IoT Edge modules with Linux containers
- Tutorial: Develop and deploy a Python IoT Edge module using Linux containers
- Summary and usage methods of Azure IoT Hub SDK