Flutter实战:用手机控制全站仪,蓝牙通信与放样功能实现 简介面向移动端与测绘硬件交互开发者的Flutter蓝牙全站仪示例工程围绕徕卡TS09 plus全站仪连接场景系统讲解flutter_blue插件的设备扫描、连接建立、特征值读写以及测量坐标实时监听适合有一定Flutter基础、希望涉足蓝牙硬件控制的初中级开发者。压缩包共115个文件其中包含11个dart核心逻辑文件、23个png界面素材、15个xml配置并覆盖iOS/Android双端工程文件、Gradle构建脚本、属性配置与锁文件等整体仅861KB结构清晰便于按模块快速查阅。目前已有298人学习下载资料提供从项目初始化、设备扫描连接、坐标数据解析到页面构建的完整参考实现同时涉及状态管理与错误重试策略可帮助读者掌握蓝牙全站仪应用的整体开发流程并据此扩展至其他型号测绘仪器的适配工作。1. 为什么我想用 Flutter 去“控制”一台全站仪干测绘的老哥们应该都有过这种经历大热天在工地上架好全站仪测完一圈点还得蹲在仪器旁边戳那块小屏幕。按键小、反应慢、菜单层级深导数据还要拿U盘来回倒。更别说曲面墙放样这种活儿仪器自带程序算得费劲屏幕又显示不了多少信息操作起来极其难受。我去年接了一个项目核心诉求很简单把全站仪的数据采集和控制搬到手机上。硬件端走蓝牙通信业务端要同时覆盖iOS和Android还得支持离线作业和后端同步。当时团队里有人建议用原生双端开发我直接拍板用了Flutter。原因也简单项目周期只有三个月原生双端等于写两遍业务代码Flutter一套Dart代码两边跑UI迭代又快地图、表单、数据报表这些界面在Flutter生态里都有现成方案。这里要先说清楚一个概念全站仪的蓝牙和我们平时连耳机、连手环的蓝牙完全是两码事。测绘仪器走的基本都是经典蓝牙(Bluetooth Classic)的SPP串口透传协议简单说就是把蓝牙通道当成一根无线串口线来用。手机端通过蓝牙连接仪器后往串口里写ASCII文本指令仪器的测量结果同样以文本形式返回。整个链路就是手机发指令 → 蓝牙透传 → 全站仪执行 → 返回结果 → 蓝牙回传 → App解析上屏。这个项目做完我才真正体会到Flutter做这种工具型App确实有天然优势——高帧率的UI渲染、丰富的图表组件、跨平台一致的表现配合蓝牙串口通信处理测绘业务绰绰有余。后面几节我把整个项目的架构、蓝牙层的实现、放样逻辑的计算、数据存储和同步方案以及调试过程中踩过的坑全部拆开讲一遍给想做类似项目的人一个完整的参考。2. 项目整体架构与关键选型推演2.1 系统核心链路手机作为“智能屏幕”整套系统的设计思路是把全站仪定位成“测量内核”手机App定位成“交互大脑”。全站仪负责干它最擅长的测角、测距、跟踪测量手机负责干仪器不擅长的正经事显示图形化界面、管理上千个放样点、现场拍照记录、实时上传数据。这种架构下App端主要拆成五个模块蓝牙通信层负责扫描、配对、连接、读写串口数据向上层提供统一的收发接口指令协议层负责把业务操作封装成全站仪能识别的命令帧同时解析仪器返回的原始数据业务逻辑层坐标计算、放样引导、数据校验、点位管理等测绘核心逻辑数据持久层本地数据库存储测量数据、放样点库、项目配置支持离线作业同步服务层联网后与后端服务器增量同步数据模块间通过Repository模式解耦界面层只依赖业务逻辑层的接口不直接碰蓝牙。这样设计的好处很明显哪天要换仪器品牌只改指令协议层就够了UI完全不用动。2.2 技术选型的三层考量Flutter这块没什么争议重点说下蓝牙方案和数据存储。蓝牙通信我用的是flutter_blue_plus这个插件。选它的理由一是维护活跃二是支持经典蓝牙SPP和BLE双协议。在Android上同时管理两种连接类型不容易这个插件把底层差异封装得比较干净。iOS这边相对特殊系统对经典蓝牙SPP限制很严只支持MFi认证设备直连实测下来iPhone上想连传统全站仪非常困难只能走BLE兜底方案。这个后面会详细讲。数据存储我本地用的是sqflite就是SQLite的Flutter封装。为什么不用Hive或者Isar这种NoSQL方案因为测绘数据本身就是强关系型的——项目表关联放样点表放样点表关联测量记录表一组坐标往往还带着时间、气象参数、棱镜常数这些附属信息用关系型数据库组织最自然查询和统计也方便。2.3 离线优先的同步策略野外作业没信号是常态所以App必须离线能用回到办公室再同步。我用的是“离线优先”架构所有写操作先落本地数据库同时进入一张待同步记录表网络恢复后按时间戳增量推送。后端同步是另一个话题了这里不展开但Flutter做本地数据库加后端同步这条技术路线是完全可以落地的不用有什么顾虑。3. 蓝牙通信层的完整拆解从配对到数据上屏3.1 经典蓝牙SPP vs BLE怎么选这是整个项目里第一个关键决策点。全站仪这类测绘设备市面上绝大多数走的是经典蓝牙SPP因为串口透传对仪器厂商来说最简单可靠仪器端的MCU程序几乎不用改。SPP的特点就是像一根无线串口线数据流稳定、延迟低、吞吐量够用缺点是功耗高、连接建立慢。BLE呢省电、连接快、广播包方便做设备发现但数据传输要走GATT规范的Characteristic通道还得自己处理MTU大小、分包粘包对工业仪器的固件来说改动量不小。所以新款的国产全站仪里很多是SPP和BLE同时支持进口的老仪器基本上只有SPP。我的建议是通话如果你的目标仪器只支持SPPAndroid端直接连没问题iOS端要做好心理准备——必须买MFi认证的蓝牙转串口硬件或者干脆用支持BLE的新款仪器。选型的时候要把这个因素放在第一位考虑否则后期返工的成本非常高。3.2 指令协议解析以GeoCOM为例全站仪通信协议最主流的是GeoCOM徕卡系仪器用得多国内不少国产仪器事实上也兼容这套协议。GeoCOM的指令结构是这么个套路%R1Q,Request,参数,参数...比如要让仪器测距测角发送的指令大概是%R1Q,2008,1,0,0仪器返回的数据是%R1P,0,0,ErrorCode,HzAngle,VAngle,Distance,Time其中HzAngle是水平角VAngle是垂直角Distance是斜距。这些值一般是以角度秒或者度为单位需要根据协议说明换算。注意不同厂商的返回格式可能会差几个字段写解析器的时候一定要对着仪器说明书逐字节核对别想当然。3.3 粘包、拆包与超时重试蓝牙串口有个很烦人的特点——数据不是一次到位。仪器返回一帧完整数据可能需要拆成好几段到达稍不留神就会读到半个帧或者拼接错误。这里我的处理方式是维护一个字节缓冲区每次收到数据先追加进去然后按协议帧头%R1P、帧尾换行符做切割合法帧才交给解析器。还有一个重点是超时机制。蓝牙连接受距离、遮挡、设备状态影响很大指令发出去可能10秒没回应。我这边是发指令后启动2秒定时器2秒没响应就重发一次累计三次无响应就丢弃这次操作在界面上提示“通信超时”。千万别做成无限等待实测下来这是最容易卡死App的bug来源。3.4 蓝牙连接过程中的典型坑连接这块Android端有个坑——动态权限。Android 12之后扫描蓝牙设备需要BLUETOOTH_SCAN和BLUETOOTH_CONNECT这两个运行时权限很多人只申请了旧的BLUETOOTH权限导致扫描不到设备。我是在App启动时统一申请定位、蓝牙、存储三类权限实测下来最省事。iOS端的坑更隐蔽。前面说过iOS对SPP支持极差就算你用的是BLE全站仪也会遇到系统弹窗“是否允许配对”要多做一步配对确认的处理。如果目标设备只支持SPP在iOS上基本可以放弃直连了备选方案是买一个BLE转SPP的透传模块插在全站仪的数据口上做转换。4. 测量业务核心逻辑实现4.1 测距、测角和坐标计算全站仪的核心测量能力就两个测角、测距。拿到水平角、垂直角和斜距之后坐标计算就是高中数学的立体几何平面坐标增量N S × sin(V) × cos(Hz)E S × sin(V) × sin(Hz)高程增量Z S × cos(V) 仪器高 - 棱镜高这些公式看起来简单但实际工程环境里要考虑仪器高、棱镜高、球气差改正、投影变形这些修正项。我开始的时候只实现了基础公式现场测试发现算出来的坐标偏差超出预期后来把仪器高和棱镜高参数做成可配置项、在设置页默认填好常用值才算稳定下来。放样模式下则要反算角度和距离偏差把“目标点坐标 vs 当前实测位置”的差值连仪器转向提示一起显示出来引导测量员快速把棱镜移动到目标位置。4.2 曲面墙上点放样的实现思路“全站仪在曲面墙上点放样”是搜索引擎里很热的一个词正好是这个项目的一个亮点功能。曲面墙放样和普通地面点放样的区别在于普通放样是二维平面坐标棱镜立在平地上仪器能直接测到棱镜曲面墙上的点是在三维空间里的棱镜没法直接贴在墙上得先用全站仪照准墙面把仪器方向角读出来再根据墙面的曲率参数计算棱镜应该在的位置。我的实现思路分三步在墙面上采集三个基准点拟合出墙面的曲面方程。空间三个点可以确定一个平面但曲面墙需要更多采样点来做拟合拿到放样点的设计坐标后反算出该点对应的仪器水平角和垂直角驱动全站仪自动照准这个方向测量员沿着激光指示方向把棱镜移到墙上App根据实时测量结果和设计坐标的偏差用图形化箭头的形式引导移动这个功能做好后现场反馈特别好——原先要在墙上打一排线才能找点现在照着App的指示直接放样效率至少快了一倍。但要注意曲面墙拟合的精度高度依赖采样点的分布采样点尽量覆盖全墙面别集中在某一小块区域。4.3 项目数据模型设计数据表结构设计的成败直接决定后面好不好扩展。我这边实际用到的核心表有四张projects项目基本信息项目名、创建时间、坐标系、中央子午线参数points放样点库含点号、设计坐标、偏差容忍值、所属项目measurements测量记录含实测坐标、观测时间、天气参数、棱镜高sync_queue待同步记录记录每次操作的增删改类型时间戳measurements表专门设了一个观测时间字段这个后续同步冲突合并时会用到。数据模型设计上多花点时间思考后面写逻辑会很省心这个心得是玩了好几个项目才总结出来的。5. 实操过程复盘从Hello World到稳定版本5.1 环境配置和依赖踩坑Flutter环境本身安装不算难但有几个细节容易卡人。一个是Flutter SDK和Android Gradle Plugin的版本兼容问题新版Flutter对Gradle版本有硬性要求老项目直接报错“You are applying Flutters main Gradle plugin imperatively”搜半天才发现是新旧构建方式的冲突。我现在的习惯是每个项目都锁定Flutter版本然后单独配一份gradle-wrapper.properties。依赖安装还有一个经典坑国内网络拉不下来包。项目里如果直接跑flutter pub get会因为网络问题卡半天建议配置pub.dev的镜像。用本地镜像后依赖下载速度稳定很多少踩不少坑。5.2 真机联调的关键配置开发阶段在模拟器上是连不了蓝牙的买了两台测试机一台Android一台iPhone每天带着去工地实测。Android真机调试要注意USB调试权限和蓝牙权限分开授权部分国产ROM默认禁止后台使用蓝牙要在系统设置里把App的“后台运行”权限放开。iOS真机调试必须在Xcode里配置好Signing Capabilities再加上蓝牙的Privacy Usage Description。这个不配置的话App连接蓝牙时会直接崩溃或者闪退报错信息还不明显排查了半天。5.3 最小可行性版本怎么切做工具型App最容易翻车的地方是杂七杂八的功能一口气全铺开。我的项目排期方案是先做最小可行性版本只包含连接仪器、单点测量、放样三个功能把核心链路跑通之后再迭代加曲面放样、批量导入导出、数据同步这些高级功能。这个节奏安排下来第一阶段用了一个半月后面的功能更多是加法明显稳得多。6. 常见问题速查与规避技巧调了大半年蓝牙和全站仪我把实战中踩过的最典型的坑整理成了一张速查表这里直接全量贴出来问题现象原因解决方式扫描不到设备全站仪蓝牙已开启但App列表为空Android 12缺少动态权限仪器未进入可发现模式检查BLUETOOTH_SCAN等权限按说明书操作仪器进入蓝牙配对模式连接后频繁断连连接成功但几十秒后掉线仪器距离过远或中间有遮挡手机休眠网络休眠策略缩短连接距离设置Wi-Fi永不休眠检查仪器端自动关闭节能模式指令发出去没响应仪器不动App一直显示等待波特率不匹配串口参数不对指令协议版本不兼容统一串口设置核对指令格式建议先用PC串口助手做基线测试返回数据乱码收到一堆不可读字符波特率不匹配或仪器返回二进制ASCII混合格式切换字符编码方式重新核对协议文档iOS连不上SPP设备Android正常iPhone扫描不到iOS不支持非MFi设备的SPP连接购买BLE转SPP模块换用支持BLE的双模仪器放样偏差偏大放样点位和设计坐标差很多未配置棱镜常数、仪器高未进行后视定向当地投影参数不对认真设置仪器参数严格执行后视定向流程确认坐标系参数配置正确曲面拟合不准放样点落在曲面外采样点分布不均或数量不足拟合算法不适合剧烈曲率变化增加采样点、覆盖整面对高曲率区域做分段拟合补充三个直接提高作业效率的细节连接前先在手机设置里把蓝牙配对完成再进App连接成功率会高很多构造蓝牙长连接时每隔一段时间发一次心跳指令防止仪器端休眠断连全站仪指令协议文档一定从仪器厂商官网下最新版别拿老机器的说明书套新型号7. 版本迭代与可扩展方向这个项目做到后期已经有用户主动反馈使用体验甚至提了不少新需求。这里分享几个已经落地和值得继续做的方向给想做类似工具型App的朋友参考。批量放样与路径规划一次性导入几百个放样点按最近路径排序引导减少测量员来回跑的路线。目前我们的批量放样功能只能按点号顺序走下一步想优化成根据点位分布自动规划最短路径。语音播报偏差值放样时测量员眼睛盯棱镜没法一直看手机屏。做TTS语音播报“偏左三公分”“偏高两公分”直接解放双手实测反馈很好。三维可视化和点云叠加把放样点、已测点和CAD底图叠加到地图上这个对UI渲染性能要求高Flutter里可以用自定义绘制实现。多品牌仪器适配目前重点兼容的是GeoCOM系协议后续考虑扩展更多国内品牌的私有协议。工具型App项目的天花板往往不在技术难点上而是看你对业务场景的理解有多深。多跑几次现场、多和设备师傅聊几次比你多写一万行代码有用得多。8. 写在最后的项目复盘做这类“手机连接工业设备”的项目最大的感受是技术难点不在UI也不在业务逻辑而是在“设备通信”这一层。你写的代码能不能稳定地连上设备、发指令、读数据、解析数据决定了整个App的生死。Flutter在这个场景下表现比我预想的要好跨平台一致性、渲染性能、生态成熟度都够用拿来做工具型App是完全没有短板的。如果现在有人也准备做类似的项目我的建议就三条第一先花一周时间把目标设备的通信协议吃透拿PC串口助手把所有指令的返回都测一遍再动手写代码第二蓝牙通信层一定要做好超时和状态机管理这是稳定性的大头第三别把所有功能都写完再上现场测试第一版就带着最小可用版本去工地真机跑一遍你会发现很多问题只有真实验证才能暴露出来。最后再分享一个让我印象特别深的现场瞬间第一次用自己写的App在工地上成功放出一条完整的弧线墙时旁边的测量老师傅愣了一下仔细看了看手机屏幕然后说“这个真好用以后不用蹲地上看仪器了。”做项目最值得的就是这些真实用户反馈的瞬间。本文还有配套的精品资源点击获取