前言

看完本文后你将了解如下内容:
小部件编辑器中的Settings schema的来源,用法。
编辑器的JavaScript中如何获取Settings schema设置的内容。
源码方式添加的组件,如何获取Settings schema设置的内容。
源码方式添加的组件,如何显示在部件库中,或者说如何才能使用。这个在另一篇文章介绍。

介绍

小部件编辑器是一个用于开发自定义小部件的迷你IDE。它由顶部工具栏和四个主要部分组成:

image.png
这篇文章来介绍Settings schema(设置模式)的作用和用法。
还记得自己第一次打开小部件编辑器的时候,左边俩栏还大概知道是什么,对于右上方这个框框,一脸问号?这是什么东西!现在看来很简单。看完文章,相信你也轻松拿下!


官网哪里有介绍?

https://thingsboard.io/docs/user-guide/contribution/widgets-development/#settings-schema-section
里面基本讲解还是如何利用TB的小部件编辑器来开发小部件。这篇文章会涉及前端源码和settings schema之间的操作。
官网介绍中值得一提的是:他介绍了settings schema的来源react-schema-form构建测试的页面

react-schema-form?

Github开源官方介绍
React表单是基于json模式的,用于生成和验证表单。这是angular模式表单项目,它使用material-ui来实现底层组件。
简单来说:这是一个前端工具,你传给它俩个JSON,它给你生成表单!
正好TB的前端也是angular项目,ui采用的也是material-ui。

Settings schema?

中文翻译为设置模式
Settings schema的JSON结构如下,分为俩部分:

  1. schema决定表单类型,输入框?单选框?下拉列表?日期?等等..
  2. form决定对应表单顺序,样式等
  1. {
  2. "schema":{
  3. "type":"object",
  4. "title":"EntitiesTableSettings",
  5. "properties":Object{...},
  6. "required":[
  7. ]
  8. },
  9. "form":Array[15]
  10. }

Settings schema构建的表单就对应小部件编辑状态下的编辑详情页的第三个tab「高级」里面的所有表单内容。
image.png
打开react-schema-form builder先体验一把。这里表单种类很多.
打开TB的 部件包 > Entity admin widgets > Device admin table
将这个组件的设置模式中的schema对应的JOSN对象拷贝到react-schema-form builder的Schema框中,再将这个组件的设置模式中的form对应的JOSN数组拷贝到react-schema-form builder的form框中。


看看右边的表单是不是和Device admin table组件的设置>高级 中的表单内容一致呢。
可以尝试改变一下form 数组中的元素顺序,再看看表单中的元素位置会不会做相应调换呢?


image.png
所以,无论是代码级别的新建组件,还是用小部件编辑器来新建组件,都离不开使用react-schema-form构建表单!因为无论什么组件,肯得是要做一些设置的。组件编辑页的前俩个和最后一个Tab「数据」「设置」「动作」是所有组件都一样的通用设置,第三个Tab「高级」就是每个组件都不同的个性化设置!

练习

假设我们要结合TB自带的实体列表组件,实现一个设备的批量RPC组件,如下图。
image.png

实现思路

  1. 实体列表的表格添加复选框,用来多选要控制的设备。

复选框,input和按钮我是通过改源码实现,本文不讲解,只介绍settings schema相关内容。

  1. 高级设置中,新增表单,供填写要控制的多个方法名method。

image.png

  1. 表格初始化时,获取方法名method,生成对应个数的input框,供输入params参数。
  2. 表格最后添加一个按钮,点击按钮后,获取对应method和params,
  3. 调用angular项目中的服务DeviceService中的sendOneWayRpcCommand或者sendTwoWayRpcCommand方法来循环发送多个设备的多个RPC命令。

表单构建

打开react-schema-form builder对应输入下面内容:
Form

  1. [
  2. "enableBatchRpc",
  3. {
  4. "key": "batchRpc",
  5. "add": "添加",
  6. "style": {
  7. "add": "btn-success"
  8. },
  9. "items": [
  10. "batchRpc[]"
  11. ]
  12. }
  13. ]

schema

  1. {
  2. "type": "object",
  3. "title": "Test",
  4. "properties": {
  5. "enableBatchRpc":{
  6. "type":"boolean",
  7. "title":"允许批量控制设备",
  8. "default":false
  9. },
  10. "batchRpc": {
  11. "type": "array",
  12. "title": "添加要批量控制的method",
  13. "maxItems": 5,
  14. "items": {
  15. "type": "string",
  16. "title": "method",
  17. "required": [
  18. "method"
  19. ]
  20. }
  21. }
  22. }
  23. }

实现表单如下:
image.png
现在我们打开TB的 部件包 > Entity admin widgets > Device admin table点击编辑。
将刚刚验证成功的schema和form,都加到Settings schema中对应的schema和form的下面。
因为Settings schema中之前就有内容,所以只需拷贝schema的properties里的内容和form 中括号[]的内容。
拷贝后的内容也列出来吧。

  1. {
  2. "schema": {
  3. "type": "object",
  4. "title": "EntitiesTableSettings",
  5. "properties": {
  6. "entitiesTitle": {
  7. "title": "Entities table title",
  8. "type": "string",
  9. "default": ""
  10. },
  11. "enableSearch": {
  12. "title": "Enable entities search",
  13. "type": "boolean",
  14. "default": true
  15. },
  16. "enableSelectColumnDisplay": {
  17. "title": "Enable select columns to display",
  18. "type": "boolean",
  19. "default": true
  20. },
  21. "enableStickyHeader": {
  22. "title": "Always display header",
  23. "type": "boolean",
  24. "default": true
  25. },
  26. "enableStickyAction": {
  27. "title": "Always display actions column",
  28. "type": "boolean",
  29. "default": true
  30. },
  31. "displayEntityName": {
  32. "title": "Display entity name column",
  33. "type": "boolean",
  34. "default": true
  35. },
  36. "entityNameColumnTitle": {
  37. "title": "Entity name column title",
  38. "type": "string",
  39. "default": ""
  40. },
  41. "displayEntityLabel": {
  42. "title": "Display entity label column",
  43. "type": "boolean",
  44. "default": false
  45. },
  46. "entityLabelColumnTitle": {
  47. "title": "Entity label column title",
  48. "type": "string",
  49. "default": ""
  50. },
  51. "displayEntityType": {
  52. "title": "Display entity type column",
  53. "type": "boolean",
  54. "default": true
  55. },
  56. "displayPagination": {
  57. "title": "Display pagination",
  58. "type": "boolean",
  59. "default": true
  60. },
  61. "defaultPageSize": {
  62. "title": "Default page size",
  63. "type": "number",
  64. "default": 10
  65. },
  66. "defaultSortOrder": {
  67. "title": "Default sort order",
  68. "type": "string",
  69. "default": "entityName"
  70. },
  71. "useRowStyleFunction": {
  72. "title": "Use row style function",
  73. "type": "boolean",
  74. "default": false
  75. },
  76. "rowStyleFunction": {
  77. "title": "Row style function: f(entity, ctx)",
  78. "type": "string",
  79. "default": ""
  80. },
  81. "enableBatchRpc":{
  82. "type":"boolean",
  83. "title":"允许批量控制设备",
  84. "default":false
  85. },
  86. "batchRpc": {
  87. "type": "array",
  88. "title": "添加要批量控制的method",
  89. "maxItems": 5,
  90. "items": {
  91. "type": "string",
  92. "title": "method",
  93. "required": [
  94. "method"
  95. ]
  96. }
  97. }
  98. },
  99. "required": []
  100. },
  101. "form": [
  102. "entitiesTitle",
  103. "enableSearch",
  104. "enableSelectColumnDisplay",
  105. "enableStickyHeader",
  106. "enableStickyAction",
  107. "displayEntityName",
  108. "entityNameColumnTitle",
  109. "displayEntityLabel",
  110. "entityLabelColumnTitle",
  111. "displayEntityType",
  112. "displayPagination",
  113. "defaultPageSize",
  114. "defaultSortOrder",
  115. "useRowStyleFunction",
  116. {
  117. "key": "rowStyleFunction",
  118. "type": "javascript",
  119. "condition": "model.useRowStyleFunction === true"
  120. },
  121. "enableBatchRpc",
  122. {
  123. "key": "batchRpc",
  124. "add": "添加",
  125. "style": {
  126. "add": "btn-success"
  127. },
  128. "items": [
  129. "batchRpc[]"
  130. ]
  131. }
  132. ]
  133. }

然后点击另存为,添加到一个自定义部件包中。
新建一个仪表板,选择刚刚另存为的小部件,切到高级选项卡,查看是否出现了我们新增的表单内容.
image.png
点击按钮添加俩个method
image.png
然后回到小部件编辑器 新增俩行JavaScript代码 参考基本小部件API

  1. console.log(self.ctx.settings.enableBatchRpc);
  2. console.log(JSON.stringify(self.ctx.settings.batchRpc));

image.png
保存后在浏览器打开F12的console控制台的情况下,打开刚刚创建的仪表盘。可以看到成功获取了表单数据。
image.png
如何发送命令呢?同样参考基本小部件API

  1. //分别对应https://thingsboard.io/docs/user-guide/rpc/介绍的无响应和有响应的RPC命令
  2. self.ctx.controlApi.sendOneWayCommand("setThreshold",{"value":1});
  3. self.ctx.controlApi.sendTwoWayCommand("setThreshold",{"value":1});
  4. RpcApiTypeScript定义
  5. export interface RpcApi {
  6. sendOneWayCommand: (method: string, params?: any, timeout?: number) => Observable<any>;
  7. sendTwoWayCommand: (method: string, params?: any, timeout?: number) => Observable<any>;
  8. }

源码使用