# GosafeTracker **Repository Path**: andaai/GosafeTracker ## Basic Information - **Project Name**: GosafeTracker - **Description**: GosafeTracker - **Primary Language**: Python - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2024-07-12 - **Last Updated**: 2024-07-12 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # GosafeTracker ## 应用入口 应用程序入口脚本文件:`_main.py` > 注:只有应用入口脚本命名为`main.py`的时候,模组上电才会自动运行`main.py`脚本。 入口脚本中的`create_app`为工厂函数,该函数内创建应用程序对象`Application`,并将应用拓展组件(`extensions`文件夹中以业务需求划分定义的各种组件)通过`init_app`方法注册到当前应用程序对象中。我们使用该工厂函数创建全局唯一应用程序对象`app`,通过`app.mainloop()`启动整个应用服务,该函数内部会逐个调用应用拓展组件中的`load`方法来加载各个拓展的服务。 ![](./docs/media/main.png) ## 地理围栏 模块`geofence.py`,用户接口示例如下: ```python from usr.qframe import CurrentApp from usr.extensions.geofence import Circular, Rectangle, Point, Polygon # geofence是一个全局的象,该对象可用于保存围栏参数,以及判定一个坐标处于哪些围栏中的接口 # 通过CurrentAPP()来获取注册到当前应用程序对象中的geofence对象 gf = CurrentApp().geofence # 圆形围栏 测试点:50, 120 --> '1' gf.fences.update({ '0': Circular(Point(113.0, 25.31), 1000), # [1, 1, 113.0, 25.31, 1000], '1': Circular(Point(120.0, 50), 1000), # [1, 1, 120.0, 50, 1000], '2': Circular(Point(117.30794, 31.79322), 100), # [1, 1, 117.30794, 31.79322, 100], # 合肥 }) # 矩形围栏 测试点:15, 15 --> '3' gf.fences.update({ '3': Rectangle(Point(10, 20), Point(20, 10)), # [2, 1, 10, 20, 20, 10], '4': Rectangle(Point(20, 30), Point(30, 20)), # [2, 1, 20, 30, 30, 20], }) # 多边形围栏 测试点:31.51031807840651, 117.55787896484374 --> '5' # 巢湖 gf.fences.update({ '5': Polygon([ Point(117.37935113281249, 31.711477410980944), Point(117.44801568359374, 31.674085343031127), Point(117.49745416015624, 31.575859527107386), Point(117.61830376953124, 31.639016599620224), Point(117.82704400390624, 31.587558513127775), Point(117.61281060546874, 31.425982924793466), Point(117.44526910156249, 31.484557065120843), Point(117.31068658203124, 31.587558513127775), Point(117.30519341796874, 31.688109134141744) ]) }) # 构建围栏RTree gf.build() print("======= 圆形围栏 测试点:50, 120 --> '1'") print('result: ', gf.check_point_in_fences(Point(120, 50))) print("======= 矩形围栏 测试点:15, 15 --> '3'") print('result: ', gf.check_point_in_fences(Point(10, 20))) print("======= 多边形围栏 测试点:31.51031807840651, 117.55787896484374 --> '5'") print('result: ', gf.check_point_in_fences(Point(117.55787896484374, 31.51031807840651))) print('=======') print('fences: ', gf.fences) print('=======') print('tree data: ', gf.rtree.db) ``` ## GNSS接口 模块`gnss.py`,提供gnss定位数据的读取和解析接口。 ```python from usr.qframe import CurrentApp # 获取注册的gnss对象 gnss = CurrentApp().gnss # 单独读取一次gnss数据,返回值是Nmea对象(该对象封装NMEA协议数据) nmea = gnss.read() # 读取并解析定位数据 data = gnss.get_location_info() # data格式如下: # { # 'status': nmea.GNRMC.status, # 'lat': float(nmea.GNRMC.lat or '0'), # 'uLat': nmea.GNRMC.uLat, # 'lon': float(nmea.GNRMC.lon or '0'), # 'uLon': nmea.GNRMC.uLon, # 'msl': float(nmea.GNGGA.msl or '0'), # 'spd': float(nmea.GNRMC.spd or '0'), # 'cog': float(nmea.GNRMC.cog or '0'), # 'utctime': nmea.GNRMC.utctime[:6], # 'date': nmea.GNRMC.date, #} ``` > 注:gnss组件被正确加载后,会自动启动一个线程间隔5s读取定位数据,并交给`handle_nmea`方法处理。用户可通过重写该方法实现自己业务。 ## 固件升级与脚本升级 采用MQTT服务实施升级业务。MQTT参数配置在配置文件中的配置项`OTA_SERVER`。 ```json { "OTA_SERVER": { "server": "mq.tongxinmao.com", "port": 18830, "client_id": "txm_1682300811", "user": "", "password": "", "clean_session": true, "qos": 0, "keepalive": 60 } } ``` 功能主题: | 功能 | 主题 | | ---------------------------------- | ------------------------ | | 升级计划(云端发布,设备订阅) | "/device/upgrade/plan" | | 升级状态发布(设备发布,云端订阅) | "/device/upgrade/status" | | 设备版本上报(设备发布,云端订阅) | "/device/upgrade/report" | 设备版本上报: ```python { "firmware_version": "EG912UGLAAR03A01M08_OCPU_QPY", # 固件版本 "app_version": "1.0.0" # 应用版本 } ``` 根据升级协议,分为**固件升级**和**应用脚本升级**两种消息格式: ```python # 固件升级json消息格式: { "version": <固件版本号>, "type": "lte", "url": <固件升级文件url>, "checksum": <固件文件校验码> } # 应用脚本升级json消息格式: { "version": <应用版本号>, "type": "app", "url": <应用脚本tar包url>, "checksum": <应用脚本tar包校验码> } ``` 升级状态消息格式: ```python # 文件下载失败 { "version": version, "status": { "code": 11000, "desc": "firmware downloading error" } } # 文件正在下载 { "version": version, "status": { "code": 10000, "desc": "firmware downloading" } } # 文件下载成功 { "version": version, "status": { "code": 12000, "desc": "firmware downloading success" } } # 正在升级 { "version": version, "status": { "code": 13000, "desc": "firmware updating" } } ```