最近由于要经常操作网关扩展,如添加http扩展,新增mqtt扩展的映射。经常出现网关不同步问题。导致了经过网关的数据,设备有创建,但是没有相应遥测数据,之前有看过群里大佬写过thingsboard网关与tb配置同步的源码分析:
https://blog.csdn.net/Zzhou1990/article/details/102477059 Thingsboard Gateway 根据云端配置初始化
前记
以下纯属本人臆想推测,难免会有疏漏。欢迎看者多加指正,互相进步。
理解大佬源码分析
从大佬文章中,大致可以理解成:当网关配置与thingsboard互通后,并允许thingsboard远程更新,则网关中连接thingsboard mqtt broker的mqtt客户端有订阅了属性更新主题v1/devices/me/attributes
,用于实时获取共享属性更新。每当在thingsboard平台上配置网关扩展,thingsboard就会自动将配置信息保存为共享属性configuration
的值。此时网关中的mqtt客户端监听到共享属性更新,会根据共享属性值重新初始化网关扩展配置。而后再把相应扩展配置上传至网关客户端属性appliedConfiguration
,见如下代码:
private void updateConfiguration(String configuration) {
try {
if (extensionsConfigListener != null) {
extensionsConfigListener.accept(configuration);
}
onAppliedConfiguration(configuration);
} catch (Exception e) {
log.warn("Failed to update extension configurations [[]]", e.getMessage(), e);
}
public void onAppliedConfiguration(String configuration) {
byte[] msgData = toBytes(newNode().put("appliedConfiguration", configuration));
persistMessage(DEVICE_ATTRIBUTES_TOPIC, msgIdSeq.incrementAndGet(), msgData, null, null,
error ->
log.warn("Could not publish applied configuration", error));
}
同步状态判断依据
查阅thingsboard ui模块下的如下文件:
D:\JAVA\iot\code\thingsboard\ui\src\app\extension\extension-table.directive.js
确认同步方法:
function reloadExtensions() {
vm.subscribed = false;
vm.allExtensions.length = 0;
vm.extensions.length = 0;
vm.extensionsPromise = attributeService.getEntityAttributesValues(vm.entityType, vm.entityId, types.attributesScope.shared.value, ["configuration"]);
vm.extensionsPromise.then(
function success(data) {
if (data.length) {
vm.allExtensions = angular.fromJson(data[0].value);
} else {
vm.allExtensions = [];
}
vm.selectedExtensions = [];
updateExtensions();
vm.extensionsPromise = null;
},
function fail() {
vm.extensions = [];
vm.selectedExtensions = [];
updateExtensions();
vm.extensionsPromise = null;
}
);
}
function updateExtensions() {
vm.selectedExtensions = [];
var result = $filter('orderBy')(vm.allExtensions, vm.query.order);
// $log.info(result);
if (vm.query.search != null) {
result = $filter('filter')(result, function(extension) {
if(!vm.query.search || (extension.id.indexOf(vm.query.search) != -1) || (extension.type.indexOf(vm.query.search) != -1)) {
return true;
}
return false;
});
}
vm.extensionsCount = result.length;
var startIndex = vm.query.limit * (vm.query.page - 1);
vm.extensions = result.slice(startIndex, startIndex + vm.query.limit);
vm.extensionsJSON = angular.toJson(vm.extensions);
checkForSync();
}
function subscribeForClientAttributes() {
if (!vm.subscribed) {
if (vm.entityId && vm.entityType) {
$scope.subscriber = {
subscriptionCommands: [{
entityType: vm.entityType,
entityId: vm.entityId,
scope: 'CLIENT_SCOPE'
}],
type: 'attribute',
onData: function (data) {
if (data.data) {
onSubscriptionData(data.data);
}
vm.subscribed = true;
}
};
telemetryWebsocketService.subscribe($scope.subscriber);
}
}
}
function onSubscriptionData(data) {
// $log.info(data);
if ($.isEmptyObject(data)) {
vm.appliedConfiguration = undefined;
} else {
if (data.appliedConfiguration && data.appliedConfiguration[0] && data.appliedConfiguration[0][1]) {
vm.appliedConfiguration = data.appliedConfiguration[0][1];
}
}
updateExtensions();
$scope.$digest();
}
function checkForSync() {
// $log.info("app:"+vm.appliedConfiguration);
// $log.info("ext:"+vm.extensionsJSON);
if (vm.appliedConfiguration && vm.extensionsJSON && vm.appliedConfiguration === vm.extensionsJSON) {
vm.syncStatus = $translate.instant('extension.sync.sync');
vm.syncLastTime = formatDate();
$scope.isSync = true;
} else {
vm.syncStatus = $translate.instant('extension.sync.not-sync');
$scope.isSync = false;
}
}
可以看出同步状态是通过判断网关的客户端属性appliedConfiguration
与加工过的共享属性configuration
值是否一致。
同时发现一个自认为的bug:共享属性configuration
会被排序加工成extensionsJSON
,排序是根据扩展id升序排序的,所以会导致客户端属性与加工后的共享属性不一致,导致提示不同步,但好像并不影响使用:
var result = $filter('orderBy')(vm.allExtensions, vm.query.order);
vm.query = {
order: 'id',
limit: 5,
page: 1,
search: null
};
所以我自己建议是添加网关扩展时id累加命名,如1_green,2_red。