diff --git a/docs/Application_guide/zh/media/solutions/tracker/after_ota.png b/docs/Application_guide/zh/media/solutions/tracker/after_ota.png new file mode 100644 index 0000000000000000000000000000000000000000..0971e55240dbc61c8cd38a6300f1acdde36c9dbf Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/tracker/after_ota.png differ diff --git a/docs/Application_guide/zh/media/solutions/tracker/aliyun_create_device.png b/docs/Application_guide/zh/media/solutions/tracker/aliyun_create_device.png new file mode 100644 index 0000000000000000000000000000000000000000..254620b218d5db68b65cef66db3d95467b600b68 Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/tracker/aliyun_create_device.png differ diff --git a/docs/Application_guide/zh/media/solutions/tracker/aliyun_create_product.png b/docs/Application_guide/zh/media/solutions/tracker/aliyun_create_product.png new file mode 100644 index 0000000000000000000000000000000000000000..acc99a0e64b8f0ce7b33da07f0cb0b3b5b32621c Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/tracker/aliyun_create_product.png differ diff --git a/docs/Application_guide/zh/media/solutions/tracker/aliyun_export_lite_mode_object_model.png b/docs/Application_guide/zh/media/solutions/tracker/aliyun_export_lite_mode_object_model.png new file mode 100644 index 0000000000000000000000000000000000000000..073cd76edc588bfd814da0052be6eb1e606aeb96 Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/tracker/aliyun_export_lite_mode_object_model.png differ diff --git a/docs/Application_guide/zh/media/solutions/tracker/aliyun_import_object_model.png b/docs/Application_guide/zh/media/solutions/tracker/aliyun_import_object_model.png new file mode 100644 index 0000000000000000000000000000000000000000..6123be724b45d3aef7fbebd8647cf465aafdd849 Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/tracker/aliyun_import_object_model.png differ diff --git a/docs/Application_guide/zh/media/solutions/tracker/aliyun_mqtt_param.png b/docs/Application_guide/zh/media/solutions/tracker/aliyun_mqtt_param.png new file mode 100644 index 0000000000000000000000000000000000000000..9e1be0a22cac6b5283f60af107577954408e8e7e Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/tracker/aliyun_mqtt_param.png differ diff --git a/docs/Application_guide/zh/media/solutions/tracker/aliyun_online_send_message.png b/docs/Application_guide/zh/media/solutions/tracker/aliyun_online_send_message.png new file mode 100644 index 0000000000000000000000000000000000000000..8382eac354f1e739db594d001c82c4228aecbcfd Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/tracker/aliyun_online_send_message.png differ diff --git a/docs/Application_guide/zh/media/solutions/tracker/aliyun_ota_fota_module.png b/docs/Application_guide/zh/media/solutions/tracker/aliyun_ota_fota_module.png new file mode 100644 index 0000000000000000000000000000000000000000..3db28b17724abf60317c180846a51931eafb2f35 Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/tracker/aliyun_ota_fota_module.png differ diff --git a/docs/Application_guide/zh/media/solutions/tracker/aliyun_ota_fota_plain.png b/docs/Application_guide/zh/media/solutions/tracker/aliyun_ota_fota_plain.png new file mode 100644 index 0000000000000000000000000000000000000000..fed62ed39efda028b150fbe2c556b235e08ca4be Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/tracker/aliyun_ota_fota_plain.png differ diff --git a/docs/Application_guide/zh/media/solutions/tracker/aliyun_ota_fota_plain_2.png b/docs/Application_guide/zh/media/solutions/tracker/aliyun_ota_fota_plain_2.png new file mode 100644 index 0000000000000000000000000000000000000000..875f7f83ff18c275ca6122120a1a3c7664d7d1c5 Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/tracker/aliyun_ota_fota_plain_2.png differ diff --git a/docs/Application_guide/zh/media/solutions/tracker/aliyun_ota_fota_upgrade_package.png b/docs/Application_guide/zh/media/solutions/tracker/aliyun_ota_fota_upgrade_package.png new file mode 100644 index 0000000000000000000000000000000000000000..e04822b5b266ac82be012e76e863a5f5a866b0d9 Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/tracker/aliyun_ota_fota_upgrade_package.png differ diff --git a/docs/Application_guide/zh/media/solutions/tracker/aliyun_ota_fota_upgrade_process.png b/docs/Application_guide/zh/media/solutions/tracker/aliyun_ota_fota_upgrade_process.png new file mode 100644 index 0000000000000000000000000000000000000000..dc14cc23d57f2b59f984c13e59e6242192eb8d7c Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/tracker/aliyun_ota_fota_upgrade_process.png differ diff --git a/docs/Application_guide/zh/media/solutions/tracker/aliyun_ota_sota_module.png b/docs/Application_guide/zh/media/solutions/tracker/aliyun_ota_sota_module.png new file mode 100644 index 0000000000000000000000000000000000000000..2237541f41600f0a6a75adc04141ae1280879b41 Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/tracker/aliyun_ota_sota_module.png differ diff --git a/docs/Application_guide/zh/media/solutions/tracker/aliyun_ota_sota_plain.png b/docs/Application_guide/zh/media/solutions/tracker/aliyun_ota_sota_plain.png new file mode 100644 index 0000000000000000000000000000000000000000..3820e75154432405a0b91ef5f11453c307fe4456 Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/tracker/aliyun_ota_sota_plain.png differ diff --git a/docs/Application_guide/zh/media/solutions/tracker/aliyun_ota_sota_upgrade_package.png b/docs/Application_guide/zh/media/solutions/tracker/aliyun_ota_sota_upgrade_package.png new file mode 100644 index 0000000000000000000000000000000000000000..e7090edc0770ca4ad47d8d90506f3324cd3d9f3c Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/tracker/aliyun_ota_sota_upgrade_package.png differ diff --git a/docs/Application_guide/zh/media/solutions/tracker/aliyun_ota_sota_upgrade_process.png b/docs/Application_guide/zh/media/solutions/tracker/aliyun_ota_sota_upgrade_process.png new file mode 100644 index 0000000000000000000000000000000000000000..431771964d72414dd67d73f0266e7e2807c0b85c Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/tracker/aliyun_ota_sota_upgrade_process.png differ diff --git a/docs/Application_guide/zh/media/solutions/tracker/aliyun_tracker_running_saas_view.png b/docs/Application_guide/zh/media/solutions/tracker/aliyun_tracker_running_saas_view.png new file mode 100644 index 0000000000000000000000000000000000000000..f3b81d75155ab2309e0203f9e43dd5b41f868cb8 Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/tracker/aliyun_tracker_running_saas_view.png differ diff --git a/docs/Application_guide/zh/media/solutions/tracker/bord.png b/docs/Application_guide/zh/media/solutions/tracker/bord.png new file mode 100644 index 0000000000000000000000000000000000000000..c30c2bb9575f1f72b1fa25f12c737d1e6657ce74 Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/tracker/bord.png differ diff --git a/docs/Application_guide/zh/media/solutions/tracker/code.png b/docs/Application_guide/zh/media/solutions/tracker/code.png new file mode 100644 index 0000000000000000000000000000000000000000..aaa4455ea14310ba72e2b72d0596c5e3db0c5867 Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/tracker/code.png differ diff --git a/docs/Application_guide/zh/media/solutions/tracker/comport.png b/docs/Application_guide/zh/media/solutions/tracker/comport.png new file mode 100644 index 0000000000000000000000000000000000000000..ab550004d688a6a71ec28feec2804959275a2800 Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/tracker/comport.png differ diff --git a/docs/Application_guide/zh/media/solutions/tracker/solution-tracker-001.png b/docs/Application_guide/zh/media/solutions/tracker/solution-tracker-001.png deleted file mode 100644 index 66ac56ab80bb5863724383b36282160fde9e1cd3..0000000000000000000000000000000000000000 Binary files a/docs/Application_guide/zh/media/solutions/tracker/solution-tracker-001.png and /dev/null differ diff --git a/docs/Application_guide/zh/media/solutions/tracker/solution-tracker-002.png b/docs/Application_guide/zh/media/solutions/tracker/solution-tracker-002.png deleted file mode 100644 index 460123a5bb105feeb55d026fbcebea090a96c322..0000000000000000000000000000000000000000 Binary files a/docs/Application_guide/zh/media/solutions/tracker/solution-tracker-002.png and /dev/null differ diff --git a/docs/Application_guide/zh/media/solutions/tracker/solution-tracker-003.png b/docs/Application_guide/zh/media/solutions/tracker/solution-tracker-003.png deleted file mode 100644 index 045d9bf13c83cb6ca6978629e8480dc32e442afd..0000000000000000000000000000000000000000 Binary files a/docs/Application_guide/zh/media/solutions/tracker/solution-tracker-003.png and /dev/null differ diff --git a/docs/Application_guide/zh/media/solutions/tracker/solution-tracker-004.png b/docs/Application_guide/zh/media/solutions/tracker/solution-tracker-004.png deleted file mode 100644 index 876f750fa912e71e10e11925ebf1cc2d77cf5415..0000000000000000000000000000000000000000 Binary files a/docs/Application_guide/zh/media/solutions/tracker/solution-tracker-004.png and /dev/null differ diff --git a/docs/Application_guide/zh/media/solutions/tracker/solution-tracker-005.png b/docs/Application_guide/zh/media/solutions/tracker/solution-tracker-005.png deleted file mode 100644 index ac7440f5e989de4d89e95578685c2444b5784b77..0000000000000000000000000000000000000000 Binary files a/docs/Application_guide/zh/media/solutions/tracker/solution-tracker-005.png and /dev/null differ diff --git a/docs/Application_guide/zh/media/solutions/tracker/solution-tracker-006.png b/docs/Application_guide/zh/media/solutions/tracker/solution-tracker-006.png deleted file mode 100644 index 6ed45ce7c5544ce3cadd744a4b6295f01af40166..0000000000000000000000000000000000000000 Binary files a/docs/Application_guide/zh/media/solutions/tracker/solution-tracker-006.png and /dev/null differ diff --git a/docs/Application_guide/zh/media/solutions/tracker/solution-tracker-007.png b/docs/Application_guide/zh/media/solutions/tracker/solution-tracker-007.png deleted file mode 100644 index 1952d0a4efaac91f26078ea13a3723ba00fac7f0..0000000000000000000000000000000000000000 Binary files a/docs/Application_guide/zh/media/solutions/tracker/solution-tracker-007.png and /dev/null differ diff --git a/docs/Application_guide/zh/media/solutions/tracker/solution-tracker-008.png b/docs/Application_guide/zh/media/solutions/tracker/solution-tracker-008.png deleted file mode 100644 index 51055475f8566e9650f35113f1a7f48c6b17325c..0000000000000000000000000000000000000000 Binary files a/docs/Application_guide/zh/media/solutions/tracker/solution-tracker-008.png and /dev/null differ diff --git a/docs/Application_guide/zh/media/solutions/tracker/solution-tracker-009.png b/docs/Application_guide/zh/media/solutions/tracker/solution-tracker-009.png deleted file mode 100644 index 52e3a88264a241cbde3737a5bcbdf69913960b9f..0000000000000000000000000000000000000000 Binary files a/docs/Application_guide/zh/media/solutions/tracker/solution-tracker-009.png and /dev/null differ diff --git a/docs/Application_guide/zh/media/solutions/tracker/solution-tracker-010.png b/docs/Application_guide/zh/media/solutions/tracker/solution-tracker-010.png deleted file mode 100644 index dc51f07fc6acb6b1a1187fb05c3bbf2e12c7e7fd..0000000000000000000000000000000000000000 Binary files a/docs/Application_guide/zh/media/solutions/tracker/solution-tracker-010.png and /dev/null differ diff --git a/docs/Application_guide/zh/media/solutions/tracker/solution-tracker-011.png b/docs/Application_guide/zh/media/solutions/tracker/solution-tracker-011.png deleted file mode 100644 index cc4b964c030468a76451983b53980e965aa6c0f8..0000000000000000000000000000000000000000 Binary files a/docs/Application_guide/zh/media/solutions/tracker/solution-tracker-011.png and /dev/null differ diff --git a/docs/Application_guide/zh/media/solutions/tracker/solution-tracker-012.png b/docs/Application_guide/zh/media/solutions/tracker/solution-tracker-012.png deleted file mode 100644 index 0052db0c64c24408dd15f87ca799cd3044d3088f..0000000000000000000000000000000000000000 Binary files a/docs/Application_guide/zh/media/solutions/tracker/solution-tracker-012.png and /dev/null differ diff --git a/docs/Application_guide/zh/media/solutions/tracker/solution-tracker-013.png b/docs/Application_guide/zh/media/solutions/tracker/solution-tracker-013.png deleted file mode 100644 index fd7f3541838b6f0d6421929ded9e9c0eda1c476b..0000000000000000000000000000000000000000 Binary files a/docs/Application_guide/zh/media/solutions/tracker/solution-tracker-013.png and /dev/null differ diff --git a/docs/Application_guide/zh/media/solutions/tracker/solution-tracker-014.png b/docs/Application_guide/zh/media/solutions/tracker/solution-tracker-014.png deleted file mode 100644 index 0d0845ba7e7121c9da46af19fa98df08cce5a77f..0000000000000000000000000000000000000000 Binary files a/docs/Application_guide/zh/media/solutions/tracker/solution-tracker-014.png and /dev/null differ diff --git a/docs/Application_guide/zh/media/solutions/tracker/solution-tracker-015.png b/docs/Application_guide/zh/media/solutions/tracker/solution-tracker-015.png deleted file mode 100644 index b1b07d3582fbfc117e30ae7d4f10cf20d741836c..0000000000000000000000000000000000000000 Binary files a/docs/Application_guide/zh/media/solutions/tracker/solution-tracker-015.png and /dev/null differ diff --git a/docs/Application_guide/zh/media/solutions/tracker/solution-tracker-016.png b/docs/Application_guide/zh/media/solutions/tracker/solution-tracker-016.png deleted file mode 100644 index 7e18beb12610194b5849a458f4214eea51f77cdc..0000000000000000000000000000000000000000 Binary files a/docs/Application_guide/zh/media/solutions/tracker/solution-tracker-016.png and /dev/null differ diff --git a/docs/Application_guide/zh/media/solutions/tracker/tracker_application.png b/docs/Application_guide/zh/media/solutions/tracker/tracker_application.png deleted file mode 100644 index 8309e6de83cd9d132b44ba65f1eda99d2c635916..0000000000000000000000000000000000000000 Binary files a/docs/Application_guide/zh/media/solutions/tracker/tracker_application.png and /dev/null differ diff --git a/docs/Application_guide/zh/media/solutions/tracker/tracker_funcion.png b/docs/Application_guide/zh/media/solutions/tracker/tracker_funcion.png deleted file mode 100644 index a7cbc61fa92e61d8e0b1262083fdca3cb42c3836..0000000000000000000000000000000000000000 Binary files a/docs/Application_guide/zh/media/solutions/tracker/tracker_funcion.png and /dev/null differ diff --git a/docs/Application_guide/zh/media/solutions/tracker/tracker_process.png b/docs/Application_guide/zh/media/solutions/tracker/tracker_process.png deleted file mode 100644 index bf933ff912776939eb2ed05cbf76809fbd4ae8bc..0000000000000000000000000000000000000000 Binary files a/docs/Application_guide/zh/media/solutions/tracker/tracker_process.png and /dev/null differ diff --git a/docs/Application_guide/zh/media/solutions/tracker/tracker_running.png b/docs/Application_guide/zh/media/solutions/tracker/tracker_running.png new file mode 100644 index 0000000000000000000000000000000000000000..113f36d657f15ca6359856a136d791b7daadef6e Binary files /dev/null and b/docs/Application_guide/zh/media/solutions/tracker/tracker_running.png differ diff --git "a/docs/Application_guide/zh/media/solutions/tracker/\350\277\236\347\272\277.png" "b/docs/Application_guide/zh/media/solutions/tracker/\350\277\236\347\272\277.png" new file mode 100644 index 0000000000000000000000000000000000000000..d41ac896f92c7033834f4bbd695ffbb8d69d44a2 Binary files /dev/null and "b/docs/Application_guide/zh/media/solutions/tracker/\350\277\236\347\272\277.png" differ diff --git a/docs/Application_guide/zh/sidebar.yaml b/docs/Application_guide/zh/sidebar.yaml index 5cb8e611cb849734ad69d4dc9a822ad0d92bc0a8..eae1de20624669dd337c6ab7bd8f1872458b2a8f 100644 --- a/docs/Application_guide/zh/sidebar.yaml +++ b/docs/Application_guide/zh/sidebar.yaml @@ -317,6 +317,13 @@ items: file: solutions/electricity-meter/software_design.md - label: 智能定位器 file: solutions/tracker/README.md + items: + - label: 开发资源汇总 + file: solutions/tracker/dev_resources.md + - label: 快速上手 + file: solutions/tracker/quick_start.md + - label: 软件设计讲解 + file: solutions/tracker/software_design.md label: SensorHub file: solutions/SensorHub/README.md items: diff --git a/docs/Application_guide/zh/solutions/tracker/README.md b/docs/Application_guide/zh/solutions/tracker/README.md index a12333d7b126bbad73873680c4727e5d4a19f3eb..8f679d8eecc1e99eb579ad400da19f641ec07231 100644 --- a/docs/Application_guide/zh/solutions/tracker/README.md +++ b/docs/Application_guide/zh/solutions/tracker/README.md @@ -1,380 +1,23 @@ -# 智能定位器解决方案 +# 功能介绍 -## 方案介绍 +该智能定位器方案基于 EC200UEUAA QuecPython 标准开发板实现,具有以下特性: -本文档主要描述移远通信QuecPython定位器的设计框架, 包含软硬件系统框架、关键组件功能描述、系统初始化流程和业务流程的介绍以及功能示例, 方便用户快速了解QuecPython定位器的整体架构与功能。 - -### 产品概述 - -- Tracker智能定位器。 -- 终端设备功能涵盖绝大部分定位器应用场景 -- 可视化运营平台+手机APP, 设备管理和数据查看更方便 - -![](../../media/solutions/tracker/tracker_process.png) - -### 产品功能 - -- 多重定位、安全围栏、危险报警、紧急求救、语音监听、录音、轨迹回放、远程控制等 -- 智能定位 - - 系统利用4G通信/多重定位/分布式服务等技术, 为智能定位器行业提供从端到服务的一站式解决方案 -- 全平台支持 - - 设备运营平台和手机APP功能齐全, 终端设备厂商无需自行搭建服务平台即可快速实现对设备和终端用户的管理 -- 可靠稳定 - - 终端设备定位精度高、危险感知灵敏度高、功耗低、运行稳定, 终端设备厂商可套壳即用, 极大缩短硬件开发周期 - -![](../../media/solutions/tracker/tracker_funcion.png) - -### 产品特点 - -- 位置信息、危险警情智能感知、识别和上报 -- 支持阿里Iot平台、ThingsBoard、私有服务等多种Iot平台对接 -- QuecPython二次开发, 模块化、定制化、缩短开发周期 -- 可视化运营平台、手机APP控制终端 - -### 应用行业 - -- 车载定位 -- 物流货运 -- 人员定位 -- 电子学生证 -- 宠物定位 -- 特殊行业(农业灌溉, 稀有物种监控等) - -![](../../media/solutions/tracker/tracker_application.png) - -## 应用框架 - -### 功能简介 - -智能定位器方案中的软件功能介绍如下图所示, 方案根据定位器实际业务进行功能拆分, 模块化开发实现。 - -![solution-tracker-101](../../media/solutions/tracker/solution-tracker-101.png) - -- 传输协议解析 - + 阿里Iot平台连接与数据交互 - + ThingsBoard平台连接与数据交互 - + GT06协议 - + JT/T808协议 -- 网络管理 - + MQTT协议(阿里Iot/ThingsBoard/其他平台) - + TCP/UDP协议(GT06/JTT808协议) - + APN设置(用于注网拨号) - + LTE NET(4G注网拨号) -- 外设管理 - + GNSS定位数据的读取, 使能, AGPS注入等 - + G-Sensor传感器数据读取 - + Charge IC充电管理, 获取设备充电状态 - + Battery电池管理, 读取电池电压, 换算电量 - + LED指示灯 -- 数据存储 - + 系统配置参数存储 - + 定位数据补传存储 - + AGPS下载存储 - + 日志信息存储 -- 设备升级 - + OTA升级 -- 业务功能管理 - + 网络与IoT 平台的连接与重连 - + 设备数据采集与上报 - + 报警检测与上报 - + IoT 平台下行指令处理 - + 设备低功耗休眠 - -### 数据交互流程 - -模组、IoT 平台之间数据交互流程如下图介绍: - -![solution-tracker-102](../../media/solutions/tracker/solution-tracker-102.png) - -流程描述: - -1. 手机APP发送指令到IoT 平台, 服务端通过TCP/UDP/MQTT协议下发指令数据到模组端接收, 模组进行解析处理; -2. 模组通过TCP/UDP/MQTT协议上报数据到IoT 平台, IoT 平台进行处理, 同步显示到手机端 - -### 设计思想与模式 - -- 本系统采用监听者模式设计, 通过回调函数进行消息的传递事件的监听 -- 软件根据定位器业务需求对其功能进行拆分, 主要分模块来实现, 每个部分独立开发实现, 相互之间减少依赖, 可独立调试运行, 达到解耦合的效果; -- 功能之间的事件交互都通过回调函数来完成, 所有的业务功能处理全部在`Tracker`类中进行处理, 如下行的指令处理, 报警检测, 数据采集与上报, 设备的控制等。 - -![solution-tracker-104](../../media/solutions/tracker/solution-tracker-104.png) - -1. 所有的功能模块通过`Tracker.add_module`注册到`Tracker`类中进行控制 -2. Server模块(IoT 平台交互模块)通过回调将服务型下行的数据传递到`Tracker.server_callback`中进行处理 -3. NetManage模块通过回调将网络断开连接事件传递到`Tracker.net_callback`中进行处理 - -### 软件架构图 - -软件系统框架介绍描述如下: - -- 展现层, 对接不同的 Iot 平台, 进行可视化展示 -- 传输层, 支持使用不同的协议进行交互 -- 业务功层, 主要用于采集设备数据, 控制设备模块, 接收处理IoT 平台下行指令, 数据的整合上报 -- 设备层, 主要为设备数据的信息的采集与设备功能设置, 主要是定位数据的获取与解析, 传感器数据的读取, 电池管理, 历史数据存储, 外设控制, 设备的基础数据, 如设备的版本信息, IMEI号, APN设置, 网络拨号, 设备低功耗等 - -![solution-tracker-107](../../media/solutions/tracker/solution-tracker-107.png) - -### 业务流程 - -![solution-tracker-105](../../media/solutions/tracker/solution-tracker-105.png) - -业务流程说明: - -1. 设备上电启动 -2. 网络(APN)配置与(驻网拨号)连接, IoT 平台配置与连接, 失败重试 -3. 设备模块启动检测与数据采集 - - GNSS定位模块启动, 等待定位数据 - - G-Sensor三轴加速传感器模块启动与校准检测 - - LED指示灯(网络状态/定位状态/充电状态等)启动 - - 电池电量采集与充电状态检测 - - 报警检测(超速检测/震动检测/围栏检测/低电检测等) -4. IoT 平台连接成功后, 检测是否有历史数据需要上报进行上报 -5. IoT 平台连接成功, 上报当前设备信息(定位/告警) -6. IoT 平台连接失败则存储当前设备信息(定位/告警) -7. 设备无任务, 进入低功耗模式, 定时唤醒设备进行设备信息检测与上报 -8. IoT 平台连接成功后, 等待IoT 平台下发指令信息 -9. 指令信息的解析 - - 设备控制指令, 如修改设备业务参数, 控制设备关机重启等 - - 下发OTA升级指令, 进行OTA升级 - - 设备信息查询指令, 应答设备信息 - -### 系统初始化流程 - -![solution-tracker-106](../../media/solutions/tracker/solution-tracker-106.png) - -1. 基础功能模块初始化, 低功耗管理, 配置参数, 电池, 历史文件, 定位, 传感器。 -2. 初始化IoT 平台客户端模块, 阿里Iot或ThingsBoard平台或私有服务平台(GT06、JT/T808等) -3. 初始化核心业务模块(Tracker), 将各个功能模块通过add_module接口添加到Tracker对象中, 再将Tracker.server_callback注册到Server对象中, 用于接收服务端下行的消息指令。 - -## 应用开发 - -### 方案资源获取 - -定位器解决方案资源下载地址: https://github.com/QuecPython/solution-tracker - -> 该方案项目有一个`modules`子仓库, 在下载时需要注意同步下载 -> -> 子仓库同步下载指令`git clone --recursive https://github.com/QuecPython/solution-tracker.git` - -资源包目录展示: - -![solution-tracker-001](../../media/solutions/tracker/solution-tracker-001.png) - -- code 文件夹: - -该目录下包含软件方案代码 - -![solution-tracker-002](../../media/solutions/tracker/solution-tracker-002.png) - -- docs 文件夹: - -该目录下包含用户指导手册与功能接口说明的项目文档 - -![solution-tracker-003](../../media/solutions/tracker/solution-tracker-003.png) - -- object_model_demo 文件夹: - -该目录下提供了一个阿里Iot平台的物模型文件, 可以直接导入阿里Iot平台, 方便调试 - -### 方案说明 - -此方案为定位器公版方案, 不包含全部业务功能, 方案提供定位器业务核心组件的功能实现以及与服务端完成数据交互, 事件转发等功能, 使用者应基于此框架继续开发业务功能, 当前软件框架完成功能如下: - -- MQTT协议通讯(当前方案支持阿里Iot平台/ThingsBoard平台) +- MQTT协议通讯(当前方案支持阿里 IoT 平台/ThingsBoard 平台) - 配置文件读写 -- OTA远程升级 -- LED指示灯 +- OTA 远程升级 +- LED 指示灯 - 设备网络管理 - 设备信息管理 - 电池电量与充电管理 - 备份信息存储 -- GNSS定位/基站定位/Wifi定位 +- GNSS 定位/基站定位/Wifi 定位 - 低功耗管理 - 日志存储记录 -### 环境搭建 - -#### USB驱动安装 - -请根据调试模组平台进行驱动下载安装, [点击此处下载](https://python.quectel.com/resource-download?cid=5) - -![solution-tracker-004](../../media/solutions/tracker/solution-tracker-004.png) - -#### 开发调试工具 - -推荐使用QPYcom进行开发调试, 此文档中的流程介绍均使用该工具进行, 且成功安装USB驱动 - -工具下载链接: [点击此处下载](https://python.quectel.com/resource-download?cid=8) - -![solution-tracker-005](../../media/solutions/tracker/solution-tracker-005.png) - -工具使用说明: [点击此处访问](https://python.quectel.com/doc/Application_guide/en/dev-tools/QPYcom/qpycom-gui.html) - -#### 代码配置参数修改 - -目前方案代码使用的配置参数未进行配置, 请按照下面说明进行更改。 - -找到code中的以`settings_`开头的配置文件进行配置, 根据实际参数进行调整, 如下图: - -- `settings_server.py` 用于配置连接的 IoT 平台连接信息 - -```python -class AliIotConfig: - - product_key = "" - product_secret = "" - device_name = "" - device_secret = "" - server = "iot-as-mqtt.cn-shanghai.aliyuncs.com" - qos = 1 - - -class ThingsBoardConfig: - - host = "" - port = 1883 - username = "" - qos = 0 - client_id = "" -``` - -- `settings_loc.py` 用于配置定位模块的配置信息(外挂GNSS串口, 基站/Wifi定位的认证信息) - -```python -gps_cfg = { - "UARTn": UART.UART1, - "buadrate": 115200, - "databits": 8, - "parity": 0, - "stopbits": 1, - "flowctl": 0, - "gps_mode": _gps_mode.external, - "nmea": 0b010111, - "PowerPin": None, - "StandbyPin": None, - "BackupPin": None, -} - -cell_cfg = { - "serverAddr": "www.queclocator.com", - "port": 80, - "token": "xxxxxxxxxx", - "timeout": 3, - "profileIdx": profile_idx, -} - -wifi_cfg = { - "token": "xxxxxxxxxx" -} -``` - -- `settings_user.py` 用于配置用户业务功能的相关配置参数(如报警开关, 低电阈值等) - -```python -class _server: - none = 0x0 - AliIot = 0x1 - ThingsBoard = 0x2 - -class _drive_behavior_code: - none = 0x0 - sharply_start = 0x1 - sharply_stop = 0x2 - sharply_turn_left = 0x3 - sharply_turn_right = 0x4 - -class _ota_upgrade_module: - none = 0x0 - sys = 0x1 - app = 0x2 - -debug = 1 -log_level = "DEBUG" -checknet_timeout = 60 -server = _server.AliIot -phone_num = "" -low_power_alert_threshold = 20 -low_power_shutdown_threshold = 5 -over_speed_threshold = 50 -sw_ota = 1 -sw_ota_auto_upgrade = 1 -sw_voice_listen = 0 -sw_voice_record = 0 -sw_fault_alert = 1 -sw_low_power_alert = 1 -sw_over_speed_alert = 1 -sw_sim_abnormal_alert = 1 -sw_disassemble_alert = 1 -sw_drive_behavior_alert = 1 -drive_behavior_code = _drive_behavior_code.none -loc_method = _loc_method.all -loc_gps_read_timeout = 300 -work_mode = _work_mode.cycle -work_mode_timeline = 3600 -work_cycle_period = 30 -user_ota_action = -1 -ota_status = { - "sys_current_version": "", - "sys_target_version": "--", - "app_current_version": "", - "app_target_version": "--", - "upgrade_module": _ota_upgrade_module.none, - "upgrade_status": _ota_upgrade_status.none, -} -``` - -#### 烧录固件 - -根据当前调试模组型号下载对应QuecPython固件, 并使用Qpycom工具进行烧录 - -固件下载地址: [点击此处访问](https://python.quectel.com/resource-download?cid=15) - -![solution-tracker-006](../../media/solutions/tracker/solution-tracker-006.png) - -使用QPYcom工具下载固件 - -1. 选择固件 - -![solution-tracker-007](../../media/solutions/tracker/solution-tracker-007.png) - -2. 下载固件 - -![solution-tracker-008](../../media/solutions/tracker/solution-tracker-008.png) - -3. 等待固件烧录 - -![solution-tracker-009](../../media/solutions/tracker/solution-tracker-009.png) - -4. 烧录成功 - -![solution-tracker-010](../../media/solutions/tracker/solution-tracker-010.png) - -5. 连接交互口 - -![solution-tracker-011](../../media/solutions/tracker/solution-tracker-011.png) - -6. 查看烧录信息 - -![solution-tracker-012](../../media/solutions/tracker/solution-tracker-012.png) - -#### 烧录代码 - -- 建议在下载代码前将文件中的`main.py`重命名为`_main.py`, 因为`main.py`会上电自运行, 不方便调试, 我们测试阶段可以手动执行`_main.py`来运行, 方便调试问题 - -- 通过USB下载代码需要设备预留USB接口或测试点, 或使用开发板进行调试, 并提前安装好驱动 - -1. 选择`Quectel USB NMEA PORT`, 该串口为交互口, 程序LOG也会通过该串口输出 - -![solution-tracker-013](../../media/solutions/tracker/solution-tracker-013.png) - -2. 将业务功能代码批量烧录设备, 点击下载脚本后等待下载完成, 下载完成后在文件中查看 - -![solution-tracker-014](../../media/solutions/tracker/solution-tracker-014.png) - -3. 烧录成功后建议重启设备, 然后运行功能(如烧录了`main.py`, 则重启设备后, 功能会自动运行, 如已将`main.py`重命名后烧录, 则需手动运行`_main.py`启动功能) - -![solution-tracker-015](../../media/solutions/tracker/solution-tracker-015.png) +![](../../media/solutions/tracker/bord.png) -4. 运行结果展示 +------ -![solution-tracker-016](../../media/solutions/tracker/solution-tracker-016.png) +- [开发资源汇总](./dev_resources.md) +- [快速上手](./quick_start.md) +- [软件设计讲解](./software_design.md) \ No newline at end of file diff --git a/docs/Application_guide/zh/solutions/tracker/dev_resources.md b/docs/Application_guide/zh/solutions/tracker/dev_resources.md new file mode 100644 index 0000000000000000000000000000000000000000..fb25cb642d3b40d9f8b9caaf037b0d002ddf31bc --- /dev/null +++ b/docs/Application_guide/zh/solutions/tracker/dev_resources.md @@ -0,0 +1,68 @@ +# 开发资源汇总 + +## 开发板资料 + +- 型号:EC200UEUAA QuecPython 标准开发板 +- 购买:[点此跳转](https://www.waveshare.com/ec200u-au-c4-p01.htm) +- 开发板文档 + - [规格书](https://python.quectel.com/wp-content/uploads/2024/09/EC200UA_C4-P01%E7%B3%BB%E5%88%97%E5%BC%80%E5%8F%91%E6%9D%BF%E4%BA%A7%E5%93%81%E8%A7%84%E6%A0%BC%E5%8F%8A%E7%94%A8%E6%88%B7%E6%8C%87%E5%AF%BC.pdf) + - [原理图](https://python.quectel.com/wp-content/uploads/2024/09/EC200UA_C4-P01%E7%B3%BB%E5%88%97%E5%BC%80%E5%8F%91%E6%9D%BF%E5%8E%9F%E7%90%86%E5%9B%BE.pdf) + - [丝印图](https://python.quectel.com/wp-content/uploads/2024/09/EC200UA_C4-P01%E7%B3%BB%E5%88%97%E5%BC%80%E5%8F%91%E6%9D%BF%E4%B8%9D%E5%8D%B0.pdf) + - [资源介绍与使用指导](https://python.quectel.com/doc/Getting_started/zh/evb/ec200x-evb.html) + +## 模组资料 + +- 型号:[EC200UEUAA](https://python.quectel.com/modules-cat/ec200u-series) +- [规格书](https://python.quectel.com/wp-content/uploads/2024/09/Quectel_EC200U%E7%B3%BB%E5%88%97_LTE_Standard_%E6%A8%A1%E5%9D%97%E4%BA%A7%E5%93%81%E8%A7%84%E6%A0%BC%E4%B9%A6_V1.4.pdf) +- [驱动下载](https://python.quectel.com/wp-content/uploads/2024/09/Quectel_Windows_USB_DriverU_V1.0.19.zip) + +## 配件资料 + +- GNSS 天线 + 转接线 + - 型号:YLY001CA + YM0003AA + - 购买:[点此跳转](https://e.tb.cn/h.TpAFyEz02BnCHRD?tk=fznae6ITVEX) + +## 开发工具 + +- QuecPython 调试工具 - QPYcom + - 版本:V3.6.0 + - 下载 [QPYcom](https://python.quectel.com/wp-content/uploads/2024/09/QPYcom_V3.6.0.zip) + - [使用教程](https://python.quectel.com/doc/Application_guide/zh/dev-tools/QPYcom/index.html) +- 代码编辑器 - VSCode + - 下载 [VSCode](https://code.visualstudio.com/) + +## 固件包 + +- 版本:EC200UEUAAR03A04M08_OCPU_QPY_BETA0418 +- 下载[固件](https://python.quectel.com/wp-content/uploads/2024/09/QPY_OCPU_BETA0001_EC200U_EUAA_FW.zip) + +## 实验源码 + +- 版本号:V2.0.0 + +- [github 仓库](https://github.com/QuecPython/solution-tracker/tree/master) + + ```bash + # 1.拉取主项目代码 + git clone https://github.com/QuecPython/solution-tracker.git + + # 2.进入项目根目录 + cd solution-tracker/ + + # 3.切换对应的主项目分支 + git checkout master + + # 4.子项目初始化 + git submodule init + + # 5.子项目代码拉取 + git submodule update + + # 6.进入子项目目录 + cd code/modules/ + + # 7.切换对应的子项目分支 + git checkout master + ``` + +- [压缩包下载](https://codeload.github.com/QuecPython/solution-tracker/zip/refs/heads/master) \ No newline at end of file diff --git a/docs/Application_guide/zh/solutions/tracker/quick_start.md b/docs/Application_guide/zh/solutions/tracker/quick_start.md new file mode 100644 index 0000000000000000000000000000000000000000..685ffdc9a6d7fb70fd1468c3a9e60dc957c24bde --- /dev/null +++ b/docs/Application_guide/zh/solutions/tracker/quick_start.md @@ -0,0 +1,276 @@ +# 快速上手 + +## 硬件准备 + +- Windows 电脑一台,建议 `Win10` 系统 +- 一套 [EC200UEUAA QuecPython 标准开发板](https://python.quectel.com/doc/Getting_started/zh/evb/ec200x-evb.html)(含 LTE 天线、 Type-C 数据线等) +- 一根 [GNSS天线](https://e.tb.cn/h.TpAFyEz02BnCHRD?tk=fznae6ITVEX) +- 一个排针跳线帽 +- 一张可正常使用的 Nano SIM 卡 + +## 环境搭建 + +- 下载并安装 EC200U 系列模组驱动: [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) 工具到电脑的合适位置 +- 使用 QPYcom 烧录[固件包](https://python.quectel.com/wp-content/uploads/2024/09/QPY_OCPU_BETA0001_EC200U_EUAA_FW.zip) +- 下载[实验源码](https://codeload.github.com/QuecPython/solution-tracker/zip/refs/heads/master) + +## 硬件连接 + +按照下图进行硬件连接: + +![](../../media/solutions/tracker/连线.png) + +1. 将 LTE 天线连接至标识有 `LTE` 字样的天线连接座上 +2. 将 GNSS 天线连接至标识有 `GNSS` 字样的天线连接座上 +3. 在图示位置开发板背面插入可用的 Nano SIM 卡 +4. 使用跳线帽将标识有 `GNSS_EN` 字样的两根排针短接,使能开发板内置 GNSS 功能 +5. 使用 Type-C 数据线连接开发板和电脑 + +## 云服务平台 + +按照以下步骤创建、配置并连接阿里云物联网平台: + +### 创建产品与设备 + +详情可参考阿里云说明文档:[创建产品与设备](https://help.aliyun.com/document_detail/73705.html)。 + +- 创建产品 + +![aliyun_create_product](../../media/solutions/tracker/aliyun_create_product.png) + +- 创建设备 + +![aliyun_create_device](../../media/solutions/tracker/aliyun_create_device.png) + +### 定义物模型 + +详情可参考阿里云说明文档:[为产品定义物模型](https://help.aliyun.com/document_detail/117636.html)。 + +物模型可以更直观的看到上传的数据值,本解决方案提供了物模型 demo,可直接导入工程项目中 `object_model_demo/ali_cloud_object_model.json` 文件自动生成,无需手动创建。 + +![aliyun_import_object_model](../../media/solutions/tracker/aliyun_import_object_model.png) + +## 设备开发 + +本节重点阐述用户在业务上需要关注的配置或代码如何修改,以便用户能够快速上手。 + +在开始前,先用 `VSCode` 打开项目工程源码,找到 code 中的以 `settings_` 开头的配置文件进行配置。 + +> 本方案支持两个可选平台:阿里 IoT 和 Thingsboard。这里主要介绍使用阿里 IoT 的配置与连接。 + +### IoT 平台连接信息 + +`settings_server.py` 用于配置 IoT 平台连接信息 + +![](../../media/solutions/tracker/aliyun_mqtt_param.png) + +```python +# 以下两个平台使用哪个就配置哪个,本解决方案以阿里 IoT 为例 +class AliIotConfig: + product_key = "" + product_secret = None + device_name = "" + device_secret = "" + server = "iot-as-mqtt.cn-shanghai.aliyuncs.com" # 默认参数 + qos = 1 + +class ThingsBoardConfig: + host = "" + port = 1883 + username = "" + qos = 0 + client_id = "" +``` + +### 定位模块配置信息 + +`settings_loc.py` 用于配置定位模块的配置信息(内置 GNSS/外挂 GNSS 串口,基站/Wifi 定位的认证信息) + +> 本解决方案基于 EC200UEUAA QuecPython 标准开发板的内置 GNSS 功能实现。 + +```python +# GNSS 定位 +gps_cfg = { + "gps_mode": _gps_mode.internal, # 内置 GNSS + "UARTn": UART.UART2, + "buadrate": 115200, + "databits": 8, + "parity": 0, + "stopbits": 1, + "flowctl": 0, + "PowerPin": None, + "StandbyPin": None, + "BackupPin": None, +} + +# 基站定位 +cell_cfg = { + "serverAddr": "www.queclocator.com", + "port": 80, + "token": "xxxxxxxxxx", + "timeout": 3, + "profileIdx": profile_idx, +} + +# Wifi 定位 +wifi_cfg = { + "token": "xxxxxxxxxx" +} +``` + +### 用户业务配置信息 + +`settings_user.py` 用于配置用户业务功能的相关配置参数(如报警开关、低电阈值等) + +```python +class _server: + none = 0x0 + AliIot = 0x1 + ThingsBoard = 0x2 + +class _drive_behavior_code: + none = 0x0 + sharply_start = 0x1 + sharply_stop = 0x2 + sharply_turn_left = 0x3 + sharply_turn_right = 0x4 + +class _ota_upgrade_module: + none = 0x0 + sys = 0x1 + app = 0x2 + +debug = 1 +log_level = "DEBUG" +checknet_timeout = 60 +server = _server.AliIot +phone_num = "" +low_power_alert_threshold = 20 +low_power_shutdown_threshold = 5 +over_speed_threshold = 50 +sw_ota = 1 +sw_ota_auto_upgrade = 1 +sw_voice_listen = 0 +sw_voice_record = 0 +sw_fault_alert = 1 +sw_low_power_alert = 1 +sw_over_speed_alert = 1 +sw_sim_abnormal_alert = 1 +sw_disassemble_alert = 1 +sw_drive_behavior_alert = 1 +drive_behavior_code = _drive_behavior_code.none +loc_method = _loc_method.all +loc_gps_read_timeout = 300 +work_mode = _work_mode.cycle +work_mode_timeline = 3600 +work_cycle_period = 30 +user_ota_action = -1 +ota_status = { + "sys_current_version": "", + "sys_target_version": "--", + "app_current_version": "", + "app_target_version": "--", + "upgrade_module": _ota_upgrade_module.none, + "upgrade_status": _ota_upgrade_status.none, +} +``` + +### 开机 + +完成硬件连接的工作后,开发板会自动开机,查看电脑设备管理器的端口列表中是否出现包含 `Quectel USB` 字样的 COM 口。 + +![](../../media/solutions/tracker/comport.png) + +### 烧录固件包 + +参考[此章节](https://python.quectel.com/doc/Application_guide/zh/dev-tools/QPYcom/qpycom-dw.html#下载固件),烧录固件包 [QPY_OCPU_BETA0001_EC200U_EUAA_FW](https://python.quectel.com/wp-content/uploads/2024/09/QPY_OCPU_BETA0001_EC200U_EUAA_FW.zip) 至开发板。 + +### 脚本导入与运行 + +1. 参考[此章节](https://python.quectel.com/doc/Getting_started/zh/first_python.html#PC与模组间的文件传输),将源码目录下 `code` 文件夹中的所有文件导入到模组文件系统,如下图所示: + + ![](../../media/solutions/tracker/code.png) + +2. 参考[此章节](https://python.quectel.com/doc/Getting_started/zh/first_python.html#执行脚本文件),执行主程序文件 `_main.py`。 +3. 参考[此章节](https://python.quectel.com/doc/Getting_started/zh/first_python.html#停止程序运行),停止程序运行。 + +## 业务调试 + +### 程序启动 + +执行 `_main.py` 脚本后,程序开始运行,在交互页面即可查看项目运行状态: + +> 程序要运行一段时间后才能获取到 GNSS 定位信息,具体可参考相关[文档说明](https://python.quectel.com/doc/FAQ/zh/hardware/gnss.html#%3Cstrong%3E%E4%BB%80%E4%B9%88%E6%98%AFGNSS%E7%9A%84%E5%86%B7%E5%90%AF%E5%8A%A8%E3%80%81%E6%B8%A9%E5%90%AF%E5%8A%A8%E5%92%8C%E7%83%AD%E5%90%AF%E5%8A%A8%3C/strong%3E)。 + +![tracker_running](../../media/solutions/tracker/tracker_running.png) + +在阿里云物联网平台可查看设备状态信息。 + +![aliyun_tracker_running_saas_view](../../media/solutions/tracker/aliyun_tracker_running_saas_view.png) + +### 云端控制 + +通过在线调试下发指令到设备端进行设备控制与数据交互。 + +![aliyun_online_send_message](../../media/solutions/tracker/aliyun_online_send_message.png) + +### OTA升级 + +> **固件升级只支持差分升级,不支持整包升级**; +> +> **项目文件升级包,以修改项目代码文件后缀名为 `.bin` 的方式做成升级包,上传云端,可上传多个文件**。 + +#### 固件升级 + +1. 制作固件升级差分包(联系固件开发人员); +2. 创建 OTA 模块,以设备平台名称命名,如: `EC200U-EUAA`。 + +![aliyun_ota_fota_module](../../media/solutions/tracker/aliyun_ota_fota_module.png) + +3. 创建OTA升级包 + + 升级包名称以 `settings.py` 中 `PROJECT_NAME` 命名,如:`QuecPython-Tracker`。 + +![aliyun_ota_fota_upgrade_package](../../media/solutions/tracker/aliyun_ota_fota_upgrade_package.png) + +4. 选择批量升级,创建升级计划 + +![aliyun_ota_fota_plain](../../media/solutions/tracker/aliyun_ota_fota_plain.png) + +![](../../media/solutions/tracker/aliyun_ota_fota_plain_2.png) + +5. 等待设备升级,查看升级结果 + + 当设备开启 OTA 升级和 OTA 自动升级,则等待设备升级完成,查看升级结果; + + + 当设备开启 OTA 升级,但未开启自动升级时,可通过在线调试模块下发 `user_ota_action=1` 的物模型设置指令,进行 OTA 升级。 + + > 设备下载固件成功后会重启进入升级,需要等待一段时间。当观察到 QPYcom 重新出现 `Quectel USB` 字样的端口时,说明 OTA 升级完成。此时打开交互端口重新运行 `_main.py` 脚本,上报升级成功后的版本号,云端刷新即可看到 OTA 状态为 `升级成功`。 + +![](../../media/solutions/tracker/after_ota.png) + +![aliyun_ota_fota_upgrade_process](../../media/solutions/tracker/aliyun_ota_fota_upgrade_process.png) + +#### 项目升级 + +1. 创建 OTA 模块,以 `settings.py` 中 `PROJECT_NAME` 命名,如:`QuecPython-Tracker`。 + +![aliyun_ota_sota_module](../../media/solutions/tracker/aliyun_ota_sota_module.png) + +2. 将需要升级的项目文件后缀名修改为 `.bin` +3. 创建 OTA 升级包 + + 此处需要在**推送给设备的自定义信息**中编写升级文件名对应的设备全路径文件名,如:`{"files":{"common.bin":"/usr/modules/common.py","settings.bin":"/usr/settings.py","test_tracker.bin":"/usr/test_tracker.py"}}` + +![aliyun_ota_sota_upgrade_package](../../media/solutions/tracker/aliyun_ota_sota_upgrade_package.png) + +4. 选择批量升级,创建升级计划 + +![aliyun_ota_sota_plain](../../media/solutions/tracker/aliyun_ota_sota_plain.png) + +5. 等待设备升级,查看升级结果 + + + 当设备开启 OTA 升级和 OTA 自动升级,则等待设备升级完成,查看升级结果; + + 当设备开启 OTA 升级,但未开启自动升级时,可通过在线调试模块下发 `user_ota_action=1` 的物模型设置指令,进行 OTA 升级。 + +![aliyun_ota_sota_upgrade_process](../../media/solutions/tracker/aliyun_ota_sota_upgrade_process.png) \ No newline at end of file diff --git a/docs/Application_guide/zh/solutions/tracker/software_design.md b/docs/Application_guide/zh/solutions/tracker/software_design.md new file mode 100644 index 0000000000000000000000000000000000000000..99beed2ce44d9e56a604af1f6512d5850d97dd03 --- /dev/null +++ b/docs/Application_guide/zh/solutions/tracker/software_design.md @@ -0,0 +1,835 @@ +# 软件设计讲解 + +## 引言 + +本文档主要描述移远通信 QuecPython 定位器的设计框架,包含软硬件系统框架、关键组件功能描述、系统初始化流程和业务流程的介绍以及功能示例,方便用户快速了解 QuecPython 定位器的整体架构与功能。 + +## 功能简介 + +智能定位器方案中的软件功能介绍如下图所示,方案根据定位器实际业务进行功能拆分,模块化开发实现。 + +![solution-tracker-101](../../media/solutions/tracker/solution-tracker-101.png) + +- 传输协议解析 + + 阿里 IoT 平台连接与数据交互 + + ThingsBoard 平台连接与数据交互 + + GT06 协议 + + JT/T808 协议 +- 网络管理 + + MQTT 协议(阿里 IoT/ThingsBoard/其他平台) + + TCP/UDP 协议(GT06/JTT808 协议) + + APN 设置(用于注网拨号) + + LTE NET(4G 注网拨号) +- 外设管理 + + GNSS 定位数据的读取、使能、AGPS 注入等 + + G-Sensor 传感器数据读取 + + Charge IC 充电管理,获取设备充电状态 + + Battery 电池管理,读取电池电压,换算电量 + + LED 指示灯 +- 数据存储 + + 系统配置参数存储 + + 定位数据补传存储 + + AGPS 下载存储 + + 日志信息存储 +- 设备升级 + + OTA 升级 +- 业务功能管理 + + 网络与 IoT 平台的连接与重连 + + 设备数据采集与上报 + + 报警检测与上报 + + IoT 平台下行指令处理 + + 设备低功耗休眠 + +## 数据交互流程 + +模组、IoT 平台之间数据交互流程如下图介绍: + +![solution-tracker-102](../../media/solutions/tracker/solution-tracker-102.png) + +流程描述: + +1. 手机 APP 发送指令到 IoT 平台,服务端通过 TCP/UDP/MQTT 协议下发指令数据到模组端接收,模组进行解析处理; +2. 模组通过 TCP/UDP/MQTT 协议上报数据到 IoT 平台,IoT 平台进行处理,同步显示到手机端。 + +## 软件框架 + +### 设计思想与模式 + +- 本系统采用监听者模式设计,通过回调函数进行消息的传递事件的监听; +- 软件根据定位器业务需求对其功能进行拆分,主要分模块来实现,每个部分独立开发实现,相互之间减少依赖,可独立调试运行,达到解耦合的效果; +- 功能之间的事件交互都通过回调函数来完成,所有的业务功能处理全部在 `Tracker` 类中进行处理,如下行的指令处理,报警检测,数据采集与上报,设备的控制等。 + +![solution-tracker-104](../../media/solutions/tracker/solution-tracker-104.png) + +1. 所有的功能模块通过 `Tracker.add_module` 注册到 `Tracker` 类中进行控制; +2. Server 模块(IoT 平台交互模块)通过回调将服务型下行的数据传递到 `Tracker.server_callback` 中进行处理; +3. NetManage 模块通过回调将网络断开连接事件传递到 `Tracker.net_callback` 中进行处理。 + +### 软件架构图 + +软件系统框架介绍描述如下: + +- 展现层,对接不同的 IoT 平台; +- 传输层,使用不同的协议进行交互; +- 业务层,主要用于采集设备数据,控制设备模块,接收处理 IoT 平台下行指令,数据的整合上报; +- 设备层,主要是定位数据的获取与解析,传感器数据的读取,电池管理,历史数据存储等功能,设备数据的信息的采集与设备功能设置,如设备的版本信息,IMEI号,APN 设置,网络拨号,设备低功耗等。 + +![solution-tracker-107](../../media/solutions/tracker/solution-tracker-107.png) + +## 功能组件介绍 + +### 核心业务模块(Tracker) + +1. 功能描述 + + 实现核心业务逻辑,与服务端的数据交互解析,设备模块的控制,所有功能以事件的形式,传入业务事件消息队列子线程中处理。 + +2. 实现原理 + +- 通过注册功能模块,获取各个功能模块的数据,如定位信息,电池信息,传感器信息等 + + ```python + class Tracker: + ... + + def add_module(self, module): + # 将各个功能模块注册到Tracker类中,在Tracker类中进行控制 + if isinstance(module, AliIot): + self.__server = module + elif isinstance(module, AliIotOTA): + self.__server_ota = module + elif isinstance(module, Battery): + self.__battery = module + elif isinstance(module, History): + self.__history = module + elif isinstance(module, GNSS): + self.__gnss = module + elif isinstance(module, CellLocator): + self.__cell = module + elif isinstance(module, WiFiLocator): + self.__wifi = module + elif isinstance(module, NMEAParse): + self.__nmea_parse = module + elif isinstance(module, CoordinateSystemConvert): + self.__csc = module + elif isinstance(module, NetManage): + self.__net_manage = module + elif isinstance(module, PowerManage): + self.__pm = module + elif isinstance(module, TempHumiditySensor): + self.__temp_sensor = module + elif isinstance(module, Settings): + self.__settings = module + else: + return False + return True + + def running(self, args=None): + if self.__running_tag == 1: + return + self.__running_tag = 1 + # 禁用设备休眠 + self.__pm.autosleep(0) + self.__pm.set_psm(mode=0) + # 启动业务事件消息队列监听子线程 + self.__business_start() + # 发送OTA版本刷新指令到事件队列中进行执行 + self.__business_queue.put((0, "ota_refresh")) + # 发送上报定位数据事件(包含网络的连接,设备数据的采集,设备数据的上报) + self.__business_queue.put((0, "loc_report")) + # 发送OTA升级查询指令事件 + self.__business_queue.put((0, "check_ota")) + # 发送设备休眠事件 + self.__business_queue.put((0, "into_sleep")) + self.__running_tag = 0 + ``` + +- 通过回调监听服务端下发的指令消息,进行业务处理 + + ```python + class Tracker: + ... + + def server_callback(self, args): + # 服务端下行消息传入业务事件消息队列中进行处理 + self.__business_queue.put((1, args)) + ``` + + ```python + class Tracker: + ... + + def __business_running(self): + while True: + data = self.__business_queue.get() + with self.__business_lock: + self.__business_tag = 1 + ... + # 处理IoT 平台下行指令功能 + if data[0] == 1: + self.__server_option(*data[1]) + self.__business_tag = 0 + ``` + + ```python + class Tracker: + ... + + def __server_option(self, topic, data): + if topic.endswith("/property/set"): + # 处理属性设置的下行消息 + self.__server_property_set(data) + elif topic.find("/rrpc/request/") != -1: + # 处理透传数据的下行消息 + msg_id = topic.split("/")[-1] + self.__server_rrpc_response(msg_id, data) + elif topic.find("/thing/service/") != -1: + # 处理服务数据的下行消息 + service = topic.split("/")[-1] + self.__server_service_response(service, data) + elif topic.startswith("/ota/device/upgrade/") or topic.endswith("/ota/firmware/get_reply"): + # 处理OTA升级的下行消息 + user_cfg = self.__settings.read("user") + if self.__server_ota_flag == 0: + if user_cfg["sw_ota"] == 1: + self.__server_ota_flag = 1 + if user_cfg["sw_ota_auto_upgrade"] == 1 or user_cfg["user_ota_action"] == 1: + # 满足OTA升级条件,执行OTA升级流程 + self.__server_ota_process(data) + else: + self.__server_ota_flag = 0 + self.__server_ota.set_ota_data(data["data"]) + ota_info = self.__server_ota.get_ota_info() + ota_info["ota_status"] = 1 + self.__server_ota_state_save(**ota_info) + else: + module = data.get("data", {}).get("module") + self.__server.ota_device_progress(-1, "Device is not alowed ota.", module) + ``` + +- 通过RTC回调唤醒操作,唤醒设备休眠,进行业务数据上报 + + ```python + class Tracker: + ... + + def __into_sleep(self): + while True: + if self.__business_queue.size() == 0 and self.__business_tag == 0: + break + utime.sleep_ms(500) + user_cfg = self.__settings.read("user") + # 根据休眠时长自动调整休眠模式,autosleep或者psm + if user_cfg["work_cycle_period"] < user_cfg["work_mode_timeline"]: + self.__pm.autosleep(1) + else: + self.__pm.set_psm(mode=1, tau=user_cfg["work_cycle_period"], act=5) + # 启动RTC定时唤醒设备 + self.__set_rtc(user_cfg["work_cycle_period"], self.running) + + def __set_rtc(self, period, callback): + # 设置RTC唤醒时钟,唤醒设备 + self.__business_rtc.enable_alarm(0) + if callback and callable(callback): + self.__business_rtc.register_callback(callback) + atime = utime.localtime(utime.mktime(utime.localtime()) + period) + alarm_time = (atime[0], atime[1], atime[2], atime[6], atime[3], atime[4], atime[5], 0) + _res = self.__business_rtc.set_alarm(alarm_time) + log.debug("alarm_time: %s, set_alarm res %s." % (str(alarm_time), _res)) + return self.__business_rtc.enable_alarm(1) if _res == 0 else -1 + ``` + +3. 注册功能模块与回调函数配置 + + ```python + def main(): + # 初始化网络功能模块 + net_manage = NetManage(PROJECT_NAME, PROJECT_VERSION) + # 初始化配置参数功能模块 + settings = Settings() + # 初始化电池检测功能模块 + battery = Battery() + # 初始化历史数据功能模块 + history = History() + # 初始化IoT 平台(阿里Iot)功能模块 + server_cfg = settings.read("server") + server = AliIot(**server_cfg) + # 初始化IoT 平台(阿里Iot)OTA功能模块 + server_ota = AliIotOTA(PROJECT_NAME, FIRMWARE_NAME) + server_ota.set_server(server) + # 初始化低功耗功能模块 + power_manage = PowerManage() + # 初始化温湿度传感器功能模块 + temp_sensor = TempHumiditySensor(i2cn=I2C.I2C1, mode=I2C.FAST_MODE) + loc_cfg = settings.read("loc") + # 初始化GNSS定位功能模块 + gnss = GNSS(**loc_cfg["gps_cfg"]) + # 初始化基站定位功能模块 + cell = CellLocator(**loc_cfg["cell_cfg"]) + # 初始化Wifi定位功能模块 + wifi = WiFiLocator(**loc_cfg["wifi_cfg"]) + # 初始化GNSS定位数据解析功能模块 + nmea_parse = NMEAParse() + # 初始化WGS84与GCJ02坐标系转换功能模块 + cyc = CoordinateSystemConvert() + + # 初始化Tracker业务功能模块 + tracker = Tracker() + # 将基础功能模块注册到Tracker类中进行控制 + tracker.add_module(settings) + tracker.add_module(battery) + tracker.add_module(history) + tracker.add_module(net_manage) + tracker.add_module(server) + tracker.add_module(server_ota) + tracker.add_module(power_manage) + tracker.add_module(temp_sensor) + tracker.add_module(gnss) + tracker.add_module(cell) + tracker.add_module(wifi) + tracker.add_module(nmea_parse) + tracker.add_module(cyc) + + # 将基础事件添加到事件列表中 + server.add_event("over_speed_alert") + server.add_event("sim_abnormal_alert") + server.add_event("low_power_alert") + server.add_event("fault_alert") + + # 设置网络模块的回调, 当网络断开,进行业务处理 + net_manage.set_callback(tracker.net_callback) + # 设置服务端下行数据接收的回调,当服务端下发指令时,进行业务处理 + server.set_callback(tracker.server_callback) + + # 启动Tracker项目业务功能. + tracker.running() + + if __name__ == "__main__": + # 主文件启动 + main() + ``` + +### 定位模块(loction) + +1. 功能描述 + + 通过内置或外挂 GNSS,基站,Wifi 获取当前设备定位信息。 + +2. 实现原理 + +- 内置 GNSS 通过 `quecgnss` 接口开启与读取 GNSS 数据 + + ```python + class GNSS: + ... + + def __internal_read(self): + log.debug("__internal_read start.") + # 开启GNSS + self.__internal_open() + + # 清除串口缓存的GNSS历史数据 + while self.__break == 0: + gnss_data = quecgnss.read(1024) + if gnss_data[0] == 0: + self.__break = 1 + self.__break = 0 + + self.__gps_nmea_data_clean() + self.__gps_data_check_timer.start(2000, 1, self.__gps_data_check_callback) + cycle = 0 + # 读取GNSS原始数据 + while self.__break == 0: + gnss_data = quecgnss.read(1024) + if gnss_data and gnss_data[1]: + this_gps_data = gnss_data[1].decode() if len(gnss_data) > 1 and gnss_data[1] else "" + self.__reverse_gps_data(this_gps_data) + if self.__check_gps_valid(): + self.__break = 1 + cycle += 1 + if cycle >= self.__retry: + if self.__break != 1: + self.__break = 1 + if self.__break != 1: + utime.sleep(1) + self.__gps_data_check_timer.stop() + self.__break = 0 + + self.__gps_data_check_callback(None) + # 关闭GNSS + self.__internal_close() + log.debug("__internal_read %s." % ("success" if self.__get_gps_data() else "failed")) + return self.__get_gps_data() + ``` + +- 外挂 GNSS 通过 UART 串口读取 GNSS 数据 + + ```python + class GNSS: + ... + + def __external_read(self): + # 开启GNSS UART串口 + self.__external_open() + log.debug("__external_read start") + + # 清除串口缓存的GNSS历史数据 + while self.__break == 0: + self.__gps_timer.start(50, 0, self.__gps_timer_callback) + signal = self.__external_retrieve_queue.get() + log.debug("[first] signal: %s" % signal) + if signal: + to_read = self.__external_obj.any() + log.debug("[first] to_read: %s" % to_read) + if to_read > 0: + self.__set_gps_data(self.__external_obj.read(to_read).decode()) + self.__gps_timer.stop() + self.__break = 0 + + self.__gps_nmea_data_clean() + self.__gps_data_check_timer.start(2000, 1, self.__gps_data_check_callback) + cycle = 0 + # 读取GNSS原始数据 + while self.__break == 0: + self.__gps_timer.start(1500, 0, self.__gps_timer_callback) + signal = self.__external_retrieve_queue.get() + log.debug("[second] signal: %s" % signal) + if signal: + to_read = self.__external_obj.any() + log.debug("[second] to_read: %s" % to_read) + if to_read > 0: + self.__reverse_gps_data(self.__external_obj.read(to_read).decode()) + if self.__check_gps_valid(): + self.__break = 1 + + self.__gps_timer.stop() + cycle += 1 + if cycle >= self.__retry: + self.__break = 1 + if self.__break != 1: + utime.sleep(1) + self.__gps_data_check_timer.stop() + self.__break = 0 + + # To check GPS data is usable or not. + self.__gps_data_check_callback(None) + # 关闭GNSS串口 + self.__external_close() + log.debug("__external_read %s." % ("success" if self.__get_gps_data() else "failed")) + return self.__get_gps_data() + ``` + +- 基站定位通过 cellLocator 基站定位接口获取基站定位经纬度、精度等信息 + + ```python + class CellLocator: + ... + + def __read_thread(self): + loc_data = () + try: + # 读取基站定位信息 + loc_data = cellLocator.getLocation( + self.__serverAddr, + self.__port, + self.__token, + self.__timeout, + self.__profileIdx + ) + loc_data = loc_data if isinstance(loc_data, tuple) and loc_data[0] and loc_data[1] else () + except Exception as e: + sys.print_exception(e) + self.__queue.put(loc_data) + ``` + +- Wifi 定位通过 wifilocator 和 wifiScan 接口获取定位经纬度、精度、mac 地址等信息 + + ```python + class WiFiLocator: + + def __init__(self, token): + self.__wifilocator = wifilocator(token) if wifilocator else None + + def __read_thread(self): + loc_data = () + try: + # 读取Wifi定位信息 + loc_data = self.__wifilocator_obj.getwifilocator() + loc_data = loc_data if isinstance(loc_data, tuple) and loc_data[0] and loc_data[1] else () + except Exception as e: + sys.print_exception(e) + self.__queue.put(loc_data) + ``` + +### 电池模块(battery) + +1. 功能描述 + + 读取电池的电量、电压,获取电池的充电状态,通过回调函数通知用户电池充电状态变化。 + +2. 实现原理 + +- 电池电压的获取方式有两种 + + 通过 Power 模块获取电源电压; + + 通过 ADC 获取电压进行计算。 + + ```python + class Battery(object): + ... + + def __get_power_vbatt(self): + """Get vbatt from power""" + # 通过Power模块获取电源电压 + return int(sum([Power.getVbatt() for i in range(100)]) / 100) + + def __get_adc_vbatt(self): + """Get vbatt from adc""" + # 通过ADC获取电压进行计算 + self.__adc.open() + utime.sleep_ms(self.__adc_period) + adc_list = list() + for i in range(self.__adc_period): + adc_list.append(self.__adc.read(self.__adc_num)) + utime.sleep_ms(self.__adc_period) + adc_list.remove(min(adc_list)) + adc_list.remove(max(adc_list)) + adc_value = int(sum(adc_list) / len(adc_list)) + self.__adc.close() + vbatt_value = adc_value * (self.__factor + 1) + return vbatt_value + ``` + +- 电池电量目前只提供模拟计算,录入了一个电压,温度对应电池电量的数据关系表进行模糊计算 + + ```python + BATTERY_OCV_TABLE = { + "nix_coy_mnzo2": { + 55: { + 4152: 100, 4083: 95, 4023: 90, 3967: 85, 3915: 80, 3864: 75, 3816: 70, 3773: 65, 3737: 60, 3685: 55, + 3656: 50, 3638: 45, 3625: 40, 3612: 35, 3596: 30, 3564: 25, 3534: 20, 3492: 15, 3457: 10, 3410: 5, 3380: 0, + }, + 20: { + 4143: 100, 4079: 95, 4023: 90, 3972: 85, 3923: 80, 3876: 75, 3831: 70, 3790: 65, 3754: 60, 3720: 55, + 3680: 50, 3652: 45, 3634: 40, 3621: 35, 3608: 30, 3595: 25, 3579: 20, 3548: 15, 3511: 10, 3468: 5, 3430: 0, + }, + 0: { + 4147: 100, 4089: 95, 4038: 90, 3990: 85, 3944: 80, 3899: 75, 3853: 70, 3811: 65, 3774: 60, 3741: 55, + 3708: 50, 3675: 45, 3651: 40, 3633: 35, 3620: 30, 3608: 25, 3597: 20, 3585: 15, 3571: 10, 3550: 5, 3500: 0, + }, + }, + } + ``` + + ```python + class Battery: + ... + + def __get_soc_from_dict(self, key, volt_arg): + """Get battery energy from map""" + if BATTERY_OCV_TABLE[self.__battery_ocv].get(key): + volts = sorted(BATTERY_OCV_TABLE[self.__battery_ocv][key].keys(), reverse=True) + pre_volt = 0 + volt_not_under = 0 # Determine whether the voltage is lower than the minimum voltage value of soc. + for volt in volts: + if volt_arg > volt: + volt_not_under = 1 + soc1 = BATTERY_OCV_TABLE[self.__battery_ocv][key].get(volt, 0) + soc2 = BATTERY_OCV_TABLE[self.__battery_ocv][key].get(pre_volt, 0) + break + else: + pre_volt = volt + if pre_volt == 0: # Input Voltarg > Highest Voltarg + return soc1 + elif volt_not_under == 0: + return 0 + else: + return soc2 - (soc2 - soc1) * (pre_volt - volt_arg) // (pre_volt - volt) + + def __get_soc(self, temp, volt_arg): + """Get battery energy by temperature and voltage""" + if temp > 30: + return self.__get_soc_from_dict(55, volt_arg) + elif temp < 10: + return self.__get_soc_from_dict(0, volt_arg) + else: + return self.__get_soc_from_dict(20, volt_arg) + ``` + +- 电池的充电状态是通过引脚中断与获取引脚的电平高低判断当前设备的充电状态 + + ```python + class Battery: + ... + + def __update_charge_status(self): + """Update Charge status by gpio status""" + if not self.__usb: + chrg_level = self.__chrg_gpio.read() + stdby_level = self.__stdby_gpio.read() + if chrg_level == 1 and stdby_level == 1: + # Not charge. + self.__charge_status = 0 + elif chrg_level == 0 and stdby_level == 1: + # Charging. + self.__charge_status = 1 + elif chrg_level == 1 and stdby_level == 0: + # Charge over. + self.__charge_status = 2 + else: + raise TypeError("CHRG and STDBY cannot be 0 at the same time!") + else: + self.__usb_charge() + + @property + def charge_status(self): + """Get charge status + Returns: + 0 - Not charged + 1 - Charging + 2 - Finished charging + """ + self.__update_charge_status() + return self.__charge_status + ``` + +### 低功耗模块(power_manage) + +1. 功能描述 + + 周期性唤醒设备并进行业务处理,业务处理完成后,设备进入休眠模式。 + + 当前支持的休眠模式有: + + - autosleep; + - psm。 + +2. 实现原理 + + 设置对应的休眠模式,使设备进入休眠,通过 RTC 定时器进行设备唤醒 + + ```python + class PowerManage: + ... + + def autosleep(self, val): + """Set device autosleep. + + Args: + val (int): 0 - disable, 1 - enable. + + Returns: + bool: True - success. False - failed. + """ + return True if hasattr(pm, "autosleep") and val in (0, 1) and pm.autosleep(val) == 0 else False + + def set_psm(self, mode=1, tau=None, act=None): + """Set device psm. + + Args: + mode (int): 0 - disable psm, 1 - enable psm. + tau (int/None): tau seconds. When mode is 0, this value is None. (default: `None`) + act (int/None): act seconds. When mode is 0, this value is None. (default: `None`) + + Returns: + bool: True - success. False - failed. + """ + if not hasattr(pm, "set_psm_time") or not hasattr(pm, "get_psm_time"): + return False + if mode == 0: + return pm.set_psm_time(0) + else: + self.__init_tau(tau) + self.__init_act(act) + res = pm.set_psm_time(self.__tau_unit, self.__tau_time, self.__act_unit, self.__act_time) + log.info("set_psm_time: %s" % res) + if res: + get_psm_res = pm.get_psm_time() + log.debug("get_psm_res: %s" % str(get_psm_res)) + if get_psm_res[0] == 1 and get_psm_res[1:] == [self.__tau_unit, self.__tau_time, self.__act_unit, self.__act_time]: + log.debug("PSM time equal set time.") + return res + ``` + +### 阿里 IoT(aliyunIot) + +1. 功能描述 + + 通过 MQTT 协议与阿里 IoT 物联网模块进行交互。 + + - 设备连接登录平台; + - 发送物模型数据到服务端; + - 接收服务端下发的指令; + - OTA 升级。 + + > 此处以阿里 IoT MQTT 协议为例,实际应用以实际对接的 IoT 平台与协议进行开发,基本逻辑模式一致。 + +2. 实现原理 + + 通过 MQTT 协议,按照阿里 IoT 物联网模块的通信规则进行登录与数据交互。 + +- 注册登录 + + ```python + class AliIot: + ... + + def connect(self): + res = -1 + self.__server = "%s.%s" % (self.__product_key, self.__domain) + log.debug("self.__product_key: %s" % self.__product_key) + log.debug("self.__product_secret: %s" % self.__product_secret) + log.debug("self.__device_name: %s" % self.__device_name) + log.debug("self.__device_secret: %s" % self.__device_secret) + log.debug("self.__server: %s" % self.__server) + self.__server = aLiYun(self.__product_key, self.__product_secret, self.__device_name, self.__device_secret, self.__server) + res = self.__server.setMqtt(self.__device_name) + if res == 0: + self.__server.setCallback(self.__subscribe_callback) + res = self.__subscribe_topics() + if res == 0: + self.__server.start() + return res + ``` + +- 数据上传 + + ```python + class AliIot: + ... + + def properties_report(self, data):. + # 属性上报 + _timestamp = self.__timestamp + _id = self.__id + params = {key: {"value": val, "time": _timestamp} for key, val in data.items()} + properties = { + "id": _id, + "version": "1.0", + "sys": { + "ack": 1 + }, + "params": params, + "method": "thing.event.property.post", + } + pub_res = self.__server.publish(self.ica_topic_property_post, ujson.dumps(properties), qos=self.__qos) if self.__server else -1 + return self.__get_post_res(_id) if pub_res is True else False + + def event_report(self, event, data): + # 事件上报 + _timestamp = self.__timestamp + _id = self.__id + params = {"value": data, "time": _timestamp} + properties = { + "id": _id, + "version": "1.0", + "sys": { + "ack": 1 + }, + "params": params, + "method": "thing.event.%s.post" % event, + } + pub_res = self.__server.publish(self.ica_topic_event_post.format(event), ujson.dumps(properties), qos=self.__qos) if self.__server else -1 + return self.__get_post_res(_id) if pub_res is True else False + ``` + +- 下行数据回传 + + ```python + class AliIot: + ... + + def __subscribe_callback(self, topic, data): + topic = topic.decode() + try: + data = ujson.loads(data) + except: + pass + log.debug("topic: %s, data: %s" % (topic, str(data))) + + if topic.endswith("/post_reply"): + self.__put_post_res(data["id"], True if int(data["code"]) == 200 else False) + return + elif topic.endswith("/thing/ota/firmware/get_reply"): + self.__put_post_res(data["id"], True if int(data["code"]) == 200 else False) + + if self.__callback and callable(self.__callback): + # 传入Tracker.server_callback中进行处理 + self.__callback((topic, data)) + ``` + +- OTA 升级 + + ```python + class AliIotOTA: + ... + + def start(self): + # 开始OTA升级 + if self.__module == self.__project_name: + self.__start_sota() + elif self.__module == self.__firmware_name: + self.__start_fota() + else: + return False + return True + + def __start_fota(self): + log.debug("__start_fota") + fota_obj = fota() + url1 = self.__files[0]["url"] + url2 = self.__files[1]["url"] if len(self.__files) > 1 else "" + log.debug("start httpDownload") + if url2: + res = fota_obj.httpDownload(url1=url1, url2=url2, callback=self.__fota_callback) if fota_obj else -1 + else: + res = fota_obj.httpDownload(url1=url1, callback=self.__fota_callback) if fota_obj else -1 + log.debug("httpDownload res: %s" % res) + if res == 0: + self.__ota_timer.start(600 * 1000, 0, self.__ota_timer_callback) + fota_res = self.__fota_queue.get() + self.__ota_timer.stop() + return fota_res + else: + self.__server.ota_device_progress(-2, "Download File Failed.", module=self.__module) + return False + ``` + +### UML 类图 + +项目软件代码中各组件对象之间存在依赖关系与继承关系,我们可以将定位器这个产品作为顶层对象,它由若干个对应的功能所组成,本章节通过 UML 类图将其与所依赖的组件对象建立了关联,具体如下图所示。 + +![solution-tracker-104](../../media/solutions/tracker/solution-tracker-104.png) + +## 事件流程描述 + +### 业务流程 + +![solution-tracker-105](../../media/solutions/tracker/solution-tracker-105.png) + +业务流程说明: + +1. 设备上电启动; +2. 网络(APN)配置与(注网拨号)连接,IoT 平台配置与连接,失败重试; +3. 设备模块启动检测与数据采集; + - GNSS 定位模块启动,等待定位数据; + - G-Sensor 三轴加速传感器模块启动与校准检测; + - LED 指示灯(网络状态/定位状态/充电状态等)启动; + - 电池电量采集与充电状态检测; + - 报警检测(超速检测/震动检测/围栏检测/低电检测等)。 +4. IoT 平台连接成功后,检测是否有历史数据需要上报进行上报; +5. IoT 平台连接成功,上报当前设备信息(定位/告警); +6. IoT 平台连接失败则存储当前设备信息(定位/告警); +7. 设备无任务,进入低功耗模式,定时唤醒设备进行设备信息检测与上报; +8. IoT 平台连接成功后,等待 IoT 平台下发指令信息; +9. 指令信息的解析。 + - 设备控制指令,如修改设备业务参数,控制设备关机重启等; + - 下发 OTA 升级指令,进行 OTA 升级; + - 设备信息查询指令,应答设备信息。 + +### 系统初始化流程 + +![solution-tracker-106](../../media/solutions/tracker/solution-tracker-106.png) + +1. 基础功能模块初始化,低功耗管理,配置参数,电池,历史文件,定位,传感器; +2. 初始化 IoT 平台客户端模块,阿里 IoT 或 ThingsBoard 平台或私有服务平台(GT06、JT/T808 等); +3. 初始化核心业务模块(Tracker),将各个功能模块通过 `add_module` 接口添加到 Tracker 对象中,再将 `Tracker.server_callback` 注册到 Server 对象中,用于接收服务端下行的消息指令。