# 背景

此项目实现以下功能：

1. 根据creem文件生成Workflow Canvas Python FB(Function Block)框架代码。
2. 根据creem文件和Python FB代码生成FB文件(.json格式文件)。将生成的FB文件加载到Workflow Canvas中，即可在Workflow Canvas中使用该功能块。
3. 提供一些FB的代码模板以供开发人员参考。
4. 生成RB(Resource Block)文件框架。
5. 与RA服务交互，实现RB的上传，查询，删除。
6. 提供一些RB的代码模板以供开发人员参考。

# 使用

1. Windows

   支持x86_64的Win10系统。

   在项目根目录下通过PowerShell执行：

   ```shell
   $ ./devkit/win/devkit.exe
   ```

2. Linux

   支持x86_64的Ubuntu20.04系统。

   在项目根目录下通过终端执行：

   ```shell
   $ ./devkit/linux/devkit
   ```

可以输入help来获取各个命令的具体使用说明。

根据命令行交互可以实现以下FB和RB功能：

### FB功能

1. 根据creem文件生成python模板代码。代码保存在creem文件同目录下的runtime文件夹下。
2. 根据creem文件和代码生成对应的.json文件（用于直接加载到成Workflow Canvas运行），和.bxt文件（用于加入成Workflow Canvas标准库）。

用户除了根据creem文件生成python模板代码外，还可以参考提供的样例代码，自行实现FB的代码。然后再使用此项目生成对用的.bxt文件和.json文件。

一般的使用流程为：

1. 创建文件夹function_blocks。

2. 将creem文件，例如System.Idle.xml拷贝至function_blocks/System.Idle目录下。

3. 在根目录下运行devkit

4. 在命令行交互中执行

   ```shell
   $ fb_generate function_blocks/System.Idle/System.Idle.xml
   ```

   FB的命名推荐使用"."连接的方式。

   命令执行成功后，会在function_blocks/System.Idle目录下生成runtime文件夹。此文件夹为根据creem文件生成的FB模板代码。

5. 编辑FB模板代码，实现FB的功能。

6. 在命令行交互中执行

   ```shell
   $ fb_build function_blocks/System.Idle
   ```

   命令执行成功后，会在creem文件夹中生成对应的System.Idle.xml，System.Idle.bxt，functionBlock.json文件。

7. 将functionBlock.json文件载入Workflow Canvas中即可使用此功能块。

除了使用fb_genenrate命令生成模板代码外，用户也可以完全自己实现功能块代码。

templates/FBs目录下提供了一些样例代码供参考。

但是用户必须将代码放在对应目录的runtime文件夹下。

### RB功能

1. 生成RB(Resource Block)文件框架。
2. 上传RB文件至RA。
3. 查询当前RA中已加载的所有RB。
4. 查询RB的具体信息
5. 删除RB。

RB文件用于实现与资源（例如设备，协议服务器等）保持长连接下的命令和数据交互。RB作为一个插件，需要被加载到RA服务中使用。

一般的使用流程为：

1. 创建文件夹resource_blocks用于保存生成的RB文件

2. 在根目录下执行devkit

3. 在命令行交互中执行

   ```shell
   $ rb_generate resource_blocks/Resource_Template
   ```

   需要注意的是，**RB文件的命名推荐使用”_“连接，而不能使用"."连接。**

   命令执行成功后，会在resource_blocks下生成Resource_Template目录。此文件夹为该RB的框架文件。其中包括以下文件。

   ![image-20230105110104344](doc/rb_template.png)

   info.json文件描述了此RB文件的信息。生成的内容如下：

   ```json
   {
     "author": "Author",
     "version": "0.0.1",
     "name": "Resource_Template",
     "description": "Here is description about this resource block",
     "type": [
       "Here is device type list this resource block work with"
     ]
   }
   ```

   RB开发人员需要根据实际情况修改此文件。需要注意的是**其中的”type“部分一定要修改为与真实的资源类型一致。**

   resource_template.py文件包含一个为此名为”ResourceTemplate“的类，此类为该RB的调用入口。

   其中最主要的是run_command(self, request)函数。当RA收到一个该资源的请求时，会调用此函数。因此RB开发人员需要在此函数中实现对应资源交互的功能。

   其中request为具体的请求内容。一个常见的request内容如下：

   ```json
   {
       "device_uuid": "",
       "device_info": {
           "id": "Robotic.Cobot.UniversalRobots.UR5.1",
           "type": "Robotic.Cobot.UniversalRobots.UR5",
           "parameters": {
               "ipAddress": "192.168.205.129",
               "portNumber": "1000"
           }
       },
       "cmd_id": 1005,
       "cmd_param": {
           "reference": {
               "name": "FlangeCenter"
               "x": 0.0,
               "y": 0.0,
               "z": 0.0,
               "rx": 0.0,
               "ry": 0.0,
               "rz": 0.0
           },
           "tool": {
               "name": "gripper1"
               "x": 0.0,
               "y": 0.0,
               "z": 100.0,
               "rx": 0.0,
               "ry": 0.0,
               "rz": 0.0
           }
       },
       "req_id": "1"
   }
   ```

   它包含以下几部分

   - **device_info**
     - 包含设备的 id 标识符， type 类型 和 parameters 连接参数。
     - id 标识符 - 在id通常与Workflow Canvas中的资源ID一致。
     - type 类型 - 同一种设备类型，type 是相同的，且此type与RB的info.json中的type一致。RA 根据这个 type 信息来搜索，调用对应的 RB。
     - parameters 链接参数 - 连接设备所需要的参数，比如 IP 地址和端口，设备访问必要的认证信息，或者是串口路径等。
   - **device_uuid**
     - 设备的唯一 uuid，这个是 RA 根据 device_info  计算出来的。
   - **cmd_id**
     - 命令标识符，RB中根据cmd_id来判断与资源交互的具体命令。
   - **cmd_param**
     - 执行 cmd_id命令所需要的参数，可以为空。如果有命令参数，需要将 参数名 和 参数值 以 key + value 的形式放入 **cmd_param** 中
   - **req_id**
     - 请求的id，为了区分同一设备同一命令下的不同请求，RA在返回时会带上这个参数。

   在执行完对应请求的命令后，需要返回响应。

   一个常见的 response 回复如下:

   ```json
   {
       "device_uuid": "015a1a64-db4a-32b9-bbd3-f0d7152a47da",
       "cmd_id": 1005,
       "cmd_param": {
           "reference": {
               "name": "FlangeCenter"
               "x": 0.0,
               "y": 0.0,
               "z": 0.0,
               "rx": 0.0,
               "ry": 0.0,
               "rz": 0.0
           },
           "tool": {
               "name": "gripper1"
               "x": 0.0,
               "y": 0.0,
               "z": 100.0,
               "rx": 0.0,
               "ry": 0.0,
               "rz": 0.0
           }
       },
       "req_id": "1",
       "error_code": {
           "value": 0,
           "description": "Command id run success"
       },
       "data": {
           "x": -769.7946670275132,
           "y": -89.28702274031627,
           "z": -62.97789612500429,
           "rx": 1.306226266844728,
           "ry": -0.9691494377389571,
           "rz": 0.7857241537700308
       }
   }
   ```

   它包含以下几部分：

   - **device_uuid**
     - 同 request
   - **device_info**
     - 同 request
   - **cmd_id**
     - 同 request
   - **cmd_param**
     - 同 request
   - **req_id**
     - 同 request
   - **error_code**
     - value - 错误代码的数值，成功时返回 0
     - description - 错误代码的具体文字解释，
   - **data**
     - 返回运行结果的具体值

4. 在命令行交互中执行

   ```shell
   $ rb_upload resource_blocks/Resource_Template http://127.0.0.1:61720
   ```

   将Resource_Template上传至RA。

5. 在命令行交互中执行

   ```json
   $ rb_list
   ```

   来显示RA中已加载的所有RB。

6. 在命令行交互中执行

   ```json
   rb_show [RB name] 
   ```

   来显示该RB的具体信息。

7. 在命令行交互中执行

   ```json
   rb_delete [RB name]
   ```

   来删除指定RB。
   
   
