# FunctionGraph开发说明
#### 概述
物联网平台支持使用FunctionGraph编解码的功能，根据您提交的脚本文件，实现设备二进制格式与JSON格式相互转换。常在设备能力比较弱，只能上报简单的二进制数据的设备场景下使用。FunctionGraph的函数托管计算服务支持Node.js、Python、Java、Go、C#、PHP、Cangjie和定制运行时语言，可以满足多种开发需求；具有实时查看运行日志、查看图形化监控等功能，大大的提高了开发者开发、调试效率。
![](https://support.huaweicloud.com/devg-iothub/public_sys-resources/note_3.0-zh-cn.png)
- FunctionGraph是一项基于事件驱动的函数托管计算服务。使用FunctionGraph函数，只需编写业务函数代码并设置运行的条件，无需配置和管理服务器等基础设施，函数以弹性、免运维、高可靠的方式运行。
- FunctionGraph的收费标准可见：[FunctionGraph函数工作流计费概述](https://support.huaweicloud.com/price-functiongraph/functiongraph_00_0001.html)。此外，FunctionGraph按函数实际执行资源计费，不执行不产生费用。
 
![](https://support.huaweicloud.com/devg-iothub/public_sys-resources/notice_3.0-zh-cn.png)
下面将讲述数据转换格式及其原理，您可以根据您接入协议选择对应示例代码直接进行IoTDA接入实践（推荐）：
- [MQTT（S）-编解码插件样例](https://support.huaweicloud.com/devg-iothub/iot_02_0012.html)
- [NB-IoT（CoAP）- 编解码插件样例](https://support.huaweicloud.com/devg-iothub/iot_02_0013.html)
 
#### 使用流程
图1FunctionGraph使用流程
![](https://support.huaweicloud.com/devg-iothub/figure/zh-cn_image_0000002244397593.png "点击放大")
1. 创建产品：在IoTDA创建一个CoAP协议或MQTT协议的产品及设备。具体说明可见：[创建产品](https://support.huaweicloud.com/devg-iothub/iot_01_0053.html)。
   1. 访问[设备接入服务](https://www.huaweicloud.com/product/iothub.html)，单击"管理控制台"进入设备接入控制台。选择您的实例，单击实例卡片进入。
   
   2. 单击左侧导航栏"产品"，单击页面左侧的"创建产品"。根据页面提示填写参数，然后单击"确定"，完成产品的创建。
    
2. 编写FunctionGraph插件：
   1. 创建函数方法可见：[FunctionGraph创建函数](https://support.huaweicloud.com/usermanual-functiongraph/functiongraph_01_1441.html)。需要注意的是，创建的事件函数要与在IoTDA中创建的产品局点一致，否则无法被产品引用，局点可在控制台左上方知晓。
      图2FunctionGraph开发-局点查看   
      ![](https://support.huaweicloud.com/devg-iothub/figure/zh-cn_image_0000002221875994.png "点击放大") 
   
   2. 编写编解码插件：FunctionGraph支持多种运行时语言，包括Python 、Node.js、Java、Go、C#、PHP、Cangjie及定制运行时等，不同语言所支持的版本有所差异。具体使用说明可见：[FunctionGraph编程语言说明及开发指导](https://support.huaweicloud.com/usermanual-functiongraph/functiongraph_01_0151.html)。
      ![](https://support.huaweicloud.com/devg-iothub/public_sys-resources/note_3.0-zh-cn.png)
      FunctionGraph函数创建-快速入门可见：[使用空白模板创建并执行函数](https://support.huaweicloud.com/qs-functiongraph/functiongraph_04_0101.html)。
      
    
3. 部署FunctionGraph插件：
   1. 回到[设备接入服务](https://www.huaweicloud.com/product/iothub.html)控制台，打开产品页面，单击页面中的"插件开发 \> FunctionGraph开发"。若是第一次使用，需要进行访问授权。
      图3FunctionGraph开发-插件授权   
      ![](https://support.huaweicloud.com/devg-iothub/figure/zh-cn_image_0000002221786110.png "点击放大") 
   
   2. 授权成功后，选择您在[2]创建的目标函数并单击"部署"。
      图4FunctionGraph开发-部署插件   
      ![](https://support.huaweicloud.com/devg-iothub/figure/zh-cn_image_0000002256705825.png "点击放大") 
    
#### IoTDA+FunctionGraph通信说明（API）
图5IoTDA+FunctionGraph使用说明
![](https://support.huaweicloud.com/devg-iothub/figure/zh-cn_image_0000002244168397.png "点击放大")
1. 当上报数据为二进制数据时，IoTDA会自动将数据data进行Base64编码，在IoTDA内部以Base64编码后的数据格式存储。例如：设备上报数据\[0x01, 0x02\]，在IoTDA中存储的数据为"AQI="。
   ![](https://support.huaweicloud.com/devg-iothub/public_sys-resources/note_3.0-zh-cn.png)
   在创建产品时，若为CoAP协议，默认为二进制数据格式，发送到编解码插件会是Base64编码后的数据。若为MQTT（S）协议，将根据您选择的数据格式及编码格式进行数据转换，具体可见：[创建产品说明](https://support.huaweicloud.com/usermanual-iothub/iot_01_0054.html)。
   
2. IoTDA接收到数据后，若存在编解码插件，将会把数据以特定格式传输到FunctionGraph。参数及数据格式（固定格式A）为：
   表1上行数据格式 
   | 字段名       | 必选/可选 | 类型      | 参数描述                                                                                                                                                                                                                                                                                                                                                                                                                                              |
   |:---|:---|:---|:---|
   | codecType | 必选  | String | **参数解释：** 编解码类型。decode为上行解码（二进制流转换为JSON格式）；encode为下行编码（JSON格式转换为二进制流）                                                                                                                                                                                                                                                                                                                             |
   | message  | 必选    | String | **参数解释：** 是JSON格式转换成的字符串数据，其中包含topic和payload两个参数。 - topic：当为MQTT协议时，会携带上报的Topic；当为CoAP协议时，值为null。  - payload：设备上报数据的Base64编码后数据（若为MQTT协议，可在产品选择编码格式）。   |
      
   IoTDA发送给FunctionGraph解码请求示例（CoAP）：
   ```
   {
       "codecType": "decode",
       "message": "{\"topic\": null,\"payload\": \"AABQAFo=\"}"
   }
   ```
   IoTDA发送给FunctionGraph解码请求示例（MQTT）：
   ```
   {
       "codecType": "decode",
       "message": "{\"topic\": \"$oc/devices/661f99d6da14e268414f0af6_longsj123/sys/properties/report\",\"payload\": \"AABQAFo=\"}"
   }
   ```
   
3. 经过FunctionGraph解码后，返回解码结果。其发送给平台（IoTDA）的数据格式及参数（固定格式B）为：
   表2下行数据格式 
   | 字段名     | 必选/可选 | 类型       | 参数描述                                                                                          |
   |:---|:---|:---|:---|
   | status | 必选 | String  | **参数解释：** 标识解码的执行结果，200表示成功，其他表示设备执行结果为失败。    |
   | message | 必选    | String | **参数解释：** 用于解码数据（二进制流解码为JSON格式），为JSON格式转换成的字符串。 |
      
   FunctionGraph发送给IoTDA的解码结果示例：
   ```
   {
        "status": 200,
        "message": "{\"msg_type\":\"properties_report\",\"services\":[{\"service_id\":\"smokedetector\",\"properties\":{\"level\":258,\"temperature\":3.4}}]}"
    }
   ```
   
4. 当平台或应用侧进行数据下发时，IoTDA会下发JSON格式的数据，需要经过编解码功能把JSON格式数据转换为二进制码流再进行数据下发。
5. IoTDA下发数据前，若存在编解码插件，将会把数据以特定格式传输到FunctionGraph。传输到FunctionGraph的数据格式及参数（固定格式A）为：
   表3上行数据格式 
   | 字段名      | 必选/可选 | 类型      | 参数描述                                                                                                                 |
   |:---|:---|:---|:---|
   | codecType | 必选      | String | **参数解释：** 编解码类型。decode为上行解码（二进制流转换为JSON格式）；encode为下行编码（JSON格式转换为二进制流） |
   | message  | 必选      | String   | **参数解释：** 是JSON格式转换成的字符串数据。                                           |
      
   IoTDA发送给FunctionGraph编码请求示例：
   ```
   {
       "codecType": "encode",
       "message": "{\"msg_type\":\"commands\",\"service_id\": \"smokedetector\",\"paras\": {\"value\": 1},\"command_name\": \"SET_ALARM\",\"hasMore\": 0,\"request_id\": 1}"
   }
   ```
   
6. 经过FunctionGraph编码后，返回编码结果。其发送给平台（IoTDA）的数据格式及参数（固定格式C）为：
   表4下行数据格式 
   | 字段名         | 必选/可选 | 类型    | 参数描述                                                                                                                                                                                                                                                                                   |
   |:---|:---|:---|:---|
   | status     | 必选       | String   | **参数解释：** 标识编码的执行结果，200表示成功，其他表示失败。                                                                                                                                                                                                      |
   | message | 必选    | String | **参数解释：** 是JSON格式转换成的字符串数据，其中包含payload参数。 - payload：FunctionGraph编码后的byte\[\]数据。   |
      
   FunctionGraph发送给IoTDA的编码结果示例：
   ```
   {
        "status": 200,
        "message": "{\"payload\":[2,1,0,0,1]}"
    }
   ```
   
7. 经过编解码插件后，平台将返回给设备二进制流数据。比如说：\[2,1,0,0,1\]。
#### IoTDA物模型数据格式
表5物模型数据格式说明 
| 编解码                                                                    | 数据类型           | msg_type               | 支持协议          | 说明                                                                     |
|:---|:---|:---|:---|:---|
| 解码 （二进制码流转换成JSON格式数据）  | 设备属性上报        | properties_report      | ALL          | [设备属性上报]                |
| 解码 （二进制码流转换成JSON格式数据）  | 设备返回命令响应      | command_response       | ALL           | [平台命令下发的响应消息]            |
| 解码 （二进制码流转换成JSON格式数据）  | 设备返回平台设置设备属性响应 | properties_set_response | MQTT/MQTTS   | [平台设置设备属性的响应消息]        |
| 解码 （二进制码流转换成JSON格式数据）  | 设备返回平台查询设备属性响应 | properties_get_response | MQTT/MQTTS     | [平台查询设备属性的响应消息]        |
| 解码 （二进制码流转换成JSON格式数据）  | 设备消息上报         | message_up              | MQTT/MQTTS     | [设备消息上报]             |
| 编码 （JSON格式转换成二进制码流） | 平台命令下发         | commands              | ALL            | [平台命令下发]            |
| 编码 （JSON格式转换成二进制码流） | 平台响应设备属性上报   | properties_report_reply | NB-IoT（CoAP） | [平台响应设备属性上报（NB-IoT设备）] |
| 编码 （JSON格式转换成二进制码流） | 平台设置设备属性       | properties_set       | MQTT/MQTTS    | [平台设置设备属性]               |
| 编码 （JSON格式转换成二进制码流） | 平台查询设备属性      | properties_get          | MQTT/MQTTS  | [平台查询设备属性]           |
| 编码 （JSON格式转换成二进制码流） | 平台消息下发       | messages               | MQTT/MQTTS  | [平台消息下发]                |
   
**数据解码格式定义**
数据解析场景，平台收到设备侧的数据时，平台会将设备侧payload中的二进制码流发送到FunctionGraph；FunctionGraph中需要实现二进制码流解码，解码成平台能识别的产品模型中定义的JSON格式，平台对解析后的JSON要求：
```
{
     "status": 200,
     "message": "${解码后的JSON数据格式}"
 }
```
其中${解码后的JSON数据格式}，为平台对FunctionGraph解析后要求的JSON格式，其要求的数据格式为：
- 设备属性上报
  ```
  {
      "msg_type": "properties_report",
      "services": [{
          "service_id": "Battery",
          "properties": {
              "batteryLevel": 57
          },
          "event_time": "20151212T121212Z"
      }]
  }
  ```
  表6设备属性上报数据格式 
  | 字段名        | 必选/可选 | 类型                    | 参数描述                                  |
  |:---|:---|:---|:---|
  | msg_type    | 必选     | String                | 属性上报的消息类型，固定为：properties_report。      |
  | services | 必选   | List\<ServiceProperty\> | 设备服务数据列表（具体结构参考下表ServiceProperty定义表）。 |
     
  表7ServiceProperty结构定义 
  | 字段名       | 必选/可选 | 类型     | 参数描述                                                                                                                                       |
  |:---|:---|:---|:---|
  | service_id   | 必选    | String | 设备的服务ID。                                                                                                                                  |
  | properties | 必选   | Object  | 设备服务的属性列表，具体字段在设备关联的产品模型中定义。                                                                                                             |
  | event_time | 可选 | String | 设备采集数据UTC时间（格式：yyyyMMddTHHmmssZ），如：20161219T114920Z。 设备上报数据不带该参数或参数格式错误时，则数据上报时间以平台时间为准。 |
     
  

- 平台设置设备属性的响应消息
  ```
  {
     "msg_type": "properties_set_response",
     "request_id": "42aa08ea-84c1-4025-a7b2-c1f6efe547c2",
     "result_code": 0,
     "result_desc": "success"
  }
  ```
  表8设备属性的响应消息数据格式 
  | 字段名          | 必选/可选 | 类型       | 参数描述                                                                                 |
  |:---|:---|:---|:---|
  | msg_type   | 必选     | String  | 属性上报的消息类型，固定为： properties_set_response |
  | request_id  | 可选    | String | 用于唯一标识这次请求，设备侧收到的消息带该参数时，响应消息需要将该参数值返回给平台。如果解码后的消息不带该字段，则以topic中带的request_id为准。     |
  | result_code | 可选    | Integer   | 命令的执行结果，0表示成功，其他表示失败。不带默认认为成功。                                                      |
  | result_desc  | 可选    | String    | 属性设置的响应描述。                                                                           |
     
  
- 平台查询设备属性的响应消息
  ```
  {
  "msg_type": "properties_get_response",
  "request_id": "42aa08ea-84c1-4025-a7b2-c1f6efe547c2",
      "services": [
          {
              "service_id": "analog",
              "properties": {
                  "PhV_phsA": "1",
                  "PhV_phsB": "2"
              },
              "event_time": "20190606T121212Z"
          }
      ]
  }
  ```
  表9平台查询设备属性的响应数据格式 
  | 字段名      | 必选/可选 | 类型                    | 参数描述                                                                            |
  |:---|:---|:---|:---|
  | msg_type | 必选    | String                 | 固定为：properties_get_response                                                    |
  | request_id | 可选     | String                | 用于唯一标识这次请求，设备侧收到的消息带该参数时，响应消息需要将该参数值返回给平台。如果解码后的消息不带该字段，则以topic中带的request_id为准。 |
  | services   | 必选     | List\<ServiceProperty\> | 设备服务数据列表（具体结构参考下表ServiceProperty定义表）。                                              |
     
  表10ServiceProperty结构定义 
  | 字段名         | 必选/可选 | 类型       | 参数描述                                                                                                                                   |
  |:---|:---|:---|:---|
  | service_id | 必选    | String   | 设备的服务ID。                                                                                                                                |
  | properties  | 必选      | Object | 设备服务的属性列表，具体字段在设备关联的产品模型中定义。                                                                                                             |
  | event_time   | 可选       | String  | 设备采集数据UTC时间（格式：yyyyMMddTHHmmssZ），如：20161219T114920Z。 设备上报数据不带该参数或参数格式错误时，则数据上报时间以平台时间为准。 |
     
  
- 平台命令下发的响应消息
  ```
  {
    "msg_type": "command_response",
    "request_id": "42aa08ea-84c1-4025-a7b2-c1f6efe547c2",
     "result_code": 0,
    "command_name": "ON_OFF",
    "service_id": "WaterMeter",
    "paras": {
      "value": "1"
    }  
  }
  ```
  表11平台命令下发数据格式 
  | 字段名         | 必选/可选 | 类型      | 参数描述                                                                           |
  |:---|:---|:---|:---|
  | msg_type    | 必选    | String      | 固定为：command_response                                                            |
  | request_id  | 可选      | String   | 用于唯一标识这次请求，设备侧收到的消息带该参数时，响应消息需要将该参数值返回给平台。如果解码后的消息不带该字段，则以topic中带的request_id为准。 |
  | result_code | 可选   | Integer | 标识命令的执行结果，0表示成功，其他表示失败。不带默认认为成功。                                                |
  | response_name | 可选    | String    | 命令的响应名称，在设备关联的产品模型中定义。                                                         |
  | paras         | 可选    | Object    | 命令的响应参数，具体字段在设备关联的产品模型中定义。                                                      |
     
  
- 设备消息上报
  ```
  {
    "msg_type": "message_up",
    "content": "hello"
  }
  ```
  表12设备消息上报数据格式 
  | 字段名      | 必选/可选 | 类型      | 参数描述             |
  |:---|:---|:---|:---|
  | msg_type | 必选   | String | 固定为：message_up |
  | content  | 可选    | String   | 消息内容。          |
     
  
**数据编码格式定义**
数据解析场景，平台进行数据下发时，会将产品模型定义的JSON格式数据（如果不是该格式的数据则可能会导致编解码失败），发送给FunctionGraph；FunctionGraph需要将JSON格式的数据，编码为设备可以识别的二进制码流；编码时平台传递到FunctionGraph的JSON格式如下：
```
{
    "codecType": "encode",
    "message": "${平台发送给FunctionGraph的JSON数据格式}"
}
```
其中${平台发送给FunctionGraph的JSON数据格式}，为平台发送给FunctionGraph的编码前的JSON数据，其发送的格式为：
- 平台命令下发
  ```
  { 
    "msg_type": "commands", 
     "request_id": "42aa08ea-84c1-4025-a7b2-c1f6efe547c2",
    "command_name": "ON_OFF", 
    "service_id": "WaterMeter", 
    "paras": { 
      "value": 1
    } 
  }
  ```
  表13设备命令下发数据格式 
  | 字段名         | 必选/可选 | 类型      | 参数描述                         |
  |:---|:---|:---|:---|
  | msg_type    | 必选     | String  | 固定为：commands                |
  | request_id  | 必选  | String   | 用于唯一标识这次请求，该标识会通过topic下发给设备。   |
  | service_id    | 可选  | String   | 设备的服务ID。                     |
  | command_name | 可选   | String | 设备命令名称，在设备关联的产品模型中定义。       |
  | paras          | 可选    | Object  | 设备命令的执行参数，具体字段在设备关联的产品模型中定义。 |
     
  
- 平台设置设备属性
  ```
  { 
  "msg_type": "properties_set",
  "request_id": "42aa08ea-84c1-4025-a7b2-c1f6efe547c2",
      "services": [{ 
              "service_id": "Temperature", 
              "properties": { 
                  "value": 57 
              } 
          }, 
          { 
              "service_id": "Battery", 
              "properties": { 
                  "level": 80 
              } 
          } 
      ] 
  }
  ```
  表14平台设置设备属性数据格式 
  | 字段名       | 必选/可选 | 类型                    | 参数描述                                        |
  |:---|:---|:---|:---|
  | msg_type    | 必选     | String                | 固定为：properties_set                          |
  | request_id | 必选     | String                 | 用于唯一标识这次请求，设备侧收到的消息带该参数时，响应消息需要将该参数值返回给平台。 |
  | services  | 必选  | List\<ServiceProperty\> | 设备服务数据列表。                                  |
     
  ServiceProperty结构定义：
  表15ServiceProperty结构定义 
  | 字段名        | 必选/可选 | 类型   | 参数描述                    |
  |:---|:---|:---|:---|
  | service_id | 必选    | String | 设备的服务ID。               |
  | properties | 必选    | Object | 设备服务的属性列表，具体字段在产品模型里定义。 |
     
  
- 平台查询设备属性
  ```
  { 
     "msg_type": "properties_get",
     "request_id": "42aa08ea-84c1-4025-a7b2-c1f6efe547c2",
     "service_id": "Temperature" 
  }
  ```
  表16平台查询设备属性数据格式 
  | 字段名      | 必选/可选 | 类型     | 参数描述                       |
  |:---|:---|:---|:---|
  | msg_type    | 必选    | String  | 固定为：properties_get         |
  | request_id | 必选    | String  | 用于唯一标识这次请求，该标识会通过topic下发给设备。 |
  | service_id | 可选   | String | 设备的服务ID。                   |
     
  
- 平台响应设备属性上报（NB-IoT设备）
  ```
  { 
    "msg_type": "properties_report_reply",
    "request": "213355656",
    "result_code": 0
  }
  ```
  表17平台响应设备属性上报数据格式 
  | 字段名            | 必选/可选 | 类型         | 参数描述                         |
  |:---|:---|:---|:---|
  | msg_type     | 必选      | String     | 固定为：properties_report_reply |
  | request      | 可选     | String  | 属性上报的BASE64编码字符串。           |
  | result_code | 可选     | Integer | 属性上报的执行结果。                  |
  | has_more    | 可选     | Boolean | 是否存在缓存命令。                    |
     
  
- 平台消息下发
  ```
  { 
    "msg_type": "messages",
    "content": "hello"
  }
  ```
  表18设备消息下发数据格式 
  | 字段名     | 必选/可选 | 类型      | 参数描述        |
  |:---|:---|:---|:---|
  | msg_type | 必选  | String | 固定为：messages |
  | content | 可选  | String  | 消息下发的内容。   |
     
  
 
