ThingsBoard自定义图表组件切换分组后无数据显示问题
问题:ThingsBoard层级组件切换分组后图表无数据显示
我在ThingsBoard中使用Hierarchy Widget(层级组件),该组件选中节点时会广播事件。层级结构如下:
- Group 1
- device 1
- device 2
- device 3
- Group 2
- device 1
- device 2
- device 3
需求是图表组件初始显示Group 1下设备的时序数据,选中Group 2时切换显示该分组下设备的时序数据。我编写代码让图表组件监听change-graph广播事件,获取分组ID后定义新数据源并创建订阅,但订阅后data为空,导致图表无法显示折线,代码如下:
self.onInit = function() { self.ctx.$scope.timeSeriesChartWidget.onInit(); let $scope = self.ctx.$scope; self.ctx.broadcastService = $scope.$injector.get(self.ctx.servicesMap.get('broadcastService')); self.ctx.broadcastService.on('change-graph', function(event, args) { const receivedData = args[0]; const groupId = receivedData.groupId; const groupName = receivedData.groupName; console.log('PSI Line Chart received "change-graph" for Group:', groupName, 'ID:', groupId); if (!groupId) { console.warn('Received "change-graph" broadcast but groupId is undefined. Chart will not update.'); return; } const datasources = [ { type: 'entity', dataKeys: [ { name: 'psi', type: 'timeseries', label: 'Pressure', settings: {} } ], entityFilter: { type: 'relationsQuery', rootEntity: { id: groupId, entityType: 'ASSET' }, direction: 'FROM', maxLevel: 1, fetchLastLevelOnly: false, filters: [ { relationType: "Contains", entityTypes: [ "DEVICE" ] } ] } } ]; const subscriptionOptions = { type: 'timeseries', // Subscription type singleEntity: false, datasources: datasources, // Describes what data you want to subscribe ignoreDataUpdateOnIntervalTick: true, //if true onDataUpdated will be triggered only when new data appears otherwise onDataUpdate will be triggered every second useDashboardTimewindow: true, callbacks: { onDataUpdated: () => { self.onDataUpdated(); }, }, }; self.ctx.subscriptionApi.createSubscription(subscriptionOptions, true).subscribe( (subscription) => { //Data is not available here! Code below just indicates where data will save. self.ctx.defaultSubscription = subscription; //Saves subscription information into widget context self.ctx.data = subscription.data; //Saves data into widget context self.ctx.datasources = subscription.datasources; //Saves datasource into widget context } ); }); const defaultGrupo1Id = '0a2f8e60-6959-11f0-899a-b775ed58e7c9'; // Your actual Grupo 1 ID self.ctx.broadcastService.broadcast('change-graph', { groupId: defaultGrupo1Id, groupName: 'Grupo 1' }); };
解决方案
1. 不要在订阅成功回调中直接赋值数据
createSubscription的subscribe回调仅表示订阅创建成功,此时数据尚未加载完成。正确的做法是在onDataUpdated回调中获取并更新数据。
2. 销毁旧订阅避免内存泄漏
每次创建新订阅前,先检查是否存在旧订阅,调用unsubscribe销毁,防止重复订阅导致的资源浪费。
3. 确认分组的实体类型
ThingsBoard中默认的分组实体类型是GROUP,而非ASSET,如果你的分组是系统默认的Group类型,需要修改rootEntity的entityType为GROUP。
4. 修正onDataUpdated方法处理数据
确保onDataUpdated方法正确将订阅数据同步到组件上下文,并触发图表刷新。
修改后的代码示例
self.onInit = function() { self.ctx.$scope.timeSeriesChartWidget.onInit(); let $scope = self.ctx.$scope; self.ctx.broadcastService = $scope.$injector.get(self.ctx.servicesMap.get('broadcastService')); // 统一处理数据更新的方法 self.onDataUpdated = function() { // 从订阅中获取最新数据并赋值到上下文 if (self.ctx.defaultSubscription) { self.ctx.data = self.ctx.defaultSubscription.data; self.ctx.datasources = self.ctx.defaultSubscription.datasources; // 触发图表组件的数据更新逻辑 self.ctx.$scope.timeSeriesChartWidget.onDataUpdated(); } }; self.ctx.broadcastService.on('change-graph', function(event, args) { const receivedData = args[0]; const groupId = receivedData.groupId; const groupName = receivedData.groupName; console.log('PSI Line Chart received "change-graph" for Group:', groupName, 'ID:', groupId); if (!groupId) { console.warn('Received "change-graph" broadcast but groupId is undefined. Chart will not update.'); return; } // 销毁旧订阅 if (self.ctx.defaultSubscription) { self.ctx.defaultSubscription.unsubscribe(); self.ctx.defaultSubscription = null; } const datasources = [ { type: 'entity', dataKeys: [ { name: 'psi', type: 'timeseries', label: 'Pressure', settings: {} } ], entityFilter: { type: 'relationsQuery', rootEntity: { id: groupId, entityType: 'GROUP' // 修正为默认分组类型 }, direction: 'FROM', maxLevel: 1, fetchLastLevelOnly: true, // 只获取设备层级,优化查询效率 filters: [ { relationType: "Contains", entityTypes: ["DEVICE"] } ] } } ]; const subscriptionOptions = { type: 'timeseries', singleEntity: false, datasources: datasources, ignoreDataUpdateOnIntervalTick: true, useDashboardTimewindow: true, callbacks: { onDataUpdated: () => { self.onDataUpdated(); }, }, }; // 创建新订阅 self.ctx.subscriptionApi.createSubscription(subscriptionOptions, true).subscribe( (subscription) => { self.ctx.defaultSubscription = subscription; // 首次订阅后手动触发一次数据更新,确保初始数据加载 setTimeout(() => self.onDataUpdated(), 500); } ); }); const defaultGrupo1Id = '0a2f8e60-6959-11f0-899a-b775ed58e7c9'; self.ctx.broadcastService.broadcast('change-graph', { groupId: defaultGrupo1Id, groupName: 'Grupo 1' }); };
额外检查项
- 确认分组与设备之间的关系类型是
Contains,且设备的psi时序数据存在 - 检查Dashboard的时间窗口设置,确保包含设备的历史数据
- 查看浏览器控制台,确认是否有实体权限或查询错误的日志信息
内容的提问来源于stack exchange,提问作者user23510896
相关产品推荐
相关产品推荐

