Board logo

标题: 使用 Bluemix 提供的 IoT 和 GPS 服务提高您的健康水平(5) [打印本页]

作者: look_w    时间: 2018-11-13 19:02     标题: 使用 Bluemix 提供的 IoT 和 GPS 服务提高您的健康水平(5)

地图全知如何帮助用户找到可以散步、长途旅行或跑步的位置?使用 HTML5 功能访问位置服务(要么通过支持位置的标准 PC 浏览器,要么通过移动设备的 GPS        功能),现在仪表板中增加了一个嵌入式 Google 地图,可显示用户的当前位置。在该地图的视图下面,您要提供一个基于行程查找本地公园的搜索功能,即来自 Pitney Bowes        的第三方 Travel Boundary Service 部分提供的一个功能。
出行时间与半径搜索Travel Boundary Service 只是散步地点搜索得出的部分答案,因为它只关注于回答一个问题,即 “地图哪一部分可在指定的出行时间内从某一点到达?”        该服务返回一个多边形,包含地图上满足您的出行时间条件的点。如果要使用此多边形和实际地点数据库生成附近公园的列表,则需要执行其他的步骤。
travel boundary service 是一个有用的位置搜索方法,因为距离可以与可达性和出行时间分离开来。一家餐厅可能距离当前 GPS 位置仅有 500        英尺,但是,如果它在一条河的对岸,而且最近的跨线桥有 10 英里远,那么实际的出行时间要远远长于河这边街上距离 1,000 英尺的餐厅。这一固有的半径搜索问题通过 Bluemix        中提供的 travel boundary service 得到了解决。
获悉用户可能没有时间长途跋涉去一个公园,我将 travel boundary service 与可供用户选择的 4 个针对出行时间距离的固定时间选项(5、10、15 或 20        分钟)结合起来:
对 Pitney Bowes 服务的 REST 调用使用 restcall 模块建立 API 端点和参数:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
function queryBoundaryData(distance, lat, lon, callbackFn) {

    var url = require('url');

    var iotURLObj = url.parse(tbsprops.url);
    var host = iotURLObj.host;
    var endpoint = iotURLObj.pathname;
    endpoint += "?latitude=" + lat + "&longitude=" + lon +
                "&cost=" + distance + "&units=Minutes&appId="+tbsprops.appId;

    //appears to be a potential issue with the SSL cert on the PitneyBowes
    //boundary service; using "rejectUnauthorized: false" as option to the
    //HTTPS Node.js module until this problem is corrected
    var options = {
      host: host,
      path: endpoint,
      method: "GET",
      rejectUnauthorized: false
    };
    console.log("URL: "+host+" / Endpoint: "+endpoint);

    //send the request to the Travel Boundary Service API
    restcall.get(options, true, callbackFn);
}




请注意,在注释中,在撰写本文时为了规避 SSL 证书问题,允许 SSL 验证松散连接安全,以便进行 REST        调用(一个合理的临时解决方法,因为您传递的数据没有固有的隐私问题)。如果您使用的数据需要较强的隐私和安全性,那么更好的选择是使用 API 提供程序纠正证书验证/签名问题。
查找公园有了从 travel boundary service 返回的多边形(交给回调函数)之后,如何找到该区域内的公园?用于访问位置数据的选项有限。Google Maps        API(更准确地说是 Google Places)不提供多边形搜索 API。         有一个多边形搜索功能,但兴趣点 (POI) 数据库比 Google 弱。
这两种地图/搜索服务都不是 Bluemix 服务。但您可以使用与调用服务类似的方式从您的应用程序调用外部 REST API(没有 Bluemix 生态系统的集成服务绑定、支持和        SLA 承诺)。这样做的一个优势在于,您不用硬编码源代码中的任何服务信息,而是可以使用 Bluemix 内 “用户定义的” 环境区域,在一个可以从您的应用程序访问的变量中添加服务端点        URL 和应用程序密钥/ID 细节。
从 Bluemix 仪表板创建用户定义的环境变量的步骤如下:
您还可以使用 cf 命令行工具执行这些变量添加工作:
1
cf set-env appnamevariable value




由于现在已准备好了所有必要组件:用于搜索的多边形、一个 MapQuest API 密钥(免费支持有限的 API 调用)和 “Parks” 的 MapQuest 类别代码(可在        MapQuest 的在线 POI 文档中找到),MapQuest REST 调用构建起来相当简单。
在我们现在应当已经熟悉的代码模式中,用于搜索公园的 API 调用如下所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
function findParksInPolygon(polygonData, callbackFn) {

    //MapQuest API host - added in Bluemix user-defined env data
    var host = process.env.mqHost;
    //community version API key to MapQuest services - from user env data
    var mq_appKey = process.env.mqAPIKey;

    //search USA dataset with group == Parks code
    var searchParksOnly = "&hostedData=mqap.ntpois|group_sic_code=?|799951"
    //polygon search endpoint + API key and above Parks restriction
    var endpoint = "/search/v2/polygon?key="+mq_appKey+searchParksOnly;
    endpoint += "&polygon=";

    //iterate through the polygon from the PitneyBowes service and add to
    //the API call to MapQuest
    var polygonResult = polygonData.Output.IsoPolygonResponse.Polygon[0];
    (polygonResult.Exterior.LineString[0].Pos).forEach(function (point) {
      endpoint += ""+point.Y+","+point.X+",";
    });
    //trim the ending comma
    endpoint.replace(/\,$/,"");

    var options = {
      host: host,
      path: endpoint,
      method: "GET"
    };

    console.log("URL: "+host+" / Endpoint: "+endpoint);

    //send the request to the MapQuest Polygon Search API
    restcall.get(options, false, callbackFn);
}




对于美国和加拿大以外的位置,您可以将 searchParksOnly 变量中的 hostedData= 参数改为          mqap.internationalpois,从而将数据库切换为 MapQuest 的国际 POI        数据库。应用程序经过改进后就能评估用户的位置数据,并决定要使用哪个数据库。
代码最乏味的部分是,将 travel boundary service 多边形数据修改为 MapQuest API 期待的形式。因为对该路径(架构图中的 GET          /tbs)的原始调用是使用浏览器端 JavaScript 的 Ajax 调用,该调用通过用户选定出行时间后单击 Search        按钮来驱动,响应并非一个渲染的 HTML 页面,因为它用于其他路径;它仅通过 HTTP 连接传递回 JSON。以下代码段中汇总了该路径的操作的整个序列:
1
2
3
4
5
6
queryBoundaryData(dist, lat, lon, function(polygonData) {
   //now use the polygon response to search MapQuest Polygon search API
   findParksInPolygon(polygonData, function(resultData) {
     res.send(resultData);
   });
});




请注意,为了简便起见,回调函数被实现为匿名内联函数。结果是,浏览器端 JavaScript(参见 public/js/iot.js 文件中的          searchNearMe() 函数)收到 MapQuest 多边形 POI 数据搜索所得的原始 JSON,并负责将其显示给最终用户。
我没有编写一个大的循环来在更美观的 HTML 中呈现所有结果,而是使用了   模板库。内联模板处理从原始数据到表格式化的公园显示的转换。有了表明用户位置的嵌入式 Google Map        之后,就可以很容易地通过结果循环,为每个结果添加标记到地图并随附 Google Maps Directions 服务的链接:
有关使用 Google 的 Map 和 Marker 类的更多细节,查看 public/js/iot.js 中 searchNearMe()        函数中的代码。它使用了 google.maps.Marker 类,以及 MapQuest        查询已经提供的位置和名称信息,将标记添加到地图。另外这有助于移动设备上的访问:单击标记的信息窗口中的链接可以自动进入针对选定目标公园的导航模式。




欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) Powered by Discuz! 7.0.0