脚本作为应用组建的重要补充,为用户提供更加灵活的方式来实现项目的业务逻辑。当前平台支持的脚本语言为node.js。编程语法及支持的内容都和标准node.js相同。

新建脚本

通过点击项目工作台左侧的“脚本”按钮,进入脚本管理页面。



点击列表右上侧的“新建脚本”按钮会弹出新建脚本弹窗。



用户需要为脚本命名,现阶段仅支持Node.js脚本。点击确认后,进入脚本编辑流程。



新建出的脚本文件,平台会为用户自动生成必须的初始化代码。用户可以快速地在已有的代码中开始自己的业务逻辑的书写。其中IIoTClient为系统为用户实例化的一个可以对平台数据源,设备进行操作的对象实例。由于脚本的语法本身完全与Node.js相同,所以在此不对脚本的基础使用作介绍,下面会重点介绍如何通过脚本对项目中的数据源和设备进行操作。

示例代码解读

/*
初始化一个名为IIoTClient类,引用了iiot-sdk.js这个包,其中./iiot-sdk/iiot-sdk.js路径不允许改变
  iiot-sdk.js是平台封装的一个sdk文件,里面调用了aliyun-api-gateway的API,并且封装了一些常用接口
  比如下面要介绍的数据源操作、设备操作、OEE操作的API。
*/
const IIoTClient = require('./iiot-sdk/iiot-sdk.js');  

/*
这是阿里云FC的标准入口函数写法,入口可以带有三个参数,event事件,context上下文,及脚本执行的回调,
对于这三个参数的解析可以参考
https://help.aliyun.com/document_detail/52633.html?spm=a2c4g.11186623.6.569.242b79cdQVeNfH
*/
module.exports.handler = function(event, context, callback) { 
  /*
  这里实例化一个cient对象,用于后面对于sdk中的API的调用,注意这里的appKey是阿里云网关调用的签名
  这里用户不需要修改,平台会自动注入环境变量
  */
  const client = new IIoTClient({ 
    appKey: process.env['appKey'], 
    appSecret: process.env['appSecret'] 
  }); 

  /*
  这里是自定义的一个属性参数变量,变量类型为json对象,对象中的key请参考下面的API参数说明,每个API
  入参的格式都是不一样的,必须符合入参格式才能调用成功。
  */
  const getPropertiesParams = {
    "productKey": "a147vduL8D6",   /*产品名*/
    "deviceName": "ptOEEyufa0322A", /*设备名*/
    "properties": ["E_Craft_Speed_China_Spray", "E_Craft_TT_Drying_Spray"] /*两个设备属性*/
};

/*
client.xxx.then(value => {},error=>{});这是标准语法,返回的是异步调用成功和失败的结果
  开发者只需要在{}内写自己的逻辑即可。
  */  
client.getThingDeviceProperties(getPropertiesParams).then(value => {
    /*这是一句nodejs的标准打印函数,这个在si/oc平台上调试运行的时候是打印不出来的,只能在本地调试的时候打印出*/
    console.log("get device property ok, data : " + JSON.stringify(value));

    /*这是阿里云FC脚本回调的标准API,结果会在oc/si的调试窗口显示出来,作为脚本的执行返回值*/
    /*如果是返回成功,则callback的第一个参数必须为null*/
    callback(null, JSON.stringify(value)); 
    /*JSON.stringify是javascript的json转字符串函数,以为value返回的是一个对象,
      所以需要字符串序列化才能打印出来,返回的格式请参考API返回的格式章节*/
}, error => {
   callback(error)); /*如果是返回失败,则只需要一个参数*/
});
}

API返回的格式

对于sdk中封装的API,其返回格式都是一个json对象,对象中的成员如下:

返回参数 类型 说明
code 整形 200为API执行成功,其他为失败
data 对象 对象中的成员请参考具体的API
id 字符串 唯一id标识
例如:{"code":200,"data":{"E_Craft_Speed_China_Spray":11},"id":"1553846140475"}
例如:字符串对象中的成员请参考具体的APIdata整形说明返回参数如何在脚本代码中获取结果的具体值?

返回结果是个对象,所以可以使用value.data.E_Craft_Speed_China_Spray 即可以获取11这个值。数据源操作

数据写入

说明:将脚本内计算的数据写入指定的数据源节点内。

/**
* @param params 数据源写入参数
* {
*      "id" : 582,                    //int, 数据源Id
*      "name" : "SourceTable",        //String, 数据源标识。标识和Id,二者选一即可
*      "nodes" : ["field1","field2"],      //数据表字段名数组
*      "data" : [["f1","f2"],["f3","f4"]]  //数据内容数组
* }
 @returns {}
*/
pushDataToDataSource(params);
数据拉取

说明:通过一定规则条件从指定数据源节点获取数据。

/**
* @param params 数据源拉取参数
* {
    "id":123                               //数据源ID
   "name":"SourceForTest",                //数据源名称,名称、ID至少填一个
   "expr":{
   "condition":[{
       "col":"city",
       "op":"EQUAL",
       "value":"北京"
    }],
     "op":"AND"
    },
    "nodes":[                              //需要查询的列名
      {"name":"field1"},
    {"name":"field2"}
  ],
    "page":{"to":1, "size":15},             //分页信息
    "orderby":[{"col":"id", "type":"asc"}]  //排序信息
* }
* @returns {*}
*/
pullDataFromDataSource(params);
操作示例
const IIoTClient = require('./iiot-sdk/iiot-sdk.js');
module.exports.handler = function(event, context, callback) {

    const client = new IIoTClient({
        appKey: process.env['appKey'],
        appSecret: process.env['appSecret']
    });

    const params = {'data':[['北京',10.1,'2018-04-26 00:00:00'],['北京',19.8,'2018-04-26 02:00:00']],'id':15132,'name':'数据源名称','nodes':['city','temp','time']};

    client.pushDataToDataSource(params).then(value => {
        console.log('ok, data : ' + JSON.stringify(value));
        callback(null, value);
    }, error => {
        console.error('failed, data :'  + JSON.stringify(error));
        callback(error);
    });
}
设置设备属性 setThingDeviceProperties

参数说明:

"productKey": String,
    "deviceName": String,
    "items": {
        "param1": value1,  /*需要设置的属性1*/
        "param2": value2   /*需要设置的属性2*/
    }
示例:
const IIoTClient = require('./iiot-sdk/iiot-sdk.js'); 

module.exports.handler = function(event, context, callback) { 
  const client = new IIoTClient({ 
    appKey: process.env['appKey'], 
    appSecret: process.env['appSecret'] 
  }); 

const setPropertiesParams = {
    "productKey": "a147vduL8D6",
    "deviceName": "ptOEEyufa0322A",
    "items": {
        "E_Craft_Speed_China_Spray": 1.0,
        "E_Craft_TT_Drying_Spray": 2.0
    }
};
client.setThingDeviceProperties(setPropertiesParams).then(value => {
    console.log("setThingDeviceProperty, data : " + JSON.stringify(value));
    callback(null,JSON.stringify(value));
}, error => {
    console.error("get device property failed");
    callback(error);
});
  //请开始编写代码
}
调用设备服务 invokeThingDeviceService

参数说明:

"productKey": String,
    "deviceName": String,
    "identifier": 服务标识名,
    "args": {
        "xx": xx,
        "xx": xx
    } /*args为服务调用的参数,为一个json对象*/
示例
const IIoTClient = require('./iiot-sdk/iiot-sdk.js'); 

module.exports.handler = function(event, context, callback) { 
  const client = new IIoTClient({ 
    appKey: process.env['appKey'], 
    appSecret: process.env['appSecret'] 
  }); 

const invokeParams = {
    "productKey": "a147vduL8D6",
    "deviceName": "ptOEEyufa0322A",
    "identifier": "yibu",
    "args": {
        "a": 100,
        "b": 200
    }
};
client.invokeThingDeviceService(invokeParams).then(value => {
    console.log('ok, data : ' + JSON.stringify(value));
    callback(null,JSON.stringify(value));
}, error => {
    console.error('failed, data :' + JSON.stringify(error));
    callback(error);
});
}
OEE查询 queryOeeDayShift

参数说明:

{
"equipmentCode": 必须,字符串,查询日期。如2019-01-01
"queryDate":  不必须,字符串,设备ID
"shiftName": 不必须,字符串,班次名。未填则不指定班次。
}
示例
const IIoTClient = require('./iiot-sdk/iiot-sdk.js'); 

module.exports.handler = function(event, context, callback) { 
  const client = new IIoTClient({ 
    appKey: process.env['appKey'], 
    appSecret: process.env['appSecret'] 
  }); 

const oeeParams = {
    "equipmentCode": "53"
};
client.queryOeeDayShift(oeeParams).then(value => {
    console.log('ok, data : ' + JSON.stringify(value));
    callback(null,JSON.stringify(value));
}, error => {
    console.error('failed, data :' + JSON.stringify(error));
    callback(error);
});
}
返回示例









  {"code":200,"data":{"productDefectsSum":0,"productTotalSum":0,"peRatio":0,"eaRatio":1.0002,"qrRatio":0,"shiftDate":"2019-03-28","operatingTime":1192.75,"idealCycleTime":0,"oeeRatio":0,"oeeShiftDuration":0},"id":"a3337fc7-61ba-40d1-92fd-8ddd4826fd71"}脚本执行在完成编码后,用户需要先对脚本进行保存,保存按钮位于编辑器的右上部分。在完成保存后,通过编辑器的左上侧的执行按钮来完成一次脚本的执行。同时,可以在编辑器的调试输出窗口中看到脚本的执行返回情况。通过反复执行和观察输出,完成脚本的调试。组态触发通过在组态中绑定脚本与输入框,将数据的内容作为输入参数调用脚本。传入的参数对应脚本入口函数handler的event参数,格式为JSON字符串。在脚本中可以通过event做JSON转换后获取配置的参数值。例如图中示例,“确定”按钮关联了输入框与脚本“006”,并制定输入框内容对应参数名为“arg1”。当输入框填写“test”并点击“确认”按钮后,会向后台脚本发起调用请求,并携带参数'{"arg1":"test"}'。后台脚本通过var eventJson = JSON.parse(event) 获取event JSON对象,然后通过eventJson.arg1在脚本内获取输入框填写内容。event是有脚本调用方封装数据格式传入脚本中,一般是JSON格式,脚本内通过解析event的格式来获取脚本调用的入参数据。在组态触发中event封装的为输入框组合的数据。规则触发规则触发关联脚本执行时,会在后台封装event数据格式,携带设备标识参数。触发器服务会对设备上报属性、上报事件发送不同的even数据格式。<设备属性触发>


  {
    "source":"DEVICE_STATUS",  //消息来源
    "timestamp":1523844349000, //消息时间戳(毫秒级)
    "context":{  //消息的上下文数据,比如设备id,设备分组,场景id等
      "deviceName":"test001",
      "productKey":"a1OvAcS1uxy",
    "sceneId":"1q2w3e"
    },
    "bodyData":{ //消息的主要数据,比如设备上报的属性数据
      "LightSwitch":{
            "time":1524216467962,
            "value":0
        }
    }
}<设备事件触发>


  {
    "source":"DEVICE_EVENT",  //消息来源
    "timestamp":1523844349000, //消息时间戳(毫秒级)
    "context":{  //消息的上下文数据,比如设备id,设备分组,场景id等
      "deviceName":"test001",
      "productKey":"a1OvAcS1uxy",
    "eventCode":"Shortage",
    "sceneId":"1q2w3e"
    },
    "bodyData":{ //消息的主要数据,比如设备上报的属性数据
      "x":0,
        "y":1,
        "inventory":10    
  }
}

脚本执行

在完成编码后,用户需要先对脚本进行保存,保存按钮位于编辑器的右上部分。在完成保存后,通过编辑器的左上侧的执行按钮来完成一次脚本的执行。同时,可以在编辑器的调试输出窗口中看到脚本的执行返回情况。通过反复执行和观察输出,完成脚本的调试。

组态触发



通过在组态中绑定脚本与输入框,将数据的内容作为输入参数调用脚本。传入的参数对应脚本入口函数handler的event参数,格式为JSON字符串。在脚本中可以通过event做JSON转换后获取配置的参数值。例如图中示例,“确定”按钮关联了输入框与脚本“006”,并制定输入框内容对应参数名为“arg1”。当输入框填写“test”并点击“确认”按钮后,会向后台脚本发起调用请求,并携带参数'{"arg1":"test"}'。后台脚本通过var eventJson = JSON.parse(event) 获取event JSON对象,然后通过eventJson.arg1在脚本内获取输入框填写内容。event是有脚本调用方封装数据格式传入脚本中,一般是JSON格式,脚本内通过解析event的格式来获取脚本调用的入参数据。在组态触发中event封装的为输入框组合的数据。

规则触发

规则触发关联脚本执行时,会在后台封装event数据格式,携带设备标识参数。触发器服务会对设备上报属性、上报事件发送不同的even数据格式。

<设备属性触发>
{
    "source":"DEVICE_STATUS",  //消息来源
    "timestamp":1523844349000, //消息时间戳(毫秒级)
    "context":{  //消息的上下文数据,比如设备id,设备分组,场景id等
      "deviceName":"test001",
      "productKey":"a1OvAcS1uxy",
    "sceneId":"1q2w3e"
    },
    "bodyData":{ //消息的主要数据,比如设备上报的属性数据
      "LightSwitch":{
            "time":1524216467962,
            "value":0
        }
    }
}
<设备事件触发>
{
    "source":"DEVICE_EVENT",  //消息来源
    "timestamp":1523844349000, //消息时间戳(毫秒级)
    "context":{  //消息的上下文数据,比如设备id,设备分组,场景id等
      "deviceName":"test001",
      "productKey":"a1OvAcS1uxy",
    "eventCode":"Shortage",
    "sceneId":"1q2w3e"
    },
    "bodyData":{ //消息的主要数据,比如设备上报的属性数据
      "x":0,
        "y":1,
        "inventory":10    
  }
}