Commit 1d0755f10157dfc0f2e4b6b0c905444dcd68ba2f

Authored by Igor Kulikov
2 parents bbf78721 04e21816

Merge branch 'master' of github.com:thingsboard/thingsboard

Showing 80 changed files with 1391 additions and 939 deletions

Too many changes to show.

To preserve performance only 80 of 182 files are displayed.

1 1 {
2 2 "title": "Firmware",
  3 + "image": null,
3 4 "configuration": {
4 5 "description": "",
5 6 "widgets": {
... ... @@ -247,7 +248,7 @@
247 248 "name": "Edit firmware",
248 249 "icon": "edit",
249 250 "type": "customPretty",
250   - "customHtml": "<form #editEntityForm=\"ngForm\" [formGroup]=\"editEntityFormGroup\"\n (ngSubmit)=\"save()\" class=\"edit-entity-form\">\n <mat-toolbar fxLayout=\"row\" color=\"primary\">\n <h2>Edit firmware {{entityName}}</h2>\n <span fxFlex></span>\n <button mat-icon-button (click)=\"cancel()\" type=\"button\">\n <mat-icon class=\"material-icons\">close</mat-icon>\n </button>\n </mat-toolbar>\n <mat-progress-bar color=\"warn\" mode=\"indeterminate\" *ngIf=\"isLoading$ | async\">\n </mat-progress-bar>\n <div style=\"height: 4px;\" *ngIf=\"!(isLoading$ | async)\"></div>\n <div *ngIf=\"entity.deviceProfileId\" mat-dialog-content fxLayout=\"column\">\n <tb-firmware-autocomplete\n [useFullEntityId]=\"true\"\n [deviceProfileId]=\"entity.deviceProfileId.id\"\n formControlName=\"firmwareId\">\n </tb-firmware-autocomplete>\n </div>\n <div mat-dialog-actions fxLayout=\"row\" fxLayoutAlign=\"end center\">\n <button mat-button color=\"primary\"\n type=\"button\"\n [disabled]=\"(isLoading$ | async)\"\n (click)=\"cancel()\" cdkFocusInitial>\n Cancel\n </button>\n <button mat-button mat-raised-button color=\"primary\"\n type=\"submit\"\n [disabled]=\"(isLoading$ | async) || editEntityForm.invalid || !editEntityForm.dirty\">\n Save\n </button>\n </div>\n</form>",
  251 + "customHtml": "<form #editEntityForm=\"ngForm\" [formGroup]=\"editEntityFormGroup\"\n (ngSubmit)=\"save()\" class=\"edit-entity-form\">\n <mat-toolbar fxLayout=\"row\" color=\"primary\">\n <h2>Edit firmware {{entityName}}</h2>\n <span fxFlex></span>\n <button mat-icon-button (click)=\"cancel()\" type=\"button\">\n <mat-icon class=\"material-icons\">close</mat-icon>\n </button>\n </mat-toolbar>\n <mat-progress-bar color=\"warn\" mode=\"indeterminate\" *ngIf=\"isLoading$ | async\">\n </mat-progress-bar>\n <div style=\"height: 4px;\" *ngIf=\"!(isLoading$ | async)\"></div>\n <div *ngIf=\"entity.deviceProfileId\" mat-dialog-content fxLayout=\"column\">\n <tb-ota-package-autocomplete\n [useFullEntityId]=\"true\"\n [deviceProfileId]=\"entity.deviceProfileId.id\"\n formControlName=\"firmwareId\">\n </tb-ota-package-autocomplete>\n </div>\n <div mat-dialog-actions fxLayout=\"row\" fxLayoutAlign=\"end center\">\n <button mat-button color=\"primary\"\n type=\"button\"\n [disabled]=\"(isLoading$ | async)\"\n (click)=\"cancel()\" cdkFocusInitial>\n Cancel\n </button>\n <button mat-button mat-raised-button color=\"primary\"\n type=\"submit\"\n [disabled]=\"(isLoading$ | async) || editEntityForm.invalid || !editEntityForm.dirty\">\n Save\n </button>\n </div>\n</form>",
251 252 "customCss": "",
252 253 "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet customDialog = $injector.get(widgetContext.servicesMap.get('customDialog'));\nlet entityService = $injector.get(widgetContext.servicesMap.get('entityService'));\nlet deviceService = $injector.get(widgetContext.servicesMap.get('deviceService'));\n\nopenEditEntityDialog();\n\nfunction openEditEntityDialog() {\n customDialog.customDialog(htmlTemplate, EditEntityDialogController).subscribe();\n}\n\nfunction EditEntityDialogController(instance) {\n let vm = instance;\n\n vm.entityName = entityName;\n vm.entity = {};\n\n vm.editEntityFormGroup = vm.fb.group({\n firmwareId: [null]\n });\n\n getEntityInfo();\n\n vm.cancel = function() {\n vm.dialogRef.close(null);\n };\n\n vm.save = function() {\n vm.editEntityFormGroup.markAsPristine();\n saveEntity().subscribe(\n function () {\n // widgetContext.updateAliases();\n vm.dialogRef.close(null);\n }\n );\n };\n\n\n function getEntityInfo() {\n entityService.getEntity(entityId.entityType, entityId.id).subscribe(\n function (data) {\n vm.entity = data;\n vm.editEntityFormGroup.patchValue({\n firmwareId: vm.entity.firmwareId\n }, {emitEvent: false});\n }\n );\n }\n\n function saveEntity() {\n const formValues = vm.editEntityFormGroup.value;\n vm.entity.firmwareId = formValues.firmwareId;\n return deviceService.saveDevice(vm.entity);\n }\n}",
253 254 "customResources": [],
... ... @@ -257,7 +258,7 @@
257 258 "name": "Download firware",
258 259 "icon": "file_download",
259 260 "type": "custom",
260   - "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet entityService = $injector.get(widgetContext.servicesMap.get('entityService'));\nlet firmwareService = $injector.get(widgetContext.servicesMap.get('firmwareService'));\nlet deviceProfileService = $injector.get(widgetContext.servicesMap.get('deviceProfileService'));\n\ngetDeviceFirmware();\n\nfunction getDeviceFirmware() {\n entityService.getEntity(entityId.entityType, entityId.id).subscribe(\n function (data) {\n if (data.firmwareId !== null) {\n firmwareService.downloadFirmware(data.firmwareId.id).subscribe(); \n } else {\n deviceProfileService.getDeviceProfile(data.deviceProfileId.id).subscribe(\n function (deviceProfile) {\n if (deviceProfile.firmwareId !== null) {\n firmwareService.downloadFirmware(deviceProfile.firmwareId.id).subscribe();\n } else {\n widgetContext.showToast('warn', 'Device ' + entityName +' has not firmware set.', 2000, 'top');\n\n }\n });\n }\n }\n );\n}",
  261 + "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet entityService = $injector.get(widgetContext.servicesMap.get('entityService'));\nlet otaPackageService = $injector.get(widgetContext.servicesMap.get('otaPackageService'));\nlet deviceProfileService = $injector.get(widgetContext.servicesMap.get('deviceProfileService'));\n\ngetDeviceFirmware();\n\nfunction getDeviceFirmware() {\n entityService.getEntity(entityId.entityType, entityId.id).subscribe(\n function (data) {\n if (data.firmwareId !== null) {\n otaPackageService.downloadOtaPackage(data.firmwareId.id).subscribe(); \n } else {\n deviceProfileService.getDeviceProfile(data.deviceProfileId.id).subscribe(\n function (deviceProfile) {\n if (deviceProfile.firmwareId !== null) {\n otaPackageService.downloadOtaPackage(deviceProfile.firmwareId.id).subscribe();\n } else {\n widgetContext.showToast('warn', 'Device ' + entityName +' has not firmware set.', 2000, 'top');\n\n }\n });\n }\n }\n );\n}",
261 262 "id": "12533058-42f6-e75f-620c-219c48d01ec0"
262 263 },
263 264 {
... ... @@ -1021,7 +1022,7 @@
1021 1022 "name": "Edit firmware",
1022 1023 "icon": "edit",
1023 1024 "type": "customPretty",
1024   - "customHtml": "<form #editEntityForm=\"ngForm\" [formGroup]=\"editEntityFormGroup\"\n (ngSubmit)=\"save()\" class=\"edit-entity-form\">\n <mat-toolbar fxLayout=\"row\" color=\"primary\">\n <h2>Edit firmware {{entityName}}</h2>\n <span fxFlex></span>\n <button mat-icon-button (click)=\"cancel()\" type=\"button\">\n <mat-icon class=\"material-icons\">close</mat-icon>\n </button>\n </mat-toolbar>\n <mat-progress-bar color=\"warn\" mode=\"indeterminate\" *ngIf=\"isLoading$ | async\">\n </mat-progress-bar>\n <div style=\"height: 4px;\" *ngIf=\"!(isLoading$ | async)\"></div>\n <div mat-dialog-content fxLayout=\"column\">\n <tb-firmware-autocomplete\n [useFullEntityId]=\"true\"\n formControlName=\"firmwareId\">\n </tb-firmware-autocomplete>\n </div>\n <div mat-dialog-actions fxLayout=\"row\" fxLayoutAlign=\"end center\">\n <button mat-button color=\"primary\"\n type=\"button\"\n [disabled]=\"(isLoading$ | async)\"\n (click)=\"cancel()\" cdkFocusInitial>\n Cancel\n </button>\n <button mat-button mat-raised-button color=\"primary\"\n type=\"submit\"\n [disabled]=\"(isLoading$ | async) || editEntityForm.invalid || !editEntityForm.dirty\">\n Save\n </button>\n </div>\n</form>",
  1025 + "customHtml": "<form #editEntityForm=\"ngForm\" [formGroup]=\"editEntityFormGroup\"\n (ngSubmit)=\"save()\" class=\"edit-entity-form\">\n <mat-toolbar fxLayout=\"row\" color=\"primary\">\n <h2>Edit firmware {{entityName}}</h2>\n <span fxFlex></span>\n <button mat-icon-button (click)=\"cancel()\" type=\"button\">\n <mat-icon class=\"material-icons\">close</mat-icon>\n </button>\n </mat-toolbar>\n <mat-progress-bar color=\"warn\" mode=\"indeterminate\" *ngIf=\"isLoading$ | async\">\n </mat-progress-bar>\n <div style=\"height: 4px;\" *ngIf=\"!(isLoading$ | async)\"></div>\n <div *ngIf=\"entity.deviceProfileId\" mat-dialog-content fxLayout=\"column\">\n <tb-ota-package-autocomplete\n [useFullEntityId]=\"true\"\n [deviceProfileId]=\"entity.deviceProfileId.id\"\n formControlName=\"firmwareId\">\n </tb-ota-package-autocomplete>\n </div>\n <div mat-dialog-actions fxLayout=\"row\" fxLayoutAlign=\"end center\">\n <button mat-button color=\"primary\"\n type=\"button\"\n [disabled]=\"(isLoading$ | async)\"\n (click)=\"cancel()\" cdkFocusInitial>\n Cancel\n </button>\n <button mat-button mat-raised-button color=\"primary\"\n type=\"submit\"\n [disabled]=\"(isLoading$ | async) || editEntityForm.invalid || !editEntityForm.dirty\">\n Save\n </button>\n </div>\n</form>",
1025 1026 "customCss": "",
1026 1027 "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet customDialog = $injector.get(widgetContext.servicesMap.get('customDialog'));\nlet entityService = $injector.get(widgetContext.servicesMap.get('entityService'));\nlet deviceService = $injector.get(widgetContext.servicesMap.get('deviceService'));\n\nopenEditEntityDialog();\n\nfunction openEditEntityDialog() {\n customDialog.customDialog(htmlTemplate, EditEntityDialogController).subscribe();\n}\n\nfunction EditEntityDialogController(instance) {\n let vm = instance;\n\n vm.entityName = entityName;\n vm.entity = {};\n\n vm.editEntityFormGroup = vm.fb.group({\n firmwareId: [null]\n });\n\n getEntityInfo();\n\n vm.cancel = function() {\n vm.dialogRef.close(null);\n };\n\n vm.save = function() {\n vm.editEntityFormGroup.markAsPristine();\n saveEntity().subscribe(\n function () {\n // widgetContext.updateAliases();\n vm.dialogRef.close(null);\n }\n );\n };\n\n\n function getEntityInfo() {\n entityService.getEntity(entityId.entityType, entityId.id).subscribe(\n function (data) {\n vm.entity = data;\n vm.editEntityFormGroup.patchValue({\n firmwareId: vm.entity.firmwareId\n }, {emitEvent: false});\n }\n );\n }\n\n function saveEntity() {\n const formValues = vm.editEntityFormGroup.value;\n vm.entity.firmwareId = formValues.firmwareId;\n return deviceService.saveDevice(vm.entity);\n }\n}",
1027 1028 "customResources": [],
... ... @@ -1031,7 +1032,7 @@
1031 1032 "name": "Download firware",
1032 1033 "icon": "file_download",
1033 1034 "type": "custom",
1034   - "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet entityService = $injector.get(widgetContext.servicesMap.get('entityService'));\nlet firmwareService = $injector.get(widgetContext.servicesMap.get('firmwareService'));\nlet deviceProfileService = $injector.get(widgetContext.servicesMap.get('deviceProfileService'));\n\ngetDeviceFirmware();\n\nfunction getDeviceFirmware() {\n entityService.getEntity(entityId.entityType, entityId.id).subscribe(\n function (data) {\n if (data.firmwareId !== null) {\n firmwareService.downloadFirmware(data.firmwareId.id).subscribe(); \n } else {\n deviceProfileService.getDeviceProfile(data.deviceProfileId.id).subscribe(\n function (deviceProfile) {\n if (deviceProfile.firmwareId !== null) {\n firmwareService.downloadFirmware(deviceProfile.firmwareId.id).subscribe();\n } else {\n widgetContext.showToast('warn', 'Device ' + entityName +' has not firmware set.', 2000, 'top');\n\n }\n });\n }\n }\n );\n}",
  1035 + "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet entityService = $injector.get(widgetContext.servicesMap.get('entityService'));\nlet otaPackageService = $injector.get(widgetContext.servicesMap.get('otaPackageService'));\nlet deviceProfileService = $injector.get(widgetContext.servicesMap.get('deviceProfileService'));\n\ngetDeviceFirmware();\n\nfunction getDeviceFirmware() {\n entityService.getEntity(entityId.entityType, entityId.id).subscribe(\n function (data) {\n if (data.firmwareId !== null) {\n otaPackageService.downloadOtaPackage(data.firmwareId.id).subscribe(); \n } else {\n deviceProfileService.getDeviceProfile(data.deviceProfileId.id).subscribe(\n function (deviceProfile) {\n if (deviceProfile.firmwareId !== null) {\n otaPackageService.downloadOtaPackage(deviceProfile.firmwareId.id).subscribe();\n } else {\n widgetContext.showToast('warn', 'Device ' + entityName +' has not firmware set.', 2000, 'top');\n\n }\n });\n }\n }\n );\n}",
1035 1036 "id": "12533058-42f6-e75f-620c-219c48d01ec0"
1036 1037 },
1037 1038 {
... ... @@ -1297,7 +1298,7 @@
1297 1298 "name": "Edit firmware",
1298 1299 "icon": "edit",
1299 1300 "type": "customPretty",
1300   - "customHtml": "<form #editEntityForm=\"ngForm\" [formGroup]=\"editEntityFormGroup\"\n (ngSubmit)=\"save()\" class=\"edit-entity-form\">\n <mat-toolbar fxLayout=\"row\" color=\"primary\">\n <h2>Edit firmware {{entityName}}</h2>\n <span fxFlex></span>\n <button mat-icon-button (click)=\"cancel()\" type=\"button\">\n <mat-icon class=\"material-icons\">close</mat-icon>\n </button>\n </mat-toolbar>\n <mat-progress-bar color=\"warn\" mode=\"indeterminate\" *ngIf=\"isLoading$ | async\">\n </mat-progress-bar>\n <div style=\"height: 4px;\" *ngIf=\"!(isLoading$ | async)\"></div>\n <div mat-dialog-content fxLayout=\"column\">\n <tb-firmware-autocomplete\n [useFullEntityId]=\"true\"\n formControlName=\"firmwareId\">\n </tb-firmware-autocomplete>\n </div>\n <div mat-dialog-actions fxLayout=\"row\" fxLayoutAlign=\"end center\">\n <button mat-button color=\"primary\"\n type=\"button\"\n [disabled]=\"(isLoading$ | async)\"\n (click)=\"cancel()\" cdkFocusInitial>\n Cancel\n </button>\n <button mat-button mat-raised-button color=\"primary\"\n type=\"submit\"\n [disabled]=\"(isLoading$ | async) || editEntityForm.invalid || !editEntityForm.dirty\">\n Save\n </button>\n </div>\n</form>",
  1301 + "customHtml": "<form #editEntityForm=\"ngForm\" [formGroup]=\"editEntityFormGroup\"\n (ngSubmit)=\"save()\" class=\"edit-entity-form\">\n <mat-toolbar fxLayout=\"row\" color=\"primary\">\n <h2>Edit firmware {{entityName}}</h2>\n <span fxFlex></span>\n <button mat-icon-button (click)=\"cancel()\" type=\"button\">\n <mat-icon class=\"material-icons\">close</mat-icon>\n </button>\n </mat-toolbar>\n <mat-progress-bar color=\"warn\" mode=\"indeterminate\" *ngIf=\"isLoading$ | async\">\n </mat-progress-bar>\n <div style=\"height: 4px;\" *ngIf=\"!(isLoading$ | async)\"></div>\n <div *ngIf=\"entity.deviceProfileId\" mat-dialog-content fxLayout=\"column\">\n <tb-ota-package-autocomplete\n [useFullEntityId]=\"true\"\n [deviceProfileId]=\"entity.deviceProfileId.id\"\n formControlName=\"firmwareId\">\n </tb-ota-package-autocomplete>\n </div>\n <div mat-dialog-actions fxLayout=\"row\" fxLayoutAlign=\"end center\">\n <button mat-button color=\"primary\"\n type=\"button\"\n [disabled]=\"(isLoading$ | async)\"\n (click)=\"cancel()\" cdkFocusInitial>\n Cancel\n </button>\n <button mat-button mat-raised-button color=\"primary\"\n type=\"submit\"\n [disabled]=\"(isLoading$ | async) || editEntityForm.invalid || !editEntityForm.dirty\">\n Save\n </button>\n </div>\n</form>",
1301 1302 "customCss": "",
1302 1303 "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet customDialog = $injector.get(widgetContext.servicesMap.get('customDialog'));\nlet entityService = $injector.get(widgetContext.servicesMap.get('entityService'));\nlet deviceService = $injector.get(widgetContext.servicesMap.get('deviceService'));\n\nopenEditEntityDialog();\n\nfunction openEditEntityDialog() {\n customDialog.customDialog(htmlTemplate, EditEntityDialogController).subscribe();\n}\n\nfunction EditEntityDialogController(instance) {\n let vm = instance;\n\n vm.entityName = entityName;\n vm.entity = {};\n\n vm.editEntityFormGroup = vm.fb.group({\n firmwareId: [null]\n });\n\n getEntityInfo();\n\n vm.cancel = function() {\n vm.dialogRef.close(null);\n };\n\n vm.save = function() {\n vm.editEntityFormGroup.markAsPristine();\n saveEntity().subscribe(\n function () {\n // widgetContext.updateAliases();\n vm.dialogRef.close(null);\n }\n );\n };\n\n\n function getEntityInfo() {\n entityService.getEntity(entityId.entityType, entityId.id).subscribe(\n function (data) {\n vm.entity = data;\n vm.editEntityFormGroup.patchValue({\n firmwareId: vm.entity.firmwareId\n }, {emitEvent: false});\n }\n );\n }\n\n function saveEntity() {\n const formValues = vm.editEntityFormGroup.value;\n vm.entity.firmwareId = formValues.firmwareId;\n return deviceService.saveDevice(vm.entity);\n }\n}",
1303 1304 "customResources": [],
... ... @@ -1307,7 +1308,7 @@
1307 1308 "name": "Download firware",
1308 1309 "icon": "file_download",
1309 1310 "type": "custom",
1310   - "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet entityService = $injector.get(widgetContext.servicesMap.get('entityService'));\nlet firmwareService = $injector.get(widgetContext.servicesMap.get('firmwareService'));\nlet deviceProfileService = $injector.get(widgetContext.servicesMap.get('deviceProfileService'));\n\ngetDeviceFirmware();\n\nfunction getDeviceFirmware() {\n entityService.getEntity(entityId.entityType, entityId.id).subscribe(\n function (data) {\n if (data.firmwareId !== null) {\n firmwareService.downloadFirmware(data.firmwareId.id).subscribe(); \n } else {\n deviceProfileService.getDeviceProfile(data.deviceProfileId.id).subscribe(\n function (deviceProfile) {\n if (deviceProfile.firmwareId !== null) {\n firmwareService.downloadFirmware(deviceProfile.firmwareId.id).subscribe();\n } else {\n widgetContext.showToast('warn', 'Device ' + entityName +' has not firmware set.', 2000, 'top');\n\n }\n });\n }\n }\n );\n}",
  1311 + "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet entityService = $injector.get(widgetContext.servicesMap.get('entityService'));\nlet otaPackageService = $injector.get(widgetContext.servicesMap.get('otaPackageService'));\nlet deviceProfileService = $injector.get(widgetContext.servicesMap.get('deviceProfileService'));\n\ngetDeviceFirmware();\n\nfunction getDeviceFirmware() {\n entityService.getEntity(entityId.entityType, entityId.id).subscribe(\n function (data) {\n if (data.firmwareId !== null) {\n otaPackageService.downloadOtaPackage(data.firmwareId.id).subscribe(); \n } else {\n deviceProfileService.getDeviceProfile(data.deviceProfileId.id).subscribe(\n function (deviceProfile) {\n if (deviceProfile.firmwareId !== null) {\n otaPackageService.downloadOtaPackage(deviceProfile.firmwareId.id).subscribe();\n } else {\n widgetContext.showToast('warn', 'Device ' + entityName +' has not firmware set.', 2000, 'top');\n\n }\n });\n }\n }\n );\n}",
1311 1312 "id": "12533058-42f6-e75f-620c-219c48d01ec0"
1312 1313 },
1313 1314 {
... ... @@ -1573,7 +1574,7 @@
1573 1574 "name": "Edit firmware",
1574 1575 "icon": "edit",
1575 1576 "type": "customPretty",
1576   - "customHtml": "<form #editEntityForm=\"ngForm\" [formGroup]=\"editEntityFormGroup\"\n (ngSubmit)=\"save()\" class=\"edit-entity-form\">\n <mat-toolbar fxLayout=\"row\" color=\"primary\">\n <h2>Edit firmware {{entityName}}</h2>\n <span fxFlex></span>\n <button mat-icon-button (click)=\"cancel()\" type=\"button\">\n <mat-icon class=\"material-icons\">close</mat-icon>\n </button>\n </mat-toolbar>\n <mat-progress-bar color=\"warn\" mode=\"indeterminate\" *ngIf=\"isLoading$ | async\">\n </mat-progress-bar>\n <div style=\"height: 4px;\" *ngIf=\"!(isLoading$ | async)\"></div>\n <div mat-dialog-content fxLayout=\"column\">\n <tb-firmware-autocomplete\n [useFullEntityId]=\"true\"\n formControlName=\"firmwareId\">\n </tb-firmware-autocomplete>\n </div>\n <div mat-dialog-actions fxLayout=\"row\" fxLayoutAlign=\"end center\">\n <button mat-button color=\"primary\"\n type=\"button\"\n [disabled]=\"(isLoading$ | async)\"\n (click)=\"cancel()\" cdkFocusInitial>\n Cancel\n </button>\n <button mat-button mat-raised-button color=\"primary\"\n type=\"submit\"\n [disabled]=\"(isLoading$ | async) || editEntityForm.invalid || !editEntityForm.dirty\">\n Save\n </button>\n </div>\n</form>",
  1577 + "customHtml": "<form #editEntityForm=\"ngForm\" [formGroup]=\"editEntityFormGroup\"\n (ngSubmit)=\"save()\" class=\"edit-entity-form\">\n <mat-toolbar fxLayout=\"row\" color=\"primary\">\n <h2>Edit firmware {{entityName}}</h2>\n <span fxFlex></span>\n <button mat-icon-button (click)=\"cancel()\" type=\"button\">\n <mat-icon class=\"material-icons\">close</mat-icon>\n </button>\n </mat-toolbar>\n <mat-progress-bar color=\"warn\" mode=\"indeterminate\" *ngIf=\"isLoading$ | async\">\n </mat-progress-bar>\n <div style=\"height: 4px;\" *ngIf=\"!(isLoading$ | async)\"></div>\n <div *ngIf=\"entity.deviceProfileId\" mat-dialog-content fxLayout=\"column\">\n <tb-ota-package-autocomplete\n [useFullEntityId]=\"true\"\n [deviceProfileId]=\"entity.deviceProfileId.id\"\n formControlName=\"firmwareId\">\n </tb-ota-package-autocomplete>\n </div>\n <div mat-dialog-actions fxLayout=\"row\" fxLayoutAlign=\"end center\">\n <button mat-button color=\"primary\"\n type=\"button\"\n [disabled]=\"(isLoading$ | async)\"\n (click)=\"cancel()\" cdkFocusInitial>\n Cancel\n </button>\n <button mat-button mat-raised-button color=\"primary\"\n type=\"submit\"\n [disabled]=\"(isLoading$ | async) || editEntityForm.invalid || !editEntityForm.dirty\">\n Save\n </button>\n </div>\n</form>",
1577 1578 "customCss": "",
1578 1579 "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet customDialog = $injector.get(widgetContext.servicesMap.get('customDialog'));\nlet entityService = $injector.get(widgetContext.servicesMap.get('entityService'));\nlet deviceService = $injector.get(widgetContext.servicesMap.get('deviceService'));\n\nopenEditEntityDialog();\n\nfunction openEditEntityDialog() {\n customDialog.customDialog(htmlTemplate, EditEntityDialogController).subscribe();\n}\n\nfunction EditEntityDialogController(instance) {\n let vm = instance;\n\n vm.entityName = entityName;\n vm.entity = {};\n\n vm.editEntityFormGroup = vm.fb.group({\n firmwareId: [null]\n });\n\n getEntityInfo();\n\n vm.cancel = function() {\n vm.dialogRef.close(null);\n };\n\n vm.save = function() {\n vm.editEntityFormGroup.markAsPristine();\n saveEntity().subscribe(\n function () {\n // widgetContext.updateAliases();\n vm.dialogRef.close(null);\n }\n );\n };\n\n\n function getEntityInfo() {\n entityService.getEntity(entityId.entityType, entityId.id).subscribe(\n function (data) {\n vm.entity = data;\n vm.editEntityFormGroup.patchValue({\n firmwareId: vm.entity.firmwareId\n }, {emitEvent: false});\n }\n );\n }\n\n function saveEntity() {\n const formValues = vm.editEntityFormGroup.value;\n vm.entity.firmwareId = formValues.firmwareId;\n return deviceService.saveDevice(vm.entity);\n }\n}",
1579 1580 "customResources": [],
... ... @@ -1583,7 +1584,7 @@
1583 1584 "name": "Download firware",
1584 1585 "icon": "file_download",
1585 1586 "type": "custom",
1586   - "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet entityService = $injector.get(widgetContext.servicesMap.get('entityService'));\nlet firmwareService = $injector.get(widgetContext.servicesMap.get('firmwareService'));\nlet deviceProfileService = $injector.get(widgetContext.servicesMap.get('deviceProfileService'));\n\ngetDeviceFirmware();\n\nfunction getDeviceFirmware() {\n entityService.getEntity(entityId.entityType, entityId.id).subscribe(\n function (data) {\n if (data.firmwareId !== null) {\n firmwareService.downloadFirmware(data.firmwareId.id).subscribe(); \n } else {\n deviceProfileService.getDeviceProfile(data.deviceProfileId.id).subscribe(\n function (deviceProfile) {\n if (deviceProfile.firmwareId !== null) {\n firmwareService.downloadFirmware(deviceProfile.firmwareId.id).subscribe();\n } else {\n widgetContext.showToast('warn', 'Device ' + entityName +' has not firmware set.', 2000, 'top');\n\n }\n });\n }\n }\n );\n}",
  1587 + "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet entityService = $injector.get(widgetContext.servicesMap.get('entityService'));\nlet otaPackageService = $injector.get(widgetContext.servicesMap.get('otaPackageService'));\nlet deviceProfileService = $injector.get(widgetContext.servicesMap.get('deviceProfileService'));\n\ngetDeviceFirmware();\n\nfunction getDeviceFirmware() {\n entityService.getEntity(entityId.entityType, entityId.id).subscribe(\n function (data) {\n if (data.firmwareId !== null) {\n otaPackageService.downloadOtaPackage(data.firmwareId.id).subscribe(); \n } else {\n deviceProfileService.getDeviceProfile(data.deviceProfileId.id).subscribe(\n function (deviceProfile) {\n if (deviceProfile.firmwareId !== null) {\n otaPackageService.downloadOtaPackage(deviceProfile.firmwareId.id).subscribe();\n } else {\n widgetContext.showToast('warn', 'Device ' + entityName +' has not firmware set.', 2000, 'top');\n\n }\n });\n }\n }\n );\n}",
1587 1588 "id": "12533058-42f6-e75f-620c-219c48d01ec0"
1588 1589 },
1589 1590 {
... ... @@ -1849,7 +1850,7 @@
1849 1850 "name": "Edit firmware",
1850 1851 "icon": "edit",
1851 1852 "type": "customPretty",
1852   - "customHtml": "<form #editEntityForm=\"ngForm\" [formGroup]=\"editEntityFormGroup\"\n (ngSubmit)=\"save()\" class=\"edit-entity-form\">\n <mat-toolbar fxLayout=\"row\" color=\"primary\">\n <h2>Edit firmware {{entityName}}</h2>\n <span fxFlex></span>\n <button mat-icon-button (click)=\"cancel()\" type=\"button\">\n <mat-icon class=\"material-icons\">close</mat-icon>\n </button>\n </mat-toolbar>\n <mat-progress-bar color=\"warn\" mode=\"indeterminate\" *ngIf=\"isLoading$ | async\">\n </mat-progress-bar>\n <div style=\"height: 4px;\" *ngIf=\"!(isLoading$ | async)\"></div>\n <div mat-dialog-content fxLayout=\"column\">\n <tb-firmware-autocomplete\n [useFullEntityId]=\"true\"\n formControlName=\"firmwareId\">\n </tb-firmware-autocomplete>\n </div>\n <div mat-dialog-actions fxLayout=\"row\" fxLayoutAlign=\"end center\">\n <button mat-button color=\"primary\"\n type=\"button\"\n [disabled]=\"(isLoading$ | async)\"\n (click)=\"cancel()\" cdkFocusInitial>\n Cancel\n </button>\n <button mat-button mat-raised-button color=\"primary\"\n type=\"submit\"\n [disabled]=\"(isLoading$ | async) || editEntityForm.invalid || !editEntityForm.dirty\">\n Save\n </button>\n </div>\n</form>",
  1853 + "customHtml": "<form #editEntityForm=\"ngForm\" [formGroup]=\"editEntityFormGroup\"\n (ngSubmit)=\"save()\" class=\"edit-entity-form\">\n <mat-toolbar fxLayout=\"row\" color=\"primary\">\n <h2>Edit firmware {{entityName}}</h2>\n <span fxFlex></span>\n <button mat-icon-button (click)=\"cancel()\" type=\"button\">\n <mat-icon class=\"material-icons\">close</mat-icon>\n </button>\n </mat-toolbar>\n <mat-progress-bar color=\"warn\" mode=\"indeterminate\" *ngIf=\"isLoading$ | async\">\n </mat-progress-bar>\n <div style=\"height: 4px;\" *ngIf=\"!(isLoading$ | async)\"></div>\n <div *ngIf=\"entity.deviceProfileId\" mat-dialog-content fxLayout=\"column\">\n <tb-ota-package-autocomplete\n [useFullEntityId]=\"true\"\n [deviceProfileId]=\"entity.deviceProfileId.id\"\n formControlName=\"firmwareId\">\n </tb-ota-package-autocomplete>\n </div>\n <div mat-dialog-actions fxLayout=\"row\" fxLayoutAlign=\"end center\">\n <button mat-button color=\"primary\"\n type=\"button\"\n [disabled]=\"(isLoading$ | async)\"\n (click)=\"cancel()\" cdkFocusInitial>\n Cancel\n </button>\n <button mat-button mat-raised-button color=\"primary\"\n type=\"submit\"\n [disabled]=\"(isLoading$ | async) || editEntityForm.invalid || !editEntityForm.dirty\">\n Save\n </button>\n </div>\n</form>",
1853 1854 "customCss": "",
1854 1855 "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet customDialog = $injector.get(widgetContext.servicesMap.get('customDialog'));\nlet entityService = $injector.get(widgetContext.servicesMap.get('entityService'));\nlet deviceService = $injector.get(widgetContext.servicesMap.get('deviceService'));\n\nopenEditEntityDialog();\n\nfunction openEditEntityDialog() {\n customDialog.customDialog(htmlTemplate, EditEntityDialogController).subscribe();\n}\n\nfunction EditEntityDialogController(instance) {\n let vm = instance;\n\n vm.entityName = entityName;\n vm.entity = {};\n\n vm.editEntityFormGroup = vm.fb.group({\n firmwareId: [null]\n });\n\n getEntityInfo();\n\n vm.cancel = function() {\n vm.dialogRef.close(null);\n };\n\n vm.save = function() {\n vm.editEntityFormGroup.markAsPristine();\n saveEntity().subscribe(\n function () {\n // widgetContext.updateAliases();\n vm.dialogRef.close(null);\n }\n );\n };\n\n\n function getEntityInfo() {\n entityService.getEntity(entityId.entityType, entityId.id).subscribe(\n function (data) {\n vm.entity = data;\n vm.editEntityFormGroup.patchValue({\n firmwareId: vm.entity.firmwareId\n }, {emitEvent: false});\n }\n );\n }\n\n function saveEntity() {\n const formValues = vm.editEntityFormGroup.value;\n vm.entity.firmwareId = formValues.firmwareId;\n return deviceService.saveDevice(vm.entity);\n }\n}",
1855 1856 "customResources": [],
... ... @@ -1859,7 +1860,7 @@
1859 1860 "name": "Download firware",
1860 1861 "icon": "file_download",
1861 1862 "type": "custom",
1862   - "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet entityService = $injector.get(widgetContext.servicesMap.get('entityService'));\nlet firmwareService = $injector.get(widgetContext.servicesMap.get('firmwareService'));\nlet deviceProfileService = $injector.get(widgetContext.servicesMap.get('deviceProfileService'));\n\ngetDeviceFirmware();\n\nfunction getDeviceFirmware() {\n entityService.getEntity(entityId.entityType, entityId.id).subscribe(\n function (data) {\n if (data.firmwareId !== null) {\n firmwareService.downloadFirmware(data.firmwareId.id).subscribe(); \n } else {\n deviceProfileService.getDeviceProfile(data.deviceProfileId.id).subscribe(\n function (deviceProfile) {\n if (deviceProfile.firmwareId !== null) {\n firmwareService.downloadFirmware(deviceProfile.firmwareId.id).subscribe();\n } else {\n widgetContext.showToast('warn', 'Device ' + entityName +' has not firmware set.', 2000, 'top');\n\n }\n });\n }\n }\n );\n}",
  1863 + "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet entityService = $injector.get(widgetContext.servicesMap.get('entityService'));\nlet otaPackageService = $injector.get(widgetContext.servicesMap.get('otaPackageService'));\nlet deviceProfileService = $injector.get(widgetContext.servicesMap.get('deviceProfileService'));\n\ngetDeviceFirmware();\n\nfunction getDeviceFirmware() {\n entityService.getEntity(entityId.entityType, entityId.id).subscribe(\n function (data) {\n if (data.firmwareId !== null) {\n otaPackageService.downloadOtaPackage(data.firmwareId.id).subscribe(); \n } else {\n deviceProfileService.getDeviceProfile(data.deviceProfileId.id).subscribe(\n function (deviceProfile) {\n if (deviceProfile.firmwareId !== null) {\n otaPackageService.downloadOtaPackage(deviceProfile.firmwareId.id).subscribe();\n } else {\n widgetContext.showToast('warn', 'Device ' + entityName +' has not firmware set.', 2000, 'top');\n\n }\n });\n }\n }\n );\n}",
1863 1864 "id": "12533058-42f6-e75f-620c-219c48d01ec0"
1864 1865 },
1865 1866 {
... ...
... ... @@ -59,8 +59,8 @@ CREATE TABLE IF NOT EXISTS resource (
59 59 CONSTRAINT resource_unq_key UNIQUE (tenant_id, resource_type, resource_key)
60 60 );
61 61
62   -CREATE TABLE IF NOT EXISTS firmware (
63   - id uuid NOT NULL CONSTRAINT firmware_pkey PRIMARY KEY,
  62 +CREATE TABLE IF NOT EXISTS ota_package (
  63 + id uuid NOT NULL CONSTRAINT ota_package_pkey PRIMARY KEY,
64 64 created_time bigint NOT NULL,
65 65 tenant_id uuid NOT NULL,
66 66 device_profile_id uuid,
... ... @@ -75,7 +75,7 @@ CREATE TABLE IF NOT EXISTS firmware (
75 75 data_size bigint,
76 76 additional_info varchar,
77 77 search_text varchar(255),
78   - CONSTRAINT firmware_tenant_title_version_unq_key UNIQUE (tenant_id, title, version)
  78 + CONSTRAINT ota_package_tenant_title_version_unq_key UNIQUE (tenant_id, title, version)
79 79 );
80 80
81 81 ALTER TABLE dashboard
... ... @@ -101,13 +101,13 @@ DO $$
101 101 IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_firmware_device_profile') THEN
102 102 ALTER TABLE device_profile
103 103 ADD CONSTRAINT fk_firmware_device_profile
104   - FOREIGN KEY (firmware_id) REFERENCES firmware(id);
  104 + FOREIGN KEY (firmware_id) REFERENCES ota_package(id);
105 105 END IF;
106 106
107 107 IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_software_device_profile') THEN
108 108 ALTER TABLE device_profile
109 109 ADD CONSTRAINT fk_software_device_profile
110   - FOREIGN KEY (firmware_id) REFERENCES firmware(id);
  110 + FOREIGN KEY (firmware_id) REFERENCES ota_package(id);
111 111 END IF;
112 112
113 113 IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_default_dashboard_device_profile') THEN
... ... @@ -119,13 +119,13 @@ DO $$
119 119 IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_firmware_device') THEN
120 120 ALTER TABLE device
121 121 ADD CONSTRAINT fk_firmware_device
122   - FOREIGN KEY (firmware_id) REFERENCES firmware(id);
  122 + FOREIGN KEY (firmware_id) REFERENCES ota_package(id);
123 123 END IF;
124 124
125 125 IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_software_device') THEN
126 126 ALTER TABLE device
127 127 ADD CONSTRAINT fk_software_device
128   - FOREIGN KEY (firmware_id) REFERENCES firmware(id);
  128 + FOREIGN KEY (firmware_id) REFERENCES ota_package(id);
129 129 END IF;
130 130 END;
131 131 $$;
... ...
... ... @@ -317,25 +317,48 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor {
317 317
318 318 private void handleGetAttributesRequest(TbActorCtx context, SessionInfoProto sessionInfo, GetAttributeRequestMsg request) {
319 319 int requestId = request.getRequestId();
320   - Futures.addCallback(getAttributesKvEntries(request), new FutureCallback<List<List<AttributeKvEntry>>>() {
321   - @Override
322   - public void onSuccess(@Nullable List<List<AttributeKvEntry>> result) {
323   - GetAttributeResponseMsg responseMsg = GetAttributeResponseMsg.newBuilder()
324   - .setRequestId(requestId)
325   - .addAllClientAttributeList(toTsKvProtos(result.get(0)))
326   - .addAllSharedAttributeList(toTsKvProtos(result.get(1)))
327   - .build();
328   - sendToTransport(responseMsg, sessionInfo);
329   - }
  320 + if (request.getOnlyShared()) {
  321 + Futures.addCallback(findAllAttributesByScope(DataConstants.SHARED_SCOPE), new FutureCallback<>() {
  322 + @Override
  323 + public void onSuccess(@Nullable List<AttributeKvEntry> result) {
  324 + GetAttributeResponseMsg responseMsg = GetAttributeResponseMsg.newBuilder()
  325 + .setRequestId(requestId)
  326 + .setSharedStateMsg(true)
  327 + .addAllSharedAttributeList(toTsKvProtos(result))
  328 + .build();
  329 + sendToTransport(responseMsg, sessionInfo);
  330 + }
330 331
331   - @Override
332   - public void onFailure(Throwable t) {
333   - GetAttributeResponseMsg responseMsg = GetAttributeResponseMsg.newBuilder()
334   - .setError(t.getMessage())
335   - .build();
336   - sendToTransport(responseMsg, sessionInfo);
337   - }
338   - }, MoreExecutors.directExecutor());
  332 + @Override
  333 + public void onFailure(Throwable t) {
  334 + GetAttributeResponseMsg responseMsg = GetAttributeResponseMsg.newBuilder()
  335 + .setError(t.getMessage())
  336 + .setSharedStateMsg(true)
  337 + .build();
  338 + sendToTransport(responseMsg, sessionInfo);
  339 + }
  340 + }, MoreExecutors.directExecutor());
  341 + } else {
  342 + Futures.addCallback(getAttributesKvEntries(request), new FutureCallback<>() {
  343 + @Override
  344 + public void onSuccess(@Nullable List<List<AttributeKvEntry>> result) {
  345 + GetAttributeResponseMsg responseMsg = GetAttributeResponseMsg.newBuilder()
  346 + .setRequestId(requestId)
  347 + .addAllClientAttributeList(toTsKvProtos(result.get(0)))
  348 + .addAllSharedAttributeList(toTsKvProtos(result.get(1)))
  349 + .build();
  350 + sendToTransport(responseMsg, sessionInfo);
  351 + }
  352 +
  353 + @Override
  354 + public void onFailure(Throwable t) {
  355 + GetAttributeResponseMsg responseMsg = GetAttributeResponseMsg.newBuilder()
  356 + .setError(t.getMessage())
  357 + .build();
  358 + sendToTransport(responseMsg, sessionInfo);
  359 + }
  360 + }, MoreExecutors.directExecutor());
  361 + }
339 362 }
340 363
341 364 private ListenableFuture<List<List<AttributeKvEntry>>> getAttributesKvEntries(GetAttributeRequestMsg request) {
... ... @@ -403,9 +426,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor {
403 426 }
404 427 if (hasNotificationData) {
405 428 AttributeUpdateNotificationMsg finalNotification = notification.build();
406   - attributeSubscriptions.entrySet().forEach(sub -> {
407   - sendToTransport(finalNotification, sub.getKey(), sub.getValue().getNodeId());
408   - });
  429 + attributeSubscriptions.forEach((key, value) -> sendToTransport(finalNotification, key, value.getNodeId()));
409 430 }
410 431 } else {
411 432 log.debug("[{}] No registered attributes subscriptions to process!", deviceId);
... ... @@ -475,7 +496,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor {
475 496 if (sessions.size() >= systemContext.getMaxConcurrentSessionsPerDevice()) {
476 497 UUID sessionIdToRemove = sessions.keySet().stream().findFirst().orElse(null);
477 498 if (sessionIdToRemove != null) {
478   - notifyTransportAboutClosedSession(sessionIdToRemove, sessions.remove(sessionIdToRemove));
  499 + notifyTransportAboutClosedSession(sessionIdToRemove, sessions.remove(sessionIdToRemove), "max concurrent sessions limit reached per device!");
479 500 }
480 501 }
481 502 sessions.put(sessionId, new SessionInfoMetaData(new SessionInfo(SessionType.ASYNC, sessionInfo.getNodeId())));
... ... @@ -521,7 +542,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor {
521 542 notifyTransportAboutProfileUpdate(k, v, ((DeviceCredentialsUpdateNotificationMsg) msg).getDeviceCredentials());
522 543 });
523 544 } else {
524   - sessions.forEach(this::notifyTransportAboutClosedSession);
  545 + sessions.forEach((sessionId, sessionMd) -> notifyTransportAboutClosedSession(sessionId, sessionMd, "device credentials updated!"));
525 546 attributeSubscriptions.clear();
526 547 rpcSubscriptions.clear();
527 548 dumpSessions();
... ... @@ -529,11 +550,15 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor {
529 550 }
530 551 }
531 552
532   - private void notifyTransportAboutClosedSession(UUID sessionId, SessionInfoMetaData sessionMd) {
  553 + private void notifyTransportAboutClosedSession(UUID sessionId, SessionInfoMetaData sessionMd, String message) {
  554 + SessionCloseNotificationProto sessionCloseNotificationProto = SessionCloseNotificationProto
  555 + .newBuilder()
  556 + .setMessage(message).build();
533 557 ToTransportMsg msg = ToTransportMsg.newBuilder()
534 558 .setSessionIdMSB(sessionId.getMostSignificantBits())
535 559 .setSessionIdLSB(sessionId.getLeastSignificantBits())
536   - .setSessionCloseNotification(SessionCloseNotificationProto.getDefaultInstance()).build();
  560 + .setSessionCloseNotification(sessionCloseNotificationProto)
  561 + .build();
537 562 systemContext.getTbCoreToTransportService().process(sessionMd.getSessionInfo().getNodeId(), msg);
538 563 }
539 564
... ... @@ -741,7 +766,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor {
741 766 sessions.remove(sessionId);
742 767 rpcSubscriptions.remove(sessionId);
743 768 attributeSubscriptions.remove(sessionId);
744   - notifyTransportAboutClosedSession(sessionId, sessionMD);
  769 + notifyTransportAboutClosedSession(sessionId, sessionMD, "session timeout!");
745 770 });
746 771 if (!sessionsToRemove.isEmpty()) {
747 772 dumpSessions();
... ...
... ... @@ -110,8 +110,11 @@ public class AlarmController extends BaseController {
110 110 checkParameter(ALARM_ID, strAlarmId);
111 111 try {
112 112 AlarmId alarmId = new AlarmId(toUUID(strAlarmId));
113   - checkAlarmId(alarmId, Operation.WRITE);
  113 + Alarm alarm = checkAlarmId(alarmId, Operation.WRITE);
114 114
  115 + logEntityAction(alarm.getOriginator(), alarm,
  116 + getCurrentUser().getCustomerId(),
  117 + ActionType.ALARM_DELETE, null);
115 118 sendEntityNotificationMsg(getTenantId(), alarmId, EdgeEventActionType.DELETED);
116 119
117 120 return alarmService.deleteAlarm(getTenantId(), alarmId);
... ...
... ... @@ -17,7 +17,6 @@ package org.thingsboard.server.controller;
17 17
18 18 import com.fasterxml.jackson.core.JsonProcessingException;
19 19 import com.fasterxml.jackson.databind.ObjectMapper;
20   -import com.fasterxml.jackson.databind.node.ArrayNode;
21 20 import com.fasterxml.jackson.databind.node.ObjectNode;
22 21 import lombok.Getter;
23 22 import lombok.extern.slf4j.Slf4j;
... ... @@ -31,7 +30,6 @@ import org.springframework.web.bind.annotation.ExceptionHandler;
31 30 import org.thingsboard.server.common.data.Customer;
32 31 import org.thingsboard.server.common.data.Dashboard;
33 32 import org.thingsboard.server.common.data.DashboardInfo;
34   -import org.thingsboard.server.common.data.DataConstants;
35 33 import org.thingsboard.server.common.data.Device;
36 34 import org.thingsboard.server.common.data.DeviceInfo;
37 35 import org.thingsboard.server.common.data.DeviceProfile;
... ... @@ -39,8 +37,8 @@ import org.thingsboard.server.common.data.EdgeUtils;
39 37 import org.thingsboard.server.common.data.EntityType;
40 38 import org.thingsboard.server.common.data.EntityView;
41 39 import org.thingsboard.server.common.data.EntityViewInfo;
42   -import org.thingsboard.server.common.data.Firmware;
43   -import org.thingsboard.server.common.data.FirmwareInfo;
  40 +import org.thingsboard.server.common.data.OtaPackage;
  41 +import org.thingsboard.server.common.data.OtaPackageInfo;
44 42 import org.thingsboard.server.common.data.HasName;
45 43 import org.thingsboard.server.common.data.HasTenantId;
46 44 import org.thingsboard.server.common.data.TbResourceInfo;
... ... @@ -70,7 +68,7 @@ import org.thingsboard.server.common.data.id.EdgeId;
70 68 import org.thingsboard.server.common.data.id.EntityId;
71 69 import org.thingsboard.server.common.data.id.EntityIdFactory;
72 70 import org.thingsboard.server.common.data.id.EntityViewId;
73   -import org.thingsboard.server.common.data.id.FirmwareId;
  71 +import org.thingsboard.server.common.data.id.OtaPackageId;
74 72 import org.thingsboard.server.common.data.id.TbResourceId;
75 73 import org.thingsboard.server.common.data.id.RuleChainId;
76 74 import org.thingsboard.server.common.data.id.RuleNodeId;
... ... @@ -79,10 +77,6 @@ import org.thingsboard.server.common.data.id.TenantProfileId;
79 77 import org.thingsboard.server.common.data.id.UserId;
80 78 import org.thingsboard.server.common.data.id.WidgetTypeId;
81 79 import org.thingsboard.server.common.data.id.WidgetsBundleId;
82   -import org.thingsboard.server.common.data.kv.AttributeKvEntry;
83   -import org.thingsboard.server.common.data.kv.DataType;
84   -import org.thingsboard.server.common.data.kv.KvEntry;
85   -import org.thingsboard.server.common.data.kv.TsKvEntry;
86 80 import org.thingsboard.server.common.data.page.PageLink;
87 81 import org.thingsboard.server.common.data.page.SortOrder;
88 82 import org.thingsboard.server.common.data.page.TimePageLink;
... ... @@ -94,9 +88,6 @@ import org.thingsboard.server.common.data.rule.RuleChainType;
94 88 import org.thingsboard.server.common.data.rule.RuleNode;
95 89 import org.thingsboard.server.common.data.widget.WidgetTypeDetails;
96 90 import org.thingsboard.server.common.data.widget.WidgetsBundle;
97   -import org.thingsboard.server.common.msg.TbMsg;
98   -import org.thingsboard.server.common.msg.TbMsgDataType;
99   -import org.thingsboard.server.common.msg.TbMsgMetaData;
100 91 import org.thingsboard.server.dao.asset.AssetService;
101 92 import org.thingsboard.server.dao.attributes.AttributesService;
102 93 import org.thingsboard.server.dao.audit.AuditLogService;
... ... @@ -110,7 +101,7 @@ import org.thingsboard.server.dao.edge.EdgeService;
110 101 import org.thingsboard.server.dao.entityview.EntityViewService;
111 102 import org.thingsboard.server.dao.exception.DataValidationException;
112 103 import org.thingsboard.server.dao.exception.IncorrectParameterException;
113   -import org.thingsboard.server.dao.firmware.FirmwareService;
  104 +import org.thingsboard.server.dao.ota.OtaPackageService;
114 105 import org.thingsboard.server.dao.model.ModelConstants;
115 106 import org.thingsboard.server.dao.oauth2.OAuth2ConfigTemplateService;
116 107 import org.thingsboard.server.dao.oauth2.OAuth2Service;
... ... @@ -127,8 +118,9 @@ import org.thingsboard.server.gen.transport.TransportProtos;
127 118 import org.thingsboard.server.queue.discovery.PartitionService;
128 119 import org.thingsboard.server.queue.provider.TbQueueProducerProvider;
129 120 import org.thingsboard.server.queue.util.TbCoreComponent;
  121 +import org.thingsboard.server.service.action.RuleEngineEntityActionService;
130 122 import org.thingsboard.server.service.component.ComponentDiscoveryService;
131   -import org.thingsboard.server.service.firmware.FirmwareStateService;
  123 +import org.thingsboard.server.service.ota.OtaPackageStateService;
132 124 import org.thingsboard.server.service.edge.EdgeNotificationService;
133 125 import org.thingsboard.server.service.edge.rpc.EdgeGrpcService;
134 126 import org.thingsboard.server.service.edge.rpc.init.SyncEdgeService;
... ... @@ -147,11 +139,9 @@ import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService;
147 139 import javax.mail.MessagingException;
148 140 import javax.servlet.http.HttpServletResponse;
149 141 import java.util.List;
150   -import java.util.Map;
151 142 import java.util.Optional;
152 143 import java.util.Set;
153 144 import java.util.UUID;
154   -import java.util.stream.Collectors;
155 145
156 146 import static org.thingsboard.server.dao.service.Validator.validateId;
157 147
... ... @@ -250,10 +240,10 @@ public abstract class BaseController {
250 240 protected TbResourceService resourceService;
251 241
252 242 @Autowired
253   - protected FirmwareService firmwareService;
  243 + protected OtaPackageService otaPackageService;
254 244
255 245 @Autowired
256   - protected FirmwareStateService firmwareStateService;
  246 + protected OtaPackageStateService otaPackageStateService;
257 247
258 248 @Autowired
259 249 protected TbQueueProducerProvider producerProvider;
... ... @@ -279,6 +269,9 @@ public abstract class BaseController {
279 269 @Autowired(required = false)
280 270 protected EdgeGrpcService edgeGrpcService;
281 271
  272 + @Autowired
  273 + protected RuleEngineEntityActionService ruleEngineEntityActionService;
  274 +
282 275 @Value("${server.log_controller_error_stack_trace}")
283 276 @Getter
284 277 private boolean logControllerErrorStackTrace;
... ... @@ -511,8 +504,8 @@ public abstract class BaseController {
511 504 case TB_RESOURCE:
512 505 checkResourceId(new TbResourceId(entityId.getId()), operation);
513 506 return;
514   - case FIRMWARE:
515   - checkFirmwareId(new FirmwareId(entityId.getId()), operation);
  507 + case OTA_PACKAGE:
  508 + checkOtaPackageId(new OtaPackageId(entityId.getId()), operation);
516 509 return;
517 510 default:
518 511 throw new IllegalArgumentException("Unsupported entity type: " + entityId.getEntityType());
... ... @@ -769,25 +762,25 @@ public abstract class BaseController {
769 762 }
770 763 }
771 764
772   - Firmware checkFirmwareId(FirmwareId firmwareId, Operation operation) throws ThingsboardException {
  765 + OtaPackage checkOtaPackageId(OtaPackageId otaPackageId, Operation operation) throws ThingsboardException {
773 766 try {
774   - validateId(firmwareId, "Incorrect firmwareId " + firmwareId);
775   - Firmware firmware = firmwareService.findFirmwareById(getCurrentUser().getTenantId(), firmwareId);
776   - checkNotNull(firmware);
777   - accessControlService.checkPermission(getCurrentUser(), Resource.FIRMWARE, operation, firmwareId, firmware);
778   - return firmware;
  767 + validateId(otaPackageId, "Incorrect otaPackageId " + otaPackageId);
  768 + OtaPackage otaPackage = otaPackageService.findOtaPackageById(getCurrentUser().getTenantId(), otaPackageId);
  769 + checkNotNull(otaPackage);
  770 + accessControlService.checkPermission(getCurrentUser(), Resource.OTA_PACKAGE, operation, otaPackageId, otaPackage);
  771 + return otaPackage;
779 772 } catch (Exception e) {
780 773 throw handleException(e, false);
781 774 }
782 775 }
783 776
784   - FirmwareInfo checkFirmwareInfoId(FirmwareId firmwareId, Operation operation) throws ThingsboardException {
  777 + OtaPackageInfo checkOtaPackageInfoId(OtaPackageId otaPackageId, Operation operation) throws ThingsboardException {
785 778 try {
786   - validateId(firmwareId, "Incorrect firmwareId " + firmwareId);
787   - FirmwareInfo firmwareInfo = firmwareService.findFirmwareInfoById(getCurrentUser().getTenantId(), firmwareId);
788   - checkNotNull(firmwareInfo);
789   - accessControlService.checkPermission(getCurrentUser(), Resource.FIRMWARE, operation, firmwareId, firmwareInfo);
790   - return firmwareInfo;
  779 + validateId(otaPackageId, "Incorrect otaPackageId " + otaPackageId);
  780 + OtaPackageInfo otaPackageIn = otaPackageService.findOtaPackageInfoById(getCurrentUser().getTenantId(), otaPackageId);
  781 + checkNotNull(otaPackageIn);
  782 + accessControlService.checkPermission(getCurrentUser(), Resource.OTA_PACKAGE, operation, otaPackageId, otaPackageIn);
  783 + return otaPackageIn;
791 784 } catch (Exception e) {
792 785 throw handleException(e, false);
793 786 }
... ... @@ -809,7 +802,7 @@ public abstract class BaseController {
809 802 customerId = user.getCustomerId();
810 803 }
811 804 if (e == null) {
812   - pushEntityActionToRuleEngine(entityId, entity, user, customerId, actionType, additionalInfo);
  805 + ruleEngineEntityActionService.pushEntityActionToRuleEngine(entityId, entity, user.getTenantId(), customerId, actionType, user, additionalInfo);
813 806 }
814 807 auditLogService.logEntityAction(user.getTenantId(), customerId, user.getId(), user.getName(), entityId, entity, actionType, e, additionalInfo);
815 808 }
... ... @@ -819,184 +812,6 @@ public abstract class BaseController {
819 812 return error != null ? (Exception.class.isInstance(error) ? (Exception) error : new Exception(error)) : null;
820 813 }
821 814
822   - private <E extends HasName, I extends EntityId> void pushEntityActionToRuleEngine(I entityId, E entity, User user, CustomerId customerId,
823   - ActionType actionType, Object... additionalInfo) {
824   - String msgType = null;
825   - switch (actionType) {
826   - case ADDED:
827   - msgType = DataConstants.ENTITY_CREATED;
828   - break;
829   - case DELETED:
830   - msgType = DataConstants.ENTITY_DELETED;
831   - break;
832   - case UPDATED:
833   - msgType = DataConstants.ENTITY_UPDATED;
834   - break;
835   - case ASSIGNED_TO_CUSTOMER:
836   - msgType = DataConstants.ENTITY_ASSIGNED;
837   - break;
838   - case UNASSIGNED_FROM_CUSTOMER:
839   - msgType = DataConstants.ENTITY_UNASSIGNED;
840   - break;
841   - case ATTRIBUTES_UPDATED:
842   - msgType = DataConstants.ATTRIBUTES_UPDATED;
843   - break;
844   - case ATTRIBUTES_DELETED:
845   - msgType = DataConstants.ATTRIBUTES_DELETED;
846   - break;
847   - case ALARM_ACK:
848   - msgType = DataConstants.ALARM_ACK;
849   - break;
850   - case ALARM_CLEAR:
851   - msgType = DataConstants.ALARM_CLEAR;
852   - break;
853   - case ASSIGNED_FROM_TENANT:
854   - msgType = DataConstants.ENTITY_ASSIGNED_FROM_TENANT;
855   - break;
856   - case ASSIGNED_TO_TENANT:
857   - msgType = DataConstants.ENTITY_ASSIGNED_TO_TENANT;
858   - break;
859   - case PROVISION_SUCCESS:
860   - msgType = DataConstants.PROVISION_SUCCESS;
861   - break;
862   - case PROVISION_FAILURE:
863   - msgType = DataConstants.PROVISION_FAILURE;
864   - break;
865   - case TIMESERIES_UPDATED:
866   - msgType = DataConstants.TIMESERIES_UPDATED;
867   - break;
868   - case TIMESERIES_DELETED:
869   - msgType = DataConstants.TIMESERIES_DELETED;
870   - break;
871   - case ASSIGNED_TO_EDGE:
872   - msgType = DataConstants.ENTITY_ASSIGNED_TO_EDGE;
873   - break;
874   - case UNASSIGNED_FROM_EDGE:
875   - msgType = DataConstants.ENTITY_UNASSIGNED_FROM_EDGE;
876   - break;
877   - }
878   - if (!StringUtils.isEmpty(msgType)) {
879   - try {
880   - TbMsgMetaData metaData = new TbMsgMetaData();
881   - metaData.putValue("userId", user.getId().toString());
882   - metaData.putValue("userName", user.getName());
883   - if (customerId != null && !customerId.isNullUid()) {
884   - metaData.putValue("customerId", customerId.toString());
885   - }
886   - if (actionType == ActionType.ASSIGNED_TO_CUSTOMER) {
887   - String strCustomerId = extractParameter(String.class, 1, additionalInfo);
888   - String strCustomerName = extractParameter(String.class, 2, additionalInfo);
889   - metaData.putValue("assignedCustomerId", strCustomerId);
890   - metaData.putValue("assignedCustomerName", strCustomerName);
891   - } else if (actionType == ActionType.UNASSIGNED_FROM_CUSTOMER) {
892   - String strCustomerId = extractParameter(String.class, 1, additionalInfo);
893   - String strCustomerName = extractParameter(String.class, 2, additionalInfo);
894   - metaData.putValue("unassignedCustomerId", strCustomerId);
895   - metaData.putValue("unassignedCustomerName", strCustomerName);
896   - } else if (actionType == ActionType.ASSIGNED_FROM_TENANT) {
897   - String strTenantId = extractParameter(String.class, 0, additionalInfo);
898   - String strTenantName = extractParameter(String.class, 1, additionalInfo);
899   - metaData.putValue("assignedFromTenantId", strTenantId);
900   - metaData.putValue("assignedFromTenantName", strTenantName);
901   - } else if (actionType == ActionType.ASSIGNED_TO_TENANT) {
902   - String strTenantId = extractParameter(String.class, 0, additionalInfo);
903   - String strTenantName = extractParameter(String.class, 1, additionalInfo);
904   - metaData.putValue("assignedToTenantId", strTenantId);
905   - metaData.putValue("assignedToTenantName", strTenantName);
906   - } else if (actionType == ActionType.ASSIGNED_TO_EDGE) {
907   - String strEdgeId = extractParameter(String.class, 1, additionalInfo);
908   - String strEdgeName = extractParameter(String.class, 2, additionalInfo);
909   - metaData.putValue("assignedEdgeId", strEdgeId);
910   - metaData.putValue("assignedEdgeName", strEdgeName);
911   - } else if (actionType == ActionType.UNASSIGNED_FROM_EDGE) {
912   - String strEdgeId = extractParameter(String.class, 1, additionalInfo);
913   - String strEdgeName = extractParameter(String.class, 2, additionalInfo);
914   - metaData.putValue("unassignedEdgeId", strEdgeId);
915   - metaData.putValue("unassignedEdgeName", strEdgeName);
916   - }
917   - ObjectNode entityNode;
918   - if (entity != null) {
919   - entityNode = json.valueToTree(entity);
920   - if (entityId.getEntityType() == EntityType.DASHBOARD) {
921   - entityNode.put("configuration", "");
922   - }
923   - } else {
924   - entityNode = json.createObjectNode();
925   - if (actionType == ActionType.ATTRIBUTES_UPDATED) {
926   - String scope = extractParameter(String.class, 0, additionalInfo);
927   - @SuppressWarnings("unchecked")
928   - List<AttributeKvEntry> attributes = extractParameter(List.class, 1, additionalInfo);
929   - metaData.putValue(DataConstants.SCOPE, scope);
930   - if (attributes != null) {
931   - for (AttributeKvEntry attr : attributes) {
932   - addKvEntry(entityNode, attr);
933   - }
934   - }
935   - } else if (actionType == ActionType.ATTRIBUTES_DELETED) {
936   - String scope = extractParameter(String.class, 0, additionalInfo);
937   - @SuppressWarnings("unchecked")
938   - List<String> keys = extractParameter(List.class, 1, additionalInfo);
939   - metaData.putValue(DataConstants.SCOPE, scope);
940   - ArrayNode attrsArrayNode = entityNode.putArray("attributes");
941   - if (keys != null) {
942   - keys.forEach(attrsArrayNode::add);
943   - }
944   - } else if (actionType == ActionType.TIMESERIES_UPDATED) {
945   - @SuppressWarnings("unchecked")
946   - List<TsKvEntry> timeseries = extractParameter(List.class, 0, additionalInfo);
947   - addTimeseries(entityNode, timeseries);
948   - } else if (actionType == ActionType.TIMESERIES_DELETED) {
949   - @SuppressWarnings("unchecked")
950   - List<String> keys = extractParameter(List.class, 0, additionalInfo);
951   - if (keys != null) {
952   - ArrayNode timeseriesArrayNode = entityNode.putArray("timeseries");
953   - keys.forEach(timeseriesArrayNode::add);
954   - }
955   - entityNode.put("startTs", extractParameter(Long.class, 1, additionalInfo));
956   - entityNode.put("endTs", extractParameter(Long.class, 2, additionalInfo));
957   - }
958   - }
959   - TbMsg tbMsg = TbMsg.newMsg(msgType, entityId, customerId, metaData, TbMsgDataType.JSON, json.writeValueAsString(entityNode));
960   - TenantId tenantId = user.getTenantId();
961   - if (tenantId.isNullUid()) {
962   - if (entity instanceof HasTenantId) {
963   - tenantId = ((HasTenantId) entity).getTenantId();
964   - }
965   - }
966   - tbClusterService.pushMsgToRuleEngine(tenantId, entityId, tbMsg, null);
967   - } catch (Exception e) {
968   - log.warn("[{}] Failed to push entity action to rule engine: {}", entityId, actionType, e);
969   - }
970   - }
971   - }
972   -
973   - private void addKvEntry(ObjectNode entityNode, KvEntry kvEntry) throws Exception {
974   - if (kvEntry.getDataType() == DataType.BOOLEAN) {
975   - kvEntry.getBooleanValue().ifPresent(value -> entityNode.put(kvEntry.getKey(), value));
976   - } else if (kvEntry.getDataType() == DataType.DOUBLE) {
977   - kvEntry.getDoubleValue().ifPresent(value -> entityNode.put(kvEntry.getKey(), value));
978   - } else if (kvEntry.getDataType() == DataType.LONG) {
979   - kvEntry.getLongValue().ifPresent(value -> entityNode.put(kvEntry.getKey(), value));
980   - } else if (kvEntry.getDataType() == DataType.JSON) {
981   - if (kvEntry.getJsonValue().isPresent()) {
982   - entityNode.set(kvEntry.getKey(), json.readTree(kvEntry.getJsonValue().get()));
983   - }
984   - } else {
985   - entityNode.put(kvEntry.getKey(), kvEntry.getValueAsString());
986   - }
987   - }
988   -
989   - private <T> T extractParameter(Class<T> clazz, int index, Object... additionalInfo) {
990   - T result = null;
991   - if (additionalInfo != null && additionalInfo.length > index) {
992   - Object paramObject = additionalInfo[index];
993   - if (clazz.isInstance(paramObject)) {
994   - result = clazz.cast(paramObject);
995   - }
996   - }
997   - return result;
998   - }
999   -
1000 815 protected <E extends HasName> String entityToStr(E entity) {
1001 816 try {
1002 817 return json.writeValueAsString(json.valueToTree(entity));
... ... @@ -1093,23 +908,6 @@ public abstract class BaseController {
1093 908 return result;
1094 909 }
1095 910
1096   - private void addTimeseries(ObjectNode entityNode, List<TsKvEntry> timeseries) throws Exception {
1097   - if (timeseries != null && !timeseries.isEmpty()) {
1098   - ArrayNode result = entityNode.putArray("timeseries");
1099   - Map<Long, List<TsKvEntry>> groupedTelemetry = timeseries.stream()
1100   - .collect(Collectors.groupingBy(TsKvEntry::getTs));
1101   - for (Map.Entry<Long, List<TsKvEntry>> entry : groupedTelemetry.entrySet()) {
1102   - ObjectNode element = json.createObjectNode();
1103   - element.put("ts", entry.getKey());
1104   - ObjectNode values = element.putObject("values");
1105   - for (TsKvEntry tsKvEntry : entry.getValue()) {
1106   - addKvEntry(values, tsKvEntry);
1107   - }
1108   - result.add(element);
1109   - }
1110   - }
1111   - }
1112   -
1113 911 protected void processDashboardIdFromAdditionalInfo(ObjectNode additionalInfo, String requiredFields) throws ThingsboardException {
1114 912 String dashboardId = additionalInfo.has(requiredFields) ? additionalInfo.get(requiredFields).asText() : null;
1115 913 if (dashboardId != null && !dashboardId.equals("null")) {
... ...
... ... @@ -53,6 +53,7 @@ import org.thingsboard.server.common.data.id.DeviceId;
53 53 import org.thingsboard.server.common.data.id.DeviceProfileId;
54 54 import org.thingsboard.server.common.data.id.EdgeId;
55 55 import org.thingsboard.server.common.data.id.TenantId;
  56 +import org.thingsboard.server.common.data.ota.OtaPackageType;
56 57 import org.thingsboard.server.common.data.page.PageData;
57 58 import org.thingsboard.server.common.data.page.PageLink;
58 59 import org.thingsboard.server.common.data.page.TimePageLink;
... ... @@ -75,6 +76,7 @@ import javax.annotation.Nullable;
75 76 import java.io.IOException;
76 77 import java.util.ArrayList;
77 78 import java.util.List;
  79 +import java.util.UUID;
78 80 import java.util.stream.Collectors;
79 81
80 82 import static org.thingsboard.server.controller.EdgeController.EDGE_ID;
... ... @@ -153,7 +155,7 @@ public class DeviceController extends BaseController {
153 155 deviceStateService.onDeviceUpdated(savedDevice);
154 156 }
155 157
156   - firmwareStateService.update(savedDevice, oldDevice);
  158 + otaPackageStateService.update(savedDevice, oldDevice);
157 159
158 160 return savedDevice;
159 161 } catch (Exception e) {
... ... @@ -778,4 +780,19 @@ public class DeviceController extends BaseController {
778 780 throw handleException(e);
779 781 }
780 782 }
  783 +
  784 + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
  785 + @RequestMapping(value = "/devices/count/{otaPackageType}", method = RequestMethod.GET)
  786 + @ResponseBody
  787 + public Long countDevicesByTenantIdAndDeviceProfileIdAndEmptyOtaPackage(@PathVariable("otaPackageType") String otaPackageType,
  788 + @RequestParam String deviceProfileId) throws ThingsboardException {
  789 + checkParameter("OtaPackageType", otaPackageType);
  790 + checkParameter("DeviceProfileId", deviceProfileId);
  791 + try {
  792 + return deviceService.countDevicesByTenantIdAndDeviceProfileIdAndEmptyOtaPackage(
  793 + getCurrentUser().getTenantId(), new DeviceProfileId(UUID.fromString(deviceProfileId)), OtaPackageType.valueOf(otaPackageType));
  794 + } catch (Exception e) {
  795 + throw handleException(e);
  796 + }
  797 + }
781 798 }
... ...
... ... @@ -168,7 +168,7 @@ public class DeviceProfileController extends BaseController {
168 168 null,
169 169 created ? ActionType.ADDED : ActionType.UPDATED, null);
170 170
171   - firmwareStateService.update(savedDeviceProfile, isFirmwareChanged, isSoftwareChanged);
  171 + otaPackageStateService.update(savedDeviceProfile, isFirmwareChanged, isSoftwareChanged);
172 172
173 173 sendEntityNotificationMsg(getTenantId(), savedDeviceProfile.getId(),
174 174 deviceProfile.getId() == null ? EdgeEventActionType.ADDED : EdgeEventActionType.UPDATED);
... ...
application/src/main/java/org/thingsboard/server/controller/OtaPackageController.java renamed from application/src/main/java/org/thingsboard/server/controller/FirmwareController.java
... ... @@ -30,14 +30,14 @@ import org.springframework.web.bind.annotation.ResponseBody;
30 30 import org.springframework.web.bind.annotation.RestController;
31 31 import org.springframework.web.multipart.MultipartFile;
32 32 import org.thingsboard.server.common.data.EntityType;
33   -import org.thingsboard.server.common.data.Firmware;
34   -import org.thingsboard.server.common.data.FirmwareInfo;
  33 +import org.thingsboard.server.common.data.OtaPackage;
  34 +import org.thingsboard.server.common.data.OtaPackageInfo;
35 35 import org.thingsboard.server.common.data.audit.ActionType;
36 36 import org.thingsboard.server.common.data.exception.ThingsboardException;
37   -import org.thingsboard.server.common.data.firmware.ChecksumAlgorithm;
38   -import org.thingsboard.server.common.data.firmware.FirmwareType;
  37 +import org.thingsboard.server.common.data.ota.ChecksumAlgorithm;
  38 +import org.thingsboard.server.common.data.ota.OtaPackageType;
39 39 import org.thingsboard.server.common.data.id.DeviceProfileId;
40   -import org.thingsboard.server.common.data.id.FirmwareId;
  40 +import org.thingsboard.server.common.data.id.OtaPackageId;
41 41 import org.thingsboard.server.common.data.page.PageData;
42 42 import org.thingsboard.server.common.data.page.PageLink;
43 43 import org.thingsboard.server.queue.util.TbCoreComponent;
... ... @@ -50,26 +50,26 @@ import java.nio.ByteBuffer;
50 50 @RestController
51 51 @TbCoreComponent
52 52 @RequestMapping("/api")
53   -public class FirmwareController extends BaseController {
  53 +public class OtaPackageController extends BaseController {
54 54
55   - public static final String FIRMWARE_ID = "firmwareId";
  55 + public static final String OTA_PACKAGE_ID = "otaPackageId";
56 56 public static final String CHECKSUM_ALGORITHM = "checksumAlgorithm";
57 57
58 58 @PreAuthorize("hasAnyAuthority( 'TENANT_ADMIN')")
59   - @RequestMapping(value = "/firmware/{firmwareId}/download", method = RequestMethod.GET)
  59 + @RequestMapping(value = "/otaPackage/{otaPackageId}/download", method = RequestMethod.GET)
60 60 @ResponseBody
61   - public ResponseEntity<org.springframework.core.io.Resource> downloadFirmware(@PathVariable(FIRMWARE_ID) String strFirmwareId) throws ThingsboardException {
62   - checkParameter(FIRMWARE_ID, strFirmwareId);
  61 + public ResponseEntity<org.springframework.core.io.Resource> downloadOtaPackage(@PathVariable(OTA_PACKAGE_ID) String strOtaPackageId) throws ThingsboardException {
  62 + checkParameter(OTA_PACKAGE_ID, strOtaPackageId);
63 63 try {
64   - FirmwareId firmwareId = new FirmwareId(toUUID(strFirmwareId));
65   - Firmware firmware = checkFirmwareId(firmwareId, Operation.READ);
  64 + OtaPackageId otaPackageId = new OtaPackageId(toUUID(strOtaPackageId));
  65 + OtaPackage otaPackage = checkOtaPackageId(otaPackageId, Operation.READ);
66 66
67   - ByteArrayResource resource = new ByteArrayResource(firmware.getData().array());
  67 + ByteArrayResource resource = new ByteArrayResource(otaPackage.getData().array());
68 68 return ResponseEntity.ok()
69   - .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + firmware.getFileName())
70   - .header("x-filename", firmware.getFileName())
  69 + .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + otaPackage.getFileName())
  70 + .header("x-filename", otaPackage.getFileName())
71 71 .contentLength(resource.contentLength())
72   - .contentType(parseMediaType(firmware.getContentType()))
  72 + .contentType(parseMediaType(otaPackage.getContentType()))
73 73 .body(resource);
74 74 } catch (Exception e) {
75 75 throw handleException(e);
... ... @@ -77,144 +77,144 @@ public class FirmwareController extends BaseController {
77 77 }
78 78
79 79 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
80   - @RequestMapping(value = "/firmware/info/{firmwareId}", method = RequestMethod.GET)
  80 + @RequestMapping(value = "/otaPackage/info/{otaPackageId}", method = RequestMethod.GET)
81 81 @ResponseBody
82   - public FirmwareInfo getFirmwareInfoById(@PathVariable(FIRMWARE_ID) String strFirmwareId) throws ThingsboardException {
83   - checkParameter(FIRMWARE_ID, strFirmwareId);
  82 + public OtaPackageInfo getOtaPackageInfoById(@PathVariable(OTA_PACKAGE_ID) String strOtaPackageId) throws ThingsboardException {
  83 + checkParameter(OTA_PACKAGE_ID, strOtaPackageId);
84 84 try {
85   - FirmwareId firmwareId = new FirmwareId(toUUID(strFirmwareId));
86   - return checkNotNull(firmwareService.findFirmwareInfoById(getTenantId(), firmwareId));
  85 + OtaPackageId otaPackageId = new OtaPackageId(toUUID(strOtaPackageId));
  86 + return checkNotNull(otaPackageService.findOtaPackageInfoById(getTenantId(), otaPackageId));
87 87 } catch (Exception e) {
88 88 throw handleException(e);
89 89 }
90 90 }
91 91
92 92 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
93   - @RequestMapping(value = "/firmware/{firmwareId}", method = RequestMethod.GET)
  93 + @RequestMapping(value = "/otaPackage/{otaPackageId}", method = RequestMethod.GET)
94 94 @ResponseBody
95   - public Firmware getFirmwareById(@PathVariable(FIRMWARE_ID) String strFirmwareId) throws ThingsboardException {
96   - checkParameter(FIRMWARE_ID, strFirmwareId);
  95 + public OtaPackage getOtaPackageById(@PathVariable(OTA_PACKAGE_ID) String strOtaPackageId) throws ThingsboardException {
  96 + checkParameter(OTA_PACKAGE_ID, strOtaPackageId);
97 97 try {
98   - FirmwareId firmwareId = new FirmwareId(toUUID(strFirmwareId));
99   - return checkFirmwareId(firmwareId, Operation.READ);
  98 + OtaPackageId otaPackageId = new OtaPackageId(toUUID(strOtaPackageId));
  99 + return checkOtaPackageId(otaPackageId, Operation.READ);
100 100 } catch (Exception e) {
101 101 throw handleException(e);
102 102 }
103 103 }
104 104
105 105 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
106   - @RequestMapping(value = "/firmware", method = RequestMethod.POST)
  106 + @RequestMapping(value = "/otaPackage", method = RequestMethod.POST)
107 107 @ResponseBody
108   - public FirmwareInfo saveFirmwareInfo(@RequestBody FirmwareInfo firmwareInfo) throws ThingsboardException {
109   - boolean created = firmwareInfo.getId() == null;
  108 + public OtaPackageInfo saveOtaPackageInfo(@RequestBody OtaPackageInfo otaPackageInfo) throws ThingsboardException {
  109 + boolean created = otaPackageInfo.getId() == null;
110 110 try {
111   - firmwareInfo.setTenantId(getTenantId());
112   - checkEntity(firmwareInfo.getId(), firmwareInfo, Resource.FIRMWARE);
113   - FirmwareInfo savedFirmwareInfo = firmwareService.saveFirmwareInfo(firmwareInfo);
114   - logEntityAction(savedFirmwareInfo.getId(), savedFirmwareInfo,
  111 + otaPackageInfo.setTenantId(getTenantId());
  112 + checkEntity(otaPackageInfo.getId(), otaPackageInfo, Resource.OTA_PACKAGE);
  113 + OtaPackageInfo savedOtaPackageInfo = otaPackageService.saveOtaPackageInfo(otaPackageInfo);
  114 + logEntityAction(savedOtaPackageInfo.getId(), savedOtaPackageInfo,
115 115 null, created ? ActionType.ADDED : ActionType.UPDATED, null);
116   - return savedFirmwareInfo;
  116 + return savedOtaPackageInfo;
117 117 } catch (Exception e) {
118   - logEntityAction(emptyId(EntityType.FIRMWARE), firmwareInfo,
  118 + logEntityAction(emptyId(EntityType.OTA_PACKAGE), otaPackageInfo,
119 119 null, created ? ActionType.ADDED : ActionType.UPDATED, e);
120 120 throw handleException(e);
121 121 }
122 122 }
123 123
124 124 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
125   - @RequestMapping(value = "/firmware/{firmwareId}", method = RequestMethod.POST)
  125 + @RequestMapping(value = "/otaPackage/{otaPackageId}", method = RequestMethod.POST)
126 126 @ResponseBody
127   - public Firmware saveFirmwareData(@PathVariable(FIRMWARE_ID) String strFirmwareId,
128   - @RequestParam(required = false) String checksum,
129   - @RequestParam(CHECKSUM_ALGORITHM) String checksumAlgorithmStr,
130   - @RequestBody MultipartFile file) throws ThingsboardException {
131   - checkParameter(FIRMWARE_ID, strFirmwareId);
  127 + public OtaPackage saveOtaPackageData(@PathVariable(OTA_PACKAGE_ID) String strOtaPackageId,
  128 + @RequestParam(required = false) String checksum,
  129 + @RequestParam(CHECKSUM_ALGORITHM) String checksumAlgorithmStr,
  130 + @RequestBody MultipartFile file) throws ThingsboardException {
  131 + checkParameter(OTA_PACKAGE_ID, strOtaPackageId);
132 132 checkParameter(CHECKSUM_ALGORITHM, checksumAlgorithmStr);
133 133 try {
134   - FirmwareId firmwareId = new FirmwareId(toUUID(strFirmwareId));
135   - FirmwareInfo info = checkFirmwareInfoId(firmwareId, Operation.READ);
136   -
137   - Firmware firmware = new Firmware(firmwareId);
138   - firmware.setCreatedTime(info.getCreatedTime());
139   - firmware.setTenantId(getTenantId());
140   - firmware.setDeviceProfileId(info.getDeviceProfileId());
141   - firmware.setType(info.getType());
142   - firmware.setTitle(info.getTitle());
143   - firmware.setVersion(info.getVersion());
144   - firmware.setAdditionalInfo(info.getAdditionalInfo());
  134 + OtaPackageId otaPackageId = new OtaPackageId(toUUID(strOtaPackageId));
  135 + OtaPackageInfo info = checkOtaPackageInfoId(otaPackageId, Operation.READ);
  136 +
  137 + OtaPackage otaPackage = new OtaPackage(otaPackageId);
  138 + otaPackage.setCreatedTime(info.getCreatedTime());
  139 + otaPackage.setTenantId(getTenantId());
  140 + otaPackage.setDeviceProfileId(info.getDeviceProfileId());
  141 + otaPackage.setType(info.getType());
  142 + otaPackage.setTitle(info.getTitle());
  143 + otaPackage.setVersion(info.getVersion());
  144 + otaPackage.setAdditionalInfo(info.getAdditionalInfo());
145 145
146 146 ChecksumAlgorithm checksumAlgorithm = ChecksumAlgorithm.valueOf(checksumAlgorithmStr.toUpperCase());
147 147
148 148 byte[] bytes = file.getBytes();
149 149 if (StringUtils.isEmpty(checksum)) {
150   - checksum = firmwareService.generateChecksum(checksumAlgorithm, ByteBuffer.wrap(bytes));
  150 + checksum = otaPackageService.generateChecksum(checksumAlgorithm, ByteBuffer.wrap(bytes));
151 151 }
152 152
153   - firmware.setChecksumAlgorithm(checksumAlgorithm);
154   - firmware.setChecksum(checksum);
155   - firmware.setFileName(file.getOriginalFilename());
156   - firmware.setContentType(file.getContentType());
157   - firmware.setData(ByteBuffer.wrap(bytes));
158   - firmware.setDataSize((long) bytes.length);
159   - Firmware savedFirmware = firmwareService.saveFirmware(firmware);
160   - logEntityAction(savedFirmware.getId(), savedFirmware, null, ActionType.UPDATED, null);
161   - return savedFirmware;
  153 + otaPackage.setChecksumAlgorithm(checksumAlgorithm);
  154 + otaPackage.setChecksum(checksum);
  155 + otaPackage.setFileName(file.getOriginalFilename());
  156 + otaPackage.setContentType(file.getContentType());
  157 + otaPackage.setData(ByteBuffer.wrap(bytes));
  158 + otaPackage.setDataSize((long) bytes.length);
  159 + OtaPackage savedOtaPackage = otaPackageService.saveOtaPackage(otaPackage);
  160 + logEntityAction(savedOtaPackage.getId(), savedOtaPackage, null, ActionType.UPDATED, null);
  161 + return savedOtaPackage;
162 162 } catch (Exception e) {
163   - logEntityAction(emptyId(EntityType.FIRMWARE), null, null, ActionType.UPDATED, e, strFirmwareId);
  163 + logEntityAction(emptyId(EntityType.OTA_PACKAGE), null, null, ActionType.UPDATED, e, strOtaPackageId);
164 164 throw handleException(e);
165 165 }
166 166 }
167 167
168 168 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
169   - @RequestMapping(value = "/firmwares", method = RequestMethod.GET)
  169 + @RequestMapping(value = "/otaPackages", method = RequestMethod.GET)
170 170 @ResponseBody
171   - public PageData<FirmwareInfo> getFirmwares(@RequestParam int pageSize,
172   - @RequestParam int page,
173   - @RequestParam(required = false) String textSearch,
174   - @RequestParam(required = false) String sortProperty,
175   - @RequestParam(required = false) String sortOrder) throws ThingsboardException {
  171 + public PageData<OtaPackageInfo> getOtaPackages(@RequestParam int pageSize,
  172 + @RequestParam int page,
  173 + @RequestParam(required = false) String textSearch,
  174 + @RequestParam(required = false) String sortProperty,
  175 + @RequestParam(required = false) String sortOrder) throws ThingsboardException {
176 176 try {
177 177 PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
178   - return checkNotNull(firmwareService.findTenantFirmwaresByTenantId(getTenantId(), pageLink));
  178 + return checkNotNull(otaPackageService.findTenantOtaPackagesByTenantId(getTenantId(), pageLink));
179 179 } catch (Exception e) {
180 180 throw handleException(e);
181 181 }
182 182 }
183 183
184 184 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
185   - @RequestMapping(value = "/firmwares/{deviceProfileId}/{type}/{hasData}", method = RequestMethod.GET)
  185 + @RequestMapping(value = "/otaPackages/{deviceProfileId}/{type}/{hasData}", method = RequestMethod.GET)
186 186 @ResponseBody
187   - public PageData<FirmwareInfo> getFirmwares(@PathVariable("deviceProfileId") String strDeviceProfileId,
188   - @PathVariable("type") String strType,
189   - @PathVariable("hasData") boolean hasData,
190   - @RequestParam int pageSize,
191   - @RequestParam int page,
192   - @RequestParam(required = false) String textSearch,
193   - @RequestParam(required = false) String sortProperty,
194   - @RequestParam(required = false) String sortOrder) throws ThingsboardException {
  187 + public PageData<OtaPackageInfo> getOtaPackages(@PathVariable("deviceProfileId") String strDeviceProfileId,
  188 + @PathVariable("type") String strType,
  189 + @PathVariable("hasData") boolean hasData,
  190 + @RequestParam int pageSize,
  191 + @RequestParam int page,
  192 + @RequestParam(required = false) String textSearch,
  193 + @RequestParam(required = false) String sortProperty,
  194 + @RequestParam(required = false) String sortOrder) throws ThingsboardException {
195 195 checkParameter("deviceProfileId", strDeviceProfileId);
196 196 checkParameter("type", strType);
197 197 try {
198 198 PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
199   - return checkNotNull(firmwareService.findTenantFirmwaresByTenantIdAndDeviceProfileIdAndTypeAndHasData(getTenantId(),
200   - new DeviceProfileId(toUUID(strDeviceProfileId)), FirmwareType.valueOf(strType), hasData, pageLink));
  199 + return checkNotNull(otaPackageService.findTenantOtaPackagesByTenantIdAndDeviceProfileIdAndTypeAndHasData(getTenantId(),
  200 + new DeviceProfileId(toUUID(strDeviceProfileId)), OtaPackageType.valueOf(strType), hasData, pageLink));
201 201 } catch (Exception e) {
202 202 throw handleException(e);
203 203 }
204 204 }
205 205
206 206 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
207   - @RequestMapping(value = "/firmware/{firmwareId}", method = RequestMethod.DELETE)
  207 + @RequestMapping(value = "/otaPackage/{otaPackageId}", method = RequestMethod.DELETE)
208 208 @ResponseBody
209   - public void deleteFirmware(@PathVariable("firmwareId") String strFirmwareId) throws ThingsboardException {
210   - checkParameter(FIRMWARE_ID, strFirmwareId);
  209 + public void deleteOtaPackage(@PathVariable("otaPackageId") String strOtaPackageId) throws ThingsboardException {
  210 + checkParameter(OTA_PACKAGE_ID, strOtaPackageId);
211 211 try {
212   - FirmwareId firmwareId = new FirmwareId(toUUID(strFirmwareId));
213   - FirmwareInfo info = checkFirmwareInfoId(firmwareId, Operation.DELETE);
214   - firmwareService.deleteFirmware(getTenantId(), firmwareId);
215   - logEntityAction(firmwareId, info, null, ActionType.DELETED, null, strFirmwareId);
  212 + OtaPackageId otaPackageId = new OtaPackageId(toUUID(strOtaPackageId));
  213 + OtaPackageInfo info = checkOtaPackageInfoId(otaPackageId, Operation.DELETE);
  214 + otaPackageService.deleteOtaPackage(getTenantId(), otaPackageId);
  215 + logEntityAction(otaPackageId, info, null, ActionType.DELETED, null, strOtaPackageId);
216 216 } catch (Exception e) {
217   - logEntityAction(emptyId(EntityType.FIRMWARE), null, null, ActionType.DELETED, e, strFirmwareId);
  217 + logEntityAction(emptyId(EntityType.OTA_PACKAGE), null, null, ActionType.DELETED, e, strOtaPackageId);
218 218 throw handleException(e);
219 219 }
220 220 }
... ...
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.service.action;
  17 +
  18 +import com.fasterxml.jackson.databind.ObjectMapper;
  19 +import com.fasterxml.jackson.databind.node.ArrayNode;
  20 +import com.fasterxml.jackson.databind.node.ObjectNode;
  21 +import lombok.RequiredArgsConstructor;
  22 +import lombok.extern.slf4j.Slf4j;
  23 +import org.apache.commons.lang3.StringUtils;
  24 +import org.springframework.stereotype.Service;
  25 +import org.thingsboard.server.common.data.DataConstants;
  26 +import org.thingsboard.server.common.data.EntityType;
  27 +import org.thingsboard.server.common.data.HasName;
  28 +import org.thingsboard.server.common.data.HasTenantId;
  29 +import org.thingsboard.server.common.data.User;
  30 +import org.thingsboard.server.common.data.audit.ActionType;
  31 +import org.thingsboard.server.common.data.id.CustomerId;
  32 +import org.thingsboard.server.common.data.id.EntityId;
  33 +import org.thingsboard.server.common.data.id.TenantId;
  34 +import org.thingsboard.server.common.data.kv.AttributeKvEntry;
  35 +import org.thingsboard.server.common.data.kv.DataType;
  36 +import org.thingsboard.server.common.data.kv.KvEntry;
  37 +import org.thingsboard.server.common.data.kv.TsKvEntry;
  38 +import org.thingsboard.server.common.msg.TbMsg;
  39 +import org.thingsboard.server.common.msg.TbMsgDataType;
  40 +import org.thingsboard.server.common.msg.TbMsgMetaData;
  41 +import org.thingsboard.server.queue.util.TbCoreComponent;
  42 +import org.thingsboard.server.service.queue.TbClusterService;
  43 +
  44 +import java.util.List;
  45 +import java.util.Map;
  46 +import java.util.stream.Collectors;
  47 +
  48 +@TbCoreComponent
  49 +@Service
  50 +@RequiredArgsConstructor
  51 +@Slf4j
  52 +public class RuleEngineEntityActionService {
  53 + private final TbClusterService tbClusterService;
  54 +
  55 + private static final ObjectMapper json = new ObjectMapper();
  56 +
  57 + public void pushEntityActionToRuleEngine(EntityId entityId, HasName entity, TenantId tenantId, CustomerId customerId,
  58 + ActionType actionType, User user, Object... additionalInfo) {
  59 + String msgType = null;
  60 + switch (actionType) {
  61 + case ADDED:
  62 + msgType = DataConstants.ENTITY_CREATED;
  63 + break;
  64 + case DELETED:
  65 + msgType = DataConstants.ENTITY_DELETED;
  66 + break;
  67 + case UPDATED:
  68 + msgType = DataConstants.ENTITY_UPDATED;
  69 + break;
  70 + case ASSIGNED_TO_CUSTOMER:
  71 + msgType = DataConstants.ENTITY_ASSIGNED;
  72 + break;
  73 + case UNASSIGNED_FROM_CUSTOMER:
  74 + msgType = DataConstants.ENTITY_UNASSIGNED;
  75 + break;
  76 + case ATTRIBUTES_UPDATED:
  77 + msgType = DataConstants.ATTRIBUTES_UPDATED;
  78 + break;
  79 + case ATTRIBUTES_DELETED:
  80 + msgType = DataConstants.ATTRIBUTES_DELETED;
  81 + break;
  82 + case ALARM_ACK:
  83 + msgType = DataConstants.ALARM_ACK;
  84 + break;
  85 + case ALARM_CLEAR:
  86 + msgType = DataConstants.ALARM_CLEAR;
  87 + break;
  88 + case ALARM_DELETE:
  89 + msgType = DataConstants.ALARM_DELETE;
  90 + break;
  91 + case ASSIGNED_FROM_TENANT:
  92 + msgType = DataConstants.ENTITY_ASSIGNED_FROM_TENANT;
  93 + break;
  94 + case ASSIGNED_TO_TENANT:
  95 + msgType = DataConstants.ENTITY_ASSIGNED_TO_TENANT;
  96 + break;
  97 + case PROVISION_SUCCESS:
  98 + msgType = DataConstants.PROVISION_SUCCESS;
  99 + break;
  100 + case PROVISION_FAILURE:
  101 + msgType = DataConstants.PROVISION_FAILURE;
  102 + break;
  103 + case TIMESERIES_UPDATED:
  104 + msgType = DataConstants.TIMESERIES_UPDATED;
  105 + break;
  106 + case TIMESERIES_DELETED:
  107 + msgType = DataConstants.TIMESERIES_DELETED;
  108 + break;
  109 + case ASSIGNED_TO_EDGE:
  110 + msgType = DataConstants.ENTITY_ASSIGNED_TO_EDGE;
  111 + break;
  112 + case UNASSIGNED_FROM_EDGE:
  113 + msgType = DataConstants.ENTITY_UNASSIGNED_FROM_EDGE;
  114 + break;
  115 + }
  116 + if (!StringUtils.isEmpty(msgType)) {
  117 + try {
  118 + TbMsgMetaData metaData = new TbMsgMetaData();
  119 + if (user != null) {
  120 + metaData.putValue("userId", user.getId().toString());
  121 + metaData.putValue("userName", user.getName());
  122 + }
  123 + if (customerId != null && !customerId.isNullUid()) {
  124 + metaData.putValue("customerId", customerId.toString());
  125 + }
  126 + if (actionType == ActionType.ASSIGNED_TO_CUSTOMER) {
  127 + String strCustomerId = extractParameter(String.class, 1, additionalInfo);
  128 + String strCustomerName = extractParameter(String.class, 2, additionalInfo);
  129 + metaData.putValue("assignedCustomerId", strCustomerId);
  130 + metaData.putValue("assignedCustomerName", strCustomerName);
  131 + } else if (actionType == ActionType.UNASSIGNED_FROM_CUSTOMER) {
  132 + String strCustomerId = extractParameter(String.class, 1, additionalInfo);
  133 + String strCustomerName = extractParameter(String.class, 2, additionalInfo);
  134 + metaData.putValue("unassignedCustomerId", strCustomerId);
  135 + metaData.putValue("unassignedCustomerName", strCustomerName);
  136 + } else if (actionType == ActionType.ASSIGNED_FROM_TENANT) {
  137 + String strTenantId = extractParameter(String.class, 0, additionalInfo);
  138 + String strTenantName = extractParameter(String.class, 1, additionalInfo);
  139 + metaData.putValue("assignedFromTenantId", strTenantId);
  140 + metaData.putValue("assignedFromTenantName", strTenantName);
  141 + } else if (actionType == ActionType.ASSIGNED_TO_TENANT) {
  142 + String strTenantId = extractParameter(String.class, 0, additionalInfo);
  143 + String strTenantName = extractParameter(String.class, 1, additionalInfo);
  144 + metaData.putValue("assignedToTenantId", strTenantId);
  145 + metaData.putValue("assignedToTenantName", strTenantName);
  146 + } else if (actionType == ActionType.ASSIGNED_TO_EDGE) {
  147 + String strEdgeId = extractParameter(String.class, 1, additionalInfo);
  148 + String strEdgeName = extractParameter(String.class, 2, additionalInfo);
  149 + metaData.putValue("assignedEdgeId", strEdgeId);
  150 + metaData.putValue("assignedEdgeName", strEdgeName);
  151 + } else if (actionType == ActionType.UNASSIGNED_FROM_EDGE) {
  152 + String strEdgeId = extractParameter(String.class, 1, additionalInfo);
  153 + String strEdgeName = extractParameter(String.class, 2, additionalInfo);
  154 + metaData.putValue("unassignedEdgeId", strEdgeId);
  155 + metaData.putValue("unassignedEdgeName", strEdgeName);
  156 + }
  157 + ObjectNode entityNode;
  158 + if (entity != null) {
  159 + entityNode = json.valueToTree(entity);
  160 + if (entityId.getEntityType() == EntityType.DASHBOARD) {
  161 + entityNode.put("configuration", "");
  162 + }
  163 + } else {
  164 + entityNode = json.createObjectNode();
  165 + if (actionType == ActionType.ATTRIBUTES_UPDATED) {
  166 + String scope = extractParameter(String.class, 0, additionalInfo);
  167 + @SuppressWarnings("unchecked")
  168 + List<AttributeKvEntry> attributes = extractParameter(List.class, 1, additionalInfo);
  169 + metaData.putValue(DataConstants.SCOPE, scope);
  170 + if (attributes != null) {
  171 + for (AttributeKvEntry attr : attributes) {
  172 + addKvEntry(entityNode, attr);
  173 + }
  174 + }
  175 + } else if (actionType == ActionType.ATTRIBUTES_DELETED) {
  176 + String scope = extractParameter(String.class, 0, additionalInfo);
  177 + @SuppressWarnings("unchecked")
  178 + List<String> keys = extractParameter(List.class, 1, additionalInfo);
  179 + metaData.putValue(DataConstants.SCOPE, scope);
  180 + ArrayNode attrsArrayNode = entityNode.putArray("attributes");
  181 + if (keys != null) {
  182 + keys.forEach(attrsArrayNode::add);
  183 + }
  184 + } else if (actionType == ActionType.TIMESERIES_UPDATED) {
  185 + @SuppressWarnings("unchecked")
  186 + List<TsKvEntry> timeseries = extractParameter(List.class, 0, additionalInfo);
  187 + addTimeseries(entityNode, timeseries);
  188 + } else if (actionType == ActionType.TIMESERIES_DELETED) {
  189 + @SuppressWarnings("unchecked")
  190 + List<String> keys = extractParameter(List.class, 0, additionalInfo);
  191 + if (keys != null) {
  192 + ArrayNode timeseriesArrayNode = entityNode.putArray("timeseries");
  193 + keys.forEach(timeseriesArrayNode::add);
  194 + }
  195 + entityNode.put("startTs", extractParameter(Long.class, 1, additionalInfo));
  196 + entityNode.put("endTs", extractParameter(Long.class, 2, additionalInfo));
  197 + }
  198 + }
  199 + TbMsg tbMsg = TbMsg.newMsg(msgType, entityId, customerId, metaData, TbMsgDataType.JSON, json.writeValueAsString(entityNode));
  200 + if (tenantId.isNullUid()) {
  201 + if (entity instanceof HasTenantId) {
  202 + tenantId = ((HasTenantId) entity).getTenantId();
  203 + }
  204 + }
  205 + tbClusterService.pushMsgToRuleEngine(tenantId, entityId, tbMsg, null);
  206 + } catch (Exception e) {
  207 + log.warn("[{}] Failed to push entity action to rule engine: {}", entityId, actionType, e);
  208 + }
  209 + }
  210 + }
  211 +
  212 +
  213 + private <T> T extractParameter(Class<T> clazz, int index, Object... additionalInfo) {
  214 + T result = null;
  215 + if (additionalInfo != null && additionalInfo.length > index) {
  216 + Object paramObject = additionalInfo[index];
  217 + if (clazz.isInstance(paramObject)) {
  218 + result = clazz.cast(paramObject);
  219 + }
  220 + }
  221 + return result;
  222 + }
  223 +
  224 + private void addTimeseries(ObjectNode entityNode, List<TsKvEntry> timeseries) throws Exception {
  225 + if (timeseries != null && !timeseries.isEmpty()) {
  226 + ArrayNode result = entityNode.putArray("timeseries");
  227 + Map<Long, List<TsKvEntry>> groupedTelemetry = timeseries.stream()
  228 + .collect(Collectors.groupingBy(TsKvEntry::getTs));
  229 + for (Map.Entry<Long, List<TsKvEntry>> entry : groupedTelemetry.entrySet()) {
  230 + ObjectNode element = json.createObjectNode();
  231 + element.put("ts", entry.getKey());
  232 + ObjectNode values = element.putObject("values");
  233 + for (TsKvEntry tsKvEntry : entry.getValue()) {
  234 + addKvEntry(values, tsKvEntry);
  235 + }
  236 + result.add(element);
  237 + }
  238 + }
  239 + }
  240 +
  241 + private void addKvEntry(ObjectNode entityNode, KvEntry kvEntry) throws Exception {
  242 + if (kvEntry.getDataType() == DataType.BOOLEAN) {
  243 + kvEntry.getBooleanValue().ifPresent(value -> entityNode.put(kvEntry.getKey(), value));
  244 + } else if (kvEntry.getDataType() == DataType.DOUBLE) {
  245 + kvEntry.getDoubleValue().ifPresent(value -> entityNode.put(kvEntry.getKey(), value));
  246 + } else if (kvEntry.getDataType() == DataType.LONG) {
  247 + kvEntry.getLongValue().ifPresent(value -> entityNode.put(kvEntry.getKey(), value));
  248 + } else if (kvEntry.getDataType() == DataType.JSON) {
  249 + if (kvEntry.getJsonValue().isPresent()) {
  250 + entityNode.set(kvEntry.getKey(), json.readTree(kvEntry.getJsonValue().get()));
  251 + }
  252 + } else {
  253 + entityNode.put(kvEntry.getKey(), kvEntry.getValueAsString());
  254 + }
  255 + }
  256 +}
... ...
application/src/main/java/org/thingsboard/server/service/ota/DefaultOtaPackageStateService.java renamed from application/src/main/java/org/thingsboard/server/service/firmware/DefaultFirmwareStateService.java
... ... @@ -13,7 +13,7 @@
13 13 * See the License for the specific language governing permissions and
14 14 * limitations under the License.
15 15 */
16   -package org.thingsboard.server.service.firmware;
  16 +package org.thingsboard.server.service.ota;
17 17
18 18 import com.google.common.util.concurrent.FutureCallback;
19 19 import lombok.extern.slf4j.Slf4j;
... ... @@ -23,12 +23,9 @@ import org.thingsboard.rule.engine.api.msg.DeviceAttributesEventNotificationMsg;
23 23 import org.thingsboard.server.common.data.DataConstants;
24 24 import org.thingsboard.server.common.data.Device;
25 25 import org.thingsboard.server.common.data.DeviceProfile;
26   -import org.thingsboard.server.common.data.FirmwareInfo;
27   -import org.thingsboard.server.common.data.firmware.FirmwareType;
28   -import org.thingsboard.server.common.data.firmware.FirmwareUpdateStatus;
29   -import org.thingsboard.server.common.data.firmware.FirmwareUtil;
  26 +import org.thingsboard.server.common.data.OtaPackageInfo;
30 27 import org.thingsboard.server.common.data.id.DeviceId;
31   -import org.thingsboard.server.common.data.id.FirmwareId;
  28 +import org.thingsboard.server.common.data.id.OtaPackageId;
32 29 import org.thingsboard.server.common.data.id.TenantId;
33 30 import org.thingsboard.server.common.data.kv.AttributeKey;
34 31 import org.thingsboard.server.common.data.kv.AttributeKvEntry;
... ... @@ -37,13 +34,16 @@ import org.thingsboard.server.common.data.kv.BasicTsKvEntry;
37 34 import org.thingsboard.server.common.data.kv.LongDataEntry;
38 35 import org.thingsboard.server.common.data.kv.StringDataEntry;
39 36 import org.thingsboard.server.common.data.kv.TsKvEntry;
  37 +import org.thingsboard.server.common.data.ota.OtaPackageType;
  38 +import org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus;
  39 +import org.thingsboard.server.common.data.ota.OtaPackageUtil;
40 40 import org.thingsboard.server.common.data.page.PageData;
41 41 import org.thingsboard.server.common.data.page.PageLink;
42 42 import org.thingsboard.server.common.msg.queue.TopicPartitionInfo;
43 43 import org.thingsboard.server.dao.device.DeviceProfileService;
44 44 import org.thingsboard.server.dao.device.DeviceService;
45   -import org.thingsboard.server.dao.firmware.FirmwareService;
46   -import org.thingsboard.server.gen.transport.TransportProtos.ToFirmwareStateServiceMsg;
  45 +import org.thingsboard.server.dao.ota.OtaPackageService;
  46 +import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg;
47 47 import org.thingsboard.server.queue.TbQueueProducer;
48 48 import org.thingsboard.server.queue.common.TbProtoQueueMsg;
49 49 import org.thingsboard.server.queue.provider.TbCoreQueueFactory;
... ... @@ -58,44 +58,43 @@ import java.util.List;
58 58 import java.util.Set;
59 59 import java.util.UUID;
60 60 import java.util.function.Consumer;
61   -import java.util.function.Function;
62   -
63   -import static org.thingsboard.server.common.data.firmware.FirmwareKey.CHECKSUM;
64   -import static org.thingsboard.server.common.data.firmware.FirmwareKey.CHECKSUM_ALGORITHM;
65   -import static org.thingsboard.server.common.data.firmware.FirmwareKey.SIZE;
66   -import static org.thingsboard.server.common.data.firmware.FirmwareKey.STATE;
67   -import static org.thingsboard.server.common.data.firmware.FirmwareKey.TITLE;
68   -import static org.thingsboard.server.common.data.firmware.FirmwareKey.TS;
69   -import static org.thingsboard.server.common.data.firmware.FirmwareKey.VERSION;
70   -import static org.thingsboard.server.common.data.firmware.FirmwareType.FIRMWARE;
71   -import static org.thingsboard.server.common.data.firmware.FirmwareType.SOFTWARE;
72   -import static org.thingsboard.server.common.data.firmware.FirmwareUtil.getAttributeKey;
73   -import static org.thingsboard.server.common.data.firmware.FirmwareUtil.getTargetTelemetryKey;
74   -import static org.thingsboard.server.common.data.firmware.FirmwareUtil.getTelemetryKey;
  61 +
  62 +import static org.thingsboard.server.common.data.ota.OtaPackageKey.CHECKSUM;
  63 +import static org.thingsboard.server.common.data.ota.OtaPackageKey.CHECKSUM_ALGORITHM;
  64 +import static org.thingsboard.server.common.data.ota.OtaPackageKey.SIZE;
  65 +import static org.thingsboard.server.common.data.ota.OtaPackageKey.STATE;
  66 +import static org.thingsboard.server.common.data.ota.OtaPackageKey.TITLE;
  67 +import static org.thingsboard.server.common.data.ota.OtaPackageKey.TS;
  68 +import static org.thingsboard.server.common.data.ota.OtaPackageKey.VERSION;
  69 +import static org.thingsboard.server.common.data.ota.OtaPackageType.FIRMWARE;
  70 +import static org.thingsboard.server.common.data.ota.OtaPackageType.SOFTWARE;
  71 +import static org.thingsboard.server.common.data.ota.OtaPackageUtil.getAttributeKey;
  72 +import static org.thingsboard.server.common.data.ota.OtaPackageUtil.getTargetTelemetryKey;
  73 +import static org.thingsboard.server.common.data.ota.OtaPackageUtil.getTelemetryKey;
75 74
76 75 @Slf4j
77 76 @Service
78 77 @TbCoreComponent
79   -public class DefaultFirmwareStateService implements FirmwareStateService {
  78 +public class DefaultOtaPackageStateService implements OtaPackageStateService {
80 79
81 80 private final TbClusterService tbClusterService;
82   - private final FirmwareService firmwareService;
  81 + private final OtaPackageService otaPackageService;
83 82 private final DeviceService deviceService;
84 83 private final DeviceProfileService deviceProfileService;
85 84 private final RuleEngineTelemetryService telemetryService;
86   - private final TbQueueProducer<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> fwStateMsgProducer;
  85 + private final TbQueueProducer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> otaPackageStateMsgProducer;
87 86
88   - public DefaultFirmwareStateService(TbClusterService tbClusterService, FirmwareService firmwareService,
89   - DeviceService deviceService,
90   - DeviceProfileService deviceProfileService,
91   - RuleEngineTelemetryService telemetryService,
92   - TbCoreQueueFactory coreQueueFactory) {
  87 + public DefaultOtaPackageStateService(TbClusterService tbClusterService, OtaPackageService otaPackageService,
  88 + DeviceService deviceService,
  89 + DeviceProfileService deviceProfileService,
  90 + RuleEngineTelemetryService telemetryService,
  91 + TbCoreQueueFactory coreQueueFactory) {
93 92 this.tbClusterService = tbClusterService;
94   - this.firmwareService = firmwareService;
  93 + this.otaPackageService = otaPackageService;
95 94 this.deviceService = deviceService;
96 95 this.deviceProfileService = deviceProfileService;
97 96 this.telemetryService = telemetryService;
98   - this.fwStateMsgProducer = coreQueueFactory.createToFirmwareStateServiceMsgProducer();
  97 + this.otaPackageStateMsgProducer = coreQueueFactory.createToOtaPackageStateServiceMsgProducer();
99 98 }
100 99
101 100 @Override
... ... @@ -105,14 +104,14 @@ public class DefaultFirmwareStateService implements FirmwareStateService {
105 104 }
106 105
107 106 private void updateFirmware(Device device, Device oldDevice) {
108   - FirmwareId newFirmwareId = device.getFirmwareId();
  107 + OtaPackageId newFirmwareId = device.getFirmwareId();
109 108 if (newFirmwareId == null) {
110 109 DeviceProfile newDeviceProfile = deviceProfileService.findDeviceProfileById(device.getTenantId(), device.getDeviceProfileId());
111 110 newFirmwareId = newDeviceProfile.getFirmwareId();
112 111 }
113 112 if (oldDevice != null) {
114 113 if (newFirmwareId != null) {
115   - FirmwareId oldFirmwareId = oldDevice.getFirmwareId();
  114 + OtaPackageId oldFirmwareId = oldDevice.getFirmwareId();
116 115 if (oldFirmwareId == null) {
117 116 DeviceProfile oldDeviceProfile = deviceProfileService.findDeviceProfileById(oldDevice.getTenantId(), oldDevice.getDeviceProfileId());
118 117 oldFirmwareId = oldDeviceProfile.getFirmwareId();
... ... @@ -132,14 +131,14 @@ public class DefaultFirmwareStateService implements FirmwareStateService {
132 131 }
133 132
134 133 private void updateSoftware(Device device, Device oldDevice) {
135   - FirmwareId newSoftwareId = device.getSoftwareId();
  134 + OtaPackageId newSoftwareId = device.getSoftwareId();
136 135 if (newSoftwareId == null) {
137 136 DeviceProfile newDeviceProfile = deviceProfileService.findDeviceProfileById(device.getTenantId(), device.getDeviceProfileId());
138 137 newSoftwareId = newDeviceProfile.getSoftwareId();
139 138 }
140 139 if (oldDevice != null) {
141 140 if (newSoftwareId != null) {
142   - FirmwareId oldSoftwareId = oldDevice.getSoftwareId();
  141 + OtaPackageId oldSoftwareId = oldDevice.getSoftwareId();
143 142 if (oldSoftwareId == null) {
144 143 DeviceProfile oldDeviceProfile = deviceProfileService.findDeviceProfileById(oldDevice.getTenantId(), oldDevice.getDeviceProfileId());
145 144 oldSoftwareId = oldDeviceProfile.getSoftwareId();
... ... @@ -170,33 +169,20 @@ public class DefaultFirmwareStateService implements FirmwareStateService {
170 169 }
171 170 }
172 171
173   - private void update(TenantId tenantId, DeviceProfile deviceProfile, FirmwareType firmwareType) {
174   - Function<PageLink, PageData<Device>> getDevicesFunction;
  172 + private void update(TenantId tenantId, DeviceProfile deviceProfile, OtaPackageType otaPackageType) {
175 173 Consumer<Device> updateConsumer;
176 174
177   - switch (firmwareType) {
178   - case FIRMWARE:
179   - getDevicesFunction = pl -> deviceService.findDevicesByTenantIdAndTypeAndEmptyFirmware(tenantId, deviceProfile.getName(), pl);
180   - break;
181   - case SOFTWARE:
182   - getDevicesFunction = pl -> deviceService.findDevicesByTenantIdAndTypeAndEmptySoftware(tenantId, deviceProfile.getName(), pl);
183   - break;
184   - default:
185   - log.warn("Unsupported firmware type: [{}]", firmwareType);
186   - return;
187   - }
188   -
189 175 if (deviceProfile.getFirmwareId() != null) {
190 176 long ts = System.currentTimeMillis();
191   - updateConsumer = d -> send(d.getTenantId(), d.getId(), deviceProfile.getFirmwareId(), ts, firmwareType);
  177 + updateConsumer = d -> send(d.getTenantId(), d.getId(), deviceProfile.getFirmwareId(), ts, otaPackageType);
192 178 } else {
193   - updateConsumer = d -> remove(d, firmwareType);
  179 + updateConsumer = d -> remove(d, otaPackageType);
194 180 }
195 181
196 182 PageLink pageLink = new PageLink(100);
197 183 PageData<Device> pageData;
198 184 do {
199   - pageData = getDevicesFunction.apply(pageLink);
  185 + pageData = deviceService.findDevicesByTenantIdAndTypeAndEmptyOtaPackage(tenantId, deviceProfile.getId(), otaPackageType, pageLink);
200 186 pageData.getData().forEach(updateConsumer);
201 187
202 188 if (pageData.hasNext()) {
... ... @@ -206,60 +192,60 @@ public class DefaultFirmwareStateService implements FirmwareStateService {
206 192 }
207 193
208 194 @Override
209   - public boolean process(ToFirmwareStateServiceMsg msg) {
  195 + public boolean process(ToOtaPackageStateServiceMsg msg) {
210 196 boolean isSuccess = false;
211   - FirmwareId targetFirmwareId = new FirmwareId(new UUID(msg.getFirmwareIdMSB(), msg.getFirmwareIdLSB()));
  197 + OtaPackageId targetOtaPackageId = new OtaPackageId(new UUID(msg.getOtaPackageIdMSB(), msg.getOtaPackageIdLSB()));
212 198 DeviceId deviceId = new DeviceId(new UUID(msg.getDeviceIdMSB(), msg.getDeviceIdLSB()));
213 199 TenantId tenantId = new TenantId(new UUID(msg.getTenantIdMSB(), msg.getTenantIdLSB()));
214   - FirmwareType firmwareType = FirmwareType.valueOf(msg.getType());
  200 + OtaPackageType firmwareType = OtaPackageType.valueOf(msg.getType());
215 201 long ts = msg.getTs();
216 202
217 203 Device device = deviceService.findDeviceById(tenantId, deviceId);
218 204 if (device == null) {
219 205 log.warn("[{}] [{}] Device was removed during firmware update msg was queued!", tenantId, deviceId);
220 206 } else {
221   - FirmwareId currentFirmwareId = FirmwareUtil.getFirmwareId(device, firmwareType);
222   - if (currentFirmwareId == null) {
  207 + OtaPackageId currentOtaPackageId = OtaPackageUtil.getOtaPackageId(device, firmwareType);
  208 + if (currentOtaPackageId == null) {
223 209 DeviceProfile deviceProfile = deviceProfileService.findDeviceProfileById(tenantId, device.getDeviceProfileId());
224   - currentFirmwareId = FirmwareUtil.getFirmwareId(deviceProfile, firmwareType);
  210 + currentOtaPackageId = OtaPackageUtil.getOtaPackageId(deviceProfile, firmwareType);
225 211 }
226 212
227   - if (targetFirmwareId.equals(currentFirmwareId)) {
228   - update(device, firmwareService.findFirmwareInfoById(device.getTenantId(), targetFirmwareId), ts);
  213 + if (targetOtaPackageId.equals(currentOtaPackageId)) {
  214 + update(device, otaPackageService.findOtaPackageInfoById(device.getTenantId(), targetOtaPackageId), ts);
229 215 isSuccess = true;
230 216 } else {
231   - log.warn("[{}] [{}] Can`t update firmware for the device, target firmwareId: [{}], current firmwareId: [{}]!", tenantId, deviceId, targetFirmwareId, currentFirmwareId);
  217 + log.warn("[{}] [{}] Can`t update firmware for the device, target firmwareId: [{}], current firmwareId: [{}]!", tenantId, deviceId, targetOtaPackageId, currentOtaPackageId);
232 218 }
233 219 }
234 220 return isSuccess;
235 221 }
236 222
237   - private void send(TenantId tenantId, DeviceId deviceId, FirmwareId firmwareId, long ts, FirmwareType firmwareType) {
238   - ToFirmwareStateServiceMsg msg = ToFirmwareStateServiceMsg.newBuilder()
  223 + private void send(TenantId tenantId, DeviceId deviceId, OtaPackageId firmwareId, long ts, OtaPackageType firmwareType) {
  224 + ToOtaPackageStateServiceMsg msg = ToOtaPackageStateServiceMsg.newBuilder()
239 225 .setTenantIdMSB(tenantId.getId().getMostSignificantBits())
240 226 .setTenantIdLSB(tenantId.getId().getLeastSignificantBits())
241 227 .setDeviceIdMSB(deviceId.getId().getMostSignificantBits())
242 228 .setDeviceIdLSB(deviceId.getId().getLeastSignificantBits())
243   - .setFirmwareIdMSB(firmwareId.getId().getMostSignificantBits())
244   - .setFirmwareIdLSB(firmwareId.getId().getLeastSignificantBits())
  229 + .setOtaPackageIdMSB(firmwareId.getId().getMostSignificantBits())
  230 + .setOtaPackageIdLSB(firmwareId.getId().getLeastSignificantBits())
245 231 .setType(firmwareType.name())
246 232 .setTs(ts)
247 233 .build();
248 234
249   - FirmwareInfo firmware = firmwareService.findFirmwareInfoById(tenantId, firmwareId);
  235 + OtaPackageInfo firmware = otaPackageService.findOtaPackageInfoById(tenantId, firmwareId);
250 236 if (firmware == null) {
251 237 log.warn("[{}] Failed to send firmware update because firmware was already deleted", firmwareId);
252 238 return;
253 239 }
254 240
255   - TopicPartitionInfo tpi = new TopicPartitionInfo(fwStateMsgProducer.getDefaultTopic(), null, null, false);
256   - fwStateMsgProducer.send(tpi, new TbProtoQueueMsg<>(UUID.randomUUID(), msg), null);
  241 + TopicPartitionInfo tpi = new TopicPartitionInfo(otaPackageStateMsgProducer.getDefaultTopic(), null, null, false);
  242 + otaPackageStateMsgProducer.send(tpi, new TbProtoQueueMsg<>(UUID.randomUUID(), msg), null);
257 243
258 244 List<TsKvEntry> telemetry = new ArrayList<>();
259 245 telemetry.add(new BasicTsKvEntry(ts, new StringDataEntry(getTargetTelemetryKey(firmware.getType(), TITLE), firmware.getTitle())));
260 246 telemetry.add(new BasicTsKvEntry(ts, new StringDataEntry(getTargetTelemetryKey(firmware.getType(), VERSION), firmware.getVersion())));
261 247 telemetry.add(new BasicTsKvEntry(ts, new LongDataEntry(getTargetTelemetryKey(firmware.getType(), TS), ts)));
262   - telemetry.add(new BasicTsKvEntry(ts, new StringDataEntry(getTelemetryKey(firmware.getType(), STATE), FirmwareUpdateStatus.QUEUED.name())));
  248 + telemetry.add(new BasicTsKvEntry(ts, new StringDataEntry(getTelemetryKey(firmware.getType(), STATE), OtaPackageUpdateStatus.QUEUED.name())));
263 249
264 250 telemetryService.saveAndNotify(tenantId, deviceId, telemetry, new FutureCallback<>() {
265 251 @Override
... ... @@ -275,11 +261,11 @@ public class DefaultFirmwareStateService implements FirmwareStateService {
275 261 }
276 262
277 263
278   - private void update(Device device, FirmwareInfo firmware, long ts) {
  264 + private void update(Device device, OtaPackageInfo firmware, long ts) {
279 265 TenantId tenantId = device.getTenantId();
280 266 DeviceId deviceId = device.getId();
281 267
282   - BasicTsKvEntry status = new BasicTsKvEntry(System.currentTimeMillis(), new StringDataEntry(getTelemetryKey(firmware.getType(), STATE), FirmwareUpdateStatus.INITIATED.name()));
  268 + BasicTsKvEntry status = new BasicTsKvEntry(System.currentTimeMillis(), new StringDataEntry(getTelemetryKey(firmware.getType(), STATE), OtaPackageUpdateStatus.INITIATED.name()));
283 269
284 270 telemetryService.saveAndNotify(tenantId, deviceId, Collections.singletonList(status), new FutureCallback<>() {
285 271 @Override
... ... @@ -313,14 +299,14 @@ public class DefaultFirmwareStateService implements FirmwareStateService {
313 299 });
314 300 }
315 301
316   - private void remove(Device device, FirmwareType firmwareType) {
317   - telemetryService.deleteAndNotify(device.getTenantId(), device.getId(), DataConstants.SHARED_SCOPE, FirmwareUtil.getAttributeKeys(firmwareType),
  302 + private void remove(Device device, OtaPackageType firmwareType) {
  303 + telemetryService.deleteAndNotify(device.getTenantId(), device.getId(), DataConstants.SHARED_SCOPE, OtaPackageUtil.getAttributeKeys(firmwareType),
318 304 new FutureCallback<>() {
319 305 @Override
320 306 public void onSuccess(@Nullable Void tmp) {
321 307 log.trace("[{}] Success remove target firmware attributes!", device.getId());
322 308 Set<AttributeKey> keysToNotify = new HashSet<>();
323   - FirmwareUtil.ALL_FW_ATTRIBUTE_KEYS.forEach(key -> keysToNotify.add(new AttributeKey(DataConstants.SHARED_SCOPE, key)));
  309 + OtaPackageUtil.ALL_FW_ATTRIBUTE_KEYS.forEach(key -> keysToNotify.add(new AttributeKey(DataConstants.SHARED_SCOPE, key)));
324 310 tbClusterService.pushMsgToCore(DeviceAttributesEventNotificationMsg.onDelete(device.getTenantId(), device.getId(), keysToNotify), null);
325 311 }
326 312
... ...
application/src/main/java/org/thingsboard/server/service/ota/OtaPackageStateService.java renamed from application/src/main/java/org/thingsboard/server/service/firmware/FirmwareStateService.java
... ... @@ -13,18 +13,18 @@
13 13 * See the License for the specific language governing permissions and
14 14 * limitations under the License.
15 15 */
16   -package org.thingsboard.server.service.firmware;
  16 +package org.thingsboard.server.service.ota;
17 17
18 18 import org.thingsboard.server.common.data.Device;
19 19 import org.thingsboard.server.common.data.DeviceProfile;
20   -import org.thingsboard.server.gen.transport.TransportProtos.ToFirmwareStateServiceMsg;
  20 +import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg;
21 21
22   -public interface FirmwareStateService {
  22 +public interface OtaPackageStateService {
23 23
24 24 void update(Device device, Device oldDevice);
25 25
26 26 void update(DeviceProfile deviceProfile, boolean isFirmwareChanged, boolean isSoftwareChanged);
27 27
28   - boolean process(ToFirmwareStateServiceMsg msg);
  28 + boolean process(ToOtaPackageStateServiceMsg msg);
29 29
30 30 }
... ...
... ... @@ -50,7 +50,7 @@ import org.thingsboard.server.gen.transport.TransportProtos.TbSubscriptionCloseP
50 50 import org.thingsboard.server.gen.transport.TransportProtos.TbTimeSeriesUpdateProto;
51 51 import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg;
52 52 import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg;
53   -import org.thingsboard.server.gen.transport.TransportProtos.ToFirmwareStateServiceMsg;
  53 +import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg;
54 54 import org.thingsboard.server.gen.transport.TransportProtos.ToUsageStatsServiceMsg;
55 55 import org.thingsboard.server.gen.transport.TransportProtos.TransportToDeviceActorMsg;
56 56 import org.thingsboard.server.queue.TbQueueConsumer;
... ... @@ -60,7 +60,7 @@ import org.thingsboard.server.queue.provider.TbCoreQueueFactory;
60 60 import org.thingsboard.server.queue.util.TbCoreComponent;
61 61 import org.thingsboard.server.service.apiusage.TbApiUsageStateService;
62 62 import org.thingsboard.server.service.edge.EdgeNotificationService;
63   -import org.thingsboard.server.service.firmware.FirmwareStateService;
  63 +import org.thingsboard.server.service.ota.OtaPackageStateService;
64 64 import org.thingsboard.server.service.profile.TbDeviceProfileCache;
65 65 import org.thingsboard.server.service.queue.processing.AbstractConsumerService;
66 66 import org.thingsboard.server.service.queue.processing.IdMsgPair;
... ... @@ -75,7 +75,6 @@ import org.thingsboard.server.service.transport.msg.TransportToDeviceActorMsgWra
75 75
76 76 import javax.annotation.PostConstruct;
77 77 import javax.annotation.PreDestroy;
78   -import java.util.ArrayList;
79 78 import java.util.List;
80 79 import java.util.Optional;
81 80 import java.util.UUID;
... ... @@ -101,9 +100,9 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService<ToCore
101 100 @Value("${queue.core.stats.enabled:false}")
102 101 private boolean statsEnabled;
103 102
104   - @Value("${queue.core.firmware.pack-interval-ms:60000}")
  103 + @Value("${queue.core.ota.pack-interval-ms:60000}")
105 104 private long firmwarePackInterval;
106   - @Value("${queue.core.firmware.pack-size:100}")
  105 + @Value("${queue.core.ota.pack-size:100}")
107 106 private int firmwarePackSize;
108 107
109 108 private final TbQueueConsumer<TbProtoQueueMsg<ToCoreMsg>> mainConsumer;
... ... @@ -113,10 +112,10 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService<ToCore
113 112 private final SubscriptionManagerService subscriptionManagerService;
114 113 private final TbCoreDeviceRpcService tbCoreDeviceRpcService;
115 114 private final EdgeNotificationService edgeNotificationService;
116   - private final FirmwareStateService firmwareStateService;
  115 + private final OtaPackageStateService firmwareStateService;
117 116 private final TbCoreConsumerStats stats;
118 117 protected final TbQueueConsumer<TbProtoQueueMsg<ToUsageStatsServiceMsg>> usageStatsConsumer;
119   - private final TbQueueConsumer<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> firmwareStatesConsumer;
  118 + private final TbQueueConsumer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> firmwareStatesConsumer;
120 119
121 120 protected volatile ExecutorService usageStatsExecutor;
122 121
... ... @@ -135,11 +134,11 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService<ToCore
135 134 TbTenantProfileCache tenantProfileCache,
136 135 TbApiUsageStateService apiUsageStateService,
137 136 EdgeNotificationService edgeNotificationService,
138   - FirmwareStateService firmwareStateService) {
  137 + OtaPackageStateService firmwareStateService) {
139 138 super(actorContext, encodingService, tenantProfileCache, deviceProfileCache, apiUsageStateService, tbCoreQueueFactory.createToCoreNotificationsMsgConsumer());
140 139 this.mainConsumer = tbCoreQueueFactory.createToCoreMsgConsumer();
141 140 this.usageStatsConsumer = tbCoreQueueFactory.createToUsageStatsServiceMsgConsumer();
142   - this.firmwareStatesConsumer = tbCoreQueueFactory.createToFirmwareStateServiceMsgConsumer();
  141 + this.firmwareStatesConsumer = tbCoreQueueFactory.createToOtaPackageStateServiceMsgConsumer();
143 142 this.stateService = stateService;
144 143 this.localSubscriptionService = localSubscriptionService;
145 144 this.subscriptionManagerService = subscriptionManagerService;
... ... @@ -173,7 +172,7 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService<ToCore
173 172 public void onApplicationEvent(ApplicationReadyEvent event) {
174 173 super.onApplicationEvent(event);
175 174 launchUsageStatsConsumer();
176   - launchFirmwareUpdateNotificationConsumer();
  175 + launchOtaPackageUpdateNotificationConsumer();
177 176 }
178 177
179 178 @Override
... ... @@ -361,20 +360,20 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService<ToCore
361 360 });
362 361 }
363 362
364   - private void launchFirmwareUpdateNotificationConsumer() {
  363 + private void launchOtaPackageUpdateNotificationConsumer() {
365 364 long maxProcessingTimeoutPerRecord = firmwarePackInterval / firmwarePackSize;
366 365 firmwareStatesExecutor.submit(() -> {
367 366 while (!stopped) {
368 367 try {
369   - List<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> msgs = firmwareStatesConsumer.poll(getNotificationPollDuration());
  368 + List<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> msgs = firmwareStatesConsumer.poll(getNotificationPollDuration());
370 369 if (msgs.isEmpty()) {
371 370 continue;
372 371 }
373 372 long timeToSleep = maxProcessingTimeoutPerRecord;
374   - for (TbProtoQueueMsg<ToFirmwareStateServiceMsg> msg : msgs) {
  373 + for (TbProtoQueueMsg<ToOtaPackageStateServiceMsg> msg : msgs) {
375 374 try {
376 375 long startTime = System.currentTimeMillis();
377   - boolean isSuccessUpdate = handleFirmwareUpdates(msg);
  376 + boolean isSuccessUpdate = handleOtaPackageUpdates(msg);
378 377 long endTime = System.currentTimeMillis();
379 378 long spentTime = endTime - startTime;
380 379 timeToSleep = timeToSleep - spentTime;
... ... @@ -402,7 +401,7 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService<ToCore
402 401 }
403 402 }
404 403 }
405   - log.info("TB Firmware States Consumer stopped.");
  404 + log.info("TB Ota Package States Consumer stopped.");
406 405 });
407 406 }
408 407
... ... @@ -410,7 +409,7 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService<ToCore
410 409 statsService.process(msg, callback);
411 410 }
412 411
413   - private boolean handleFirmwareUpdates(TbProtoQueueMsg<ToFirmwareStateServiceMsg> msg) {
  412 + private boolean handleOtaPackageUpdates(TbProtoQueueMsg<ToOtaPackageStateServiceMsg> msg) {
414 413 return firmwareStateService.process(msg.getValue());
415 414 }
416 415
... ...
... ... @@ -89,7 +89,7 @@ public class DefaultTbResourceService implements TbResourceService {
89 89 } catch (InvalidDDFFileException | IOException e) {
90 90 throw new ThingsboardException(e, ThingsboardErrorCode.GENERAL);
91 91 }
92   - if (resource.getResourceType().equals(ResourceType.LWM2M_MODEL) && toLwM2mObject(resource) == null) {
  92 + if (resource.getResourceType().equals(ResourceType.LWM2M_MODEL) && toLwM2mObject(resource, true) == null) {
93 93 throw new DataValidationException(String.format("Could not parse the XML of objectModel with name %s", resource.getSearchText()));
94 94 }
95 95 } else {
... ... @@ -131,7 +131,7 @@ public class DefaultTbResourceService implements TbResourceService {
131 131 List<TbResource> resources = resourceService.findTenantResourcesByResourceTypeAndObjectIds(tenantId, ResourceType.LWM2M_MODEL,
132 132 objectIds);
133 133 return resources.stream()
134   - .flatMap(s -> Stream.ofNullable(toLwM2mObject(s)))
  134 + .flatMap(s -> Stream.ofNullable(toLwM2mObject(s, false)))
135 135 .sorted(getComparator(sortProperty, sortOrder))
136 136 .collect(Collectors.toList());
137 137 }
... ... @@ -142,7 +142,7 @@ public class DefaultTbResourceService implements TbResourceService {
142 142 validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
143 143 PageData<TbResource> resourcePageData = resourceService.findTenantResourcesByResourceTypeAndPageLink(tenantId, ResourceType.LWM2M_MODEL, pageLink);
144 144 return resourcePageData.getData().stream()
145   - .flatMap(s -> Stream.ofNullable(toLwM2mObject(s)))
  145 + .flatMap(s -> Stream.ofNullable(toLwM2mObject(s, false)))
146 146 .sorted(getComparator(sortProperty, sortOrder))
147 147 .collect(Collectors.toList());
148 148 }
... ... @@ -167,7 +167,7 @@ public class DefaultTbResourceService implements TbResourceService {
167 167 return "DESC".equals(sortOrder) ? comparator.reversed() : comparator;
168 168 }
169 169
170   - private LwM2mObject toLwM2mObject(TbResource resource) {
  170 + private LwM2mObject toLwM2mObject(TbResource resource, boolean isSave) {
171 171 try {
172 172 DDFFileParser ddfFileParser = new DDFFileParser(new DefaultDDFFileValidator());
173 173 List<ObjectModel> objectModels =
... ... @@ -186,12 +186,16 @@ public class DefaultTbResourceService implements TbResourceService {
186 186 instance.setId(0);
187 187 List<LwM2mResourceObserve> resources = new ArrayList<>();
188 188 obj.resources.forEach((k, v) -> {
189   - if (v.operations.isReadable()) {
  189 + if (isSave) {
  190 + LwM2mResourceObserve lwM2MResourceObserve = new LwM2mResourceObserve(k, v.name, false, false, false);
  191 + resources.add(lwM2MResourceObserve);
  192 + }
  193 + else if (v.operations.isReadable()) {
190 194 LwM2mResourceObserve lwM2MResourceObserve = new LwM2mResourceObserve(k, v.name, false, false, false);
191 195 resources.add(lwM2MResourceObserve);
192 196 }
193 197 });
194   - if (resources.size() > 0) {
  198 + if (isSave || resources.size() > 0) {
195 199 instance.setResources(resources.toArray(LwM2mResourceObserve[]::new));
196 200 lwM2mObject.setInstances(new LwM2mInstance[]{instance});
197 201 return lwM2mObject;
... ...
... ... @@ -30,7 +30,7 @@ import org.thingsboard.server.common.data.Customer;
30 30 import org.thingsboard.server.common.data.Device;
31 31 import org.thingsboard.server.common.data.DeviceProfile;
32 32 import org.thingsboard.server.common.data.EntityView;
33   -import org.thingsboard.server.common.data.FirmwareInfo;
  33 +import org.thingsboard.server.common.data.OtaPackageInfo;
34 34 import org.thingsboard.server.common.data.TbResourceInfo;
35 35 import org.thingsboard.server.common.data.Tenant;
36 36 import org.thingsboard.server.common.data.User;
... ... @@ -46,7 +46,7 @@ import org.thingsboard.server.common.data.id.EdgeId;
46 46 import org.thingsboard.server.common.data.id.EntityId;
47 47 import org.thingsboard.server.common.data.id.EntityIdFactory;
48 48 import org.thingsboard.server.common.data.id.EntityViewId;
49   -import org.thingsboard.server.common.data.id.FirmwareId;
  49 +import org.thingsboard.server.common.data.id.OtaPackageId;
50 50 import org.thingsboard.server.common.data.id.RuleChainId;
51 51 import org.thingsboard.server.common.data.id.RuleNodeId;
52 52 import org.thingsboard.server.common.data.id.TbResourceId;
... ... @@ -63,7 +63,7 @@ import org.thingsboard.server.dao.device.DeviceService;
63 63 import org.thingsboard.server.dao.edge.EdgeService;
64 64 import org.thingsboard.server.dao.entityview.EntityViewService;
65 65 import org.thingsboard.server.dao.exception.IncorrectParameterException;
66   -import org.thingsboard.server.dao.firmware.FirmwareService;
  66 +import org.thingsboard.server.dao.ota.OtaPackageService;
67 67 import org.thingsboard.server.dao.resource.ResourceService;
68 68 import org.thingsboard.server.dao.rule.RuleChainService;
69 69 import org.thingsboard.server.dao.tenant.TenantService;
... ... @@ -135,7 +135,7 @@ public class AccessValidator {
135 135 protected ResourceService resourceService;
136 136
137 137 @Autowired
138   - protected FirmwareService firmwareService;
  138 + protected OtaPackageService otaPackageService;
139 139
140 140 private ExecutorService executor;
141 141
... ... @@ -232,8 +232,8 @@ public class AccessValidator {
232 232 case TB_RESOURCE:
233 233 validateResource(currentUser, operation, entityId, callback);
234 234 return;
235   - case FIRMWARE:
236   - validateFirmware(currentUser, operation, entityId, callback);
  235 + case OTA_PACKAGE:
  236 + validateOtaPackage(currentUser, operation, entityId, callback);
237 237 return;
238 238 default:
239 239 //TODO: add support of other entities
... ... @@ -300,20 +300,20 @@ public class AccessValidator {
300 300 }
301 301 }
302 302
303   - private void validateFirmware(final SecurityUser currentUser, Operation operation, EntityId entityId, FutureCallback<ValidationResult> callback) {
  303 + private void validateOtaPackage(final SecurityUser currentUser, Operation operation, EntityId entityId, FutureCallback<ValidationResult> callback) {
304 304 if (currentUser.isSystemAdmin()) {
305 305 callback.onSuccess(ValidationResult.accessDenied(SYSTEM_ADMINISTRATOR_IS_NOT_ALLOWED_TO_PERFORM_THIS_OPERATION));
306 306 } else {
307   - FirmwareInfo firmware = firmwareService.findFirmwareInfoById(currentUser.getTenantId(), new FirmwareId(entityId.getId()));
308   - if (firmware == null) {
309   - callback.onSuccess(ValidationResult.entityNotFound("Firmware with requested id wasn't found!"));
  307 + OtaPackageInfo otaPackage = otaPackageService.findOtaPackageInfoById(currentUser.getTenantId(), new OtaPackageId(entityId.getId()));
  308 + if (otaPackage == null) {
  309 + callback.onSuccess(ValidationResult.entityNotFound("OtaPackage with requested id wasn't found!"));
310 310 } else {
311 311 try {
312   - accessControlService.checkPermission(currentUser, Resource.FIRMWARE, operation, entityId, firmware);
  312 + accessControlService.checkPermission(currentUser, Resource.OTA_PACKAGE, operation, entityId, otaPackage);
313 313 } catch (ThingsboardException e) {
314 314 callback.onSuccess(ValidationResult.accessDenied(e.getMessage()));
315 315 }
316   - callback.onSuccess(ValidationResult.ok(firmware));
  316 + callback.onSuccess(ValidationResult.ok(otaPackage));
317 317 }
318 318 }
319 319 }
... ...
... ... @@ -38,7 +38,7 @@ public enum Resource {
38 38 DEVICE_PROFILE(EntityType.DEVICE_PROFILE),
39 39 API_USAGE_STATE(EntityType.API_USAGE_STATE),
40 40 TB_RESOURCE(EntityType.TB_RESOURCE),
41   - FIRMWARE(EntityType.FIRMWARE),
  41 + OTA_PACKAGE(EntityType.OTA_PACKAGE),
42 42 EDGE(EntityType.EDGE);
43 43
44 44 private final EntityType entityType;
... ...
... ... @@ -42,7 +42,7 @@ public class TenantAdminPermissions extends AbstractPermissions {
42 42 put(Resource.DEVICE_PROFILE, tenantEntityPermissionChecker);
43 43 put(Resource.API_USAGE_STATE, tenantEntityPermissionChecker);
44 44 put(Resource.TB_RESOURCE, tbResourcePermissionChecker);
45   - put(Resource.FIRMWARE, tenantEntityPermissionChecker);
  45 + put(Resource.OTA_PACKAGE, tenantEntityPermissionChecker);
46 46 put(Resource.EDGE, tenantEntityPermissionChecker);
47 47 }
48 48
... ...
... ... @@ -26,27 +26,27 @@ import lombok.extern.slf4j.Slf4j;
26 26 import org.springframework.stereotype.Service;
27 27 import org.springframework.util.StringUtils;
28 28 import org.thingsboard.common.util.JacksonUtil;
29   -import org.thingsboard.server.cache.firmware.FirmwareDataCache;
  29 +import org.thingsboard.server.cache.ota.OtaPackageDataCache;
30 30 import org.thingsboard.server.common.data.ApiUsageState;
31 31 import org.thingsboard.server.common.data.DataConstants;
32 32 import org.thingsboard.server.common.data.Device;
33 33 import org.thingsboard.server.common.data.DeviceProfile;
34 34 import org.thingsboard.server.common.data.DeviceTransportType;
35 35 import org.thingsboard.server.common.data.EntityType;
36   -import org.thingsboard.server.common.data.Firmware;
37   -import org.thingsboard.server.common.data.FirmwareInfo;
  36 +import org.thingsboard.server.common.data.OtaPackage;
  37 +import org.thingsboard.server.common.data.OtaPackageInfo;
38 38 import org.thingsboard.server.common.data.ResourceType;
39 39 import org.thingsboard.server.common.data.TbResource;
40 40 import org.thingsboard.server.common.data.TenantProfile;
41 41 import org.thingsboard.server.common.data.device.credentials.BasicMqttCredentials;
42 42 import org.thingsboard.server.common.data.device.credentials.ProvisionDeviceCredentialsData;
43 43 import org.thingsboard.server.common.data.device.profile.ProvisionDeviceProfileCredentials;
44   -import org.thingsboard.server.common.data.firmware.FirmwareType;
45   -import org.thingsboard.server.common.data.firmware.FirmwareUtil;
  44 +import org.thingsboard.server.common.data.ota.OtaPackageType;
  45 +import org.thingsboard.server.common.data.ota.OtaPackageUtil;
46 46 import org.thingsboard.server.common.data.id.CustomerId;
47 47 import org.thingsboard.server.common.data.id.DeviceId;
48 48 import org.thingsboard.server.common.data.id.DeviceProfileId;
49   -import org.thingsboard.server.common.data.id.FirmwareId;
  49 +import org.thingsboard.server.common.data.id.OtaPackageId;
50 50 import org.thingsboard.server.common.data.id.TenantId;
51 51 import org.thingsboard.server.common.data.page.PageData;
52 52 import org.thingsboard.server.common.data.page.PageLink;
... ... @@ -64,7 +64,7 @@ import org.thingsboard.server.dao.device.DeviceService;
64 64 import org.thingsboard.server.dao.device.provision.ProvisionFailedException;
65 65 import org.thingsboard.server.dao.device.provision.ProvisionRequest;
66 66 import org.thingsboard.server.dao.device.provision.ProvisionResponse;
67   -import org.thingsboard.server.dao.firmware.FirmwareService;
  67 +import org.thingsboard.server.dao.ota.OtaPackageService;
68 68 import org.thingsboard.server.dao.relation.RelationService;
69 69 import org.thingsboard.server.dao.tenant.TbTenantProfileCache;
70 70 import org.thingsboard.server.gen.transport.TransportProtos;
... ... @@ -124,8 +124,8 @@ public class DefaultTransportApiService implements TransportApiService {
124 124 private final DataDecodingEncodingService dataDecodingEncodingService;
125 125 private final DeviceProvisionService deviceProvisionService;
126 126 private final TbResourceService resourceService;
127   - private final FirmwareService firmwareService;
128   - private final FirmwareDataCache firmwareDataCache;
  127 + private final OtaPackageService otaPackageService;
  128 + private final OtaPackageDataCache otaPackageDataCache;
129 129
130 130 private final ConcurrentMap<String, ReentrantLock> deviceCreationLocks = new ConcurrentHashMap<>();
131 131
... ... @@ -134,7 +134,7 @@ public class DefaultTransportApiService implements TransportApiService {
134 134 RelationService relationService, DeviceCredentialsService deviceCredentialsService,
135 135 DeviceStateService deviceStateService, DbCallbackExecutorService dbCallbackExecutorService,
136 136 TbClusterService tbClusterService, DataDecodingEncodingService dataDecodingEncodingService,
137   - DeviceProvisionService deviceProvisionService, TbResourceService resourceService, FirmwareService firmwareService, FirmwareDataCache firmwareDataCache) {
  137 + DeviceProvisionService deviceProvisionService, TbResourceService resourceService, OtaPackageService otaPackageService, OtaPackageDataCache otaPackageDataCache) {
138 138 this.deviceProfileCache = deviceProfileCache;
139 139 this.tenantProfileCache = tenantProfileCache;
140 140 this.apiUsageStateService = apiUsageStateService;
... ... @@ -147,8 +147,8 @@ public class DefaultTransportApiService implements TransportApiService {
147 147 this.dataDecodingEncodingService = dataDecodingEncodingService;
148 148 this.deviceProvisionService = deviceProvisionService;
149 149 this.resourceService = resourceService;
150   - this.firmwareService = firmwareService;
151   - this.firmwareDataCache = firmwareDataCache;
  150 + this.otaPackageService = otaPackageService;
  151 + this.otaPackageDataCache = otaPackageDataCache;
152 152 }
153 153
154 154 @Override
... ... @@ -184,8 +184,8 @@ public class DefaultTransportApiService implements TransportApiService {
184 184 result = handle(transportApiRequestMsg.getDeviceRequestMsg());
185 185 } else if (transportApiRequestMsg.hasDeviceCredentialsRequestMsg()) {
186 186 result = handle(transportApiRequestMsg.getDeviceCredentialsRequestMsg());
187   - } else if (transportApiRequestMsg.hasFirmwareRequestMsg()) {
188   - result = handle(transportApiRequestMsg.getFirmwareRequestMsg());
  187 + } else if (transportApiRequestMsg.hasOtaPackageRequestMsg()) {
  188 + result = handle(transportApiRequestMsg.getOtaPackageRequestMsg());
189 189 }
190 190
191 191 return Futures.transform(Optional.ofNullable(result).orElseGet(this::getEmptyTransportApiResponseFuture),
... ... @@ -511,50 +511,50 @@ public class DefaultTransportApiService implements TransportApiService {
511 511 }
512 512 }
513 513
514   - private ListenableFuture<TransportApiResponseMsg> handle(TransportProtos.GetFirmwareRequestMsg requestMsg) {
  514 + private ListenableFuture<TransportApiResponseMsg> handle(TransportProtos.GetOtaPackageRequestMsg requestMsg) {
515 515 TenantId tenantId = new TenantId(new UUID(requestMsg.getTenantIdMSB(), requestMsg.getTenantIdLSB()));
516 516 DeviceId deviceId = new DeviceId(new UUID(requestMsg.getDeviceIdMSB(), requestMsg.getDeviceIdLSB()));
517   - FirmwareType firmwareType = FirmwareType.valueOf(requestMsg.getType());
  517 + OtaPackageType otaPackageType = OtaPackageType.valueOf(requestMsg.getType());
518 518 Device device = deviceService.findDeviceById(tenantId, deviceId);
519 519
520 520 if (device == null) {
521 521 return getEmptyTransportApiResponseFuture();
522 522 }
523 523
524   - FirmwareId firmwareId = FirmwareUtil.getFirmwareId(device, firmwareType);
525   - if (firmwareId == null) {
  524 + OtaPackageId otaPackageId = OtaPackageUtil.getOtaPackageId(device, otaPackageType);
  525 + if (otaPackageId == null) {
526 526 DeviceProfile deviceProfile = deviceProfileCache.find(device.getDeviceProfileId());
527   - firmwareId = FirmwareUtil.getFirmwareId(deviceProfile, firmwareType);
  527 + otaPackageId = OtaPackageUtil.getOtaPackageId(deviceProfile, otaPackageType);
528 528 }
529 529
530   - TransportProtos.GetFirmwareResponseMsg.Builder builder = TransportProtos.GetFirmwareResponseMsg.newBuilder();
  530 + TransportProtos.GetOtaPackageResponseMsg.Builder builder = TransportProtos.GetOtaPackageResponseMsg.newBuilder();
531 531
532   - if (firmwareId == null) {
  532 + if (otaPackageId == null) {
533 533 builder.setResponseStatus(TransportProtos.ResponseStatus.NOT_FOUND);
534 534 } else {
535   - FirmwareInfo firmwareInfo = firmwareService.findFirmwareInfoById(tenantId, firmwareId);
  535 + OtaPackageInfo otaPackageInfo = otaPackageService.findOtaPackageInfoById(tenantId, otaPackageId);
536 536
537   - if (firmwareInfo == null) {
  537 + if (otaPackageInfo == null) {
538 538 builder.setResponseStatus(TransportProtos.ResponseStatus.NOT_FOUND);
539 539 } else {
540 540 builder.setResponseStatus(TransportProtos.ResponseStatus.SUCCESS);
541   - builder.setFirmwareIdMSB(firmwareId.getId().getMostSignificantBits());
542   - builder.setFirmwareIdLSB(firmwareId.getId().getLeastSignificantBits());
543   - builder.setType(firmwareInfo.getType().name());
544   - builder.setTitle(firmwareInfo.getTitle());
545   - builder.setVersion(firmwareInfo.getVersion());
546   - builder.setFileName(firmwareInfo.getFileName());
547   - builder.setContentType(firmwareInfo.getContentType());
548   - if (!firmwareDataCache.has(firmwareId.toString())) {
549   - Firmware firmware = firmwareService.findFirmwareById(tenantId, firmwareId);
550   - firmwareDataCache.put(firmwareId.toString(), firmware.getData().array());
  541 + builder.setOtaPackageIdMSB(otaPackageId.getId().getMostSignificantBits());
  542 + builder.setOtaPackageIdLSB(otaPackageId.getId().getLeastSignificantBits());
  543 + builder.setType(otaPackageInfo.getType().name());
  544 + builder.setTitle(otaPackageInfo.getTitle());
  545 + builder.setVersion(otaPackageInfo.getVersion());
  546 + builder.setFileName(otaPackageInfo.getFileName());
  547 + builder.setContentType(otaPackageInfo.getContentType());
  548 + if (!otaPackageDataCache.has(otaPackageId.toString())) {
  549 + OtaPackage otaPackage = otaPackageService.findOtaPackageById(tenantId, otaPackageId);
  550 + otaPackageDataCache.put(otaPackageId.toString(), otaPackage.getData().array());
551 551 }
552 552 }
553 553 }
554 554
555 555 return Futures.immediateFuture(
556 556 TransportApiResponseMsg.newBuilder()
557   - .setFirmwareResponseMsg(builder.build())
  557 + .setOtaPackageResponseMsg(builder.build())
558 558 .build());
559 559 }
560 560
... ...
... ... @@ -17,9 +17,9 @@ package org.thingsboard.server.service.ttl;
17 17
18 18 import lombok.extern.slf4j.Slf4j;
19 19 import org.springframework.beans.factory.annotation.Value;
20   -import org.thingsboard.server.dao.util.PsqlDao;
21 20
22 21 import java.sql.Connection;
  22 +import java.sql.DriverManager;
23 23 import java.sql.ResultSet;
24 24 import java.sql.SQLException;
25 25 import java.sql.SQLWarning;
... ... @@ -62,4 +62,8 @@ public abstract class AbstractCleanUpService {
62 62
63 63 protected abstract void doCleanUp(Connection connection) throws SQLException;
64 64
  65 + protected Connection getConnection() throws SQLException {
  66 + return DriverManager.getConnection(dbUrl, dbUserName, dbPassword);
  67 + }
  68 +
65 69 }
... ...
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.service.ttl.alarms;
  17 +
  18 +import lombok.RequiredArgsConstructor;
  19 +import lombok.extern.slf4j.Slf4j;
  20 +import org.springframework.beans.factory.annotation.Value;
  21 +import org.springframework.scheduling.annotation.Scheduled;
  22 +import org.springframework.stereotype.Service;
  23 +import org.thingsboard.server.common.data.alarm.Alarm;
  24 +import org.thingsboard.server.common.data.audit.ActionType;
  25 +import org.thingsboard.server.common.data.id.AlarmId;
  26 +import org.thingsboard.server.common.data.id.TenantId;
  27 +import org.thingsboard.server.common.data.page.PageData;
  28 +import org.thingsboard.server.common.data.page.PageLink;
  29 +import org.thingsboard.server.common.data.page.SortOrder;
  30 +import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration;
  31 +import org.thingsboard.server.common.msg.queue.ServiceType;
  32 +import org.thingsboard.server.dao.alarm.AlarmDao;
  33 +import org.thingsboard.server.dao.alarm.AlarmService;
  34 +import org.thingsboard.server.dao.relation.RelationService;
  35 +import org.thingsboard.server.dao.tenant.TbTenantProfileCache;
  36 +import org.thingsboard.server.dao.tenant.TenantDao;
  37 +import org.thingsboard.server.dao.util.PsqlDao;
  38 +import org.thingsboard.server.queue.discovery.PartitionService;
  39 +import org.thingsboard.server.queue.util.TbCoreComponent;
  40 +import org.thingsboard.server.service.action.RuleEngineEntityActionService;
  41 +import org.thingsboard.server.service.ttl.AbstractCleanUpService;
  42 +
  43 +import java.sql.Connection;
  44 +import java.sql.SQLException;
  45 +import java.util.Date;
  46 +import java.util.Optional;
  47 +import java.util.UUID;
  48 +import java.util.concurrent.TimeUnit;
  49 +
  50 +@TbCoreComponent
  51 +@Service
  52 +@Slf4j
  53 +@RequiredArgsConstructor
  54 +public class AlarmsCleanUpService {
  55 + @Value("${sql.ttl.alarms.removal_batch_size}")
  56 + private Integer removalBatchSize;
  57 +
  58 + private final TenantDao tenantDao;
  59 + private final AlarmDao alarmDao;
  60 + private final AlarmService alarmService;
  61 + private final RelationService relationService;
  62 + private final RuleEngineEntityActionService ruleEngineEntityActionService;
  63 + private final PartitionService partitionService;
  64 + private final TbTenantProfileCache tenantProfileCache;
  65 +
  66 + @Scheduled(initialDelayString = "#{T(org.apache.commons.lang3.RandomUtils).nextLong(0, ${sql.ttl.alarms.checking_interval})}", fixedDelayString = "${sql.ttl.alarms.checking_interval}")
  67 + public void cleanUp() {
  68 + PageLink tenantsBatchRequest = new PageLink(10_000, 0);
  69 + PageLink removalBatchRequest = new PageLink(removalBatchSize, 0 );
  70 + PageData<TenantId> tenantsIds;
  71 + do {
  72 + tenantsIds = tenantDao.findTenantsIds(tenantsBatchRequest);
  73 + for (TenantId tenantId : tenantsIds.getData()) {
  74 + if (!partitionService.resolve(ServiceType.TB_CORE, tenantId, tenantId).isMyPartition()) {
  75 + continue;
  76 + }
  77 +
  78 + Optional<DefaultTenantProfileConfiguration> tenantProfileConfiguration = tenantProfileCache.get(tenantId).getProfileConfiguration();
  79 + if (tenantProfileConfiguration.isEmpty() || tenantProfileConfiguration.get().getAlarmsTtlDays() == 0) {
  80 + continue;
  81 + }
  82 +
  83 + long ttl = TimeUnit.DAYS.toMillis(tenantProfileConfiguration.get().getAlarmsTtlDays());
  84 + long expirationTime = System.currentTimeMillis() - ttl;
  85 +
  86 + long totalRemoved = 0;
  87 + while (true) {
  88 + PageData<AlarmId> toRemove = alarmDao.findAlarmsIdsByEndTsBeforeAndTenantId(expirationTime, tenantId, removalBatchRequest);
  89 + toRemove.getData().forEach(alarmId -> {
  90 + relationService.deleteEntityRelations(tenantId, alarmId);
  91 + Alarm alarm = alarmService.deleteAlarm(tenantId, alarmId).getAlarm();
  92 + ruleEngineEntityActionService.pushEntityActionToRuleEngine(alarm.getOriginator(), alarm, tenantId, null, ActionType.ALARM_DELETE, null);
  93 + });
  94 +
  95 + totalRemoved += toRemove.getTotalElements();
  96 + if (!toRemove.hasNext()) {
  97 + break;
  98 + }
  99 + }
  100 +
  101 + if (totalRemoved > 0) {
  102 + log.info("Removed {} outdated alarm(s) for tenant {} older than {}", totalRemoved, tenantId, new Date(expirationTime));
  103 + }
  104 + }
  105 +
  106 + tenantsBatchRequest = tenantsBatchRequest.nextPageLink();
  107 + } while (tenantsIds.hasNext());
  108 + }
  109 +
  110 +}
... ...
... ... @@ -40,7 +40,7 @@ public class EdgeEventsCleanUpService extends AbstractCleanUpService {
40 40 @Scheduled(initialDelayString = "${sql.ttl.edge_events.execution_interval_ms}", fixedDelayString = "${sql.ttl.edge_events.execution_interval_ms}")
41 41 public void cleanUp() {
42 42 if (ttlTaskExecutionEnabled) {
43   - try (Connection conn = DriverManager.getConnection(dbUrl, dbUserName, dbPassword)) {
  43 + try (Connection conn = getConnection()) {
44 44 doCleanUp(conn);
45 45 } catch (SQLException e) {
46 46 log.error("SQLException occurred during TTL task execution ", e);
... ...
... ... @@ -43,7 +43,7 @@ public class EventsCleanUpService extends AbstractCleanUpService {
43 43 @Scheduled(initialDelayString = "${sql.ttl.events.execution_interval_ms}", fixedDelayString = "${sql.ttl.events.execution_interval_ms}")
44 44 public void cleanUp() {
45 45 if (ttlTaskExecutionEnabled) {
46   - try (Connection conn = DriverManager.getConnection(dbUrl, dbUserName, dbPassword)) {
  46 + try (Connection conn = getConnection()) {
47 47 doCleanUp(conn);
48 48 } catch (SQLException e) {
49 49 log.error("SQLException occurred during TTL task execution ", e);
... ...
... ... @@ -36,7 +36,7 @@ public abstract class AbstractTimeseriesCleanUpService extends AbstractCleanUpSe
36 36 @Scheduled(initialDelayString = "${sql.ttl.ts.execution_interval_ms}", fixedDelayString = "${sql.ttl.ts.execution_interval_ms}")
37 37 public void cleanUp() {
38 38 if (ttlTaskExecutionEnabled) {
39   - try (Connection conn = DriverManager.getConnection(dbUrl, dbUserName, dbPassword)) {
  39 + try (Connection conn = getConnection()) {
40 40 doCleanUp(conn);
41 41 } catch (SQLException e) {
42 42 log.error("SQLException occurred during TTL task execution ", e);
... ...
... ... @@ -273,6 +273,9 @@ sql:
273 273 enabled: "${SQL_TTL_EDGE_EVENTS_ENABLED:true}"
274 274 execution_interval_ms: "${SQL_TTL_EDGE_EVENTS_EXECUTION_INTERVAL:86400000}" # Number of milliseconds. The current value corresponds to one day
275 275 edge_events_ttl: "${SQL_TTL_EDGE_EVENTS_TTL:2628000}" # Number of seconds. The current value corresponds to one month
  276 + alarms:
  277 + checking_interval: "${SQL_ALARMS_TTL_CHECKING_INTERVAL:7200000}" # Number of milliseconds. The current value corresponds to two hours
  278 + removal_batch_size: "${SQL_ALARMS_TTL_REMOVAL_BATCH_SIZE:3000}" # To delete outdated alarms not all at once but in batches
276 279
277 280 # Actor system parameters
278 281 actors:
... ... @@ -371,7 +374,10 @@ caffeine:
371 374 tokensOutdatageTime:
372 375 timeToLiveInMinutes: 20000
373 376 maxSize: 10000
374   - firmwares:
  377 + otaPackages:
  378 + timeToLiveInMinutes: 60
  379 + maxSize: 10
  380 + otaPackagesData:
375 381 timeToLiveInMinutes: 60
376 382 maxSize: 10
377 383 edges:
... ... @@ -497,7 +503,7 @@ audit-log:
497 503 "device_profile": "${AUDIT_LOG_MASK_DEVICE_PROFILE:W}"
498 504 "edge": "${AUDIT_LOG_MASK_EDGE:W}"
499 505 "tb_resource": "${AUDIT_LOG_MASK_RESOURCE:W}"
500   - "firmware": "${AUDIT_LOG_MASK_FIRMWARE:W}"
  506 + "ota_package": "${AUDIT_LOG_MASK_OTA_PACKAGE:W}"
501 507 sink:
502 508 # Type of external sink. possible options: none, elasticsearch
503 509 type: "${AUDIT_LOG_SINK_TYPE:none}"
... ... @@ -749,7 +755,7 @@ queue:
749 755 sasl.config: "${TB_QUEUE_KAFKA_CONFLUENT_SASL_JAAS_CONFIG:org.apache.kafka.common.security.plain.PlainLoginModule required username=\"CLUSTER_API_KEY\" password=\"CLUSTER_API_SECRET\";}"
750 756 security.protocol: "${TB_QUEUE_KAFKA_CONFLUENT_SECURITY_PROTOCOL:SASL_SSL}"
751 757 consumer-properties-per-topic:
752   - tb_firmware:
  758 + tb_ota_package:
753 759 - key: max.poll.records
754 760 value: 10
755 761 other:
... ... @@ -759,7 +765,7 @@ queue:
759 765 transport-api: "${TB_QUEUE_KAFKA_TA_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:1048576000;partitions:1;min.insync.replicas:1}"
760 766 notifications: "${TB_QUEUE_KAFKA_NOTIFICATIONS_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:1048576000;partitions:1;min.insync.replicas:1}"
761 767 js-executor: "${TB_QUEUE_KAFKA_JE_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:104857600;partitions:100;min.insync.replicas:1}"
762   - fw-updates: "${TB_QUEUE_KAFKA_FW_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:1048576000;partitions:10;min.insync.replicas:1}"
  768 + ota-updates: "${TB_QUEUE_KAFKA_OTA_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:1048576000;partitions:10;min.insync.replicas:1}"
763 769 consumer-stats:
764 770 enabled: "${TB_QUEUE_KAFKA_CONSUMER_STATS_ENABLED:true}"
765 771 print-interval-ms: "${TB_QUEUE_KAFKA_CONSUMER_STATS_MIN_PRINT_INTERVAL_MS:60000}"
... ... @@ -830,10 +836,10 @@ queue:
830 836 poll-interval: "${TB_QUEUE_CORE_POLL_INTERVAL_MS:25}"
831 837 partitions: "${TB_QUEUE_CORE_PARTITIONS:10}"
832 838 pack-processing-timeout: "${TB_QUEUE_CORE_PACK_PROCESSING_TIMEOUT_MS:2000}"
833   - firmware:
834   - topic: "${TB_QUEUE_CORE_FW_TOPIC:tb_firmware}"
835   - pack-interval-ms: "${TB_QUEUE_CORE_FW_PACK_INTERVAL_MS:60000}"
836   - pack-size: "${TB_QUEUE_CORE_FW_PACK_SIZE:100}"
  839 + ota:
  840 + topic: "${TB_QUEUE_CORE_OTA_TOPIC:tb_ota_package}"
  841 + pack-interval-ms: "${TB_QUEUE_CORE_OTA_PACK_INTERVAL_MS:60000}"
  842 + pack-size: "${TB_QUEUE_CORE_OTA_PACK_SIZE:100}"
837 843 usage-stats-topic: "${TB_QUEUE_US_TOPIC:tb_usage_stats}"
838 844 stats:
839 845 enabled: "${TB_QUEUE_CORE_STATS_ENABLED:true}"
... ...
application/src/test/java/org/thingsboard/server/controller/BaseOtaPackageControllerTest.java renamed from application/src/test/java/org/thingsboard/server/controller/BaseFirmwareControllerTest.java
... ... @@ -25,11 +25,10 @@ import org.springframework.test.web.servlet.request.MockMultipartHttpServletRequ
25 25 import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
26 26 import org.thingsboard.common.util.JacksonUtil;
27 27 import org.thingsboard.server.common.data.DeviceProfile;
28   -import org.thingsboard.server.common.data.Firmware;
29   -import org.thingsboard.server.common.data.FirmwareInfo;
  28 +import org.thingsboard.server.common.data.OtaPackage;
  29 +import org.thingsboard.server.common.data.OtaPackageInfo;
30 30 import org.thingsboard.server.common.data.Tenant;
31 31 import org.thingsboard.server.common.data.User;
32   -import org.thingsboard.server.common.data.firmware.FirmwareType;
33 32 import org.thingsboard.server.common.data.id.DeviceProfileId;
34 33 import org.thingsboard.server.common.data.page.PageData;
35 34 import org.thingsboard.server.common.data.page.PageLink;
... ... @@ -41,11 +40,11 @@ import java.util.Collections;
41 40 import java.util.List;
42 41
43 42 import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
44   -import static org.thingsboard.server.common.data.firmware.FirmwareType.FIRMWARE;
  43 +import static org.thingsboard.server.common.data.ota.OtaPackageType.FIRMWARE;
45 44
46   -public abstract class BaseFirmwareControllerTest extends AbstractControllerTest {
  45 +public abstract class BaseOtaPackageControllerTest extends AbstractControllerTest {
47 46
48   - private IdComparator<FirmwareInfo> idComparator = new IdComparator<>();
  47 + private IdComparator<OtaPackageInfo> idComparator = new IdComparator<>();
49 48
50 49 public static final String TITLE = "My firmware";
51 50 private static final String FILE_NAME = "filename.txt";
... ... @@ -93,13 +92,13 @@ public abstract class BaseFirmwareControllerTest extends AbstractControllerTest
93 92
94 93 @Test
95 94 public void testSaveFirmware() throws Exception {
96   - FirmwareInfo firmwareInfo = new FirmwareInfo();
  95 + OtaPackageInfo firmwareInfo = new OtaPackageInfo();
97 96 firmwareInfo.setDeviceProfileId(deviceProfileId);
98 97 firmwareInfo.setType(FIRMWARE);
99 98 firmwareInfo.setTitle(TITLE);
100 99 firmwareInfo.setVersion(VERSION);
101 100
102   - FirmwareInfo savedFirmwareInfo = save(firmwareInfo);
  101 + OtaPackageInfo savedFirmwareInfo = save(firmwareInfo);
103 102
104 103 Assert.assertNotNull(savedFirmwareInfo);
105 104 Assert.assertNotNull(savedFirmwareInfo.getId());
... ... @@ -112,19 +111,19 @@ public abstract class BaseFirmwareControllerTest extends AbstractControllerTest
112 111
113 112 save(savedFirmwareInfo);
114 113
115   - FirmwareInfo foundFirmwareInfo = doGet("/api/firmware/info/" + savedFirmwareInfo.getId().getId().toString(), FirmwareInfo.class);
  114 + OtaPackageInfo foundFirmwareInfo = doGet("/api/otaPackage/info/" + savedFirmwareInfo.getId().getId().toString(), OtaPackageInfo.class);
116 115 Assert.assertEquals(foundFirmwareInfo.getTitle(), savedFirmwareInfo.getTitle());
117 116 }
118 117
119 118 @Test
120 119 public void testSaveFirmwareData() throws Exception {
121   - FirmwareInfo firmwareInfo = new FirmwareInfo();
  120 + OtaPackageInfo firmwareInfo = new OtaPackageInfo();
122 121 firmwareInfo.setDeviceProfileId(deviceProfileId);
123 122 firmwareInfo.setType(FIRMWARE);
124 123 firmwareInfo.setTitle(TITLE);
125 124 firmwareInfo.setVersion(VERSION);
126 125
127   - FirmwareInfo savedFirmwareInfo = save(firmwareInfo);
  126 + OtaPackageInfo savedFirmwareInfo = save(firmwareInfo);
128 127
129 128 Assert.assertNotNull(savedFirmwareInfo);
130 129 Assert.assertNotNull(savedFirmwareInfo.getId());
... ... @@ -137,12 +136,12 @@ public abstract class BaseFirmwareControllerTest extends AbstractControllerTest
137 136
138 137 save(savedFirmwareInfo);
139 138
140   - FirmwareInfo foundFirmwareInfo = doGet("/api/firmware/info/" + savedFirmwareInfo.getId().getId().toString(), FirmwareInfo.class);
  139 + OtaPackageInfo foundFirmwareInfo = doGet("/api/otaPackage/info/" + savedFirmwareInfo.getId().getId().toString(), OtaPackageInfo.class);
141 140 Assert.assertEquals(foundFirmwareInfo.getTitle(), savedFirmwareInfo.getTitle());
142 141
143 142 MockMultipartFile testData = new MockMultipartFile("file", FILE_NAME, CONTENT_TYPE, DATA.array());
144 143
145   - Firmware savedFirmware = savaData("/api/firmware/" + savedFirmwareInfo.getId().getId().toString() + "?checksum={checksum}&checksumAlgorithm={checksumAlgorithm}", testData, CHECKSUM, CHECKSUM_ALGORITHM);
  144 + OtaPackage savedFirmware = savaData("/api/otaPackage/" + savedFirmwareInfo.getId().getId().toString() + "?checksum={checksum}&checksumAlgorithm={checksumAlgorithm}", testData, CHECKSUM, CHECKSUM_ALGORITHM);
146 145
147 146 Assert.assertEquals(FILE_NAME, savedFirmware.getFileName());
148 147 Assert.assertEquals(CONTENT_TYPE, savedFirmware.getContentType());
... ... @@ -150,97 +149,97 @@ public abstract class BaseFirmwareControllerTest extends AbstractControllerTest
150 149
151 150 @Test
152 151 public void testUpdateFirmwareFromDifferentTenant() throws Exception {
153   - FirmwareInfo firmwareInfo = new FirmwareInfo();
  152 + OtaPackageInfo firmwareInfo = new OtaPackageInfo();
154 153 firmwareInfo.setDeviceProfileId(deviceProfileId);
155 154 firmwareInfo.setType(FIRMWARE);
156 155 firmwareInfo.setTitle(TITLE);
157 156 firmwareInfo.setVersion(VERSION);
158 157
159   - FirmwareInfo savedFirmwareInfo = save(firmwareInfo);
  158 + OtaPackageInfo savedFirmwareInfo = save(firmwareInfo);
160 159
161 160 loginDifferentTenant();
162   - doPost("/api/firmware", savedFirmwareInfo, FirmwareInfo.class, status().isForbidden());
  161 + doPost("/api/otaPackage", savedFirmwareInfo, OtaPackageInfo.class, status().isForbidden());
163 162 deleteDifferentTenant();
164 163 }
165 164
166 165 @Test
167 166 public void testFindFirmwareInfoById() throws Exception {
168   - FirmwareInfo firmwareInfo = new FirmwareInfo();
  167 + OtaPackageInfo firmwareInfo = new OtaPackageInfo();
169 168 firmwareInfo.setDeviceProfileId(deviceProfileId);
170 169 firmwareInfo.setType(FIRMWARE);
171 170 firmwareInfo.setTitle(TITLE);
172 171 firmwareInfo.setVersion(VERSION);
173 172
174   - FirmwareInfo savedFirmwareInfo = save(firmwareInfo);
  173 + OtaPackageInfo savedFirmwareInfo = save(firmwareInfo);
175 174
176   - FirmwareInfo foundFirmware = doGet("/api/firmware/info/" + savedFirmwareInfo.getId().getId().toString(), FirmwareInfo.class);
  175 + OtaPackageInfo foundFirmware = doGet("/api/otaPackage/info/" + savedFirmwareInfo.getId().getId().toString(), OtaPackageInfo.class);
177 176 Assert.assertNotNull(foundFirmware);
178 177 Assert.assertEquals(savedFirmwareInfo, foundFirmware);
179 178 }
180 179
181 180 @Test
182 181 public void testFindFirmwareById() throws Exception {
183   - FirmwareInfo firmwareInfo = new FirmwareInfo();
  182 + OtaPackageInfo firmwareInfo = new OtaPackageInfo();
184 183 firmwareInfo.setDeviceProfileId(deviceProfileId);
185 184 firmwareInfo.setType(FIRMWARE);
186 185 firmwareInfo.setTitle(TITLE);
187 186 firmwareInfo.setVersion(VERSION);
188 187
189   - FirmwareInfo savedFirmwareInfo = save(firmwareInfo);
  188 + OtaPackageInfo savedFirmwareInfo = save(firmwareInfo);
190 189
191 190 MockMultipartFile testData = new MockMultipartFile("file", FILE_NAME, CONTENT_TYPE, DATA.array());
192 191
193   - Firmware savedFirmware = savaData("/api/firmware/" + savedFirmwareInfo.getId().getId().toString() + "?checksum={checksum}&checksumAlgorithm={checksumAlgorithm}", testData, CHECKSUM, CHECKSUM_ALGORITHM);
  192 + OtaPackage savedFirmware = savaData("/api/otaPackage/" + savedFirmwareInfo.getId().getId().toString() + "?checksum={checksum}&checksumAlgorithm={checksumAlgorithm}", testData, CHECKSUM, CHECKSUM_ALGORITHM);
194 193
195   - Firmware foundFirmware = doGet("/api/firmware/" + savedFirmwareInfo.getId().getId().toString(), Firmware.class);
  194 + OtaPackage foundFirmware = doGet("/api/otaPackage/" + savedFirmwareInfo.getId().getId().toString(), OtaPackage.class);
196 195 Assert.assertNotNull(foundFirmware);
197 196 Assert.assertEquals(savedFirmware, foundFirmware);
198 197 }
199 198
200 199 @Test
201 200 public void testDeleteFirmware() throws Exception {
202   - FirmwareInfo firmwareInfo = new FirmwareInfo();
  201 + OtaPackageInfo firmwareInfo = new OtaPackageInfo();
203 202 firmwareInfo.setDeviceProfileId(deviceProfileId);
204 203 firmwareInfo.setType(FIRMWARE);
205 204 firmwareInfo.setTitle(TITLE);
206 205 firmwareInfo.setVersion(VERSION);
207 206
208   - FirmwareInfo savedFirmwareInfo = save(firmwareInfo);
  207 + OtaPackageInfo savedFirmwareInfo = save(firmwareInfo);
209 208
210   - doDelete("/api/firmware/" + savedFirmwareInfo.getId().getId().toString())
  209 + doDelete("/api/otaPackage/" + savedFirmwareInfo.getId().getId().toString())
211 210 .andExpect(status().isOk());
212 211
213   - doGet("/api/firmware/info/" + savedFirmwareInfo.getId().getId().toString())
  212 + doGet("/api/otaPackage/info/" + savedFirmwareInfo.getId().getId().toString())
214 213 .andExpect(status().isNotFound());
215 214 }
216 215
217 216 @Test
218 217 public void testFindTenantFirmwares() throws Exception {
219   - List<FirmwareInfo> firmwares = new ArrayList<>();
  218 + List<OtaPackageInfo> otaPackages = new ArrayList<>();
220 219 for (int i = 0; i < 165; i++) {
221   - FirmwareInfo firmwareInfo = new FirmwareInfo();
  220 + OtaPackageInfo firmwareInfo = new OtaPackageInfo();
222 221 firmwareInfo.setDeviceProfileId(deviceProfileId);
223 222 firmwareInfo.setType(FIRMWARE);
224 223 firmwareInfo.setTitle(TITLE);
225 224 firmwareInfo.setVersion(VERSION + i);
226 225
227   - FirmwareInfo savedFirmwareInfo = save(firmwareInfo);
  226 + OtaPackageInfo savedFirmwareInfo = save(firmwareInfo);
228 227
229 228 if (i > 100) {
230 229 MockMultipartFile testData = new MockMultipartFile("file", FILE_NAME, CONTENT_TYPE, DATA.array());
231 230
232   - Firmware savedFirmware = savaData("/api/firmware/" + savedFirmwareInfo.getId().getId().toString() + "?checksum={checksum}&checksumAlgorithm={checksumAlgorithm}", testData, CHECKSUM, CHECKSUM_ALGORITHM);
233   - firmwares.add(new FirmwareInfo(savedFirmware));
  231 + OtaPackage savedFirmware = savaData("/api/otaPackage/" + savedFirmwareInfo.getId().getId().toString() + "?checksum={checksum}&checksumAlgorithm={checksumAlgorithm}", testData, CHECKSUM, CHECKSUM_ALGORITHM);
  232 + otaPackages.add(new OtaPackageInfo(savedFirmware));
234 233 } else {
235   - firmwares.add(savedFirmwareInfo);
  234 + otaPackages.add(savedFirmwareInfo);
236 235 }
237 236 }
238 237
239   - List<FirmwareInfo> loadedFirmwares = new ArrayList<>();
  238 + List<OtaPackageInfo> loadedFirmwares = new ArrayList<>();
240 239 PageLink pageLink = new PageLink(24);
241   - PageData<FirmwareInfo> pageData;
  240 + PageData<OtaPackageInfo> pageData;
242 241 do {
243   - pageData = doGetTypedWithPageLink("/api/firmwares?",
  242 + pageData = doGetTypedWithPageLink("/api/otaPackages?",
244 243 new TypeReference<>() {
245 244 }, pageLink);
246 245 loadedFirmwares.addAll(pageData.getData());
... ... @@ -249,41 +248,41 @@ public abstract class BaseFirmwareControllerTest extends AbstractControllerTest
249 248 }
250 249 } while (pageData.hasNext());
251 250
252   - Collections.sort(firmwares, idComparator);
  251 + Collections.sort(otaPackages, idComparator);
253 252 Collections.sort(loadedFirmwares, idComparator);
254 253
255   - Assert.assertEquals(firmwares, loadedFirmwares);
  254 + Assert.assertEquals(otaPackages, loadedFirmwares);
256 255 }
257 256
258 257 @Test
259 258 public void testFindTenantFirmwaresByHasData() throws Exception {
260   - List<FirmwareInfo> firmwaresWithData = new ArrayList<>();
261   - List<FirmwareInfo> firmwaresWithoutData = new ArrayList<>();
  259 + List<OtaPackageInfo> otaPackagesWithData = new ArrayList<>();
  260 + List<OtaPackageInfo> otaPackagesWithoutData = new ArrayList<>();
262 261
263 262 for (int i = 0; i < 165; i++) {
264   - FirmwareInfo firmwareInfo = new FirmwareInfo();
  263 + OtaPackageInfo firmwareInfo = new OtaPackageInfo();
265 264 firmwareInfo.setDeviceProfileId(deviceProfileId);
266 265 firmwareInfo.setType(FIRMWARE);
267 266 firmwareInfo.setTitle(TITLE);
268 267 firmwareInfo.setVersion(VERSION + i);
269 268
270   - FirmwareInfo savedFirmwareInfo = save(firmwareInfo);
  269 + OtaPackageInfo savedFirmwareInfo = save(firmwareInfo);
271 270
272 271 if (i > 100) {
273 272 MockMultipartFile testData = new MockMultipartFile("file", FILE_NAME, CONTENT_TYPE, DATA.array());
274 273
275   - Firmware savedFirmware = savaData("/api/firmware/" + savedFirmwareInfo.getId().getId().toString() + "?checksum={checksum}&checksumAlgorithm={checksumAlgorithm}", testData, CHECKSUM, CHECKSUM_ALGORITHM);
276   - firmwaresWithData.add(new FirmwareInfo(savedFirmware));
  274 + OtaPackage savedFirmware = savaData("/api/otaPackage/" + savedFirmwareInfo.getId().getId().toString() + "?checksum={checksum}&checksumAlgorithm={checksumAlgorithm}", testData, CHECKSUM, CHECKSUM_ALGORITHM);
  275 + otaPackagesWithData.add(new OtaPackageInfo(savedFirmware));
277 276 } else {
278   - firmwaresWithoutData.add(savedFirmwareInfo);
  277 + otaPackagesWithoutData.add(savedFirmwareInfo);
279 278 }
280 279 }
281 280
282   - List<FirmwareInfo> loadedFirmwaresWithData = new ArrayList<>();
  281 + List<OtaPackageInfo> loadedFirmwaresWithData = new ArrayList<>();
283 282 PageLink pageLink = new PageLink(24);
284   - PageData<FirmwareInfo> pageData;
  283 + PageData<OtaPackageInfo> pageData;
285 284 do {
286   - pageData = doGetTypedWithPageLink("/api/firmwares/" + deviceProfileId.toString() + "/FIRMWARE/true?",
  285 + pageData = doGetTypedWithPageLink("/api/otaPackages/" + deviceProfileId.toString() + "/FIRMWARE/true?",
287 286 new TypeReference<>() {
288 287 }, pageLink);
289 288 loadedFirmwaresWithData.addAll(pageData.getData());
... ... @@ -292,10 +291,10 @@ public abstract class BaseFirmwareControllerTest extends AbstractControllerTest
292 291 }
293 292 } while (pageData.hasNext());
294 293
295   - List<FirmwareInfo> loadedFirmwaresWithoutData = new ArrayList<>();
  294 + List<OtaPackageInfo> loadedFirmwaresWithoutData = new ArrayList<>();
296 295 pageLink = new PageLink(24);
297 296 do {
298   - pageData = doGetTypedWithPageLink("/api/firmwares/" + deviceProfileId.toString() + "/FIRMWARE/false?",
  297 + pageData = doGetTypedWithPageLink("/api/otaPackages/" + deviceProfileId.toString() + "/FIRMWARE/false?",
299 298 new TypeReference<>() {
300 299 }, pageLink);
301 300 loadedFirmwaresWithoutData.addAll(pageData.getData());
... ... @@ -304,25 +303,25 @@ public abstract class BaseFirmwareControllerTest extends AbstractControllerTest
304 303 }
305 304 } while (pageData.hasNext());
306 305
307   - Collections.sort(firmwaresWithData, idComparator);
308   - Collections.sort(firmwaresWithoutData, idComparator);
  306 + Collections.sort(otaPackagesWithData, idComparator);
  307 + Collections.sort(otaPackagesWithoutData, idComparator);
309 308 Collections.sort(loadedFirmwaresWithData, idComparator);
310 309 Collections.sort(loadedFirmwaresWithoutData, idComparator);
311 310
312   - Assert.assertEquals(firmwaresWithData, loadedFirmwaresWithData);
313   - Assert.assertEquals(firmwaresWithoutData, loadedFirmwaresWithoutData);
  311 + Assert.assertEquals(otaPackagesWithData, loadedFirmwaresWithData);
  312 + Assert.assertEquals(otaPackagesWithoutData, loadedFirmwaresWithoutData);
314 313 }
315 314
316 315
317   - private FirmwareInfo save(FirmwareInfo firmwareInfo) throws Exception {
318   - return doPost("/api/firmware", firmwareInfo, FirmwareInfo.class);
  316 + private OtaPackageInfo save(OtaPackageInfo firmwareInfo) throws Exception {
  317 + return doPost("/api/otaPackage", firmwareInfo, OtaPackageInfo.class);
319 318 }
320 319
321   - protected Firmware savaData(String urlTemplate, MockMultipartFile content, String... params) throws Exception {
  320 + protected OtaPackage savaData(String urlTemplate, MockMultipartFile content, String... params) throws Exception {
322 321 MockMultipartHttpServletRequestBuilder postRequest = MockMvcRequestBuilders.multipart(urlTemplate, params);
323 322 postRequest.file(content);
324 323 setJwtToken(postRequest);
325   - return readResponse(mockMvc.perform(postRequest).andExpect(status().isOk()), Firmware.class);
  324 + return readResponse(mockMvc.perform(postRequest).andExpect(status().isOk()), OtaPackage.class);
326 325 }
327 326
328 327 }
... ...
application/src/test/java/org/thingsboard/server/controller/sql/OtaPackageControllerSqlTest.java renamed from application/src/test/java/org/thingsboard/server/controller/sql/FirmwareControllerSqlTest.java
... ... @@ -15,9 +15,9 @@
15 15 */
16 16 package org.thingsboard.server.controller.sql;
17 17
18   -import org.thingsboard.server.controller.BaseFirmwareControllerTest;
  18 +import org.thingsboard.server.controller.BaseOtaPackageControllerTest;
19 19 import org.thingsboard.server.dao.service.DaoSqlTest;
20 20
21 21 @DaoSqlTest
22   -public class FirmwareControllerSqlTest extends BaseFirmwareControllerTest {
  22 +public class OtaPackageControllerSqlTest extends BaseOtaPackageControllerTest {
23 23 }
... ...
... ... @@ -44,6 +44,9 @@ public abstract class AbstractCoapAttributesUpdatesIntegrationTest extends Abstr
44 44
45 45 private static final String RESPONSE_ATTRIBUTES_PAYLOAD_DELETED = "{\"deleted\":[\"attribute5\"]}";
46 46
  47 + protected static final String POST_ATTRIBUTES_PAYLOAD_ON_CURRENT_STATE_NOTIFICATION = "{\"attribute1\":\"value\",\"attribute2\":false,\"attribute3\":41.0,\"attribute4\":72," +
  48 + "\"attribute5\":{\"someNumber\":41,\"someArray\":[],\"someNestedObject\":{\"key\":\"value\"}}}";
  49 +
47 50 @Before
48 51 public void beforeTest() throws Exception {
49 52 processBeforeTest("Test Subscribe to attribute updates", null, null);
... ... @@ -56,50 +59,85 @@ public abstract class AbstractCoapAttributesUpdatesIntegrationTest extends Abstr
56 59
57 60 @Test
58 61 public void testSubscribeToAttributesUpdatesFromTheServer() throws Exception {
59   - processTestSubscribeToAttributesUpdates();
  62 + processTestSubscribeToAttributesUpdates(false);
60 63 }
61 64
62   - protected void processTestSubscribeToAttributesUpdates() throws Exception {
  65 + @Test
  66 + public void testSubscribeToAttributesUpdatesFromTheServerWithEmptyCurrentStateNotification() throws Exception {
  67 + processTestSubscribeToAttributesUpdates(true);
  68 + }
63 69
  70 + protected void processTestSubscribeToAttributesUpdates(boolean emptyCurrentStateNotification) throws Exception {
  71 + if (!emptyCurrentStateNotification) {
  72 + doPostAsync("/api/plugins/telemetry/DEVICE/" + savedDevice.getId().getId() + "/attributes/SHARED_SCOPE", POST_ATTRIBUTES_PAYLOAD_ON_CURRENT_STATE_NOTIFICATION, String.class, status().isOk());
  73 + }
64 74 CoapClient client = getCoapClient(FeatureType.ATTRIBUTES);
65 75
66 76 CountDownLatch latch = new CountDownLatch(1);
67   - TestCoapCallback testCoapCallback = new TestCoapCallback(latch);
  77 + TestCoapCallback callback = new TestCoapCallback(latch);
68 78
69 79 Request request = Request.newGet().setObserve();
70 80 request.setType(CoAP.Type.CON);
71   - CoapObserveRelation observeRelation = client.observe(request, testCoapCallback);
  81 + CoapObserveRelation observeRelation = client.observe(request, callback);
72 82
73   - Thread.sleep(1000);
  83 + latch.await(3, TimeUnit.SECONDS);
  84 +
  85 + if (emptyCurrentStateNotification) {
  86 + validateEmptyCurrentStateAttributesResponse(callback);
  87 + } else {
  88 + validateCurrentStateAttributesResponse(callback);
  89 + }
  90 +
  91 + latch = new CountDownLatch(1);
74 92
75 93 doPostAsync("/api/plugins/telemetry/DEVICE/" + savedDevice.getId().getId() + "/attributes/SHARED_SCOPE", POST_ATTRIBUTES_PAYLOAD, String.class, status().isOk());
76 94 latch.await(3, TimeUnit.SECONDS);
77 95
78   - validateUpdateAttributesResponse(testCoapCallback);
  96 + validateUpdateAttributesResponse(callback);
79 97
80 98 latch = new CountDownLatch(1);
81 99
82 100 doDelete("/api/plugins/telemetry/DEVICE/" + savedDevice.getId().getId() + "/SHARED_SCOPE?keys=attribute5", String.class);
83 101 latch.await(3, TimeUnit.SECONDS);
84 102
85   - validateDeleteAttributesResponse(testCoapCallback);
  103 + validateDeleteAttributesResponse(callback);
86 104
87 105 observeRelation.proactiveCancel();
88 106 assertTrue(observeRelation.isCanceled());
89 107 }
90 108
91   - protected void validateUpdateAttributesResponse(TestCoapCallback callback) throws InvalidProtocolBufferException {
  109 + protected void validateCurrentStateAttributesResponse(TestCoapCallback callback) throws InvalidProtocolBufferException {
  110 + assertNotNull(callback.getPayloadBytes());
  111 + assertNotNull(callback.getObserve());
  112 + assertEquals(callback.getResponseCode(), CoAP.ResponseCode._UNKNOWN_SUCCESS_CODE);
  113 + assertEquals(0, callback.getObserve().intValue());
  114 + String response = new String(callback.getPayloadBytes(), StandardCharsets.UTF_8);
  115 + assertEquals(JacksonUtil.toJsonNode(POST_ATTRIBUTES_PAYLOAD_ON_CURRENT_STATE_NOTIFICATION), JacksonUtil.toJsonNode(response));
  116 + }
  117 +
  118 + protected void validateEmptyCurrentStateAttributesResponse(TestCoapCallback callback) throws InvalidProtocolBufferException {
92 119 assertNotNull(callback.getPayloadBytes());
93 120 assertNotNull(callback.getObserve());
  121 + assertEquals(callback.getResponseCode(), CoAP.ResponseCode._UNKNOWN_SUCCESS_CODE);
94 122 assertEquals(0, callback.getObserve().intValue());
95 123 String response = new String(callback.getPayloadBytes(), StandardCharsets.UTF_8);
  124 + assertEquals("{}", response);
  125 + }
  126 +
  127 + protected void validateUpdateAttributesResponse(TestCoapCallback callback) throws InvalidProtocolBufferException {
  128 + assertNotNull(callback.getPayloadBytes());
  129 + assertNotNull(callback.getObserve());
  130 + assertEquals(callback.getResponseCode(), CoAP.ResponseCode._UNKNOWN_SUCCESS_CODE);
  131 + assertEquals(1, callback.getObserve().intValue());
  132 + String response = new String(callback.getPayloadBytes(), StandardCharsets.UTF_8);
96 133 assertEquals(JacksonUtil.toJsonNode(POST_ATTRIBUTES_PAYLOAD), JacksonUtil.toJsonNode(response));
97 134 }
98 135
99 136 protected void validateDeleteAttributesResponse(TestCoapCallback callback) throws InvalidProtocolBufferException {
100 137 assertNotNull(callback.getPayloadBytes());
101 138 assertNotNull(callback.getObserve());
102   - assertEquals(1, callback.getObserve().intValue());
  139 + assertEquals(callback.getResponseCode(), CoAP.ResponseCode._UNKNOWN_SUCCESS_CODE);
  140 + assertEquals(2, callback.getObserve().intValue());
103 141 String response = new String(callback.getPayloadBytes(), StandardCharsets.UTF_8);
104 142 assertEquals(JacksonUtil.toJsonNode(RESPONSE_ATTRIBUTES_PAYLOAD_DELETED), JacksonUtil.toJsonNode(response));
105 143 }
... ... @@ -110,13 +148,18 @@ public abstract class AbstractCoapAttributesUpdatesIntegrationTest extends Abstr
110 148
111 149 private Integer observe;
112 150 private byte[] payloadBytes;
  151 + private CoAP.ResponseCode responseCode;
  152 +
  153 + public Integer getObserve() {
  154 + return observe;
  155 + }
113 156
114 157 public byte[] getPayloadBytes() {
115 158 return payloadBytes;
116 159 }
117 160
118   - public Integer getObserve() {
119   - return observe;
  161 + public CoAP.ResponseCode getResponseCode() {
  162 + return responseCode;
120 163 }
121 164
122 165 private TestCoapCallback(CountDownLatch latch) {
... ... @@ -125,10 +168,9 @@ public abstract class AbstractCoapAttributesUpdatesIntegrationTest extends Abstr
125 168
126 169 @Override
127 170 public void onLoad(CoapResponse response) {
128   - assertNotNull(response.getPayload());
129   - assertEquals(response.getCode(), CoAP.ResponseCode.CONTENT);
130 171 observe = response.getOptions().getObserve();
131 172 payloadBytes = response.getPayload();
  173 + responseCode = response.getCode();
132 174 latch.countDown();
133 175 }
134 176
... ...
... ... @@ -39,4 +39,9 @@ public abstract class AbstractCoapAttributesUpdatesJsonIntegrationTest extends A
39 39 public void testSubscribeToAttributesUpdatesFromTheServer() throws Exception {
40 40 super.testSubscribeToAttributesUpdatesFromTheServer();
41 41 }
  42 +
  43 + @Test
  44 + public void testSubscribeToAttributesUpdatesFromTheServerWithEmptyCurrentStateNotification() throws Exception {
  45 + super.testSubscribeToAttributesUpdatesFromTheServerWithEmptyCurrentStateNotification();
  46 + }
42 47 }
... ...
... ... @@ -17,6 +17,7 @@ package org.thingsboard.server.transport.coap.attributes.updates;
17 17
18 18 import com.google.protobuf.InvalidProtocolBufferException;
19 19 import lombok.extern.slf4j.Slf4j;
  20 +import org.eclipse.californium.core.coap.CoAP;
20 21 import org.junit.After;
21 22 import org.junit.Before;
22 23 import org.junit.Test;
... ... @@ -24,11 +25,15 @@ import org.thingsboard.server.common.data.CoapDeviceType;
24 25 import org.thingsboard.server.common.data.TransportPayloadType;
25 26 import org.thingsboard.server.gen.transport.TransportProtos;
26 27
  28 +import java.nio.charset.StandardCharsets;
  29 +import java.util.ArrayList;
  30 +import java.util.Collections;
27 31 import java.util.List;
28 32 import java.util.stream.Collectors;
29 33
30 34 import static org.junit.Assert.assertEquals;
31 35 import static org.junit.Assert.assertNotNull;
  36 +import static org.junit.Assert.assertNull;
32 37 import static org.junit.Assert.assertTrue;
33 38
34 39 @Slf4j
... ... @@ -46,11 +51,54 @@ public abstract class AbstractCoapAttributesUpdatesProtoIntegrationTest extends
46 51
47 52 @Test
48 53 public void testSubscribeToAttributesUpdatesFromTheServer() throws Exception {
49   - processTestSubscribeToAttributesUpdates();
  54 + processTestSubscribeToAttributesUpdates(false);
  55 + }
  56 +
  57 + @Test
  58 + public void testSubscribeToAttributesUpdatesFromTheServerWithEmptyCurrentStateNotification() throws Exception {
  59 + processTestSubscribeToAttributesUpdates(true);
  60 + }
  61 +
  62 + protected void validateCurrentStateAttributesResponse(TestCoapCallback callback) throws InvalidProtocolBufferException {
  63 + assertNotNull(callback.getPayloadBytes());
  64 + assertNotNull(callback.getObserve());
  65 + assertEquals(callback.getResponseCode(), CoAP.ResponseCode._UNKNOWN_SUCCESS_CODE);
  66 + assertEquals(0, callback.getObserve().intValue());
  67 + TransportProtos.AttributeUpdateNotificationMsg.Builder expectedCurrentStateNotificationMsgBuilder = TransportProtos.AttributeUpdateNotificationMsg.newBuilder();
  68 + TransportProtos.TsKvProto tsKvProtoAttribute1 = getTsKvProto("attribute1", "value", TransportProtos.KeyValueType.STRING_V);
  69 + TransportProtos.TsKvProto tsKvProtoAttribute2 = getTsKvProto("attribute2", "false", TransportProtos.KeyValueType.BOOLEAN_V);
  70 + TransportProtos.TsKvProto tsKvProtoAttribute3 = getTsKvProto("attribute3", "41.0", TransportProtos.KeyValueType.DOUBLE_V);
  71 + TransportProtos.TsKvProto tsKvProtoAttribute4 = getTsKvProto("attribute4", "72", TransportProtos.KeyValueType.LONG_V);
  72 + TransportProtos.TsKvProto tsKvProtoAttribute5 = getTsKvProto("attribute5", "{\"someNumber\":41,\"someArray\":[],\"someNestedObject\":{\"key\":\"value\"}}", TransportProtos.KeyValueType.JSON_V);
  73 + List<TransportProtos.TsKvProto> tsKvProtoList = new ArrayList<>();
  74 + tsKvProtoList.add(tsKvProtoAttribute1);
  75 + tsKvProtoList.add(tsKvProtoAttribute2);
  76 + tsKvProtoList.add(tsKvProtoAttribute3);
  77 + tsKvProtoList.add(tsKvProtoAttribute4);
  78 + tsKvProtoList.add(tsKvProtoAttribute5);
  79 + TransportProtos.AttributeUpdateNotificationMsg expectedCurrentStateNotificationMsg = expectedCurrentStateNotificationMsgBuilder.addAllSharedUpdated(tsKvProtoList).build();
  80 + TransportProtos.AttributeUpdateNotificationMsg actualCurrentStateNotificationMsg = TransportProtos.AttributeUpdateNotificationMsg.parseFrom(callback.getPayloadBytes());
  81 +
  82 + List<TransportProtos.KeyValueProto> expectedSharedUpdatedList = expectedCurrentStateNotificationMsg.getSharedUpdatedList().stream().map(TransportProtos.TsKvProto::getKv).collect(Collectors.toList());
  83 + List<TransportProtos.KeyValueProto> actualSharedUpdatedList = actualCurrentStateNotificationMsg.getSharedUpdatedList().stream().map(TransportProtos.TsKvProto::getKv).collect(Collectors.toList());
  84 +
  85 + assertEquals(expectedSharedUpdatedList.size(), actualSharedUpdatedList.size());
  86 + assertTrue(actualSharedUpdatedList.containsAll(expectedSharedUpdatedList));
  87 +
  88 + }
  89 +
  90 + protected void validateEmptyCurrentStateAttributesResponse(TestCoapCallback callback) throws InvalidProtocolBufferException {
  91 + assertNull(callback.getPayloadBytes());
  92 + assertNotNull(callback.getObserve());
  93 + assertEquals(callback.getResponseCode(), CoAP.ResponseCode._UNKNOWN_SUCCESS_CODE);
  94 + assertEquals(0, callback.getObserve().intValue());
50 95 }
51 96
52 97 protected void validateUpdateAttributesResponse(TestCoapCallback callback) throws InvalidProtocolBufferException {
53 98 assertNotNull(callback.getPayloadBytes());
  99 + assertNotNull(callback.getObserve());
  100 + assertEquals(callback.getResponseCode(), CoAP.ResponseCode._UNKNOWN_SUCCESS_CODE);
  101 + assertEquals(1, callback.getObserve().intValue());
54 102 TransportProtos.AttributeUpdateNotificationMsg.Builder attributeUpdateNotificationMsgBuilder = TransportProtos.AttributeUpdateNotificationMsg.newBuilder();
55 103 List<TransportProtos.TsKvProto> tsKvProtoList = getTsKvProtoList();
56 104 attributeUpdateNotificationMsgBuilder.addAllSharedUpdated(tsKvProtoList);
... ... @@ -68,6 +116,9 @@ public abstract class AbstractCoapAttributesUpdatesProtoIntegrationTest extends
68 116
69 117 protected void validateDeleteAttributesResponse(TestCoapCallback callback) throws InvalidProtocolBufferException {
70 118 assertNotNull(callback.getPayloadBytes());
  119 + assertNotNull(callback.getObserve());
  120 + assertEquals(callback.getResponseCode(), CoAP.ResponseCode._UNKNOWN_SUCCESS_CODE);
  121 + assertEquals(2, callback.getObserve().intValue());
71 122 TransportProtos.AttributeUpdateNotificationMsg.Builder attributeUpdateNotificationMsgBuilder = TransportProtos.AttributeUpdateNotificationMsg.newBuilder();
72 123 attributeUpdateNotificationMsgBuilder.addSharedDeleted("attribute5");
73 124
... ...
... ... @@ -83,7 +83,7 @@ public abstract class AbstractCoapServerSideRpcDefaultIntegrationTest extends Ab
83 83
84 84 @Test
85 85 public void testServerCoapTwoWayRpc() throws Exception {
86   - processTwoWayRpcTest();
  86 + processTwoWayRpcTest("{\"value1\":\"A\",\"value2\":\"B\"}");
87 87 }
88 88
89 89 }
... ...
... ... @@ -15,6 +15,7 @@
15 15 */
16 16 package org.thingsboard.server.transport.coap.rpc;
17 17
  18 +import com.fasterxml.jackson.databind.JsonNode;
18 19 import lombok.extern.slf4j.Slf4j;
19 20 import org.apache.commons.lang3.StringUtils;
20 21 import org.eclipse.californium.core.CoapClient;
... ... @@ -24,17 +25,18 @@ import org.eclipse.californium.core.CoapResponse;
24 25 import org.eclipse.californium.core.coap.CoAP;
25 26 import org.eclipse.californium.core.coap.MediaTypeRegistry;
26 27 import org.eclipse.californium.core.coap.Request;
27   -import org.junit.Assert;
28   -import org.thingsboard.server.transport.coap.AbstractCoapIntegrationTest;
  28 +import org.thingsboard.common.util.JacksonUtil;
29 29 import org.thingsboard.server.common.data.CoapDeviceType;
30 30 import org.thingsboard.server.common.data.TransportPayloadType;
31 31 import org.thingsboard.server.common.msg.session.FeatureType;
  32 +import org.thingsboard.server.transport.coap.AbstractCoapIntegrationTest;
32 33
33 34 import java.util.concurrent.CountDownLatch;
34 35 import java.util.concurrent.TimeUnit;
35 36
36 37 import static org.junit.Assert.assertEquals;
37 38 import static org.junit.Assert.assertNotNull;
  39 +import static org.junit.Assert.assertNull;
38 40 import static org.junit.Assert.assertTrue;
39 41 import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
40 42
... ... @@ -55,57 +57,66 @@ public abstract class AbstractCoapServerSideRpcIntegrationTest extends AbstractC
55 57 client.useCONs();
56 58
57 59 CountDownLatch latch = new CountDownLatch(1);
58   - TestCoapCallback testCoapCallback = new TestCoapCallback(client, latch, true);
  60 + TestCoapCallback callback = new TestCoapCallback(client, latch, true);
59 61
60 62 Request request = Request.newGet().setObserve();
61   - CoapObserveRelation observeRelation = client.observe(request, testCoapCallback);
  63 + CoapObserveRelation observeRelation = client.observe(request, callback);
  64 +
  65 + latch.await(3, TimeUnit.SECONDS);
  66 +
  67 + validateCurrentStateNotification(callback);
  68 +
  69 + latch = new CountDownLatch(1);
62 70
63 71 String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"23\",\"value\": 1}}";
64 72 String deviceId = savedDevice.getId().getId().toString();
65 73 String result = doPostAsync("/api/plugins/rpc/oneway/" + deviceId, setGpioRequest, String.class, status().isOk());
66   - Assert.assertTrue(StringUtils.isEmpty(result));
  74 +
67 75 latch.await(3, TimeUnit.SECONDS);
68   - assertEquals(0, testCoapCallback.getObserve().intValue());
  76 +
  77 + validateOneWayStateChangedNotification(callback, result);
  78 +
69 79 observeRelation.proactiveCancel();
70 80 assertTrue(observeRelation.isCanceled());
71 81 }
72 82
73   - protected void processTwoWayRpcTest() throws Exception {
  83 + protected void processTwoWayRpcTest(String expectedResponseResult) throws Exception {
74 84 CoapClient client = getCoapClient(FeatureType.RPC);
75 85 client.useCONs();
76 86
77 87 CountDownLatch latch = new CountDownLatch(1);
78   - TestCoapCallback testCoapCallback = new TestCoapCallback(client, latch, false);
  88 + TestCoapCallback callback = new TestCoapCallback(client, latch, false);
79 89
80 90 Request request = Request.newGet().setObserve();
81 91 request.setType(CoAP.Type.CON);
82   - CoapObserveRelation observeRelation = client.observe(request, testCoapCallback);
  92 + CoapObserveRelation observeRelation = client.observe(request, callback);
  93 +
  94 + latch.await(3, TimeUnit.SECONDS);
  95 +
  96 + validateCurrentStateNotification(callback);
83 97
84 98 String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"26\",\"value\": 1}}";
85 99 String deviceId = savedDevice.getId().getId().toString();
86 100
87   - String expected = "{\"value1\":\"A\",\"value2\":\"B\"}";
  101 + String actualResult = doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setGpioRequest, String.class, status().isOk());
  102 + latch.await(3, TimeUnit.SECONDS);
  103 +
  104 + validateTwoWayStateChangedNotification(callback, 1, expectedResponseResult, actualResult);
88 105
89   - String result = doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setGpioRequest, String.class, status().isOk());
  106 + latch = new CountDownLatch(1);
  107 +
  108 + actualResult = doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setGpioRequest, String.class, status().isOk());
90 109 latch.await(3, TimeUnit.SECONDS);
91 110
92   - assertEquals(expected, result);
93   - assertEquals(0, testCoapCallback.getObserve().intValue());
  111 + validateTwoWayStateChangedNotification(callback, 2, expectedResponseResult, actualResult);
  112 +
94 113 observeRelation.proactiveCancel();
95 114 assertTrue(observeRelation.isCanceled());
96   -
97   -// // TODO: 3/11/21 Fix test to validate next RPC
98   -// latch = new CountDownLatch(1);
99   -//
100   -// result = doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setGpioRequest, String.class, status().isOk());
101   -// latch.await(3, TimeUnit.SECONDS);
102   -//
103   -// assertEquals(expected, result);
104   -// assertEquals(1, testCoapCallback.getObserve().intValue());
105 115 }
106 116
107 117 protected void processOnLoadResponse(CoapResponse response, CoapClient client, Integer observe, CountDownLatch latch) {
108   - client.setURI(getRpcResponseFeatureTokenUrl(accessToken, observe));
  118 + JsonNode responseJson = JacksonUtil.fromBytes(response.getPayload());
  119 + client.setURI(getRpcResponseFeatureTokenUrl(accessToken, responseJson.get("id").asInt()));
109 120 client.post(new CoapHandler() {
110 121 @Override
111 122 public void onLoad(CoapResponse response) {
... ... @@ -130,11 +141,21 @@ public abstract class AbstractCoapServerSideRpcIntegrationTest extends AbstractC
130 141 private final CountDownLatch latch;
131 142 private final boolean isOneWayRpc;
132 143
  144 + private Integer observe;
  145 + private byte[] payloadBytes;
  146 + private CoAP.ResponseCode responseCode;
  147 +
133 148 public Integer getObserve() {
134 149 return observe;
135 150 }
136 151
137   - private Integer observe;
  152 + public byte[] getPayloadBytes() {
  153 + return payloadBytes;
  154 + }
  155 +
  156 + public CoAP.ResponseCode getResponseCode() {
  157 + return responseCode;
  158 + }
138 159
139 160 TestCoapCallback(CoapClient client, CountDownLatch latch, boolean isOneWayRpc) {
140 161 this.client = client;
... ... @@ -144,14 +165,15 @@ public abstract class AbstractCoapServerSideRpcIntegrationTest extends AbstractC
144 165
145 166 @Override
146 167 public void onLoad(CoapResponse response) {
147   - log.warn("coap response: {}, {}", response.getResponseText(), response.getCode());
148   - assertNotNull(response.getPayload());
149   - assertEquals(response.getCode(), CoAP.ResponseCode.CONTENT);
  168 + payloadBytes = response.getPayload();
  169 + responseCode = response.getCode();
150 170 observe = response.getOptions().getObserve();
151   - if (!isOneWayRpc) {
152   - processOnLoadResponse(response, client, observe, latch);
153   - } else {
154   - latch.countDown();
  171 + if (observe != null) {
  172 + if (!isOneWayRpc && observe > 0) {
  173 + processOnLoadResponse(response, client, observe, latch);
  174 + } else {
  175 + latch.countDown();
  176 + }
155 177 }
156 178 }
157 179
... ... @@ -162,4 +184,28 @@ public abstract class AbstractCoapServerSideRpcIntegrationTest extends AbstractC
162 184
163 185 }
164 186
  187 + private void validateCurrentStateNotification(TestCoapCallback callback) {
  188 + assertNull(callback.getPayloadBytes());
  189 + assertNotNull(callback.getObserve());
  190 + assertEquals(callback.getResponseCode(), CoAP.ResponseCode.VALID);
  191 + assertEquals(0, callback.getObserve().intValue());
  192 + }
  193 +
  194 + private void validateOneWayStateChangedNotification(TestCoapCallback callback, String result) {
  195 + assertTrue(StringUtils.isEmpty(result));
  196 + assertNotNull(callback.getPayloadBytes());
  197 + assertNotNull(callback.getObserve());
  198 + assertEquals(callback.getResponseCode(), CoAP.ResponseCode._UNKNOWN_SUCCESS_CODE);
  199 + assertEquals(1, callback.getObserve().intValue());
  200 + }
  201 +
  202 + private void validateTwoWayStateChangedNotification(TestCoapCallback callback, int expectedObserveNumber, String expectedResult, String actualResult) {
  203 + assertEquals(expectedResult, actualResult);
  204 + assertNotNull(callback.getPayloadBytes());
  205 + assertNotNull(callback.getObserve());
  206 + assertEquals(callback.getResponseCode(), CoAP.ResponseCode._UNKNOWN_SUCCESS_CODE);
  207 + assertEquals(expectedObserveNumber, callback.getObserve().intValue());
  208 + }
  209 +
  210 +
165 211 }
... ...
... ... @@ -42,7 +42,7 @@ public abstract class AbstractCoapServerSideRpcJsonIntegrationTest extends Abstr
42 42
43 43 @Test
44 44 public void testServerCoapTwoWayRpc() throws Exception {
45   - processTwoWayRpcTest();
  45 + processTwoWayRpcTest("{\"value1\":\"A\",\"value2\":\"B\"}");
46 46 }
47 47
48 48 }
... ...
... ... @@ -85,37 +85,11 @@ public abstract class AbstractCoapServerSideRpcProtoIntegrationTest extends Abst
85 85
86 86 @Test
87 87 public void testServerCoapTwoWayRpc() throws Exception {
88   - processTwoWayRpcTest();
89   - }
90   -
91   - protected void processTwoWayRpcTest() throws Exception {
92   - CoapClient client = getCoapClient(FeatureType.RPC);
93   - client.useCONs();
94   -
95   - CountDownLatch latch = new CountDownLatch(1);
96   - TestCoapCallback testCoapCallback = new TestCoapCallback(client, latch, false);
97   -
98   - Request request = Request.newGet().setObserve();
99   - request.setType(CoAP.Type.CON);
100   - CoapObserveRelation observeRelation = client.observe(request, testCoapCallback);
101   -
102   - String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"26\",\"value\": 1}}";
103   - String deviceId = savedDevice.getId().getId().toString();
104   -
105   - String expected = "{\"payload\":\"{\\\"value1\\\":\\\"A\\\",\\\"value2\\\":\\\"B\\\"}\"}";
106   -
107   - String result = doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setGpioRequest, String.class, status().isOk());
108   - latch.await(3, TimeUnit.SECONDS);
109   -
110   - assertEquals(expected, result);
111   - assertEquals(0, testCoapCallback.getObserve().intValue());
112   - observeRelation.proactiveCancel();
113   - assertTrue(observeRelation.isCanceled());
  88 + processTwoWayRpcTest("{\"payload\":\"{\\\"value1\\\":\\\"A\\\",\\\"value2\\\":\\\"B\\\"}\"}");
114 89 }
115 90
116 91 @Override
117 92 protected void processOnLoadResponse(CoapResponse response, CoapClient client, Integer observe, CountDownLatch latch) {
118   - client.setURI(getRpcResponseFeatureTokenUrl(accessToken, observe));
119 93 ProtoTransportPayloadConfiguration protoTransportPayloadConfiguration = getProtoTransportPayloadConfiguration();
120 94 ProtoFileElement rpcRequestProtoSchemaFile = protoTransportPayloadConfiguration.getTransportProtoSchema(RPC_REQUEST_PROTO_SCHEMA);
121 95 DynamicSchema rpcRequestProtoSchema = protoTransportPayloadConfiguration.getDynamicSchema(rpcRequestProtoSchemaFile, ProtoTransportPayloadConfiguration.RPC_REQUEST_PROTO_SCHEMA);
... ... @@ -123,25 +97,22 @@ public abstract class AbstractCoapServerSideRpcProtoIntegrationTest extends Abst
123 97 byte[] requestPayload = response.getPayload();
124 98 DynamicMessage.Builder rpcRequestMsg = rpcRequestProtoSchema.newMessageBuilder("RpcRequestMsg");
125 99 Descriptors.Descriptor rpcRequestMsgDescriptor = rpcRequestMsg.getDescriptorForType();
126   - assertNotNull(rpcRequestMsgDescriptor);
127 100 try {
128 101 DynamicMessage dynamicMessage = DynamicMessage.parseFrom(rpcRequestMsgDescriptor, requestPayload);
129   - List<Descriptors.FieldDescriptor> fields = rpcRequestMsgDescriptor.getFields();
130   - for (Descriptors.FieldDescriptor fieldDescriptor: fields) {
131   - assertTrue(dynamicMessage.hasField(fieldDescriptor));
132   - }
  102 + Descriptors.FieldDescriptor requestIdDescriptor = rpcRequestMsgDescriptor.findFieldByName("requestId");
  103 + int requestId = (int) dynamicMessage.getField(requestIdDescriptor);
133 104 ProtoFileElement rpcResponseProtoSchemaFile = protoTransportPayloadConfiguration.getTransportProtoSchema(DEVICE_RPC_RESPONSE_PROTO_SCHEMA);
134 105 DynamicSchema rpcResponseProtoSchema = protoTransportPayloadConfiguration.getDynamicSchema(rpcResponseProtoSchemaFile, ProtoTransportPayloadConfiguration.RPC_RESPONSE_PROTO_SCHEMA);
135 106 DynamicMessage.Builder rpcResponseBuilder = rpcResponseProtoSchema.newMessageBuilder("RpcResponseMsg");
136 107 Descriptors.Descriptor rpcResponseMsgDescriptor = rpcResponseBuilder.getDescriptorForType();
137   - assertNotNull(rpcResponseMsgDescriptor);
138 108 DynamicMessage rpcResponseMsg = rpcResponseBuilder
139 109 .setField(rpcResponseMsgDescriptor.findFieldByName("payload"), DEVICE_RESPONSE)
140 110 .build();
  111 + client.setURI(getRpcResponseFeatureTokenUrl(accessToken, requestId));
141 112 client.post(new CoapHandler() {
142 113 @Override
143 114 public void onLoad(CoapResponse response) {
144   - log.warn("Command Response Ack: {}, {}", response.getCode(), response.getResponseText());
  115 + log.warn("Command Response Ack: {}", response.getCode());
145 116 latch.countDown();
146 117 }
147 118
... ...
common/cache/src/main/java/org/thingsboard/server/cache/ota/CaffeineOtaPackageCache.java renamed from common/cache/src/main/java/org/thingsboard/server/cache/firmware/CaffeineFirmwareCache.java
... ... @@ -13,19 +13,20 @@
13 13 * See the License for the specific language governing permissions and
14 14 * limitations under the License.
15 15 */
16   -package org.thingsboard.server.cache.firmware;
  16 +package org.thingsboard.server.cache.ota;
17 17
18 18 import lombok.RequiredArgsConstructor;
19 19 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
20 20 import org.springframework.cache.CacheManager;
21 21 import org.springframework.stereotype.Service;
22 22
23   -import static org.thingsboard.server.common.data.CacheConstants.FIRMWARE_CACHE;
  23 +import static org.thingsboard.server.common.data.CacheConstants.OTA_PACKAGE_CACHE;
  24 +import static org.thingsboard.server.common.data.CacheConstants.OTA_PACKAGE_DATA_CACHE;
24 25
25 26 @Service
26 27 @ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "caffeine", matchIfMissing = true)
27 28 @RequiredArgsConstructor
28   -public class CaffeineFirmwareCache implements FirmwareDataCache {
  29 +public class CaffeineOtaPackageCache implements OtaPackageDataCache {
29 30
30 31 private final CacheManager cacheManager;
31 32
... ... @@ -36,7 +37,7 @@ public class CaffeineFirmwareCache implements FirmwareDataCache {
36 37
37 38 @Override
38 39 public byte[] get(String key, int chunkSize, int chunk) {
39   - byte[] data = cacheManager.getCache(FIRMWARE_CACHE).get(key, byte[].class);
  40 + byte[] data = cacheManager.getCache(OTA_PACKAGE_DATA_CACHE).get(key, byte[].class);
40 41
41 42 if (chunkSize < 1) {
42 43 return data;
... ... @@ -58,11 +59,11 @@ public class CaffeineFirmwareCache implements FirmwareDataCache {
58 59
59 60 @Override
60 61 public void put(String key, byte[] value) {
61   - cacheManager.getCache(FIRMWARE_CACHE).putIfAbsent(key, value);
  62 + cacheManager.getCache(OTA_PACKAGE_DATA_CACHE).putIfAbsent(key, value);
62 63 }
63 64
64 65 @Override
65 66 public void evict(String key) {
66   - cacheManager.getCache(FIRMWARE_CACHE).evict(key);
  67 + cacheManager.getCache(OTA_PACKAGE_DATA_CACHE).evict(key);
67 68 }
68 69 }
... ...
common/cache/src/main/java/org/thingsboard/server/cache/ota/OtaPackageDataCache.java renamed from common/cache/src/main/java/org/thingsboard/server/cache/firmware/FirmwareDataCache.java
... ... @@ -13,9 +13,9 @@
13 13 * See the License for the specific language governing permissions and
14 14 * limitations under the License.
15 15 */
16   -package org.thingsboard.server.cache.firmware;
  16 +package org.thingsboard.server.cache.ota;
17 17
18   -public interface FirmwareDataCache {
  18 +public interface OtaPackageDataCache {
19 19
20 20 byte[] get(String key);
21 21
... ... @@ -25,8 +25,8 @@ public interface FirmwareDataCache {
25 25
26 26 void evict(String key);
27 27
28   - default boolean has(String firmwareId) {
29   - byte[] data = get(firmwareId, 1, 0);
  28 + default boolean has(String otaPackageId) {
  29 + byte[] data = get(otaPackageId, 1, 0);
30 30 return data != null && data.length > 0;
31 31 }
32 32 }
... ...
common/cache/src/main/java/org/thingsboard/server/cache/ota/RedisOtaPackageDataCache.java renamed from common/cache/src/main/java/org/thingsboard/server/cache/firmware/RedisFirmwareDataCache.java
... ... @@ -13,7 +13,7 @@
13 13 * See the License for the specific language governing permissions and
14 14 * limitations under the License.
15 15 */
16   -package org.thingsboard.server.cache.firmware;
  16 +package org.thingsboard.server.cache.ota;
17 17
18 18 import lombok.RequiredArgsConstructor;
19 19 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
... ... @@ -21,12 +21,13 @@ import org.springframework.data.redis.connection.RedisConnection;
21 21 import org.springframework.data.redis.connection.RedisConnectionFactory;
22 22 import org.springframework.stereotype.Service;
23 23
24   -import static org.thingsboard.server.common.data.CacheConstants.FIRMWARE_CACHE;
  24 +import static org.thingsboard.server.common.data.CacheConstants.OTA_PACKAGE_CACHE;
  25 +import static org.thingsboard.server.common.data.CacheConstants.OTA_PACKAGE_DATA_CACHE;
25 26
26 27 @Service
27 28 @ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "redis")
28 29 @RequiredArgsConstructor
29   -public class RedisFirmwareDataCache implements FirmwareDataCache {
  30 +public class RedisOtaPackageDataCache implements OtaPackageDataCache {
30 31
31 32 private final RedisConnectionFactory redisConnectionFactory;
32 33
... ... @@ -39,30 +40,30 @@ public class RedisFirmwareDataCache implements FirmwareDataCache {
39 40 public byte[] get(String key, int chunkSize, int chunk) {
40 41 try (RedisConnection connection = redisConnectionFactory.getConnection()) {
41 42 if (chunkSize == 0) {
42   - return connection.get(toFirmwareCacheKey(key));
  43 + return connection.get(toOtaPackageCacheKey(key));
43 44 }
44 45
45 46 int startIndex = chunkSize * chunk;
46 47 int endIndex = startIndex + chunkSize - 1;
47   - return connection.getRange(toFirmwareCacheKey(key), startIndex, endIndex);
  48 + return connection.getRange(toOtaPackageCacheKey(key), startIndex, endIndex);
48 49 }
49 50 }
50 51
51 52 @Override
52 53 public void put(String key, byte[] value) {
53 54 try (RedisConnection connection = redisConnectionFactory.getConnection()) {
54   - connection.set(toFirmwareCacheKey(key), value);
  55 + connection.set(toOtaPackageCacheKey(key), value);
55 56 }
56 57 }
57 58
58 59 @Override
59 60 public void evict(String key) {
60 61 try (RedisConnection connection = redisConnectionFactory.getConnection()) {
61   - connection.del(toFirmwareCacheKey(key));
  62 + connection.del(toOtaPackageCacheKey(key));
62 63 }
63 64 }
64 65
65   - private byte[] toFirmwareCacheKey(String key) {
66   - return String.format("%s::%s", FIRMWARE_CACHE, key).getBytes();
  66 + private byte[] toOtaPackageCacheKey(String key) {
  67 + return String.format("%s::%s", OTA_PACKAGE_DATA_CACHE, key).getBytes();
67 68 }
68 69 }
... ...
... ... @@ -27,6 +27,7 @@ import org.thingsboard.server.common.data.id.DeviceId;
27 27 import org.thingsboard.server.common.data.id.DeviceProfileId;
28 28 import org.thingsboard.server.common.data.id.EdgeId;
29 29 import org.thingsboard.server.common.data.id.TenantId;
  30 +import org.thingsboard.server.common.data.ota.OtaPackageType;
30 31 import org.thingsboard.server.common.data.page.PageData;
31 32 import org.thingsboard.server.common.data.page.PageLink;
32 33 import org.thingsboard.server.common.data.security.DeviceCredentials;
... ... @@ -63,9 +64,9 @@ public interface DeviceService {
63 64
64 65 PageData<Device> findDevicesByTenantIdAndType(TenantId tenantId, String type, PageLink pageLink);
65 66
66   - PageData<Device> findDevicesByTenantIdAndTypeAndEmptyFirmware(TenantId tenantId, String type, PageLink pageLink);
  67 + PageData<Device> findDevicesByTenantIdAndTypeAndEmptyOtaPackage(TenantId tenantId, DeviceProfileId deviceProfileId, OtaPackageType type, PageLink pageLink);
67 68
68   - PageData<Device> findDevicesByTenantIdAndTypeAndEmptySoftware(TenantId tenantId, String type, PageLink pageLink);
  69 + Long countDevicesByTenantIdAndDeviceProfileIdAndEmptyOtaPackage(TenantId tenantId, DeviceProfileId deviceProfileId, OtaPackageType otaPackageType);
69 70
70 71 PageData<DeviceInfo> findDeviceInfosByTenantIdAndType(TenantId tenantId, String type, PageLink pageLink);
71 72
... ...
common/dao-api/src/main/java/org/thingsboard/server/dao/ota/OtaPackageService.java renamed from common/dao-api/src/main/java/org/thingsboard/server/dao/firmware/FirmwareService.java
... ... @@ -13,40 +13,40 @@
13 13 * See the License for the specific language governing permissions and
14 14 * limitations under the License.
15 15 */
16   -package org.thingsboard.server.dao.firmware;
  16 +package org.thingsboard.server.dao.ota;
17 17
18 18 import com.google.common.util.concurrent.ListenableFuture;
19   -import org.thingsboard.server.common.data.Firmware;
20   -import org.thingsboard.server.common.data.FirmwareInfo;
21   -import org.thingsboard.server.common.data.firmware.ChecksumAlgorithm;
22   -import org.thingsboard.server.common.data.firmware.FirmwareType;
  19 +import org.thingsboard.server.common.data.OtaPackage;
  20 +import org.thingsboard.server.common.data.OtaPackageInfo;
  21 +import org.thingsboard.server.common.data.ota.ChecksumAlgorithm;
  22 +import org.thingsboard.server.common.data.ota.OtaPackageType;
23 23 import org.thingsboard.server.common.data.id.DeviceProfileId;
24   -import org.thingsboard.server.common.data.id.FirmwareId;
  24 +import org.thingsboard.server.common.data.id.OtaPackageId;
25 25 import org.thingsboard.server.common.data.id.TenantId;
26 26 import org.thingsboard.server.common.data.page.PageData;
27 27 import org.thingsboard.server.common.data.page.PageLink;
28 28
29 29 import java.nio.ByteBuffer;
30 30
31   -public interface FirmwareService {
  31 +public interface OtaPackageService {
32 32
33   - FirmwareInfo saveFirmwareInfo(FirmwareInfo firmwareInfo);
  33 + OtaPackageInfo saveOtaPackageInfo(OtaPackageInfo otaPackageInfo);
34 34
35   - Firmware saveFirmware(Firmware firmware);
  35 + OtaPackage saveOtaPackage(OtaPackage otaPackage);
36 36
37 37 String generateChecksum(ChecksumAlgorithm checksumAlgorithm, ByteBuffer data);
38 38
39   - Firmware findFirmwareById(TenantId tenantId, FirmwareId firmwareId);
  39 + OtaPackage findOtaPackageById(TenantId tenantId, OtaPackageId otaPackageId);
40 40
41   - FirmwareInfo findFirmwareInfoById(TenantId tenantId, FirmwareId firmwareId);
  41 + OtaPackageInfo findOtaPackageInfoById(TenantId tenantId, OtaPackageId otaPackageId);
42 42
43   - ListenableFuture<FirmwareInfo> findFirmwareInfoByIdAsync(TenantId tenantId, FirmwareId firmwareId);
  43 + ListenableFuture<OtaPackageInfo> findOtaPackageInfoByIdAsync(TenantId tenantId, OtaPackageId otaPackageId);
44 44
45   - PageData<FirmwareInfo> findTenantFirmwaresByTenantId(TenantId tenantId, PageLink pageLink);
  45 + PageData<OtaPackageInfo> findTenantOtaPackagesByTenantId(TenantId tenantId, PageLink pageLink);
46 46
47   - PageData<FirmwareInfo> findTenantFirmwaresByTenantIdAndDeviceProfileIdAndTypeAndHasData(TenantId tenantId, DeviceProfileId deviceProfileId, FirmwareType firmwareType, boolean hasData, PageLink pageLink);
  47 + PageData<OtaPackageInfo> findTenantOtaPackagesByTenantIdAndDeviceProfileIdAndTypeAndHasData(TenantId tenantId, DeviceProfileId deviceProfileId, OtaPackageType otaPackageType, boolean hasData, PageLink pageLink);
48 48
49   - void deleteFirmware(TenantId tenantId, FirmwareId firmwareId);
  49 + void deleteOtaPackage(TenantId tenantId, OtaPackageId otaPackageId);
50 50
51   - void deleteFirmwaresByTenantId(TenantId tenantId);
  51 + void deleteOtaPackagesByTenantId(TenantId tenantId);
52 52 }
... ...
... ... @@ -29,5 +29,6 @@ public class CacheConstants {
29 29 public static final String DEVICE_PROFILE_CACHE = "deviceProfiles";
30 30 public static final String ATTRIBUTES_CACHE = "attributes";
31 31 public static final String TOKEN_OUTDATAGE_TIME_CACHE = "tokensOutdatageTime";
32   - public static final String FIRMWARE_CACHE = "firmwares";
  32 + public static final String OTA_PACKAGE_CACHE = "otaPackages";
  33 + public static final String OTA_PACKAGE_DATA_CACHE = "otaPackagesData";
33 34 }
... ...
... ... @@ -66,6 +66,7 @@ public class DataConstants {
66 66 public static final String TIMESERIES_DELETED = "TIMESERIES_DELETED";
67 67 public static final String ALARM_ACK = "ALARM_ACK";
68 68 public static final String ALARM_CLEAR = "ALARM_CLEAR";
  69 + public static final String ALARM_DELETE = "ALARM_DELETE";
69 70 public static final String ENTITY_ASSIGNED_FROM_TENANT = "ENTITY_ASSIGNED_FROM_TENANT";
70 71 public static final String ENTITY_ASSIGNED_TO_TENANT = "ENTITY_ASSIGNED_TO_TENANT";
71 72 public static final String PROVISION_SUCCESS = "PROVISION_SUCCESS";
... ...
... ... @@ -23,7 +23,7 @@ import org.thingsboard.server.common.data.device.data.DeviceData;
23 23 import org.thingsboard.server.common.data.id.CustomerId;
24 24 import org.thingsboard.server.common.data.id.DeviceId;
25 25 import org.thingsboard.server.common.data.id.DeviceProfileId;
26   -import org.thingsboard.server.common.data.id.FirmwareId;
  26 +import org.thingsboard.server.common.data.id.OtaPackageId;
27 27 import org.thingsboard.server.common.data.id.TenantId;
28 28 import org.thingsboard.server.common.data.validation.NoXss;
29 29
... ... @@ -32,7 +32,7 @@ import java.io.IOException;
32 32
33 33 @EqualsAndHashCode(callSuper = true)
34 34 @Slf4j
35   -public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implements HasName, HasTenantId, HasCustomerId, HasFirmware {
  35 +public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implements HasName, HasTenantId, HasCustomerId, HasOtaPackage {
36 36
37 37 private static final long serialVersionUID = 2807343040519543363L;
38 38
... ... @@ -49,8 +49,8 @@ public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implemen
49 49 @JsonIgnore
50 50 private byte[] deviceDataBytes;
51 51
52   - private FirmwareId firmwareId;
53   - private FirmwareId softwareId;
  52 + private OtaPackageId firmwareId;
  53 + private OtaPackageId softwareId;
54 54
55 55 public Device() {
56 56 super();
... ... @@ -167,19 +167,19 @@ public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implemen
167 167 return getName();
168 168 }
169 169
170   - public FirmwareId getFirmwareId() {
  170 + public OtaPackageId getFirmwareId() {
171 171 return firmwareId;
172 172 }
173 173
174   - public void setFirmwareId(FirmwareId firmwareId) {
  174 + public void setFirmwareId(OtaPackageId firmwareId) {
175 175 this.firmwareId = firmwareId;
176 176 }
177 177
178   - public FirmwareId getSoftwareId() {
  178 + public OtaPackageId getSoftwareId() {
179 179 return softwareId;
180 180 }
181 181
182   - public void setSoftwareId(FirmwareId softwareId) {
  182 + public void setSoftwareId(OtaPackageId softwareId) {
183 183 this.softwareId = softwareId;
184 184 }
185 185
... ...
... ... @@ -23,7 +23,7 @@ import lombok.extern.slf4j.Slf4j;
23 23 import org.thingsboard.server.common.data.device.profile.DeviceProfileData;
24 24 import org.thingsboard.server.common.data.id.DashboardId;
25 25 import org.thingsboard.server.common.data.id.DeviceProfileId;
26   -import org.thingsboard.server.common.data.id.FirmwareId;
  26 +import org.thingsboard.server.common.data.id.OtaPackageId;
27 27 import org.thingsboard.server.common.data.id.RuleChainId;
28 28 import org.thingsboard.server.common.data.id.TenantId;
29 29 import org.thingsboard.server.common.data.validation.NoXss;
... ... @@ -37,7 +37,7 @@ import static org.thingsboard.server.common.data.SearchTextBasedWithAdditionalIn
37 37 @Data
38 38 @EqualsAndHashCode(callSuper = true)
39 39 @Slf4j
40   -public class DeviceProfile extends SearchTextBased<DeviceProfileId> implements HasName, HasTenantId, HasFirmware {
  40 +public class DeviceProfile extends SearchTextBased<DeviceProfileId> implements HasName, HasTenantId, HasOtaPackage {
41 41
42 42 private TenantId tenantId;
43 43 @NoXss
... ... @@ -60,9 +60,9 @@ public class DeviceProfile extends SearchTextBased<DeviceProfileId> implements H
60 60 @NoXss
61 61 private String provisionDeviceKey;
62 62
63   - private FirmwareId firmwareId;
  63 + private OtaPackageId firmwareId;
64 64
65   - private FirmwareId softwareId;
  65 + private OtaPackageId softwareId;
66 66
67 67 public DeviceProfile() {
68 68 super();
... ...
... ... @@ -19,5 +19,5 @@ package org.thingsboard.server.common.data;
19 19 * @author Andrew Shvayka
20 20 */
21 21 public enum EntityType {
22   - TENANT, CUSTOMER, USER, DASHBOARD, ASSET, DEVICE, ALARM, RULE_CHAIN, RULE_NODE, ENTITY_VIEW, WIDGETS_BUNDLE, WIDGET_TYPE, TENANT_PROFILE, DEVICE_PROFILE, API_USAGE_STATE, TB_RESOURCE, FIRMWARE, EDGE;
  22 + TENANT, CUSTOMER, USER, DASHBOARD, ASSET, DEVICE, ALARM, RULE_CHAIN, RULE_NODE, ENTITY_VIEW, WIDGETS_BUNDLE, WIDGET_TYPE, TENANT_PROFILE, DEVICE_PROFILE, API_USAGE_STATE, TB_RESOURCE, OTA_PACKAGE, EDGE;
23 23 }
... ...
common/data/src/main/java/org/thingsboard/server/common/data/HasOtaPackage.java renamed from common/data/src/main/java/org/thingsboard/server/common/data/HasFirmware.java
... ... @@ -15,11 +15,11 @@
15 15 */
16 16 package org.thingsboard.server.common.data;
17 17
18   -import org.thingsboard.server.common.data.id.FirmwareId;
  18 +import org.thingsboard.server.common.data.id.OtaPackageId;
19 19
20   -public interface HasFirmware {
  20 +public interface HasOtaPackage {
21 21
22   - FirmwareId getFirmwareId();
  22 + OtaPackageId getFirmwareId();
23 23
24   - FirmwareId getSoftwareId();
  24 + OtaPackageId getSoftwareId();
25 25 }
... ...
common/data/src/main/java/org/thingsboard/server/common/data/OtaPackage.java renamed from common/data/src/main/java/org/thingsboard/server/common/data/Firmware.java
... ... @@ -17,27 +17,27 @@ package org.thingsboard.server.common.data;
17 17
18 18 import lombok.Data;
19 19 import lombok.EqualsAndHashCode;
20   -import org.thingsboard.server.common.data.id.FirmwareId;
  20 +import org.thingsboard.server.common.data.id.OtaPackageId;
21 21
22 22 import java.nio.ByteBuffer;
23 23
24 24 @Data
25 25 @EqualsAndHashCode(callSuper = true)
26   -public class Firmware extends FirmwareInfo {
  26 +public class OtaPackage extends OtaPackageInfo {
27 27
28 28 private static final long serialVersionUID = 3091601761339422546L;
29 29
30 30 private transient ByteBuffer data;
31 31
32   - public Firmware() {
  32 + public OtaPackage() {
33 33 super();
34 34 }
35 35
36   - public Firmware(FirmwareId id) {
  36 + public OtaPackage(OtaPackageId id) {
37 37 super(id);
38 38 }
39 39
40   - public Firmware(Firmware firmware) {
  40 + public OtaPackage(OtaPackage firmware) {
41 41 super(firmware);
42 42 this.data = firmware.getData();
43 43 }
... ...
common/data/src/main/java/org/thingsboard/server/common/data/OtaPackageInfo.java renamed from common/data/src/main/java/org/thingsboard/server/common/data/FirmwareInfo.java
... ... @@ -19,22 +19,22 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
19 19 import lombok.Data;
20 20 import lombok.EqualsAndHashCode;
21 21 import lombok.extern.slf4j.Slf4j;
22   -import org.thingsboard.server.common.data.firmware.ChecksumAlgorithm;
23   -import org.thingsboard.server.common.data.firmware.FirmwareType;
  22 +import org.thingsboard.server.common.data.ota.ChecksumAlgorithm;
  23 +import org.thingsboard.server.common.data.ota.OtaPackageType;
24 24 import org.thingsboard.server.common.data.id.DeviceProfileId;
25   -import org.thingsboard.server.common.data.id.FirmwareId;
  25 +import org.thingsboard.server.common.data.id.OtaPackageId;
26 26 import org.thingsboard.server.common.data.id.TenantId;
27 27
28 28 @Slf4j
29 29 @Data
30 30 @EqualsAndHashCode(callSuper = true)
31   -public class FirmwareInfo extends SearchTextBasedWithAdditionalInfo<FirmwareId> implements HasName, HasTenantId {
  31 +public class OtaPackageInfo extends SearchTextBasedWithAdditionalInfo<OtaPackageId> implements HasName, HasTenantId {
32 32
33 33 private static final long serialVersionUID = 3168391583570815419L;
34 34
35 35 private TenantId tenantId;
36 36 private DeviceProfileId deviceProfileId;
37   - private FirmwareType type;
  37 + private OtaPackageType type;
38 38 private String title;
39 39 private String version;
40 40 private boolean hasData;
... ... @@ -45,27 +45,27 @@ public class FirmwareInfo extends SearchTextBasedWithAdditionalInfo<FirmwareId>
45 45 private Long dataSize;
46 46
47 47
48   - public FirmwareInfo() {
  48 + public OtaPackageInfo() {
49 49 super();
50 50 }
51 51
52   - public FirmwareInfo(FirmwareId id) {
  52 + public OtaPackageInfo(OtaPackageId id) {
53 53 super(id);
54 54 }
55 55
56   - public FirmwareInfo(FirmwareInfo firmwareInfo) {
57   - super(firmwareInfo);
58   - this.tenantId = firmwareInfo.getTenantId();
59   - this.deviceProfileId = firmwareInfo.getDeviceProfileId();
60   - this.type = firmwareInfo.getType();
61   - this.title = firmwareInfo.getTitle();
62   - this.version = firmwareInfo.getVersion();
63   - this.hasData = firmwareInfo.isHasData();
64   - this.fileName = firmwareInfo.getFileName();
65   - this.contentType = firmwareInfo.getContentType();
66   - this.checksumAlgorithm = firmwareInfo.getChecksumAlgorithm();
67   - this.checksum = firmwareInfo.getChecksum();
68   - this.dataSize = firmwareInfo.getDataSize();
  56 + public OtaPackageInfo(OtaPackageInfo otaPackageInfo) {
  57 + super(otaPackageInfo);
  58 + this.tenantId = otaPackageInfo.getTenantId();
  59 + this.deviceProfileId = otaPackageInfo.getDeviceProfileId();
  60 + this.type = otaPackageInfo.getType();
  61 + this.title = otaPackageInfo.getTitle();
  62 + this.version = otaPackageInfo.getVersion();
  63 + this.hasData = otaPackageInfo.isHasData();
  64 + this.fileName = otaPackageInfo.getFileName();
  65 + this.contentType = otaPackageInfo.getContentType();
  66 + this.checksumAlgorithm = otaPackageInfo.getChecksumAlgorithm();
  67 + this.checksum = otaPackageInfo.getChecksum();
  68 + this.dataSize = otaPackageInfo.getDataSize();
69 69 }
70 70
71 71 @Override
... ...
... ... @@ -27,6 +27,7 @@ import org.thingsboard.server.common.data.validation.NoXss;
27 27
28 28 import java.io.ByteArrayInputStream;
29 29 import java.io.IOException;
  30 +import java.util.Optional;
30 31
31 32 import static org.thingsboard.server.common.data.SearchTextBasedWithAdditionalInfo.mapper;
32 33
... ... @@ -92,6 +93,13 @@ public class TenantProfile extends SearchTextBased<TenantProfileId> implements H
92 93 }
93 94 }
94 95
  96 + @JsonIgnore
  97 + public Optional<DefaultTenantProfileConfiguration> getProfileConfiguration() {
  98 + return Optional.ofNullable(getProfileData().getConfiguration())
  99 + .filter(profileConfiguration -> profileConfiguration instanceof DefaultTenantProfileConfiguration)
  100 + .map(profileConfiguration -> (DefaultTenantProfileConfiguration) profileConfiguration);
  101 + }
  102 +
95 103 public TenantProfileData createDefaultTenantProfileData() {
96 104 TenantProfileData tpd = new TenantProfileData();
97 105 tpd.setConfiguration(new DefaultTenantProfileConfiguration());
... ...
... ... @@ -39,6 +39,7 @@ public enum ActionType {
39 39 RELATIONS_DELETED(false),
40 40 ALARM_ACK(false),
41 41 ALARM_CLEAR(false),
  42 + ALARM_DELETE(false),
42 43 LOGIN(false),
43 44 LOGOUT(false),
44 45 LOCKOUT(false),
... ...
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.common.data.exception;
  17 +
  18 +public class ApiUsageLimitsExceededException extends RuntimeException {
  19 + public ApiUsageLimitsExceededException(String message) {
  20 + super(message);
  21 + }
  22 +
  23 + public ApiUsageLimitsExceededException() {
  24 + }
  25 +}
... ...
... ... @@ -71,8 +71,8 @@ public class EntityIdFactory {
71 71 return new ApiUsageStateId(uuid);
72 72 case TB_RESOURCE:
73 73 return new TbResourceId(uuid);
74   - case FIRMWARE:
75   - return new FirmwareId(uuid);
  74 + case OTA_PACKAGE:
  75 + return new OtaPackageId(uuid);
76 76 case EDGE:
77 77 return new EdgeId(uuid);
78 78 }
... ...
common/data/src/main/java/org/thingsboard/server/common/data/id/OtaPackageId.java renamed from common/data/src/main/java/org/thingsboard/server/common/data/id/FirmwareId.java
... ... @@ -22,23 +22,23 @@ import org.thingsboard.server.common.data.EntityType;
22 22
23 23 import java.util.UUID;
24 24
25   -public class FirmwareId extends UUIDBased implements EntityId {
  25 +public class OtaPackageId extends UUIDBased implements EntityId {
26 26
27 27 private static final long serialVersionUID = 1L;
28 28
29 29 @JsonCreator
30   - public FirmwareId(@JsonProperty("id") UUID id) {
  30 + public OtaPackageId(@JsonProperty("id") UUID id) {
31 31 super(id);
32 32 }
33 33
34   - public static FirmwareId fromString(String firmwareId) {
35   - return new FirmwareId(UUID.fromString(firmwareId));
  34 + public static OtaPackageId fromString(String firmwareId) {
  35 + return new OtaPackageId(UUID.fromString(firmwareId));
36 36 }
37 37
38 38 @JsonIgnore
39 39 @Override
40 40 public EntityType getEntityType() {
41   - return EntityType.FIRMWARE;
  41 + return EntityType.OTA_PACKAGE;
42 42 }
43 43
44 44 }
... ...
common/data/src/main/java/org/thingsboard/server/common/data/ota/ChecksumAlgorithm.java renamed from common/data/src/main/java/org/thingsboard/server/common/data/firmware/ChecksumAlgorithm.java
... ... @@ -13,7 +13,7 @@
13 13 * See the License for the specific language governing permissions and
14 14 * limitations under the License.
15 15 */
16   -package org.thingsboard.server.common.data.firmware;
  16 +package org.thingsboard.server.common.data.ota;
17 17
18 18 public enum ChecksumAlgorithm {
19 19 MD5,
... ...
common/data/src/main/java/org/thingsboard/server/common/data/ota/OtaPackageKey.java renamed from common/data/src/main/java/org/thingsboard/server/common/data/firmware/FirmwareKey.java
... ... @@ -13,18 +13,18 @@
13 13 * See the License for the specific language governing permissions and
14 14 * limitations under the License.
15 15 */
16   -package org.thingsboard.server.common.data.firmware;
  16 +package org.thingsboard.server.common.data.ota;
17 17
18 18 import lombok.Getter;
19 19
20   -public enum FirmwareKey {
  20 +public enum OtaPackageKey {
21 21
22 22 TITLE("title"), VERSION("version"), TS("ts"), STATE("state"), SIZE("size"), CHECKSUM("checksum"), CHECKSUM_ALGORITHM("checksum_algorithm");
23 23
24 24 @Getter
25 25 private final String value;
26 26
27   - FirmwareKey(String value) {
  27 + OtaPackageKey(String value) {
28 28 this.value = value;
29 29 }
30 30 }
... ...
common/data/src/main/java/org/thingsboard/server/common/data/ota/OtaPackageType.java renamed from common/data/src/main/java/org/thingsboard/server/common/data/firmware/FirmwareType.java
... ... @@ -13,18 +13,18 @@
13 13 * See the License for the specific language governing permissions and
14 14 * limitations under the License.
15 15 */
16   -package org.thingsboard.server.common.data.firmware;
  16 +package org.thingsboard.server.common.data.ota;
17 17
18 18 import lombok.Getter;
19 19
20   -public enum FirmwareType {
  20 +public enum OtaPackageType {
21 21
22 22 FIRMWARE("fw"), SOFTWARE("sw");
23 23
24 24 @Getter
25 25 private final String keyPrefix;
26 26
27   - FirmwareType(String keyPrefix) {
  27 + OtaPackageType(String keyPrefix) {
28 28 this.keyPrefix = keyPrefix;
29 29 }
30 30 }
... ...
common/data/src/main/java/org/thingsboard/server/common/data/ota/OtaPackageUpdateStatus.java renamed from common/data/src/main/java/org/thingsboard/server/common/data/firmware/FirmwareUpdateStatus.java
... ... @@ -13,8 +13,8 @@
13 13 * See the License for the specific language governing permissions and
14 14 * limitations under the License.
15 15 */
16   -package org.thingsboard.server.common.data.firmware;
  16 +package org.thingsboard.server.common.data.ota;
17 17
18   -public enum FirmwareUpdateStatus {
  18 +public enum OtaPackageUpdateStatus {
19 19 QUEUED, INITIATED, DOWNLOADING, DOWNLOADED, VERIFIED, UPDATING, UPDATED, FAILED
20 20 }
... ...
common/data/src/main/java/org/thingsboard/server/common/data/ota/OtaPackageUtil.java renamed from common/data/src/main/java/org/thingsboard/server/common/data/firmware/FirmwareUtil.java
... ... @@ -13,21 +13,19 @@
13 13 * See the License for the specific language governing permissions and
14 14 * limitations under the License.
15 15 */
16   -package org.thingsboard.server.common.data.firmware;
  16 +package org.thingsboard.server.common.data.ota;
17 17
18 18 import lombok.extern.slf4j.Slf4j;
19   -import org.thingsboard.server.common.data.HasFirmware;
20   -import org.thingsboard.server.common.data.id.FirmwareId;
  19 +import org.thingsboard.server.common.data.HasOtaPackage;
  20 +import org.thingsboard.server.common.data.id.OtaPackageId;
21 21
22 22 import java.util.ArrayList;
23 23 import java.util.Collections;
24 24 import java.util.List;
25   -
26   -import static org.thingsboard.server.common.data.firmware.FirmwareType.FIRMWARE;
27   -import static org.thingsboard.server.common.data.firmware.FirmwareType.SOFTWARE;
  25 +import java.util.function.Supplier;
28 26
29 27 @Slf4j
30   -public class FirmwareUtil {
  28 +public class OtaPackageUtil {
31 29
32 30 public static final List<String> ALL_FW_ATTRIBUTE_KEYS;
33 31
... ... @@ -35,19 +33,19 @@ public class FirmwareUtil {
35 33
36 34 static {
37 35 ALL_FW_ATTRIBUTE_KEYS = new ArrayList<>();
38   - for (FirmwareKey key : FirmwareKey.values()) {
39   - ALL_FW_ATTRIBUTE_KEYS.add(getAttributeKey(FIRMWARE, key));
  36 + for (OtaPackageKey key : OtaPackageKey.values()) {
  37 + ALL_FW_ATTRIBUTE_KEYS.add(getAttributeKey(OtaPackageType.FIRMWARE, key));
40 38
41 39 }
42 40
43 41 ALL_SW_ATTRIBUTE_KEYS = new ArrayList<>();
44   - for (FirmwareKey key : FirmwareKey.values()) {
45   - ALL_SW_ATTRIBUTE_KEYS.add(getAttributeKey(SOFTWARE, key));
  42 + for (OtaPackageKey key : OtaPackageKey.values()) {
  43 + ALL_SW_ATTRIBUTE_KEYS.add(getAttributeKey(OtaPackageType.SOFTWARE, key));
46 44
47 45 }
48 46 }
49 47
50   - public static List<String> getAttributeKeys(FirmwareType firmwareType) {
  48 + public static List<String> getAttributeKeys(OtaPackageType firmwareType) {
51 49 switch (firmwareType) {
52 50 case FIRMWARE:
53 51 return ALL_FW_ATTRIBUTE_KEYS;
... ... @@ -57,35 +55,46 @@ public class FirmwareUtil {
57 55 return Collections.emptyList();
58 56 }
59 57
60   - public static String getAttributeKey(FirmwareType type, FirmwareKey key) {
  58 + public static String getAttributeKey(OtaPackageType type, OtaPackageKey key) {
61 59 return type.getKeyPrefix() + "_" + key.getValue();
62 60 }
63 61
64   - public static String getTargetTelemetryKey(FirmwareType type, FirmwareKey key) {
  62 + public static String getTargetTelemetryKey(OtaPackageType type, OtaPackageKey key) {
65 63 return getTelemetryKey("target_", type, key);
66 64 }
67 65
68   - public static String getCurrentTelemetryKey(FirmwareType type, FirmwareKey key) {
  66 + public static String getCurrentTelemetryKey(OtaPackageType type, OtaPackageKey key) {
69 67 return getTelemetryKey("current_", type, key);
70 68 }
71 69
72   - private static String getTelemetryKey(String prefix, FirmwareType type, FirmwareKey key) {
  70 + private static String getTelemetryKey(String prefix, OtaPackageType type, OtaPackageKey key) {
73 71 return prefix + type.getKeyPrefix() + "_" + key.getValue();
74 72 }
75 73
76   - public static String getTelemetryKey(FirmwareType type, FirmwareKey key) {
  74 + public static String getTelemetryKey(OtaPackageType type, OtaPackageKey key) {
77 75 return type.getKeyPrefix() + "_" + key.getValue();
78 76 }
79 77
80   - public static FirmwareId getFirmwareId(HasFirmware entity, FirmwareType firmwareType) {
81   - switch (firmwareType) {
  78 + public static OtaPackageId getOtaPackageId(HasOtaPackage entity, OtaPackageType type) {
  79 + switch (type) {
82 80 case FIRMWARE:
83 81 return entity.getFirmwareId();
84 82 case SOFTWARE:
85 83 return entity.getSoftwareId();
86 84 default:
87   - log.warn("Unsupported firmware type: [{}]", firmwareType);
  85 + log.warn("Unsupported ota package type: [{}]", type);
88 86 return null;
89 87 }
90 88 }
  89 +
  90 + public static <T> T getByOtaPackageType(Supplier<T> firmwareSupplier, Supplier<T> softwareSupplier, OtaPackageType type) {
  91 + switch (type) {
  92 + case FIRMWARE:
  93 + return firmwareSupplier.get();
  94 + case SOFTWARE:
  95 + return softwareSupplier.get();
  96 + default:
  97 + throw new RuntimeException("Unsupported OtaPackage type: " + type);
  98 + }
  99 + }
91 100 }
... ...
... ... @@ -17,10 +17,11 @@ package org.thingsboard.server.common.data.page;
17 17
18 18 import com.fasterxml.jackson.annotation.JsonCreator;
19 19 import com.fasterxml.jackson.annotation.JsonProperty;
20   -import org.thingsboard.server.common.data.BaseData;
21 20
22 21 import java.util.Collections;
23 22 import java.util.List;
  23 +import java.util.function.Function;
  24 +import java.util.stream.Collectors;
24 25
25 26 public class PageData<T> {
26 27
... ... @@ -61,4 +62,8 @@ public class PageData<T> {
61 62 return hasNext;
62 63 }
63 64
  65 + public <D> PageData<D> mapData(Function<T, D> mapper) {
  66 + return new PageData<>(getData().stream().map(mapper).collect(Collectors.toList()), getTotalPages(), getTotalElements(), hasNext());
  67 + }
  68 +
64 69 }
... ...
... ... @@ -53,6 +53,7 @@ public class DefaultTenantProfileConfiguration implements TenantProfileConfigura
53 53 private long maxCreatedAlarms;
54 54
55 55 private int defaultStorageTtlDays;
  56 + private int alarmsTtlDays;
56 57
57 58 private double warnThreshold;
58 59
... ...
... ... @@ -38,7 +38,7 @@ public class TbKafkaTopicConfigs {
38 38 private String notificationsProperties;
39 39 @Value("${queue.kafka.topic-properties.js-executor}")
40 40 private String jsExecutorProperties;
41   - @Value("${queue.kafka.topic-properties.fw-updates:}")
  41 + @Value("${queue.kafka.topic-properties.ota-updates:}")
42 42 private String fwUpdatesProperties;
43 43
44 44 @Getter
... ...
... ... @@ -187,14 +187,14 @@ public class AwsSqsMonolithQueueFactory implements TbCoreQueueFactory, TbRuleEng
187 187 }
188 188
189 189 @Override
190   - public TbQueueConsumer<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> createToFirmwareStateServiceMsgConsumer() {
191   - return new TbAwsSqsConsumerTemplate<>(transportApiAdmin, sqsSettings, coreSettings.getFirmwareTopic(),
192   - msg -> new TbProtoQueueMsg<>(msg.getKey(), ToFirmwareStateServiceMsg.parseFrom(msg.getData()), msg.getHeaders()));
  190 + public TbQueueConsumer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgConsumer() {
  191 + return new TbAwsSqsConsumerTemplate<>(transportApiAdmin, sqsSettings, coreSettings.getOtaPackageTopic(),
  192 + msg -> new TbProtoQueueMsg<>(msg.getKey(), ToOtaPackageStateServiceMsg.parseFrom(msg.getData()), msg.getHeaders()));
193 193 }
194 194
195 195 @Override
196   - public TbQueueProducer<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> createToFirmwareStateServiceMsgProducer() {
197   - return new TbAwsSqsProducerTemplate<>(coreAdmin, sqsSettings, coreSettings.getFirmwareTopic());
  196 + public TbQueueProducer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgProducer() {
  197 + return new TbAwsSqsProducerTemplate<>(coreAdmin, sqsSettings, coreSettings.getOtaPackageTopic());
198 198 }
199 199
200 200 @PreDestroy
... ...
... ... @@ -23,7 +23,7 @@ import org.thingsboard.server.common.msg.queue.ServiceType;
23 23 import org.thingsboard.server.gen.js.JsInvokeProtos;
24 24 import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg;
25 25 import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg;
26   -import org.thingsboard.server.gen.transport.TransportProtos.ToFirmwareStateServiceMsg;
  26 +import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg;
27 27 import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg;
28 28 import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg;
29 29 import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg;
... ... @@ -177,14 +177,14 @@ public class AwsSqsTbCoreQueueFactory implements TbCoreQueueFactory {
177 177 }
178 178
179 179 @Override
180   - public TbQueueConsumer<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> createToFirmwareStateServiceMsgConsumer() {
181   - return new TbAwsSqsConsumerTemplate<>(transportApiAdmin, sqsSettings, coreSettings.getFirmwareTopic(),
182   - msg -> new TbProtoQueueMsg<>(msg.getKey(), ToFirmwareStateServiceMsg.parseFrom(msg.getData()), msg.getHeaders()));
  180 + public TbQueueConsumer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgConsumer() {
  181 + return new TbAwsSqsConsumerTemplate<>(transportApiAdmin, sqsSettings, coreSettings.getOtaPackageTopic(),
  182 + msg -> new TbProtoQueueMsg<>(msg.getKey(), ToOtaPackageStateServiceMsg.parseFrom(msg.getData()), msg.getHeaders()));
183 183 }
184 184
185 185 @Override
186   - public TbQueueProducer<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> createToFirmwareStateServiceMsgProducer() {
187   - return new TbAwsSqsProducerTemplate<>(coreAdmin, sqsSettings, coreSettings.getFirmwareTopic());
  186 + public TbQueueProducer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgProducer() {
  187 + return new TbAwsSqsProducerTemplate<>(coreAdmin, sqsSettings, coreSettings.getOtaPackageTopic());
188 188 }
189 189
190 190 @PreDestroy
... ...
... ... @@ -131,13 +131,13 @@ public class InMemoryMonolithQueueFactory implements TbCoreQueueFactory, TbRuleE
131 131 }
132 132
133 133 @Override
134   - public TbQueueConsumer<TbProtoQueueMsg<TransportProtos.ToFirmwareStateServiceMsg>> createToFirmwareStateServiceMsgConsumer() {
135   - return new InMemoryTbQueueConsumer<>(coreSettings.getFirmwareTopic());
  134 + public TbQueueConsumer<TbProtoQueueMsg<TransportProtos.ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgConsumer() {
  135 + return new InMemoryTbQueueConsumer<>(coreSettings.getOtaPackageTopic());
136 136 }
137 137
138 138 @Override
139   - public TbQueueProducer<TbProtoQueueMsg<TransportProtos.ToFirmwareStateServiceMsg>> createToFirmwareStateServiceMsgProducer() {
140   - return new InMemoryTbQueueProducer<>(coreSettings.getFirmwareTopic());
  139 + public TbQueueProducer<TbProtoQueueMsg<TransportProtos.ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgProducer() {
  140 + return new InMemoryTbQueueProducer<>(coreSettings.getOtaPackageTopic());
141 141 }
142 142
143 143 @Override
... ...
... ... @@ -23,7 +23,7 @@ import org.thingsboard.server.common.msg.queue.ServiceType;
23 23 import org.thingsboard.server.gen.js.JsInvokeProtos;
24 24 import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg;
25 25 import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg;
26   -import org.thingsboard.server.gen.transport.TransportProtos.ToFirmwareStateServiceMsg;
  26 +import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg;
27 27 import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg;
28 28 import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg;
29 29 import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg;
... ... @@ -277,24 +277,24 @@ public class KafkaMonolithQueueFactory implements TbCoreQueueFactory, TbRuleEngi
277 277 }
278 278
279 279 @Override
280   - public TbQueueConsumer<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> createToFirmwareStateServiceMsgConsumer() {
281   - TbKafkaConsumerTemplate.TbKafkaConsumerTemplateBuilder<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> consumerBuilder = TbKafkaConsumerTemplate.builder();
  280 + public TbQueueConsumer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgConsumer() {
  281 + TbKafkaConsumerTemplate.TbKafkaConsumerTemplateBuilder<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> consumerBuilder = TbKafkaConsumerTemplate.builder();
282 282 consumerBuilder.settings(kafkaSettings);
283   - consumerBuilder.topic(coreSettings.getFirmwareTopic());
284   - consumerBuilder.clientId("monolith-fw-consumer-" + serviceInfoProvider.getServiceId());
285   - consumerBuilder.groupId("monolith-fw-consumer");
286   - consumerBuilder.decoder(msg -> new TbProtoQueueMsg<>(msg.getKey(), ToFirmwareStateServiceMsg.parseFrom(msg.getData()), msg.getHeaders()));
  283 + consumerBuilder.topic(coreSettings.getOtaPackageTopic());
  284 + consumerBuilder.clientId("monolith-ota-consumer-" + serviceInfoProvider.getServiceId());
  285 + consumerBuilder.groupId("monolith-ota-consumer");
  286 + consumerBuilder.decoder(msg -> new TbProtoQueueMsg<>(msg.getKey(), ToOtaPackageStateServiceMsg.parseFrom(msg.getData()), msg.getHeaders()));
287 287 consumerBuilder.admin(fwUpdatesAdmin);
288 288 consumerBuilder.statsService(consumerStatsService);
289 289 return consumerBuilder.build();
290 290 }
291 291
292 292 @Override
293   - public TbQueueProducer<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> createToFirmwareStateServiceMsgProducer() {
294   - TbKafkaProducerTemplate.TbKafkaProducerTemplateBuilder<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> requestBuilder = TbKafkaProducerTemplate.builder();
  293 + public TbQueueProducer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgProducer() {
  294 + TbKafkaProducerTemplate.TbKafkaProducerTemplateBuilder<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> requestBuilder = TbKafkaProducerTemplate.builder();
295 295 requestBuilder.settings(kafkaSettings);
296   - requestBuilder.clientId("monolith-fw-producer-" + serviceInfoProvider.getServiceId());
297   - requestBuilder.defaultTopic(coreSettings.getFirmwareTopic());
  296 + requestBuilder.clientId("monolith-ota-producer-" + serviceInfoProvider.getServiceId());
  297 + requestBuilder.defaultTopic(coreSettings.getOtaPackageTopic());
298 298 requestBuilder.admin(fwUpdatesAdmin);
299 299 return requestBuilder.build();
300 300 }
... ...
... ... @@ -23,7 +23,7 @@ import org.thingsboard.server.common.msg.queue.ServiceType;
23 23 import org.thingsboard.server.gen.js.JsInvokeProtos;
24 24 import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg;
25 25 import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg;
26   -import org.thingsboard.server.gen.transport.TransportProtos.ToFirmwareStateServiceMsg;
  26 +import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg;
27 27 import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg;
28 28 import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg;
29 29 import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg;
... ... @@ -245,24 +245,24 @@ public class KafkaTbCoreQueueFactory implements TbCoreQueueFactory {
245 245 }
246 246
247 247 @Override
248   - public TbQueueConsumer<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> createToFirmwareStateServiceMsgConsumer() {
249   - TbKafkaConsumerTemplate.TbKafkaConsumerTemplateBuilder<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> consumerBuilder = TbKafkaConsumerTemplate.builder();
  248 + public TbQueueConsumer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgConsumer() {
  249 + TbKafkaConsumerTemplate.TbKafkaConsumerTemplateBuilder<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> consumerBuilder = TbKafkaConsumerTemplate.builder();
250 250 consumerBuilder.settings(kafkaSettings);
251   - consumerBuilder.topic(coreSettings.getFirmwareTopic());
252   - consumerBuilder.clientId("tb-core-fw-consumer-" + serviceInfoProvider.getServiceId());
253   - consumerBuilder.groupId("tb-core-fw-consumer");
254   - consumerBuilder.decoder(msg -> new TbProtoQueueMsg<>(msg.getKey(), ToFirmwareStateServiceMsg.parseFrom(msg.getData()), msg.getHeaders()));
  251 + consumerBuilder.topic(coreSettings.getOtaPackageTopic());
  252 + consumerBuilder.clientId("tb-core-ota-consumer-" + serviceInfoProvider.getServiceId());
  253 + consumerBuilder.groupId("tb-core-ota-consumer");
  254 + consumerBuilder.decoder(msg -> new TbProtoQueueMsg<>(msg.getKey(), ToOtaPackageStateServiceMsg.parseFrom(msg.getData()), msg.getHeaders()));
255 255 consumerBuilder.admin(fwUpdatesAdmin);
256 256 consumerBuilder.statsService(consumerStatsService);
257 257 return consumerBuilder.build();
258 258 }
259 259
260 260 @Override
261   - public TbQueueProducer<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> createToFirmwareStateServiceMsgProducer() {
262   - TbKafkaProducerTemplate.TbKafkaProducerTemplateBuilder<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> requestBuilder = TbKafkaProducerTemplate.builder();
  261 + public TbQueueProducer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgProducer() {
  262 + TbKafkaProducerTemplate.TbKafkaProducerTemplateBuilder<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> requestBuilder = TbKafkaProducerTemplate.builder();
263 263 requestBuilder.settings(kafkaSettings);
264   - requestBuilder.clientId("tb-core-fw-producer-" + serviceInfoProvider.getServiceId());
265   - requestBuilder.defaultTopic(coreSettings.getFirmwareTopic());
  264 + requestBuilder.clientId("tb-core-ota-producer-" + serviceInfoProvider.getServiceId());
  265 + requestBuilder.defaultTopic(coreSettings.getOtaPackageTopic());
266 266 requestBuilder.admin(fwUpdatesAdmin);
267 267 return requestBuilder.build();
268 268 }
... ...
... ... @@ -22,9 +22,9 @@ import org.springframework.stereotype.Component;
22 22 import org.thingsboard.server.common.msg.queue.ServiceType;
23 23 import org.thingsboard.server.gen.js.JsInvokeProtos.RemoteJsRequest;
24 24 import org.thingsboard.server.gen.js.JsInvokeProtos.RemoteJsResponse;
25   -import org.thingsboard.server.gen.transport.TransportProtos.*;
26 25 import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg;
27 26 import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg;
  27 +import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg;
28 28 import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg;
29 29 import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg;
30 30 import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg;
... ... @@ -192,14 +192,14 @@ public class PubSubMonolithQueueFactory implements TbCoreQueueFactory, TbRuleEng
192 192 }
193 193
194 194 @Override
195   - public TbQueueConsumer<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> createToFirmwareStateServiceMsgConsumer() {
196   - return new TbPubSubConsumerTemplate<>(coreAdmin, pubSubSettings, coreSettings.getFirmwareTopic(),
197   - msg -> new TbProtoQueueMsg<>(msg.getKey(), ToFirmwareStateServiceMsg.parseFrom(msg.getData()), msg.getHeaders()));
  195 + public TbQueueConsumer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgConsumer() {
  196 + return new TbPubSubConsumerTemplate<>(coreAdmin, pubSubSettings, coreSettings.getOtaPackageTopic(),
  197 + msg -> new TbProtoQueueMsg<>(msg.getKey(), ToOtaPackageStateServiceMsg.parseFrom(msg.getData()), msg.getHeaders()));
198 198 }
199 199
200 200 @Override
201   - public TbQueueProducer<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> createToFirmwareStateServiceMsgProducer() {
202   - return new TbPubSubProducerTemplate<>(coreAdmin, pubSubSettings, coreSettings.getFirmwareTopic());
  201 + public TbQueueProducer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgProducer() {
  202 + return new TbPubSubProducerTemplate<>(coreAdmin, pubSubSettings, coreSettings.getOtaPackageTopic());
203 203 }
204 204
205 205 @Override
... ...
... ... @@ -23,7 +23,7 @@ import org.thingsboard.server.common.msg.queue.ServiceType;
23 23 import org.thingsboard.server.gen.js.JsInvokeProtos;
24 24 import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg;
25 25 import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg;
26   -import org.thingsboard.server.gen.transport.TransportProtos.ToFirmwareStateServiceMsg;
  26 +import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg;
27 27 import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg;
28 28 import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg;
29 29 import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg;
... ... @@ -166,14 +166,14 @@ public class PubSubTbCoreQueueFactory implements TbCoreQueueFactory {
166 166 }
167 167
168 168 @Override
169   - public TbQueueConsumer<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> createToFirmwareStateServiceMsgConsumer() {
170   - return new TbPubSubConsumerTemplate<>(coreAdmin, pubSubSettings, coreSettings.getFirmwareTopic(),
171   - msg -> new TbProtoQueueMsg<>(msg.getKey(), ToFirmwareStateServiceMsg.parseFrom(msg.getData()), msg.getHeaders()));
  169 + public TbQueueConsumer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgConsumer() {
  170 + return new TbPubSubConsumerTemplate<>(coreAdmin, pubSubSettings, coreSettings.getOtaPackageTopic(),
  171 + msg -> new TbProtoQueueMsg<>(msg.getKey(), ToOtaPackageStateServiceMsg.parseFrom(msg.getData()), msg.getHeaders()));
172 172 }
173 173
174 174 @Override
175   - public TbQueueProducer<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> createToFirmwareStateServiceMsgProducer() {
176   - return new TbPubSubProducerTemplate<>(coreAdmin, pubSubSettings, coreSettings.getFirmwareTopic());
  175 + public TbQueueProducer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgProducer() {
  176 + return new TbPubSubProducerTemplate<>(coreAdmin, pubSubSettings, coreSettings.getOtaPackageTopic());
177 177 }
178 178
179 179 @Override
... ...
... ... @@ -24,7 +24,7 @@ import org.thingsboard.server.gen.js.JsInvokeProtos.RemoteJsRequest;
24 24 import org.thingsboard.server.gen.js.JsInvokeProtos.RemoteJsResponse;
25 25 import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg;
26 26 import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg;
27   -import org.thingsboard.server.gen.transport.TransportProtos.ToFirmwareStateServiceMsg;
  27 +import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg;
28 28 import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg;
29 29 import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg;
30 30 import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg;
... ... @@ -190,14 +190,14 @@ public class RabbitMqMonolithQueueFactory implements TbCoreQueueFactory, TbRuleE
190 190 }
191 191
192 192 @Override
193   - public TbQueueConsumer<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> createToFirmwareStateServiceMsgConsumer() {
194   - return new TbRabbitMqConsumerTemplate<>(coreAdmin, rabbitMqSettings, coreSettings.getFirmwareTopic(),
195   - msg -> new TbProtoQueueMsg<>(msg.getKey(), ToFirmwareStateServiceMsg.parseFrom(msg.getData()), msg.getHeaders()));
  193 + public TbQueueConsumer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgConsumer() {
  194 + return new TbRabbitMqConsumerTemplate<>(coreAdmin, rabbitMqSettings, coreSettings.getOtaPackageTopic(),
  195 + msg -> new TbProtoQueueMsg<>(msg.getKey(), ToOtaPackageStateServiceMsg.parseFrom(msg.getData()), msg.getHeaders()));
196 196 }
197 197
198 198 @Override
199   - public TbQueueProducer<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> createToFirmwareStateServiceMsgProducer() {
200   - return new TbRabbitMqProducerTemplate<>(coreAdmin, rabbitMqSettings, coreSettings.getFirmwareTopic());
  199 + public TbQueueProducer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgProducer() {
  200 + return new TbRabbitMqProducerTemplate<>(coreAdmin, rabbitMqSettings, coreSettings.getOtaPackageTopic());
201 201 }
202 202
203 203 @Override
... ...
... ... @@ -23,7 +23,7 @@ import org.thingsboard.server.common.msg.queue.ServiceType;
23 23 import org.thingsboard.server.gen.js.JsInvokeProtos;
24 24 import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg;
25 25 import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg;
26   -import org.thingsboard.server.gen.transport.TransportProtos.ToFirmwareStateServiceMsg;
  26 +import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg;
27 27 import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg;
28 28 import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg;
29 29 import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg;
... ... @@ -172,14 +172,14 @@ public class RabbitMqTbCoreQueueFactory implements TbCoreQueueFactory {
172 172 }
173 173
174 174 @Override
175   - public TbQueueConsumer<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> createToFirmwareStateServiceMsgConsumer() {
176   - return new TbRabbitMqConsumerTemplate<>(coreAdmin, rabbitMqSettings, coreSettings.getFirmwareTopic(),
177   - msg -> new TbProtoQueueMsg<>(msg.getKey(), ToFirmwareStateServiceMsg.parseFrom(msg.getData()), msg.getHeaders()));
  175 + public TbQueueConsumer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgConsumer() {
  176 + return new TbRabbitMqConsumerTemplate<>(coreAdmin, rabbitMqSettings, coreSettings.getOtaPackageTopic(),
  177 + msg -> new TbProtoQueueMsg<>(msg.getKey(), ToOtaPackageStateServiceMsg.parseFrom(msg.getData()), msg.getHeaders()));
178 178 }
179 179
180 180 @Override
181   - public TbQueueProducer<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> createToFirmwareStateServiceMsgProducer() {
182   - return new TbRabbitMqProducerTemplate<>(coreAdmin, rabbitMqSettings, coreSettings.getFirmwareTopic());
  181 + public TbQueueProducer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgProducer() {
  182 + return new TbRabbitMqProducerTemplate<>(coreAdmin, rabbitMqSettings, coreSettings.getOtaPackageTopic());
183 183 }
184 184
185 185 @Override
... ...
... ... @@ -23,7 +23,7 @@ import org.thingsboard.server.common.msg.queue.ServiceType;
23 23 import org.thingsboard.server.gen.js.JsInvokeProtos;
24 24 import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg;
25 25 import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg;
26   -import org.thingsboard.server.gen.transport.TransportProtos.ToFirmwareStateServiceMsg;
  26 +import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg;
27 27 import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg;
28 28 import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg;
29 29 import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg;
... ... @@ -189,14 +189,14 @@ public class ServiceBusMonolithQueueFactory implements TbCoreQueueFactory, TbRul
189 189 }
190 190
191 191 @Override
192   - public TbQueueConsumer<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> createToFirmwareStateServiceMsgConsumer() {
193   - return new TbServiceBusConsumerTemplate<>(coreAdmin, serviceBusSettings, coreSettings.getFirmwareTopic(),
194   - msg -> new TbProtoQueueMsg<>(msg.getKey(), ToFirmwareStateServiceMsg.parseFrom(msg.getData()), msg.getHeaders()));
  192 + public TbQueueConsumer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgConsumer() {
  193 + return new TbServiceBusConsumerTemplate<>(coreAdmin, serviceBusSettings, coreSettings.getOtaPackageTopic(),
  194 + msg -> new TbProtoQueueMsg<>(msg.getKey(), ToOtaPackageStateServiceMsg.parseFrom(msg.getData()), msg.getHeaders()));
195 195 }
196 196
197 197 @Override
198   - public TbQueueProducer<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> createToFirmwareStateServiceMsgProducer() {
199   - return new TbServiceBusProducerTemplate<>(coreAdmin, serviceBusSettings, coreSettings.getFirmwareTopic());
  198 + public TbQueueProducer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgProducer() {
  199 + return new TbServiceBusProducerTemplate<>(coreAdmin, serviceBusSettings, coreSettings.getOtaPackageTopic());
200 200 }
201 201
202 202 @Override
... ...
... ... @@ -23,7 +23,7 @@ import org.thingsboard.server.common.msg.queue.ServiceType;
23 23 import org.thingsboard.server.gen.js.JsInvokeProtos;
24 24 import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg;
25 25 import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg;
26   -import org.thingsboard.server.gen.transport.TransportProtos.ToFirmwareStateServiceMsg;
  26 +import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg;
27 27 import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg;
28 28 import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg;
29 29 import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg;
... ... @@ -172,14 +172,14 @@ public class ServiceBusTbCoreQueueFactory implements TbCoreQueueFactory {
172 172 }
173 173
174 174 @Override
175   - public TbQueueConsumer<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> createToFirmwareStateServiceMsgConsumer() {
176   - return new TbServiceBusConsumerTemplate<>(coreAdmin, serviceBusSettings, coreSettings.getFirmwareTopic(),
177   - msg -> new TbProtoQueueMsg<>(msg.getKey(), ToFirmwareStateServiceMsg.parseFrom(msg.getData()), msg.getHeaders()));
  175 + public TbQueueConsumer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgConsumer() {
  176 + return new TbServiceBusConsumerTemplate<>(coreAdmin, serviceBusSettings, coreSettings.getOtaPackageTopic(),
  177 + msg -> new TbProtoQueueMsg<>(msg.getKey(), ToOtaPackageStateServiceMsg.parseFrom(msg.getData()), msg.getHeaders()));
178 178 }
179 179
180 180 @Override
181   - public TbQueueProducer<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> createToFirmwareStateServiceMsgProducer() {
182   - return new TbServiceBusProducerTemplate<>(coreAdmin, serviceBusSettings, coreSettings.getFirmwareTopic());
  181 + public TbQueueProducer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgProducer() {
  182 + return new TbServiceBusProducerTemplate<>(coreAdmin, serviceBusSettings, coreSettings.getOtaPackageTopic());
183 183 }
184 184
185 185 @Override
... ...
... ... @@ -16,7 +16,7 @@
16 16 package org.thingsboard.server.queue.provider;
17 17
18 18 import org.thingsboard.server.gen.js.JsInvokeProtos;
19   -import org.thingsboard.server.gen.transport.TransportProtos.ToFirmwareStateServiceMsg;
  19 +import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg;
20 20 import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg;
21 21 import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg;
22 22 import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg;
... ... @@ -91,14 +91,14 @@ public interface TbCoreQueueFactory extends TbUsageStatsClientQueueFactory {
91 91 *
92 92 * @return
93 93 */
94   - TbQueueConsumer<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> createToFirmwareStateServiceMsgConsumer();
  94 + TbQueueConsumer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgConsumer();
95 95
96 96 /**
97 97 * Used to consume messages about firmware update notifications by TB Core Service
98 98 *
99 99 * @return
100 100 */
101   - TbQueueProducer<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> createToFirmwareStateServiceMsgProducer();
  101 + TbQueueProducer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgProducer();
102 102
103 103 /**
104 104 * Used to consume high priority messages by TB Core Service
... ...
... ... @@ -15,7 +15,6 @@
15 15 */
16 16 package org.thingsboard.server.queue.provider;
17 17
18   -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
19 18 import org.springframework.stereotype.Service;
20 19 import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg;
21 20 import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg;
... ... @@ -25,11 +24,12 @@ import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg;
25 24 import org.thingsboard.server.gen.transport.TransportProtos.ToUsageStatsServiceMsg;
26 25 import org.thingsboard.server.queue.TbQueueProducer;
27 26 import org.thingsboard.server.queue.common.TbProtoQueueMsg;
  27 +import org.thingsboard.server.queue.util.TbCoreComponent;
28 28
29 29 import javax.annotation.PostConstruct;
30 30
31 31 @Service
32   -@ConditionalOnExpression("'${service.type:null}'=='monolith' || '${service.type:null}'=='tb-core'")
  32 +@TbCoreComponent
33 33 public class TbCoreQueueProducerProvider implements TbQueueProducerProvider {
34 34
35 35 private final TbCoreQueueFactory tbQueueProvider;
... ...
... ... @@ -26,8 +26,8 @@ public class TbQueueCoreSettings {
26 26 @Value("${queue.core.topic}")
27 27 private String topic;
28 28
29   - @Value("${queue.core.firmware.topic:tb_firmware}")
30   - private String firmwareTopic;
  29 + @Value("${queue.core.ota.topic:tb_ota_package}")
  30 + private String otaPackageTopic;
31 31
32 32 @Value("${queue.core.usage-stats-topic:tb_usage_stats}")
33 33 private String usageStatsTopic;
... ...
... ... @@ -137,6 +137,7 @@ message GetAttributeRequestMsg {
137 137 int32 requestId = 1;
138 138 repeated string clientAttributeNames = 2;
139 139 repeated string sharedAttributeNames = 3;
  140 + bool onlyShared = 4;
140 141 }
141 142
142 143 message GetAttributeResponseMsg {
... ... @@ -144,6 +145,7 @@ message GetAttributeResponseMsg {
144 145 repeated TsKvProto clientAttributeList = 2;
145 146 repeated TsKvProto sharedAttributeList = 3;
146 147 string error = 5;
  148 + bool sharedStateMsg = 6;
147 149 }
148 150
149 151 message AttributeUpdateNotificationMsg {
... ... @@ -386,7 +388,7 @@ enum ResponseStatus {
386 388 FAILURE = 3;
387 389 }
388 390
389   -message GetFirmwareRequestMsg {
  391 +message GetOtaPackageRequestMsg {
390 392 int64 deviceIdMSB = 1;
391 393 int64 deviceIdLSB = 2;
392 394 int64 tenantIdMSB = 3;
... ... @@ -394,10 +396,10 @@ message GetFirmwareRequestMsg {
394 396 string type = 5;
395 397 }
396 398
397   -message GetFirmwareResponseMsg {
  399 +message GetOtaPackageResponseMsg {
398 400 ResponseStatus responseStatus = 1;
399   - int64 firmwareIdMSB = 2;
400   - int64 firmwareIdLSB = 3;
  401 + int64 otaPackageIdMSB = 2;
  402 + int64 otaPackageIdLSB = 3;
401 403 string type = 4;
402 404 string title = 5;
403 405 string version = 6;
... ... @@ -625,7 +627,7 @@ message TransportApiRequestMsg {
625 627 ProvisionDeviceRequestMsg provisionDeviceRequestMsg = 7;
626 628 ValidateDeviceLwM2MCredentialsRequestMsg validateDeviceLwM2MCredentialsRequestMsg = 8;
627 629 GetResourceRequestMsg resourceRequestMsg = 9;
628   - GetFirmwareRequestMsg firmwareRequestMsg = 10;
  630 + GetOtaPackageRequestMsg otaPackageRequestMsg = 10;
629 631 GetSnmpDevicesRequestMsg snmpDevicesRequestMsg = 11;
630 632 GetDeviceRequestMsg deviceRequestMsg = 12;
631 633 GetDeviceCredentialsRequestMsg deviceCredentialsRequestMsg = 13;
... ... @@ -640,7 +642,7 @@ message TransportApiResponseMsg {
640 642 GetSnmpDevicesResponseMsg snmpDevicesResponseMsg = 5;
641 643 LwM2MResponseMsg lwM2MResponseMsg = 6;
642 644 GetResourceResponseMsg resourceResponseMsg = 7;
643   - GetFirmwareResponseMsg firmwareResponseMsg = 8;
  645 + GetOtaPackageResponseMsg otaPackageResponseMsg = 8;
644 646 GetDeviceResponseMsg deviceResponseMsg = 9;
645 647 GetDeviceCredentialsResponseMsg deviceCredentialsResponseMsg = 10;
646 648 }
... ... @@ -708,13 +710,13 @@ message ToUsageStatsServiceMsg {
708 710 int64 customerIdLSB = 7;
709 711 }
710 712
711   -message ToFirmwareStateServiceMsg {
  713 +message ToOtaPackageStateServiceMsg {
712 714 int64 ts = 1;
713 715 int64 tenantIdMSB = 2;
714 716 int64 tenantIdLSB = 3;
715 717 int64 deviceIdMSB = 4;
716 718 int64 deviceIdLSB = 5;
717   - int64 firmwareIdMSB = 6;
718   - int64 firmwareIdLSB = 7;
  719 + int64 otaPackageIdMSB = 6;
  720 + int64 otaPackageIdLSB = 7;
719 721 string type = 8;
720 722 }
... ...
... ... @@ -18,6 +18,7 @@ package org.thingsboard.server.transport.coap;
18 18 import lombok.extern.slf4j.Slf4j;
19 19 import org.eclipse.californium.core.CoapResource;
20 20 import org.eclipse.californium.core.coap.CoAP;
  21 +import org.eclipse.californium.core.coap.Response;
21 22 import org.eclipse.californium.core.server.resources.CoapExchange;
22 23 import org.thingsboard.server.common.data.DeviceProfile;
23 24 import org.thingsboard.server.common.transport.TransportContext;
... ... @@ -56,7 +57,7 @@ public abstract class AbstractCoapTransportResource extends CoapResource {
56 57
57 58 protected abstract void processHandlePost(CoapExchange exchange);
58 59
59   - protected void reportActivity(TransportProtos.SessionInfoProto sessionInfo, boolean hasAttributeSubscription, boolean hasRpcSubscription) {
  60 + protected void reportSubscriptionInfo(TransportProtos.SessionInfoProto sessionInfo, boolean hasAttributeSubscription, boolean hasRpcSubscription) {
60 61 transportContext.getTransportService().process(sessionInfo, TransportProtos.SubscriptionInfoProto.newBuilder()
61 62 .setAttributeSubscription(hasAttributeSubscription)
62 63 .setRpcSubscription(hasRpcSubscription)
... ... @@ -64,6 +65,10 @@ public abstract class AbstractCoapTransportResource extends CoapResource {
64 65 .build(), TransportServiceCallback.EMPTY);
65 66 }
66 67
  68 + protected void reportActivity(TransportProtos.SessionInfoProto sessionInfo) {
  69 + transportService.reportActivity(sessionInfo);
  70 + }
  71 +
67 72 protected static TransportProtos.SessionEventMsg getSessionEventMsg(TransportProtos.SessionEvent event) {
68 73 return TransportProtos.SessionEventMsg.newBuilder()
69 74 .setSessionType(TransportProtos.SessionType.ASYNC)
... ... @@ -112,13 +117,19 @@ public abstract class AbstractCoapTransportResource extends CoapResource {
112 117
113 118 @Override
114 119 public void onSuccess(Void msg) {
115   - exchange.respond(onSuccessResponse);
  120 + Response response = new Response(onSuccessResponse);
  121 + response.setAcknowledged(isConRequest());
  122 + exchange.respond(response);
116 123 }
117 124
118 125 @Override
119 126 public void onError(Throwable e) {
120 127 exchange.respond(onFailureResponse);
121 128 }
  129 +
  130 + private boolean isConRequest() {
  131 + return exchange.advanced().getRequest().isConfirmable();
  132 + }
122 133 }
123 134
124 135 public static class CoapNoOpCallback implements TransportServiceCallback<Void> {
... ...
... ... @@ -18,6 +18,7 @@ package org.thingsboard.server.transport.coap;
18 18 import lombok.Getter;
19 19 import lombok.extern.slf4j.Slf4j;
20 20 import org.springframework.beans.factory.annotation.Autowired;
  21 +import org.springframework.beans.factory.annotation.Value;
21 22 import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
22 23 import org.springframework.stereotype.Component;
23 24 import org.thingsboard.server.common.transport.TransportContext;
... ... @@ -35,6 +36,10 @@ import org.thingsboard.server.transport.coap.efento.adaptor.EfentoCoapAdaptor;
35 36 public class CoapTransportContext extends TransportContext {
36 37
37 38 @Getter
  39 + @Value("${transport.sessions.report_timeout}")
  40 + private long sessionReportTimeout;
  41 +
  42 + @Getter
38 43 @Autowired
39 44 private JsonCoapAdaptor jsonCoapAdaptor;
40 45
... ...
... ... @@ -28,6 +28,7 @@ import org.eclipse.californium.core.observe.ObserveRelation;
28 28 import org.eclipse.californium.core.server.resources.CoapExchange;
29 29 import org.eclipse.californium.core.server.resources.Resource;
30 30 import org.eclipse.californium.core.server.resources.ResourceObserver;
  31 +import org.springframework.util.CollectionUtils;
31 32 import org.thingsboard.server.coapserver.CoapServerService;
32 33 import org.thingsboard.server.coapserver.TbCoapDtlsSessionInfo;
33 34 import org.thingsboard.server.common.data.DataConstants;
... ... @@ -43,7 +44,7 @@ import org.thingsboard.server.common.data.device.profile.DeviceProfileTransportC
43 44 import org.thingsboard.server.common.data.device.profile.JsonTransportPayloadConfiguration;
44 45 import org.thingsboard.server.common.data.device.profile.ProtoTransportPayloadConfiguration;
45 46 import org.thingsboard.server.common.data.device.profile.TransportPayloadTypeConfiguration;
46   -import org.thingsboard.server.common.data.firmware.FirmwareType;
  47 +import org.thingsboard.server.common.data.ota.OtaPackageType;
47 48 import org.thingsboard.server.common.data.security.DeviceTokenCredentials;
48 49 import org.thingsboard.server.common.msg.session.FeatureType;
49 50 import org.thingsboard.server.common.msg.session.SessionMsgType;
... ... @@ -55,11 +56,14 @@ import org.thingsboard.server.gen.transport.TransportProtos;
55 56 import org.thingsboard.server.transport.coap.adaptors.CoapTransportAdaptor;
56 57
57 58 import java.util.List;
  59 +import java.util.Map;
58 60 import java.util.Optional;
  61 +import java.util.Random;
59 62 import java.util.Set;
60 63 import java.util.UUID;
61 64 import java.util.concurrent.ConcurrentHashMap;
62 65 import java.util.concurrent.ConcurrentMap;
  66 +import java.util.concurrent.TimeUnit;
63 67 import java.util.concurrent.atomic.AtomicInteger;
64 68
65 69 @Slf4j
... ... @@ -72,25 +76,30 @@ public class CoapTransportResource extends AbstractCoapTransportResource {
72 76 private static final int REQUEST_ID_POSITION_CERTIFICATE_REQUEST = 4;
73 77 private static final String DTLS_SESSION_ID_KEY = "DTLS_SESSION_ID";
74 78
75   - private final ConcurrentMap<String, TransportProtos.SessionInfoProto> tokenToSessionIdMap = new ConcurrentHashMap<>();
76   - private final ConcurrentMap<String, AtomicInteger> tokenToNotificationCounterMap = new ConcurrentHashMap<>();
  79 + private final ConcurrentMap<String, TransportProtos.SessionInfoProto> tokenToSessionInfoMap = new ConcurrentHashMap<>();
  80 + private final ConcurrentMap<String, AtomicInteger> tokenToObserveNotificationSeqMap = new ConcurrentHashMap<>();
  81 + private final ConcurrentMap<TransportProtos.SessionInfoProto, ObserveRelation> sessionInfoToObserveRelationMap = new ConcurrentHashMap<>();
77 82 private final Set<UUID> rpcSubscriptions = ConcurrentHashMap.newKeySet();
78 83 private final Set<UUID> attributeSubscriptions = ConcurrentHashMap.newKeySet();
79 84
80 85 private ConcurrentMap<String, TbCoapDtlsSessionInfo> dtlsSessionIdMap;
81 86 private long timeout;
  87 + private long sessionReportTimeout;
82 88
83   - public CoapTransportResource(CoapTransportContext coapTransportContext, CoapServerService coapServerService, String name) {
84   - super(coapTransportContext, name);
  89 + public CoapTransportResource(CoapTransportContext ctx, CoapServerService coapServerService, String name) {
  90 + super(ctx, name);
85 91 this.setObservable(true); // enable observing
86 92 this.addObserver(new CoapResourceObserver());
87 93 this.dtlsSessionIdMap = coapServerService.getDtlsSessionsMap();
88 94 this.timeout = coapServerService.getTimeout();
89   -// this.setObservable(false); // disable observing
90   -// this.setObserveType(CoAP.Type.CON); // configure the notification type to CONs
91   -// this.getAttributes().setObservable(); // mark observable in the Link-Format
  95 + this.sessionReportTimeout = ctx.getSessionReportTimeout();
  96 + ctx.getScheduler().scheduleAtFixedRate(() -> {
  97 + Set<TransportProtos.SessionInfoProto> observeSessions = sessionInfoToObserveRelationMap.keySet();
  98 + observeSessions.forEach(this::reportActivity);
  99 + }, new Random().nextInt((int) sessionReportTimeout), sessionReportTimeout, TimeUnit.MILLISECONDS);
92 100 }
93 101
  102 + @Override
94 103 public void checkObserveRelation(Exchange exchange, Response response) {
95 104 String token = getTokenFromRequest(exchange.getRequest());
96 105 final ObserveRelation relation = exchange.getRelation();
... ... @@ -103,11 +112,20 @@ public class CoapTransportResource extends AbstractCoapTransportResource {
103 112 relation.setEstablished();
104 113 addObserveRelation(relation);
105 114 }
106   - AtomicInteger notificationCounter = tokenToNotificationCounterMap.computeIfAbsent(token, s -> new AtomicInteger(0));
  115 + AtomicInteger notificationCounter = tokenToObserveNotificationSeqMap.computeIfAbsent(token, s -> new AtomicInteger(0));
107 116 response.getOptions().setObserve(notificationCounter.getAndIncrement());
108 117 } // ObserveLayer takes care of the else case
109 118 }
110 119
  120 + public void clearAndNotifyObserveRelation(ObserveRelation relation, CoAP.ResponseCode code) {
  121 + relation.cancel();
  122 + relation.getExchange().sendResponse(new Response(code));
  123 + }
  124 +
  125 + public Map<TransportProtos.SessionInfoProto, ObserveRelation> getSessionInfoToObserveRelationMap() {
  126 + return sessionInfoToObserveRelationMap;
  127 + }
  128 +
111 129 @Override
112 130 protected void processHandleGet(CoapExchange exchange) {
113 131 Optional<FeatureType> featureType = getFeatureType(exchange.advanced().getRequest());
... ... @@ -239,7 +257,7 @@ public class CoapTransportResource extends AbstractCoapTransportResource {
239 257 }
240 258
241 259 private void processRequest(CoapExchange exchange, SessionMsgType type, Request request, TransportProtos.SessionInfoProto sessionInfo, DeviceProfile deviceProfile) {
242   - UUID sessionId = new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB());
  260 + UUID sessionId = toSessionId(sessionInfo);
243 261 try {
244 262 TransportConfigurationContainer transportConfigurationContainer = getTransportConfigurationContainer(deviceProfile);
245 263 CoapTransportAdaptor coapTransportAdaptor = getCoapTransportAdaptor(transportConfigurationContainer.isJsonPayload());
... ... @@ -249,14 +267,14 @@ public class CoapTransportResource extends AbstractCoapTransportResource {
249 267 coapTransportAdaptor.convertToPostAttributes(sessionId, request,
250 268 transportConfigurationContainer.getAttributesMsgDescriptor()),
251 269 new CoapOkCallback(exchange, CoAP.ResponseCode.CREATED, CoAP.ResponseCode.INTERNAL_SERVER_ERROR));
252   - reportActivity(sessionInfo, attributeSubscriptions.contains(sessionId), rpcSubscriptions.contains(sessionId));
  270 + reportSubscriptionInfo(sessionInfo, attributeSubscriptions.contains(sessionId), rpcSubscriptions.contains(sessionId));
253 271 break;
254 272 case POST_TELEMETRY_REQUEST:
255 273 transportService.process(sessionInfo,
256 274 coapTransportAdaptor.convertToPostTelemetry(sessionId, request,
257 275 transportConfigurationContainer.getTelemetryMsgDescriptor()),
258 276 new CoapOkCallback(exchange, CoAP.ResponseCode.CREATED, CoAP.ResponseCode.INTERNAL_SERVER_ERROR));
259   - reportActivity(sessionInfo, attributeSubscriptions.contains(sessionId), rpcSubscriptions.contains(sessionId));
  277 + reportSubscriptionInfo(sessionInfo, attributeSubscriptions.contains(sessionId), rpcSubscriptions.contains(sessionId));
260 278 break;
261 279 case CLAIM_REQUEST:
262 280 transportService.process(sessionInfo,
... ... @@ -264,49 +282,52 @@ public class CoapTransportResource extends AbstractCoapTransportResource {
264 282 new CoapOkCallback(exchange, CoAP.ResponseCode.CREATED, CoAP.ResponseCode.INTERNAL_SERVER_ERROR));
265 283 break;
266 284 case SUBSCRIBE_ATTRIBUTES_REQUEST:
267   - TransportProtos.SessionInfoProto currentAttrSession = tokenToSessionIdMap.get(getTokenFromRequest(request));
  285 + TransportProtos.SessionInfoProto currentAttrSession = tokenToSessionInfoMap.get(getTokenFromRequest(request));
268 286 if (currentAttrSession == null) {
269 287 attributeSubscriptions.add(sessionId);
270 288 registerAsyncCoapSession(exchange, sessionInfo, coapTransportAdaptor,
271 289 transportConfigurationContainer.getRpcRequestDynamicMessageBuilder(), getTokenFromRequest(request));
272 290 transportService.process(sessionInfo,
273 291 TransportProtos.SubscribeToAttributeUpdatesMsg.getDefaultInstance(), new CoapNoOpCallback(exchange));
  292 + transportService.process(sessionInfo,
  293 + TransportProtos.GetAttributeRequestMsg.newBuilder().setOnlyShared(true).build(),
  294 + new CoapNoOpCallback(exchange));
274 295 }
275 296 break;
276 297 case UNSUBSCRIBE_ATTRIBUTES_REQUEST:
277 298 TransportProtos.SessionInfoProto attrSession = lookupAsyncSessionInfo(getTokenFromRequest(request));
278 299 if (attrSession != null) {
279   - UUID attrSessionId = new UUID(attrSession.getSessionIdMSB(), attrSession.getSessionIdLSB());
  300 + UUID attrSessionId = toSessionId(attrSession);
280 301 attributeSubscriptions.remove(attrSessionId);
  302 + sessionInfoToObserveRelationMap.remove(attrSession);
281 303 transportService.process(attrSession,
282 304 TransportProtos.SubscribeToAttributeUpdatesMsg.newBuilder().setUnsubscribe(true).build(),
283 305 new CoapOkCallback(exchange, CoAP.ResponseCode.DELETED, CoAP.ResponseCode.INTERNAL_SERVER_ERROR));
284   - closeAndDeregister(sessionInfo, sessionId);
  306 + closeAndDeregister(sessionInfo);
285 307 }
286 308 break;
287 309 case SUBSCRIBE_RPC_COMMANDS_REQUEST:
288   - TransportProtos.SessionInfoProto currentRpcSession = tokenToSessionIdMap.get(getTokenFromRequest(request));
  310 + TransportProtos.SessionInfoProto currentRpcSession = tokenToSessionInfoMap.get(getTokenFromRequest(request));
289 311 if (currentRpcSession == null) {
290 312 rpcSubscriptions.add(sessionId);
291 313 registerAsyncCoapSession(exchange, sessionInfo, coapTransportAdaptor,
292 314 transportConfigurationContainer.getRpcRequestDynamicMessageBuilder(), getTokenFromRequest(request));
293 315 transportService.process(sessionInfo,
294 316 TransportProtos.SubscribeToRPCMsg.getDefaultInstance(),
295   - new CoapNoOpCallback(exchange));
296   - } else {
297   - UUID rpcSessionId = new UUID(currentRpcSession.getSessionIdMSB(), currentRpcSession.getSessionIdLSB());
298   - reportActivity(currentRpcSession, attributeSubscriptions.contains(rpcSessionId), rpcSubscriptions.contains(rpcSessionId));
  317 + new CoapOkCallback(exchange, CoAP.ResponseCode.VALID, CoAP.ResponseCode.INTERNAL_SERVER_ERROR)
  318 + );
299 319 }
300 320 break;
301 321 case UNSUBSCRIBE_RPC_COMMANDS_REQUEST:
302 322 TransportProtos.SessionInfoProto rpcSession = lookupAsyncSessionInfo(getTokenFromRequest(request));
303 323 if (rpcSession != null) {
304   - UUID rpcSessionId = new UUID(rpcSession.getSessionIdMSB(), rpcSession.getSessionIdLSB());
  324 + UUID rpcSessionId = toSessionId(rpcSession);
305 325 rpcSubscriptions.remove(rpcSessionId);
  326 + sessionInfoToObserveRelationMap.remove(rpcSession);
306 327 transportService.process(rpcSession,
307 328 TransportProtos.SubscribeToRPCMsg.newBuilder().setUnsubscribe(true).build(),
308 329 new CoapOkCallback(exchange, CoAP.ResponseCode.DELETED, CoAP.ResponseCode.INTERNAL_SERVER_ERROR));
309   - closeAndDeregister(sessionInfo, sessionId);
  330 + closeAndDeregister(sessionInfo);
310 331 }
311 332 break;
312 333 case TO_DEVICE_RPC_RESPONSE:
... ... @@ -329,10 +350,10 @@ public class CoapTransportResource extends AbstractCoapTransportResource {
329 350 new CoapNoOpCallback(exchange));
330 351 break;
331 352 case GET_FIRMWARE_REQUEST:
332   - getFirmwareCallback(sessionInfo, exchange, FirmwareType.FIRMWARE);
  353 + getOtaPackageCallback(sessionInfo, exchange, OtaPackageType.FIRMWARE);
333 354 break;
334 355 case GET_SOFTWARE_REQUEST:
335   - getFirmwareCallback(sessionInfo, exchange, FirmwareType.SOFTWARE);
  356 + getOtaPackageCallback(sessionInfo, exchange, OtaPackageType.SOFTWARE);
336 357 break;
337 358 }
338 359 } catch (AdaptorException e) {
... ... @@ -341,29 +362,33 @@ public class CoapTransportResource extends AbstractCoapTransportResource {
341 362 }
342 363 }
343 364
344   - private void getFirmwareCallback(TransportProtos.SessionInfoProto sessionInfo, CoapExchange exchange, FirmwareType firmwareType) {
345   - TransportProtos.GetFirmwareRequestMsg requestMsg = TransportProtos.GetFirmwareRequestMsg.newBuilder()
  365 + private UUID toSessionId(TransportProtos.SessionInfoProto sessionInfoProto) {
  366 + return new UUID(sessionInfoProto.getSessionIdMSB(), sessionInfoProto.getSessionIdLSB());
  367 + }
  368 +
  369 + private void getOtaPackageCallback(TransportProtos.SessionInfoProto sessionInfo, CoapExchange exchange, OtaPackageType firmwareType) {
  370 + TransportProtos.GetOtaPackageRequestMsg requestMsg = TransportProtos.GetOtaPackageRequestMsg.newBuilder()
346 371 .setTenantIdMSB(sessionInfo.getTenantIdMSB())
347 372 .setTenantIdLSB(sessionInfo.getTenantIdLSB())
348 373 .setDeviceIdMSB(sessionInfo.getDeviceIdMSB())
349 374 .setDeviceIdLSB(sessionInfo.getDeviceIdLSB())
350 375 .setType(firmwareType.name()).build();
351   - transportContext.getTransportService().process(sessionInfo, requestMsg, new FirmwareCallback(exchange));
  376 + transportContext.getTransportService().process(sessionInfo, requestMsg, new OtaPackageCallback(exchange));
352 377 }
353 378
354 379 private TransportProtos.SessionInfoProto lookupAsyncSessionInfo(String token) {
355   - tokenToNotificationCounterMap.remove(token);
356   - return tokenToSessionIdMap.remove(token);
  380 + tokenToObserveNotificationSeqMap.remove(token);
  381 + return tokenToSessionInfoMap.remove(token);
357 382 }
358 383
359 384 private void registerAsyncCoapSession(CoapExchange exchange, TransportProtos.SessionInfoProto sessionInfo, CoapTransportAdaptor coapTransportAdaptor, DynamicMessage.Builder rpcRequestDynamicMessageBuilder, String token) {
360   - tokenToSessionIdMap.putIfAbsent(token, sessionInfo);
  385 + tokenToSessionInfoMap.putIfAbsent(token, sessionInfo);
361 386 transportService.registerAsyncSession(sessionInfo, getCoapSessionListener(exchange, coapTransportAdaptor, rpcRequestDynamicMessageBuilder));
362 387 transportService.process(sessionInfo, getSessionEventMsg(TransportProtos.SessionEvent.OPEN), null);
363 388 }
364 389
365 390 private CoapSessionListener getCoapSessionListener(CoapExchange exchange, CoapTransportAdaptor coapTransportAdaptor, DynamicMessage.Builder rpcRequestDynamicMessageBuilder) {
366   - return new CoapSessionListener(exchange, coapTransportAdaptor, rpcRequestDynamicMessageBuilder);
  391 + return new CoapSessionListener(this, exchange, coapTransportAdaptor, rpcRequestDynamicMessageBuilder);
367 392 }
368 393
369 394 private String getTokenFromRequest(Request request) {
... ... @@ -445,25 +470,25 @@ public class CoapTransportResource extends AbstractCoapTransportResource {
445 470 }
446 471 }
447 472
448   - private class FirmwareCallback implements TransportServiceCallback<TransportProtos.GetFirmwareResponseMsg> {
  473 + private class OtaPackageCallback implements TransportServiceCallback<TransportProtos.GetOtaPackageResponseMsg> {
449 474 private final CoapExchange exchange;
450 475
451   - FirmwareCallback(CoapExchange exchange) {
  476 + OtaPackageCallback(CoapExchange exchange) {
452 477 this.exchange = exchange;
453 478 }
454 479
455 480 @Override
456   - public void onSuccess(TransportProtos.GetFirmwareResponseMsg msg) {
  481 + public void onSuccess(TransportProtos.GetOtaPackageResponseMsg msg) {
457 482 String title = exchange.getQueryParameter("title");
458 483 String version = exchange.getQueryParameter("version");
459 484 if (msg.getResponseStatus().equals(TransportProtos.ResponseStatus.SUCCESS)) {
460 485 if (msg.getTitle().equals(title) && msg.getVersion().equals(version)) {
461   - String firmwareId = new UUID(msg.getFirmwareIdMSB(), msg.getFirmwareIdLSB()).toString();
  486 + String firmwareId = new UUID(msg.getOtaPackageIdMSB(), msg.getOtaPackageIdLSB()).toString();
462 487 String strChunkSize = exchange.getQueryParameter("size");
463 488 String strChunk = exchange.getQueryParameter("chunk");
464 489 int chunkSize = StringUtils.isEmpty(strChunkSize) ? 0 : Integer.parseInt(strChunkSize);
465 490 int chunk = StringUtils.isEmpty(strChunk) ? 0 : Integer.parseInt(strChunk);
466   - exchange.respond(CoAP.ResponseCode.CONTENT, transportContext.getFirmwareDataCache().get(firmwareId, chunkSize, chunk));
  491 + exchange.respond(CoAP.ResponseCode.CONTENT, transportContext.getOtaPackageDataCache().get(firmwareId, chunkSize, chunk));
467 492 } else {
468 493 exchange.respond(CoAP.ResponseCode.BAD_REQUEST);
469 494 }
... ... @@ -481,11 +506,13 @@ public class CoapTransportResource extends AbstractCoapTransportResource {
481 506
482 507 private static class CoapSessionListener implements SessionMsgListener {
483 508
  509 + private final CoapTransportResource coapTransportResource;
484 510 private final CoapExchange exchange;
485 511 private final CoapTransportAdaptor coapTransportAdaptor;
486 512 private final DynamicMessage.Builder rpcRequestDynamicMessageBuilder;
487 513
488   - CoapSessionListener(CoapExchange exchange, CoapTransportAdaptor coapTransportAdaptor, DynamicMessage.Builder rpcRequestDynamicMessageBuilder) {
  514 + CoapSessionListener(CoapTransportResource coapTransportResource, CoapExchange exchange, CoapTransportAdaptor coapTransportAdaptor, DynamicMessage.Builder rpcRequestDynamicMessageBuilder) {
  515 + this.coapTransportResource = coapTransportResource;
489 516 this.exchange = exchange;
490 517 this.coapTransportAdaptor = coapTransportAdaptor;
491 518 this.rpcRequestDynamicMessageBuilder = rpcRequestDynamicMessageBuilder;
... ... @@ -494,7 +521,7 @@ public class CoapTransportResource extends AbstractCoapTransportResource {
494 521 @Override
495 522 public void onGetAttributesResponse(TransportProtos.GetAttributeResponseMsg msg) {
496 523 try {
497   - exchange.respond(coapTransportAdaptor.convertToPublish(msg));
  524 + exchange.respond(coapTransportAdaptor.convertToPublish(isConRequest(), msg));
498 525 } catch (AdaptorException e) {
499 526 log.trace("Failed to reply due to error", e);
500 527 exchange.respond(CoAP.ResponseCode.INTERNAL_SERVER_ERROR);
... ... @@ -512,8 +539,21 @@ public class CoapTransportResource extends AbstractCoapTransportResource {
512 539 }
513 540
514 541 @Override
515   - public void onRemoteSessionCloseCommand(TransportProtos.SessionCloseNotificationProto sessionCloseNotification) {
516   - exchange.respond(CoAP.ResponseCode.SERVICE_UNAVAILABLE);
  542 + public void onRemoteSessionCloseCommand(UUID sessionId, TransportProtos.SessionCloseNotificationProto sessionCloseNotification) {
  543 + log.trace("[{}] Received the remote command to close the session: {}", sessionId, sessionCloseNotification.getMessage());
  544 + Map<TransportProtos.SessionInfoProto, ObserveRelation> sessionToObserveRelationMap = coapTransportResource.getSessionInfoToObserveRelationMap();
  545 + if (coapTransportResource.getObserverCount() > 0 && !CollectionUtils.isEmpty(sessionToObserveRelationMap)) {
  546 + Set<TransportProtos.SessionInfoProto> observeSessions = sessionToObserveRelationMap.keySet();
  547 + Optional<TransportProtos.SessionInfoProto> observeSessionToClose = observeSessions.stream().filter(sessionInfoProto -> {
  548 + UUID observeSessionId = new UUID(sessionInfoProto.getSessionIdMSB(), sessionInfoProto.getSessionIdLSB());
  549 + return observeSessionId.equals(sessionId);
  550 + }).findFirst();
  551 + if (observeSessionToClose.isPresent()) {
  552 + TransportProtos.SessionInfoProto sessionInfoProto = observeSessionToClose.get();
  553 + ObserveRelation observeRelation = sessionToObserveRelationMap.get(sessionInfoProto);
  554 + coapTransportResource.clearAndNotifyObserveRelation(observeRelation, CoAP.ResponseCode.SERVICE_UNAVAILABLE);
  555 + }
  556 + }
517 557 }
518 558
519 559 @Override
... ... @@ -529,7 +569,7 @@ public class CoapTransportResource extends AbstractCoapTransportResource {
529 569 @Override
530 570 public void onToServerRpcResponse(TransportProtos.ToServerRpcResponseMsg msg) {
531 571 try {
532   - exchange.respond(coapTransportAdaptor.convertToPublish(msg));
  572 + exchange.respond(coapTransportAdaptor.convertToPublish(isConRequest(), msg));
533 573 } catch (AdaptorException e) {
534 574 log.trace("Failed to reply due to error", e);
535 575 exchange.respond(CoAP.ResponseCode.INTERNAL_SERVER_ERROR);
... ... @@ -561,29 +601,29 @@ public class CoapTransportResource extends AbstractCoapTransportResource {
561 601
562 602 @Override
563 603 public void addedObserveRelation(ObserveRelation relation) {
564   - if (log.isTraceEnabled()) {
565   - Request request = relation.getExchange().getRequest();
566   - log.trace("Added Observe relation for token: {}", getTokenFromRequest(request));
567   - }
  604 + Request request = relation.getExchange().getRequest();
  605 + String token = getTokenFromRequest(request);
  606 + sessionInfoToObserveRelationMap.putIfAbsent(tokenToSessionInfoMap.get(token), relation);
  607 + log.trace("Added Observe relation for token: {}", token);
568 608 }
569 609
570 610 @Override
571 611 public void removedObserveRelation(ObserveRelation relation) {
572 612 Request request = relation.getExchange().getRequest();
573   - String tokenFromRequest = getTokenFromRequest(request);
574   - log.trace("Relation removed for token: {}", tokenFromRequest);
575   - TransportProtos.SessionInfoProto sessionInfoToRemove = lookupAsyncSessionInfo(tokenFromRequest);
576   - if (sessionInfoToRemove != null) {
577   - closeAndDeregister(sessionInfoToRemove, new UUID(sessionInfoToRemove.getSessionIdMSB(), sessionInfoToRemove.getDeviceIdLSB()));
578   - }
  613 + String token = getTokenFromRequest(request);
  614 + TransportProtos.SessionInfoProto session = tokenToSessionInfoMap.get(token);
  615 + sessionInfoToObserveRelationMap.remove(session);
  616 + log.trace("Relation removed for token: {}", token);
579 617 }
580 618 }
581 619
582   - private void closeAndDeregister(TransportProtos.SessionInfoProto session, UUID sessionId) {
  620 + private void closeAndDeregister(TransportProtos.SessionInfoProto session) {
  621 + UUID sessionId = toSessionId(session);
583 622 transportService.process(session, getSessionEventMsg(TransportProtos.SessionEvent.CLOSED), null);
584 623 transportService.deregisterSession(session);
585 624 rpcSubscriptions.remove(sessionId);
586 625 attributeSubscriptions.remove(sessionId);
  626 + sessionInfoToObserveRelationMap.remove(session);
587 627 }
588 628
589 629 private TransportConfigurationContainer getTransportConfigurationContainer(DeviceProfile deviceProfile) throws AdaptorException {
... ...
... ... @@ -19,7 +19,6 @@ import lombok.extern.slf4j.Slf4j;
19 19 import org.eclipse.californium.core.CoapResource;
20 20 import org.eclipse.californium.core.CoapServer;
21 21 import org.springframework.beans.factory.annotation.Autowired;
22   -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
23 22 import org.springframework.stereotype.Service;
24 23 import org.thingsboard.server.common.data.TbTransportService;
25 24 import org.thingsboard.server.coapserver.CoapServerService;
... ...
... ... @@ -40,6 +40,7 @@ public class CoapAdaptorUtils {
40 40 result.addAllSharedAttributeNames(sharedKeys);
41 41 }
42 42 }
  43 + result.setOnlyShared(false);
43 44 return result.build();
44 45 }
45 46
... ...
... ... @@ -39,13 +39,13 @@ public interface CoapTransportAdaptor {
39 39
40 40 TransportProtos.ClaimDeviceMsg convertToClaimDevice(UUID sessionId, Request inbound, TransportProtos.SessionInfoProto sessionInfo) throws AdaptorException;
41 41
42   - Response convertToPublish(TransportProtos.GetAttributeResponseMsg responseMsg) throws AdaptorException;
  42 + Response convertToPublish(boolean isConfirmable, TransportProtos.GetAttributeResponseMsg responseMsg) throws AdaptorException;
43 43
44 44 Response convertToPublish(boolean isConfirmable, TransportProtos.AttributeUpdateNotificationMsg notificationMsg) throws AdaptorException;
45 45
46 46 Response convertToPublish(boolean isConfirmable, TransportProtos.ToDeviceRpcRequestMsg rpcRequest, DynamicMessage.Builder rpcRequestDynamicMessageBuilder) throws AdaptorException;
47 47
48   - Response convertToPublish(TransportProtos.ToServerRpcResponseMsg msg) throws AdaptorException;
  48 + Response convertToPublish(boolean isConfirmable, TransportProtos.ToServerRpcResponseMsg msg) throws AdaptorException;
49 49
50 50 ProvisionDeviceRequestMsg convertToProvisionRequestMsg(UUID sessionId, Request inbound) throws AdaptorException;
51 51
... ...
... ... @@ -26,12 +26,14 @@ import org.eclipse.californium.core.coap.CoAP;
26 26 import org.eclipse.californium.core.coap.Request;
27 27 import org.eclipse.californium.core.coap.Response;
28 28 import org.springframework.stereotype.Component;
  29 +import org.springframework.util.StringUtils;
29 30 import org.thingsboard.server.common.data.id.DeviceId;
30 31 import org.thingsboard.server.common.transport.adaptor.AdaptorException;
31 32 import org.thingsboard.server.common.transport.adaptor.JsonConverter;
32 33 import org.thingsboard.server.gen.transport.TransportProtos;
33 34 import org.thingsboard.server.transport.coap.CoapTransportResource;
34 35
  36 +import java.util.List;
35 37 import java.util.Optional;
36 38 import java.util.UUID;
37 39
... ... @@ -101,10 +103,11 @@ public class JsonCoapAdaptor implements CoapTransportAdaptor {
101 103 }
102 104
103 105 @Override
104   - public Response convertToPublish(TransportProtos.ToServerRpcResponseMsg msg) throws AdaptorException {
  106 + public Response convertToPublish(boolean isConfirmable, TransportProtos.ToServerRpcResponseMsg msg) throws AdaptorException {
105 107 Response response = new Response(CoAP.ResponseCode.CONTENT);
106 108 JsonElement result = JsonConverter.toJson(msg);
107 109 response.setPayload(result.toString());
  110 + response.setAcknowledged(isConfirmable);
108 111 return response;
109 112 }
110 113
... ... @@ -119,21 +122,35 @@ public class JsonCoapAdaptor implements CoapTransportAdaptor {
119 122 }
120 123
121 124 @Override
122   - public Response convertToPublish(TransportProtos.GetAttributeResponseMsg msg) throws AdaptorException {
123   - if (msg.getClientAttributeListCount() == 0 && msg.getSharedAttributeListCount() == 0) {
124   - return new Response(CoAP.ResponseCode.NOT_FOUND);
  125 + public Response convertToPublish(boolean isConfirmable, TransportProtos.GetAttributeResponseMsg msg) throws AdaptorException {
  126 + if (msg.getSharedStateMsg()) {
  127 + if (StringUtils.isEmpty(msg.getError())) {
  128 + Response response = new Response(CoAP.ResponseCode._UNKNOWN_SUCCESS_CODE);
  129 + response.setAcknowledged(isConfirmable);
  130 + TransportProtos.AttributeUpdateNotificationMsg notificationMsg = TransportProtos.AttributeUpdateNotificationMsg.newBuilder().addAllSharedUpdated(msg.getSharedAttributeListList()).build();
  131 + JsonObject result = JsonConverter.toJson(notificationMsg);
  132 + response.setPayload(result.toString());
  133 + return response;
  134 + } else {
  135 + return new Response(CoAP.ResponseCode.INTERNAL_SERVER_ERROR);
  136 + }
125 137 } else {
126   - Response response = new Response(CoAP.ResponseCode.CONTENT);
127   - JsonObject result = JsonConverter.toJson(msg);
128   - response.setPayload(result.toString());
129   - return response;
  138 + if (msg.getClientAttributeListCount() == 0 && msg.getSharedAttributeListCount() == 0) {
  139 + return new Response(CoAP.ResponseCode.NOT_FOUND);
  140 + } else {
  141 + Response response = new Response(CoAP.ResponseCode.CONTENT);
  142 + response.setAcknowledged(isConfirmable);
  143 + JsonObject result = JsonConverter.toJson(msg);
  144 + response.setPayload(result.toString());
  145 + return response;
  146 + }
130 147 }
131 148 }
132 149
133 150 private Response getObserveNotification(boolean confirmable, JsonElement json) {
134   - Response response = new Response(CoAP.ResponseCode.CONTENT);
  151 + Response response = new Response(CoAP.ResponseCode._UNKNOWN_SUCCESS_CODE);
135 152 response.setPayload(json.toString());
136   - response.setConfirmable(confirmable);
  153 + response.setAcknowledged(confirmable);
137 154 return response;
138 155 }
139 156
... ...