ThingsBoard Extensions
ThingsBoard extensions 是我们的附加项目,允许你创建自己的Angular组件并在部件和操作中使用它们。 我们强烈建议在解决方案的任何复杂逻辑中使用此功能,因为它让你能够复用代码,并充分利用TypeScript、RXJS、Angular等的全部功能。 本文介绍如何在ThingsBoard 3.6及更高版本中通过UI连接你的extensions。
首先需要准备包含已编译组件的文件。默认文件名为 thingsboard-extension-widgets.js。创建该文件的说明请参阅 ThingsBoard extensions 的 README 文件。
准备好包含组件的文件后,将其加载到ThingsBoard:
- 进入”Resources“下的”JavaScript library“页面;
- 点击”Add JavaScript resource“按钮(窗口右上角的”加号”图标);
- 在弹出窗口中,在”JavaScript type“选择器中选择”Extension“(或选择”Module“以粘贴代码片段);
- 输入模块标题;
- 拖拽包含已编译组件的文件;
- 点击”Add”。
你的组件已成功添加到ThingsBoard。
下面介绍如何在部件中使用这些组件。我们将创建一个简单的Latest value部件,使用extensions中的组件(若对创建新部件有疑问,请参阅 创建新部件定义):
- 进入”Resources“下的”Widgets library“页面;
- 点击窗口右上角的”plus“图标,选择”Create new widget“;
- 选择部件类型”Latest value“;
- 输入部件名称;
- 进入”Resources“选项卡,点击”Add“按钮;
- 勾选”Is extension“;
- 从下拉菜单中选择你的extension模块;
模块已与部件连接。现在可以在部件中使用你的Angular组件:
- 进入”HTML“选项卡,添加自定义组件。示例中为 tb-example-table(别忘了添加 ctx);
- 清空 self.onInit、self.onDataUpdated、self.onResize 的默认内容;
- 在onDataUpdated函数中添加如下代码:
1
self.ctx.$scope.exampleTableComponent.onDataUpdated();
当部件收到新数据时,会触发自定义组件中的更新函数;
- 添加以下函数:
1 2 3 4 5 6 7 8 9
self.typeParameters = function() { return { maxDatasources: 1, //最大数据源数量为 1 singleEntity: true, //仅允许一个实体 previewWidth: '250px', //预览 X 轴默认尺寸 previewHeight: '250px', //预览 Y 轴默认尺寸 embedTitlePanel: true, //隐藏标题栏 }; };
该函数设置部件的行为规则;
- 点击”Run”按钮预览部件效果;
- 点击”Save”保存修改。
现在部件中已使用你的组件。
ThingsBoard extensions 允许你在ThingsBoard平台范围内创建任意类型的部件。
祝你开发顺利!
集成现有代码创建部件定义
以下示例演示如何复用/集成外部JavaScript库或现有代码来创建新部件。
使用外部JavaScript库
Latest Values示例
本示例使用外部 gauge.js 库创建 Latest Values 仪表类部件。
在 Widgets Bundle 视图中,点击屏幕右下角的大“+”按钮,然后点击“Create new widget type”。 在 Select widget type 弹窗中点击 Latest Values。 Widget Editor 将打开,并预填充默认 Latest Values 模板部件的内容。
- 打开 Resources 选项卡,点击“Add”,插入以下链接:
1
https://bernii.github.io/gauge.js/dist/gauge.min.js
- 清空“Resources”区域中CSS选项卡的内容。
- 在“Resources”的HTML选项卡中放入以下HTML代码:
1
<canvas id="my-gauge"></canvas>
- 在“JavaScript”区域中放入以下JavaScript代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
var canvasElement;
var gauge;
self.onInit = function() {
canvasElement = $('#my-gauge', self.ctx.$container)[0];
gauge = new Gauge(canvasElement);
gauge.minValue = -1000;
gauge.maxValue = 1000;
gauge.animationSpeed = 16;
self.onResize();
}
self.onResize = function() {
canvasElement.width = self.ctx.width;
canvasElement.height = self.ctx.height;
gauge.update(true);
gauge.render();
}
self.onDataUpdated = function() {
if (self.ctx.defaultSubscription.data[0].data.length) {
var value = self.ctx.defaultSubscription.data[0].data[0][1];
gauge.set(value);
}
}
- 点击 Widget Editor Toolbar 上的 Run 按钮,在 Widget preview 区域查看结果。

本示例使用了外部JS库API,在 Resources 区域注入对应URL后即可使用。 显示值来自 subscription data 属性中第一个dataKey的数据。
Time-Series示例
本示例使用外部 Chart.js 库创建 Time-Series 折线图部件。
在 Widgets Bundle 视图中,点击屏幕右下角的大“+”按钮,然后点击“Create new widget type”。 在 Select widget type 弹窗中点击 Time-Series。 Widget Editor 将打开,并预填充默认 Time-Series 模板部件的内容。
- 打开 Resources 选项卡,点击“Add”,插入以下链接:
1
https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js
- 清空“Resources”区域中CSS选项卡的内容。
- 在“Resources”的HTML选项卡中放入以下HTML代码:
1
<canvas id="myChart"></canvas>
- 在“JavaScript”区域中放入以下JavaScript代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
var myChart;
self.onInit = function() {
var chartData = {
datasets: []
};
for (var i=0; i < self.ctx.data.length; i++) {
var dataKey = self.ctx.data[i].dataKey;
var dataset = {
label: dataKey.label,
data: [],
borderColor: dataKey.color,
fill: false
};
chartData.datasets.push(dataset);
}
var options = {
maintainAspectRatio: false,
legend: {
display: false
},
scales: {
xAxes: [{
type: 'time',
ticks: {
maxRotation: 0,
autoSkipPadding: 30
}
}]
}
};
var canvasElement = $('#myChart', self.ctx.$container)[0];
var canvasCtx = canvasElement.getContext('2d');
myChart = new Chart(canvasCtx, {
type: 'line',
data: chartData,
options: options
});
self.onResize();
}
self.onResize = function() {
myChart.resize();
}
self.onDataUpdated = function() {
for (var i = 0; i < self.ctx.data.length; i++) {
var datasourceData = self.ctx.data[i];
var dataSet = datasourceData.data;
myChart.data.datasets[i].data.length = 0;
var data = myChart.data.datasets[i].data;
for (var d = 0; d < dataSet.length; d++) {
var tsValuePair = dataSet[d];
var ts = tsValuePair[0];
var value = tsValuePair[1];
data.push({t: ts, y: value});
}
}
myChart.options.scales.xAxes[0].ticks.min = self.ctx.timeWindow.minTime;
myChart.options.scales.xAxes[0].ticks.max = self.ctx.timeWindow.maxTime;
myChart.update();
}
- 点击 Widget Editor Toolbar 上的 Run 按钮,在 Widget preview 区域查看结果。

本示例使用了外部JS库API,在 Resources 区域注入对应URL后即可使用。 图表数据集根据 ctx 的 data 属性中配置的dataKeys进行准备。 在 onDataUpdated 函数中,数据源数据被转换为Chart.js折线图格式并推入图表数据集。 注意:xAxis(时间轴)限制在 ctx 的 timeWindow 属性得到的当前timewindow范围内。
使用现有JavaScript代码
另一种创建部件的方式是使用已打包的JavaScript代码。 此时可以创建自己的TypeScript类或Angular组件,并将其打包进ThingsBoard UI代码。 要使该代码在部件中可访问,需要注册对应的Angular模块或将TypeScript类注入到全局变量(例如window对象)。 部分ThingsBoard部件已采用此方式。可参考 polyfills.ts 或 widget-components.module.ts。 其中说明了如何将bundled类或组件注册以供ThingsBoard部件使用。 例如“Timeseries - Flot”部件(来自“Charts”Widgets Bundle)使用 TbFlot TypeScript类,该类在 polyfills.ts 中作为window属性注入:
1
2
3
4
5
6
7
8
...
import { TbFlot } from '@home/components/widget/lib/flot-widget';
...
(window as any).TbFlot = TbFlot;
...
另一个例子是“Timeseries table”部件(来自“Cards”Widgets Bundle),使用Angular组件 tb-timeseries-table-widget,该组件在 widget-components.module.ts 中注册为 WidgetComponentsModule 的依赖。 因此该组件可在部件模板HTML中使用。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
import { TimeseriesTableWidgetComponent } from '@home/components/widget/lib/timeseries-table-widget.component';
...
@NgModule({
declarations:
[
...
TimeseriesTableWidgetComponent,
...
],
...
exports: [
...
TimeseriesTableWidgetComponent,
...
],
...
})
export class WidgetComponentsModule { }