
IoT-For-Beginners 运输项目第 3 课使用 Azure Maps 与 GeoJSON 可视化 GPS 位置数据【免费下载链接】IoT-For-Beginners12 Weeks, 24 Lessons, IoT for All!项目地址: https://gitcode.com/GitHub_Trending/io/IoT-For-Beginners导读本课聚焦 IoT-For-Beginners 运输Transport项目中位置追踪环节的关键一步把上一课已经存储到云端 Blob 存储的 GPS 遥测数据在浏览器中以 Azure Maps 交互式地图的形式可视化呈现。你将依次掌握四件事理解数据可视化对 IoT 场景的价值、通过 Azure CLI 创建 Azure Maps 资源、用 Web SDK 在单页 HTML 中加载地图、以及使用 GeoJSON 标准格式把存储中的全部 GPS 轨迹点渲染为地图上的气泡图层。读完本课你将具备一套可直接复制运行的设备 GPS 数据 → 云端存储 → 网页地图端到端可视化方案。课程在运输项目中的位置本课是 3-transport 项目第 3 课位于完整数据链路的最后一环第 1 课location-tracking从 Wio Terminal、树莓派或虚拟设备上的 GPS 传感器读取经纬度第 2 课store-location-data通过 Azure IoT Hub 接收遥测用 Azure FunctionsEvent Hub 触发器把每条 GPS 事件写成gps-data容器中的 JSON Blob本课用 Azure Maps 把 Blob 中积累的轨迹点绘制到网页地图上。数据流为GPS 传感器 → IoT Hub → Azure Functions → Blob 存储 → Azure Maps Web SDK 地图页面。本课代码全部集中在一个index.html文件中完整实现位于仓库 code/index.html。什么是数据可视化从表格到地图数据可视化的本质是把数据以更利于人类理解的形式呈现从而帮助人更快做出决策——它不限于图表也包括符号、颜色、甚至报警时闪烁的红灯。课程用一个农场项目中的土壤湿度数据表说明问题日期读数01/06/2021 00:0025701/06/2021 01:0026801/06/2021 02:0029501/06/2021 03:0030501/06/2021 04:0032501/06/2021 05:0035901/06/2021 06:0039801/06/2021 07:0041001/06/2021 08:0042901/06/2021 09:0045101/06/2021 10:0046001/06/2021 11:0045201/06/2021 12:0042001/06/2021 13:0040801/06/2021 14:0043101/06/2021 15:0046201/06/2021 16:0043201/06/2021 17:0040201/06/2021 18:0038701/06/2021 19:0036001/06/2021 20:0035801/06/2021 21:0035401/06/2021 22:0035601/06/2021 23:00362一面数字墙很难直接读出含义一旦绘制成折线图湿度随时间的变化立刻清晰再叠加一条自动浇水系统在读数 450 时启动的参考线读者就能瞬间定位到系统被触发的时刻对 GPS 数据而言最直观的可视化方式就是把点画在地图上。例如物流场景中显示配送卡车实时位置、甚至附带货箱内容冷藏车需预留冷库空间的地图能让分拣中心的员工提前规划。好的可视化不一定复杂——有时最好的可视化就是一个闪烁的灯。地图服务与 Azure Maps 选型可用的地图服务很多Bing Maps、Leaflet、OpenStreetMap、Google Maps 等。本课选择 Azure Maps——它是一组地理空间服务与 SDK 的集合为 Web 与移动应用提供新鲜地图数据与地理上下文。Azure Maps 的能力包括推荐交通路线、交通事故信息、室内导航、搜索、海拔数据、天气服务等并且可通过 Azure Event Grid 集成实现地图的实时更新。从展示能力看Azure Maps 支持空白画布、瓦片、卫星图、卫星影像叠加道路、多种灰度图、带阴影地形的海拔图、夜间视图和高对比度地图通过启用平移、捏合、点击等控件控制地图交互通过叠加图层控制外观图层类型包括气泡bubble、线条line、多边形polygon、热力图heat map等。具体使用哪套 API 取决于 SDK 选型REST API、Web SDK或移动端的 Android SDK。本课使用Web SDK绘制地图并展示传感器 GPS 轨迹。创建 Azure Maps 资源动手第一步是创建 Azure Maps 账户资源。课程沿用gps-sensor资源组在终端中执行az maps account create --name gps-sensor \ --resource-group gps-sensor \ --accept-tos \ --sku S1--name gps-sensor资源名--resource-group gps-sensor所在资源组--accept-tos接受服务条款必选参数--sku S1付费层级包含较丰富的功能并带有一定量的免费调用额度。接着获取 API 密钥地图页面鉴权使用az maps account keys list --name gps-sensor \ --resource-group gps-sensor \ --output table复制输出中的PrimaryKey值稍后填入网页代码的subscription_key占位符。在网页中显示地图课程采用极简架构整份 Web 应用只用一个index.html文件生产环境通常会拆分为更多模块。仓库中已给出完整可运行版本code/index.html。第 1 步HTML 骨架与地图容器html head style #myMap { width:100%; height:100%; } /style /head body onloadinit() div idmyMap/div /body /html地图会加载进myMap这个div可命名并设置样式的页面区块CSS 让它铺满整页宽高body onloadinit()确保页面加载完成后调用初始化函数。第 2 步引入 Azure Maps Web SDK在head内加入外部样式表与脚本——这相当于 C 引入头文件或 Python 导入模块link relstylesheet hrefhttps://atlas.microsoft.com/sdk/javascript/mapcontrol/2/atlas.min.css typetext/css / script srchttps://atlas.microsoft.com/sdk/javascript/mapcontrol/2/atlas.min.js/script样式表控制地图外观脚本提供地图加载与交互逻辑。第 3 步初始化地图script typetext/javascript function init() { var map new atlas.Map(myMap, { center: [-122.26473, 47.73444], zoom: 12, authOptions: { authType: subscriptionKey, subscriptionKey: subscription_key, } }); } /script将subscription_key替换为az maps account keys list获取的PrimaryKey。center使用[经度, 纬度]顺序[-122.26473, 47.73444]即美国华盛顿州西雅图市中心zoom: 12控制缩放级别。保存后在浏览器打开index.html即可看到聚焦西雅图的地图可以调整zoom与center数值换成自己数据对应的经纬度来重新定位地图。 本地开发更规范的方式是用http-server等静态服务器托管页面安装 Node.js 与 npm 后在index.html所在目录执行http-server浏览器访问http://127.0.0.1:8080/即可。GeoJSONAzure Maps 的地图数据语言地图已经就绪下一步要把存储在存储账户中的 GPS 数据渲染成地图上的标记层。Azure Maps 要求的数据格式是 GeoJSON——一个用于表达地理数据的开放标准 JSON 规范。学习与调试 GeoJSON 的好工具是 geojson.io可粘贴样例数据即时预览并排查错误。一个最小示例{ type: FeatureCollection, features: [ { type: Feature, geometry: { type: Point, coordinates: [ -2.10237979888916, 57.164918677004714 ] } } ] }结构要点数据以Feature嵌套在FeatureCollection中Feature内含geometrygeometry的type可以是Point、多边形等coordinates给出具体坐标。⚠️坐标顺序陷阱GeoJSON 对点数据要求lon, lat经度在前、纬度在后的顺序而不是常见的lat, lon顺序写反会导致点显示在错误位置。Azure Maps 支持标准 GeoJSON 及若干扩展特性如绘制圆形等几何体。用 GeoJSON 把 GPS 轨迹绘制到地图前一课store-location-data将每条 GPS 遥测以 JSON 写入 Blob 容器gps-dataBlob 命名形如gps-sensor/uuid.json内容为{device_id: gps-sensor, timestamp: 2021-05-21T00:57:53.878Z, gps: {lat: 47.73092, lon: -122.26206}}浏览器页面读取这些 Blob 时会有两处关键前置工作CORS 放行、以及用存储列表 API 枚举文件。配置存储 CORS 以允许网页读取直接从网页向存储发起读取会遭遇浏览器控制台报错——因为存储账户默认未开启 CORSCross-Origin Resource Sharing跨域资源共享。出于安全考虑Azure 需要显式配置防止未预期的站点访问你的数据。执行az storage cors add --methods GET \ --origins * \ --services b \ --account-name storage_name \ --account-key key1storage_name存储账户名key1存储账户密钥可用az storage account keys list --output table --account-name storage_name获取--methods GET允许 GET即读取数据请求--origins **通配符表示允许任意来源网站--services b仅作用于 blob 服务。加载并渲染 GPS 数据把init函数整体替换为以下代码仓库 code/index.html 中即为最终形态fetch(https://storage_name.blob.core.windows.net/gps-data/?restypecontainercomplist) .then(response response.text()) .then(str new window.DOMParser().parseFromString(str, text/xml)) .then(xml { let blobList Array.from(xml.querySelectorAll(Url)); blobList.forEach(async blobUrl { loadJSON(blobUrl.innerHTML) }); }) .then( response { map new atlas.Map(myMap, { center: [-122.26473, 47.73444], zoom: 14, authOptions: { authType: subscriptionKey, subscriptionKey: subscription_key, } }); map.events.add(ready, function () { var source new atlas.source.DataSource(); map.sources.add(source); map.layers.add(new atlas.layer.BubbleLayer(source)); source.add(features); }) })这段代码分四步工作枚举容器内 Blob对https://storage_name.blob.core.windows.net/gps-data/?restypecontainercomplist发起请求restypecontainercomplist表示列出容器内所有 Blob 的信息不是 Blob 内容本身而是每个 Blob 的可访问 URL。该 URL 可直接粘贴到浏览器查看 XML 形式的 blob 清单每个Url元素就是单个 Blob 的下载地址逐个加载 Blob用DOMParser把 XML 响应解析成文档取出所有Url元素逐个调用loadJSON加载真实数据创建地图控件与上节相同的方式创建atlas.Map注意这里zoom提升到 14更贴近地面并给ready事件挂接回调——该事件在地图渲染完成、可见于页面时触发ready回调中构建图层new atlas.source.DataSource()创建 Azure Maps 数据源一个待填充 GeoJSON 数据的容器map.layers.add(new atlas.layer.BubbleLayer(source))把它渲染为气泡图层在每个 GeoJSON 点上画圆最后source.add(features)把解析出的全部点塞进数据源。loadJSON把存储 JSON 转换为 GeoJSON Feature在init下方追加var map, features; function loadJSON(file) { var xhr new XMLHttpRequest(); features []; xhr.onreadystatechange function () { if (xhr.readyState XMLHttpRequest.DONE) { if (xhr.status 200) { gps JSON.parse(xhr.responseText) features.push( new atlas.data.Feature(new atlas.data.Point([parseFloat(gps.gps.lon), parseFloat(gps.gps.lat)])) ) } } }; xhr.open(GET, file, true); xhr.send(); }逐行要点var map, features;把map与features提升为脚本级变量供init与loadJSON共享features最终会被ready回调里的source.add(features)消费new XMLHttpRequest()发起异步 GET 请求readyState XMLHttpRequest.DONE且status 200表示请求成功JSON.parse(xhr.responseText)解析 Blob 内容取出gps.gps.lon与gps.gps.lat——这正是前一课写入 Blob 的{gps: {lat: ..., lon: ...}}嵌套结构可对照 store-location-data 中message_json { gps : { lat:lat, lon:lon } }的遥测构造parseFloat把字符串坐标转为浮点数new atlas.data.Point([lon, lat])严格按lon, lat顺序构造点对应 GeoJSON 的坐标序约定atlas.data.Feature包装为 Feature注意由于存储 JSON 中字段本就是lon经度与lat纬度此处解析天然满足lon, lat顺序。浏览器加载页面后会依次完成加载地图 → 枚举 Blob → 拉取全部 GPS 数据 → 在ready回调中以气泡图层绘制。课程示例西雅图附近的圣爱德华州立公园徒步轨迹运行结果如下气泡沿公园边缘勾勒出完整路径进阶挑战与作业 挑战让轨迹动起来当前实现展示的是静态标记。课程的进阶挑战是利用带时间戳的 JSON 文件为 Web 应用加入动画让标记随时间沿路径移动从而还原设备行进过程。部署作业完成可视化后可参考 assignment.md 将应用部署上线如 Azure Static Web Apps。该作业特别强调一个安全实践借助部署平台把subscriptionKey以环境变量形式存入云端并把代码中的密钥重构为变量引用避免把 API 密钥硬编码在公开仓库中。评分标准Rubric核心两条应用能否正常工作subscriptionKey是否存于云端并通过变量调用。小结本课打通了 IoT 位置数据的最后一公里从 Azure CLI 创建 Maps 资源到用 Web SDK 在单页 HTML 中加载地图再到用 GeoJSON 标准表达坐标、以DataSource BubbleLayer把云端 Blob 中累积的 GPS 轨迹渲染为地图上的气泡路径。全部关键代码集中在一个可运行的 index.html 中配合上文的 CORS 配置与坐标顺序要点即可复现完整的传感器 → 云端 → 地图可视化链路。继续研究可阅读课程配套的 sketchnote 概览图 以及 运输项目主页 中其他课程。【免费下载链接】IoT-For-Beginners12 Weeks, 24 Lessons, IoT for All!项目地址: https://gitcode.com/GitHub_Trending/io/IoT-For-Beginners创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考