You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 14:52:03