diff --git "a/docs/Application_guide/zh/media/solutions/DTU/4G\350\203\266\346\243\222\345\244\251\347\272\277.jpg" "b/docs/Application_guide/zh/media/solutions/DTU/4G\350\203\266\346\243\222\345\244\251\347\272\277.jpg" new file mode 100644 index 0000000000000000000000000000000000000000..66650e405222f9a0b82509fa5424ea2b672bcd7f Binary files /dev/null and "b/docs/Application_guide/zh/media/solutions/DTU/4G\350\203\266\346\243\222\345\244\251\347\272\277.jpg" differ diff --git a/docs/Application_guide/zh/media/solutions/DTU/DTU_wires_connection.png b/docs/Application_guide/zh/media/solutions/DTU/DTU_wires_connection.png new file mode 100644 index 0000000000000000000000000000000000000000..2a1a5497716fd2ed4ffc8f5a71a67e8a7f2f4652 Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/DTU/DTU_wires_connection.png differ diff --git a/docs/Application_guide/zh/media/solutions/DTU/EC800GCN.png b/docs/Application_guide/zh/media/solutions/DTU/EC800GCN.png new file mode 100644 index 0000000000000000000000000000000000000000..6c57b10d315acb2eed67fe9c992f62b614763aec Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/DTU/EC800GCN.png differ diff --git a/docs/Application_guide/zh/media/solutions/DTU/HuaDTU.jpg b/docs/Application_guide/zh/media/solutions/DTU/HuaDTU.jpg new file mode 100644 index 0000000000000000000000000000000000000000..59f79e566d9b94b02f722ead1cdaad1252a51e6b Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/DTU/HuaDTU.jpg differ diff --git a/docs/Application_guide/zh/media/solutions/DTU/UML.png b/docs/Application_guide/zh/media/solutions/DTU/UML.png new file mode 100644 index 0000000000000000000000000000000000000000..ad7cd0c464d62cde72d699ffbfcc0c7c7ada8c31 Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/DTU/UML.png differ diff --git a/docs/Application_guide/zh/media/solutions/DTU/cloud_down.png b/docs/Application_guide/zh/media/solutions/DTU/cloud_down.png new file mode 100644 index 0000000000000000000000000000000000000000..0feebf83cab55858bcc9ec36b1954f283e8e66d8 Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/DTU/cloud_down.png differ diff --git a/docs/Application_guide/zh/media/solutions/DTU/cloud_up.png b/docs/Application_guide/zh/media/solutions/DTU/cloud_up.png new file mode 100644 index 0000000000000000000000000000000000000000..6a93ab866a6e9148e17bce5541286d75a7729fda Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/DTU/cloud_up.png differ diff --git a/docs/Application_guide/zh/media/solutions/DTU/debug_log.png b/docs/Application_guide/zh/media/solutions/DTU/debug_log.png new file mode 100644 index 0000000000000000000000000000000000000000..f56e908927718dacf402095c07180bc33d70651c Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/DTU/debug_log.png differ diff --git a/docs/Application_guide/zh/media/solutions/DTU/debug_log_down_data.png b/docs/Application_guide/zh/media/solutions/DTU/debug_log_down_data.png new file mode 100644 index 0000000000000000000000000000000000000000..b020bdacebfc014c0b76610e9d7e1d712e196a33 Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/DTU/debug_log_down_data.png differ diff --git a/docs/Application_guide/zh/media/solutions/DTU/debugview.png b/docs/Application_guide/zh/media/solutions/DTU/debugview.png new file mode 100644 index 0000000000000000000000000000000000000000..ceb61c02b8301368c4c8c8d36229797cc8f9248e Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/DTU/debugview.png differ diff --git a/docs/Application_guide/zh/media/solutions/DTU/download_scripts.png b/docs/Application_guide/zh/media/solutions/DTU/download_scripts.png new file mode 100644 index 0000000000000000000000000000000000000000..034704cb7628bc86bbeedc9b21aba6705b0ee163 Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/DTU/download_scripts.png differ diff --git a/docs/Application_guide/zh/media/solutions/DTU/dtu_graph.png b/docs/Application_guide/zh/media/solutions/DTU/dtu_graph.png new file mode 100644 index 0000000000000000000000000000000000000000..e4a29ee2c7464a9dfd39a4d3e6afd85c556d9340 Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/DTU/dtu_graph.png differ diff --git a/docs/Application_guide/zh/media/solutions/DTU/dupont.png b/docs/Application_guide/zh/media/solutions/DTU/dupont.png new file mode 100644 index 0000000000000000000000000000000000000000..d04543958240f2e29e82f2dcfca4a754a6cee8ac Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/DTU/dupont.png differ diff --git a/docs/Application_guide/zh/media/solutions/DTU/flowchart.png b/docs/Application_guide/zh/media/solutions/DTU/flowchart.png new file mode 100644 index 0000000000000000000000000000000000000000..00cb771a230a7035fc9ae1a4be30d955c092ba3a Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/DTU/flowchart.png differ diff --git a/docs/Application_guide/zh/media/solutions/DTU/gitbash.png b/docs/Application_guide/zh/media/solutions/DTU/gitbash.png new file mode 100644 index 0000000000000000000000000000000000000000..45d0f79ff5b0466097693d3bc91505f503a4a723 Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/DTU/gitbash.png differ diff --git a/docs/Application_guide/zh/media/solutions/DTU/mini_usb.png b/docs/Application_guide/zh/media/solutions/DTU/mini_usb.png new file mode 100644 index 0000000000000000000000000000000000000000..ec4361fd79f4bdd719630867ca2a0df58016996d Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/DTU/mini_usb.png differ diff --git a/docs/Application_guide/zh/media/solutions/DTU/qcom_down.png b/docs/Application_guide/zh/media/solutions/DTU/qcom_down.png new file mode 100644 index 0000000000000000000000000000000000000000..e5e661ad34343b1496497e97630d0e7ca78eb4e4 Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/DTU/qcom_down.png differ diff --git a/docs/Application_guide/zh/media/solutions/DTU/qcom_test.png b/docs/Application_guide/zh/media/solutions/DTU/qcom_test.png new file mode 100644 index 0000000000000000000000000000000000000000..69f9bc5177a6a1c31ad03be86802bb6e83802b43 Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/DTU/qcom_test.png differ diff --git a/docs/Application_guide/zh/media/solutions/DTU/repl_logs.png b/docs/Application_guide/zh/media/solutions/DTU/repl_logs.png new file mode 100644 index 0000000000000000000000000000000000000000..785382aef1fe3cea174d9108d1807edef2dbb84a Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/DTU/repl_logs.png differ diff --git a/docs/Application_guide/zh/media/solutions/DTU/run_scripts.png b/docs/Application_guide/zh/media/solutions/DTU/run_scripts.png new file mode 100644 index 0000000000000000000000000000000000000000..ccd49d4a8a6711bd0674297709cdfe733f2668da Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/DTU/run_scripts.png differ diff --git a/docs/Application_guide/zh/media/solutions/DTU/sim_card.png b/docs/Application_guide/zh/media/solutions/DTU/sim_card.png new file mode 100644 index 0000000000000000000000000000000000000000..4d49057b4f9179495c1c946403273af14d20e7db Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/DTU/sim_card.png differ diff --git a/docs/Application_guide/zh/media/solutions/DTU/usb_ttl.png b/docs/Application_guide/zh/media/solutions/DTU/usb_ttl.png new file mode 100644 index 0000000000000000000000000000000000000000..cc0e9fd13517673a255ca1b31a33dd975fdc46ea Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/DTU/usb_ttl.png differ diff --git a/docs/Application_guide/zh/sidebar.yaml b/docs/Application_guide/zh/sidebar.yaml index 8c7c4b53b825481383cc5a25b5d534db36fab9e4..a2c162a00fbe88e0160b2c576dadb45c49b4d200 100644 --- a/docs/Application_guide/zh/sidebar.yaml +++ b/docs/Application_guide/zh/sidebar.yaml @@ -265,8 +265,20 @@ items: - label: 产品方案 file: solutions/README.md items: - - label: DTU 方案 + - label: EP-D200 华系列 DTU file: solutions/DTU/README.md + items: + - label: 开发资源汇总 + file: solutions/DTU/dev_resources.md + - label: 快速上手 + file: solutions/DTU/quick_start.md + items: + - label: 基于 TCP 协议的设备开发 + file: solutions/DTU/tcp_demo.md + - label: 基于 MQTT 协议的设备开发 + file: solutions/DTU/mqtt_demo.md + - label: 软件设计讲解 + file: solutions/DTU/software_design.md - label: 智慧农业中控面板 file: solutions/Agriculture-Control-Panel/README.md - label: 可穿戴解决方案 diff --git a/docs/Application_guide/zh/solutions/DTU/README.md b/docs/Application_guide/zh/solutions/DTU/README.md index 0378887c512cf201b32670431feea5c13af8855b..6baa5d2049d3d85088a65f50e9165619e60d2cdf 100644 --- a/docs/Application_guide/zh/solutions/DTU/README.md +++ b/docs/Application_guide/zh/solutions/DTU/README.md @@ -1,549 +1,26 @@ -# DTU方案介绍及应用指导 +# EP-D200 华系列 DTU -## 方案概述 +华系列 DTU 产品搭载移远 EC800G-CN 模块,支持 4G Cat1 全网通,可实现串口与 4G(CAT1)的数据互传,相比于传统 2G/3G 网络,覆盖更广、速率更快、延时更低。采用宽电(9~36V)供电。接口丰富,提供 RS232、RS485 和 TTL 三种接口可选。开发方便快捷,支持透传,支持 Python 二次开发。安全可靠,支持软、硬件看门狗守护。体型小巧安装方便(22.6 * 74.6 mm)。 本产品方案支持 4G 全网通,采用宽电压(9~36V)供电,提供 RS232、RS485 和 TTL 三种接口,可使本产品应用于各种行业和复杂场景满足通信数传的需求,如电网、交通、消防、工业生产、气象环境、农业、矿产等等。 -### DTU简介 +**功能列表**: -DTU (Data Transfer Unit,数据传输单元),是专门用于将串口**数据转换**为网络数据或将网络数据转换为串口数据通过无线**通信网络**进行传送的**无线终端设备**。具备组网迅速灵活,网络覆盖范围广,建设周期短、成本低等诸多优点。广泛应用于气象、水文水利、地质等行业。 +- 支持 Mqtt 透传 +- 支持 TCP/UDP 透传 +- 支持 RS485 转 4G +- 支持 4G 全网通 +- 支持 Python 语言二次开发 +- 支持 9~36V 宽幅供电 +- POWER/DATA/WORK 指示灯 -### 基本原理 +**产品图示**: -DTU主要功能就是把设备的数据通过无线的方式传送回云端(后台服务),如`图1:《DTU简介》`中所示,要完成数据传输需要建立一套完成的数据传输系统,这个系统中包括:DTU设备、客户设备(MCU)、移动网络、后台中心(云端)。在DTU设备中插入一张SIM卡,待设备上电后先**拨号和注册网络**;然后通过网络与云端中心服务**建立连接**;后续,DTU设备可以与云端后台服务**双向通信** —— 通过串口接收MCU数据经过处理后上报给云端(**数据上行**),DTU接收云端数据经过处理后通过串口发送给MCU(**数据下行**)。 + -![](../../media/solutions/DTU/DTU.png) +## 开发指南 -
图1 DTU简介
-> 传感器(温度、湿度等传感器)采集数据发送给设备端MCU,设备端MCU通过串口将采集到的数据通过DTU发送到云端中心服务器,服务器接收到数据可以进行分析、处理、显示、保存等操作。 +[开发资源汇总](./dev_resources.md) -### 应用领域 - -![](../../media/solutions/DTU/DTU应用领域.jpg) - -
图2 DTU应用领域
-## 硬件选型 - - 本方案支持多款QuecPython硬件设备,下面介绍`QuecPython EVB开发板`和`DP-DTU-Q600`。 - -#### QuecPython_EVB开发板介绍 - -以搭载了`EC200U`模组的开发板`QuecPython_EC2X_EVB_V2.0` (EC2X开发板介绍:)为例。 - -如下图所示,设备使用type-c给模块供电,UART与TTL转USB模块连接至开发电脑,可轻松实现调试。 - -![](../../media/solutions/DTU/quecpython_evb.png) - -
图3 QuecPython_EC2X_EVB_V2.0使用UART与TTL转USB连接电脑
- - - - -| 开发板上的PIN脚 | TTL转USB模块 | 图中线的颜色 | -| --------------- | ------------ | ------------ | -| J7的13脚(TX) | RX | 红线 | -| J7的14脚(RX) | TX | 橙线 | -| J7的3脚(GND) | GND | 黄线 | - -更多开发板请参阅: - -#### DP-DTU-Q600产品介绍 - -DP-DTU-Q600 是一款 LTE CAT1 网络的 DTU,方便集成到工控机、工业设备、传感设备里,其物理尺寸为 72mm x 40.5mm x 20mm 产品具备网络覆盖广、传输延时低的特点,支持三大运营商接入;产品有三个指示灯,方便客户确认设备状态。 - -![](../../media/solutions/DTU/DP-DTU-Q600.png) - -
图4 DP-DTU-Q600
-产品规格: - -| 规格 | 参数 | -| ---------- | -------------------- | -| 供电范围 | DC5-24V | -| DC5-24V | 2PIN 端子 | -| 天线接口 | SMA 外螺纹内孔 | -| SIM 卡接口 | 自弹式 NANO SIM 卡槽 | -| 网络制式 | 4G CAT1 全网通 | -| 通信接口 | 2PIN 端子 RS485 | - -产品特点: - -- 内部集成TCP/IP协议栈,并且具有嵌入式操作系统, 具备拨号上网以及TCP/IP数据通信的功能 -- 提供串口数据双向转换功能 -- 支持自动心跳,保持永久在线 -- 支持参数配置,永久保存 -- 支持用户串口参数设置 -- 支持用户二次开发 -- 物联网卡,无需特殊卡,一般物联网卡都可使用 -- NANO SIM 卡槽 -- RS485 接口,方便集成 - -设备调试: - -- 在NANO SIM卡座中插入SIM卡 -- 连接好天线 -- 接入电源 - -![](../../media/solutions/DTU/DP-DTU-Q600硬件接口图示2.png) - -
图5 DP-DTU-Q600硬件接口
-连接设备至开发机(本文采用`CP2102 USB to TTL模块`进行连接和调试)。 - -使用2根杜邦线分别连接`485A`、`485B`针脚,将`CP2102`连接至开发机的`USB`口(如图6所示)。 - -![](../../media/solutions/DTU/DTU_BOARD_003.jpg) - -
图6 DP600R连接开发机
-> 连接成功后,设备上电以及连接网络后`power`和`net`指示灯亮起。 - -#### 使用QPYcom调试 - -安装QPYCom以及搭建QuecPython开发环境参考文档:。 - -##### 打开repl串口 - - - -![](../../media/solutions/DTU/qpycom_select_port2.png) - -
图7 QPYCom打开repl串口
-##### 下载脚本 - -创建下载项目 —— 切换到下载选项卡,点击创建项目,并输入任意项目名称。 - -> 此处我们创建名为`dtu`的项目。 - -![](../../media/solutions/DTU/qpycom_proj2.png) - -
图8 QPYCom新建项目
-选择导入文件 —— 右击`usr`目录,在弹出的选择框中点击**一键导入**,继而选择我们DTU代码仓库中的**code**文件夹 —— 即将code中的所有代码一键导入至模组。如下图所示: - -![](../../media/solutions/DTU/qpycom_add_file2.png) - -
图9 QPYCom一键导入脚本
-导入脚本 —— 点击右下角`下载脚本`按钮,即可开始导入脚本。 - -##### 运行DTU应用 - -切换至"文件"选项卡,在右边选中"dtu.py",点击运行按钮,即可开始dtu调试运行,如果需要上电自动运行,只需要将"dtu.py"更名为"main.py"即可实现上电自动运行。 - -![](../../media/solutions/DTU/qpycom_run2.png) - -
图10 QPYCom执行脚本
-DTU运行成功,在QPYcom的"交互"窗口中,可观察到打印如下。 - -> 应用程序运行依赖具体用户参数配置,比如配置MQTT连接参数等。参考后续DTU方案介绍章节。 - -![](../../media/solutions/DTU/dtu_init2.png) - -
图11 QPYCom脚本输出日志
-## 方案软件设计 - -### 系统框图 - -![](../../media/solutions/DTU/DTU组件图示4.png) - -
图12 DTU方案系统图示
-组件说明: - -- 各类云对象:继承`modules.CloudObservable`并重写相应方法,主要实现云端初始化、连接以及数据收发等功能。 -- 订阅器:继承`modules.CloudObserver`并重写相应方法,主要实现订阅并接收云端对象的消息通知,并根据消息类型调用不同的执行器去处理。 -- 执行器:主要用于具体的业务处理,被订阅器所调用,默认有下行执行器(处理下行数据转发串口)、OTA升级执行器(处理升级消息和触发升级)、上行执行器(主要用于处理上行数据)。 -- 发布器:主要关联云端对象,用于将数据发布给云端。 - -组件协作流程: - -- 构建串口对象 —— 通常至少有一个串口作为通信通道使用,根据实际情况选择使用多个或一个串口。 -- 构建下行数据执行器和OTA升级执行器 —— 执行器主要用作于业务处理,用户需要在执行器中实现具体的业务处理逻辑方法。 - - 下行数据执行器需添加一个串口对象,用于处理下行消息 —— 通过串口转发。 - - OTA升级执行器,需要实现具体的升级业务流程。 -- 创建云端对象 一一 支持阿里云、腾讯云、MQTT等,根据实际业务需求导入使用。 -- 创建订阅器。 - - 云端对象添加订阅器作为其观察者。 - - 订阅器可以有多个,对应下行消息多路处理。 -- 创建发布器。 - - 添加云端对象,作为发布器发布消息的⽬标对象。 -- 创建上⾏数据执⾏器。 - - 上⾏数据执⾏器,主要⽤于接收串⼝数据处理。 - - 添加⼀个发布器⽤作该执⾏器发布消息,具体该消息如何发布由发布器来决定。 - -> 下行数据支持多路,**订阅器**作为一个观察者可以有多个,当一个云端添加多个订阅器后,一旦有消息下行,则会通知所有订阅器,不同的订阅器可能通过不同的**下行执行器**或**OTA升级执行器**对数据进行处理。 -> -> 上行数据支持多路,当需要监听多个串口数据,可以有多个**上行执行器**将多个串口数据转发云端。 - -### 观察者模式 - -- **概念:**当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知依赖它的对象。观察者模式属于行为型模式。 -- **意图:**定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。 -- **主要解决:**一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。 -- **何时使用:**一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知,进行广播通知。 -- **关键代码:**在抽象类里有一个列表存放观察者们。 - -在DTU方案设计中,一个云端类(`Socket`和`MqttIot`)对象都是一个**被观察者**,当有下行数据时,会**通知**`RemoteSubscribe`(订阅器,**一个观察者**),而`RemoteSubscribe`会根据不同业务从而调用不同的**执行器**来处理。 - -### 组件类设计与交互 - -#### 类继承 - -##### 云端类继承图示 - -```mermaid -graph TD; -CloudObservable[CloudObservable] -CloudObservable --> MqttIot[MqttIot] -CloudObservable --> AliYunIot[AliYunIot] -CloudObservable --> HuaweiIot[HuaweiIot] -CloudObservable --> QuecThing[QuecThing] -CloudObservable --> Socket[Socket] -CloudObservable --> TXYunIot[TXYunIot] -``` - -**CloudObservable**: 可被观察者类,主要用于定义各种云对象类时被继承和重写。主要用户接口有: - -- init:云端初始化 - -- addObserver: 添加一个观察者对象 -- delObserver:移除一个观察者对象 -- notifyObservers:通知所有观察者 -- through_post_data:透传数据发布 -- post_data:云端消息发布 -- ota_request:云端发布OTA升级请求 -- ota_action:执行升级动作 - -##### 订阅器类继承图示 - -```mermaid -graph TD; -CloudObserver[CloudObserver] --> RemoteSubscribe[RemoteSubscribe] -``` - -**CloudObserver**:观察者对象类,主要用于被动接收通知。主要有以下方法: - -- `execute`:在被被观察者通知后,会调用该方法执行具体动作。 - -**RemoteSubscribe**: 订阅器,是一个观察者,用于接收云端下行数据通知。主要方法有: - -- `execute`:当被通知时,调用该方法执行具体的业务处理流程。(不同的业务使用不同的执行器处理,在该类对象中定义2种执行器:`__executor`(普通执行器),`__ota_executor`(专用于执行ota升级的执行器)) -- `add_executor`:添加执行器。 - -#### 下行数据处理 - -下行数据处理时序图: - -```mermaid -sequenceDiagram -Title: Device downlink data processing timing - -participant cloud as Cloud[mqtt] -participant mqtt as MqttIot -participant rs as RemoteSubscribe -participant executor as Executor - -mqtt -->> cloud: connect cloud & subscribe -rs -->> executor: add executor -mqtt -->> rs: add observer -rs -->> rs: Waiting for notification - -cloud ->> mqtt: downlink data -mqtt ->> rs: notify observer(carrying downlink data) -rs ->> executor: call executor -``` - -本方案中定义处理下行数据的执行器有两种: - -- `DownlinkTransaction`:下行数据执行器,负责将云端数据通过串口转发。 -- `OtaTransaction`:OTA升级执行器,负责处理升级相关业务。 - -举个例子,当有下行数据时。假设为透传数据,会调用`DownlinkTransaction`执行器通过串口转发数据给MCU;假设为OTA升级消息,则会调用`OtaTransaction`执行器执行升级流程。 - -#### 上行数据处理 - -上行数据处理时序图: - -```mermaid -sequenceDiagram -Title: Device uplink data processing timing - - -participant cloud as Cloud[mqtt] -participant mqtt as MqttIot -participant rp as RemotePublish -participant executor as UplinkTransaction - - -mqtt -->> cloud: connect cloud & subscribe -rp -->> mqtt: add cloud -executor -->> rp: add publisher -executor -->> executor: read serial data - -executor ->> rp: uplink data -rp ->> mqtt: check connect status -mqtt ->> rp: report connect status -rp ->> mqtt: reconnect according to status - -rp ->> mqtt: uplink data -mqtt ->> cloud: uplink data -``` - -本方案中定义处理上行数据执行器有一种: - -- `UplinkTransaction`:上行数据执行器,用于接收串口数据并上传云端。 - - 主要属性: - - `__remote_pub`: 远程发布器,用于上传数据至云端。是`modules.remote.RemotePublish`类对象。 - - `__serial`: 串口对象,用于串口数据收发。定义于`modules.serial.Serial`。 - - 主要方法: - - `uplink_main`:用于接收串口数据,并上传云端。 - -## 方案用户使用说明 - -### 编写配置文件 - -DTU配置文件路径:`code/dtu_config.json`。 - -基于mqtt私有云做如下配置: - -- 系统配置 - -![system_config.png](../../media/solutions/DTU/system_config.png) - -- mqtt私有云配置 - -![mqtt_config.png](../../media/solutions/DTU/mqtt_config.png) - -设备端接口调用流程(接口调用逻辑、参数配置)、上位机工具配置参数、云端配置 - -### DTU初始化流程及接口说明 - -`code/dtu.py`中定义了应用类`Dtu`,其实例为应用对象,调用方法`start`即启动应用服务。 - -```python -from usr.dtu import Dtu - -if __name__ == "__main__": - dtu = Dtu() - dtu.start() -``` - -#### 类`Dtu`接口说明 - -类`Dtu`中定义如下方法,说明如下所示(说明⻅代码中的注释部分,完整代码参阅`dtu.py`使⽤示 例)。 - -```python -class Dtu(Singleton): - - def __init__(self): - # 定义一个定时器,用于定时检查OTA升级计划 - self.__ota_timer = osTimer() - # OTA升级执行器,用于执行OTA升级相关业务 - self.__ota_transaction = None - - def __cloud_init(self, protocol): - # 根据传入protocol参数指定协议,来初始化云端对象和连接云端 - # 该参数对应配置项`system_config.cloud` - pass - - def __periodic_ota_check(self, args): - # 定时检查OTA升级计划 - pass - - def start(self): - # 初始化DTU,以及启动各项服务 - pass -``` - -#### 应用服务初始化流程说明 - -DTU应用服务在`start`函数调用后即初始化和启动各项服务。 - -初始化流程: - -- 加载系统配置 -- 创建串口通信对象(`usr.modules.serial.Serial`) -- 创建云端对象(`usr.modules.mqttIot.MqttIot`或其他云对象) -- 创建GUI工具通信对象(`usr.modules.dtu_transaction.GuiToolsInteraction`) -- 创建数据上行执行器(`usr.modules.dtu_transaction.UplinkTransaction`) -- 创建数据下行执行器(`usr.modules.dtu_transaction.DownlinkTransaction`) -- 创建OTA升级执行器(`usr.modules.dtu_transaction.OtaTransaction`) -- 创建订阅器(`usr.modules.remote.RemoteSubscribe`) -- 创建发布器(`usr.modules.remote.RemotePublish`) -- 启动定时器定期检查OTA升级计划 -- 创建服务线程持续读取串口数据,解析并上传至云端 - -流程步骤详细说明: - -(1)加载系统配置 - -```python -from usr.settings import settings -``` - -`settings`是一个全局的配置文件(`Settings`)对象,对应是`/usr/dtu_config.json`配置文件参数,采用json格式持久化。 - -方法: - -- `get`:获取当前所有配置参数(即json文件导入的dict类型数据) -- `set(opt, val)`:设置`opt`配置项,参数是`val`。 -- `save`:持久化保存配置。 -- `remove`:删除配置文件。 -- `reset`:恢复默认配置。 -- `set_multi(**kwargs)`:批量设置参数。 - -(2)创建串口通信对象 - -```python -from usr.modules.serial import Serial - -# Serial initialization -serial = Serial(int(uart_setting.get("port")), - int(uart_setting.get("baudrate")), - int(uart_setting.get("databits")), - int(uart_setting.get("parity")), - int(uart_setting.get("stopbits")), - int(uart_setting.get("flowctl")), - uart_setting.get("rs485_direction_pin")) -``` - -`serial`是一个串口通信对象(`Serial`)。 - -方法: - -- `write(data)`:传入写入data字节。 -- `read(n, timeout)`: 串口读n个字节,超时时间为timeout。 - -(3)创建云端对象 - -`Dtu.__init_cloud`方法用于创建云端对象(根据系统配置文件,创建不同的云端对象)。 - -```python -class Dtu(object): - - def __init_cloud(self, protocol): - if protocol == 'mqtt': - cloud_config = settings.current_settings.get("mqtt_private_cloud_config") - client_id = cloud_config["client_id"] if cloud_config.get("client_id") else modem.getDevImei() - cloud = MqttIot(cloud_config.get("server", None), - int(cloud_config.get("qos", 0)), - int(cloud_config.get("port", 1883)), - cloud_config.get("clean_session"), - client_id, - cloud_config.get("username"), - cloud_config.get("password"), - cloud_config.get("publish"), - cloud_config.get("subscribe"), - cloud_config.get("keep_alive") - ) - cloud.init(enforce=True) - return cloud - else: - # 略,其他云端对象初始化参阅`code/dtu.py` - pass - - def start(self): - # ... - cloud = self.__cloud_init(settings.current_settings["system_config"]["cloud"]) - # ... -``` - -以MQTT为例,从系统配置文件中读取mqtt配置参数,实例化`MqttIot`对象传入参数,并调用`MqttIot.init`方法完成云对象的初始化操作。 - -方法: - -- `addObserver`: 添加观察者对象,用于云端在接收下行数据后,交由该对象处理。 - - 订阅器:当接收云端通知(携带下行数据)后,调用执行器处理。 - -(4)创建GUI工具通信对象 - -```python -gui_tool_inter = GuiToolsInteraction() -``` - -GUI通信对象`GuiToolsInteraction`,用于解析串口下发的上位机指令,并处理具体指令业务。 - -方法: - -- `parse_serial_data`:解析串口数据。 - -(5)创建数据上行执行器 - -```python -up_transaction = UplinkTransaction() -up_transaction.add_module(serial) -up_transaction.add_module(gui_tool_inter) -``` - -方法: - -- `add_module`:添加模块对象。 - - 串口对象:上行执行器通过串口对象读取串口数据。 - - GUI通信对象,通过GUI对象解析读取到的串口数据。 - - 发布器对象,通过该对象将数据发布给云端。 -- `uplink_main`:读取串口数据,并使用GUI对象解析(如果是指令数据则处理指令业务,如果是上行数据则转发给云端)。 - -(6)创建数据下行执行器 - -```python -down_transaction = DownlinkTransaction() -down_transaction.add_module(serial) -``` - -方法: - -- `add_module`:添加模块对象 - - 串口对象:下行执行器,通过串口对象转发下行数据。 -- `downlink_main`:用于处理下行数据。 - -(7)创建OTA升级执行器 - -```python -ota_transaction = OtaTransaction() -``` - -方法: - -- `ota_check`:检查OTA升级计划 -- `event_ota_plain`:响应升级计划(在接收到下发的升级计划后,校验参数和启动升级流程) -- `add_module`:添加模块对象 - - 发布器对象:通过发布器对象上报升级状态,或者主动请求升级计划。 - -(8)创建订阅器 - -```python -remote_sub = RemoteSubscribe() -remote_sub.add_executor(down_transaction, 1) -remote_sub.add_executor(ota_transaction, 2) -cloud.addObserver(remote_sub) -``` - -方法: - -- `add_executor`:添加执行器。 - - 下行执行器:通过串口转发数据。 - - OTA升级执行器:解析下行升级消息,并处理升级请求。 - -(9)创建发布器 - -```python -remote_pub = RemotePublish() -remote_pub.add_cloud(cloud) -up_transaction.add_module(remote_pub) -ota_transaction.add_module(remote_pub) -``` - -方法: - -- `add_cloud`:添加云端对象,用该云端对象发布消息。 - -(10)启动定时器定期检查OTA升级计划 - -```python -# 每600秒检测一次升级计划 -self.__ota_timer.start(1000 * 600, 1, self.__periodic_ota_check) -``` - -(11)创建服务线程持续读取串口数据,解析并上传至云端 - -```python -# Start uplink transaction -_thread.start_new_thread(up_transaction.uplink_main, ()) -``` - -启动单独线程执行`up_transaction.uplink_main`,`uplink_main`方法中,持续读取串口数据,使用`GuiToolsInteraction`解析串口数据处理上位机指令,或使用`RemotePublish`转发数据给云端。 +[快速上手](./dev_resources.md) +[软件设计讲解](./software_design.md) diff --git a/docs/Application_guide/zh/solutions/DTU/dev_resources.md b/docs/Application_guide/zh/solutions/DTU/dev_resources.md new file mode 100644 index 0000000000000000000000000000000000000000..84094db82f483b094fabbdb747a667eb07f30d49 --- /dev/null +++ b/docs/Application_guide/zh/solutions/DTU/dev_resources.md @@ -0,0 +1,58 @@ +# 开发资源汇总 + +本文档针对华系列 QuecPython 4G DTU,搜集和罗列了所需的硬件资源清单以及相关的配套资料。 + +## 开发板资料 + +- 型号:[EC800GCN 华系列 DTU 开发板](https://python.quectel.com/doc/Getting_started/zh/evb/ec800g_hua_dtu.html) +- 购买链接:[点此跳转](https://www.quecmall.com/goods-detail/2c9080168ef07110018f1853d4050002) +- 开发板文档: + - [EC800G_华-DTU系列开发板产品规格及用户指导](https://python.quectel.com/wp-content/uploads/2024/09/EC800G_华-DTU系列开发板产品规格及用户指导.pdf) + +## 模组资料 + +- 型号:[EC800GCN](https://python.quectel.com/modules-cat/ec800g-series) +- 规格书: [Quectel_EC800G-CN_LTE_Standard_模块产品规格书](https://python.quectel.com/wp-content/uploads/2024/09/Quectel_EC800G-CN_LTE_Standard_%E6%A8%A1%E5%9D%97%E4%BA%A7%E5%93%81%E8%A7%84%E6%A0%BC%E4%B9%A6_V1.3.pdf) +- 驱动下载:[QuecPython_USB_Driver_Win10_U_G](https://python.quectel.com/wp-content/uploads/2024/09/Quectel_Windows_USB_DriverU_V1.0.19.zip) + +## 配件资料 + +- 4G胶棒天线(1根) + - 型号: YECT012W1A + - 购买链接:[点击跳转](https://www.quecmall.com/goods-detail/2c90800c92239d5401923be899bc002c) +- Nano Sim 卡 (1张) +- Mini USB 数据线 (1根) +- USB 转 TTL 模块(1个) + - 型号: QTMU0085DP + - 购买链接:[点击跳转](https://www.quecmall.com/goods-detail/2c90800b8eec5c8e018f659f669c0043) + +## 开发工具 + +- QPYcom - QuecPython 调试工具 + - 版本:V3.6.0 + - 下载链接:[QPYcom](https://images.quectel.com/python/2022/12/QPYcom_V3.6.0.zip) +- QCOM - 串口调试工具 + - 版本:V1.6 + - 下载链接:[点击跳转](https://python.quectel.com/wp-content/uploads/2024/09/QCOM_V1.6.zip) +- VSCode - 代码编辑工具 + - 下载链接:[点击跳转](https://code.visualstudio.com/) + +## 固件包 + +- 版本: QPY_OCPU_BETA0002_EC800G_CNLD_FW +- 下载链接:[点击跳转](https://python.quectel.com/wp-content/uploads/2024/09/QPY_OCPU_BETA0002_EC800G_CNLD_FW.zip) + +## 实验源码 + +- 版本:v1.0.0 + +- Github 仓库下载 + + ```shell + git clone https://github.com/QuecPython/solution-HuaDTU.git + cd solution-HuaDTU + git checkout v1.0.0 + ``` + +- [下载Zip源码包](https://github.com/QuecPython/solution-HuaDTU/archive/refs/heads/main.zip) + diff --git a/docs/Application_guide/zh/solutions/DTU/mqtt_demo.md b/docs/Application_guide/zh/solutions/DTU/mqtt_demo.md new file mode 100644 index 0000000000000000000000000000000000000000..58bcef1333d4c06d1c9866e2bf9cd3bc18497775 --- /dev/null +++ b/docs/Application_guide/zh/solutions/DTU/mqtt_demo.md @@ -0,0 +1,154 @@ +# 基于 MQTT 协议的设备开发 + +## 修改配置文件 + +工程配置文件路径:`code/dtu_config.json`。 + +基于 TCP 私有服务器数据透传做如下配置: + +- 默认 `system_config.cloud` 配置项定义为 `"tcp"` 即 TCP 透传模式,系统会自行读取 `socket_private_cloud_config` 配置项。 + + ```python + { + "system_config": { + "cloud": "mqtt" # 默认配置 mqtt 透传模式 + } + } + ``` + +- 本实验采用 MQTT 透传模式,用户需根据实际情况设置 `mqtt_private_cloud_config` 配置项中的 MQTT 服务器域名(*server*)、端口(*port*)、客户端id(*client_id*)以及订阅和发布主题等参数,如下。 + + ```python + { + "mqtt_private_cloud_config": { + "server": "mq.tongxinmao.com", + "port": 18830, + "client_id": "txm_1682300809", + "user": "", + "password": "", + "clean_session": true, + "qos": 0, + "keepalive": 60, + "subscribe": {"down": "/public/TEST/down"}, # 下行数据透传主题 + "publish": {"up": "/public/TEST/up"} # 上行数据透传主题 + } + } + ``` + +- `uart_config` 配置项是串口配置参数,默认是根据当前实验开发板做的配置,不可更改。如用户采用其他开发板则需要根据实际硬件进行配置。 + +```python +{ + "uart_config": { + "port": 2, # 串口号,根据实际硬件配置选择,当前实验不可更改 + "baudrate": 115200, # 波特率 + "bytesize": 8, # 数据位 + "parity": 0, # 奇偶校验 + "stopbits": 1, # 停止位 + "flowctl": 0, # 流控 + "rs485_config": { # RS485 配置 + "gpio_num": 28, # 485 控制脚,当前实验不可更改 + "direction": 0 # 引脚电平变化控制,1表示引脚电平变化为:串口发送数据之前由低拉高、发送数据之后再由高拉低,0表示引脚电平变化为:串口发送数据之前由高拉低、发送数据之后再由低拉高 + } + } +} +``` + +完整配置文件模版如下: + +```json +{ + "system_config": { + "cloud": "tcp" + }, + "mqtt_private_cloud_config": { + "server": "mq.tongxinmao.com", + "port": 18830, + "client_id": "txm_1682300809", + "user": "", + "password": "", + "clean_session": true, + "qos": 0, + "keepalive": 60, + "subscribe": {"down": "/public/TEST/down"}, + "publish": {"up": "/public/TEST/up"} + }, + "socket_private_cloud_config": { + "domain": "112.31.84.164", + "port": 8305, + "timeout": 5, + "keep_alive": 5 + }, + "uart_config": { + "port": 2, + "baudrate": 115200, + "bytesize": 8, + "parity": 0, + "stopbits": 1, + "flowctl": 0, + "rs485_config": { + "gpio_num": 28, + "direction": 0 + } + } +} +``` + +参数说明: + +- `system_config.config`: 指定当前使用的私有云类型。目前支持tcp和mqtt。 +- `mqtt_private_cloud_config`: MQTT私有云配置。 +- `socket_private_cloud_config`: tcp私有云配置。 +- `uart_config`:串口参数配置。 + +## 脚本导入并运行 + +下载安装 **QPYCom** 工具后使用该工具下载脚本至 QuecPython 模组。 + +> 💡 **Tips** +> +> QPYCom 安装和使用教程:https://python.quectel.com/doc/Application_guide/zh/dev-tools/QPYcom/index.html + +## 业务调试 + +**查看 REPL 交互口日志** + +程序运行后,在 REPL 交互页面可以看到日志输出如下图所示。 DTU服务中有2个线程处理数据,一个是用于检测读取串口数据并转发数据给云端,一个是检测云端下行数据透传给串口,如下图所示。 + +![](../../media/solutions/DTU/repl_logs.png) + + **上行数据透传** + +使用串口调试工具模拟mcu给模组发送上行数据。 + +- 在`Input String`输入框中输入`hello world!`字符串。 +- 点击`Send Command`按钮通过串口发送数据。 + +![](../../media/solutions/DTU/qcom_test.png) + +DTU接收串口数据,直接透传至mqtt云端。 + +![](../../media/solutions/DTU/debug_log.png) + + 云端接收上行数据日志 + +![](../../media/solutions/DTU/cloud_up.png) + +**下行数据透传** + +云端发送下行数据。 + +- 设置云端下行数据主题(与DTU应用配置的订阅主题一致)。 +- 输入下行数据。 +- 发布。 + +![](../../media/solutions/DTU/cloud_down.png) + + DTU下行数据日志。 + +![](../../media/solutions/DTU/debug_log_down_data.png) + +通过QCOM观察串口调试工具模拟mcu接收模组下行数据。 + +![](../../media/solutions/DTU/qcom_down.png) + diff --git a/docs/Application_guide/zh/solutions/DTU/quick_start.md b/docs/Application_guide/zh/solutions/DTU/quick_start.md new file mode 100644 index 0000000000000000000000000000000000000000..87b996d90937b846d9ff0520c11e548b39ac7128 --- /dev/null +++ b/docs/Application_guide/zh/solutions/DTU/quick_start.md @@ -0,0 +1,36 @@ +# 快速上手 + +## 硬件准备 + +- Windows 电脑一台,建议 Win10 系统。 +- 一套 [EC800GCN 华系列 DTU 开发板](https://python.quectel.com/doc/Getting_started/zh/evb/ec800g_hua_dtu.html)。 +- 一张可用的 Nano Sim 卡。 +- 一根胶棒天线。 +- 一根 Mini USB 数据线。 +- 一个 USB 转 TTL 模块。 + +## 环境搭建 + +- 下载并安装 EC800G 系列模组驱动:[QuecPython_USB_Driver_Win10_U_G](https://python.quectel.com/wp-content/uploads/2024/09/Quectel_Windows_USB_DriverU_V1.0.19.zip)。 +- 下载并安装 [VSCode](https://code.visualstudio.com/)。 +- 下载并解压 [QPYCom](https://python.quectel.com/wp-content/uploads/2024/09/QPYcom_V3.6.0.zip) 工具到电脑的合适位置。 +- 下载并安装固件包[QPY_OCPU_BETA0002_EC800G_CNLD_FW](https://python.quectel.com/wp-content/uploads/2024/09/QPY_OCPU_BETA0002_EC800G_CNLD_FW.zip)。(固件包烧录请参阅 [使用 QPYcom 烧录固件](https://python.quectel.com/doc/Application_guide/zh/dev-tools/QPYcom/qpycom-dw.html)) +- 下载实验源码。 + +## 硬件连接 + +按照下图进行硬件连接: + +![](../../media/solutions/DTU/DTU_wires_connection.png) + +1. 连接胶棒天线。 +2. 插入 Nano Sim 卡。 +3. 使用 mini USB 数据线连接至电脑。 +4. 使用 USB 转 TTL 模块连接至电脑。TX(DTU开发板) 接 RX(USB 转 TTL 模块);RX(DTU开发板) 接 TX(USB 转 TTL 模块);GND(DTU开发板) 接 GND(USB 转 TTL 模块)共地。(如果采用 RS485 接口,则两端的 A 线连接至 A 线,B 线连接至 B 线。) +5. 开发板采用 9~36 V 宽幅供电。 + +## 设备开发 + +- [基于 TCP 协议的设备开发](./tcp_demo.md) +- [基于 MQTT 协议的设备开发](./mqtt_demo.md) + diff --git a/docs/Application_guide/zh/solutions/DTU/software_design.md b/docs/Application_guide/zh/solutions/DTU/software_design.md new file mode 100644 index 0000000000000000000000000000000000000000..d4e5682d1b343b874245af6dcbb2b3366049e818 --- /dev/null +++ b/docs/Application_guide/zh/solutions/DTU/software_design.md @@ -0,0 +1,334 @@ +# 软件设计讲解 + +## 应用流程图 + +一般了解一个程序代码大多从启动部分开始,这里也采取这种方式,先寻找程序的启动源头。本例程,一般的程序启动顺序如下图所示: + +![](../../media/solutions/DTU/flowchart.png) + +整体上业务可以总结为如下流程: + +1. 启动喂狗线程(华系列 4G DTU 载有硬件狗) +2. 初始化 DTU 对象后,读取系统配置 +3. 初始化串口外设 +4. 检查网络状态 +5. 初始化云端配置和消息队列 +6. 启动数据上下、下行业务线程 + +> 💡 基本原理:本 DTU 采用 **多线程 + 消息队列** 实现串口和云端数据的上下行转发。其中,上行线程(Uplink data thread)用于读取串口数据并发送至云端;下行线程(Downlink data thread)读取消息队列中的云端数据通过串口转发;消息队列用于缓存云端的下行数据。 + +## 目录结构 + +- `usr`: + - `_main.py`:主脚本 + - `dtu_config.json`:配置文件 + - `dtu.py`:DTU 模型对象 + - `logging.py`:日志模块 + - `cloud_abc.py`:云对象模型抽象基类 + - `mqttIot.py`:Mqtt 云对象模型实现 + - `network.py`:网络 + - `serial.py`:串口模型对象实现 + - `socketIot.py`:Socket 云对象模型实现 + - `threading.py`:线程、队列和互斥锁 + - `utils.py`:工具类 + +## API说明 + +### Manager 管理类 + +示例程序的主脚本 `_main.py` 中我们定义一个 `Manager` 类来管理初始化的各种关联的对象。 + +主要方法: + +- `__init__`:管理类初始化方法 + - 看门狗:由于华系列 4G DTU 配置硬件看门狗(GPIO12),所以主脚本程序中需要初始化一个 `self.dog_pin` 对象并采用 `osTimer` 周期喂狗。 + - DTU 模型对象:`self.dtu` 是 DTU 对象,通过该对象方法 `self.dty.config.read_from_json("/usr/dtu_config.json")` 从文件中读取相关配置。`start` 方法是程序主入口,先启动间隔 3s 的喂狗定时器,然后检查 sim 卡和网络状态,最后调用 `self.dtu.run()` 来启动 DTU 例程。 +- `start`:启动方法 + - 开启喂狗定时器 + - 检查 sim 卡状态 + - 检查网络状态 + - 启动 dtu 例程 +- `__feed`:喂狗定时器的回调函数 + +实现如下: + +```python +import sim +import osTimer +from machine import Pin +from usr import network +from usr.dtu import DTU + + +class Manager(object): + + def __init__(self, dog_gpio=Pin.GPIO12): + self.dog_pin = Pin(dog_gpio, Pin.OUT, Pin.PULL_DISABLE, 1) + self.dog_feed_timer = osTimer() + + self.dtu = DTU('Quectel') + self.dtu.config.read_from_json('/usr/dtu_config.json') + + def start(self): + # start timer to feed dog + self.dog_feed_timer.start(3000, 1, self.__feed) + # check sim card + if sim.getStatus() != 1: + raise ValueError("sim card not ready") + # check network + network.wait_network_ready() + # start dtu business + self.dtu.run() + + def __feed(self, args): + if self.dog_pin.read(): + self.dog_pin.write(0) + else: + self.dog_pin.write(1) + + +if __name__ == "__main__": + manager = Manager() + manager.start() +``` + +### 对象模型 + +本方案中定义了多个对象模型,其中主要有 `DTU` 对象模型、云对象模型(`CloudABS`)和串口对象模型(`Serial`)。基本定义如下: + +![](../../media/solutions/DTU/UML.png) + +#### DTU 对象模型 + +在 `dtu.py` 模块中定义 DTU 类,该类主要用于管理串口、云、以及数据的上下行业务。 + +`config` 属性: + +DTU 对象中有一个属性 `config` 是类 `Configure` 对象,该对象用于管理应用配置。如下: + +```python +from usr.dtu import DTU + +dtu = DTU('Quectel') +dtu.config.read_from_json('/usr/dtu_config.json') +``` + +其中,支持从 json 文件中存储相关配置,操作方法类似内置字典类型,可以采用如下方式来读写配置(以读取 `system_config` 配置项为例)。 + +- 从指定 json 文件中导入配置:`dtu.config.read_from_json('/usr/dtu_config.json')` +- 使用`get` 方法读取配置项:`dtu.config.get("system_config")` +- 使用运算符`[]` 读取配置项:`dtu.config["system_config"]` +- 保存并更新配置:`dtu.config.save()` + +`serial` 属性: + +该属性是一个 property 属性,用于构建串口对象,用户一般无需修改,只需要按照实际情况定义配置参数即可。 + +```python +@property +def serial(self): + """create&get serial object according configure""" + __serial__ = getattr(self, '__serial__', None) + if __serial__ is None: + __serial__ = Serial(**self.config.get('uart_config')) # init serial + __serial__.open() # open serial + setattr(self, '__serial__', __serial__) + return __serial__ +``` + +`cloud`属性: + +该属性是一个 property 属性,用于获取云对象,方法中使用 `__create_cloud` 来实际构建云对象。 + +```python +@property +def cloud(self): + """get cloud object""" + cloud = getattr(self, '__cloud__', None) + if cloud is None: + cloud = self.__create_cloud() # create cloud object + setattr(self, '__cloud__', cloud) + return cloud +``` + +`__create_cloud` 方法: + +该方法,是用于实际创建云对象,如果用户自定义云对象,则需要再该函数中新增自定义对象初始化。 + +```python +def __create_cloud(self): + """create cloud object according configure""" + # read cloud type + cloud_type = self.config.get('system_config.cloud') + if cloud_type == "mqtt": + mqtt_config = self.config.get('mqtt_private_cloud_config') # init mqtt cloud + cloud = MqttIot(**mqtt_config) + elif cloud_type == "tcp": + socket_config = self.config.get('socket_private_cloud_config') # init tcp cloud + cloud = SocketIot(**socket_config) + else: + raise ValueError('\"{}\" not supported now!'.format(cloud_type)) + cloud.connect() # connect to cloud + cloud.listen() # start listen message from cloud + return cloud +``` + +`up_transaction_handler` 方法:用于上行数据传输业务线程入口函数。 + +`down_transaction_handler` 方法:用于下行数据传输业务线程入口函数。 + +`run` 方法:启动业务,包括根据配置文件创建串口和云对象以及创建上下行业务数据处理线程。 + +#### Serial 对象模型 + +在 `serial.py` 模块中定义串口模型类 `Serial`,主要用户实现串口的读写操作。主要接口如: + +- `Serial` + - `__init__`: 串口初始化。 + - `open`:打开串口。 + - `close`:关闭串口。 + - `write`:串口写。 + - `read`:串口读。 + +串口使用示例: + +```python +from usr.serial import Serial + +# init Serial object +s = Serial(port=2, baudrate=115200, bytesize=8, parity=0, stopbits=1, flowctl=0, rs485_config=None) +# open serial +s.open() + +# serial write method +s.write(b"hello world!") + +# serial read method +recv_data = s.read() +print(recv_data) +``` + +#### Cloud 对象模型 + +**Cloud 模型** + +为了适配不同的云平台(socket 私有云、mqtt 等),本方案定义抽象云类型如下,用户可以自行按照抽象类型,自定义 Cloud 对象以适配不同云平台。 + +> 💡 Cloud 模型对象实现可以参考 `socketIot` 和 `MqttIot`。 + +```python +class CloudABC(object): + + def __init__(self, **kwargs): + """ + key arguments: kwargs, used for initial params for cloud (customer used). + """ + raise NotImplementedError("this method should me implemented for customer designed Cloud Object") + + def connect(self): + """connect to Coud""" + raise NotImplementedError("customer should implement this method to connect cloud") + + def listen(self): + """listen message from cloud. + + usually we use this method to start a thread for receiving message from the cloud and put message input a Queue, and then use `self.recv` method to get it on app side. + """ + raise NotImplementedError("customer should implement this method to listen cloud message") + + def recv(self): + """receive a message""" + raise NotImplementedError("customer should implement this method to recv a message") + + def send(self, *args): + """send message + + position arguments: args, customer designed method used for send message + """ + raise NotImplementedError("customer should implement this method to send a message") +``` + +上述是 Cloud 对象模型主要方法和属性,其中: + +- `__init__`:接收关键字参数,通常用于配置云端初始化参数,用户可自行定义。 +- `connect`:连接云端服务器。 +- `listen`:监听云端下行消息,通常在该方法中使用线程来读取云端下行数据,并放入消息队列中方便应用侧通过 `self.recv` 方法来获取。 +- `recv`:获取下行消息。 +- `send`:发送上行消息,接收若干位置参数用户可自定义。 + +## 业务代码讲解 + +数传业务主要在 DTU 类(`dtu.py`)中实现,该类主要用于管理串口、云、以及数据的上下行业务。 + +DTU 对象在主脚本中通过调用 `run` 方法来开启整个 DTU 业务,其中该方法主要用于创建并运行两个线程,分别是上行数据处理线程(线程工作函数是 `up_transaction_handler`)和下行数据处理线程(线程工作函数是 `down_transaction_handler`)。在线程函数中分别通过两个 property 属性来获取对应的串口对象和云对象。其中串口对象属性是 `serial`,线程在调用该属性时即刻创建并打开配置的串口对象提供读写接口。其中云对象属性是 `cloud`,线程在调用该属性时即刻创建并连云对象提供接收和发送接口。 + +函数调用时序图: + +```mermaid +sequenceDiagram +Title: Device data transmit-processing timing + + +participant cloud as Cloud +participant dtu as DTU +participant serial as Serial + +loop down_transaction_handler thread +cloud ->> dtu: CloudABC.recv +dtu ->> serial: Serial.write +end + +loop up_transaction_handler thread +serial ->> dtu: Serial.read +dtu ->> cloud: CloudABC.send +end +``` + +上行数据处理线程函数 `DTU.up_transaction_handler` 实现如下: + +```python +class DTU(object): + + # ... + + def up_transaction_handler(self): + while True: + try: + data = self.serial.read(1024) + if data: + logger.info('up transfer msg: {}'.format(data)) + if isinstance(self.cloud, SocketIot): + msg = [data] + elif isinstance(self.cloud, MqttIot): + msg = ['up', data] + else: + raise TypeError('unknow cloud type.') + self.cloud.send(*msg) + except Exception as e: + logger.error('up transfer error: {}'.format(e)) + + # ... +``` + +`up_transaction_handler`函数按照 1KB 的 buffer 读取串口数据(用户可以自行调整buffer大小),并格式化消息后通过 `CloudABC.send` 接口发送数据至云端。用户继承 `CloudABC` 并自定义云对象并实现 `CloudABC.send` 方法后可根据自定义消息格式处理并发送数据。 + +下行数据处理线程函数 `down_transaction_handler` 实现如下: + +```python +class DTU(object): + + # ... + + def down_transaction_handler(self): + while True: + try: + msg = self.cloud.recv() + logger.info('down transfer msg: {}'.format(msg['data'])) + self.serial.write(msg['data']) + except Exception as e: + logger.error('down transfer error: {}'.format(e)) + + # ... +``` + +`down_transaction_handler` 函数通过调用 `CloudABC.recv` 来获取下行消息,并通过 `Serial.write` 转发消息。 \ No newline at end of file diff --git a/docs/Application_guide/zh/solutions/DTU/tcp_demo.md b/docs/Application_guide/zh/solutions/DTU/tcp_demo.md new file mode 100644 index 0000000000000000000000000000000000000000..9b8d81b8ea26521f875df77c7072aebe2e132f97 --- /dev/null +++ b/docs/Application_guide/zh/solutions/DTU/tcp_demo.md @@ -0,0 +1,119 @@ +# 基于 TCP 协议的设备开发 + +## 修改配置文件 + +工程配置文件路径:`code/dtu_config.json`。 + +基于 TCP 私有服务器数据透传做如下配置: + +- 默认 `system_config.cloud` 配置项定义为 `"tcp"` 即 TCP 透传模式,系统会自行读取 `socket_private_cloud_config` 配置项。 + + ```python + { + "system_config": { + "cloud": "tcp" # 默认配置 tcp 透传模式 + } + } + ``` + +- 本实验采用 TCP 透传模式,用户需根据实际情况设置 `socket_private_cloud_config` 配置项中的 TCP 服务器域名(*domain*)和端口(*port*)。 + + ```python + { + "socket_private_cloud_config": { + "domain": "112.31.84.164", # 服务器域名/ip + "port": 8305, # 端口号 + "timeout": 5, # 超时时间 (unit: s) + "keep_alive": 5 # 心跳周期 (unit: s) + } + } + ``` + +- `uart_config` 配置项是串口配置参数,默认是根据当前实验开发板做的配置,不可更改。如用户采用其他开发板则需要根据实际硬件进行配置。 + +```python +{ + "uart_config": { + "port": 2, # 串口号,根据实际硬件配置选择,当前实验不可更改 + "baudrate": 115200, # 波特率 + "bytesize": 8, # 数据位 + "parity": 0, # 奇偶校验 + "stopbits": 1, # 停止位 + "flowctl": 0, # 流控 + "rs485_config": { # RS485 配置 + "gpio_num": 28, # 485 控制脚,当前实验不可更改 + "direction": 0 # 引脚电平变化控制,1表示引脚电平变化为:串口发送数据之前由低拉高、发送数据之后再由高拉低,0表示引脚电平变化为:串口发送数据之前由高拉低、发送数据之后再由低拉高 + } + } +} +``` + +完整配置文件模版如下: + +```json +{ + "system_config": { + "cloud": "tcp" + }, + "mqtt_private_cloud_config": { + "server": "mq.tongxinmao.com", + "port": 18830, + "client_id": "txm_1682300809", + "user": "", + "password": "", + "clean_session": true, + "qos": 0, + "keepalive": 60, + "subscribe": {"down": "/public/TEST/down"}, + "publish": {"up": "/public/TEST/up"} + }, + "socket_private_cloud_config": { + "domain": "112.31.84.164", + "port": 8305, + "timeout": 5, + "keep_alive": 5 + }, + "uart_config": { + "port": 2, + "baudrate": 115200, + "bytesize": 8, + "parity": 0, + "stopbits": 1, + "flowctl": 0, + "rs485_config": { + "gpio_num": 28, + "direction": 0 + } + } +} +``` + +参数说明: + +- `system_config.config`: 指定当前使用的私有云类型。目前支持tcp和mqtt。 +- `mqtt_private_cloud_config`: MQTT私有云配置。 +- `socket_private_cloud_config`: tcp私有云配置。 +- `uart_config`:串口参数配置。 + +## 脚本导入并运行 + +下载安装 **QPYCom** 工具后使用该工具下载脚本至 QuecPython 模组。 + +> 💡 **Tips** +> +> QPYCom 安装和使用教程:https://python.quectel.com/doc/Application_guide/zh/dev-tools/QPYcom/index.html + +## 业务调试 + +程序运行后,在 REPL 交互页面可以看到日志输出如下图所示。 + +左侧图示,我们使用 QCOM 模拟 MCU 打开用于透传的模组串口(即 USB 转 TTL 模块对应的 COM 口)。 + +右侧图示,REPL 交互口输出的模组日志。 + +使用串口工具 QCOM 模拟 MCU 串口上行数据,通过 DTU 透传至 TCP 回显服务器,再由回显服务器将相同数据通过 DTU 下行透传至 QCOM。 + +![](../../media/solutions/DTU/debugview.png) + +本案例中采用的是 TCP 回显服务器,所以 QCOM 上行数据,经过 DTU 透传至 TCP 服务器接收到之后会立即按原路径下行。 + diff --git a/docs/Application_guide/zh/solutions/README.md b/docs/Application_guide/zh/solutions/README.md index 31528f681bf4835a7b459388d4e1cdb6836ecd76..17fcb726fb842fd6618f55b805704002fd459f3c 100644 --- a/docs/Application_guide/zh/solutions/README.md +++ b/docs/Application_guide/zh/solutions/README.md @@ -2,9 +2,9 @@ 为了方便客户应用开发,加快客户项目快速落地,QuecPython 团队针对一些常见的行业应用推出了自己的软件解决方案,包括云喇叭、DTU、公网对讲机、电表、网络摄像头、CPE 电话机、智能定位器、手表、电子学生证、充电桩等。 -- [DTU](./DTU/README.md) +- [EP-D200 华系列 DTU](./DTU/README.md) - [智慧农业中控面板](./Agriculture-Control-Panel/README.md) - [可穿戴解决方案](./Wear/readme.md) - [电表](./electricity-meter/README.md) - [智能定位器](./tracker/README.md) -- [公网对讲机](./poc/README.md) \ No newline at end of file +- [公网对讲机](./poc/README.md)