
在虚拟 IoT 硬件上读取 GPS 数据使用 CounterFit 模拟 UART GPS 传感器实战指南【免费下载链接】IoT-For-Beginners12 Weeks, 24 Lessons, IoT for All!项目地址: https://gitcode.com/GitHub_Trending/io/IoT-For-Beginners本篇技术指南聚焦于 Microsoft 开源课程 IoT-For-Beginners 中「位置追踪Location tracking」单元3-transport/lessons/1-location-tracking的虚拟设备章节如何在无实体硬件的情况下通过 CounterFit 模拟器在虚拟 IoT 设备上添加一个基于 UART 串口通信的 GPS 传感器并用 Python 程序读取其原始 NMEA 数据。阅读并动手完成本指南后你将掌握 CounterFit 虚拟传感器的创建流程、counterfit-shims-serial串口模拟库的用法、三种 GPS 数据源Lat/Lon、NMEA 语句、GPX 文件的配置方式并能理解输出数据的含义为后续课程中使用pynmea2解码经纬度打下基础。虚拟硬件用 CounterFit 模拟 GPS 传感器在真实世界中GPS 传感器通常包含一根天线用于接收 GPS 卫星发出的无线电波并将这些信号转换为经纬度、海拔等定位数据。而在本课程的虚拟设备方案中这一切由CounterFit应用模拟它不需要任何真实硬件就可以在虚拟 IoT 设备上模拟一个通过UART串口通信的 GPS 传感器。 UART 的详细原理在项目 2 第 2 课中介绍过如有需要可以回顾。虚拟 GPS 传感器与真实传感器最大的不同在于数据来源你可以通过三种方式向模拟传感器“喂入”数据——直接设置一个固定的latitude纬度和 longitude经度发送原始的 NMEA 语句NMEA 是 GPS 行业标准的文本格式将在后文详解上传一个包含多个位置的GPX 文件例如徒步轨迹传感器会按顺序逐条返回这些位置。前置准备创建 CounterFit Python 工程在添加虚拟 GPS 传感器之前你需要先准备好一个基于 CounterFit 的 Python 虚拟设备工程。参考入门单元第 1 课中的虚拟设备指南完成以下操作在电脑上新建一个名为gps-sensor的文件夹在文件夹内创建单个 Python 文件app.py配置好 Python 虚拟环境virtual environment安装 CounterFit 所需的 pip 包使应用能够与 CounterFit 建立连接。完成基础工程后还需要额外安装一个专用的 pip 包——CounterFit 串口模拟垫片shim。它允许 Python 程序通过串口连接与 UART 类传感器通信。请务必在已激活虚拟环境的终端中执行pip install counterfit-shims-serial在 CounterFit 中添加 UART GPS 传感器启动 CounterFit Web 应用后按以下步骤创建虚拟 GPS 传感器在Sensors传感器面板的Create sensor创建传感器输入框中打开Sensor type传感器类型下拉菜单选择UART GPS将Port端口保持为/dev/ttyAMA0点击Add添加按钮即可在/dev/ttyAMA0端口上创建 GPS 传感器。创建成功后传感器会出现在传感器列表中。说明/dev/ttyAMA0是 Linux 系统中 UART 串口设备的经典地址。在真实的 Raspberry Pi 方案中Grove Base Hat 的 UART 口也使用该地址虚拟方案沿用此路径以保持与真实硬件一致的编程体验。编写程序读取 GPS 数据在 VS Code 中打开gps-sensor工程与app.py文件按顺序添加以下代码。1. 连接 CounterFit在app.py顶部加入以下代码让应用连接本地运行的 CounterFit 服务默认地址127.0.0.1端口5000from counterfit_connection import CounterFitConnection CounterFitConnection.init(127.0.0.1, 5000)2. 导入库并建立串口连接在连接代码下方导入time与counterfit_shims_serial并建立到虚拟 GPS 传感器的串口连接import time import counterfit_shims_serial serial counterfit_shims_serial.Serial(/dev/ttyAMA0)这段代码从counterfit-shims-serialpip 包中导入serial模块然后连接到/dev/ttyAMA0串口——这正是虚拟 GPS 传感器为其 UART 端口使用的串口地址。注意这里模拟的是pyserial的 API因此后续调用readline()等方法的写法与真实串口编程完全一致。3. 循环读取并打印数据在下方添加数据读取逻辑def print_gps_data(line): print(line.rstrip()) while True: line serial.readline().decode(utf-8) while len(line) 0: print_gps_data(line) line serial.readline().decode(utf-8) time.sleep(1)代码逻辑说明print_gps_data(line)函数负责把传入的每一行数据去除末尾换行符后打印到控制台外层while True进入无限循环每次迭代尽量多地读取串口缓冲区中的文本行内层while len(line) 0保证一次性处理完当前缓冲区内的所有数据当所有可读数据被消费后程序休眠 1 秒再进入下一轮读取。4. 运行程序运行app.py时请使用与 CounterFit Web 应用不同的终端确保 CounterFit 应用保持运行状态。程序启动后会持续监听串口等待虚拟 GPS 数据。配置 GPS 数据源Lat/Lon、NMEA 与 GPX返回 CounterFit Web 应用通过以下三种方式之一为 GPS 传感器设置数据源最后点击Set设置按钮将配置应用到传感器。方式一Lat/Lon经纬度坐标将Source数据源设置为Lat/Lon然后指定一个纬度、经度以及用于定位的卫星数量。由于该值只会发送一次请勾选Repeat重复复选框让数据每秒重复发送。方式二NMEA 语句将Source设置为NMEA并在文本框中输入若干条 NMEA 语句。传感器会依次发送这些语句每条新的 GGA定位语句之间间隔 1 秒。可以使用 nmeagen.org 这类工具通过在地图上绘制轨迹来生成相应的语句。由于这些值只发送一次同样建议勾选Repeat复选框使全部语句发送完毕 1 秒后自动重复。方式三GPX 文件将Source设置为 GPX 文件并上传一个包含轨迹位置的 GPX 文件可从 AllTrails 等主流地图与徒步网站下载。GPX 文件中包含一条轨迹上的多个 GPS 位置点传感器会以每秒一个位置的频率依次返回。同样勾选Repeat复选框可在全部位置发送完后 1 秒重复播放。配置完成后点击Set此时程序控制台会出现类似下面的原始输出$GNGGA,020604.001,4738.538654,N,12208.341758,W,1,3,,164.7,M,-17.1,M,,*67 $GNGGA,020604.001,4738.538654,N,12208.341758,W,1,3,,164.7,M,-17.1,M,,*67至此你的虚拟 GPS 传感器程序已成功运行理解 NMEA 输出原始数据的含义控制台中看似“乱码”的输出实际上是标准 GPS 数据。GPS 传感器使用NMEA 0183标准输出数据NMEA 是美国国家海洋电子协会National Marine Electronics Association制定的海事电子设备通信标准。NMEA 消息基于文本每条语句sentence以$字符开头随后是 2 个字符表示消息来源例如GP代表美国 GPS 系统GN代表俄罗斯 GLONASS 系统再后 3 个字符表示消息类型其余部分是逗号分隔的字段以换行符结尾。常见消息类型包括类型说明GGAGPS 定位数据包括传感器经纬度、海拔以及参与定位的卫星数量ZDA当前日期和时间含本地时区信息GSV视野内可见卫星的详细信息以示例语句$GNGGA,020604.001,4738.538654,N,12208.341758,W,1,3,,164.7,M,-17.1,M,,*67为例纬度部分为4738.538654,NNMEA 使用(dd)dmm.mmmm格式表示经纬度度、分秒为分的十进制小数4738.538654转换为十进制即为 47.6423109方向字符N表示北纬故为正值经度部分为12208.341758,W转换为十进制为 122.1390293方向字符W表示西经故为负值即 -122.1390293。这也解释了本课程后续输出中微软园区坐标47.6423109,-122.1390293的来源。 GPS 数据本身带有时间戳因此 IoT 设备如果需要时间可以直接从 GPS 传感器获取而无需依赖 NTP 服务器或内部实时时钟。进阶用 pynmea2 解码经纬度原始 NMEA 数据可读性差更推荐使用开源库将其解码为可直接使用的格式。本课程配套的解码章节提供了完整方案安装解码库pip3 install pynmea2在app.py中导入模块并将print_gps_data函数替换为如下实现import pynmea2 def print_gps_data(line): msg pynmea2.parse(line) if msg.sentence_type GGA: lat pynmea2.dm_to_sd(msg.lat) lon pynmea2.dm_to_sd(msg.lon) if msg.lat_dir S: lat lat * -1 if msg.lon_dir W: lon lon * -1 print(f{lat},{lon} - from {msg.num_sats} satellites)该代码用pynmea2解析串口读取的行若消息类型为GGA即定位语句则用dm_to_sd函数把 NMEA 的(d)ddmm.mmmm格式转换为十进制小数随后根据方向字符将南纬、西经转为负值最后打印出十进制坐标与定位所用的卫星数量。运行后输出形如47.6423109,-122.1390293 - from 3 satellites仓库中的参考实现本文涉及的全部代码均可在当前仓库中找到现成实现读取原始 GPS 数据的虚拟设备程序code-gps/virtual-device/gps-sensor/app.py加入pynmea2解码的进阶版本code-gps-decode/virtual-device/gps-sensor/app.py同一课程的 Raspberry Pi 硬件版本pi-gps-sensor.md 与 Wio Terminal 版本wio-terminal-gps-sensor.md三者编程逻辑完全同构便于在真实硬件上无缝迁移本课完整背景知识供应链、经纬度、GPS 原理、NMEA 详解见课程主页。小结通过本指南你在无实体硬件的前提下完成了 GPS 传感器的虚拟接入理解了 UART 串口在虚拟方案中的等价实现counterfit-shims-serial掌握了三种数据源的配置方式并能解读标准 NMEA GGA 语句中的经纬度字段。这套流程与 Raspberry Pi 真实硬件的串口编程pyserial/dev/ttyAMA0几乎一致是理解后续「存储位置数据」「可视化位置数据」与「地理围栏」课程的基础。【免费下载链接】IoT-For-Beginners12 Weeks, 24 Lessons, IoT for All!项目地址: https://gitcode.com/GitHub_Trending/io/IoT-For-Beginners创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考