我们使用了 Bluemix Node.js SDK 来开发样本客户端 web 应用程序,以便与区块链交互并从区块链查询数据。这个客户端应用程序将会查询区块链,以显示资产和事务细节。它还会触发模拟数据,这些数据被发送到 Watson IoT Platform ,然后发送到驾驶员分析服务来获得驾驶行为评级。
这是所有 REST API 调用所使用的配置。它建立了您将要连接的对等节点,用于验证 API 调用的用户 id 和密码,以及调用参数。
- var config = {
- host: "<peer id>-vp0.us.blockchain.ibm.com",
- port: "5003",
- secure_context: "<user id>",
- enroll_secret: "<enroll secret>",
- protocol: "https",
- debug_mode: true,
- chaincodeURL: "<peer id>-vp0.us.blockchain.ibm.com:5003/chaincode",
- name: blk_chaincode,
- path: blk_chaincode,
- messageId: "",
- contract_version: "1.0",
- timeout: 3000,
- template: {
- "jsonrpc": "2.0",
- "method": "{{method}}",
- "params": {
- "type": 1,
- "chaincodeID": {
- "name": "mycc",
- },
- "ctorMsg": {
- "function": "{{function}}",
- "args": [],
- },
- "secureContext": "<user id>",
- },
- "id": 0
- },
- };
以下各节将逐步指导您实现演示应用程序。其中的代码段将展示如何使用 IBM Blockchain REST API 注册资产、更新资产数据,以及在区块链中查询当前和历史资产数据。
用户首先将他或她拥有的车辆注册为资产。图 5 显示了演示应用程序支持的资产细节。
点击查看大图
需要使用这个区块链方法:
。另外,使用一个 Cloudant 数据库作为该演示的车辆存储库。在区块链中创建资产后,将车辆插入该数据库中。
- createAsset()
- // Prepare the rest body for createAsset
- createBody.method = 'invoke';
- createBody.params.ctorMsg.
- function = 'createAsset';
- createBody.params.ctorMsg.args = ["{\"assetID\":\"" + input_vin + "\",\"ownerName\":\"" + input_ownerName + "\",\"createDate\":\"" + v_createdt + "\",\"numberPlate\":\"" + input_numberPlate + "\"}"];
- // Call blockchain createAsset function using rest api
- https.request(options,
- function(res4) {
- res4.setEncoding('utf8');
- res4.on('data',
- function(chunk) {
- console.log('BODY: ' + chunk);
- });
- // Prepare the vehicle JSON structure for inserting into Cloudant
- var vehicle = {
- vin: input_vin,
- owner: input_ownerName,
- number: input_numberPlate,
- status: 'active',
- createDate: v_createdt
- };
- var v_id = input_vin + ' - ' + input_numberPlate;
- // Insert the vehicle into Cloudant
- db.insert(vehicle, v_id,
- function(err, body, header) {
- if (err) {
- return console.log(v_id + ' -- [insert] ', err.message);
- }
- });
- }).end(JSON.stringify(createBody));
这就完成了要跟踪的资产的准备工作。第 2 步将展示如何捕获和扩充 IoT 数据。
注册一辆车后,需要发送车载传感器数据。使用一个设备模拟器将车辆探测数据发送到 Watson IoT Platform。请参阅设备模拟器代码,了解模拟器车辆驾驶数据。
下面这段代码展示了如何将数据发送到 Watson IoT Platform:
- deviceClient
- .
- connect
- ();
- deviceClient.on('connect',
- function() {
- if (iotDeviceConnectionStatus == false) {
- iotDeviceConnectionStatus = true;
- var i = 0;
- console.log("connected");
- var IOTSent = setInterval(function sendIOTData() {
- if (i >= totalcount) {
- deviceClient.disconnect();
- iotDeviceConnectionStatus = false;
- selectedVehicle.sim_status_id = "1";
- iotDataSent = true;
- clearInterval(IOTSent);
- return;
- }
- datatopublish.d = carprobesampledata[i];
- i++;
- processingStatus = "Capturing car data " + i + "/" + totalcount;
- console.log(processingStatus);
- var driveTimestamp = new Date().toISOString();
- datatopublish.d.timestamp = drivedate + driveTimestamp.substr(10, driveTimestamp.length);
- datatopublish.d.trip_id = assetid + moment(new Date()).format('DD');
- datatopublish.ts = drivedate + moment(new Date()).format('THH:mm:ss.SSSZZ');
- deviceClient.publish('load', 'json', JSON.stringify(datatopublish), 0);
- },
- delay * 800);
- console.log("End of on connect..");
- }
- });
上面介绍的自定义 Node-RED 流将会监听 IoT Platform 事件。该流从 IoT Platform 接收传感器数据。我们已实现了这个流来调用 Context Mapping 服务并扩充数据。
然后 Node-RED 流将经过扩充的传感器数据发送到 Driver Analysis 服务进行存储。
接下来,您需要协调该数据的分析,并在区块链资产中更新分析结果。在本教程中,协调工作由前端模拟器演示应用程序完成。
用户应会看到 UI 中的状态已更新。
驾驶员分析作业提交 API (POST) URL,如下所示:
- https://automotive.internetofthings.ibmcloud.com/driverinsights/jobcontrol/job?tenant_id=yourtenantid&from= dateoftravel&to=dateoftravel
- Authorization Basic userid:secretkey
userid 和 secretkey 来自您附加到 Bluemix 应用程序的 Driver Behavior 服务。如果您想在一个批次中分析多天的数据,可以让 “to” 日期晚于 “from” 日期。
- var
- new_event_date
- =
- moment
- (
- selectedVehicle
- .
- lastEventDate
- ,
- 'DD-MMM-YYYY'
- ).
- add
- (
- 1
- ,
- 'days'
- ).
- format
- (
- 'YYYY-MM-DD'
- );
- path_str = "&from=" + new_event_date + "&to=" + new_event_date;
- console.log(path_str);
- driver_path_post =
- “https://automotive.internetofthings.ibmcloud.com/driverinsights/jobcontrol/job?tenant_id=<tenant_id>”+
- path_str;
- request(
- {
- url : driver_path_post,
- method : 'POST',
- headers : {
- "Authorization" : auth,
- "content-Type" : 'application/x-www-form-urlencoded'
- }
- },
- function (error, response, body) {
- var jsonbody = JSON.parse(body);
- selectedVehicle.job_id = jsonbody.job_id;
- selectedVehicle.sim_status_id = "2";
- selectedVehicle.sim_status_desc = "Driver analysis in progress. This might take couple of minutes. Job id = " + jsonbody.job_id;
- res7.render('index', { title : 'Home', moment: moment, selectedVehicle : selectedVehicle, vehicleList : db_vehicle_list, sim_triggered : 'true'});
- });
这会返回一个 JSON 格式的
,如下所示:
- job_id
- {
- "job_id": "4f9b70ef-6bcd-4a21-b311-e57ba9729a3d"
- }
有了这个
后,等待驾驶员分析完成。对于我们的样本数据,这可能花费大约一分钟的时间。
- job_id
这是作业状态 API (GET) URL:
- https://automotive.internetofthings.ibmcloud.com/driverinsights/drbresult/tripSummaryList?tenant_id=yourtenantid&job_id=yourjobid
代码段如下所示:
- path_str
- =
- "&job_id="
- +
- selectedVehicle
- .
- job_id
- ;
- driver_path_get =
- “https://automotive.internetofthings.ibmcloud.com/driverinsights/jobcontrol/job?tenant_id=<tenant_id>”
- + path_str;
- request(
- {
- url : driver_path_get,
- method : 'GET',
- headers : {
- "Authorization" : auth,
- "content-Type" : 'application/x-www-form-urlencoded'
- }
- },
- function (error, response, body) {
- var jbody_1 = JSON.parse(body);
- var sim_stat = jbody_1["job_status"];
- console.log("job status - " + sim_stat);
- if(sim_stat=="SUCCEEDED")
- {
- selectedVehicle.sim_status_id = "3";
- selectedVehicle.sim_status_desc = "Driver analysis is complete.. Fetching results...";
- }
- });
返回的 JSON 将包含作业状态 “RUNNING” 或 “SUCCEEDED”。如果它处于 “RUNNING” 状态,则会在一定间隔后调用同一个 API。
得到驾驶员分析结果后,需要将结果数据结构转换为可被我们部署的链代码接受的数据结构。
在我们的样本代码中,为简单起见,此结构基本保持相同;不需要重大转换。
要抓取行程细节,需要对驾驶员服务 API 执行两次调用。使用租户 id 和作业 id 进行第一次调用,以获取行程
uuid:
- https://automotive.internetofthings.ibmcloud.com/driverinsights/drbresult/tripSummaryList?tenant_id=<tenant_id>&job_id=<job_id>
使用行程 uuid
进行第二次调用,以获取行程细节:
- https://automotive.internetofthings.ibmcloud.com/driverinsights/drbresult/trip?tenant_id=<tenant_id>&trip_uuid=<trip_uuid>
此数据结构中已更新了驾驶员和保险公司评级。如果检测到不良驾驶事件,则会降低评级;如果未检测到事件,表明驾驶行为良好,评级会提升。
接下来,使用一个字符串数组作为输入参数,调用链代码的
方法。该数组的长度为 1。所以该数组的
- updateAsset
元素会包含上一步中获得的数据结构。
- 第
- 0
- 个
- // Prepare the rest body for updateAsset
- updateBody.method = 'invoke';
- updateBody.params.ctorMsg.function = 'updateAsset';
- updateBody.params.ctorMsg.args = ["{\"assetID\":\""+ input_vin +"\",\"lastEvent\":\""+ input_lastEvent +"\"}"];
- // Call blockchain updateAsset function using rest api
- https.request(options, function(res4) {
- res4.setEncoding('utf8');
- res4.on('data', function (chunk) {
- console.log('BODY: ' + chunk);
- });
- }).end(JSON.stringify(updateBody));
使用资产 ID 调用
来获取最新评级,并将它显示在 UI 上。
- readAsset()
- var
- queryBody
- =
- config
- .
- template
- ;
- queryBody.params.chaincodeID.name = blk_chaincode;
- // Prepare the rest body for readAsset
- queryBody.method = 'query';
- queryBody.params.ctorMsg.function = 'readAsset';
- queryBody.params.ctorMsg.args = [ "{\"assetID\":\""+selected_vin+"\"}"];
- console.log('queryBody - ' + JSON.stringify(queryBody));
- var raw_str;
- // Call blockchain readAsset function using rest api
- https.request(options, function(res2) {
- res2.setEncoding('utf8');
- res2.on('data', function (chunk) {
- console.log('BODY: ' + chunk);
- raw_str+=chunk;
- var json_str = eval('(' + chunk + ')');
- var json_msg = eval('(' + json_str.result.message + ')');
- selectedVehicle.assetID = json_msg.assetID;
- selectedVehicle.createDate = json_msg.createDate;
- selectedVehicle.ownerName = json_msg.ownerName;
- selectedVehicle.numberPlate = json_msg.numberPlate;
- selectedVehicle.lastEventDate = moment(new Date(json_msg.txntimestamp)).format('DD-MMM-YYYY');
- });
- }).end(JSON.stringify(queryBody));
如下面的代码段中所示,调用链代码的
方法来获取历史数据。通过使用历史数据,可以列出车辆过去的行程,而且可以根据纬度和经度在地图上显示该行程。
- readAssetHistory()
- queryBody
- .
- method
- =
- 'query'
- ;
- queryBody.params.ctorMsg.
- function = 'readAssetHistory';
- queryBody.params.ctorMsg.args = ["{\"assetID\":\"" + selectedVehicle.assetID + "\"}"];
- // Call blockchain readAsset function using rest api
- https.request(options,
- function(res2) { res2.setEncoding('utf8'); res2.on('data',
- function(chunk) { console.log('BODY: ' + chunk);
- var jbody_1 = JSON.parse(chunk);
- var json_msg = jbody_1[0].result.message;
- });
- }).end(JSON.stringify(queryBody));
本教程中的演示(和代码样本)表明,快速构建一个与 IBM Blockchain 服务实例集成的认知 IoT 应用程序相对容易一些。可以分析来自 IoT 传感器的数据并将其传递到运行规则的区块链智能合约中,完成可由所有参与的对等节点验证和同意的事务。
可通过包含更多认知服务来进一步增强这个应用程序,例如,这些服务可以集成一个行程期间的天气数据或不同位置的驾驶限制,以便进一步分析驾驶员在不同条件下的响应。还可以在培训场景中使用类似的解决方案来分析新驾驶员的表现。
来源: http://www.ibm.com/developerworks/cn/cloud/library/cl-softlayer-go-overview/index.html