Browse Source

Merge pull request #4672 from thingsboard/merge-issue-fix

Merge issue fix
pull/4679/head
Andrew Shvayka 5 years ago
committed by GitHub
parent
commit
b978f0f7ab
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 21
      application/src/main/data/json/demo/dashboards/firmware.json
  2. 14
      application/src/main/data/upgrade/3.2.2/schema_update.sql
  3. 42
      application/src/main/java/org/thingsboard/server/controller/BaseController.java
  4. 19
      application/src/main/java/org/thingsboard/server/controller/DeviceController.java
  5. 2
      application/src/main/java/org/thingsboard/server/controller/DeviceProfileController.java
  6. 222
      application/src/main/java/org/thingsboard/server/controller/FirmwareController.java
  7. 222
      application/src/main/java/org/thingsboard/server/controller/OtaPackageController.java
  8. 136
      application/src/main/java/org/thingsboard/server/service/ota/DefaultOtaPackageStateService.java
  9. 8
      application/src/main/java/org/thingsboard/server/service/ota/OtaPackageStateService.java
  10. 31
      application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerService.java
  11. 24
      application/src/main/java/org/thingsboard/server/service/security/AccessValidator.java
  12. 2
      application/src/main/java/org/thingsboard/server/service/security/permission/Resource.java
  13. 2
      application/src/main/java/org/thingsboard/server/service/security/permission/TenantAdminPermissions.java
  14. 68
      application/src/main/java/org/thingsboard/server/service/transport/DefaultTransportApiService.java
  15. 19
      application/src/main/resources/thingsboard.yml
  16. 115
      application/src/test/java/org/thingsboard/server/controller/BaseOtaPackageControllerTest.java
  17. 4
      application/src/test/java/org/thingsboard/server/controller/sql/OtaPackageControllerSqlTest.java
  18. 13
      common/cache/src/main/java/org/thingsboard/server/cache/ota/CaffeineOtaPackageCache.java
  19. 8
      common/cache/src/main/java/org/thingsboard/server/cache/ota/OtaPackageDataCache.java
  20. 19
      common/cache/src/main/java/org/thingsboard/server/cache/ota/RedisOtaPackageDataCache.java
  21. 5
      common/dao-api/src/main/java/org/thingsboard/server/dao/device/DeviceService.java
  22. 52
      common/dao-api/src/main/java/org/thingsboard/server/dao/firmware/FirmwareService.java
  23. 52
      common/dao-api/src/main/java/org/thingsboard/server/dao/ota/OtaPackageService.java
  24. 3
      common/data/src/main/java/org/thingsboard/server/common/data/CacheConstants.java
  25. 16
      common/data/src/main/java/org/thingsboard/server/common/data/Device.java
  26. 8
      common/data/src/main/java/org/thingsboard/server/common/data/DeviceProfile.java
  27. 2
      common/data/src/main/java/org/thingsboard/server/common/data/EntityType.java
  28. 8
      common/data/src/main/java/org/thingsboard/server/common/data/HasOtaPackage.java
  29. 10
      common/data/src/main/java/org/thingsboard/server/common/data/OtaPackage.java
  30. 40
      common/data/src/main/java/org/thingsboard/server/common/data/OtaPackageInfo.java
  31. 4
      common/data/src/main/java/org/thingsboard/server/common/data/id/EntityIdFactory.java
  32. 10
      common/data/src/main/java/org/thingsboard/server/common/data/id/OtaPackageId.java
  33. 2
      common/data/src/main/java/org/thingsboard/server/common/data/ota/ChecksumAlgorithm.java
  34. 6
      common/data/src/main/java/org/thingsboard/server/common/data/ota/OtaPackageKey.java
  35. 6
      common/data/src/main/java/org/thingsboard/server/common/data/ota/OtaPackageType.java
  36. 4
      common/data/src/main/java/org/thingsboard/server/common/data/ota/OtaPackageUpdateStatus.java
  37. 49
      common/data/src/main/java/org/thingsboard/server/common/data/ota/OtaPackageUtil.java
  38. 2
      common/queue/src/main/java/org/thingsboard/server/queue/kafka/TbKafkaTopicConfigs.java
  39. 10
      common/queue/src/main/java/org/thingsboard/server/queue/provider/AwsSqsMonolithQueueFactory.java
  40. 12
      common/queue/src/main/java/org/thingsboard/server/queue/provider/AwsSqsTbCoreQueueFactory.java
  41. 8
      common/queue/src/main/java/org/thingsboard/server/queue/provider/InMemoryMonolithQueueFactory.java
  42. 22
      common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaMonolithQueueFactory.java
  43. 22
      common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaTbCoreQueueFactory.java
  44. 12
      common/queue/src/main/java/org/thingsboard/server/queue/provider/PubSubMonolithQueueFactory.java
  45. 12
      common/queue/src/main/java/org/thingsboard/server/queue/provider/PubSubTbCoreQueueFactory.java
  46. 12
      common/queue/src/main/java/org/thingsboard/server/queue/provider/RabbitMqMonolithQueueFactory.java
  47. 12
      common/queue/src/main/java/org/thingsboard/server/queue/provider/RabbitMqTbCoreQueueFactory.java
  48. 12
      common/queue/src/main/java/org/thingsboard/server/queue/provider/ServiceBusMonolithQueueFactory.java
  49. 12
      common/queue/src/main/java/org/thingsboard/server/queue/provider/ServiceBusTbCoreQueueFactory.java
  50. 6
      common/queue/src/main/java/org/thingsboard/server/queue/provider/TbCoreQueueFactory.java
  51. 4
      common/queue/src/main/java/org/thingsboard/server/queue/provider/TbCoreQueueProducerProvider.java
  52. 4
      common/queue/src/main/java/org/thingsboard/server/queue/settings/TbQueueCoreSettings.java
  53. 18
      common/queue/src/main/proto/queue.proto
  54. 22
      common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/CoapTransportResource.java
  55. 32
      common/transport/http/src/main/java/org/thingsboard/server/transport/http/DeviceApiController.java
  56. 150
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2MTransportMsgHandler.java
  57. 152
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportRequest.java
  58. 11
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServerHelper.java
  59. 53
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportUtil.java
  60. 6
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClient.java
  61. 8
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContextImpl.java
  62. 66
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mFwSwUpdate.java
  63. 4
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/Lwm2mClientRpcRequest.java
  64. 9
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbLwM2mRedisRegistrationStore.java
  65. 3
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/utils/LwM2mValueConverterImpl.java
  66. 58
      common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java
  67. 4
      common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/adaptors/JsonMqttAdaptor.java
  68. 4
      common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/adaptors/MqttTransportAdaptor.java
  69. 4
      common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/adaptors/ProtoMqttAdaptor.java
  70. 5
      common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/TransportContext.java
  71. 6
      common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/TransportService.java
  72. 6
      common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/service/DefaultTransportService.java
  73. 8
      dao/src/main/java/org/thingsboard/server/dao/device/DeviceDao.java
  74. 16
      dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileServiceImpl.java
  75. 45
      dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java
  76. 12
      dao/src/main/java/org/thingsboard/server/dao/entity/BaseEntityService.java
  77. 379
      dao/src/main/java/org/thingsboard/server/dao/firmware/BaseFirmwareService.java
  78. 31
      dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java
  79. 6
      dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractDeviceEntity.java
  80. 6
      dao/src/main/java/org/thingsboard/server/dao/model/sql/DeviceProfileEntity.java
  81. 70
      dao/src/main/java/org/thingsboard/server/dao/model/sql/OtaPackageEntity.java
  82. 72
      dao/src/main/java/org/thingsboard/server/dao/model/sql/OtaPackageInfoEntity.java
  83. 366
      dao/src/main/java/org/thingsboard/server/dao/ota/BaseOtaPackageService.java
  84. 6
      dao/src/main/java/org/thingsboard/server/dao/ota/OtaPackageDao.java
  85. 18
      dao/src/main/java/org/thingsboard/server/dao/ota/OtaPackageInfoDao.java
  86. 20
      dao/src/main/java/org/thingsboard/server/dao/sql/device/DeviceRepository.java
  87. 36
      dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceDao.java
  88. 60
      dao/src/main/java/org/thingsboard/server/dao/sql/firmware/FirmwareInfoRepository.java
  89. 94
      dao/src/main/java/org/thingsboard/server/dao/sql/firmware/JpaFirmwareInfoDao.java
  90. 20
      dao/src/main/java/org/thingsboard/server/dao/sql/ota/JpaOtaPackageDao.java
  91. 94
      dao/src/main/java/org/thingsboard/server/dao/sql/ota/JpaOtaPackageInfoDao.java
  92. 60
      dao/src/main/java/org/thingsboard/server/dao/sql/ota/OtaPackageInfoRepository.java
  93. 6
      dao/src/main/java/org/thingsboard/server/dao/sql/ota/OtaPackageRepository.java
  94. 6
      dao/src/main/java/org/thingsboard/server/dao/tenant/TenantServiceImpl.java
  95. 14
      dao/src/main/resources/sql/schema-entities-hsql.sql
  96. 14
      dao/src/main/resources/sql/schema-entities.sql
  97. 4
      dao/src/test/java/org/thingsboard/server/dao/service/AbstractServiceTest.java
  98. 11
      dao/src/test/java/org/thingsboard/server/dao/service/BaseDeviceProfileServiceTest.java
  99. 14
      dao/src/test/java/org/thingsboard/server/dao/service/BaseDeviceServiceTest.java
  100. 246
      dao/src/test/java/org/thingsboard/server/dao/service/BaseOtaPackageServiceTest.java

21
application/src/main/data/json/demo/dashboards/firmware.json

@ -1,5 +1,6 @@
{
"title": "Firmware",
"image": null,
"configuration": {
"description": "",
"widgets": {
@ -247,7 +248,7 @@
"name": "Edit firmware",
"icon": "edit",
"type": "customPretty",
"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>",
"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>",
"customCss": "",
"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}",
"customResources": [],
@ -257,7 +258,7 @@
"name": "Download firware",
"icon": "file_download",
"type": "custom",
"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}",
"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}",
"id": "12533058-42f6-e75f-620c-219c48d01ec0"
},
{
@ -1021,7 +1022,7 @@
"name": "Edit firmware",
"icon": "edit",
"type": "customPretty",
"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>",
"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>",
"customCss": "",
"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}",
"customResources": [],
@ -1031,7 +1032,7 @@
"name": "Download firware",
"icon": "file_download",
"type": "custom",
"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}",
"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}",
"id": "12533058-42f6-e75f-620c-219c48d01ec0"
},
{
@ -1297,7 +1298,7 @@
"name": "Edit firmware",
"icon": "edit",
"type": "customPretty",
"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>",
"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>",
"customCss": "",
"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}",
"customResources": [],
@ -1307,7 +1308,7 @@
"name": "Download firware",
"icon": "file_download",
"type": "custom",
"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}",
"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}",
"id": "12533058-42f6-e75f-620c-219c48d01ec0"
},
{
@ -1573,7 +1574,7 @@
"name": "Edit firmware",
"icon": "edit",
"type": "customPretty",
"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>",
"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>",
"customCss": "",
"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}",
"customResources": [],
@ -1583,7 +1584,7 @@
"name": "Download firware",
"icon": "file_download",
"type": "custom",
"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}",
"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}",
"id": "12533058-42f6-e75f-620c-219c48d01ec0"
},
{
@ -1849,7 +1850,7 @@
"name": "Edit firmware",
"icon": "edit",
"type": "customPretty",
"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>",
"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>",
"customCss": "",
"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}",
"customResources": [],
@ -1859,7 +1860,7 @@
"name": "Download firware",
"icon": "file_download",
"type": "custom",
"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}",
"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}",
"id": "12533058-42f6-e75f-620c-219c48d01ec0"
},
{

14
application/src/main/data/upgrade/3.2.2/schema_update.sql

@ -59,8 +59,8 @@ CREATE TABLE IF NOT EXISTS resource (
CONSTRAINT resource_unq_key UNIQUE (tenant_id, resource_type, resource_key)
);
CREATE TABLE IF NOT EXISTS firmware (
id uuid NOT NULL CONSTRAINT firmware_pkey PRIMARY KEY,
CREATE TABLE IF NOT EXISTS ota_package (
id uuid NOT NULL CONSTRAINT ota_package_pkey PRIMARY KEY,
created_time bigint NOT NULL,
tenant_id uuid NOT NULL,
device_profile_id uuid,
@ -75,7 +75,7 @@ CREATE TABLE IF NOT EXISTS firmware (
data_size bigint,
additional_info varchar,
search_text varchar(255),
CONSTRAINT firmware_tenant_title_version_unq_key UNIQUE (tenant_id, title, version)
CONSTRAINT ota_package_tenant_title_version_unq_key UNIQUE (tenant_id, title, version)
);
ALTER TABLE dashboard
@ -101,13 +101,13 @@ DO $$
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_firmware_device_profile') THEN
ALTER TABLE device_profile
ADD CONSTRAINT fk_firmware_device_profile
FOREIGN KEY (firmware_id) REFERENCES firmware(id);
FOREIGN KEY (firmware_id) REFERENCES ota_package(id);
END IF;
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_software_device_profile') THEN
ALTER TABLE device_profile
ADD CONSTRAINT fk_software_device_profile
FOREIGN KEY (firmware_id) REFERENCES firmware(id);
FOREIGN KEY (firmware_id) REFERENCES ota_package(id);
END IF;
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_default_dashboard_device_profile') THEN
@ -119,13 +119,13 @@ DO $$
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_firmware_device') THEN
ALTER TABLE device
ADD CONSTRAINT fk_firmware_device
FOREIGN KEY (firmware_id) REFERENCES firmware(id);
FOREIGN KEY (firmware_id) REFERENCES ota_package(id);
END IF;
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_software_device') THEN
ALTER TABLE device
ADD CONSTRAINT fk_software_device
FOREIGN KEY (firmware_id) REFERENCES firmware(id);
FOREIGN KEY (firmware_id) REFERENCES ota_package(id);
END IF;
END;
$$;

42
application/src/main/java/org/thingsboard/server/controller/BaseController.java

@ -39,8 +39,8 @@ import org.thingsboard.server.common.data.EdgeUtils;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.EntityView;
import org.thingsboard.server.common.data.EntityViewInfo;
import org.thingsboard.server.common.data.Firmware;
import org.thingsboard.server.common.data.FirmwareInfo;
import org.thingsboard.server.common.data.OtaPackage;
import org.thingsboard.server.common.data.OtaPackageInfo;
import org.thingsboard.server.common.data.HasName;
import org.thingsboard.server.common.data.HasTenantId;
import org.thingsboard.server.common.data.TbResourceInfo;
@ -70,7 +70,7 @@ import org.thingsboard.server.common.data.id.EdgeId;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.EntityIdFactory;
import org.thingsboard.server.common.data.id.EntityViewId;
import org.thingsboard.server.common.data.id.FirmwareId;
import org.thingsboard.server.common.data.id.OtaPackageId;
import org.thingsboard.server.common.data.id.TbResourceId;
import org.thingsboard.server.common.data.id.RuleChainId;
import org.thingsboard.server.common.data.id.RuleNodeId;
@ -110,7 +110,7 @@ import org.thingsboard.server.dao.edge.EdgeService;
import org.thingsboard.server.dao.entityview.EntityViewService;
import org.thingsboard.server.dao.exception.DataValidationException;
import org.thingsboard.server.dao.exception.IncorrectParameterException;
import org.thingsboard.server.dao.firmware.FirmwareService;
import org.thingsboard.server.dao.ota.OtaPackageService;
import org.thingsboard.server.dao.model.ModelConstants;
import org.thingsboard.server.dao.oauth2.OAuth2ConfigTemplateService;
import org.thingsboard.server.dao.oauth2.OAuth2Service;
@ -128,7 +128,7 @@ import org.thingsboard.server.queue.discovery.PartitionService;
import org.thingsboard.server.queue.provider.TbQueueProducerProvider;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.component.ComponentDiscoveryService;
import org.thingsboard.server.service.firmware.FirmwareStateService;
import org.thingsboard.server.service.ota.OtaPackageStateService;
import org.thingsboard.server.service.edge.EdgeNotificationService;
import org.thingsboard.server.service.edge.rpc.EdgeGrpcService;
import org.thingsboard.server.service.edge.rpc.init.SyncEdgeService;
@ -250,10 +250,10 @@ public abstract class BaseController {
protected TbResourceService resourceService;
@Autowired
protected FirmwareService firmwareService;
protected OtaPackageService otaPackageService;
@Autowired
protected FirmwareStateService firmwareStateService;
protected OtaPackageStateService otaPackageStateService;
@Autowired
protected TbQueueProducerProvider producerProvider;
@ -511,8 +511,8 @@ public abstract class BaseController {
case TB_RESOURCE:
checkResourceId(new TbResourceId(entityId.getId()), operation);
return;
case FIRMWARE:
checkFirmwareId(new FirmwareId(entityId.getId()), operation);
case OTA_PACKAGE:
checkOtaPackageId(new OtaPackageId(entityId.getId()), operation);
return;
default:
throw new IllegalArgumentException("Unsupported entity type: " + entityId.getEntityType());
@ -769,25 +769,25 @@ public abstract class BaseController {
}
}
Firmware checkFirmwareId(FirmwareId firmwareId, Operation operation) throws ThingsboardException {
OtaPackage checkOtaPackageId(OtaPackageId otaPackageId, Operation operation) throws ThingsboardException {
try {
validateId(firmwareId, "Incorrect firmwareId " + firmwareId);
Firmware firmware = firmwareService.findFirmwareById(getCurrentUser().getTenantId(), firmwareId);
checkNotNull(firmware);
accessControlService.checkPermission(getCurrentUser(), Resource.FIRMWARE, operation, firmwareId, firmware);
return firmware;
validateId(otaPackageId, "Incorrect otaPackageId " + otaPackageId);
OtaPackage otaPackage = otaPackageService.findOtaPackageById(getCurrentUser().getTenantId(), otaPackageId);
checkNotNull(otaPackage);
accessControlService.checkPermission(getCurrentUser(), Resource.OTA_PACKAGE, operation, otaPackageId, otaPackage);
return otaPackage;
} catch (Exception e) {
throw handleException(e, false);
}
}
FirmwareInfo checkFirmwareInfoId(FirmwareId firmwareId, Operation operation) throws ThingsboardException {
OtaPackageInfo checkOtaPackageInfoId(OtaPackageId otaPackageId, Operation operation) throws ThingsboardException {
try {
validateId(firmwareId, "Incorrect firmwareId " + firmwareId);
FirmwareInfo firmwareInfo = firmwareService.findFirmwareInfoById(getCurrentUser().getTenantId(), firmwareId);
checkNotNull(firmwareInfo);
accessControlService.checkPermission(getCurrentUser(), Resource.FIRMWARE, operation, firmwareId, firmwareInfo);
return firmwareInfo;
validateId(otaPackageId, "Incorrect otaPackageId " + otaPackageId);
OtaPackageInfo otaPackageIn = otaPackageService.findOtaPackageInfoById(getCurrentUser().getTenantId(), otaPackageId);
checkNotNull(otaPackageIn);
accessControlService.checkPermission(getCurrentUser(), Resource.OTA_PACKAGE, operation, otaPackageId, otaPackageIn);
return otaPackageIn;
} catch (Exception e) {
throw handleException(e, false);
}

19
application/src/main/java/org/thingsboard/server/controller/DeviceController.java

@ -53,6 +53,7 @@ import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.data.id.EdgeId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.ota.OtaPackageType;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.page.TimePageLink;
@ -75,6 +76,7 @@ import javax.annotation.Nullable;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
import static org.thingsboard.server.controller.EdgeController.EDGE_ID;
@ -153,7 +155,7 @@ public class DeviceController extends BaseController {
deviceStateService.onDeviceUpdated(savedDevice);
}
firmwareStateService.update(savedDevice, oldDevice);
otaPackageStateService.update(savedDevice, oldDevice);
return savedDevice;
} catch (Exception e) {
@ -778,4 +780,19 @@ public class DeviceController extends BaseController {
throw handleException(e);
}
}
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/devices/count/{otaPackageType}", method = RequestMethod.GET)
@ResponseBody
public Long countDevicesByTenantIdAndDeviceProfileIdAndEmptyOtaPackage(@PathVariable("otaPackageType") String otaPackageType,
@RequestParam String deviceProfileId) throws ThingsboardException {
checkParameter("OtaPackageType", otaPackageType);
checkParameter("DeviceProfileId", deviceProfileId);
try {
return deviceService.countDevicesByTenantIdAndDeviceProfileIdAndEmptyOtaPackage(
getCurrentUser().getTenantId(), new DeviceProfileId(UUID.fromString(deviceProfileId)), OtaPackageType.valueOf(otaPackageType));
} catch (Exception e) {
throw handleException(e);
}
}
}

2
application/src/main/java/org/thingsboard/server/controller/DeviceProfileController.java

@ -168,7 +168,7 @@ public class DeviceProfileController extends BaseController {
null,
created ? ActionType.ADDED : ActionType.UPDATED, null);
firmwareStateService.update(savedDeviceProfile, isFirmwareChanged, isSoftwareChanged);
otaPackageStateService.update(savedDeviceProfile, isFirmwareChanged, isSoftwareChanged);
sendEntityNotificationMsg(getTenantId(), savedDeviceProfile.getId(),
deviceProfile.getId() == null ? EdgeEventActionType.ADDED : EdgeEventActionType.UPDATED);

222
application/src/main/java/org/thingsboard/server/controller/FirmwareController.java

@ -1,222 +0,0 @@
/**
* Copyright © 2016-2021 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.controller;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.Firmware;
import org.thingsboard.server.common.data.FirmwareInfo;
import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.firmware.ChecksumAlgorithm;
import org.thingsboard.server.common.data.firmware.FirmwareType;
import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.data.id.FirmwareId;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.security.permission.Operation;
import org.thingsboard.server.service.security.permission.Resource;
import java.nio.ByteBuffer;
@Slf4j
@RestController
@TbCoreComponent
@RequestMapping("/api")
public class FirmwareController extends BaseController {
public static final String FIRMWARE_ID = "firmwareId";
public static final String CHECKSUM_ALGORITHM = "checksumAlgorithm";
@PreAuthorize("hasAnyAuthority( 'TENANT_ADMIN')")
@RequestMapping(value = "/firmware/{firmwareId}/download", method = RequestMethod.GET)
@ResponseBody
public ResponseEntity<org.springframework.core.io.Resource> downloadFirmware(@PathVariable(FIRMWARE_ID) String strFirmwareId) throws ThingsboardException {
checkParameter(FIRMWARE_ID, strFirmwareId);
try {
FirmwareId firmwareId = new FirmwareId(toUUID(strFirmwareId));
Firmware firmware = checkFirmwareId(firmwareId, Operation.READ);
ByteArrayResource resource = new ByteArrayResource(firmware.getData().array());
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + firmware.getFileName())
.header("x-filename", firmware.getFileName())
.contentLength(resource.contentLength())
.contentType(parseMediaType(firmware.getContentType()))
.body(resource);
} catch (Exception e) {
throw handleException(e);
}
}
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/firmware/info/{firmwareId}", method = RequestMethod.GET)
@ResponseBody
public FirmwareInfo getFirmwareInfoById(@PathVariable(FIRMWARE_ID) String strFirmwareId) throws ThingsboardException {
checkParameter(FIRMWARE_ID, strFirmwareId);
try {
FirmwareId firmwareId = new FirmwareId(toUUID(strFirmwareId));
return checkNotNull(firmwareService.findFirmwareInfoById(getTenantId(), firmwareId));
} catch (Exception e) {
throw handleException(e);
}
}
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/firmware/{firmwareId}", method = RequestMethod.GET)
@ResponseBody
public Firmware getFirmwareById(@PathVariable(FIRMWARE_ID) String strFirmwareId) throws ThingsboardException {
checkParameter(FIRMWARE_ID, strFirmwareId);
try {
FirmwareId firmwareId = new FirmwareId(toUUID(strFirmwareId));
return checkFirmwareId(firmwareId, Operation.READ);
} catch (Exception e) {
throw handleException(e);
}
}
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/firmware", method = RequestMethod.POST)
@ResponseBody
public FirmwareInfo saveFirmwareInfo(@RequestBody FirmwareInfo firmwareInfo) throws ThingsboardException {
boolean created = firmwareInfo.getId() == null;
try {
firmwareInfo.setTenantId(getTenantId());
checkEntity(firmwareInfo.getId(), firmwareInfo, Resource.FIRMWARE);
FirmwareInfo savedFirmwareInfo = firmwareService.saveFirmwareInfo(firmwareInfo);
logEntityAction(savedFirmwareInfo.getId(), savedFirmwareInfo,
null, created ? ActionType.ADDED : ActionType.UPDATED, null);
return savedFirmwareInfo;
} catch (Exception e) {
logEntityAction(emptyId(EntityType.FIRMWARE), firmwareInfo,
null, created ? ActionType.ADDED : ActionType.UPDATED, e);
throw handleException(e);
}
}
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/firmware/{firmwareId}", method = RequestMethod.POST)
@ResponseBody
public Firmware saveFirmwareData(@PathVariable(FIRMWARE_ID) String strFirmwareId,
@RequestParam(required = false) String checksum,
@RequestParam(CHECKSUM_ALGORITHM) String checksumAlgorithmStr,
@RequestBody MultipartFile file) throws ThingsboardException {
checkParameter(FIRMWARE_ID, strFirmwareId);
checkParameter(CHECKSUM_ALGORITHM, checksumAlgorithmStr);
try {
FirmwareId firmwareId = new FirmwareId(toUUID(strFirmwareId));
FirmwareInfo info = checkFirmwareInfoId(firmwareId, Operation.READ);
Firmware firmware = new Firmware(firmwareId);
firmware.setCreatedTime(info.getCreatedTime());
firmware.setTenantId(getTenantId());
firmware.setDeviceProfileId(info.getDeviceProfileId());
firmware.setType(info.getType());
firmware.setTitle(info.getTitle());
firmware.setVersion(info.getVersion());
firmware.setAdditionalInfo(info.getAdditionalInfo());
ChecksumAlgorithm checksumAlgorithm = ChecksumAlgorithm.valueOf(checksumAlgorithmStr.toUpperCase());
byte[] bytes = file.getBytes();
if (StringUtils.isEmpty(checksum)) {
checksum = firmwareService.generateChecksum(checksumAlgorithm, ByteBuffer.wrap(bytes));
}
firmware.setChecksumAlgorithm(checksumAlgorithm);
firmware.setChecksum(checksum);
firmware.setFileName(file.getOriginalFilename());
firmware.setContentType(file.getContentType());
firmware.setData(ByteBuffer.wrap(bytes));
firmware.setDataSize((long) bytes.length);
Firmware savedFirmware = firmwareService.saveFirmware(firmware);
logEntityAction(savedFirmware.getId(), savedFirmware, null, ActionType.UPDATED, null);
return savedFirmware;
} catch (Exception e) {
logEntityAction(emptyId(EntityType.FIRMWARE), null, null, ActionType.UPDATED, e, strFirmwareId);
throw handleException(e);
}
}
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/firmwares", method = RequestMethod.GET)
@ResponseBody
public PageData<FirmwareInfo> getFirmwares(@RequestParam int pageSize,
@RequestParam int page,
@RequestParam(required = false) String textSearch,
@RequestParam(required = false) String sortProperty,
@RequestParam(required = false) String sortOrder) throws ThingsboardException {
try {
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
return checkNotNull(firmwareService.findTenantFirmwaresByTenantId(getTenantId(), pageLink));
} catch (Exception e) {
throw handleException(e);
}
}
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/firmwares/{deviceProfileId}/{type}/{hasData}", method = RequestMethod.GET)
@ResponseBody
public PageData<FirmwareInfo> getFirmwares(@PathVariable("deviceProfileId") String strDeviceProfileId,
@PathVariable("type") String strType,
@PathVariable("hasData") boolean hasData,
@RequestParam int pageSize,
@RequestParam int page,
@RequestParam(required = false) String textSearch,
@RequestParam(required = false) String sortProperty,
@RequestParam(required = false) String sortOrder) throws ThingsboardException {
checkParameter("deviceProfileId", strDeviceProfileId);
checkParameter("type", strType);
try {
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
return checkNotNull(firmwareService.findTenantFirmwaresByTenantIdAndDeviceProfileIdAndTypeAndHasData(getTenantId(),
new DeviceProfileId(toUUID(strDeviceProfileId)), FirmwareType.valueOf(strType), hasData, pageLink));
} catch (Exception e) {
throw handleException(e);
}
}
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/firmware/{firmwareId}", method = RequestMethod.DELETE)
@ResponseBody
public void deleteFirmware(@PathVariable("firmwareId") String strFirmwareId) throws ThingsboardException {
checkParameter(FIRMWARE_ID, strFirmwareId);
try {
FirmwareId firmwareId = new FirmwareId(toUUID(strFirmwareId));
FirmwareInfo info = checkFirmwareInfoId(firmwareId, Operation.DELETE);
firmwareService.deleteFirmware(getTenantId(), firmwareId);
logEntityAction(firmwareId, info, null, ActionType.DELETED, null, strFirmwareId);
} catch (Exception e) {
logEntityAction(emptyId(EntityType.FIRMWARE), null, null, ActionType.DELETED, e, strFirmwareId);
throw handleException(e);
}
}
}

222
application/src/main/java/org/thingsboard/server/controller/OtaPackageController.java

@ -0,0 +1,222 @@
/**
* Copyright © 2016-2021 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.controller;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.OtaPackage;
import org.thingsboard.server.common.data.OtaPackageInfo;
import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.ota.ChecksumAlgorithm;
import org.thingsboard.server.common.data.ota.OtaPackageType;
import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.data.id.OtaPackageId;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.security.permission.Operation;
import org.thingsboard.server.service.security.permission.Resource;
import java.nio.ByteBuffer;
@Slf4j
@RestController
@TbCoreComponent
@RequestMapping("/api")
public class OtaPackageController extends BaseController {
public static final String OTA_PACKAGE_ID = "otaPackageId";
public static final String CHECKSUM_ALGORITHM = "checksumAlgorithm";
@PreAuthorize("hasAnyAuthority( 'TENANT_ADMIN')")
@RequestMapping(value = "/otaPackage/{otaPackageId}/download", method = RequestMethod.GET)
@ResponseBody
public ResponseEntity<org.springframework.core.io.Resource> downloadOtaPackage(@PathVariable(OTA_PACKAGE_ID) String strOtaPackageId) throws ThingsboardException {
checkParameter(OTA_PACKAGE_ID, strOtaPackageId);
try {
OtaPackageId otaPackageId = new OtaPackageId(toUUID(strOtaPackageId));
OtaPackage otaPackage = checkOtaPackageId(otaPackageId, Operation.READ);
ByteArrayResource resource = new ByteArrayResource(otaPackage.getData().array());
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + otaPackage.getFileName())
.header("x-filename", otaPackage.getFileName())
.contentLength(resource.contentLength())
.contentType(parseMediaType(otaPackage.getContentType()))
.body(resource);
} catch (Exception e) {
throw handleException(e);
}
}
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/otaPackage/info/{otaPackageId}", method = RequestMethod.GET)
@ResponseBody
public OtaPackageInfo getOtaPackageInfoById(@PathVariable(OTA_PACKAGE_ID) String strOtaPackageId) throws ThingsboardException {
checkParameter(OTA_PACKAGE_ID, strOtaPackageId);
try {
OtaPackageId otaPackageId = new OtaPackageId(toUUID(strOtaPackageId));
return checkNotNull(otaPackageService.findOtaPackageInfoById(getTenantId(), otaPackageId));
} catch (Exception e) {
throw handleException(e);
}
}
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/otaPackage/{otaPackageId}", method = RequestMethod.GET)
@ResponseBody
public OtaPackage getOtaPackageById(@PathVariable(OTA_PACKAGE_ID) String strOtaPackageId) throws ThingsboardException {
checkParameter(OTA_PACKAGE_ID, strOtaPackageId);
try {
OtaPackageId otaPackageId = new OtaPackageId(toUUID(strOtaPackageId));
return checkOtaPackageId(otaPackageId, Operation.READ);
} catch (Exception e) {
throw handleException(e);
}
}
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/otaPackage", method = RequestMethod.POST)
@ResponseBody
public OtaPackageInfo saveOtaPackageInfo(@RequestBody OtaPackageInfo otaPackageInfo) throws ThingsboardException {
boolean created = otaPackageInfo.getId() == null;
try {
otaPackageInfo.setTenantId(getTenantId());
checkEntity(otaPackageInfo.getId(), otaPackageInfo, Resource.OTA_PACKAGE);
OtaPackageInfo savedOtaPackageInfo = otaPackageService.saveOtaPackageInfo(otaPackageInfo);
logEntityAction(savedOtaPackageInfo.getId(), savedOtaPackageInfo,
null, created ? ActionType.ADDED : ActionType.UPDATED, null);
return savedOtaPackageInfo;
} catch (Exception e) {
logEntityAction(emptyId(EntityType.OTA_PACKAGE), otaPackageInfo,
null, created ? ActionType.ADDED : ActionType.UPDATED, e);
throw handleException(e);
}
}
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/otaPackage/{otaPackageId}", method = RequestMethod.POST)
@ResponseBody
public OtaPackage saveOtaPackageData(@PathVariable(OTA_PACKAGE_ID) String strOtaPackageId,
@RequestParam(required = false) String checksum,
@RequestParam(CHECKSUM_ALGORITHM) String checksumAlgorithmStr,
@RequestBody MultipartFile file) throws ThingsboardException {
checkParameter(OTA_PACKAGE_ID, strOtaPackageId);
checkParameter(CHECKSUM_ALGORITHM, checksumAlgorithmStr);
try {
OtaPackageId otaPackageId = new OtaPackageId(toUUID(strOtaPackageId));
OtaPackageInfo info = checkOtaPackageInfoId(otaPackageId, Operation.READ);
OtaPackage otaPackage = new OtaPackage(otaPackageId);
otaPackage.setCreatedTime(info.getCreatedTime());
otaPackage.setTenantId(getTenantId());
otaPackage.setDeviceProfileId(info.getDeviceProfileId());
otaPackage.setType(info.getType());
otaPackage.setTitle(info.getTitle());
otaPackage.setVersion(info.getVersion());
otaPackage.setAdditionalInfo(info.getAdditionalInfo());
ChecksumAlgorithm checksumAlgorithm = ChecksumAlgorithm.valueOf(checksumAlgorithmStr.toUpperCase());
byte[] bytes = file.getBytes();
if (StringUtils.isEmpty(checksum)) {
checksum = otaPackageService.generateChecksum(checksumAlgorithm, ByteBuffer.wrap(bytes));
}
otaPackage.setChecksumAlgorithm(checksumAlgorithm);
otaPackage.setChecksum(checksum);
otaPackage.setFileName(file.getOriginalFilename());
otaPackage.setContentType(file.getContentType());
otaPackage.setData(ByteBuffer.wrap(bytes));
otaPackage.setDataSize((long) bytes.length);
OtaPackage savedOtaPackage = otaPackageService.saveOtaPackage(otaPackage);
logEntityAction(savedOtaPackage.getId(), savedOtaPackage, null, ActionType.UPDATED, null);
return savedOtaPackage;
} catch (Exception e) {
logEntityAction(emptyId(EntityType.OTA_PACKAGE), null, null, ActionType.UPDATED, e, strOtaPackageId);
throw handleException(e);
}
}
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/otaPackages", method = RequestMethod.GET)
@ResponseBody
public PageData<OtaPackageInfo> getOtaPackages(@RequestParam int pageSize,
@RequestParam int page,
@RequestParam(required = false) String textSearch,
@RequestParam(required = false) String sortProperty,
@RequestParam(required = false) String sortOrder) throws ThingsboardException {
try {
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
return checkNotNull(otaPackageService.findTenantOtaPackagesByTenantId(getTenantId(), pageLink));
} catch (Exception e) {
throw handleException(e);
}
}
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/otaPackages/{deviceProfileId}/{type}/{hasData}", method = RequestMethod.GET)
@ResponseBody
public PageData<OtaPackageInfo> getOtaPackages(@PathVariable("deviceProfileId") String strDeviceProfileId,
@PathVariable("type") String strType,
@PathVariable("hasData") boolean hasData,
@RequestParam int pageSize,
@RequestParam int page,
@RequestParam(required = false) String textSearch,
@RequestParam(required = false) String sortProperty,
@RequestParam(required = false) String sortOrder) throws ThingsboardException {
checkParameter("deviceProfileId", strDeviceProfileId);
checkParameter("type", strType);
try {
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
return checkNotNull(otaPackageService.findTenantOtaPackagesByTenantIdAndDeviceProfileIdAndTypeAndHasData(getTenantId(),
new DeviceProfileId(toUUID(strDeviceProfileId)), OtaPackageType.valueOf(strType), hasData, pageLink));
} catch (Exception e) {
throw handleException(e);
}
}
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/otaPackage/{otaPackageId}", method = RequestMethod.DELETE)
@ResponseBody
public void deleteOtaPackage(@PathVariable("otaPackageId") String strOtaPackageId) throws ThingsboardException {
checkParameter(OTA_PACKAGE_ID, strOtaPackageId);
try {
OtaPackageId otaPackageId = new OtaPackageId(toUUID(strOtaPackageId));
OtaPackageInfo info = checkOtaPackageInfoId(otaPackageId, Operation.DELETE);
otaPackageService.deleteOtaPackage(getTenantId(), otaPackageId);
logEntityAction(otaPackageId, info, null, ActionType.DELETED, null, strOtaPackageId);
} catch (Exception e) {
logEntityAction(emptyId(EntityType.OTA_PACKAGE), null, null, ActionType.DELETED, e, strOtaPackageId);
throw handleException(e);
}
}
}

136
application/src/main/java/org/thingsboard/server/service/firmware/DefaultFirmwareStateService.java → application/src/main/java/org/thingsboard/server/service/ota/DefaultOtaPackageStateService.java

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.service.firmware;
package org.thingsboard.server.service.ota;
import com.google.common.util.concurrent.FutureCallback;
import lombok.extern.slf4j.Slf4j;
@ -23,12 +23,9 @@ import org.thingsboard.rule.engine.api.msg.DeviceAttributesEventNotificationMsg;
import org.thingsboard.server.common.data.DataConstants;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.FirmwareInfo;
import org.thingsboard.server.common.data.firmware.FirmwareType;
import org.thingsboard.server.common.data.firmware.FirmwareUpdateStatus;
import org.thingsboard.server.common.data.firmware.FirmwareUtil;
import org.thingsboard.server.common.data.OtaPackageInfo;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.FirmwareId;
import org.thingsboard.server.common.data.id.OtaPackageId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.kv.AttributeKey;
import org.thingsboard.server.common.data.kv.AttributeKvEntry;
@ -37,13 +34,16 @@ import org.thingsboard.server.common.data.kv.BasicTsKvEntry;
import org.thingsboard.server.common.data.kv.LongDataEntry;
import org.thingsboard.server.common.data.kv.StringDataEntry;
import org.thingsboard.server.common.data.kv.TsKvEntry;
import org.thingsboard.server.common.data.ota.OtaPackageType;
import org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus;
import org.thingsboard.server.common.data.ota.OtaPackageUtil;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.msg.queue.TopicPartitionInfo;
import org.thingsboard.server.dao.device.DeviceProfileService;
import org.thingsboard.server.dao.device.DeviceService;
import org.thingsboard.server.dao.firmware.FirmwareService;
import org.thingsboard.server.gen.transport.TransportProtos.ToFirmwareStateServiceMsg;
import org.thingsboard.server.dao.ota.OtaPackageService;
import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg;
import org.thingsboard.server.queue.TbQueueProducer;
import org.thingsboard.server.queue.common.TbProtoQueueMsg;
import org.thingsboard.server.queue.provider.TbCoreQueueFactory;
@ -58,44 +58,43 @@ import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.function.Consumer;
import java.util.function.Function;
import static org.thingsboard.server.common.data.firmware.FirmwareKey.CHECKSUM;
import static org.thingsboard.server.common.data.firmware.FirmwareKey.CHECKSUM_ALGORITHM;
import static org.thingsboard.server.common.data.firmware.FirmwareKey.SIZE;
import static org.thingsboard.server.common.data.firmware.FirmwareKey.STATE;
import static org.thingsboard.server.common.data.firmware.FirmwareKey.TITLE;
import static org.thingsboard.server.common.data.firmware.FirmwareKey.TS;
import static org.thingsboard.server.common.data.firmware.FirmwareKey.VERSION;
import static org.thingsboard.server.common.data.firmware.FirmwareType.FIRMWARE;
import static org.thingsboard.server.common.data.firmware.FirmwareType.SOFTWARE;
import static org.thingsboard.server.common.data.firmware.FirmwareUtil.getAttributeKey;
import static org.thingsboard.server.common.data.firmware.FirmwareUtil.getTargetTelemetryKey;
import static org.thingsboard.server.common.data.firmware.FirmwareUtil.getTelemetryKey;
import static org.thingsboard.server.common.data.ota.OtaPackageKey.CHECKSUM;
import static org.thingsboard.server.common.data.ota.OtaPackageKey.CHECKSUM_ALGORITHM;
import static org.thingsboard.server.common.data.ota.OtaPackageKey.SIZE;
import static org.thingsboard.server.common.data.ota.OtaPackageKey.STATE;
import static org.thingsboard.server.common.data.ota.OtaPackageKey.TITLE;
import static org.thingsboard.server.common.data.ota.OtaPackageKey.TS;
import static org.thingsboard.server.common.data.ota.OtaPackageKey.VERSION;
import static org.thingsboard.server.common.data.ota.OtaPackageType.FIRMWARE;
import static org.thingsboard.server.common.data.ota.OtaPackageType.SOFTWARE;
import static org.thingsboard.server.common.data.ota.OtaPackageUtil.getAttributeKey;
import static org.thingsboard.server.common.data.ota.OtaPackageUtil.getTargetTelemetryKey;
import static org.thingsboard.server.common.data.ota.OtaPackageUtil.getTelemetryKey;
@Slf4j
@Service
@TbCoreComponent
public class DefaultFirmwareStateService implements FirmwareStateService {
public class DefaultOtaPackageStateService implements OtaPackageStateService {
private final TbClusterService tbClusterService;
private final FirmwareService firmwareService;
private final OtaPackageService otaPackageService;
private final DeviceService deviceService;
private final DeviceProfileService deviceProfileService;
private final RuleEngineTelemetryService telemetryService;
private final TbQueueProducer<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> fwStateMsgProducer;
private final TbQueueProducer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> otaPackageStateMsgProducer;
public DefaultFirmwareStateService(TbClusterService tbClusterService, FirmwareService firmwareService,
DeviceService deviceService,
DeviceProfileService deviceProfileService,
RuleEngineTelemetryService telemetryService,
TbCoreQueueFactory coreQueueFactory) {
public DefaultOtaPackageStateService(TbClusterService tbClusterService, OtaPackageService otaPackageService,
DeviceService deviceService,
DeviceProfileService deviceProfileService,
RuleEngineTelemetryService telemetryService,
TbCoreQueueFactory coreQueueFactory) {
this.tbClusterService = tbClusterService;
this.firmwareService = firmwareService;
this.otaPackageService = otaPackageService;
this.deviceService = deviceService;
this.deviceProfileService = deviceProfileService;
this.telemetryService = telemetryService;
this.fwStateMsgProducer = coreQueueFactory.createToFirmwareStateServiceMsgProducer();
this.otaPackageStateMsgProducer = coreQueueFactory.createToOtaPackageStateServiceMsgProducer();
}
@Override
@ -105,14 +104,14 @@ public class DefaultFirmwareStateService implements FirmwareStateService {
}
private void updateFirmware(Device device, Device oldDevice) {
FirmwareId newFirmwareId = device.getFirmwareId();
OtaPackageId newFirmwareId = device.getFirmwareId();
if (newFirmwareId == null) {
DeviceProfile newDeviceProfile = deviceProfileService.findDeviceProfileById(device.getTenantId(), device.getDeviceProfileId());
newFirmwareId = newDeviceProfile.getFirmwareId();
}
if (oldDevice != null) {
if (newFirmwareId != null) {
FirmwareId oldFirmwareId = oldDevice.getFirmwareId();
OtaPackageId oldFirmwareId = oldDevice.getFirmwareId();
if (oldFirmwareId == null) {
DeviceProfile oldDeviceProfile = deviceProfileService.findDeviceProfileById(oldDevice.getTenantId(), oldDevice.getDeviceProfileId());
oldFirmwareId = oldDeviceProfile.getFirmwareId();
@ -132,14 +131,14 @@ public class DefaultFirmwareStateService implements FirmwareStateService {
}
private void updateSoftware(Device device, Device oldDevice) {
FirmwareId newSoftwareId = device.getSoftwareId();
OtaPackageId newSoftwareId = device.getSoftwareId();
if (newSoftwareId == null) {
DeviceProfile newDeviceProfile = deviceProfileService.findDeviceProfileById(device.getTenantId(), device.getDeviceProfileId());
newSoftwareId = newDeviceProfile.getSoftwareId();
}
if (oldDevice != null) {
if (newSoftwareId != null) {
FirmwareId oldSoftwareId = oldDevice.getSoftwareId();
OtaPackageId oldSoftwareId = oldDevice.getSoftwareId();
if (oldSoftwareId == null) {
DeviceProfile oldDeviceProfile = deviceProfileService.findDeviceProfileById(oldDevice.getTenantId(), oldDevice.getDeviceProfileId());
oldSoftwareId = oldDeviceProfile.getSoftwareId();
@ -170,33 +169,20 @@ public class DefaultFirmwareStateService implements FirmwareStateService {
}
}
private void update(TenantId tenantId, DeviceProfile deviceProfile, FirmwareType firmwareType) {
Function<PageLink, PageData<Device>> getDevicesFunction;
private void update(TenantId tenantId, DeviceProfile deviceProfile, OtaPackageType otaPackageType) {
Consumer<Device> updateConsumer;
switch (firmwareType) {
case FIRMWARE:
getDevicesFunction = pl -> deviceService.findDevicesByTenantIdAndTypeAndEmptyFirmware(tenantId, deviceProfile.getName(), pl);
break;
case SOFTWARE:
getDevicesFunction = pl -> deviceService.findDevicesByTenantIdAndTypeAndEmptySoftware(tenantId, deviceProfile.getName(), pl);
break;
default:
log.warn("Unsupported firmware type: [{}]", firmwareType);
return;
}
if (deviceProfile.getFirmwareId() != null) {
long ts = System.currentTimeMillis();
updateConsumer = d -> send(d.getTenantId(), d.getId(), deviceProfile.getFirmwareId(), ts, firmwareType);
updateConsumer = d -> send(d.getTenantId(), d.getId(), deviceProfile.getFirmwareId(), ts, otaPackageType);
} else {
updateConsumer = d -> remove(d, firmwareType);
updateConsumer = d -> remove(d, otaPackageType);
}
PageLink pageLink = new PageLink(100);
PageData<Device> pageData;
do {
pageData = getDevicesFunction.apply(pageLink);
pageData = deviceService.findDevicesByTenantIdAndTypeAndEmptyOtaPackage(tenantId, deviceProfile.getId(), otaPackageType, pageLink);
pageData.getData().forEach(updateConsumer);
if (pageData.hasNext()) {
@ -206,60 +192,60 @@ public class DefaultFirmwareStateService implements FirmwareStateService {
}
@Override
public boolean process(ToFirmwareStateServiceMsg msg) {
public boolean process(ToOtaPackageStateServiceMsg msg) {
boolean isSuccess = false;
FirmwareId targetFirmwareId = new FirmwareId(new UUID(msg.getFirmwareIdMSB(), msg.getFirmwareIdLSB()));
OtaPackageId targetOtaPackageId = new OtaPackageId(new UUID(msg.getOtaPackageIdMSB(), msg.getOtaPackageIdLSB()));
DeviceId deviceId = new DeviceId(new UUID(msg.getDeviceIdMSB(), msg.getDeviceIdLSB()));
TenantId tenantId = new TenantId(new UUID(msg.getTenantIdMSB(), msg.getTenantIdLSB()));
FirmwareType firmwareType = FirmwareType.valueOf(msg.getType());
OtaPackageType firmwareType = OtaPackageType.valueOf(msg.getType());
long ts = msg.getTs();
Device device = deviceService.findDeviceById(tenantId, deviceId);
if (device == null) {
log.warn("[{}] [{}] Device was removed during firmware update msg was queued!", tenantId, deviceId);
} else {
FirmwareId currentFirmwareId = FirmwareUtil.getFirmwareId(device, firmwareType);
if (currentFirmwareId == null) {
OtaPackageId currentOtaPackageId = OtaPackageUtil.getOtaPackageId(device, firmwareType);
if (currentOtaPackageId == null) {
DeviceProfile deviceProfile = deviceProfileService.findDeviceProfileById(tenantId, device.getDeviceProfileId());
currentFirmwareId = FirmwareUtil.getFirmwareId(deviceProfile, firmwareType);
currentOtaPackageId = OtaPackageUtil.getOtaPackageId(deviceProfile, firmwareType);
}
if (targetFirmwareId.equals(currentFirmwareId)) {
update(device, firmwareService.findFirmwareInfoById(device.getTenantId(), targetFirmwareId), ts);
if (targetOtaPackageId.equals(currentOtaPackageId)) {
update(device, otaPackageService.findOtaPackageInfoById(device.getTenantId(), targetOtaPackageId), ts);
isSuccess = true;
} else {
log.warn("[{}] [{}] Can`t update firmware for the device, target firmwareId: [{}], current firmwareId: [{}]!", tenantId, deviceId, targetFirmwareId, currentFirmwareId);
log.warn("[{}] [{}] Can`t update firmware for the device, target firmwareId: [{}], current firmwareId: [{}]!", tenantId, deviceId, targetOtaPackageId, currentOtaPackageId);
}
}
return isSuccess;
}
private void send(TenantId tenantId, DeviceId deviceId, FirmwareId firmwareId, long ts, FirmwareType firmwareType) {
ToFirmwareStateServiceMsg msg = ToFirmwareStateServiceMsg.newBuilder()
private void send(TenantId tenantId, DeviceId deviceId, OtaPackageId firmwareId, long ts, OtaPackageType firmwareType) {
ToOtaPackageStateServiceMsg msg = ToOtaPackageStateServiceMsg.newBuilder()
.setTenantIdMSB(tenantId.getId().getMostSignificantBits())
.setTenantIdLSB(tenantId.getId().getLeastSignificantBits())
.setDeviceIdMSB(deviceId.getId().getMostSignificantBits())
.setDeviceIdLSB(deviceId.getId().getLeastSignificantBits())
.setFirmwareIdMSB(firmwareId.getId().getMostSignificantBits())
.setFirmwareIdLSB(firmwareId.getId().getLeastSignificantBits())
.setOtaPackageIdMSB(firmwareId.getId().getMostSignificantBits())
.setOtaPackageIdLSB(firmwareId.getId().getLeastSignificantBits())
.setType(firmwareType.name())
.setTs(ts)
.build();
FirmwareInfo firmware = firmwareService.findFirmwareInfoById(tenantId, firmwareId);
OtaPackageInfo firmware = otaPackageService.findOtaPackageInfoById(tenantId, firmwareId);
if (firmware == null) {
log.warn("[{}] Failed to send firmware update because firmware was already deleted", firmwareId);
return;
}
TopicPartitionInfo tpi = new TopicPartitionInfo(fwStateMsgProducer.getDefaultTopic(), null, null, false);
fwStateMsgProducer.send(tpi, new TbProtoQueueMsg<>(UUID.randomUUID(), msg), null);
TopicPartitionInfo tpi = new TopicPartitionInfo(otaPackageStateMsgProducer.getDefaultTopic(), null, null, false);
otaPackageStateMsgProducer.send(tpi, new TbProtoQueueMsg<>(UUID.randomUUID(), msg), null);
List<TsKvEntry> telemetry = new ArrayList<>();
telemetry.add(new BasicTsKvEntry(ts, new StringDataEntry(getTargetTelemetryKey(firmware.getType(), TITLE), firmware.getTitle())));
telemetry.add(new BasicTsKvEntry(ts, new StringDataEntry(getTargetTelemetryKey(firmware.getType(), VERSION), firmware.getVersion())));
telemetry.add(new BasicTsKvEntry(ts, new LongDataEntry(getTargetTelemetryKey(firmware.getType(), TS), ts)));
telemetry.add(new BasicTsKvEntry(ts, new StringDataEntry(getTelemetryKey(firmware.getType(), STATE), FirmwareUpdateStatus.QUEUED.name())));
telemetry.add(new BasicTsKvEntry(ts, new StringDataEntry(getTelemetryKey(firmware.getType(), STATE), OtaPackageUpdateStatus.QUEUED.name())));
telemetryService.saveAndNotify(tenantId, deviceId, telemetry, new FutureCallback<>() {
@Override
@ -275,11 +261,11 @@ public class DefaultFirmwareStateService implements FirmwareStateService {
}
private void update(Device device, FirmwareInfo firmware, long ts) {
private void update(Device device, OtaPackageInfo firmware, long ts) {
TenantId tenantId = device.getTenantId();
DeviceId deviceId = device.getId();
BasicTsKvEntry status = new BasicTsKvEntry(System.currentTimeMillis(), new StringDataEntry(getTelemetryKey(firmware.getType(), STATE), FirmwareUpdateStatus.INITIATED.name()));
BasicTsKvEntry status = new BasicTsKvEntry(System.currentTimeMillis(), new StringDataEntry(getTelemetryKey(firmware.getType(), STATE), OtaPackageUpdateStatus.INITIATED.name()));
telemetryService.saveAndNotify(tenantId, deviceId, Collections.singletonList(status), new FutureCallback<>() {
@Override
@ -313,14 +299,14 @@ public class DefaultFirmwareStateService implements FirmwareStateService {
});
}
private void remove(Device device, FirmwareType firmwareType) {
telemetryService.deleteAndNotify(device.getTenantId(), device.getId(), DataConstants.SHARED_SCOPE, FirmwareUtil.getAttributeKeys(firmwareType),
private void remove(Device device, OtaPackageType firmwareType) {
telemetryService.deleteAndNotify(device.getTenantId(), device.getId(), DataConstants.SHARED_SCOPE, OtaPackageUtil.getAttributeKeys(firmwareType),
new FutureCallback<>() {
@Override
public void onSuccess(@Nullable Void tmp) {
log.trace("[{}] Success remove target firmware attributes!", device.getId());
Set<AttributeKey> keysToNotify = new HashSet<>();
FirmwareUtil.ALL_FW_ATTRIBUTE_KEYS.forEach(key -> keysToNotify.add(new AttributeKey(DataConstants.SHARED_SCOPE, key)));
OtaPackageUtil.ALL_FW_ATTRIBUTE_KEYS.forEach(key -> keysToNotify.add(new AttributeKey(DataConstants.SHARED_SCOPE, key)));
tbClusterService.pushMsgToCore(DeviceAttributesEventNotificationMsg.onDelete(device.getTenantId(), device.getId(), keysToNotify), null);
}

8
application/src/main/java/org/thingsboard/server/service/firmware/FirmwareStateService.java → application/src/main/java/org/thingsboard/server/service/ota/OtaPackageStateService.java

@ -13,18 +13,18 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.service.firmware;
package org.thingsboard.server.service.ota;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.gen.transport.TransportProtos.ToFirmwareStateServiceMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg;
public interface FirmwareStateService {
public interface OtaPackageStateService {
void update(Device device, Device oldDevice);
void update(DeviceProfile deviceProfile, boolean isFirmwareChanged, boolean isSoftwareChanged);
boolean process(ToFirmwareStateServiceMsg msg);
boolean process(ToOtaPackageStateServiceMsg msg);
}

31
application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerService.java

@ -50,7 +50,7 @@ import org.thingsboard.server.gen.transport.TransportProtos.TbSubscriptionCloseP
import org.thingsboard.server.gen.transport.TransportProtos.TbTimeSeriesUpdateProto;
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToFirmwareStateServiceMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToUsageStatsServiceMsg;
import org.thingsboard.server.gen.transport.TransportProtos.TransportToDeviceActorMsg;
import org.thingsboard.server.queue.TbQueueConsumer;
@ -60,7 +60,7 @@ import org.thingsboard.server.queue.provider.TbCoreQueueFactory;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.apiusage.TbApiUsageStateService;
import org.thingsboard.server.service.edge.EdgeNotificationService;
import org.thingsboard.server.service.firmware.FirmwareStateService;
import org.thingsboard.server.service.ota.OtaPackageStateService;
import org.thingsboard.server.service.profile.TbDeviceProfileCache;
import org.thingsboard.server.service.queue.processing.AbstractConsumerService;
import org.thingsboard.server.service.queue.processing.IdMsgPair;
@ -75,7 +75,6 @@ import org.thingsboard.server.service.transport.msg.TransportToDeviceActorMsgWra
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
@ -101,9 +100,9 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService<ToCore
@Value("${queue.core.stats.enabled:false}")
private boolean statsEnabled;
@Value("${queue.core.firmware.pack-interval-ms:60000}")
@Value("${queue.core.ota.pack-interval-ms:60000}")
private long firmwarePackInterval;
@Value("${queue.core.firmware.pack-size:100}")
@Value("${queue.core.ota.pack-size:100}")
private int firmwarePackSize;
private final TbQueueConsumer<TbProtoQueueMsg<ToCoreMsg>> mainConsumer;
@ -113,10 +112,10 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService<ToCore
private final SubscriptionManagerService subscriptionManagerService;
private final TbCoreDeviceRpcService tbCoreDeviceRpcService;
private final EdgeNotificationService edgeNotificationService;
private final FirmwareStateService firmwareStateService;
private final OtaPackageStateService firmwareStateService;
private final TbCoreConsumerStats stats;
protected final TbQueueConsumer<TbProtoQueueMsg<ToUsageStatsServiceMsg>> usageStatsConsumer;
private final TbQueueConsumer<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> firmwareStatesConsumer;
private final TbQueueConsumer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> firmwareStatesConsumer;
protected volatile ExecutorService usageStatsExecutor;
@ -135,11 +134,11 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService<ToCore
TbTenantProfileCache tenantProfileCache,
TbApiUsageStateService apiUsageStateService,
EdgeNotificationService edgeNotificationService,
FirmwareStateService firmwareStateService) {
OtaPackageStateService firmwareStateService) {
super(actorContext, encodingService, tenantProfileCache, deviceProfileCache, apiUsageStateService, tbCoreQueueFactory.createToCoreNotificationsMsgConsumer());
this.mainConsumer = tbCoreQueueFactory.createToCoreMsgConsumer();
this.usageStatsConsumer = tbCoreQueueFactory.createToUsageStatsServiceMsgConsumer();
this.firmwareStatesConsumer = tbCoreQueueFactory.createToFirmwareStateServiceMsgConsumer();
this.firmwareStatesConsumer = tbCoreQueueFactory.createToOtaPackageStateServiceMsgConsumer();
this.stateService = stateService;
this.localSubscriptionService = localSubscriptionService;
this.subscriptionManagerService = subscriptionManagerService;
@ -173,7 +172,7 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService<ToCore
public void onApplicationEvent(ApplicationReadyEvent event) {
super.onApplicationEvent(event);
launchUsageStatsConsumer();
launchFirmwareUpdateNotificationConsumer();
launchOtaPackageUpdateNotificationConsumer();
}
@Override
@ -361,20 +360,20 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService<ToCore
});
}
private void launchFirmwareUpdateNotificationConsumer() {
private void launchOtaPackageUpdateNotificationConsumer() {
long maxProcessingTimeoutPerRecord = firmwarePackInterval / firmwarePackSize;
firmwareStatesExecutor.submit(() -> {
while (!stopped) {
try {
List<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> msgs = firmwareStatesConsumer.poll(getNotificationPollDuration());
List<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> msgs = firmwareStatesConsumer.poll(getNotificationPollDuration());
if (msgs.isEmpty()) {
continue;
}
long timeToSleep = maxProcessingTimeoutPerRecord;
for (TbProtoQueueMsg<ToFirmwareStateServiceMsg> msg : msgs) {
for (TbProtoQueueMsg<ToOtaPackageStateServiceMsg> msg : msgs) {
try {
long startTime = System.currentTimeMillis();
boolean isSuccessUpdate = handleFirmwareUpdates(msg);
boolean isSuccessUpdate = handleOtaPackageUpdates(msg);
long endTime = System.currentTimeMillis();
long spentTime = endTime - startTime;
timeToSleep = timeToSleep - spentTime;
@ -402,7 +401,7 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService<ToCore
}
}
}
log.info("TB Firmware States Consumer stopped.");
log.info("TB Ota Package States Consumer stopped.");
});
}
@ -410,7 +409,7 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService<ToCore
statsService.process(msg, callback);
}
private boolean handleFirmwareUpdates(TbProtoQueueMsg<ToFirmwareStateServiceMsg> msg) {
private boolean handleOtaPackageUpdates(TbProtoQueueMsg<ToOtaPackageStateServiceMsg> msg) {
return firmwareStateService.process(msg.getValue());
}

24
application/src/main/java/org/thingsboard/server/service/security/AccessValidator.java

@ -30,7 +30,7 @@ import org.thingsboard.server.common.data.Customer;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.EntityView;
import org.thingsboard.server.common.data.FirmwareInfo;
import org.thingsboard.server.common.data.OtaPackageInfo;
import org.thingsboard.server.common.data.TbResourceInfo;
import org.thingsboard.server.common.data.Tenant;
import org.thingsboard.server.common.data.User;
@ -46,7 +46,7 @@ import org.thingsboard.server.common.data.id.EdgeId;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.EntityIdFactory;
import org.thingsboard.server.common.data.id.EntityViewId;
import org.thingsboard.server.common.data.id.FirmwareId;
import org.thingsboard.server.common.data.id.OtaPackageId;
import org.thingsboard.server.common.data.id.RuleChainId;
import org.thingsboard.server.common.data.id.RuleNodeId;
import org.thingsboard.server.common.data.id.TbResourceId;
@ -63,7 +63,7 @@ import org.thingsboard.server.dao.device.DeviceService;
import org.thingsboard.server.dao.edge.EdgeService;
import org.thingsboard.server.dao.entityview.EntityViewService;
import org.thingsboard.server.dao.exception.IncorrectParameterException;
import org.thingsboard.server.dao.firmware.FirmwareService;
import org.thingsboard.server.dao.ota.OtaPackageService;
import org.thingsboard.server.dao.resource.ResourceService;
import org.thingsboard.server.dao.rule.RuleChainService;
import org.thingsboard.server.dao.tenant.TenantService;
@ -135,7 +135,7 @@ public class AccessValidator {
protected ResourceService resourceService;
@Autowired
protected FirmwareService firmwareService;
protected OtaPackageService otaPackageService;
private ExecutorService executor;
@ -232,8 +232,8 @@ public class AccessValidator {
case TB_RESOURCE:
validateResource(currentUser, operation, entityId, callback);
return;
case FIRMWARE:
validateFirmware(currentUser, operation, entityId, callback);
case OTA_PACKAGE:
validateOtaPackage(currentUser, operation, entityId, callback);
return;
default:
//TODO: add support of other entities
@ -300,20 +300,20 @@ public class AccessValidator {
}
}
private void validateFirmware(final SecurityUser currentUser, Operation operation, EntityId entityId, FutureCallback<ValidationResult> callback) {
private void validateOtaPackage(final SecurityUser currentUser, Operation operation, EntityId entityId, FutureCallback<ValidationResult> callback) {
if (currentUser.isSystemAdmin()) {
callback.onSuccess(ValidationResult.accessDenied(SYSTEM_ADMINISTRATOR_IS_NOT_ALLOWED_TO_PERFORM_THIS_OPERATION));
} else {
FirmwareInfo firmware = firmwareService.findFirmwareInfoById(currentUser.getTenantId(), new FirmwareId(entityId.getId()));
if (firmware == null) {
callback.onSuccess(ValidationResult.entityNotFound("Firmware with requested id wasn't found!"));
OtaPackageInfo otaPackage = otaPackageService.findOtaPackageInfoById(currentUser.getTenantId(), new OtaPackageId(entityId.getId()));
if (otaPackage == null) {
callback.onSuccess(ValidationResult.entityNotFound("OtaPackage with requested id wasn't found!"));
} else {
try {
accessControlService.checkPermission(currentUser, Resource.FIRMWARE, operation, entityId, firmware);
accessControlService.checkPermission(currentUser, Resource.OTA_PACKAGE, operation, entityId, otaPackage);
} catch (ThingsboardException e) {
callback.onSuccess(ValidationResult.accessDenied(e.getMessage()));
}
callback.onSuccess(ValidationResult.ok(firmware));
callback.onSuccess(ValidationResult.ok(otaPackage));
}
}
}

2
application/src/main/java/org/thingsboard/server/service/security/permission/Resource.java

@ -38,7 +38,7 @@ public enum Resource {
DEVICE_PROFILE(EntityType.DEVICE_PROFILE),
API_USAGE_STATE(EntityType.API_USAGE_STATE),
TB_RESOURCE(EntityType.TB_RESOURCE),
FIRMWARE(EntityType.FIRMWARE),
OTA_PACKAGE(EntityType.OTA_PACKAGE),
EDGE(EntityType.EDGE);
private final EntityType entityType;

2
application/src/main/java/org/thingsboard/server/service/security/permission/TenantAdminPermissions.java

@ -42,7 +42,7 @@ public class TenantAdminPermissions extends AbstractPermissions {
put(Resource.DEVICE_PROFILE, tenantEntityPermissionChecker);
put(Resource.API_USAGE_STATE, tenantEntityPermissionChecker);
put(Resource.TB_RESOURCE, tbResourcePermissionChecker);
put(Resource.FIRMWARE, tenantEntityPermissionChecker);
put(Resource.OTA_PACKAGE, tenantEntityPermissionChecker);
put(Resource.EDGE, tenantEntityPermissionChecker);
}

68
application/src/main/java/org/thingsboard/server/service/transport/DefaultTransportApiService.java

@ -26,27 +26,27 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.cache.firmware.FirmwareDataCache;
import org.thingsboard.server.cache.ota.OtaPackageDataCache;
import org.thingsboard.server.common.data.ApiUsageState;
import org.thingsboard.server.common.data.DataConstants;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.DeviceTransportType;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.Firmware;
import org.thingsboard.server.common.data.FirmwareInfo;
import org.thingsboard.server.common.data.OtaPackage;
import org.thingsboard.server.common.data.OtaPackageInfo;
import org.thingsboard.server.common.data.ResourceType;
import org.thingsboard.server.common.data.TbResource;
import org.thingsboard.server.common.data.TenantProfile;
import org.thingsboard.server.common.data.device.credentials.BasicMqttCredentials;
import org.thingsboard.server.common.data.device.credentials.ProvisionDeviceCredentialsData;
import org.thingsboard.server.common.data.device.profile.ProvisionDeviceProfileCredentials;
import org.thingsboard.server.common.data.firmware.FirmwareType;
import org.thingsboard.server.common.data.firmware.FirmwareUtil;
import org.thingsboard.server.common.data.ota.OtaPackageType;
import org.thingsboard.server.common.data.ota.OtaPackageUtil;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.data.id.FirmwareId;
import org.thingsboard.server.common.data.id.OtaPackageId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
@ -64,7 +64,7 @@ import org.thingsboard.server.dao.device.DeviceService;
import org.thingsboard.server.dao.device.provision.ProvisionFailedException;
import org.thingsboard.server.dao.device.provision.ProvisionRequest;
import org.thingsboard.server.dao.device.provision.ProvisionResponse;
import org.thingsboard.server.dao.firmware.FirmwareService;
import org.thingsboard.server.dao.ota.OtaPackageService;
import org.thingsboard.server.dao.relation.RelationService;
import org.thingsboard.server.dao.tenant.TbTenantProfileCache;
import org.thingsboard.server.gen.transport.TransportProtos;
@ -124,8 +124,8 @@ public class DefaultTransportApiService implements TransportApiService {
private final DataDecodingEncodingService dataDecodingEncodingService;
private final DeviceProvisionService deviceProvisionService;
private final TbResourceService resourceService;
private final FirmwareService firmwareService;
private final FirmwareDataCache firmwareDataCache;
private final OtaPackageService otaPackageService;
private final OtaPackageDataCache otaPackageDataCache;
private final ConcurrentMap<String, ReentrantLock> deviceCreationLocks = new ConcurrentHashMap<>();
@ -134,7 +134,7 @@ public class DefaultTransportApiService implements TransportApiService {
RelationService relationService, DeviceCredentialsService deviceCredentialsService,
DeviceStateService deviceStateService, DbCallbackExecutorService dbCallbackExecutorService,
TbClusterService tbClusterService, DataDecodingEncodingService dataDecodingEncodingService,
DeviceProvisionService deviceProvisionService, TbResourceService resourceService, FirmwareService firmwareService, FirmwareDataCache firmwareDataCache) {
DeviceProvisionService deviceProvisionService, TbResourceService resourceService, OtaPackageService otaPackageService, OtaPackageDataCache otaPackageDataCache) {
this.deviceProfileCache = deviceProfileCache;
this.tenantProfileCache = tenantProfileCache;
this.apiUsageStateService = apiUsageStateService;
@ -147,8 +147,8 @@ public class DefaultTransportApiService implements TransportApiService {
this.dataDecodingEncodingService = dataDecodingEncodingService;
this.deviceProvisionService = deviceProvisionService;
this.resourceService = resourceService;
this.firmwareService = firmwareService;
this.firmwareDataCache = firmwareDataCache;
this.otaPackageService = otaPackageService;
this.otaPackageDataCache = otaPackageDataCache;
}
@Override
@ -184,8 +184,8 @@ public class DefaultTransportApiService implements TransportApiService {
result = handle(transportApiRequestMsg.getDeviceRequestMsg());
} else if (transportApiRequestMsg.hasDeviceCredentialsRequestMsg()) {
result = handle(transportApiRequestMsg.getDeviceCredentialsRequestMsg());
} else if (transportApiRequestMsg.hasFirmwareRequestMsg()) {
result = handle(transportApiRequestMsg.getFirmwareRequestMsg());
} else if (transportApiRequestMsg.hasOtaPackageRequestMsg()) {
result = handle(transportApiRequestMsg.getOtaPackageRequestMsg());
}
return Futures.transform(Optional.ofNullable(result).orElseGet(this::getEmptyTransportApiResponseFuture),
@ -511,50 +511,50 @@ public class DefaultTransportApiService implements TransportApiService {
}
}
private ListenableFuture<TransportApiResponseMsg> handle(TransportProtos.GetFirmwareRequestMsg requestMsg) {
private ListenableFuture<TransportApiResponseMsg> handle(TransportProtos.GetOtaPackageRequestMsg requestMsg) {
TenantId tenantId = new TenantId(new UUID(requestMsg.getTenantIdMSB(), requestMsg.getTenantIdLSB()));
DeviceId deviceId = new DeviceId(new UUID(requestMsg.getDeviceIdMSB(), requestMsg.getDeviceIdLSB()));
FirmwareType firmwareType = FirmwareType.valueOf(requestMsg.getType());
OtaPackageType otaPackageType = OtaPackageType.valueOf(requestMsg.getType());
Device device = deviceService.findDeviceById(tenantId, deviceId);
if (device == null) {
return getEmptyTransportApiResponseFuture();
}
FirmwareId firmwareId = FirmwareUtil.getFirmwareId(device, firmwareType);
if (firmwareId == null) {
OtaPackageId otaPackageId = OtaPackageUtil.getOtaPackageId(device, otaPackageType);
if (otaPackageId == null) {
DeviceProfile deviceProfile = deviceProfileCache.find(device.getDeviceProfileId());
firmwareId = FirmwareUtil.getFirmwareId(deviceProfile, firmwareType);
otaPackageId = OtaPackageUtil.getOtaPackageId(deviceProfile, otaPackageType);
}
TransportProtos.GetFirmwareResponseMsg.Builder builder = TransportProtos.GetFirmwareResponseMsg.newBuilder();
TransportProtos.GetOtaPackageResponseMsg.Builder builder = TransportProtos.GetOtaPackageResponseMsg.newBuilder();
if (firmwareId == null) {
if (otaPackageId == null) {
builder.setResponseStatus(TransportProtos.ResponseStatus.NOT_FOUND);
} else {
FirmwareInfo firmwareInfo = firmwareService.findFirmwareInfoById(tenantId, firmwareId);
OtaPackageInfo otaPackageInfo = otaPackageService.findOtaPackageInfoById(tenantId, otaPackageId);
if (firmwareInfo == null) {
if (otaPackageInfo == null) {
builder.setResponseStatus(TransportProtos.ResponseStatus.NOT_FOUND);
} else {
builder.setResponseStatus(TransportProtos.ResponseStatus.SUCCESS);
builder.setFirmwareIdMSB(firmwareId.getId().getMostSignificantBits());
builder.setFirmwareIdLSB(firmwareId.getId().getLeastSignificantBits());
builder.setType(firmwareInfo.getType().name());
builder.setTitle(firmwareInfo.getTitle());
builder.setVersion(firmwareInfo.getVersion());
builder.setFileName(firmwareInfo.getFileName());
builder.setContentType(firmwareInfo.getContentType());
if (!firmwareDataCache.has(firmwareId.toString())) {
Firmware firmware = firmwareService.findFirmwareById(tenantId, firmwareId);
firmwareDataCache.put(firmwareId.toString(), firmware.getData().array());
builder.setOtaPackageIdMSB(otaPackageId.getId().getMostSignificantBits());
builder.setOtaPackageIdLSB(otaPackageId.getId().getLeastSignificantBits());
builder.setType(otaPackageInfo.getType().name());
builder.setTitle(otaPackageInfo.getTitle());
builder.setVersion(otaPackageInfo.getVersion());
builder.setFileName(otaPackageInfo.getFileName());
builder.setContentType(otaPackageInfo.getContentType());
if (!otaPackageDataCache.has(otaPackageId.toString())) {
OtaPackage otaPackage = otaPackageService.findOtaPackageById(tenantId, otaPackageId);
otaPackageDataCache.put(otaPackageId.toString(), otaPackage.getData().array());
}
}
}
return Futures.immediateFuture(
TransportApiResponseMsg.newBuilder()
.setFirmwareResponseMsg(builder.build())
.setOtaPackageResponseMsg(builder.build())
.build());
}

19
application/src/main/resources/thingsboard.yml

@ -371,7 +371,10 @@ caffeine:
tokensOutdatageTime:
timeToLiveInMinutes: 20000
maxSize: 10000
firmwares:
otaPackages:
timeToLiveInMinutes: 60
maxSize: 10
otaPackagesData:
timeToLiveInMinutes: 60
maxSize: 10
edges:
@ -497,7 +500,7 @@ audit-log:
"device_profile": "${AUDIT_LOG_MASK_DEVICE_PROFILE:W}"
"edge": "${AUDIT_LOG_MASK_EDGE:W}"
"tb_resource": "${AUDIT_LOG_MASK_RESOURCE:W}"
"firmware": "${AUDIT_LOG_MASK_FIRMWARE:W}"
"ota_package": "${AUDIT_LOG_MASK_OTA_PACKAGE:W}"
sink:
# Type of external sink. possible options: none, elasticsearch
type: "${AUDIT_LOG_SINK_TYPE:none}"
@ -749,7 +752,7 @@ queue:
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\";}"
security.protocol: "${TB_QUEUE_KAFKA_CONFLUENT_SECURITY_PROTOCOL:SASL_SSL}"
consumer-properties-per-topic:
tb_firmware:
tb_ota_package:
- key: max.poll.records
value: 10
other:
@ -759,7 +762,7 @@ queue:
transport-api: "${TB_QUEUE_KAFKA_TA_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:1048576000;partitions:1;min.insync.replicas:1}"
notifications: "${TB_QUEUE_KAFKA_NOTIFICATIONS_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:1048576000;partitions:1;min.insync.replicas:1}"
js-executor: "${TB_QUEUE_KAFKA_JE_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:104857600;partitions:100;min.insync.replicas:1}"
fw-updates: "${TB_QUEUE_KAFKA_FW_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:1048576000;partitions:10;min.insync.replicas:1}"
ota-updates: "${TB_QUEUE_KAFKA_OTA_TOPIC_PROPERTIES:retention.ms:604800000;segment.bytes:26214400;retention.bytes:1048576000;partitions:10;min.insync.replicas:1}"
consumer-stats:
enabled: "${TB_QUEUE_KAFKA_CONSUMER_STATS_ENABLED:true}"
print-interval-ms: "${TB_QUEUE_KAFKA_CONSUMER_STATS_MIN_PRINT_INTERVAL_MS:60000}"
@ -830,10 +833,10 @@ queue:
poll-interval: "${TB_QUEUE_CORE_POLL_INTERVAL_MS:25}"
partitions: "${TB_QUEUE_CORE_PARTITIONS:10}"
pack-processing-timeout: "${TB_QUEUE_CORE_PACK_PROCESSING_TIMEOUT_MS:2000}"
firmware:
topic: "${TB_QUEUE_CORE_FW_TOPIC:tb_firmware}"
pack-interval-ms: "${TB_QUEUE_CORE_FW_PACK_INTERVAL_MS:60000}"
pack-size: "${TB_QUEUE_CORE_FW_PACK_SIZE:100}"
ota:
topic: "${TB_QUEUE_CORE_OTA_TOPIC:tb_ota_package}"
pack-interval-ms: "${TB_QUEUE_CORE_OTA_PACK_INTERVAL_MS:60000}"
pack-size: "${TB_QUEUE_CORE_OTA_PACK_SIZE:100}"
usage-stats-topic: "${TB_QUEUE_US_TOPIC:tb_usage_stats}"
stats:
enabled: "${TB_QUEUE_CORE_STATS_ENABLED:true}"

115
application/src/test/java/org/thingsboard/server/controller/BaseFirmwareControllerTest.java → application/src/test/java/org/thingsboard/server/controller/BaseOtaPackageControllerTest.java

@ -25,11 +25,10 @@ import org.springframework.test.web.servlet.request.MockMultipartHttpServletRequ
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.Firmware;
import org.thingsboard.server.common.data.FirmwareInfo;
import org.thingsboard.server.common.data.OtaPackage;
import org.thingsboard.server.common.data.OtaPackageInfo;
import org.thingsboard.server.common.data.Tenant;
import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.firmware.FirmwareType;
import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
@ -41,11 +40,11 @@ import java.util.Collections;
import java.util.List;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.thingsboard.server.common.data.firmware.FirmwareType.FIRMWARE;
import static org.thingsboard.server.common.data.ota.OtaPackageType.FIRMWARE;
public abstract class BaseFirmwareControllerTest extends AbstractControllerTest {
public abstract class BaseOtaPackageControllerTest extends AbstractControllerTest {
private IdComparator<FirmwareInfo> idComparator = new IdComparator<>();
private IdComparator<OtaPackageInfo> idComparator = new IdComparator<>();
public static final String TITLE = "My firmware";
private static final String FILE_NAME = "filename.txt";
@ -93,13 +92,13 @@ public abstract class BaseFirmwareControllerTest extends AbstractControllerTest
@Test
public void testSaveFirmware() throws Exception {
FirmwareInfo firmwareInfo = new FirmwareInfo();
OtaPackageInfo firmwareInfo = new OtaPackageInfo();
firmwareInfo.setDeviceProfileId(deviceProfileId);
firmwareInfo.setType(FIRMWARE);
firmwareInfo.setTitle(TITLE);
firmwareInfo.setVersion(VERSION);
FirmwareInfo savedFirmwareInfo = save(firmwareInfo);
OtaPackageInfo savedFirmwareInfo = save(firmwareInfo);
Assert.assertNotNull(savedFirmwareInfo);
Assert.assertNotNull(savedFirmwareInfo.getId());
@ -112,19 +111,19 @@ public abstract class BaseFirmwareControllerTest extends AbstractControllerTest
save(savedFirmwareInfo);
FirmwareInfo foundFirmwareInfo = doGet("/api/firmware/info/" + savedFirmwareInfo.getId().getId().toString(), FirmwareInfo.class);
OtaPackageInfo foundFirmwareInfo = doGet("/api/otaPackage/info/" + savedFirmwareInfo.getId().getId().toString(), OtaPackageInfo.class);
Assert.assertEquals(foundFirmwareInfo.getTitle(), savedFirmwareInfo.getTitle());
}
@Test
public void testSaveFirmwareData() throws Exception {
FirmwareInfo firmwareInfo = new FirmwareInfo();
OtaPackageInfo firmwareInfo = new OtaPackageInfo();
firmwareInfo.setDeviceProfileId(deviceProfileId);
firmwareInfo.setType(FIRMWARE);
firmwareInfo.setTitle(TITLE);
firmwareInfo.setVersion(VERSION);
FirmwareInfo savedFirmwareInfo = save(firmwareInfo);
OtaPackageInfo savedFirmwareInfo = save(firmwareInfo);
Assert.assertNotNull(savedFirmwareInfo);
Assert.assertNotNull(savedFirmwareInfo.getId());
@ -137,12 +136,12 @@ public abstract class BaseFirmwareControllerTest extends AbstractControllerTest
save(savedFirmwareInfo);
FirmwareInfo foundFirmwareInfo = doGet("/api/firmware/info/" + savedFirmwareInfo.getId().getId().toString(), FirmwareInfo.class);
OtaPackageInfo foundFirmwareInfo = doGet("/api/otaPackage/info/" + savedFirmwareInfo.getId().getId().toString(), OtaPackageInfo.class);
Assert.assertEquals(foundFirmwareInfo.getTitle(), savedFirmwareInfo.getTitle());
MockMultipartFile testData = new MockMultipartFile("file", FILE_NAME, CONTENT_TYPE, DATA.array());
Firmware savedFirmware = savaData("/api/firmware/" + savedFirmwareInfo.getId().getId().toString() + "?checksum={checksum}&checksumAlgorithm={checksumAlgorithm}", testData, CHECKSUM, CHECKSUM_ALGORITHM);
OtaPackage savedFirmware = savaData("/api/otaPackage/" + savedFirmwareInfo.getId().getId().toString() + "?checksum={checksum}&checksumAlgorithm={checksumAlgorithm}", testData, CHECKSUM, CHECKSUM_ALGORITHM);
Assert.assertEquals(FILE_NAME, savedFirmware.getFileName());
Assert.assertEquals(CONTENT_TYPE, savedFirmware.getContentType());
@ -150,97 +149,97 @@ public abstract class BaseFirmwareControllerTest extends AbstractControllerTest
@Test
public void testUpdateFirmwareFromDifferentTenant() throws Exception {
FirmwareInfo firmwareInfo = new FirmwareInfo();
OtaPackageInfo firmwareInfo = new OtaPackageInfo();
firmwareInfo.setDeviceProfileId(deviceProfileId);
firmwareInfo.setType(FIRMWARE);
firmwareInfo.setTitle(TITLE);
firmwareInfo.setVersion(VERSION);
FirmwareInfo savedFirmwareInfo = save(firmwareInfo);
OtaPackageInfo savedFirmwareInfo = save(firmwareInfo);
loginDifferentTenant();
doPost("/api/firmware", savedFirmwareInfo, FirmwareInfo.class, status().isForbidden());
doPost("/api/otaPackage", savedFirmwareInfo, OtaPackageInfo.class, status().isForbidden());
deleteDifferentTenant();
}
@Test
public void testFindFirmwareInfoById() throws Exception {
FirmwareInfo firmwareInfo = new FirmwareInfo();
OtaPackageInfo firmwareInfo = new OtaPackageInfo();
firmwareInfo.setDeviceProfileId(deviceProfileId);
firmwareInfo.setType(FIRMWARE);
firmwareInfo.setTitle(TITLE);
firmwareInfo.setVersion(VERSION);
FirmwareInfo savedFirmwareInfo = save(firmwareInfo);
OtaPackageInfo savedFirmwareInfo = save(firmwareInfo);
FirmwareInfo foundFirmware = doGet("/api/firmware/info/" + savedFirmwareInfo.getId().getId().toString(), FirmwareInfo.class);
OtaPackageInfo foundFirmware = doGet("/api/otaPackage/info/" + savedFirmwareInfo.getId().getId().toString(), OtaPackageInfo.class);
Assert.assertNotNull(foundFirmware);
Assert.assertEquals(savedFirmwareInfo, foundFirmware);
}
@Test
public void testFindFirmwareById() throws Exception {
FirmwareInfo firmwareInfo = new FirmwareInfo();
OtaPackageInfo firmwareInfo = new OtaPackageInfo();
firmwareInfo.setDeviceProfileId(deviceProfileId);
firmwareInfo.setType(FIRMWARE);
firmwareInfo.setTitle(TITLE);
firmwareInfo.setVersion(VERSION);
FirmwareInfo savedFirmwareInfo = save(firmwareInfo);
OtaPackageInfo savedFirmwareInfo = save(firmwareInfo);
MockMultipartFile testData = new MockMultipartFile("file", FILE_NAME, CONTENT_TYPE, DATA.array());
Firmware savedFirmware = savaData("/api/firmware/" + savedFirmwareInfo.getId().getId().toString() + "?checksum={checksum}&checksumAlgorithm={checksumAlgorithm}", testData, CHECKSUM, CHECKSUM_ALGORITHM);
OtaPackage savedFirmware = savaData("/api/otaPackage/" + savedFirmwareInfo.getId().getId().toString() + "?checksum={checksum}&checksumAlgorithm={checksumAlgorithm}", testData, CHECKSUM, CHECKSUM_ALGORITHM);
Firmware foundFirmware = doGet("/api/firmware/" + savedFirmwareInfo.getId().getId().toString(), Firmware.class);
OtaPackage foundFirmware = doGet("/api/otaPackage/" + savedFirmwareInfo.getId().getId().toString(), OtaPackage.class);
Assert.assertNotNull(foundFirmware);
Assert.assertEquals(savedFirmware, foundFirmware);
}
@Test
public void testDeleteFirmware() throws Exception {
FirmwareInfo firmwareInfo = new FirmwareInfo();
OtaPackageInfo firmwareInfo = new OtaPackageInfo();
firmwareInfo.setDeviceProfileId(deviceProfileId);
firmwareInfo.setType(FIRMWARE);
firmwareInfo.setTitle(TITLE);
firmwareInfo.setVersion(VERSION);
FirmwareInfo savedFirmwareInfo = save(firmwareInfo);
OtaPackageInfo savedFirmwareInfo = save(firmwareInfo);
doDelete("/api/firmware/" + savedFirmwareInfo.getId().getId().toString())
doDelete("/api/otaPackage/" + savedFirmwareInfo.getId().getId().toString())
.andExpect(status().isOk());
doGet("/api/firmware/info/" + savedFirmwareInfo.getId().getId().toString())
doGet("/api/otaPackage/info/" + savedFirmwareInfo.getId().getId().toString())
.andExpect(status().isNotFound());
}
@Test
public void testFindTenantFirmwares() throws Exception {
List<FirmwareInfo> firmwares = new ArrayList<>();
List<OtaPackageInfo> otaPackages = new ArrayList<>();
for (int i = 0; i < 165; i++) {
FirmwareInfo firmwareInfo = new FirmwareInfo();
OtaPackageInfo firmwareInfo = new OtaPackageInfo();
firmwareInfo.setDeviceProfileId(deviceProfileId);
firmwareInfo.setType(FIRMWARE);
firmwareInfo.setTitle(TITLE);
firmwareInfo.setVersion(VERSION + i);
FirmwareInfo savedFirmwareInfo = save(firmwareInfo);
OtaPackageInfo savedFirmwareInfo = save(firmwareInfo);
if (i > 100) {
MockMultipartFile testData = new MockMultipartFile("file", FILE_NAME, CONTENT_TYPE, DATA.array());
Firmware savedFirmware = savaData("/api/firmware/" + savedFirmwareInfo.getId().getId().toString() + "?checksum={checksum}&checksumAlgorithm={checksumAlgorithm}", testData, CHECKSUM, CHECKSUM_ALGORITHM);
firmwares.add(new FirmwareInfo(savedFirmware));
OtaPackage savedFirmware = savaData("/api/otaPackage/" + savedFirmwareInfo.getId().getId().toString() + "?checksum={checksum}&checksumAlgorithm={checksumAlgorithm}", testData, CHECKSUM, CHECKSUM_ALGORITHM);
otaPackages.add(new OtaPackageInfo(savedFirmware));
} else {
firmwares.add(savedFirmwareInfo);
otaPackages.add(savedFirmwareInfo);
}
}
List<FirmwareInfo> loadedFirmwares = new ArrayList<>();
List<OtaPackageInfo> loadedFirmwares = new ArrayList<>();
PageLink pageLink = new PageLink(24);
PageData<FirmwareInfo> pageData;
PageData<OtaPackageInfo> pageData;
do {
pageData = doGetTypedWithPageLink("/api/firmwares?",
pageData = doGetTypedWithPageLink("/api/otaPackages?",
new TypeReference<>() {
}, pageLink);
loadedFirmwares.addAll(pageData.getData());
@ -249,41 +248,41 @@ public abstract class BaseFirmwareControllerTest extends AbstractControllerTest
}
} while (pageData.hasNext());
Collections.sort(firmwares, idComparator);
Collections.sort(otaPackages, idComparator);
Collections.sort(loadedFirmwares, idComparator);
Assert.assertEquals(firmwares, loadedFirmwares);
Assert.assertEquals(otaPackages, loadedFirmwares);
}
@Test
public void testFindTenantFirmwaresByHasData() throws Exception {
List<FirmwareInfo> firmwaresWithData = new ArrayList<>();
List<FirmwareInfo> firmwaresWithoutData = new ArrayList<>();
List<OtaPackageInfo> otaPackagesWithData = new ArrayList<>();
List<OtaPackageInfo> otaPackagesWithoutData = new ArrayList<>();
for (int i = 0; i < 165; i++) {
FirmwareInfo firmwareInfo = new FirmwareInfo();
OtaPackageInfo firmwareInfo = new OtaPackageInfo();
firmwareInfo.setDeviceProfileId(deviceProfileId);
firmwareInfo.setType(FIRMWARE);
firmwareInfo.setTitle(TITLE);
firmwareInfo.setVersion(VERSION + i);
FirmwareInfo savedFirmwareInfo = save(firmwareInfo);
OtaPackageInfo savedFirmwareInfo = save(firmwareInfo);
if (i > 100) {
MockMultipartFile testData = new MockMultipartFile("file", FILE_NAME, CONTENT_TYPE, DATA.array());
Firmware savedFirmware = savaData("/api/firmware/" + savedFirmwareInfo.getId().getId().toString() + "?checksum={checksum}&checksumAlgorithm={checksumAlgorithm}", testData, CHECKSUM, CHECKSUM_ALGORITHM);
firmwaresWithData.add(new FirmwareInfo(savedFirmware));
OtaPackage savedFirmware = savaData("/api/otaPackage/" + savedFirmwareInfo.getId().getId().toString() + "?checksum={checksum}&checksumAlgorithm={checksumAlgorithm}", testData, CHECKSUM, CHECKSUM_ALGORITHM);
otaPackagesWithData.add(new OtaPackageInfo(savedFirmware));
} else {
firmwaresWithoutData.add(savedFirmwareInfo);
otaPackagesWithoutData.add(savedFirmwareInfo);
}
}
List<FirmwareInfo> loadedFirmwaresWithData = new ArrayList<>();
List<OtaPackageInfo> loadedFirmwaresWithData = new ArrayList<>();
PageLink pageLink = new PageLink(24);
PageData<FirmwareInfo> pageData;
PageData<OtaPackageInfo> pageData;
do {
pageData = doGetTypedWithPageLink("/api/firmwares/" + deviceProfileId.toString() + "/FIRMWARE/true?",
pageData = doGetTypedWithPageLink("/api/otaPackages/" + deviceProfileId.toString() + "/FIRMWARE/true?",
new TypeReference<>() {
}, pageLink);
loadedFirmwaresWithData.addAll(pageData.getData());
@ -292,10 +291,10 @@ public abstract class BaseFirmwareControllerTest extends AbstractControllerTest
}
} while (pageData.hasNext());
List<FirmwareInfo> loadedFirmwaresWithoutData = new ArrayList<>();
List<OtaPackageInfo> loadedFirmwaresWithoutData = new ArrayList<>();
pageLink = new PageLink(24);
do {
pageData = doGetTypedWithPageLink("/api/firmwares/" + deviceProfileId.toString() + "/FIRMWARE/false?",
pageData = doGetTypedWithPageLink("/api/otaPackages/" + deviceProfileId.toString() + "/FIRMWARE/false?",
new TypeReference<>() {
}, pageLink);
loadedFirmwaresWithoutData.addAll(pageData.getData());
@ -304,25 +303,25 @@ public abstract class BaseFirmwareControllerTest extends AbstractControllerTest
}
} while (pageData.hasNext());
Collections.sort(firmwaresWithData, idComparator);
Collections.sort(firmwaresWithoutData, idComparator);
Collections.sort(otaPackagesWithData, idComparator);
Collections.sort(otaPackagesWithoutData, idComparator);
Collections.sort(loadedFirmwaresWithData, idComparator);
Collections.sort(loadedFirmwaresWithoutData, idComparator);
Assert.assertEquals(firmwaresWithData, loadedFirmwaresWithData);
Assert.assertEquals(firmwaresWithoutData, loadedFirmwaresWithoutData);
Assert.assertEquals(otaPackagesWithData, loadedFirmwaresWithData);
Assert.assertEquals(otaPackagesWithoutData, loadedFirmwaresWithoutData);
}
private FirmwareInfo save(FirmwareInfo firmwareInfo) throws Exception {
return doPost("/api/firmware", firmwareInfo, FirmwareInfo.class);
private OtaPackageInfo save(OtaPackageInfo firmwareInfo) throws Exception {
return doPost("/api/otaPackage", firmwareInfo, OtaPackageInfo.class);
}
protected Firmware savaData(String urlTemplate, MockMultipartFile content, String... params) throws Exception {
protected OtaPackage savaData(String urlTemplate, MockMultipartFile content, String... params) throws Exception {
MockMultipartHttpServletRequestBuilder postRequest = MockMvcRequestBuilders.multipart(urlTemplate, params);
postRequest.file(content);
setJwtToken(postRequest);
return readResponse(mockMvc.perform(postRequest).andExpect(status().isOk()), Firmware.class);
return readResponse(mockMvc.perform(postRequest).andExpect(status().isOk()), OtaPackage.class);
}
}

4
application/src/test/java/org/thingsboard/server/controller/sql/FirmwareControllerSqlTest.java → application/src/test/java/org/thingsboard/server/controller/sql/OtaPackageControllerSqlTest.java

@ -15,9 +15,9 @@
*/
package org.thingsboard.server.controller.sql;
import org.thingsboard.server.controller.BaseFirmwareControllerTest;
import org.thingsboard.server.controller.BaseOtaPackageControllerTest;
import org.thingsboard.server.dao.service.DaoSqlTest;
@DaoSqlTest
public class FirmwareControllerSqlTest extends BaseFirmwareControllerTest {
public class OtaPackageControllerSqlTest extends BaseOtaPackageControllerTest {
}

13
common/cache/src/main/java/org/thingsboard/server/cache/firmware/CaffeineFirmwareCache.java → common/cache/src/main/java/org/thingsboard/server/cache/ota/CaffeineOtaPackageCache.java

@ -13,19 +13,20 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.cache.firmware;
package org.thingsboard.server.cache.ota;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cache.CacheManager;
import org.springframework.stereotype.Service;
import static org.thingsboard.server.common.data.CacheConstants.FIRMWARE_CACHE;
import static org.thingsboard.server.common.data.CacheConstants.OTA_PACKAGE_CACHE;
import static org.thingsboard.server.common.data.CacheConstants.OTA_PACKAGE_DATA_CACHE;
@Service
@ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "caffeine", matchIfMissing = true)
@RequiredArgsConstructor
public class CaffeineFirmwareCache implements FirmwareDataCache {
public class CaffeineOtaPackageCache implements OtaPackageDataCache {
private final CacheManager cacheManager;
@ -36,7 +37,7 @@ public class CaffeineFirmwareCache implements FirmwareDataCache {
@Override
public byte[] get(String key, int chunkSize, int chunk) {
byte[] data = cacheManager.getCache(FIRMWARE_CACHE).get(key, byte[].class);
byte[] data = cacheManager.getCache(OTA_PACKAGE_DATA_CACHE).get(key, byte[].class);
if (chunkSize < 1) {
return data;
@ -58,11 +59,11 @@ public class CaffeineFirmwareCache implements FirmwareDataCache {
@Override
public void put(String key, byte[] value) {
cacheManager.getCache(FIRMWARE_CACHE).putIfAbsent(key, value);
cacheManager.getCache(OTA_PACKAGE_DATA_CACHE).putIfAbsent(key, value);
}
@Override
public void evict(String key) {
cacheManager.getCache(FIRMWARE_CACHE).evict(key);
cacheManager.getCache(OTA_PACKAGE_DATA_CACHE).evict(key);
}
}

8
common/cache/src/main/java/org/thingsboard/server/cache/firmware/FirmwareDataCache.java → common/cache/src/main/java/org/thingsboard/server/cache/ota/OtaPackageDataCache.java

@ -13,9 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.cache.firmware;
package org.thingsboard.server.cache.ota;
public interface FirmwareDataCache {
public interface OtaPackageDataCache {
byte[] get(String key);
@ -25,8 +25,8 @@ public interface FirmwareDataCache {
void evict(String key);
default boolean has(String firmwareId) {
byte[] data = get(firmwareId, 1, 0);
default boolean has(String otaPackageId) {
byte[] data = get(otaPackageId, 1, 0);
return data != null && data.length > 0;
}
}

19
common/cache/src/main/java/org/thingsboard/server/cache/firmware/RedisFirmwareDataCache.java → common/cache/src/main/java/org/thingsboard/server/cache/ota/RedisOtaPackageDataCache.java

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.cache.firmware;
package org.thingsboard.server.cache.ota;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@ -21,12 +21,13 @@ import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.stereotype.Service;
import static org.thingsboard.server.common.data.CacheConstants.FIRMWARE_CACHE;
import static org.thingsboard.server.common.data.CacheConstants.OTA_PACKAGE_CACHE;
import static org.thingsboard.server.common.data.CacheConstants.OTA_PACKAGE_DATA_CACHE;
@Service
@ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "redis")
@RequiredArgsConstructor
public class RedisFirmwareDataCache implements FirmwareDataCache {
public class RedisOtaPackageDataCache implements OtaPackageDataCache {
private final RedisConnectionFactory redisConnectionFactory;
@ -39,30 +40,30 @@ public class RedisFirmwareDataCache implements FirmwareDataCache {
public byte[] get(String key, int chunkSize, int chunk) {
try (RedisConnection connection = redisConnectionFactory.getConnection()) {
if (chunkSize == 0) {
return connection.get(toFirmwareCacheKey(key));
return connection.get(toOtaPackageCacheKey(key));
}
int startIndex = chunkSize * chunk;
int endIndex = startIndex + chunkSize - 1;
return connection.getRange(toFirmwareCacheKey(key), startIndex, endIndex);
return connection.getRange(toOtaPackageCacheKey(key), startIndex, endIndex);
}
}
@Override
public void put(String key, byte[] value) {
try (RedisConnection connection = redisConnectionFactory.getConnection()) {
connection.set(toFirmwareCacheKey(key), value);
connection.set(toOtaPackageCacheKey(key), value);
}
}
@Override
public void evict(String key) {
try (RedisConnection connection = redisConnectionFactory.getConnection()) {
connection.del(toFirmwareCacheKey(key));
connection.del(toOtaPackageCacheKey(key));
}
}
private byte[] toFirmwareCacheKey(String key) {
return String.format("%s::%s", FIRMWARE_CACHE, key).getBytes();
private byte[] toOtaPackageCacheKey(String key) {
return String.format("%s::%s", OTA_PACKAGE_DATA_CACHE, key).getBytes();
}
}

5
common/dao-api/src/main/java/org/thingsboard/server/dao/device/DeviceService.java

@ -27,6 +27,7 @@ import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.data.id.EdgeId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.ota.OtaPackageType;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.security.DeviceCredentials;
@ -63,9 +64,9 @@ public interface DeviceService {
PageData<Device> findDevicesByTenantIdAndType(TenantId tenantId, String type, PageLink pageLink);
PageData<Device> findDevicesByTenantIdAndTypeAndEmptyFirmware(TenantId tenantId, String type, PageLink pageLink);
PageData<Device> findDevicesByTenantIdAndTypeAndEmptyOtaPackage(TenantId tenantId, DeviceProfileId deviceProfileId, OtaPackageType type, PageLink pageLink);
PageData<Device> findDevicesByTenantIdAndTypeAndEmptySoftware(TenantId tenantId, String type, PageLink pageLink);
Long countDevicesByTenantIdAndDeviceProfileIdAndEmptyOtaPackage(TenantId tenantId, DeviceProfileId deviceProfileId, OtaPackageType otaPackageType);
PageData<DeviceInfo> findDeviceInfosByTenantIdAndType(TenantId tenantId, String type, PageLink pageLink);

52
common/dao-api/src/main/java/org/thingsboard/server/dao/firmware/FirmwareService.java

@ -1,52 +0,0 @@
/**
* Copyright © 2016-2021 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.dao.firmware;
import com.google.common.util.concurrent.ListenableFuture;
import org.thingsboard.server.common.data.Firmware;
import org.thingsboard.server.common.data.FirmwareInfo;
import org.thingsboard.server.common.data.firmware.ChecksumAlgorithm;
import org.thingsboard.server.common.data.firmware.FirmwareType;
import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.data.id.FirmwareId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import java.nio.ByteBuffer;
public interface FirmwareService {
FirmwareInfo saveFirmwareInfo(FirmwareInfo firmwareInfo);
Firmware saveFirmware(Firmware firmware);
String generateChecksum(ChecksumAlgorithm checksumAlgorithm, ByteBuffer data);
Firmware findFirmwareById(TenantId tenantId, FirmwareId firmwareId);
FirmwareInfo findFirmwareInfoById(TenantId tenantId, FirmwareId firmwareId);
ListenableFuture<FirmwareInfo> findFirmwareInfoByIdAsync(TenantId tenantId, FirmwareId firmwareId);
PageData<FirmwareInfo> findTenantFirmwaresByTenantId(TenantId tenantId, PageLink pageLink);
PageData<FirmwareInfo> findTenantFirmwaresByTenantIdAndDeviceProfileIdAndTypeAndHasData(TenantId tenantId, DeviceProfileId deviceProfileId, FirmwareType firmwareType, boolean hasData, PageLink pageLink);
void deleteFirmware(TenantId tenantId, FirmwareId firmwareId);
void deleteFirmwaresByTenantId(TenantId tenantId);
}

52
common/dao-api/src/main/java/org/thingsboard/server/dao/ota/OtaPackageService.java

@ -0,0 +1,52 @@
/**
* Copyright © 2016-2021 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.dao.ota;
import com.google.common.util.concurrent.ListenableFuture;
import org.thingsboard.server.common.data.OtaPackage;
import org.thingsboard.server.common.data.OtaPackageInfo;
import org.thingsboard.server.common.data.ota.ChecksumAlgorithm;
import org.thingsboard.server.common.data.ota.OtaPackageType;
import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.data.id.OtaPackageId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import java.nio.ByteBuffer;
public interface OtaPackageService {
OtaPackageInfo saveOtaPackageInfo(OtaPackageInfo otaPackageInfo);
OtaPackage saveOtaPackage(OtaPackage otaPackage);
String generateChecksum(ChecksumAlgorithm checksumAlgorithm, ByteBuffer data);
OtaPackage findOtaPackageById(TenantId tenantId, OtaPackageId otaPackageId);
OtaPackageInfo findOtaPackageInfoById(TenantId tenantId, OtaPackageId otaPackageId);
ListenableFuture<OtaPackageInfo> findOtaPackageInfoByIdAsync(TenantId tenantId, OtaPackageId otaPackageId);
PageData<OtaPackageInfo> findTenantOtaPackagesByTenantId(TenantId tenantId, PageLink pageLink);
PageData<OtaPackageInfo> findTenantOtaPackagesByTenantIdAndDeviceProfileIdAndTypeAndHasData(TenantId tenantId, DeviceProfileId deviceProfileId, OtaPackageType otaPackageType, boolean hasData, PageLink pageLink);
void deleteOtaPackage(TenantId tenantId, OtaPackageId otaPackageId);
void deleteOtaPackagesByTenantId(TenantId tenantId);
}

3
common/data/src/main/java/org/thingsboard/server/common/data/CacheConstants.java

@ -29,5 +29,6 @@ public class CacheConstants {
public static final String DEVICE_PROFILE_CACHE = "deviceProfiles";
public static final String ATTRIBUTES_CACHE = "attributes";
public static final String TOKEN_OUTDATAGE_TIME_CACHE = "tokensOutdatageTime";
public static final String FIRMWARE_CACHE = "firmwares";
public static final String OTA_PACKAGE_CACHE = "otaPackages";
public static final String OTA_PACKAGE_DATA_CACHE = "otaPackagesData";
}

16
common/data/src/main/java/org/thingsboard/server/common/data/Device.java

@ -23,7 +23,7 @@ import org.thingsboard.server.common.data.device.data.DeviceData;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.data.id.FirmwareId;
import org.thingsboard.server.common.data.id.OtaPackageId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.validation.NoXss;
@ -32,7 +32,7 @@ import java.io.IOException;
@EqualsAndHashCode(callSuper = true)
@Slf4j
public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implements HasName, HasTenantId, HasCustomerId, HasFirmware {
public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implements HasName, HasTenantId, HasCustomerId, HasOtaPackage {
private static final long serialVersionUID = 2807343040519543363L;
@ -49,8 +49,8 @@ public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implemen
@JsonIgnore
private byte[] deviceDataBytes;
private FirmwareId firmwareId;
private FirmwareId softwareId;
private OtaPackageId firmwareId;
private OtaPackageId softwareId;
public Device() {
super();
@ -167,19 +167,19 @@ public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implemen
return getName();
}
public FirmwareId getFirmwareId() {
public OtaPackageId getFirmwareId() {
return firmwareId;
}
public void setFirmwareId(FirmwareId firmwareId) {
public void setFirmwareId(OtaPackageId firmwareId) {
this.firmwareId = firmwareId;
}
public FirmwareId getSoftwareId() {
public OtaPackageId getSoftwareId() {
return softwareId;
}
public void setSoftwareId(FirmwareId softwareId) {
public void setSoftwareId(OtaPackageId softwareId) {
this.softwareId = softwareId;
}

8
common/data/src/main/java/org/thingsboard/server/common/data/DeviceProfile.java

@ -23,7 +23,7 @@ import lombok.extern.slf4j.Slf4j;
import org.thingsboard.server.common.data.device.profile.DeviceProfileData;
import org.thingsboard.server.common.data.id.DashboardId;
import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.data.id.FirmwareId;
import org.thingsboard.server.common.data.id.OtaPackageId;
import org.thingsboard.server.common.data.id.RuleChainId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.validation.NoXss;
@ -37,7 +37,7 @@ import static org.thingsboard.server.common.data.SearchTextBasedWithAdditionalIn
@Data
@EqualsAndHashCode(callSuper = true)
@Slf4j
public class DeviceProfile extends SearchTextBased<DeviceProfileId> implements HasName, HasTenantId, HasFirmware {
public class DeviceProfile extends SearchTextBased<DeviceProfileId> implements HasName, HasTenantId, HasOtaPackage {
private TenantId tenantId;
@NoXss
@ -60,9 +60,9 @@ public class DeviceProfile extends SearchTextBased<DeviceProfileId> implements H
@NoXss
private String provisionDeviceKey;
private FirmwareId firmwareId;
private OtaPackageId firmwareId;
private FirmwareId softwareId;
private OtaPackageId softwareId;
public DeviceProfile() {
super();

2
common/data/src/main/java/org/thingsboard/server/common/data/EntityType.java

@ -19,5 +19,5 @@ package org.thingsboard.server.common.data;
* @author Andrew Shvayka
*/
public enum EntityType {
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;
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;
}

8
common/data/src/main/java/org/thingsboard/server/common/data/HasFirmware.java → common/data/src/main/java/org/thingsboard/server/common/data/HasOtaPackage.java

@ -15,11 +15,11 @@
*/
package org.thingsboard.server.common.data;
import org.thingsboard.server.common.data.id.FirmwareId;
import org.thingsboard.server.common.data.id.OtaPackageId;
public interface HasFirmware {
public interface HasOtaPackage {
FirmwareId getFirmwareId();
OtaPackageId getFirmwareId();
FirmwareId getSoftwareId();
OtaPackageId getSoftwareId();
}

10
common/data/src/main/java/org/thingsboard/server/common/data/Firmware.java → common/data/src/main/java/org/thingsboard/server/common/data/OtaPackage.java

@ -17,27 +17,27 @@ package org.thingsboard.server.common.data;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.thingsboard.server.common.data.id.FirmwareId;
import org.thingsboard.server.common.data.id.OtaPackageId;
import java.nio.ByteBuffer;
@Data
@EqualsAndHashCode(callSuper = true)
public class Firmware extends FirmwareInfo {
public class OtaPackage extends OtaPackageInfo {
private static final long serialVersionUID = 3091601761339422546L;
private transient ByteBuffer data;
public Firmware() {
public OtaPackage() {
super();
}
public Firmware(FirmwareId id) {
public OtaPackage(OtaPackageId id) {
super(id);
}
public Firmware(Firmware firmware) {
public OtaPackage(OtaPackage firmware) {
super(firmware);
this.data = firmware.getData();
}

40
common/data/src/main/java/org/thingsboard/server/common/data/FirmwareInfo.java → common/data/src/main/java/org/thingsboard/server/common/data/OtaPackageInfo.java

@ -19,22 +19,22 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;
import org.thingsboard.server.common.data.firmware.ChecksumAlgorithm;
import org.thingsboard.server.common.data.firmware.FirmwareType;
import org.thingsboard.server.common.data.ota.ChecksumAlgorithm;
import org.thingsboard.server.common.data.ota.OtaPackageType;
import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.data.id.FirmwareId;
import org.thingsboard.server.common.data.id.OtaPackageId;
import org.thingsboard.server.common.data.id.TenantId;
@Slf4j
@Data
@EqualsAndHashCode(callSuper = true)
public class FirmwareInfo extends SearchTextBasedWithAdditionalInfo<FirmwareId> implements HasName, HasTenantId {
public class OtaPackageInfo extends SearchTextBasedWithAdditionalInfo<OtaPackageId> implements HasName, HasTenantId {
private static final long serialVersionUID = 3168391583570815419L;
private TenantId tenantId;
private DeviceProfileId deviceProfileId;
private FirmwareType type;
private OtaPackageType type;
private String title;
private String version;
private boolean hasData;
@ -45,27 +45,27 @@ public class FirmwareInfo extends SearchTextBasedWithAdditionalInfo<FirmwareId>
private Long dataSize;
public FirmwareInfo() {
public OtaPackageInfo() {
super();
}
public FirmwareInfo(FirmwareId id) {
public OtaPackageInfo(OtaPackageId id) {
super(id);
}
public FirmwareInfo(FirmwareInfo firmwareInfo) {
super(firmwareInfo);
this.tenantId = firmwareInfo.getTenantId();
this.deviceProfileId = firmwareInfo.getDeviceProfileId();
this.type = firmwareInfo.getType();
this.title = firmwareInfo.getTitle();
this.version = firmwareInfo.getVersion();
this.hasData = firmwareInfo.isHasData();
this.fileName = firmwareInfo.getFileName();
this.contentType = firmwareInfo.getContentType();
this.checksumAlgorithm = firmwareInfo.getChecksumAlgorithm();
this.checksum = firmwareInfo.getChecksum();
this.dataSize = firmwareInfo.getDataSize();
public OtaPackageInfo(OtaPackageInfo otaPackageInfo) {
super(otaPackageInfo);
this.tenantId = otaPackageInfo.getTenantId();
this.deviceProfileId = otaPackageInfo.getDeviceProfileId();
this.type = otaPackageInfo.getType();
this.title = otaPackageInfo.getTitle();
this.version = otaPackageInfo.getVersion();
this.hasData = otaPackageInfo.isHasData();
this.fileName = otaPackageInfo.getFileName();
this.contentType = otaPackageInfo.getContentType();
this.checksumAlgorithm = otaPackageInfo.getChecksumAlgorithm();
this.checksum = otaPackageInfo.getChecksum();
this.dataSize = otaPackageInfo.getDataSize();
}
@Override

4
common/data/src/main/java/org/thingsboard/server/common/data/id/EntityIdFactory.java

@ -71,8 +71,8 @@ public class EntityIdFactory {
return new ApiUsageStateId(uuid);
case TB_RESOURCE:
return new TbResourceId(uuid);
case FIRMWARE:
return new FirmwareId(uuid);
case OTA_PACKAGE:
return new OtaPackageId(uuid);
case EDGE:
return new EdgeId(uuid);
}

10
common/data/src/main/java/org/thingsboard/server/common/data/id/FirmwareId.java → common/data/src/main/java/org/thingsboard/server/common/data/id/OtaPackageId.java

@ -22,23 +22,23 @@ import org.thingsboard.server.common.data.EntityType;
import java.util.UUID;
public class FirmwareId extends UUIDBased implements EntityId {
public class OtaPackageId extends UUIDBased implements EntityId {
private static final long serialVersionUID = 1L;
@JsonCreator
public FirmwareId(@JsonProperty("id") UUID id) {
public OtaPackageId(@JsonProperty("id") UUID id) {
super(id);
}
public static FirmwareId fromString(String firmwareId) {
return new FirmwareId(UUID.fromString(firmwareId));
public static OtaPackageId fromString(String firmwareId) {
return new OtaPackageId(UUID.fromString(firmwareId));
}
@JsonIgnore
@Override
public EntityType getEntityType() {
return EntityType.FIRMWARE;
return EntityType.OTA_PACKAGE;
}
}

2
common/data/src/main/java/org/thingsboard/server/common/data/firmware/ChecksumAlgorithm.java → common/data/src/main/java/org/thingsboard/server/common/data/ota/ChecksumAlgorithm.java

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.firmware;
package org.thingsboard.server.common.data.ota;
public enum ChecksumAlgorithm {
MD5,

6
common/data/src/main/java/org/thingsboard/server/common/data/firmware/FirmwareKey.java → common/data/src/main/java/org/thingsboard/server/common/data/ota/OtaPackageKey.java

@ -13,18 +13,18 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.firmware;
package org.thingsboard.server.common.data.ota;
import lombok.Getter;
public enum FirmwareKey {
public enum OtaPackageKey {
TITLE("title"), VERSION("version"), TS("ts"), STATE("state"), SIZE("size"), CHECKSUM("checksum"), CHECKSUM_ALGORITHM("checksum_algorithm");
@Getter
private final String value;
FirmwareKey(String value) {
OtaPackageKey(String value) {
this.value = value;
}
}

6
common/data/src/main/java/org/thingsboard/server/common/data/firmware/FirmwareType.java → common/data/src/main/java/org/thingsboard/server/common/data/ota/OtaPackageType.java

@ -13,18 +13,18 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.firmware;
package org.thingsboard.server.common.data.ota;
import lombok.Getter;
public enum FirmwareType {
public enum OtaPackageType {
FIRMWARE("fw"), SOFTWARE("sw");
@Getter
private final String keyPrefix;
FirmwareType(String keyPrefix) {
OtaPackageType(String keyPrefix) {
this.keyPrefix = keyPrefix;
}
}

4
common/data/src/main/java/org/thingsboard/server/common/data/firmware/FirmwareUpdateStatus.java → common/data/src/main/java/org/thingsboard/server/common/data/ota/OtaPackageUpdateStatus.java

@ -13,8 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.firmware;
package org.thingsboard.server.common.data.ota;
public enum FirmwareUpdateStatus {
public enum OtaPackageUpdateStatus {
QUEUED, INITIATED, DOWNLOADING, DOWNLOADED, VERIFIED, UPDATING, UPDATED, FAILED
}

49
common/data/src/main/java/org/thingsboard/server/common/data/firmware/FirmwareUtil.java → common/data/src/main/java/org/thingsboard/server/common/data/ota/OtaPackageUtil.java

@ -13,21 +13,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.firmware;
package org.thingsboard.server.common.data.ota;
import lombok.extern.slf4j.Slf4j;
import org.thingsboard.server.common.data.HasFirmware;
import org.thingsboard.server.common.data.id.FirmwareId;
import org.thingsboard.server.common.data.HasOtaPackage;
import org.thingsboard.server.common.data.id.OtaPackageId;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static org.thingsboard.server.common.data.firmware.FirmwareType.FIRMWARE;
import static org.thingsboard.server.common.data.firmware.FirmwareType.SOFTWARE;
import java.util.function.Supplier;
@Slf4j
public class FirmwareUtil {
public class OtaPackageUtil {
public static final List<String> ALL_FW_ATTRIBUTE_KEYS;
@ -35,19 +33,19 @@ public class FirmwareUtil {
static {
ALL_FW_ATTRIBUTE_KEYS = new ArrayList<>();
for (FirmwareKey key : FirmwareKey.values()) {
ALL_FW_ATTRIBUTE_KEYS.add(getAttributeKey(FIRMWARE, key));
for (OtaPackageKey key : OtaPackageKey.values()) {
ALL_FW_ATTRIBUTE_KEYS.add(getAttributeKey(OtaPackageType.FIRMWARE, key));
}
ALL_SW_ATTRIBUTE_KEYS = new ArrayList<>();
for (FirmwareKey key : FirmwareKey.values()) {
ALL_SW_ATTRIBUTE_KEYS.add(getAttributeKey(SOFTWARE, key));
for (OtaPackageKey key : OtaPackageKey.values()) {
ALL_SW_ATTRIBUTE_KEYS.add(getAttributeKey(OtaPackageType.SOFTWARE, key));
}
}
public static List<String> getAttributeKeys(FirmwareType firmwareType) {
public static List<String> getAttributeKeys(OtaPackageType firmwareType) {
switch (firmwareType) {
case FIRMWARE:
return ALL_FW_ATTRIBUTE_KEYS;
@ -57,35 +55,46 @@ public class FirmwareUtil {
return Collections.emptyList();
}
public static String getAttributeKey(FirmwareType type, FirmwareKey key) {
public static String getAttributeKey(OtaPackageType type, OtaPackageKey key) {
return type.getKeyPrefix() + "_" + key.getValue();
}
public static String getTargetTelemetryKey(FirmwareType type, FirmwareKey key) {
public static String getTargetTelemetryKey(OtaPackageType type, OtaPackageKey key) {
return getTelemetryKey("target_", type, key);
}
public static String getCurrentTelemetryKey(FirmwareType type, FirmwareKey key) {
public static String getCurrentTelemetryKey(OtaPackageType type, OtaPackageKey key) {
return getTelemetryKey("current_", type, key);
}
private static String getTelemetryKey(String prefix, FirmwareType type, FirmwareKey key) {
private static String getTelemetryKey(String prefix, OtaPackageType type, OtaPackageKey key) {
return prefix + type.getKeyPrefix() + "_" + key.getValue();
}
public static String getTelemetryKey(FirmwareType type, FirmwareKey key) {
public static String getTelemetryKey(OtaPackageType type, OtaPackageKey key) {
return type.getKeyPrefix() + "_" + key.getValue();
}
public static FirmwareId getFirmwareId(HasFirmware entity, FirmwareType firmwareType) {
switch (firmwareType) {
public static OtaPackageId getOtaPackageId(HasOtaPackage entity, OtaPackageType type) {
switch (type) {
case FIRMWARE:
return entity.getFirmwareId();
case SOFTWARE:
return entity.getSoftwareId();
default:
log.warn("Unsupported firmware type: [{}]", firmwareType);
log.warn("Unsupported ota package type: [{}]", type);
return null;
}
}
public static <T> T getByOtaPackageType(Supplier<T> firmwareSupplier, Supplier<T> softwareSupplier, OtaPackageType type) {
switch (type) {
case FIRMWARE:
return firmwareSupplier.get();
case SOFTWARE:
return softwareSupplier.get();
default:
throw new RuntimeException("Unsupported OtaPackage type: " + type);
}
}
}

2
common/queue/src/main/java/org/thingsboard/server/queue/kafka/TbKafkaTopicConfigs.java

@ -38,7 +38,7 @@ public class TbKafkaTopicConfigs {
private String notificationsProperties;
@Value("${queue.kafka.topic-properties.js-executor}")
private String jsExecutorProperties;
@Value("${queue.kafka.topic-properties.fw-updates:}")
@Value("${queue.kafka.topic-properties.ota-updates:}")
private String fwUpdatesProperties;
@Getter

10
common/queue/src/main/java/org/thingsboard/server/queue/provider/AwsSqsMonolithQueueFactory.java

@ -187,14 +187,14 @@ public class AwsSqsMonolithQueueFactory implements TbCoreQueueFactory, TbRuleEng
}
@Override
public TbQueueConsumer<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> createToFirmwareStateServiceMsgConsumer() {
return new TbAwsSqsConsumerTemplate<>(transportApiAdmin, sqsSettings, coreSettings.getFirmwareTopic(),
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToFirmwareStateServiceMsg.parseFrom(msg.getData()), msg.getHeaders()));
public TbQueueConsumer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgConsumer() {
return new TbAwsSqsConsumerTemplate<>(transportApiAdmin, sqsSettings, coreSettings.getOtaPackageTopic(),
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToOtaPackageStateServiceMsg.parseFrom(msg.getData()), msg.getHeaders()));
}
@Override
public TbQueueProducer<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> createToFirmwareStateServiceMsgProducer() {
return new TbAwsSqsProducerTemplate<>(coreAdmin, sqsSettings, coreSettings.getFirmwareTopic());
public TbQueueProducer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgProducer() {
return new TbAwsSqsProducerTemplate<>(coreAdmin, sqsSettings, coreSettings.getOtaPackageTopic());
}
@PreDestroy

12
common/queue/src/main/java/org/thingsboard/server/queue/provider/AwsSqsTbCoreQueueFactory.java

@ -23,7 +23,7 @@ import org.thingsboard.server.common.msg.queue.ServiceType;
import org.thingsboard.server.gen.js.JsInvokeProtos;
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToFirmwareStateServiceMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg;
@ -177,14 +177,14 @@ public class AwsSqsTbCoreQueueFactory implements TbCoreQueueFactory {
}
@Override
public TbQueueConsumer<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> createToFirmwareStateServiceMsgConsumer() {
return new TbAwsSqsConsumerTemplate<>(transportApiAdmin, sqsSettings, coreSettings.getFirmwareTopic(),
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToFirmwareStateServiceMsg.parseFrom(msg.getData()), msg.getHeaders()));
public TbQueueConsumer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgConsumer() {
return new TbAwsSqsConsumerTemplate<>(transportApiAdmin, sqsSettings, coreSettings.getOtaPackageTopic(),
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToOtaPackageStateServiceMsg.parseFrom(msg.getData()), msg.getHeaders()));
}
@Override
public TbQueueProducer<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> createToFirmwareStateServiceMsgProducer() {
return new TbAwsSqsProducerTemplate<>(coreAdmin, sqsSettings, coreSettings.getFirmwareTopic());
public TbQueueProducer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgProducer() {
return new TbAwsSqsProducerTemplate<>(coreAdmin, sqsSettings, coreSettings.getOtaPackageTopic());
}
@PreDestroy

8
common/queue/src/main/java/org/thingsboard/server/queue/provider/InMemoryMonolithQueueFactory.java

@ -131,13 +131,13 @@ public class InMemoryMonolithQueueFactory implements TbCoreQueueFactory, TbRuleE
}
@Override
public TbQueueConsumer<TbProtoQueueMsg<TransportProtos.ToFirmwareStateServiceMsg>> createToFirmwareStateServiceMsgConsumer() {
return new InMemoryTbQueueConsumer<>(coreSettings.getFirmwareTopic());
public TbQueueConsumer<TbProtoQueueMsg<TransportProtos.ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgConsumer() {
return new InMemoryTbQueueConsumer<>(coreSettings.getOtaPackageTopic());
}
@Override
public TbQueueProducer<TbProtoQueueMsg<TransportProtos.ToFirmwareStateServiceMsg>> createToFirmwareStateServiceMsgProducer() {
return new InMemoryTbQueueProducer<>(coreSettings.getFirmwareTopic());
public TbQueueProducer<TbProtoQueueMsg<TransportProtos.ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgProducer() {
return new InMemoryTbQueueProducer<>(coreSettings.getOtaPackageTopic());
}
@Override

22
common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaMonolithQueueFactory.java

@ -23,7 +23,7 @@ import org.thingsboard.server.common.msg.queue.ServiceType;
import org.thingsboard.server.gen.js.JsInvokeProtos;
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToFirmwareStateServiceMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg;
@ -277,24 +277,24 @@ public class KafkaMonolithQueueFactory implements TbCoreQueueFactory, TbRuleEngi
}
@Override
public TbQueueConsumer<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> createToFirmwareStateServiceMsgConsumer() {
TbKafkaConsumerTemplate.TbKafkaConsumerTemplateBuilder<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> consumerBuilder = TbKafkaConsumerTemplate.builder();
public TbQueueConsumer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgConsumer() {
TbKafkaConsumerTemplate.TbKafkaConsumerTemplateBuilder<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> consumerBuilder = TbKafkaConsumerTemplate.builder();
consumerBuilder.settings(kafkaSettings);
consumerBuilder.topic(coreSettings.getFirmwareTopic());
consumerBuilder.clientId("monolith-fw-consumer-" + serviceInfoProvider.getServiceId());
consumerBuilder.groupId("monolith-fw-consumer");
consumerBuilder.decoder(msg -> new TbProtoQueueMsg<>(msg.getKey(), ToFirmwareStateServiceMsg.parseFrom(msg.getData()), msg.getHeaders()));
consumerBuilder.topic(coreSettings.getOtaPackageTopic());
consumerBuilder.clientId("monolith-ota-consumer-" + serviceInfoProvider.getServiceId());
consumerBuilder.groupId("monolith-ota-consumer");
consumerBuilder.decoder(msg -> new TbProtoQueueMsg<>(msg.getKey(), ToOtaPackageStateServiceMsg.parseFrom(msg.getData()), msg.getHeaders()));
consumerBuilder.admin(fwUpdatesAdmin);
consumerBuilder.statsService(consumerStatsService);
return consumerBuilder.build();
}
@Override
public TbQueueProducer<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> createToFirmwareStateServiceMsgProducer() {
TbKafkaProducerTemplate.TbKafkaProducerTemplateBuilder<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> requestBuilder = TbKafkaProducerTemplate.builder();
public TbQueueProducer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgProducer() {
TbKafkaProducerTemplate.TbKafkaProducerTemplateBuilder<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> requestBuilder = TbKafkaProducerTemplate.builder();
requestBuilder.settings(kafkaSettings);
requestBuilder.clientId("monolith-fw-producer-" + serviceInfoProvider.getServiceId());
requestBuilder.defaultTopic(coreSettings.getFirmwareTopic());
requestBuilder.clientId("monolith-ota-producer-" + serviceInfoProvider.getServiceId());
requestBuilder.defaultTopic(coreSettings.getOtaPackageTopic());
requestBuilder.admin(fwUpdatesAdmin);
return requestBuilder.build();
}

22
common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaTbCoreQueueFactory.java

@ -23,7 +23,7 @@ import org.thingsboard.server.common.msg.queue.ServiceType;
import org.thingsboard.server.gen.js.JsInvokeProtos;
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToFirmwareStateServiceMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg;
@ -245,24 +245,24 @@ public class KafkaTbCoreQueueFactory implements TbCoreQueueFactory {
}
@Override
public TbQueueConsumer<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> createToFirmwareStateServiceMsgConsumer() {
TbKafkaConsumerTemplate.TbKafkaConsumerTemplateBuilder<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> consumerBuilder = TbKafkaConsumerTemplate.builder();
public TbQueueConsumer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgConsumer() {
TbKafkaConsumerTemplate.TbKafkaConsumerTemplateBuilder<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> consumerBuilder = TbKafkaConsumerTemplate.builder();
consumerBuilder.settings(kafkaSettings);
consumerBuilder.topic(coreSettings.getFirmwareTopic());
consumerBuilder.clientId("tb-core-fw-consumer-" + serviceInfoProvider.getServiceId());
consumerBuilder.groupId("tb-core-fw-consumer");
consumerBuilder.decoder(msg -> new TbProtoQueueMsg<>(msg.getKey(), ToFirmwareStateServiceMsg.parseFrom(msg.getData()), msg.getHeaders()));
consumerBuilder.topic(coreSettings.getOtaPackageTopic());
consumerBuilder.clientId("tb-core-ota-consumer-" + serviceInfoProvider.getServiceId());
consumerBuilder.groupId("tb-core-ota-consumer");
consumerBuilder.decoder(msg -> new TbProtoQueueMsg<>(msg.getKey(), ToOtaPackageStateServiceMsg.parseFrom(msg.getData()), msg.getHeaders()));
consumerBuilder.admin(fwUpdatesAdmin);
consumerBuilder.statsService(consumerStatsService);
return consumerBuilder.build();
}
@Override
public TbQueueProducer<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> createToFirmwareStateServiceMsgProducer() {
TbKafkaProducerTemplate.TbKafkaProducerTemplateBuilder<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> requestBuilder = TbKafkaProducerTemplate.builder();
public TbQueueProducer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgProducer() {
TbKafkaProducerTemplate.TbKafkaProducerTemplateBuilder<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> requestBuilder = TbKafkaProducerTemplate.builder();
requestBuilder.settings(kafkaSettings);
requestBuilder.clientId("tb-core-fw-producer-" + serviceInfoProvider.getServiceId());
requestBuilder.defaultTopic(coreSettings.getFirmwareTopic());
requestBuilder.clientId("tb-core-ota-producer-" + serviceInfoProvider.getServiceId());
requestBuilder.defaultTopic(coreSettings.getOtaPackageTopic());
requestBuilder.admin(fwUpdatesAdmin);
return requestBuilder.build();
}

12
common/queue/src/main/java/org/thingsboard/server/queue/provider/PubSubMonolithQueueFactory.java

@ -22,9 +22,9 @@ import org.springframework.stereotype.Component;
import org.thingsboard.server.common.msg.queue.ServiceType;
import org.thingsboard.server.gen.js.JsInvokeProtos.RemoteJsRequest;
import org.thingsboard.server.gen.js.JsInvokeProtos.RemoteJsResponse;
import org.thingsboard.server.gen.transport.TransportProtos.*;
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg;
@ -192,14 +192,14 @@ public class PubSubMonolithQueueFactory implements TbCoreQueueFactory, TbRuleEng
}
@Override
public TbQueueConsumer<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> createToFirmwareStateServiceMsgConsumer() {
return new TbPubSubConsumerTemplate<>(coreAdmin, pubSubSettings, coreSettings.getFirmwareTopic(),
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToFirmwareStateServiceMsg.parseFrom(msg.getData()), msg.getHeaders()));
public TbQueueConsumer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgConsumer() {
return new TbPubSubConsumerTemplate<>(coreAdmin, pubSubSettings, coreSettings.getOtaPackageTopic(),
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToOtaPackageStateServiceMsg.parseFrom(msg.getData()), msg.getHeaders()));
}
@Override
public TbQueueProducer<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> createToFirmwareStateServiceMsgProducer() {
return new TbPubSubProducerTemplate<>(coreAdmin, pubSubSettings, coreSettings.getFirmwareTopic());
public TbQueueProducer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgProducer() {
return new TbPubSubProducerTemplate<>(coreAdmin, pubSubSettings, coreSettings.getOtaPackageTopic());
}
@Override

12
common/queue/src/main/java/org/thingsboard/server/queue/provider/PubSubTbCoreQueueFactory.java

@ -23,7 +23,7 @@ import org.thingsboard.server.common.msg.queue.ServiceType;
import org.thingsboard.server.gen.js.JsInvokeProtos;
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToFirmwareStateServiceMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg;
@ -166,14 +166,14 @@ public class PubSubTbCoreQueueFactory implements TbCoreQueueFactory {
}
@Override
public TbQueueConsumer<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> createToFirmwareStateServiceMsgConsumer() {
return new TbPubSubConsumerTemplate<>(coreAdmin, pubSubSettings, coreSettings.getFirmwareTopic(),
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToFirmwareStateServiceMsg.parseFrom(msg.getData()), msg.getHeaders()));
public TbQueueConsumer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgConsumer() {
return new TbPubSubConsumerTemplate<>(coreAdmin, pubSubSettings, coreSettings.getOtaPackageTopic(),
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToOtaPackageStateServiceMsg.parseFrom(msg.getData()), msg.getHeaders()));
}
@Override
public TbQueueProducer<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> createToFirmwareStateServiceMsgProducer() {
return new TbPubSubProducerTemplate<>(coreAdmin, pubSubSettings, coreSettings.getFirmwareTopic());
public TbQueueProducer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgProducer() {
return new TbPubSubProducerTemplate<>(coreAdmin, pubSubSettings, coreSettings.getOtaPackageTopic());
}
@Override

12
common/queue/src/main/java/org/thingsboard/server/queue/provider/RabbitMqMonolithQueueFactory.java

@ -24,7 +24,7 @@ import org.thingsboard.server.gen.js.JsInvokeProtos.RemoteJsRequest;
import org.thingsboard.server.gen.js.JsInvokeProtos.RemoteJsResponse;
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToFirmwareStateServiceMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg;
@ -190,14 +190,14 @@ public class RabbitMqMonolithQueueFactory implements TbCoreQueueFactory, TbRuleE
}
@Override
public TbQueueConsumer<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> createToFirmwareStateServiceMsgConsumer() {
return new TbRabbitMqConsumerTemplate<>(coreAdmin, rabbitMqSettings, coreSettings.getFirmwareTopic(),
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToFirmwareStateServiceMsg.parseFrom(msg.getData()), msg.getHeaders()));
public TbQueueConsumer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgConsumer() {
return new TbRabbitMqConsumerTemplate<>(coreAdmin, rabbitMqSettings, coreSettings.getOtaPackageTopic(),
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToOtaPackageStateServiceMsg.parseFrom(msg.getData()), msg.getHeaders()));
}
@Override
public TbQueueProducer<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> createToFirmwareStateServiceMsgProducer() {
return new TbRabbitMqProducerTemplate<>(coreAdmin, rabbitMqSettings, coreSettings.getFirmwareTopic());
public TbQueueProducer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgProducer() {
return new TbRabbitMqProducerTemplate<>(coreAdmin, rabbitMqSettings, coreSettings.getOtaPackageTopic());
}
@Override

12
common/queue/src/main/java/org/thingsboard/server/queue/provider/RabbitMqTbCoreQueueFactory.java

@ -23,7 +23,7 @@ import org.thingsboard.server.common.msg.queue.ServiceType;
import org.thingsboard.server.gen.js.JsInvokeProtos;
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToFirmwareStateServiceMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg;
@ -172,14 +172,14 @@ public class RabbitMqTbCoreQueueFactory implements TbCoreQueueFactory {
}
@Override
public TbQueueConsumer<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> createToFirmwareStateServiceMsgConsumer() {
return new TbRabbitMqConsumerTemplate<>(coreAdmin, rabbitMqSettings, coreSettings.getFirmwareTopic(),
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToFirmwareStateServiceMsg.parseFrom(msg.getData()), msg.getHeaders()));
public TbQueueConsumer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgConsumer() {
return new TbRabbitMqConsumerTemplate<>(coreAdmin, rabbitMqSettings, coreSettings.getOtaPackageTopic(),
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToOtaPackageStateServiceMsg.parseFrom(msg.getData()), msg.getHeaders()));
}
@Override
public TbQueueProducer<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> createToFirmwareStateServiceMsgProducer() {
return new TbRabbitMqProducerTemplate<>(coreAdmin, rabbitMqSettings, coreSettings.getFirmwareTopic());
public TbQueueProducer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgProducer() {
return new TbRabbitMqProducerTemplate<>(coreAdmin, rabbitMqSettings, coreSettings.getOtaPackageTopic());
}
@Override

12
common/queue/src/main/java/org/thingsboard/server/queue/provider/ServiceBusMonolithQueueFactory.java

@ -23,7 +23,7 @@ import org.thingsboard.server.common.msg.queue.ServiceType;
import org.thingsboard.server.gen.js.JsInvokeProtos;
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToFirmwareStateServiceMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg;
@ -189,14 +189,14 @@ public class ServiceBusMonolithQueueFactory implements TbCoreQueueFactory, TbRul
}
@Override
public TbQueueConsumer<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> createToFirmwareStateServiceMsgConsumer() {
return new TbServiceBusConsumerTemplate<>(coreAdmin, serviceBusSettings, coreSettings.getFirmwareTopic(),
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToFirmwareStateServiceMsg.parseFrom(msg.getData()), msg.getHeaders()));
public TbQueueConsumer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgConsumer() {
return new TbServiceBusConsumerTemplate<>(coreAdmin, serviceBusSettings, coreSettings.getOtaPackageTopic(),
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToOtaPackageStateServiceMsg.parseFrom(msg.getData()), msg.getHeaders()));
}
@Override
public TbQueueProducer<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> createToFirmwareStateServiceMsgProducer() {
return new TbServiceBusProducerTemplate<>(coreAdmin, serviceBusSettings, coreSettings.getFirmwareTopic());
public TbQueueProducer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgProducer() {
return new TbServiceBusProducerTemplate<>(coreAdmin, serviceBusSettings, coreSettings.getOtaPackageTopic());
}
@Override

12
common/queue/src/main/java/org/thingsboard/server/queue/provider/ServiceBusTbCoreQueueFactory.java

@ -23,7 +23,7 @@ import org.thingsboard.server.common.msg.queue.ServiceType;
import org.thingsboard.server.gen.js.JsInvokeProtos;
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToFirmwareStateServiceMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg;
@ -172,14 +172,14 @@ public class ServiceBusTbCoreQueueFactory implements TbCoreQueueFactory {
}
@Override
public TbQueueConsumer<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> createToFirmwareStateServiceMsgConsumer() {
return new TbServiceBusConsumerTemplate<>(coreAdmin, serviceBusSettings, coreSettings.getFirmwareTopic(),
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToFirmwareStateServiceMsg.parseFrom(msg.getData()), msg.getHeaders()));
public TbQueueConsumer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgConsumer() {
return new TbServiceBusConsumerTemplate<>(coreAdmin, serviceBusSettings, coreSettings.getOtaPackageTopic(),
msg -> new TbProtoQueueMsg<>(msg.getKey(), ToOtaPackageStateServiceMsg.parseFrom(msg.getData()), msg.getHeaders()));
}
@Override
public TbQueueProducer<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> createToFirmwareStateServiceMsgProducer() {
return new TbServiceBusProducerTemplate<>(coreAdmin, serviceBusSettings, coreSettings.getFirmwareTopic());
public TbQueueProducer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgProducer() {
return new TbServiceBusProducerTemplate<>(coreAdmin, serviceBusSettings, coreSettings.getOtaPackageTopic());
}
@Override

6
common/queue/src/main/java/org/thingsboard/server/queue/provider/TbCoreQueueFactory.java

@ -16,7 +16,7 @@
package org.thingsboard.server.queue.provider;
import org.thingsboard.server.gen.js.JsInvokeProtos;
import org.thingsboard.server.gen.transport.TransportProtos.ToFirmwareStateServiceMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToOtaPackageStateServiceMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg;
@ -91,14 +91,14 @@ public interface TbCoreQueueFactory extends TbUsageStatsClientQueueFactory {
*
* @return
*/
TbQueueConsumer<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> createToFirmwareStateServiceMsgConsumer();
TbQueueConsumer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgConsumer();
/**
* Used to consume messages about firmware update notifications by TB Core Service
*
* @return
*/
TbQueueProducer<TbProtoQueueMsg<ToFirmwareStateServiceMsg>> createToFirmwareStateServiceMsgProducer();
TbQueueProducer<TbProtoQueueMsg<ToOtaPackageStateServiceMsg>> createToOtaPackageStateServiceMsgProducer();
/**
* Used to consume high priority messages by TB Core Service

4
common/queue/src/main/java/org/thingsboard/server/queue/provider/TbCoreQueueProducerProvider.java

@ -15,7 +15,6 @@
*/
package org.thingsboard.server.queue.provider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.stereotype.Service;
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg;
@ -25,11 +24,12 @@ import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToUsageStatsServiceMsg;
import org.thingsboard.server.queue.TbQueueProducer;
import org.thingsboard.server.queue.common.TbProtoQueueMsg;
import org.thingsboard.server.queue.util.TbCoreComponent;
import javax.annotation.PostConstruct;
@Service
@ConditionalOnExpression("'${service.type:null}'=='monolith' || '${service.type:null}'=='tb-core'")
@TbCoreComponent
public class TbCoreQueueProducerProvider implements TbQueueProducerProvider {
private final TbCoreQueueFactory tbQueueProvider;

4
common/queue/src/main/java/org/thingsboard/server/queue/settings/TbQueueCoreSettings.java

@ -26,8 +26,8 @@ public class TbQueueCoreSettings {
@Value("${queue.core.topic}")
private String topic;
@Value("${queue.core.firmware.topic:tb_firmware}")
private String firmwareTopic;
@Value("${queue.core.ota.topic:tb_ota_package}")
private String otaPackageTopic;
@Value("${queue.core.usage-stats-topic:tb_usage_stats}")
private String usageStatsTopic;

18
common/queue/src/main/proto/queue.proto

@ -388,7 +388,7 @@ enum ResponseStatus {
FAILURE = 3;
}
message GetFirmwareRequestMsg {
message GetOtaPackageRequestMsg {
int64 deviceIdMSB = 1;
int64 deviceIdLSB = 2;
int64 tenantIdMSB = 3;
@ -396,10 +396,10 @@ message GetFirmwareRequestMsg {
string type = 5;
}
message GetFirmwareResponseMsg {
message GetOtaPackageResponseMsg {
ResponseStatus responseStatus = 1;
int64 firmwareIdMSB = 2;
int64 firmwareIdLSB = 3;
int64 otaPackageIdMSB = 2;
int64 otaPackageIdLSB = 3;
string type = 4;
string title = 5;
string version = 6;
@ -627,7 +627,7 @@ message TransportApiRequestMsg {
ProvisionDeviceRequestMsg provisionDeviceRequestMsg = 7;
ValidateDeviceLwM2MCredentialsRequestMsg validateDeviceLwM2MCredentialsRequestMsg = 8;
GetResourceRequestMsg resourceRequestMsg = 9;
GetFirmwareRequestMsg firmwareRequestMsg = 10;
GetOtaPackageRequestMsg otaPackageRequestMsg = 10;
GetSnmpDevicesRequestMsg snmpDevicesRequestMsg = 11;
GetDeviceRequestMsg deviceRequestMsg = 12;
GetDeviceCredentialsRequestMsg deviceCredentialsRequestMsg = 13;
@ -642,7 +642,7 @@ message TransportApiResponseMsg {
GetSnmpDevicesResponseMsg snmpDevicesResponseMsg = 5;
LwM2MResponseMsg lwM2MResponseMsg = 6;
GetResourceResponseMsg resourceResponseMsg = 7;
GetFirmwareResponseMsg firmwareResponseMsg = 8;
GetOtaPackageResponseMsg otaPackageResponseMsg = 8;
GetDeviceResponseMsg deviceResponseMsg = 9;
GetDeviceCredentialsResponseMsg deviceCredentialsResponseMsg = 10;
}
@ -710,13 +710,13 @@ message ToUsageStatsServiceMsg {
int64 customerIdLSB = 7;
}
message ToFirmwareStateServiceMsg {
message ToOtaPackageStateServiceMsg {
int64 ts = 1;
int64 tenantIdMSB = 2;
int64 tenantIdLSB = 3;
int64 deviceIdMSB = 4;
int64 deviceIdLSB = 5;
int64 firmwareIdMSB = 6;
int64 firmwareIdLSB = 7;
int64 otaPackageIdMSB = 6;
int64 otaPackageIdLSB = 7;
string type = 8;
}

22
common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/CoapTransportResource.java

@ -44,7 +44,7 @@ import org.thingsboard.server.common.data.device.profile.DeviceProfileTransportC
import org.thingsboard.server.common.data.device.profile.JsonTransportPayloadConfiguration;
import org.thingsboard.server.common.data.device.profile.ProtoTransportPayloadConfiguration;
import org.thingsboard.server.common.data.device.profile.TransportPayloadTypeConfiguration;
import org.thingsboard.server.common.data.firmware.FirmwareType;
import org.thingsboard.server.common.data.ota.OtaPackageType;
import org.thingsboard.server.common.data.security.DeviceTokenCredentials;
import org.thingsboard.server.common.msg.session.FeatureType;
import org.thingsboard.server.common.msg.session.SessionMsgType;
@ -350,10 +350,10 @@ public class CoapTransportResource extends AbstractCoapTransportResource {
new CoapNoOpCallback(exchange));
break;
case GET_FIRMWARE_REQUEST:
getFirmwareCallback(sessionInfo, exchange, FirmwareType.FIRMWARE);
getOtaPackageCallback(sessionInfo, exchange, OtaPackageType.FIRMWARE);
break;
case GET_SOFTWARE_REQUEST:
getFirmwareCallback(sessionInfo, exchange, FirmwareType.SOFTWARE);
getOtaPackageCallback(sessionInfo, exchange, OtaPackageType.SOFTWARE);
break;
}
} catch (AdaptorException e) {
@ -366,14 +366,14 @@ public class CoapTransportResource extends AbstractCoapTransportResource {
return new UUID(sessionInfoProto.getSessionIdMSB(), sessionInfoProto.getSessionIdLSB());
}
private void getFirmwareCallback(TransportProtos.SessionInfoProto sessionInfo, CoapExchange exchange, FirmwareType firmwareType) {
TransportProtos.GetFirmwareRequestMsg requestMsg = TransportProtos.GetFirmwareRequestMsg.newBuilder()
private void getOtaPackageCallback(TransportProtos.SessionInfoProto sessionInfo, CoapExchange exchange, OtaPackageType firmwareType) {
TransportProtos.GetOtaPackageRequestMsg requestMsg = TransportProtos.GetOtaPackageRequestMsg.newBuilder()
.setTenantIdMSB(sessionInfo.getTenantIdMSB())
.setTenantIdLSB(sessionInfo.getTenantIdLSB())
.setDeviceIdMSB(sessionInfo.getDeviceIdMSB())
.setDeviceIdLSB(sessionInfo.getDeviceIdLSB())
.setType(firmwareType.name()).build();
transportContext.getTransportService().process(sessionInfo, requestMsg, new FirmwareCallback(exchange));
transportContext.getTransportService().process(sessionInfo, requestMsg, new OtaPackageCallback(exchange));
}
private TransportProtos.SessionInfoProto lookupAsyncSessionInfo(String token) {
@ -470,25 +470,25 @@ public class CoapTransportResource extends AbstractCoapTransportResource {
}
}
private class FirmwareCallback implements TransportServiceCallback<TransportProtos.GetFirmwareResponseMsg> {
private class OtaPackageCallback implements TransportServiceCallback<TransportProtos.GetOtaPackageResponseMsg> {
private final CoapExchange exchange;
FirmwareCallback(CoapExchange exchange) {
OtaPackageCallback(CoapExchange exchange) {
this.exchange = exchange;
}
@Override
public void onSuccess(TransportProtos.GetFirmwareResponseMsg msg) {
public void onSuccess(TransportProtos.GetOtaPackageResponseMsg msg) {
String title = exchange.getQueryParameter("title");
String version = exchange.getQueryParameter("version");
if (msg.getResponseStatus().equals(TransportProtos.ResponseStatus.SUCCESS)) {
if (msg.getTitle().equals(title) && msg.getVersion().equals(version)) {
String firmwareId = new UUID(msg.getFirmwareIdMSB(), msg.getFirmwareIdLSB()).toString();
String firmwareId = new UUID(msg.getOtaPackageIdMSB(), msg.getOtaPackageIdLSB()).toString();
String strChunkSize = exchange.getQueryParameter("size");
String strChunk = exchange.getQueryParameter("chunk");
int chunkSize = StringUtils.isEmpty(strChunkSize) ? 0 : Integer.parseInt(strChunkSize);
int chunk = StringUtils.isEmpty(strChunk) ? 0 : Integer.parseInt(strChunk);
exchange.respond(CoAP.ResponseCode.CONTENT, transportContext.getFirmwareDataCache().get(firmwareId, chunkSize, chunk));
exchange.respond(CoAP.ResponseCode.CONTENT, transportContext.getOtaPackageDataCache().get(firmwareId, chunkSize, chunk));
} else {
exchange.respond(CoAP.ResponseCode.BAD_REQUEST);
}

32
common/transport/http/src/main/java/org/thingsboard/server/transport/http/DeviceApiController.java

@ -34,7 +34,7 @@ import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.async.DeferredResult;
import org.thingsboard.server.common.data.DeviceTransportType;
import org.thingsboard.server.common.data.firmware.FirmwareType;
import org.thingsboard.server.common.data.ota.OtaPackageType;
import org.thingsboard.server.common.data.TbTransportService;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.transport.SessionMsgListener;
@ -213,7 +213,7 @@ public class DeviceApiController implements TbTransportService {
@RequestParam(value = "version") String version,
@RequestParam(value = "size", required = false, defaultValue = "0") int size,
@RequestParam(value = "chunk", required = false, defaultValue = "0") int chunk) {
return getFirmwareCallback(deviceToken, title, version, size, chunk, FirmwareType.FIRMWARE);
return getOtaPackageCallback(deviceToken, title, version, size, chunk, OtaPackageType.FIRMWARE);
}
@RequestMapping(value = "/{deviceToken}/software", method = RequestMethod.GET)
@ -222,7 +222,7 @@ public class DeviceApiController implements TbTransportService {
@RequestParam(value = "version") String version,
@RequestParam(value = "size", required = false, defaultValue = "0") int size,
@RequestParam(value = "chunk", required = false, defaultValue = "0") int chunk) {
return getFirmwareCallback(deviceToken, title, version, size, chunk, FirmwareType.SOFTWARE);
return getOtaPackageCallback(deviceToken, title, version, size, chunk, OtaPackageType.SOFTWARE);
}
@RequestMapping(value = "/provision", method = RequestMethod.POST)
@ -233,17 +233,17 @@ public class DeviceApiController implements TbTransportService {
return responseWriter;
}
private DeferredResult<ResponseEntity> getFirmwareCallback(String deviceToken, String title, String version, int size, int chunk, FirmwareType firmwareType) {
private DeferredResult<ResponseEntity> getOtaPackageCallback(String deviceToken, String title, String version, int size, int chunk, OtaPackageType firmwareType) {
DeferredResult<ResponseEntity> responseWriter = new DeferredResult<>();
transportContext.getTransportService().process(DeviceTransportType.DEFAULT, ValidateDeviceTokenRequestMsg.newBuilder().setToken(deviceToken).build(),
new DeviceAuthCallback(transportContext, responseWriter, sessionInfo -> {
TransportProtos.GetFirmwareRequestMsg requestMsg = TransportProtos.GetFirmwareRequestMsg.newBuilder()
TransportProtos.GetOtaPackageRequestMsg requestMsg = TransportProtos.GetOtaPackageRequestMsg.newBuilder()
.setTenantIdMSB(sessionInfo.getTenantIdMSB())
.setTenantIdLSB(sessionInfo.getTenantIdLSB())
.setDeviceIdMSB(sessionInfo.getDeviceIdMSB())
.setDeviceIdLSB(sessionInfo.getDeviceIdLSB())
.setType(firmwareType.name()).build();
transportContext.getTransportService().process(sessionInfo, requestMsg, new GetFirmwareCallback(responseWriter, title, version, size, chunk));
transportContext.getTransportService().process(sessionInfo, requestMsg, new GetOtaPackageCallback(responseWriter, title, version, size, chunk));
}));
return responseWriter;
}
@ -294,14 +294,14 @@ public class DeviceApiController implements TbTransportService {
}
}
private class GetFirmwareCallback implements TransportServiceCallback<TransportProtos.GetFirmwareResponseMsg> {
private class GetOtaPackageCallback implements TransportServiceCallback<TransportProtos.GetOtaPackageResponseMsg> {
private final DeferredResult<ResponseEntity> responseWriter;
private final String title;
private final String version;
private final int chuckSize;
private final int chuck;
GetFirmwareCallback(DeferredResult<ResponseEntity> responseWriter, String title, String version, int chuckSize, int chuck) {
GetOtaPackageCallback(DeferredResult<ResponseEntity> responseWriter, String title, String version, int chuckSize, int chuck) {
this.responseWriter = responseWriter;
this.title = title;
this.version = version;
@ -310,17 +310,17 @@ public class DeviceApiController implements TbTransportService {
}
@Override
public void onSuccess(TransportProtos.GetFirmwareResponseMsg firmwareResponseMsg) {
if (!TransportProtos.ResponseStatus.SUCCESS.equals(firmwareResponseMsg.getResponseStatus())) {
public void onSuccess(TransportProtos.GetOtaPackageResponseMsg otaPackageResponseMsg) {
if (!TransportProtos.ResponseStatus.SUCCESS.equals(otaPackageResponseMsg.getResponseStatus())) {
responseWriter.setResult(new ResponseEntity<>(HttpStatus.NOT_FOUND));
} else if (title.equals(firmwareResponseMsg.getTitle()) && version.equals(firmwareResponseMsg.getVersion())) {
String firmwareId = new UUID(firmwareResponseMsg.getFirmwareIdMSB(), firmwareResponseMsg.getFirmwareIdLSB()).toString();
ByteArrayResource resource = new ByteArrayResource(transportContext.getFirmwareDataCache().get(firmwareId, chuckSize, chuck));
} else if (title.equals(otaPackageResponseMsg.getTitle()) && version.equals(otaPackageResponseMsg.getVersion())) {
String otaPackageId = new UUID(otaPackageResponseMsg.getOtaPackageIdMSB(), otaPackageResponseMsg.getOtaPackageIdLSB()).toString();
ByteArrayResource resource = new ByteArrayResource(transportContext.getOtaPackageDataCache().get(otaPackageId, chuckSize, chuck));
ResponseEntity<ByteArrayResource> response = ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + firmwareResponseMsg.getFileName())
.header("x-filename", firmwareResponseMsg.getFileName())
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + otaPackageResponseMsg.getFileName())
.header("x-filename", otaPackageResponseMsg.getFileName())
.contentLength(resource.contentLength())
.contentType(parseMediaType(firmwareResponseMsg.getContentType()))
.contentType(parseMediaType(otaPackageResponseMsg.getContentType()))
.body(resource);
responseWriter.setResult(response);
} else {

150
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2MTransportMsgHandler.java

@ -39,13 +39,13 @@ import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.common.util.ThingsBoardExecutors;
import org.thingsboard.server.cache.firmware.FirmwareDataCache;
import org.thingsboard.server.cache.ota.OtaPackageDataCache;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.firmware.FirmwareKey;
import org.thingsboard.server.common.data.firmware.FirmwareType;
import org.thingsboard.server.common.data.firmware.FirmwareUtil;
import org.thingsboard.server.common.data.id.FirmwareId;
import org.thingsboard.server.common.data.ota.OtaPackageKey;
import org.thingsboard.server.common.data.ota.OtaPackageType;
import org.thingsboard.server.common.data.ota.OtaPackageUtil;
import org.thingsboard.server.common.data.id.OtaPackageId;
import org.thingsboard.server.common.transport.TransportService;
import org.thingsboard.server.common.transport.TransportServiceCallback;
import org.thingsboard.server.common.transport.adaptor.AdaptorException;
@ -87,8 +87,8 @@ import java.util.stream.Collectors;
import static org.eclipse.californium.core.coap.CoAP.ResponseCode.BAD_REQUEST;
import static org.eclipse.leshan.core.attributes.Attribute.OBJECT_VERSION;
import static org.thingsboard.server.common.data.firmware.FirmwareUpdateStatus.DOWNLOADED;
import static org.thingsboard.server.common.data.firmware.FirmwareUpdateStatus.UPDATING;
import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.DOWNLOADED;
import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.UPDATING;
import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_PATH;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportServerHelper.getValueFromKvProto;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.CLIENT_NOT_AUTHORIZED;
@ -132,7 +132,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
private final TransportService transportService;
private final LwM2mTransportContext context;
public final LwM2MTransportServerConfig config;
public final FirmwareDataCache firmwareDataCache;
public final OtaPackageDataCache otaPackageDataCache;
public final LwM2mTransportServerHelper helper;
private final LwM2MJsonAdaptor adaptor;
private final TbLwM2MDtlsSessionStore sessionStore;
@ -143,14 +143,14 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
public DefaultLwM2MTransportMsgHandler(TransportService transportService, LwM2MTransportServerConfig config, LwM2mTransportServerHelper helper,
LwM2mClientContext clientContext,
@Lazy LwM2mTransportRequest lwM2mTransportRequest,
FirmwareDataCache firmwareDataCache,
OtaPackageDataCache otaPackageDataCache,
LwM2mTransportContext context, LwM2MJsonAdaptor adaptor, TbLwM2MDtlsSessionStore sessionStore) {
this.transportService = transportService;
this.config = config;
this.helper = helper;
this.clientContext = clientContext;
this.lwM2mTransportRequest = lwM2mTransportRequest;
this.firmwareDataCache = firmwareDataCache;
this.otaPackageDataCache = otaPackageDataCache;
this.context = context;
this.adaptor = adaptor;
this.rpcSubscriptions = new ConcurrentHashMap<>();
@ -196,8 +196,8 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
.setSubscribeToRPC(TransportProtos.SubscribeToRPCMsg.newBuilder().build())
.build();
transportService.process(msg, null);
this.getInfoFirmwareUpdate(lwM2MClient);
this.getInfoSoftwareUpdate(lwM2MClient);
this.getInfoFirmwareUpdate(lwM2MClient, null);
this.getInfoSoftwareUpdate(lwM2MClient, null);
this.initLwM2mFromClientValue(registration, lwM2MClient);
this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client create after Registration", registration.getId());
} else {
@ -247,7 +247,6 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
* @param observations - !!! Warn: if have not finishing unReg, then this operation will be finished on next Client`s connect
*/
public void unReg(Registration registration, Collection<Observation> observations) {
log.error("Client unRegistration -> test", new RuntimeException());
unRegistrationExecutor.submit(() -> {
try {
this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client unRegistration", registration.getId());
@ -286,7 +285,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
@Override
public void setCancelObservationsAll(Registration registration) {
if (registration != null) {
lwM2mTransportRequest.sendAllRequest(registration, null, OBSERVE_CANCEL_ALL,
this.lwM2mTransportRequest.sendAllRequest(registration, null, OBSERVE_CANCEL_ALL,
null, null, this.config.getTimeout(), null);
}
}
@ -335,7 +334,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
READ, pathIdVer, value);
this.sendLogsToThingsboard(msg, registration.getId());
rpcRequest.setValueMsg(String.format("%s", value));
this.sentRpcRequest(rpcRequest, response.getCode().getName(), (String) value, LOG_LW2M_VALUE);
this.sentRpcResponse(rpcRequest, response.getCode().getName(), (String) value, LOG_LW2M_VALUE);
}
/**
@ -352,21 +351,22 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
@Override
public void onAttributeUpdate(AttributeUpdateNotificationMsg msg, TransportProtos.SessionInfoProto sessionInfo) {
LwM2mClient lwM2MClient = clientContext.getClient(sessionInfo);
if (msg.getSharedUpdatedCount() > 0) {
if (msg.getSharedUpdatedCount() > 0 && lwM2MClient != null) {
log.warn ("2) OnAttributeUpdate, SharedUpdatedList() [{}]", msg.getSharedUpdatedList());
msg.getSharedUpdatedList().forEach(tsKvProto -> {
String pathName = tsKvProto.getKv().getKey();
String pathIdVer = this.getPresentPathIntoProfile(sessionInfo, pathName);
Object valueNew = getValueFromKvProto(tsKvProto.getKv());
if ((FirmwareUtil.getAttributeKey(FirmwareType.FIRMWARE, FirmwareKey.VERSION).equals(pathName)
if ((OtaPackageUtil.getAttributeKey(OtaPackageType.FIRMWARE, OtaPackageKey.VERSION).equals(pathName)
&& (!valueNew.equals(lwM2MClient.getFwUpdate().getCurrentVersion())))
|| (FirmwareUtil.getAttributeKey(FirmwareType.FIRMWARE, FirmwareKey.TITLE).equals(pathName)
|| (OtaPackageUtil.getAttributeKey(OtaPackageType.FIRMWARE, OtaPackageKey.TITLE).equals(pathName)
&& (!valueNew.equals(lwM2MClient.getFwUpdate().getCurrentTitle())))) {
this.getInfoFirmwareUpdate(lwM2MClient);
} else if ((FirmwareUtil.getAttributeKey(FirmwareType.SOFTWARE, FirmwareKey.VERSION).equals(pathName)
this.getInfoFirmwareUpdate(lwM2MClient, null);
} else if ((OtaPackageUtil.getAttributeKey(OtaPackageType.SOFTWARE, OtaPackageKey.VERSION).equals(pathName)
&& (!valueNew.equals(lwM2MClient.getSwUpdate().getCurrentVersion())))
|| (FirmwareUtil.getAttributeKey(FirmwareType.SOFTWARE, FirmwareKey.TITLE).equals(pathName)
|| (OtaPackageUtil.getAttributeKey(OtaPackageType.SOFTWARE, OtaPackageKey.TITLE).equals(pathName)
&& (!valueNew.equals(lwM2MClient.getSwUpdate().getCurrentTitle())))) {
this.getInfoSoftwareUpdate(lwM2MClient);
this.getInfoSoftwareUpdate(lwM2MClient, null);
}
if (pathIdVer != null) {
ResourceModel resourceModel = lwM2MClient.getResourceModel(pathIdVer, this.config
@ -387,16 +387,19 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
}
});
} else if (msg.getSharedDeletedCount() > 0) {
} else if (msg.getSharedDeletedCount() > 0 && lwM2MClient != null) {
msg.getSharedUpdatedList().forEach(tsKvProto -> {
String pathName = tsKvProto.getKv().getKey();
Object valueNew = getValueFromKvProto(tsKvProto.getKv());
if (FirmwareUtil.getAttributeKey(FirmwareType.FIRMWARE, FirmwareKey.VERSION).equals(pathName) && !valueNew.equals(lwM2MClient.getFwUpdate().getCurrentVersion())) {
if (OtaPackageUtil.getAttributeKey(OtaPackageType.FIRMWARE, OtaPackageKey.VERSION).equals(pathName) && !valueNew.equals(lwM2MClient.getFwUpdate().getCurrentVersion())) {
lwM2MClient.getFwUpdate().setCurrentVersion((String) valueNew);
}
});
log.info("[{}] delete [{}] onAttributeUpdate", msg.getSharedDeletedList(), sessionInfo);
}
else if (lwM2MClient == null) {
log.error ("OnAttributeUpdate, lwM2MClient is null");
}
}
/**
@ -443,6 +446,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
public void onToDeviceRpcRequest(TransportProtos.ToDeviceRpcRequestMsg toDeviceRpcRequestMsg, SessionInfoProto sessionInfo) {
// #1
this.checkRpcRequestTimeout();
log.warn ("4) toDeviceRpcRequestMsg: [{}], sessionUUID: [{}]", toDeviceRpcRequestMsg, new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB()));
String bodyParams = StringUtils.trimToNull(toDeviceRpcRequestMsg.getParams()) != null ? toDeviceRpcRequestMsg.getParams() : "null";
LwM2mTypeOper lwM2mTypeOper = setValidTypeOper(toDeviceRpcRequestMsg.getMethodName());
UUID requestUUID = new UUID(toDeviceRpcRequestMsg.getRequestIdMSB(), toDeviceRpcRequestMsg.getRequestIdLSB());
@ -479,7 +483,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
rpcSubscriptionsToRemove.forEach(rpcSubscriptions::remove);
}
public void sentRpcRequest(Lwm2mClientRpcRequest rpcRequest, String requestCode, String msg, String typeMsg) {
public void sentRpcResponse(Lwm2mClientRpcRequest rpcRequest, String requestCode, String msg, String typeMsg) {
rpcRequest.setResponseCode(requestCode);
if (LOG_LW2M_ERROR.equals(typeMsg)) {
rpcRequest.setInfoMsg(null);
@ -502,6 +506,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
@Override
public void onToDeviceRpcResponse(TransportProtos.ToDeviceRpcResponseMsg toDeviceResponse, SessionInfoProto sessionInfo) {
log.warn ("5) onToDeviceRpcResponse: [{}], sessionUUID: [{}]", toDeviceResponse, new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB()));
transportService.process(sessionInfo, toDeviceResponse, null);
}
@ -882,10 +887,16 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
*/
private Object getResourceValueFormatKv(LwM2mClient lwM2MClient, String pathIdVer) {
LwM2mResource resourceValue = this.getResourceValueFromLwM2MClient(lwM2MClient, pathIdVer);
ResourceModel.Type currentType = resourceValue.getType();
ResourceModel.Type expectedType = this.helper.getResourceModelTypeEqualsKvProtoValueType(currentType, pathIdVer);
return this.converter.convertValue(resourceValue.getValue(), currentType, expectedType,
new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer)));
if (resourceValue != null) {
ResourceModel.Type currentType = resourceValue.getType();
ResourceModel.Type expectedType = this.helper.getResourceModelTypeEqualsKvProtoValueType(currentType, pathIdVer);
return this.converter.convertValue(resourceValue.getValue(), currentType, expectedType,
new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer)));
}
else {
return null;
}
}
/**
@ -1246,22 +1257,28 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
*/
public void updateAttributeFromThingsboard(List<TransportProtos.TsKvProto> tsKvProtos, TransportProtos.SessionInfoProto sessionInfo) {
LwM2mClient lwM2MClient = clientContext.getClient(sessionInfo);
tsKvProtos.forEach(tsKvProto -> {
String pathIdVer = this.getPresentPathIntoProfile(sessionInfo, tsKvProto.getKv().getKey());
if (pathIdVer != null) {
// #1.1
if (lwM2MClient.getDelayedRequests().containsKey(pathIdVer) && tsKvProto.getTs() > lwM2MClient.getDelayedRequests().get(pathIdVer).getTs()) {
lwM2MClient.getDelayedRequests().put(pathIdVer, tsKvProto);
} else if (!lwM2MClient.getDelayedRequests().containsKey(pathIdVer)) {
lwM2MClient.getDelayedRequests().put(pathIdVer, tsKvProto);
if (lwM2MClient != null) {
log.warn("1) UpdateAttributeFromThingsboard, tsKvProtos [{}]", tsKvProtos);
tsKvProtos.forEach(tsKvProto -> {
String pathIdVer = this.getPresentPathIntoProfile(sessionInfo, tsKvProto.getKv().getKey());
if (pathIdVer != null) {
// #1.1
if (lwM2MClient.getDelayedRequests().containsKey(pathIdVer) && tsKvProto.getTs() > lwM2MClient.getDelayedRequests().get(pathIdVer).getTs()) {
lwM2MClient.getDelayedRequests().put(pathIdVer, tsKvProto);
} else if (!lwM2MClient.getDelayedRequests().containsKey(pathIdVer)) {
lwM2MClient.getDelayedRequests().put(pathIdVer, tsKvProto);
}
}
}
});
// #2.1
lwM2MClient.getDelayedRequests().forEach((pathIdVer, tsKvProto) -> {
this.updateResourcesValueToClient(lwM2MClient, this.getResourceValueFormatKv(lwM2MClient, pathIdVer),
getValueFromKvProto(tsKvProto.getKv()), pathIdVer);
});
});
// #2.1
lwM2MClient.getDelayedRequests().forEach((pathIdVer, tsKvProto) -> {
this.updateResourcesValueToClient(lwM2MClient, this.getResourceValueFormatKv(lwM2MClient, pathIdVer),
getValueFromKvProto(tsKvProto.getKv()), pathIdVer);
});
}
else {
log.error("UpdateAttributeFromThingsboard, lwM2MClient is null");
}
}
/**
@ -1340,22 +1357,30 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
}
}
public void getInfoFirmwareUpdate(LwM2mClient lwM2MClient) {
public void getInfoFirmwareUpdate(LwM2mClient lwM2MClient, Lwm2mClientRpcRequest rpcRequest) {
if (lwM2MClient.getRegistration().getSupportedVersion(FW_ID) != null) {
SessionInfoProto sessionInfo = this.getSessionInfoOrCloseSession(lwM2MClient);
if (sessionInfo != null) {
transportService.process(sessionInfo, createFirmwareRequestMsg(sessionInfo, FirmwareType.FIRMWARE.name()),
DefaultLwM2MTransportMsgHandler handler = this;
this.transportService.process(sessionInfo, createOtaPackageRequestMsg(sessionInfo, OtaPackageType.FIRMWARE.name()),
new TransportServiceCallback<>() {
@Override
public void onSuccess(TransportProtos.GetFirmwareResponseMsg response) {
public void onSuccess(TransportProtos.GetOtaPackageResponseMsg response) {
if (TransportProtos.ResponseStatus.SUCCESS.equals(response.getResponseStatus())
&& response.getType().equals(FirmwareType.FIRMWARE.name())) {
&& response.getType().equals(OtaPackageType.FIRMWARE.name())) {
log.warn ("7) firmware start with ver: [{}]", response.getVersion());
lwM2MClient.getFwUpdate().setRpcRequest(rpcRequest);
lwM2MClient.getFwUpdate().setCurrentVersion(response.getVersion());
lwM2MClient.getFwUpdate().setCurrentTitle(response.getTitle());
lwM2MClient.getFwUpdate().setCurrentId(new FirmwareId(new UUID(response.getFirmwareIdMSB(), response.getFirmwareIdLSB())).getId());
lwM2MClient.getFwUpdate().sendReadObserveInfo(lwM2mTransportRequest);
lwM2MClient.getFwUpdate().setCurrentId(new OtaPackageId(new UUID(response.getOtaPackageIdMSB(), response.getOtaPackageIdLSB())).getId());
if (rpcRequest == null) {
lwM2MClient.getFwUpdate().sendReadObserveInfo(lwM2mTransportRequest);
}
else {
lwM2MClient.getFwUpdate().writeFwSwWare(handler, lwM2mTransportRequest);
}
} else {
log.trace("Firmware [{}] [{}]", lwM2MClient.getDeviceName(), response.getResponseStatus().toString());
log.trace("OtaPackage [{}] [{}]", lwM2MClient.getDeviceName(), response.getResponseStatus().toString());
}
}
@ -1368,21 +1393,28 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
}
}
public void getInfoSoftwareUpdate(LwM2mClient lwM2MClient) {
public void getInfoSoftwareUpdate(LwM2mClient lwM2MClient, Lwm2mClientRpcRequest rpcRequest) {
if (lwM2MClient.getRegistration().getSupportedVersion(SW_ID) != null) {
SessionInfoProto sessionInfo = this.getSessionInfoOrCloseSession(lwM2MClient);
if (sessionInfo != null) {
DefaultLwM2MTransportMsgHandler serviceImpl = this;
transportService.process(sessionInfo, createFirmwareRequestMsg(sessionInfo, FirmwareType.SOFTWARE.name()),
DefaultLwM2MTransportMsgHandler handler = this;
transportService.process(sessionInfo, createOtaPackageRequestMsg(sessionInfo, OtaPackageType.SOFTWARE.name()),
new TransportServiceCallback<>() {
@Override
public void onSuccess(TransportProtos.GetFirmwareResponseMsg response) {
public void onSuccess(TransportProtos.GetOtaPackageResponseMsg response) {
if (TransportProtos.ResponseStatus.SUCCESS.equals(response.getResponseStatus())
&& response.getType().equals(FirmwareType.SOFTWARE.name())) {
&& response.getType().equals(OtaPackageType.SOFTWARE.name())) {
lwM2MClient.getSwUpdate().setRpcRequest(rpcRequest);
lwM2MClient.getSwUpdate().setCurrentVersion(response.getVersion());
lwM2MClient.getSwUpdate().setCurrentTitle(response.getTitle());
lwM2MClient.getSwUpdate().setCurrentId(new FirmwareId(new UUID(response.getFirmwareIdMSB(), response.getFirmwareIdLSB())).getId());
lwM2MClient.getSwUpdate().setCurrentId(new OtaPackageId(new UUID(response.getOtaPackageIdMSB(), response.getOtaPackageIdLSB())).getId());
lwM2MClient.getSwUpdate().sendReadObserveInfo(lwM2mTransportRequest);
if (rpcRequest == null) {
lwM2MClient.getSwUpdate().sendReadObserveInfo(lwM2mTransportRequest);
}
else {
lwM2MClient.getSwUpdate().writeFwSwWare(handler, lwM2mTransportRequest);
}
} else {
log.trace("Software [{}] [{}]", lwM2MClient.getDeviceName(), response.getResponseStatus().toString());
}
@ -1397,8 +1429,8 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
}
}
private TransportProtos.GetFirmwareRequestMsg createFirmwareRequestMsg(SessionInfoProto sessionInfo, String nameFwSW) {
return TransportProtos.GetFirmwareRequestMsg.newBuilder()
private TransportProtos.GetOtaPackageRequestMsg createOtaPackageRequestMsg(SessionInfoProto sessionInfo, String nameFwSW) {
return TransportProtos.GetOtaPackageRequestMsg.newBuilder()
.setDeviceIdMSB(sessionInfo.getDeviceIdMSB())
.setDeviceIdLSB(sessionInfo.getDeviceIdLSB())
.setTenantIdMSB(sessionInfo.getTenantIdMSB())

152
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportRequest.java

@ -71,8 +71,8 @@ import java.util.stream.Collectors;
import static org.eclipse.californium.core.coap.CoAP.ResponseCode.CONTENT;
import static org.eclipse.leshan.core.ResponseCode.BAD_REQUEST;
import static org.eclipse.leshan.core.ResponseCode.NOT_FOUND;
import static org.thingsboard.server.common.data.firmware.FirmwareUpdateStatus.DOWNLOADED;
import static org.thingsboard.server.common.data.firmware.FirmwareUpdateStatus.FAILED;
import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.DOWNLOADED;
import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.FAILED;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportServerHelper.getContentFormatByResourceModelType;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.DEFAULT_TIMEOUT;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_PACKAGE_ID;
@ -82,10 +82,8 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.L
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_VALUE;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.DISCOVER;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.DISCOVER_ALL;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.EXECUTE;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.OBSERVE_CANCEL;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.OBSERVE_CANCEL_ALL;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.OBSERVE_READ_ALL;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.WRITE_ATTRIBUTES;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.WRITE_REPLACE;
@ -134,7 +132,7 @@ public class LwM2mTransportRequest {
ContentFormat contentFormat = contentFormatName != null ? ContentFormat.fromName(contentFormatName.toUpperCase()) : ContentFormat.DEFAULT;
LwM2mClient lwM2MClient = this.lwM2mClientContext.getOrRegister(registration);
LwM2mPath resultIds = target != null ? new LwM2mPath(target) : null;
if (!OBSERVE_READ_ALL.name().equals(typeOper.name()) && resultIds != null && registration != null && resultIds.getObjectId() >= 0 && lwM2MClient != null) {
if (!OBSERVE_CANCEL.name().equals(typeOper.name()) && resultIds != null && registration != null && resultIds.getObjectId() >= 0 && lwM2MClient != null) {
if (lwM2MClient.isValidObjectVersion(targetIdVer)) {
timeoutInMs = timeoutInMs > 0 ? timeoutInMs : DEFAULT_TIMEOUT;
DownlinkRequest request = createRequest(registration, lwM2MClient, typeOper, contentFormat, target,
@ -153,47 +151,66 @@ public class LwM2mTransportRequest {
} else if (WRITE_UPDATE.name().equals(typeOper.name())) {
if (lwm2mClientRpcRequest != null) {
String errorMsg = String.format("Path %s params is not valid", targetIdVer);
handler.sentRpcRequest(lwm2mClientRpcRequest, BAD_REQUEST.getName(), errorMsg, LOG_LW2M_ERROR);
handler.sentRpcResponse(lwm2mClientRpcRequest, BAD_REQUEST.getName(), errorMsg, LOG_LW2M_ERROR);
}
} else if (WRITE_REPLACE.name().equals(typeOper.name()) || EXECUTE.name().equals(typeOper.name())) {
if (lwm2mClientRpcRequest != null) {
String errorMsg = String.format("Path %s object model is absent", targetIdVer);
handler.sentRpcRequest(lwm2mClientRpcRequest, BAD_REQUEST.getName(), errorMsg, LOG_LW2M_ERROR);
handler.sentRpcResponse(lwm2mClientRpcRequest, BAD_REQUEST.getName(), errorMsg, LOG_LW2M_ERROR);
}
} else if (!OBSERVE_CANCEL.name().equals(typeOper.name())) {
log.error("[{}], [{}] - [{}] error SendRequest", registration.getEndpoint(), typeOper.name(), targetIdVer);
if (lwm2mClientRpcRequest != null) {
ResourceModel resourceModel = lwM2MClient.getResourceModel(targetIdVer, this.config.getModelProvider());
String errorMsg = resourceModel == null ? String.format("Path %s not found in object version", targetIdVer) : "SendRequest - null";
this.handler.sentRpcRequest(lwm2mClientRpcRequest, NOT_FOUND.getName(), errorMsg, LOG_LW2M_ERROR);
this.handler.sentRpcResponse(lwm2mClientRpcRequest, NOT_FOUND.getName(), errorMsg, LOG_LW2M_ERROR);
}
}
} else if (lwm2mClientRpcRequest != null) {
String errorMsg = String.format("Path %s not found in object version", targetIdVer);
this.handler.sentRpcRequest(lwm2mClientRpcRequest, NOT_FOUND.getName(), errorMsg, LOG_LW2M_ERROR);
this.handler.sentRpcResponse(lwm2mClientRpcRequest, NOT_FOUND.getName(), errorMsg, LOG_LW2M_ERROR);
}
} else if (OBSERVE_READ_ALL.name().equals(typeOper.name()) || DISCOVER_ALL.name().equals(typeOper.name())) {
Set<String> paths;
if (OBSERVE_READ_ALL.name().equals(typeOper.name())) {
Set<Observation> observations = context.getServer().getObservationService().getObservations(registration);
paths = observations.stream().map(observation -> observation.getPath().toString()).collect(Collectors.toUnmodifiableSet());
} else {
assert registration != null;
Link[] objectLinks = registration.getSortedObjectLinks();
paths = Arrays.stream(objectLinks).map(Link::toString).collect(Collectors.toUnmodifiableSet());
}
String msg = String.format("%s: type operation %s paths - %s", LOG_LW2M_INFO,
typeOper.name(), paths);
this.handler.sendLogsToThingsboard(msg, registration.getId());
if (lwm2mClientRpcRequest != null) {
String valueMsg = String.format("Paths - %s", paths);
this.handler.sentRpcRequest(lwm2mClientRpcRequest, CONTENT.name(), valueMsg, LOG_LW2M_VALUE);
} else {
switch (typeOper) {
case OBSERVE_READ_ALL:
case DISCOVER_ALL:
Set<String> paths;
if (OBSERVE_READ_ALL.name().equals(typeOper.name())) {
Set<Observation> observations = context.getServer().getObservationService().getObservations(registration);
paths = observations.stream().map(observation -> observation.getPath().toString()).collect(Collectors.toUnmodifiableSet());
} else {
assert registration != null;
Link[] objectLinks = registration.getSortedObjectLinks();
paths = Arrays.stream(objectLinks).map(Link::toString).collect(Collectors.toUnmodifiableSet());
}
String msg = String.format("%s: type operation %s paths - %s", LOG_LW2M_INFO,
typeOper.name(), paths);
this.handler.sendLogsToThingsboard(msg, registration.getId());
if (lwm2mClientRpcRequest != null) {
String valueMsg = String.format("Paths - %s", paths);
this.handler.sentRpcResponse(lwm2mClientRpcRequest, CONTENT.name(), valueMsg, LOG_LW2M_VALUE);
}
break;
case OBSERVE_CANCEL:
case OBSERVE_CANCEL_ALL:
int observeCancelCnt = 0;
String observeCancelMsg = null;
if (OBSERVE_CANCEL.name().equals(typeOper)) {
observeCancelCnt = context.getServer().getObservationService().cancelObservations(registration, target);
observeCancelMsg = String.format("%s: type operation %s paths: %s count: %d", LOG_LW2M_INFO,
OBSERVE_CANCEL.name(), target, observeCancelCnt);
} else {
observeCancelCnt = context.getServer().getObservationService().cancelObservations(registration);
observeCancelMsg = String.format("%s: type operation %s paths: All count: %d", LOG_LW2M_INFO,
OBSERVE_CANCEL.name(), observeCancelCnt);
}
this.afterObserveCancel(registration, observeCancelCnt, observeCancelMsg, lwm2mClientRpcRequest);
break;
// lwm2mClientRpcRequest != null
case FW_UPDATE:
this.handler.getInfoFirmwareUpdate(lwM2MClient, lwm2mClientRpcRequest);
break;
}
} else if (OBSERVE_CANCEL_ALL.name().equals(typeOper.name())) {
int observeCancelCnt = context.getServer().getObservationService().cancelObservations(registration);
String observeCancelMsgAll = String.format("%s: type operation %s paths: All count: %d", LOG_LW2M_INFO,
OBSERVE_CANCEL.name(), observeCancelCnt);
this.afterObserveCancel(registration, observeCancelCnt, observeCancelMsgAll, lwm2mClientRpcRequest);
}
} catch (Exception e) {
String msg = String.format("%s: type operation %s %s", LOG_LW2M_ERROR,
@ -201,7 +218,7 @@ public class LwM2mTransportRequest {
handler.sendLogsToThingsboard(msg, registration.getId());
if (lwm2mClientRpcRequest != null) {
String errorMsg = String.format("Path %s type operation %s %s", targetIdVer, typeOper.name(), e.getMessage());
handler.sentRpcRequest(lwm2mClientRpcRequest, NOT_FOUND.getName(), errorMsg, LOG_LW2M_ERROR);
handler.sentRpcResponse(lwm2mClientRpcRequest, NOT_FOUND.getName(), errorMsg, LOG_LW2M_ERROR);
}
}
}
@ -234,17 +251,6 @@ public class LwM2mTransportRequest {
request = new ObserveRequest(contentFormat, resultIds.getObjectId());
}
break;
case OBSERVE_CANCEL:
/*
lwM2MTransportRequest.sendAllRequest(lwServer, registration, path, POST_TYPE_OPER_OBSERVE_CANCEL, null, null, null, null, context.getTimeout());
At server side this will not remove the observation from the observation store, to do it you need to use
{@code ObservationService#cancelObservation()}
*/
int observeCancelCnt = context.getServer().getObservationService().cancelObservations(registration, target);
String observeCancelMsg = String.format("%s: type operation %s paths: %s count: %d", LOG_LW2M_INFO,
OBSERVE_CANCEL.name(), target, observeCancelCnt);
this.afterObserveCancel(registration, observeCancelCnt, observeCancelMsg, rpcRequest);
break;
case EXECUTE:
ResourceModel resourceModelExecute = lwM2MClient.getResourceModel(targetIdVer, this.config.getModelProvider());
if (resourceModelExecute != null) {
@ -343,7 +349,7 @@ public class LwM2mTransportRequest {
}
/** Not Found */
if (rpcRequest != null) {
handler.sentRpcRequest(rpcRequest, response.getCode().getName(), response.getErrorMessage(), LOG_LW2M_ERROR);
handler.sentRpcResponse(rpcRequest, response.getCode().getName(), response.getErrorMessage(), LOG_LW2M_ERROR);
}
/** Not Found
set setClient_fw_info... = empty
@ -385,7 +391,7 @@ public class LwM2mTransportRequest {
handler.sendLogsToThingsboard(msg, registration.getId());
log.error("[{}] [{}] - [{}] error SendRequest", request.getClass().getName().toString(), request.getPath().toString(), e.toString());
if (rpcRequest != null) {
handler.sentRpcRequest(rpcRequest, CoAP.CodeClass.ERROR_RESPONSE.name(), e.getMessage(), LOG_LW2M_ERROR);
handler.sentRpcResponse(rpcRequest, CoAP.CodeClass.ERROR_RESPONSE.name(), e.getMessage(), LOG_LW2M_ERROR);
}
});
}
@ -431,7 +437,7 @@ public class LwM2mTransportRequest {
log.error("Path: [{}] type: [{}] value: [{}] errorMsg: [{}]]", patn, type, value, e.toString());
if (rpcRequest != null) {
String errorMsg = String.format("NumberFormatException: Resource path - %s type - %s value - %s", patn, type, value);
handler.sentRpcRequest(rpcRequest, BAD_REQUEST.getName(), errorMsg, LOG_LW2M_ERROR);
handler.sentRpcResponse(rpcRequest, BAD_REQUEST.getName(), errorMsg, LOG_LW2M_ERROR);
}
return null;
}
@ -462,44 +468,48 @@ public class LwM2mTransportRequest {
if (response instanceof ReadResponse) {
handler.onUpdateValueAfterReadResponse(registration, pathIdVer, (ReadResponse) response, rpcRequest);
} else if (response instanceof DeleteResponse) {
log.warn("[{}] Path [{}] DeleteResponse 5_Send", pathIdVer, response);
log.warn("11) [{}] Path [{}] DeleteResponse", pathIdVer, response);
if (rpcRequest != null) {
rpcRequest.setInfoMsg(null);
handler.sentRpcResponse(rpcRequest, response.getCode().getName(), null, null);
}
} else if (response instanceof DiscoverResponse) {
String discoverValue = Link.serialize(((DiscoverResponse)response).getObjectLinks());
String discoverValue = Link.serialize(((DiscoverResponse) response).getObjectLinks());
msgLog = String.format("%s: type operation: %s path: %s value: %s",
LOG_LW2M_INFO, DISCOVER.name(), request.getPath().toString(), discoverValue);
handler.sendLogsToThingsboard(msgLog, registration.getId());
log.warn("DiscoverResponse: [{}]", (DiscoverResponse) response);
if (rpcRequest != null) {
handler.sentRpcRequest(rpcRequest, response.getCode().getName(), discoverValue, LOG_LW2M_VALUE);
handler.sentRpcResponse(rpcRequest, response.getCode().getName(), discoverValue, LOG_LW2M_VALUE);
}
} else if (response instanceof ExecuteResponse) {
log.warn("[{}] Path [{}] ExecuteResponse 7_Send", pathIdVer, response);
msgLog = String.format("%s: type operation: %s path: %s",
LOG_LW2M_INFO, EXECUTE.name(), request.getPath().toString());
log.warn("9) [{}] ", msgLog);
handler.sendLogsToThingsboard(msgLog, registration.getId());
if (rpcRequest != null) {
msgLog = String.format("Start %s path: %S. Preparation finished: %s", EXECUTE.name(), path, rpcRequest.getInfoMsg());
rpcRequest.setInfoMsg(msgLog);
handler.sentRpcResponse(rpcRequest, response.getCode().getName(), path, LOG_LW2M_INFO);
}
} else if (response instanceof WriteAttributesResponse) {
msgLog = String.format("%s: type operation: %s path: %s value: %s",
LOG_LW2M_INFO, WRITE_ATTRIBUTES.name(), request.getPath().toString(), ((WriteAttributesRequest) request).getAttributes().toString());
handler.sendLogsToThingsboard(msgLog, registration.getId());
log.warn("[{}] Path [{}] WriteAttributesResponse 8_Send", pathIdVer, response);
log.warn("12) [{}] Path [{}] WriteAttributesResponse", pathIdVer, response);
if (rpcRequest != null) {
handler.sentRpcRequest(rpcRequest, response.getCode().getName(), response.toString(), LOG_LW2M_VALUE);
handler.sentRpcResponse(rpcRequest, response.getCode().getName(), response.toString(), LOG_LW2M_VALUE);
}
} else if (response instanceof WriteResponse) {
log.warn("[{}] Path [{}] WriteResponse 9_Send", pathIdVer, response);
this.infoWriteResponse(registration, response, request);
msgLog = String.format("Type operation: Write path: %s", pathIdVer);
log.warn("10) [{}] response: [{}]", msgLog, response);
this.infoWriteResponse(registration, response, request, rpcRequest);
handler.onWriteResponseOk(registration, pathIdVer, (WriteRequest) request);
}
if (rpcRequest != null) {
if (response instanceof ExecuteResponse
|| response instanceof WriteAttributesResponse
|| response instanceof DeleteResponse) {
rpcRequest.setInfoMsg(null);
handler.sentRpcRequest(rpcRequest, response.getCode().getName(), null, null);
} else if (response instanceof WriteResponse) {
handler.sentRpcRequest(rpcRequest, response.getCode().getName(), null, LOG_LW2M_INFO);
}
}
}
private void infoWriteResponse(Registration registration, LwM2mResponse response, DownlinkRequest request) {
private void infoWriteResponse(Registration registration, LwM2mResponse response, DownlinkRequest request, Lwm2mClientRpcRequest rpcRequest) {
try {
LwM2mNode node = ((WriteRequest) request).getNode();
String msg = null;
@ -517,12 +527,12 @@ public class LwM2mTransportRequest {
if (singleResource.getType() == ResourceModel.Type.STRING) {
valueLength = ((String) singleResource.getValue()).length();
value = ((String) singleResource.getValue())
.substring(Math.min(valueLength, config.getLogMaxLength()));
.substring(Math.min(valueLength, config.getLogMaxLength())).trim();
} else {
valueLength = ((byte[]) singleResource.getValue()).length;
value = new String(Arrays.copyOf(((byte[]) singleResource.getValue()),
Math.min(valueLength, config.getLogMaxLength())));
Math.min(valueLength, config.getLogMaxLength()))).trim();
}
value = valueLength > config.getLogMaxLength() ? value + "..." : value;
msg = String.format("%s: Update finished successfully: Lwm2m code - %d Resource path: %s length: %s value: %s",
@ -538,6 +548,12 @@ public class LwM2mTransportRequest {
handler.sendLogsToThingsboard(msg, registration.getId());
if (request.getPath().toString().equals(FW_PACKAGE_ID) || request.getPath().toString().equals(SW_PACKAGE_ID)) {
this.afterWriteSuccessFwSwUpdate(registration, request);
if (rpcRequest != null) {
rpcRequest.setInfoMsg(msg);
}
}
else if (rpcRequest != null) {
handler.sentRpcResponse(rpcRequest, response.getCode().getName(), msg, LOG_LW2M_INFO);
}
}
} catch (Exception e) {
@ -558,7 +574,7 @@ public class LwM2mTransportRequest {
}
if (request.getPath().toString().equals(SW_PACKAGE_ID) && lwM2MClient.getSwUpdate() != null) {
lwM2MClient.getSwUpdate().setStateUpdate(DOWNLOADED.name());
lwM2MClient.getSwUpdate().sendLogs(this.handler,WRITE_REPLACE.name(), LOG_LW2M_INFO, null);
lwM2MClient.getSwUpdate().sendLogs(this.handler, WRITE_REPLACE.name(), LOG_LW2M_INFO, null);
}
}
@ -592,7 +608,7 @@ public class LwM2mTransportRequest {
log.warn("[{}]", observeCancelMsg);
if (rpcRequest != null) {
rpcRequest.setInfoMsg(String.format("Count: %d", observeCancelCnt));
handler.sentRpcRequest(rpcRequest, CONTENT.name(), null, LOG_LW2M_INFO);
handler.sentRpcResponse(rpcRequest, CONTENT.name(), null, LOG_LW2M_INFO);
}
}
}

11
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServerHelper.java

@ -53,6 +53,8 @@ import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import static org.thingsboard.server.gen.transport.TransportProtos.KeyValueType.BOOLEAN_V;
@ -64,6 +66,13 @@ public class LwM2mTransportServerHelper {
private final LwM2mTransportContext context;
private final LwM2MJsonAdaptor adaptor;
private final AtomicInteger atomicTs = new AtomicInteger(0);
public long getTS() {
int addTs = atomicTs.getAndIncrement() >= 1000 ? atomicTs.getAndSet(0) : atomicTs.get();
return TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()) * 1000L + addTs;
}
/**
* send to Thingsboard Attribute || Telemetry
@ -96,7 +105,7 @@ public class LwM2mTransportServerHelper {
public void sendParametersOnThingsboardTelemetry(List<TransportProtos.KeyValueProto> result, SessionInfoProto sessionInfo) {
PostTelemetryMsg.Builder request = PostTelemetryMsg.newBuilder();
TransportProtos.TsKvListProto.Builder builder = TransportProtos.TsKvListProto.newBuilder();
builder.setTs(System.currentTimeMillis());
builder.setTs(this.getTS());
builder.addAllKv(result);
request.addTsKvList(builder.build());
PostTelemetryMsg postTelemetryMsg = request.build();

53
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportUtil.java

@ -43,10 +43,10 @@ import org.eclipse.leshan.server.registration.Registration;
import org.nustaq.serialization.FSTConfiguration;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration;
import org.thingsboard.server.common.data.firmware.FirmwareKey;
import org.thingsboard.server.common.data.firmware.FirmwareType;
import org.thingsboard.server.common.data.firmware.FirmwareUpdateStatus;
import org.thingsboard.server.common.data.firmware.FirmwareUtil;
import org.thingsboard.server.common.data.ota.OtaPackageKey;
import org.thingsboard.server.common.data.ota.OtaPackageType;
import org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus;
import org.thingsboard.server.common.data.ota.OtaPackageUtil;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.transport.TransportServiceCallback;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
@ -77,12 +77,12 @@ import static org.eclipse.leshan.core.model.ResourceModel.Type.OBJLNK;
import static org.eclipse.leshan.core.model.ResourceModel.Type.OPAQUE;
import static org.eclipse.leshan.core.model.ResourceModel.Type.STRING;
import static org.eclipse.leshan.core.model.ResourceModel.Type.TIME;
import static org.thingsboard.server.common.data.firmware.FirmwareUpdateStatus.DOWNLOADED;
import static org.thingsboard.server.common.data.firmware.FirmwareUpdateStatus.DOWNLOADING;
import static org.thingsboard.server.common.data.firmware.FirmwareUpdateStatus.FAILED;
import static org.thingsboard.server.common.data.firmware.FirmwareUpdateStatus.UPDATED;
import static org.thingsboard.server.common.data.firmware.FirmwareUpdateStatus.UPDATING;
import static org.thingsboard.server.common.data.firmware.FirmwareUpdateStatus.VERIFIED;
import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.DOWNLOADED;
import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.DOWNLOADING;
import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.FAILED;
import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.UPDATED;
import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.UPDATING;
import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.VERIFIED;
import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_KEY;
import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_PATH;
@ -139,7 +139,7 @@ public class LwM2mTransportUtil {
public static final String ERROR_KEY = "error";
public static final String METHOD_KEY = "methodName";
// FirmWare
// Firmware
public static final String FW_UPDATE = "Firmware update";
public static final Integer FW_ID = 5;
// Package W
@ -155,7 +155,7 @@ public class LwM2mTransportUtil {
// Update E
public static final String FW_UPDATE_ID = "/5/0/2";
// SoftWare
// Software
public static final String SW_UPDATE = "Software update";
public static final Integer SW_ID = 9;
// Package W
@ -229,11 +229,12 @@ public class LwM2mTransportUtil {
*/
WRITE_UPDATE(9, "WriteUpdate"),
WRITE_ATTRIBUTES(10, "WriteAttributes"),
DELETE(11, "Delete");
DELETE(11, "Delete"),
// only for RPC
FW_UPDATE(12,"FirmwareUpdate");
// FW_READ_INFO(12, "FirmwareReadInfo"),
// FW_UPDATE(13, "FirmwareUpdate"),
// SW_READ_INFO(15, "SoftwareReadInfo"),
// SW_UPDATE(16, "SoftwareUpdate"),
// SW_UNINSTALL(18, "SoftwareUninstall");
@ -354,7 +355,7 @@ public class LwM2mTransportUtil {
* FirmwareUpdateStatus {
* DOWNLOADING, DOWNLOADED, VERIFIED, UPDATING, UPDATED, FAILED
*/
public static FirmwareUpdateStatus EqualsFwSateToFirmwareUpdateStatus(StateFw stateFw, UpdateResultFw updateResultFw) {
public static OtaPackageUpdateStatus EqualsFwSateToFirmwareUpdateStatus(StateFw stateFw, UpdateResultFw updateResultFw) {
switch (updateResultFw) {
case INITIAL:
switch (stateFw) {
@ -500,7 +501,7 @@ public class LwM2mTransportUtil {
* FirmwareUpdateStatus {
* DOWNLOADING, DOWNLOADED, VERIFIED, UPDATING, UPDATED, FAILED
*/
public static FirmwareUpdateStatus EqualsSwSateToFirmwareUpdateStatus(UpdateStateSw updateStateSw, UpdateResultSw updateResultSw) {
public static OtaPackageUpdateStatus EqualsSwSateToFirmwareUpdateStatus(UpdateStateSw updateStateSw, UpdateResultSw updateResultSw) {
switch (updateResultSw) {
case INITIAL:
switch (updateStateSw) {
@ -932,15 +933,15 @@ public class LwM2mTransportUtil {
}
public static boolean isFwSwWords (String pathName) {
return FirmwareUtil.getAttributeKey(FirmwareType.FIRMWARE, FirmwareKey.VERSION).equals(pathName)
|| FirmwareUtil.getAttributeKey(FirmwareType.FIRMWARE, FirmwareKey.TITLE).equals(pathName)
|| FirmwareUtil.getAttributeKey(FirmwareType.FIRMWARE, FirmwareKey.CHECKSUM).equals(pathName)
|| FirmwareUtil.getAttributeKey(FirmwareType.FIRMWARE, FirmwareKey.CHECKSUM_ALGORITHM).equals(pathName)
|| FirmwareUtil.getAttributeKey(FirmwareType.FIRMWARE, FirmwareKey.SIZE).equals(pathName)
|| FirmwareUtil.getAttributeKey(FirmwareType.SOFTWARE, FirmwareKey.VERSION).equals(pathName)
|| FirmwareUtil.getAttributeKey(FirmwareType.SOFTWARE, FirmwareKey.TITLE).equals(pathName)
|| FirmwareUtil.getAttributeKey(FirmwareType.SOFTWARE, FirmwareKey.CHECKSUM).equals(pathName)
|| FirmwareUtil.getAttributeKey(FirmwareType.SOFTWARE, FirmwareKey.CHECKSUM_ALGORITHM).equals(pathName)
|| FirmwareUtil.getAttributeKey(FirmwareType.SOFTWARE, FirmwareKey.SIZE).equals(pathName);
return OtaPackageUtil.getAttributeKey(OtaPackageType.FIRMWARE, OtaPackageKey.VERSION).equals(pathName)
|| OtaPackageUtil.getAttributeKey(OtaPackageType.FIRMWARE, OtaPackageKey.TITLE).equals(pathName)
|| OtaPackageUtil.getAttributeKey(OtaPackageType.FIRMWARE, OtaPackageKey.CHECKSUM).equals(pathName)
|| OtaPackageUtil.getAttributeKey(OtaPackageType.FIRMWARE, OtaPackageKey.CHECKSUM_ALGORITHM).equals(pathName)
|| OtaPackageUtil.getAttributeKey(OtaPackageType.FIRMWARE, OtaPackageKey.SIZE).equals(pathName)
|| OtaPackageUtil.getAttributeKey(OtaPackageType.SOFTWARE, OtaPackageKey.VERSION).equals(pathName)
|| OtaPackageUtil.getAttributeKey(OtaPackageType.SOFTWARE, OtaPackageKey.TITLE).equals(pathName)
|| OtaPackageUtil.getAttributeKey(OtaPackageType.SOFTWARE, OtaPackageKey.CHECKSUM).equals(pathName)
|| OtaPackageUtil.getAttributeKey(OtaPackageType.SOFTWARE, OtaPackageKey.CHECKSUM_ALGORITHM).equals(pathName)
|| OtaPackageUtil.getAttributeKey(OtaPackageType.SOFTWARE, OtaPackageKey.SIZE).equals(pathName);
}
}

6
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClient.java

@ -31,7 +31,7 @@ import org.eclipse.leshan.server.registration.Registration;
import org.eclipse.leshan.server.security.SecurityInfo;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.firmware.FirmwareType;
import org.thingsboard.server.common.data.ota.OtaPackageType;
import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse;
import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto;
import org.thingsboard.server.gen.transport.TransportProtos.TsKvProto;
@ -120,8 +120,8 @@ public class LwM2mClient implements Cloneable {
this.init = false;
this.queuedRequests = new ConcurrentLinkedQueue<>();
this.fwUpdate = new LwM2mFwSwUpdate(this, FirmwareType.FIRMWARE);
this.swUpdate = new LwM2mFwSwUpdate(this, FirmwareType.SOFTWARE);
this.fwUpdate = new LwM2mFwSwUpdate(this, OtaPackageType.FIRMWARE);
this.swUpdate = new LwM2mFwSwUpdate(this, OtaPackageType.SOFTWARE);
if (this.credentials != null && this.credentials.hasDeviceInfo()) {
this.session = createSession(nodeId, sessionId, credentials);
this.deviceId = new UUID(session.getDeviceIdMSB(), session.getDeviceIdLSB());

8
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContextImpl.java

@ -83,11 +83,17 @@ public class LwM2mClientContextImpl implements LwM2mClientContext {
@Override
public LwM2mClient getClient(TransportProtos.SessionInfoProto sessionInfo) {
return lwM2mClientsByEndpoint.values().stream().filter(c ->
LwM2mClient lwM2mClient = lwM2mClientsByEndpoint.values().stream().filter(c ->
(new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB()))
.equals((new UUID(c.getSession().getSessionIdMSB(), c.getSession().getSessionIdLSB())))
).findAny().get();
if (lwM2mClient == null) {
log.warn("Device TimeOut? lwM2mClient is null.");
log.warn("SessionInfo input [{}], lwM2mClientsByEndpoint size: [{}]", sessionInfo, lwM2mClientsByEndpoint.values().size());
log.error("", new RuntimeException());
}
return lwM2mClient;
}
@Override

66
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mFwSwUpdate.java

@ -20,8 +20,8 @@ import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.leshan.core.request.ContentFormat;
import org.thingsboard.server.common.data.firmware.FirmwareType;
import org.thingsboard.server.common.data.firmware.FirmwareUpdateStatus;
import org.thingsboard.server.common.data.ota.OtaPackageType;
import org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus;
import org.thingsboard.server.gen.transport.TransportProtos;
import org.thingsboard.server.transport.lwm2m.server.DefaultLwM2MTransportMsgHandler;
import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportRequest;
@ -32,11 +32,12 @@ import java.util.List;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArrayList;
import static org.thingsboard.server.common.data.firmware.FirmwareKey.STATE;
import static org.thingsboard.server.common.data.firmware.FirmwareType.FIRMWARE;
import static org.thingsboard.server.common.data.firmware.FirmwareType.SOFTWARE;
import static org.thingsboard.server.common.data.firmware.FirmwareUpdateStatus.UPDATING;
import static org.thingsboard.server.common.data.firmware.FirmwareUtil.getAttributeKey;
import static org.thingsboard.server.common.data.ota.OtaPackageKey.STATE;
import static org.thingsboard.server.common.data.ota.OtaPackageType.FIRMWARE;
import static org.thingsboard.server.common.data.ota.OtaPackageType.SOFTWARE;
import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.UPDATING;
import static org.thingsboard.server.common.data.ota.OtaPackageUtil.getAttributeKey;
import static org.eclipse.californium.core.coap.CoAP.ResponseCode.CONTENT;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_NAME_ID;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_PACKAGE_ID;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_RESULT_ID;
@ -97,14 +98,17 @@ public class LwM2mFwSwUpdate {
@Getter
@Setter
private volatile boolean infoFwSwUpdate = false;
private final FirmwareType type;
private final OtaPackageType type;
@Getter
LwM2mClient lwM2MClient;
@Getter
@Setter
private final List<String> pendingInfoRequestsStart;
@Getter
@Setter
private volatile Lwm2mClientRpcRequest rpcRequest;
public LwM2mFwSwUpdate(LwM2mClient lwM2MClient, FirmwareType type) {
public LwM2mFwSwUpdate(LwM2mClient lwM2MClient, OtaPackageType type) {
this.lwM2MClient = lwM2MClient;
this.pendingInfoRequestsStart = new CopyOnWriteArrayList<>();
this.type = type;
@ -139,7 +143,7 @@ public class LwM2mFwSwUpdate {
}
if (this.pendingInfoRequestsStart.size() == 0) {
this.infoFwSwUpdate = false;
if (!FirmwareUpdateStatus.DOWNLOADING.name().equals(this.stateUpdate)) {
if (!OtaPackageUpdateStatus.DOWNLOADING.name().equals(this.stateUpdate)) {
boolean conditionalStart = this.type.equals(FIRMWARE) ? this.conditionalFwUpdateStart() :
this.conditionalSwUpdateStart();
if (conditionalStart) {
@ -153,16 +157,30 @@ public class LwM2mFwSwUpdate {
* Send FsSw to Lwm2mClient:
* before operation Write: fw_state = DOWNLOADING
*/
private void writeFwSwWare(DefaultLwM2MTransportMsgHandler handler, LwM2mTransportRequest request) {
this.stateUpdate = FirmwareUpdateStatus.DOWNLOADING.name();
// this.observeStateUpdate();
this.sendLogs(handler, WRITE_REPLACE.name(), LOG_LW2M_INFO, null);
int chunkSize = 0;
int chunk = 0;
byte[] firmwareChunk = handler.firmwareDataCache.get(this.currentId.toString(), chunkSize, chunk);
String targetIdVer = convertPathFromObjectIdToIdVer(this.pathPackageId, this.lwM2MClient.getRegistration());
request.sendAllRequest(lwM2MClient.getRegistration(), targetIdVer, WRITE_REPLACE, ContentFormat.OPAQUE.getName(),
firmwareChunk, handler.config.getTimeout(), null);
public void writeFwSwWare(DefaultLwM2MTransportMsgHandler handler, LwM2mTransportRequest request) {
if (this.currentId != null) {
this.stateUpdate = OtaPackageUpdateStatus.DOWNLOADING.name();
this.sendLogs(handler, WRITE_REPLACE.name(), LOG_LW2M_INFO, null);
int chunkSize = 0;
int chunk = 0;
byte[] firmwareChunk = handler.otaPackageDataCache.get(this.currentId.toString(), chunkSize, chunk);
String targetIdVer = convertPathFromObjectIdToIdVer(this.pathPackageId, this.lwM2MClient.getRegistration());
String fwMsg = String.format("%s: Start type operation %s paths: %s", LOG_LW2M_INFO,
LwM2mTransportUtil.LwM2mTypeOper.FW_UPDATE.name(), FW_PACKAGE_ID);
handler.sendLogsToThingsboard(fwMsg, lwM2MClient.getRegistration().getId());
log.warn("8) Start firmware Update. Send save to: [{}] ver: [{}] path: [{}]", this.lwM2MClient.getDeviceName(), this.currentVersion, targetIdVer);
request.sendAllRequest(this.lwM2MClient.getRegistration(), targetIdVer, WRITE_REPLACE, ContentFormat.OPAQUE.getName(),
firmwareChunk, handler.config.getTimeout(), this.rpcRequest);
}
else {
String msgError = "FirmWareId is null.";
log.warn("6) [{}]", msgError);
if (this.rpcRequest != null) {
handler.sentRpcResponse(this.rpcRequest, CONTENT.name(), msgError, LOG_LW2M_ERROR);
}
log.error (msgError);
this.sendLogs(handler, WRITE_REPLACE.name(), LOG_LW2M_ERROR, msgError);
}
}
public void sendLogs(DefaultLwM2MTransportMsgHandler handler, String typeOper, String typeInfo, String msgError) {
@ -185,7 +203,7 @@ public class LwM2mFwSwUpdate {
this.setStateUpdate(UPDATING.name());
this.sendLogs(handler, EXECUTE.name(), LOG_LW2M_INFO, null);
request.sendAllRequest(this.lwM2MClient.getRegistration(), this.pathInstallId, EXECUTE, ContentFormat.TLV.getName(),
null, 0, null);
null, 0, this.rpcRequest);
}
/**
@ -287,10 +305,10 @@ public class LwM2mFwSwUpdate {
LwM2mTransportUtil.UpdateResultSw.fromUpdateResultSwByCode(updateResult.intValue()).type;
String key = splitCamelCaseString((String) this.lwM2MClient.getResourceNameByRezId(null, this.pathResultId));
if (success) {
this.stateUpdate = FirmwareUpdateStatus.UPDATED.name();
this.stateUpdate = OtaPackageUpdateStatus.UPDATED.name();
this.sendLogs(handler, EXECUTE.name(), LOG_LW2M_INFO, null);
} else {
this.stateUpdate = FirmwareUpdateStatus.FAILED.name();
this.stateUpdate = OtaPackageUpdateStatus.FAILED.name();
this.sendLogs(handler, EXECUTE.name(), LOG_LW2M_ERROR, value);
}
handler.helper.sendParametersOnThingsboardTelemetry(
@ -347,7 +365,7 @@ public class LwM2mFwSwUpdate {
this.pathResultId, this.lwM2MClient.getRegistration()));
this.pendingInfoRequestsStart.forEach(pathIdVer -> {
request.sendAllRequest(this.lwM2MClient.getRegistration(), pathIdVer, OBSERVE, ContentFormat.TLV.getName(),
null, 0, null);
null, 0, this.rpcRequest);
});
}

4
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/Lwm2mClientRpcRequest.java

@ -39,6 +39,7 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.K
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.DISCOVER_ALL;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.EXECUTE;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.FW_UPDATE;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.OBSERVE_CANCEL;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.OBSERVE_READ_ALL;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.WRITE_ATTRIBUTES;
@ -140,7 +141,8 @@ public class Lwm2mClientRpcRequest {
if (this.getTargetIdVer() == null
&& !(OBSERVE_READ_ALL == this.getTypeOper()
|| DISCOVER_ALL == this.getTypeOper()
|| OBSERVE_CANCEL == this.getTypeOper())) {
|| OBSERVE_CANCEL == this.getTypeOper()
|| FW_UPDATE == this.getTypeOper())) {
this.setErrorMsg(TARGET_ID_VER_KEY + " and " +
KEY_NAME_KEY + " is null or bad format");
}

9
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbLwM2mRedisRegistrationStore.java

@ -337,23 +337,24 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto
}
}
//TODO: JedisCluster didn't implement Transaction, maybe should use some advanced key creation strategies
private void removeAddrIndex(RedisConnection connection, Registration registration) {
// Watch the key to remove.
byte[] regAddrKey = toRegAddrKey(registration.getSocketAddress());
connection.watch(regAddrKey);
// connection.watch(regAddrKey);
byte[] epFromAddr = connection.get(regAddrKey);
// Delete the key if needed.
if (Arrays.equals(epFromAddr, registration.getEndpoint().getBytes(UTF_8))) {
// Try to delete the key
connection.multi();
// connection.multi();
connection.del(regAddrKey);
connection.exec();
// connection.exec();
// if transaction failed this is not an issue as the socket address is probably reused and we don't neeed to
// delete it anymore.
} else {
// the key must not be deleted.
connection.unwatch();
// connection.unwatch();
}
}

3
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/utils/LwM2mValueConverterImpl.java

@ -43,6 +43,9 @@ public class LwM2mValueConverterImpl implements LwM2mValueConverter {
@Override
public Object convertValue(Object value, Type currentType, Type expectedType, LwM2mPath resourcePath)
throws CodecException {
if (value == null) {
return null;
}
if (expectedType == null) {
/** unknown resource, trusted value */
return value;

58
common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java

@ -47,8 +47,8 @@ import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.DeviceTransportType;
import org.thingsboard.server.common.data.TransportPayloadType;
import org.thingsboard.server.common.data.device.profile.MqttTopics;
import org.thingsboard.server.common.data.firmware.FirmwareType;
import org.thingsboard.server.common.data.id.FirmwareId;
import org.thingsboard.server.common.data.ota.OtaPackageType;
import org.thingsboard.server.common.data.id.OtaPackageId;
import org.thingsboard.server.common.msg.EncryptionUtil;
import org.thingsboard.server.common.msg.tools.TbRateLimitsException;
import org.thingsboard.server.common.transport.SessionMsgListener;
@ -126,8 +126,8 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
private volatile InetSocketAddress address;
private volatile GatewaySessionHandler gatewaySessionHandler;
private final ConcurrentHashMap<String, String> fwSessions;
private final ConcurrentHashMap<String, Integer> fwChunkSizes;
private final ConcurrentHashMap<String, String> otaPackSessions;
private final ConcurrentHashMap<String, Integer> chunkSizes;
MqttTransportHandler(MqttTransportContext context, SslHandler sslHandler) {
this.sessionId = UUID.randomUUID();
@ -137,8 +137,8 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
this.sslHandler = sslHandler;
this.mqttQoSMap = new ConcurrentHashMap<>();
this.deviceSessionCtx = new DeviceSessionCtx(sessionId, mqttQoSMap, context);
this.fwSessions = new ConcurrentHashMap<>();
this.fwChunkSizes = new ConcurrentHashMap<>();
this.otaPackSessions = new ConcurrentHashMap<>();
this.chunkSizes = new ConcurrentHashMap<>();
}
@Override
@ -320,9 +320,9 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
TransportProtos.ClaimDeviceMsg claimDeviceMsg = payloadAdaptor.convertToClaimDevice(deviceSessionCtx, mqttMsg);
transportService.process(deviceSessionCtx.getSessionInfo(), claimDeviceMsg, getPubAckCallback(ctx, msgId, claimDeviceMsg));
} else if ((fwMatcher = FW_REQUEST_PATTERN.matcher(topicName)).find()) {
getFirmwareCallback(ctx, mqttMsg, msgId, fwMatcher, FirmwareType.FIRMWARE);
getOtaPackageCallback(ctx, mqttMsg, msgId, fwMatcher, OtaPackageType.FIRMWARE);
} else if ((fwMatcher = SW_REQUEST_PATTERN.matcher(topicName)).find()) {
getFirmwareCallback(ctx, mqttMsg, msgId, fwMatcher, FirmwareType.SOFTWARE);
getOtaPackageCallback(ctx, mqttMsg, msgId, fwMatcher, OtaPackageType.SOFTWARE);
} else {
transportService.reportActivity(deviceSessionCtx.getSessionInfo());
ack(ctx, msgId);
@ -334,38 +334,38 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
}
}
private void getFirmwareCallback(ChannelHandlerContext ctx, MqttPublishMessage mqttMsg, int msgId, Matcher fwMatcher, FirmwareType type) {
private void getOtaPackageCallback(ChannelHandlerContext ctx, MqttPublishMessage mqttMsg, int msgId, Matcher fwMatcher, OtaPackageType type) {
String payload = mqttMsg.content().toString(UTF8);
int chunkSize = StringUtils.isNotEmpty(payload) ? Integer.parseInt(payload) : 0;
String requestId = fwMatcher.group("requestId");
int chunk = Integer.parseInt(fwMatcher.group("chunk"));
if (chunkSize > 0) {
this.fwChunkSizes.put(requestId, chunkSize);
this.chunkSizes.put(requestId, chunkSize);
} else {
chunkSize = fwChunkSizes.getOrDefault(requestId, 0);
chunkSize = chunkSizes.getOrDefault(requestId, 0);
}
if (chunkSize > context.getMaxPayloadSize()) {
sendFirmwareError(ctx, PAYLOAD_TOO_LARGE);
sendOtaPackageError(ctx, PAYLOAD_TOO_LARGE);
return;
}
String firmwareId = fwSessions.get(requestId);
String otaPackageId = otaPackSessions.get(requestId);
if (firmwareId != null) {
sendFirmware(ctx, mqttMsg.variableHeader().packetId(), firmwareId, requestId, chunkSize, chunk, type);
if (otaPackageId != null) {
sendOtaPackage(ctx, mqttMsg.variableHeader().packetId(), otaPackageId, requestId, chunkSize, chunk, type);
} else {
TransportProtos.SessionInfoProto sessionInfo = deviceSessionCtx.getSessionInfo();
TransportProtos.GetFirmwareRequestMsg getFirmwareRequestMsg = TransportProtos.GetFirmwareRequestMsg.newBuilder()
TransportProtos.GetOtaPackageRequestMsg getOtaPackageRequestMsg = TransportProtos.GetOtaPackageRequestMsg.newBuilder()
.setDeviceIdMSB(sessionInfo.getDeviceIdMSB())
.setDeviceIdLSB(sessionInfo.getDeviceIdLSB())
.setTenantIdMSB(sessionInfo.getTenantIdMSB())
.setTenantIdLSB(sessionInfo.getTenantIdLSB())
.setType(type.name())
.build();
transportService.process(deviceSessionCtx.getSessionInfo(), getFirmwareRequestMsg,
new FirmwareCallback(ctx, msgId, getFirmwareRequestMsg, requestId, chunkSize, chunk));
transportService.process(deviceSessionCtx.getSessionInfo(), getOtaPackageRequestMsg,
new OtaPackageCallback(ctx, msgId, getOtaPackageRequestMsg, requestId, chunkSize, chunk));
}
}
@ -425,15 +425,15 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
}
}
private class FirmwareCallback implements TransportServiceCallback<TransportProtos.GetFirmwareResponseMsg> {
private class OtaPackageCallback implements TransportServiceCallback<TransportProtos.GetOtaPackageResponseMsg> {
private final ChannelHandlerContext ctx;
private final int msgId;
private final TransportProtos.GetFirmwareRequestMsg msg;
private final TransportProtos.GetOtaPackageRequestMsg msg;
private final String requestId;
private final int chunkSize;
private final int chunk;
FirmwareCallback(ChannelHandlerContext ctx, int msgId, TransportProtos.GetFirmwareRequestMsg msg, String requestId, int chunkSize, int chunk) {
OtaPackageCallback(ChannelHandlerContext ctx, int msgId, TransportProtos.GetOtaPackageRequestMsg msg, String requestId, int chunkSize, int chunk) {
this.ctx = ctx;
this.msgId = msgId;
this.msg = msg;
@ -443,13 +443,13 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
}
@Override
public void onSuccess(TransportProtos.GetFirmwareResponseMsg response) {
public void onSuccess(TransportProtos.GetOtaPackageResponseMsg response) {
if (TransportProtos.ResponseStatus.SUCCESS.equals(response.getResponseStatus())) {
FirmwareId firmwareId = new FirmwareId(new UUID(response.getFirmwareIdMSB(), response.getFirmwareIdLSB()));
fwSessions.put(requestId, firmwareId.toString());
sendFirmware(ctx, msgId, firmwareId.toString(), requestId, chunkSize, chunk, FirmwareType.valueOf(response.getType()));
OtaPackageId firmwareId = new OtaPackageId(new UUID(response.getOtaPackageIdMSB(), response.getOtaPackageIdLSB()));
otaPackSessions.put(requestId, firmwareId.toString());
sendOtaPackage(ctx, msgId, firmwareId.toString(), requestId, chunkSize, chunk, OtaPackageType.valueOf(response.getType()));
} else {
sendFirmwareError(ctx, response.getResponseStatus().toString());
sendOtaPackageError(ctx, response.getResponseStatus().toString());
}
}
@ -460,11 +460,11 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
}
}
private void sendFirmware(ChannelHandlerContext ctx, int msgId, String firmwareId, String requestId, int chunkSize, int chunk, FirmwareType type) {
private void sendOtaPackage(ChannelHandlerContext ctx, int msgId, String firmwareId, String requestId, int chunkSize, int chunk, OtaPackageType type) {
log.trace("[{}] Send firmware [{}] to device!", sessionId, firmwareId);
ack(ctx, msgId);
try {
byte[] firmwareChunk = context.getFirmwareDataCache().get(firmwareId, chunkSize, chunk);
byte[] firmwareChunk = context.getOtaPackageDataCache().get(firmwareId, chunkSize, chunk);
deviceSessionCtx.getPayloadAdaptor()
.convertToPublish(deviceSessionCtx, firmwareChunk, requestId, chunk, type)
.ifPresent(deviceSessionCtx.getChannel()::writeAndFlush);
@ -473,7 +473,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
}
}
private void sendFirmwareError(ChannelHandlerContext ctx, String error) {
private void sendOtaPackageError(ChannelHandlerContext ctx, String error) {
log.warn("[{}] {}", sessionId, error);
deviceSessionCtx.getChannel().writeAndFlush(deviceSessionCtx
.getPayloadAdaptor()

4
common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/adaptors/JsonMqttAdaptor.java

@ -30,7 +30,7 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.thingsboard.server.common.data.device.profile.MqttTopics;
import org.thingsboard.server.common.data.firmware.FirmwareType;
import org.thingsboard.server.common.data.ota.OtaPackageType;
import org.thingsboard.server.common.transport.adaptor.AdaptorException;
import org.thingsboard.server.common.transport.adaptor.JsonConverter;
import org.thingsboard.server.gen.transport.TransportProtos;
@ -155,7 +155,7 @@ public class JsonMqttAdaptor implements MqttTransportAdaptor {
}
@Override
public Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, byte[] firmwareChunk, String requestId, int chunk, FirmwareType firmwareType) {
public Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, byte[] firmwareChunk, String requestId, int chunk, OtaPackageType firmwareType) {
return Optional.of(createMqttPublishMsg(ctx, String.format(DEVICE_SOFTWARE_FIRMWARE_RESPONSES_TOPIC_FORMAT, firmwareType.getKeyPrefix(), requestId, chunk), firmwareChunk));
}

4
common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/adaptors/MqttTransportAdaptor.java

@ -23,7 +23,7 @@ import io.netty.handler.codec.mqtt.MqttMessage;
import io.netty.handler.codec.mqtt.MqttMessageType;
import io.netty.handler.codec.mqtt.MqttPublishMessage;
import io.netty.handler.codec.mqtt.MqttPublishVariableHeader;
import org.thingsboard.server.common.data.firmware.FirmwareType;
import org.thingsboard.server.common.data.ota.OtaPackageType;
import org.thingsboard.server.common.transport.adaptor.AdaptorException;
import org.thingsboard.server.gen.transport.TransportProtos.AttributeUpdateNotificationMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ClaimDeviceMsg;
@ -78,7 +78,7 @@ public interface MqttTransportAdaptor {
Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, ProvisionDeviceResponseMsg provisionResponse) throws AdaptorException;
Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, byte[] firmwareChunk, String requestId, int chunk, FirmwareType firmwareType) throws AdaptorException;
Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, byte[] firmwareChunk, String requestId, int chunk, OtaPackageType firmwareType) throws AdaptorException;
default MqttPublishMessage createMqttPublishMsg(MqttDeviceAwareSessionContext ctx, String topic, byte[] payloadInBytes) {
MqttFixedHeader mqttFixedHeader =

4
common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/adaptors/ProtoMqttAdaptor.java

@ -28,7 +28,7 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.thingsboard.server.common.data.device.profile.MqttTopics;
import org.thingsboard.server.common.data.firmware.FirmwareType;
import org.thingsboard.server.common.data.ota.OtaPackageType;
import org.thingsboard.server.common.transport.adaptor.AdaptorException;
import org.thingsboard.server.common.transport.adaptor.JsonConverter;
import org.thingsboard.server.common.transport.adaptor.ProtoConverter;
@ -168,7 +168,7 @@ public class ProtoMqttAdaptor implements MqttTransportAdaptor {
}
@Override
public Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, byte[] firmwareChunk, String requestId, int chunk, FirmwareType firmwareType) throws AdaptorException {
public Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, byte[] firmwareChunk, String requestId, int chunk, OtaPackageType firmwareType) throws AdaptorException {
return Optional.of(createMqttPublishMsg(ctx, String.format(DEVICE_SOFTWARE_FIRMWARE_RESPONSES_TOPIC_FORMAT, firmwareType.getKeyPrefix(), requestId, chunk), firmwareChunk));
}

5
common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/TransportContext.java

@ -21,14 +21,13 @@ import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.thingsboard.common.util.ThingsBoardExecutors;
import org.thingsboard.server.cache.firmware.FirmwareDataCache;
import org.thingsboard.server.cache.ota.OtaPackageDataCache;
import org.thingsboard.server.queue.discovery.TbServiceInfoProvider;
import org.thingsboard.server.queue.scheduler.SchedulerComponent;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* Created by ashvayka on 15.10.18.
@ -53,7 +52,7 @@ public abstract class TransportContext {
@Getter
@Autowired
private FirmwareDataCache firmwareDataCache;
private OtaPackageDataCache otaPackageDataCache;
@Autowired
private TransportResourceCache transportResourceCache;

6
common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/TransportService.java

@ -29,8 +29,8 @@ import org.thingsboard.server.gen.transport.TransportProtos.GetDeviceRequestMsg;
import org.thingsboard.server.gen.transport.TransportProtos.GetDeviceResponseMsg;
import org.thingsboard.server.gen.transport.TransportProtos.GetEntityProfileRequestMsg;
import org.thingsboard.server.gen.transport.TransportProtos.GetEntityProfileResponseMsg;
import org.thingsboard.server.gen.transport.TransportProtos.GetFirmwareRequestMsg;
import org.thingsboard.server.gen.transport.TransportProtos.GetFirmwareResponseMsg;
import org.thingsboard.server.gen.transport.TransportProtos.GetOtaPackageRequestMsg;
import org.thingsboard.server.gen.transport.TransportProtos.GetOtaPackageResponseMsg;
import org.thingsboard.server.gen.transport.TransportProtos.GetOrCreateDeviceFromGatewayRequestMsg;
import org.thingsboard.server.gen.transport.TransportProtos.GetResourceRequestMsg;
import org.thingsboard.server.gen.transport.TransportProtos.GetResourceResponseMsg;
@ -115,7 +115,7 @@ public interface TransportService {
void process(TransportToDeviceActorMsg msg, TransportServiceCallback<Void> callback);
void process(SessionInfoProto sessionInfoProto, GetFirmwareRequestMsg msg, TransportServiceCallback<GetFirmwareResponseMsg> callback);
void process(SessionInfoProto sessionInfoProto, GetOtaPackageRequestMsg msg, TransportServiceCallback<GetOtaPackageResponseMsg> callback);
SessionMetaData registerAsyncSession(SessionInfoProto sessionInfo, SessionMsgListener listener);

6
common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/service/DefaultTransportService.java

@ -614,13 +614,13 @@ public class DefaultTransportService implements TransportService {
}
@Override
public void process(TransportProtos.SessionInfoProto sessionInfo, TransportProtos.GetFirmwareRequestMsg msg, TransportServiceCallback<TransportProtos.GetFirmwareResponseMsg> callback) {
public void process(TransportProtos.SessionInfoProto sessionInfo, TransportProtos.GetOtaPackageRequestMsg msg, TransportServiceCallback<TransportProtos.GetOtaPackageResponseMsg> callback) {
if (checkLimits(sessionInfo, msg, callback)) {
TbProtoQueueMsg<TransportProtos.TransportApiRequestMsg> protoMsg =
new TbProtoQueueMsg<>(UUID.randomUUID(), TransportProtos.TransportApiRequestMsg.newBuilder().setFirmwareRequestMsg(msg).build());
new TbProtoQueueMsg<>(UUID.randomUUID(), TransportProtos.TransportApiRequestMsg.newBuilder().setOtaPackageRequestMsg(msg).build());
AsyncCallbackTemplate.withCallback(transportApiRequestTemplate.send(protoMsg), response -> {
callback.onSuccess(response.getValue().getFirmwareResponseMsg());
callback.onSuccess(response.getValue().getOtaPackageResponseMsg());
}, callback::onError, transportCallbackExecutor);
}
}

8
dao/src/main/java/org/thingsboard/server/dao/device/DeviceDao.java

@ -21,6 +21,7 @@ import org.thingsboard.server.common.data.DeviceInfo;
import org.thingsboard.server.common.data.DeviceTransportType;
import org.thingsboard.server.common.data.EntitySubtype;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.ota.OtaPackageType;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.dao.Dao;
@ -81,9 +82,12 @@ public interface DeviceDao extends Dao<Device>, TenantEntityDao {
*/
PageData<Device> findDevicesByTenantIdAndType(UUID tenantId, String type, PageLink pageLink);
PageData<Device> findDevicesByTenantIdAndTypeAndEmptyFirmware(UUID tenantId, String type, PageLink pageLink);
PageData<Device> findDevicesByTenantIdAndTypeAndEmptyOtaPackage(UUID tenantId,
UUID deviceProfileId,
OtaPackageType type,
PageLink pageLink);
PageData<Device> findDevicesByTenantIdAndTypeAndEmptySoftware(UUID tenantId, String type, PageLink pageLink);
Long countDevicesByTenantIdAndDeviceProfileIdAndEmptyOtaPackage(UUID tenantId, UUID deviceProfileId, OtaPackageType otaPackageType);
/**
* Find device infos by tenantId, type and page link.

16
dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileServiceImpl.java

@ -43,7 +43,7 @@ import org.thingsboard.server.common.data.DeviceProfileInfo;
import org.thingsboard.server.common.data.DeviceProfileProvisionType;
import org.thingsboard.server.common.data.DeviceProfileType;
import org.thingsboard.server.common.data.DeviceTransportType;
import org.thingsboard.server.common.data.Firmware;
import org.thingsboard.server.common.data.OtaPackage;
import org.thingsboard.server.common.data.Tenant;
import org.thingsboard.server.common.data.device.profile.CoapDeviceProfileTransportConfiguration;
import org.thingsboard.server.common.data.device.profile.CoapDeviceTypeConfiguration;
@ -57,7 +57,7 @@ import org.thingsboard.server.common.data.device.profile.DisabledDeviceProfilePr
import org.thingsboard.server.common.data.device.profile.MqttDeviceProfileTransportConfiguration;
import org.thingsboard.server.common.data.device.profile.ProtoTransportPayloadConfiguration;
import org.thingsboard.server.common.data.device.profile.TransportPayloadTypeConfiguration;
import org.thingsboard.server.common.data.firmware.FirmwareType;
import org.thingsboard.server.common.data.ota.OtaPackageType;
import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageData;
@ -66,7 +66,7 @@ import org.thingsboard.server.common.data.rule.RuleChain;
import org.thingsboard.server.dao.dashboard.DashboardService;
import org.thingsboard.server.dao.entity.AbstractEntityService;
import org.thingsboard.server.dao.exception.DataValidationException;
import org.thingsboard.server.dao.firmware.FirmwareService;
import org.thingsboard.server.dao.ota.OtaPackageService;
import org.thingsboard.server.dao.rule.RuleChainService;
import org.thingsboard.server.dao.service.DataValidator;
import org.thingsboard.server.dao.service.PaginatedRemover;
@ -119,7 +119,7 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D
private CacheManager cacheManager;
@Autowired
private FirmwareService firmwareService;
private OtaPackageService otaPackageService;
@Autowired
private RuleChainService ruleChainService;
@ -427,11 +427,11 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D
}
if (deviceProfile.getFirmwareId() != null) {
Firmware firmware = firmwareService.findFirmwareById(tenantId, deviceProfile.getFirmwareId());
OtaPackage firmware = otaPackageService.findOtaPackageById(tenantId, deviceProfile.getFirmwareId());
if (firmware == null) {
throw new DataValidationException("Can't assign non-existent firmware!");
}
if (!firmware.getType().equals(FirmwareType.FIRMWARE)) {
if (!firmware.getType().equals(OtaPackageType.FIRMWARE)) {
throw new DataValidationException("Can't assign firmware with type: " + firmware.getType());
}
if (firmware.getData() == null) {
@ -443,11 +443,11 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D
}
if (deviceProfile.getSoftwareId() != null) {
Firmware software = firmwareService.findFirmwareById(tenantId, deviceProfile.getSoftwareId());
OtaPackage software = otaPackageService.findOtaPackageById(tenantId, deviceProfile.getSoftwareId());
if (software == null) {
throw new DataValidationException("Can't assign non-existent software!");
}
if (!software.getType().equals(FirmwareType.SOFTWARE)) {
if (!software.getType().equals(OtaPackageType.SOFTWARE)) {
throw new DataValidationException("Can't assign software with type: " + software.getType());
}
if (software.getData() == null) {

45
dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java

@ -41,7 +41,7 @@ import org.thingsboard.server.common.data.DeviceTransportType;
import org.thingsboard.server.common.data.EntitySubtype;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.EntityView;
import org.thingsboard.server.common.data.Firmware;
import org.thingsboard.server.common.data.OtaPackage;
import org.thingsboard.server.common.data.Tenant;
import org.thingsboard.server.common.data.device.DeviceSearchQuery;
import org.thingsboard.server.common.data.device.credentials.BasicMqttCredentials;
@ -54,13 +54,13 @@ import org.thingsboard.server.common.data.device.data.Lwm2mDeviceTransportConfig
import org.thingsboard.server.common.data.device.data.MqttDeviceTransportConfiguration;
import org.thingsboard.server.common.data.device.data.SnmpDeviceTransportConfiguration;
import org.thingsboard.server.common.data.edge.Edge;
import org.thingsboard.server.common.data.firmware.FirmwareType;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.data.id.EdgeId;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.ota.OtaPackageType;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.relation.EntityRelation;
@ -76,7 +76,7 @@ import org.thingsboard.server.dao.device.provision.ProvisionResponseStatus;
import org.thingsboard.server.dao.entity.AbstractEntityService;
import org.thingsboard.server.dao.event.EventService;
import org.thingsboard.server.dao.exception.DataValidationException;
import org.thingsboard.server.dao.firmware.FirmwareService;
import org.thingsboard.server.dao.ota.OtaPackageService;
import org.thingsboard.server.dao.service.DataValidator;
import org.thingsboard.server.dao.service.PaginatedRemover;
import org.thingsboard.server.dao.tenant.TbTenantProfileCache;
@ -138,7 +138,7 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe
private TbTenantProfileCache tenantProfileCache;
@Autowired
private FirmwareService firmwareService;
private OtaPackageService otaPackageService;
@Override
public DeviceInfo findDeviceInfoById(TenantId tenantId, DeviceId deviceId) {
@ -201,14 +201,12 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe
deviceCredentials.setDeviceId(savedDevice.getId());
if (device.getId() == null) {
deviceCredentialsService.createDeviceCredentials(savedDevice.getTenantId(), deviceCredentials);
}
else {
} else {
DeviceCredentials foundDeviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(device.getTenantId(), savedDevice.getId());
if (foundDeviceCredentials == null) {
deviceCredentialsService.createDeviceCredentials(savedDevice.getTenantId(), deviceCredentials);
}
else {
deviceCredentialsService.updateDeviceCredentials(device.getTenantId(), deviceCredentials);
} else {
deviceCredentialsService.updateDeviceCredentials(device.getTenantId(), deviceCredentials);
}
}
return savedDevice;
@ -364,21 +362,24 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe
}
@Override
public PageData<Device> findDevicesByTenantIdAndTypeAndEmptyFirmware(TenantId tenantId, String type, PageLink pageLink) {
log.trace("Executing findDevicesByTenantIdAndTypeAndEmptyFirmware, tenantId [{}], type [{}], pageLink [{}]", tenantId, type, pageLink);
public PageData<Device> findDevicesByTenantIdAndTypeAndEmptyOtaPackage(TenantId tenantId,
DeviceProfileId deviceProfileId,
OtaPackageType type,
PageLink pageLink) {
log.trace("Executing findDevicesByTenantIdAndTypeAndEmptyOtaPackage, tenantId [{}], deviceProfileId [{}], type [{}], pageLink [{}]",
tenantId, deviceProfileId, type, pageLink);
validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
validateString(type, "Incorrect type " + type);
validateId(tenantId, INCORRECT_DEVICE_PROFILE_ID + deviceProfileId);
validatePageLink(pageLink);
return deviceDao.findDevicesByTenantIdAndTypeAndEmptyFirmware(tenantId.getId(), type, pageLink);
return deviceDao.findDevicesByTenantIdAndTypeAndEmptyOtaPackage(tenantId.getId(), deviceProfileId.getId(), type, pageLink);
}
@Override
public PageData<Device> findDevicesByTenantIdAndTypeAndEmptySoftware(TenantId tenantId, String type, PageLink pageLink) {
log.trace("Executing findDevicesByTenantIdAndTypeAndEmptySoftware, tenantId [{}], type [{}], pageLink [{}]", tenantId, type, pageLink);
public Long countDevicesByTenantIdAndDeviceProfileIdAndEmptyOtaPackage(TenantId tenantId, DeviceProfileId deviceProfileId, OtaPackageType type) {
log.trace("Executing countDevicesByTenantIdAndDeviceProfileIdAndEmptyOtaPackage, tenantId [{}], deviceProfileId [{}], type [{}]", tenantId, deviceProfileId, type);
validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
validateString(type, "Incorrect type " + type);
validatePageLink(pageLink);
return deviceDao.findDevicesByTenantIdAndTypeAndEmptySoftware(tenantId.getId(), type, pageLink);
validateId(tenantId, INCORRECT_DEVICE_PROFILE_ID + deviceProfileId);
return deviceDao.countDevicesByTenantIdAndDeviceProfileIdAndEmptyOtaPackage(tenantId.getId(), deviceProfileId.getId(), type);
}
@Override
@ -708,11 +709,11 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe
.ifPresent(DeviceTransportConfiguration::validate);
if (device.getFirmwareId() != null) {
Firmware firmware = firmwareService.findFirmwareById(tenantId, device.getFirmwareId());
OtaPackage firmware = otaPackageService.findOtaPackageById(tenantId, device.getFirmwareId());
if (firmware == null) {
throw new DataValidationException("Can't assign non-existent firmware!");
}
if (!firmware.getType().equals(FirmwareType.FIRMWARE)) {
if (!firmware.getType().equals(OtaPackageType.FIRMWARE)) {
throw new DataValidationException("Can't assign firmware with type: " + firmware.getType());
}
if (firmware.getData() == null) {
@ -724,11 +725,11 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe
}
if (device.getSoftwareId() != null) {
Firmware software = firmwareService.findFirmwareById(tenantId, device.getSoftwareId());
OtaPackage software = otaPackageService.findOtaPackageById(tenantId, device.getSoftwareId());
if (software == null) {
throw new DataValidationException("Can't assign non-existent software!");
}
if (!software.getType().equals(FirmwareType.SOFTWARE)) {
if (!software.getType().equals(OtaPackageType.SOFTWARE)) {
throw new DataValidationException("Can't assign software with type: " + software.getType());
}
if (software.getData() == null) {

12
dao/src/main/java/org/thingsboard/server/dao/entity/BaseEntityService.java

@ -32,7 +32,7 @@ import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.EdgeId;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.EntityViewId;
import org.thingsboard.server.common.data.id.FirmwareId;
import org.thingsboard.server.common.data.id.OtaPackageId;
import org.thingsboard.server.common.data.id.RuleChainId;
import org.thingsboard.server.common.data.id.TbResourceId;
import org.thingsboard.server.common.data.id.TenantId;
@ -49,7 +49,7 @@ import org.thingsboard.server.dao.dashboard.DashboardService;
import org.thingsboard.server.dao.device.DeviceService;
import org.thingsboard.server.dao.entityview.EntityViewService;
import org.thingsboard.server.dao.exception.IncorrectParameterException;
import org.thingsboard.server.dao.firmware.FirmwareService;
import org.thingsboard.server.dao.ota.OtaPackageService;
import org.thingsboard.server.dao.resource.ResourceService;
import org.thingsboard.server.dao.rule.RuleChainService;
import org.thingsboard.server.dao.tenant.TenantService;
@ -102,7 +102,7 @@ public class BaseEntityService extends AbstractEntityService implements EntitySe
private ResourceService resourceService;
@Autowired
private FirmwareService firmwareService;
private OtaPackageService otaPackageService;
@Override
public void deleteEntityRelations(TenantId tenantId, EntityId entityId) {
@ -167,8 +167,8 @@ public class BaseEntityService extends AbstractEntityService implements EntitySe
case TB_RESOURCE:
hasName = resourceService.findResourceInfoByIdAsync(tenantId, new TbResourceId(entityId.getId()));
break;
case FIRMWARE:
hasName = firmwareService.findFirmwareInfoByIdAsync(tenantId, new FirmwareId(entityId.getId()));
case OTA_PACKAGE:
hasName = otaPackageService.findOtaPackageInfoByIdAsync(tenantId, new OtaPackageId(entityId.getId()));
break;
default:
throw new IllegalStateException("Not Implemented!");
@ -192,7 +192,7 @@ public class BaseEntityService extends AbstractEntityService implements EntitySe
case DEVICE_PROFILE:
case API_USAGE_STATE:
case TB_RESOURCE:
case FIRMWARE:
case OTA_PACKAGE:
break;
case CUSTOMER:
hasCustomerId = () -> new CustomerId(entityId.getId());

379
dao/src/main/java/org/thingsboard/server/dao/firmware/BaseFirmwareService.java

@ -1,379 +0,0 @@
/**
* Copyright © 2016-2021 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.dao.firmware;
import com.google.common.hash.HashFunction;
import com.google.common.hash.Hashing;
import com.google.common.util.concurrent.ListenableFuture;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.exception.ConstraintViolationException;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.thingsboard.server.cache.firmware.FirmwareDataCache;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.Firmware;
import org.thingsboard.server.common.data.FirmwareInfo;
import org.thingsboard.server.common.data.Tenant;
import org.thingsboard.server.common.data.exception.ThingsboardErrorCode;
import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.firmware.ChecksumAlgorithm;
import org.thingsboard.server.common.data.firmware.FirmwareType;
import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.data.id.FirmwareId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.dao.device.DeviceProfileDao;
import org.thingsboard.server.dao.exception.DataValidationException;
import org.thingsboard.server.dao.service.DataValidator;
import org.thingsboard.server.dao.service.PaginatedRemover;
import org.thingsboard.server.dao.tenant.TenantDao;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import static org.thingsboard.server.common.data.CacheConstants.FIRMWARE_CACHE;
import static org.thingsboard.server.dao.service.Validator.validateId;
import static org.thingsboard.server.dao.service.Validator.validatePageLink;
@Service
@Slf4j
@RequiredArgsConstructor
public class BaseFirmwareService implements FirmwareService {
public static final String INCORRECT_FIRMWARE_ID = "Incorrect firmwareId ";
public static final String INCORRECT_TENANT_ID = "Incorrect tenantId ";
private final TenantDao tenantDao;
private final DeviceProfileDao deviceProfileDao;
private final FirmwareDao firmwareDao;
private final FirmwareInfoDao firmwareInfoDao;
private final CacheManager cacheManager;
private final FirmwareDataCache firmwareDataCache;
@Override
public FirmwareInfo saveFirmwareInfo(FirmwareInfo firmwareInfo) {
log.trace("Executing saveFirmwareInfo [{}]", firmwareInfo);
firmwareInfoValidator.validate(firmwareInfo, FirmwareInfo::getTenantId);
try {
FirmwareId firmwareId = firmwareInfo.getId();
if (firmwareId != null) {
Cache cache = cacheManager.getCache(FIRMWARE_CACHE);
cache.evict(toFirmwareInfoKey(firmwareId));
firmwareDataCache.evict(firmwareId.toString());
}
return firmwareInfoDao.save(firmwareInfo.getTenantId(), firmwareInfo);
} catch (Exception t) {
ConstraintViolationException e = extractConstraintViolationException(t).orElse(null);
if (e != null && e.getConstraintName() != null && e.getConstraintName().equalsIgnoreCase("firmware_tenant_title_version_unq_key")) {
throw new DataValidationException("Firmware with such title and version already exists!");
} else {
throw t;
}
}
}
@Override
public Firmware saveFirmware(Firmware firmware) {
log.trace("Executing saveFirmware [{}]", firmware);
firmwareValidator.validate(firmware, FirmwareInfo::getTenantId);
try {
FirmwareId firmwareId = firmware.getId();
if (firmwareId != null) {
Cache cache = cacheManager.getCache(FIRMWARE_CACHE);
cache.evict(toFirmwareInfoKey(firmwareId));
firmwareDataCache.evict(firmwareId.toString());
}
return firmwareDao.save(firmware.getTenantId(), firmware);
} catch (Exception t) {
ConstraintViolationException e = extractConstraintViolationException(t).orElse(null);
if (e != null && e.getConstraintName() != null && e.getConstraintName().equalsIgnoreCase("firmware_tenant_title_version_unq_key")) {
throw new DataValidationException("Firmware with such title and version already exists!");
} else {
throw t;
}
}
}
@Override
public String generateChecksum(ChecksumAlgorithm checksumAlgorithm, ByteBuffer data) {
if (data == null || !data.hasArray() || data.array().length == 0) {
throw new DataValidationException("Firmware data should be specified!");
}
return getHashFunction(checksumAlgorithm).hashBytes(data.array()).toString();
}
private HashFunction getHashFunction(ChecksumAlgorithm checksumAlgorithm) {
switch (checksumAlgorithm) {
case MD5:
return Hashing.md5();
case SHA256:
return Hashing.sha256();
case SHA384:
return Hashing.sha384();
case SHA512:
return Hashing.sha512();
case CRC32:
return Hashing.crc32();
case MURMUR3_32:
return Hashing.murmur3_32();
case MURMUR3_128:
return Hashing.murmur3_128();
default:
throw new DataValidationException("Unknown checksum algorithm!");
}
}
@Override
public Firmware findFirmwareById(TenantId tenantId, FirmwareId firmwareId) {
log.trace("Executing findFirmwareById [{}]", firmwareId);
validateId(firmwareId, INCORRECT_FIRMWARE_ID + firmwareId);
return firmwareDao.findById(tenantId, firmwareId.getId());
}
@Override
@Cacheable(cacheNames = FIRMWARE_CACHE, key = "{#firmwareId}")
public FirmwareInfo findFirmwareInfoById(TenantId tenantId, FirmwareId firmwareId) {
log.trace("Executing findFirmwareInfoById [{}]", firmwareId);
validateId(firmwareId, INCORRECT_FIRMWARE_ID + firmwareId);
return firmwareInfoDao.findById(tenantId, firmwareId.getId());
}
@Override
public ListenableFuture<FirmwareInfo> findFirmwareInfoByIdAsync(TenantId tenantId, FirmwareId firmwareId) {
log.trace("Executing findFirmwareInfoByIdAsync [{}]", firmwareId);
validateId(firmwareId, INCORRECT_FIRMWARE_ID + firmwareId);
return firmwareInfoDao.findByIdAsync(tenantId, firmwareId.getId());
}
@Override
public PageData<FirmwareInfo> findTenantFirmwaresByTenantId(TenantId tenantId, PageLink pageLink) {
log.trace("Executing findTenantFirmwaresByTenantId, tenantId [{}], pageLink [{}]", tenantId, pageLink);
validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
validatePageLink(pageLink);
return firmwareInfoDao.findFirmwareInfoByTenantId(tenantId, pageLink);
}
@Override
public PageData<FirmwareInfo> findTenantFirmwaresByTenantIdAndDeviceProfileIdAndTypeAndHasData(TenantId tenantId, DeviceProfileId deviceProfileId, FirmwareType firmwareType, boolean hasData, PageLink pageLink) {
log.trace("Executing findTenantFirmwaresByTenantIdAndHasData, tenantId [{}], hasData [{}] pageLink [{}]", tenantId, hasData, pageLink);
validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
validatePageLink(pageLink);
return firmwareInfoDao.findFirmwareInfoByTenantIdAndDeviceProfileIdAndTypeAndHasData(tenantId, deviceProfileId, firmwareType, hasData, pageLink);
}
@Override
public void deleteFirmware(TenantId tenantId, FirmwareId firmwareId) {
log.trace("Executing deleteFirmware [{}]", firmwareId);
validateId(firmwareId, INCORRECT_FIRMWARE_ID + firmwareId);
try {
Cache cache = cacheManager.getCache(FIRMWARE_CACHE);
cache.evict(toFirmwareInfoKey(firmwareId));
firmwareDataCache.evict(firmwareId.toString());
firmwareDao.removeById(tenantId, firmwareId.getId());
} catch (Exception t) {
ConstraintViolationException e = extractConstraintViolationException(t).orElse(null);
if (e != null && e.getConstraintName() != null && e.getConstraintName().equalsIgnoreCase("fk_firmware_device")) {
throw new DataValidationException("The firmware referenced by the devices cannot be deleted!");
} else if (e != null && e.getConstraintName() != null && e.getConstraintName().equalsIgnoreCase("fk_firmware_device_profile")) {
throw new DataValidationException("The firmware referenced by the device profile cannot be deleted!");
} else if (e != null && e.getConstraintName() != null && e.getConstraintName().equalsIgnoreCase("fk_software_device")) {
throw new DataValidationException("The software referenced by the devices cannot be deleted!");
} else if (e != null && e.getConstraintName() != null && e.getConstraintName().equalsIgnoreCase("fk_software_device_profile")) {
throw new DataValidationException("The software referenced by the device profile cannot be deleted!");
} else {
throw t;
}
}
}
@Override
public void deleteFirmwaresByTenantId(TenantId tenantId) {
log.trace("Executing deleteFirmwaresByTenantId, tenantId [{}]", tenantId);
validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
tenantFirmwareRemover.removeEntities(tenantId, tenantId);
}
private DataValidator<FirmwareInfo> firmwareInfoValidator = new DataValidator<>() {
@Override
protected void validateDataImpl(TenantId tenantId, FirmwareInfo firmwareInfo) {
validateImpl(firmwareInfo);
}
@Override
protected void validateUpdate(TenantId tenantId, FirmwareInfo firmware) {
FirmwareInfo firmwareOld = firmwareInfoDao.findById(tenantId, firmware.getUuidId());
validateUpdateDeviceProfile(firmware, firmwareOld);
BaseFirmwareService.validateUpdate(firmware, firmwareOld);
}
};
private DataValidator<Firmware> firmwareValidator = new DataValidator<>() {
@Override
protected void validateDataImpl(TenantId tenantId, Firmware firmware) {
validateImpl(firmware);
if (StringUtils.isEmpty(firmware.getFileName())) {
throw new DataValidationException("Firmware file name should be specified!");
}
if (StringUtils.isEmpty(firmware.getContentType())) {
throw new DataValidationException("Firmware content type should be specified!");
}
if (firmware.getChecksumAlgorithm() == null) {
throw new DataValidationException("Firmware checksum algorithm should be specified!");
}
if (StringUtils.isEmpty(firmware.getChecksum())) {
throw new DataValidationException("Firmware checksum should be specified!");
}
String currentChecksum;
currentChecksum = generateChecksum(firmware.getChecksumAlgorithm(), firmware.getData());
if (!currentChecksum.equals(firmware.getChecksum())) {
throw new DataValidationException("Wrong firmware file!");
}
}
@Override
protected void validateUpdate(TenantId tenantId, Firmware firmware) {
Firmware firmwareOld = firmwareDao.findById(tenantId, firmware.getUuidId());
validateUpdateDeviceProfile(firmware, firmwareOld);
BaseFirmwareService.validateUpdate(firmware, firmwareOld);
if (firmwareOld.getData() != null && !firmwareOld.getData().equals(firmware.getData())) {
throw new DataValidationException("Updating firmware data is prohibited!");
}
}
};
private void validateUpdateDeviceProfile(FirmwareInfo firmware, FirmwareInfo firmwareOld) {
if (firmwareOld.getDeviceProfileId() != null && !firmwareOld.getDeviceProfileId().equals(firmware.getDeviceProfileId())) {
if (firmwareInfoDao.isFirmwareUsed(firmwareOld.getId(), firmware.getType(), firmwareOld.getDeviceProfileId())) {
throw new DataValidationException("Can`t update deviceProfileId because firmware is already in use!");
}
}
}
private static void validateUpdate(FirmwareInfo firmware, FirmwareInfo firmwareOld) {
if (!firmwareOld.getType().equals(firmware.getType())) {
throw new DataValidationException("Updating type is prohibited!");
}
if (!firmwareOld.getTitle().equals(firmware.getTitle())) {
throw new DataValidationException("Updating firmware title is prohibited!");
}
if (!firmwareOld.getVersion().equals(firmware.getVersion())) {
throw new DataValidationException("Updating firmware version is prohibited!");
}
if (firmwareOld.getFileName() != null && !firmwareOld.getFileName().equals(firmware.getFileName())) {
throw new DataValidationException("Updating firmware file name is prohibited!");
}
if (firmwareOld.getContentType() != null && !firmwareOld.getContentType().equals(firmware.getContentType())) {
throw new DataValidationException("Updating firmware content type is prohibited!");
}
if (firmwareOld.getChecksumAlgorithm() != null && !firmwareOld.getChecksumAlgorithm().equals(firmware.getChecksumAlgorithm())) {
throw new DataValidationException("Updating firmware content type is prohibited!");
}
if (firmwareOld.getChecksum() != null && !firmwareOld.getChecksum().equals(firmware.getChecksum())) {
throw new DataValidationException("Updating firmware content type is prohibited!");
}
if (firmwareOld.getDataSize() != null && !firmwareOld.getDataSize().equals(firmware.getDataSize())) {
throw new DataValidationException("Updating firmware data size is prohibited!");
}
}
private void validateImpl(FirmwareInfo firmwareInfo) {
if (firmwareInfo.getTenantId() == null) {
throw new DataValidationException("Firmware should be assigned to tenant!");
} else {
Tenant tenant = tenantDao.findById(firmwareInfo.getTenantId(), firmwareInfo.getTenantId().getId());
if (tenant == null) {
throw new DataValidationException("Firmware is referencing to non-existent tenant!");
}
}
if (firmwareInfo.getDeviceProfileId() != null) {
DeviceProfile deviceProfile = deviceProfileDao.findById(firmwareInfo.getTenantId(), firmwareInfo.getDeviceProfileId().getId());
if (deviceProfile == null) {
throw new DataValidationException("Firmware is referencing to non-existent device profile!");
}
}
if (firmwareInfo.getType() == null) {
throw new DataValidationException("Type should be specified!");
}
if (StringUtils.isEmpty(firmwareInfo.getTitle())) {
throw new DataValidationException("Firmware title should be specified!");
}
if (StringUtils.isEmpty(firmwareInfo.getVersion())) {
throw new DataValidationException("Firmware version should be specified!");
}
}
private PaginatedRemover<TenantId, FirmwareInfo> tenantFirmwareRemover =
new PaginatedRemover<>() {
@Override
protected PageData<FirmwareInfo> findEntities(TenantId tenantId, TenantId id, PageLink pageLink) {
return firmwareInfoDao.findFirmwareInfoByTenantId(id, pageLink);
}
@Override
protected void removeEntity(TenantId tenantId, FirmwareInfo entity) {
deleteFirmware(tenantId, entity.getId());
}
};
protected Optional<ConstraintViolationException> extractConstraintViolationException(Exception t) {
if (t instanceof ConstraintViolationException) {
return Optional.of((ConstraintViolationException) t);
} else if (t.getCause() instanceof ConstraintViolationException) {
return Optional.of((ConstraintViolationException) (t.getCause()));
} else {
return Optional.empty();
}
}
private static List<FirmwareId> toFirmwareInfoKey(FirmwareId firmwareId) {
return Collections.singletonList(firmwareId);
}
}

31
dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java

@ -479,22 +479,21 @@ public class ModelConstants {
public static final String RESOURCE_DATA_COLUMN = "data";
/**
* Firmware constants.
*/
public static final String FIRMWARE_TABLE_NAME = "firmware";
public static final String FIRMWARE_TENANT_ID_COLUMN = TENANT_ID_COLUMN;
public static final String FIRMWARE_DEVICE_PROFILE_ID_COLUMN = "device_profile_id";
public static final String FIRMWARE_TYPE_COLUMN = "type";
public static final String FIRMWARE_TITLE_COLUMN = TITLE_PROPERTY;
public static final String FIRMWARE_VERSION_COLUMN = "version";
public static final String FIRMWARE_FILE_NAME_COLUMN = "file_name";
public static final String FIRMWARE_CONTENT_TYPE_COLUMN = "content_type";
public static final String FIRMWARE_CHECKSUM_ALGORITHM_COLUMN = "checksum_algorithm";
public static final String FIRMWARE_CHECKSUM_COLUMN = "checksum";
public static final String FIRMWARE_DATA_COLUMN = "data";
public static final String FIRMWARE_DATA_SIZE_COLUMN = "data_size";
public static final String FIRMWARE_ADDITIONAL_INFO_COLUMN = ADDITIONAL_INFO_PROPERTY;
public static final String FIRMWARE_HAS_DATA_PROPERTY = "has_data";
* Ota Package constants.
*/
public static final String OTA_PACKAGE_TABLE_NAME = "ota_package";
public static final String OTA_PACKAGE_TENANT_ID_COLUMN = TENANT_ID_COLUMN;
public static final String OTA_PACKAGE_DEVICE_PROFILE_ID_COLUMN = "device_profile_id";
public static final String OTA_PACKAGE_TYPE_COLUMN = "type";
public static final String OTA_PACKAGE_TILE_COLUMN = TITLE_PROPERTY;
public static final String OTA_PACKAGE_VERSION_COLUMN = "version";
public static final String OTA_PACKAGE_FILE_NAME_COLUMN = "file_name";
public static final String OTA_PACKAGE_CONTENT_TYPE_COLUMN = "content_type";
public static final String OTA_PACKAGE_CHECKSUM_ALGORITHM_COLUMN = "checksum_algorithm";
public static final String OTA_PACKAGE_CHECKSUM_COLUMN = "checksum";
public static final String OTA_PACKAGE_DATA_COLUMN = "data";
public static final String OTA_PACKAGE_DATA_SIZE_COLUMN = "data_size";
public static final String OTA_PACKAGE_ADDITIONAL_INFO_COLUMN = ADDITIONAL_INFO_PROPERTY;
/**
* Edge constants.

6
dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractDeviceEntity.java

@ -28,7 +28,7 @@ import org.thingsboard.server.common.data.device.data.DeviceData;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.data.id.FirmwareId;
import org.thingsboard.server.common.data.id.OtaPackageId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.dao.model.BaseSqlEntity;
import org.thingsboard.server.dao.model.ModelConstants;
@ -154,10 +154,10 @@ public abstract class AbstractDeviceEntity<T extends Device> extends BaseSqlEnti
device.setDeviceProfileId(new DeviceProfileId(deviceProfileId));
}
if (firmwareId != null) {
device.setFirmwareId(new FirmwareId(firmwareId));
device.setFirmwareId(new OtaPackageId(firmwareId));
}
if (softwareId != null) {
device.setSoftwareId(new FirmwareId(softwareId));
device.setSoftwareId(new OtaPackageId(softwareId));
}
device.setDeviceData(JacksonUtil.convertValue(deviceData, DeviceData.class));
device.setName(name);

6
dao/src/main/java/org/thingsboard/server/dao/model/sql/DeviceProfileEntity.java

@ -29,7 +29,7 @@ import org.thingsboard.server.common.data.DeviceTransportType;
import org.thingsboard.server.common.data.device.profile.DeviceProfileData;
import org.thingsboard.server.common.data.id.DashboardId;
import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.data.id.FirmwareId;
import org.thingsboard.server.common.data.id.OtaPackageId;
import org.thingsboard.server.common.data.id.RuleChainId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.dao.model.BaseSqlEntity;
@ -178,11 +178,11 @@ public final class DeviceProfileEntity extends BaseSqlEntity<DeviceProfile> impl
deviceProfile.setProvisionDeviceKey(provisionDeviceKey);
if (firmwareId != null) {
deviceProfile.setFirmwareId(new FirmwareId(firmwareId));
deviceProfile.setFirmwareId(new OtaPackageId(firmwareId));
}
if (softwareId != null) {
deviceProfile.setSoftwareId(new FirmwareId(softwareId));
deviceProfile.setSoftwareId(new OtaPackageId(softwareId));
}
return deviceProfile;

70
dao/src/main/java/org/thingsboard/server/dao/model/sql/FirmwareEntity.java → dao/src/main/java/org/thingsboard/server/dao/model/sql/OtaPackageEntity.java

@ -20,11 +20,11 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import org.hibernate.annotations.Type;
import org.hibernate.annotations.TypeDef;
import org.thingsboard.server.common.data.Firmware;
import org.thingsboard.server.common.data.firmware.ChecksumAlgorithm;
import org.thingsboard.server.common.data.firmware.FirmwareType;
import org.thingsboard.server.common.data.OtaPackage;
import org.thingsboard.server.common.data.ota.ChecksumAlgorithm;
import org.thingsboard.server.common.data.ota.OtaPackageType;
import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.data.id.FirmwareId;
import org.thingsboard.server.common.data.id.OtaPackageId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.dao.model.BaseSqlEntity;
import org.thingsboard.server.dao.model.ModelConstants;
@ -40,75 +40,75 @@ import javax.persistence.Table;
import java.nio.ByteBuffer;
import java.util.UUID;
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_CHECKSUM_ALGORITHM_COLUMN;
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_CHECKSUM_COLUMN;
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_CONTENT_TYPE_COLUMN;
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_DATA_COLUMN;
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_DATA_SIZE_COLUMN;
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_DEVICE_PROFILE_ID_COLUMN;
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_FILE_NAME_COLUMN;
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_TABLE_NAME;
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_TENANT_ID_COLUMN;
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_TITLE_COLUMN;
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_TYPE_COLUMN;
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_VERSION_COLUMN;
import static org.thingsboard.server.dao.model.ModelConstants.OTA_PACKAGE_CHECKSUM_ALGORITHM_COLUMN;
import static org.thingsboard.server.dao.model.ModelConstants.OTA_PACKAGE_CHECKSUM_COLUMN;
import static org.thingsboard.server.dao.model.ModelConstants.OTA_PACKAGE_CONTENT_TYPE_COLUMN;
import static org.thingsboard.server.dao.model.ModelConstants.OTA_PACKAGE_DATA_COLUMN;
import static org.thingsboard.server.dao.model.ModelConstants.OTA_PACKAGE_DATA_SIZE_COLUMN;
import static org.thingsboard.server.dao.model.ModelConstants.OTA_PACKAGE_DEVICE_PROFILE_ID_COLUMN;
import static org.thingsboard.server.dao.model.ModelConstants.OTA_PACKAGE_FILE_NAME_COLUMN;
import static org.thingsboard.server.dao.model.ModelConstants.OTA_PACKAGE_TABLE_NAME;
import static org.thingsboard.server.dao.model.ModelConstants.OTA_PACKAGE_TENANT_ID_COLUMN;
import static org.thingsboard.server.dao.model.ModelConstants.OTA_PACKAGE_TILE_COLUMN;
import static org.thingsboard.server.dao.model.ModelConstants.OTA_PACKAGE_TYPE_COLUMN;
import static org.thingsboard.server.dao.model.ModelConstants.OTA_PACKAGE_VERSION_COLUMN;
import static org.thingsboard.server.dao.model.ModelConstants.SEARCH_TEXT_PROPERTY;
@Data
@EqualsAndHashCode(callSuper = true)
@Entity
@TypeDef(name = "json", typeClass = JsonStringType.class)
@Table(name = FIRMWARE_TABLE_NAME)
public class FirmwareEntity extends BaseSqlEntity<Firmware> implements SearchTextEntity<Firmware> {
@Table(name = OTA_PACKAGE_TABLE_NAME)
public class OtaPackageEntity extends BaseSqlEntity<OtaPackage> implements SearchTextEntity<OtaPackage> {
@Column(name = FIRMWARE_TENANT_ID_COLUMN)
@Column(name = OTA_PACKAGE_TENANT_ID_COLUMN)
private UUID tenantId;
@Column(name = FIRMWARE_DEVICE_PROFILE_ID_COLUMN)
@Column(name = OTA_PACKAGE_DEVICE_PROFILE_ID_COLUMN)
private UUID deviceProfileId;
@Enumerated(EnumType.STRING)
@Column(name = FIRMWARE_TYPE_COLUMN)
private FirmwareType type;
@Column(name = OTA_PACKAGE_TYPE_COLUMN)
private OtaPackageType type;
@Column(name = FIRMWARE_TITLE_COLUMN)
@Column(name = OTA_PACKAGE_TILE_COLUMN)
private String title;
@Column(name = FIRMWARE_VERSION_COLUMN)
@Column(name = OTA_PACKAGE_VERSION_COLUMN)
private String version;
@Column(name = FIRMWARE_FILE_NAME_COLUMN)
@Column(name = OTA_PACKAGE_FILE_NAME_COLUMN)
private String fileName;
@Column(name = FIRMWARE_CONTENT_TYPE_COLUMN)
@Column(name = OTA_PACKAGE_CONTENT_TYPE_COLUMN)
private String contentType;
@Enumerated(EnumType.STRING)
@Column(name = FIRMWARE_CHECKSUM_ALGORITHM_COLUMN)
@Column(name = OTA_PACKAGE_CHECKSUM_ALGORITHM_COLUMN)
private ChecksumAlgorithm checksumAlgorithm;
@Column(name = FIRMWARE_CHECKSUM_COLUMN)
@Column(name = OTA_PACKAGE_CHECKSUM_COLUMN)
private String checksum;
@Lob
@Column(name = FIRMWARE_DATA_COLUMN, columnDefinition = "BINARY")
@Column(name = OTA_PACKAGE_DATA_COLUMN, columnDefinition = "BINARY")
private byte[] data;
@Column(name = FIRMWARE_DATA_SIZE_COLUMN)
@Column(name = OTA_PACKAGE_DATA_SIZE_COLUMN)
private Long dataSize;
@Type(type = "json")
@Column(name = ModelConstants.FIRMWARE_ADDITIONAL_INFO_COLUMN)
@Column(name = ModelConstants.OTA_PACKAGE_ADDITIONAL_INFO_COLUMN)
private JsonNode additionalInfo;
@Column(name = SEARCH_TEXT_PROPERTY)
private String searchText;
public FirmwareEntity() {
public OtaPackageEntity() {
super();
}
public FirmwareEntity(Firmware firmware) {
public OtaPackageEntity(OtaPackage firmware) {
this.createdTime = firmware.getCreatedTime();
this.setUuid(firmware.getUuidId());
this.tenantId = firmware.getTenantId().getId();
@ -138,8 +138,8 @@ public class FirmwareEntity extends BaseSqlEntity<Firmware> implements SearchTex
}
@Override
public Firmware toData() {
Firmware firmware = new Firmware(new FirmwareId(id));
public OtaPackage toData() {
OtaPackage firmware = new OtaPackage(new OtaPackageId(id));
firmware.setCreatedTime(createdTime);
firmware.setTenantId(new TenantId(tenantId));
if (deviceProfileId != null) {

72
dao/src/main/java/org/thingsboard/server/dao/model/sql/FirmwareInfoEntity.java → dao/src/main/java/org/thingsboard/server/dao/model/sql/OtaPackageInfoEntity.java

@ -21,11 +21,11 @@ import lombok.EqualsAndHashCode;
import org.hibernate.annotations.Type;
import org.hibernate.annotations.TypeDef;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.common.data.FirmwareInfo;
import org.thingsboard.server.common.data.firmware.ChecksumAlgorithm;
import org.thingsboard.server.common.data.firmware.FirmwareType;
import org.thingsboard.server.common.data.OtaPackageInfo;
import org.thingsboard.server.common.data.ota.ChecksumAlgorithm;
import org.thingsboard.server.common.data.ota.OtaPackageType;
import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.data.id.FirmwareId;
import org.thingsboard.server.common.data.id.OtaPackageId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.dao.model.BaseSqlEntity;
import org.thingsboard.server.dao.model.ModelConstants;
@ -40,60 +40,60 @@ import javax.persistence.Table;
import javax.persistence.Transient;
import java.util.UUID;
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_CHECKSUM_ALGORITHM_COLUMN;
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_CHECKSUM_COLUMN;
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_CONTENT_TYPE_COLUMN;
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_DATA_SIZE_COLUMN;
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_DEVICE_PROFILE_ID_COLUMN;
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_FILE_NAME_COLUMN;
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_TABLE_NAME;
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_TENANT_ID_COLUMN;
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_TITLE_COLUMN;
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_TYPE_COLUMN;
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_VERSION_COLUMN;
import static org.thingsboard.server.dao.model.ModelConstants.OTA_PACKAGE_CHECKSUM_ALGORITHM_COLUMN;
import static org.thingsboard.server.dao.model.ModelConstants.OTA_PACKAGE_CHECKSUM_COLUMN;
import static org.thingsboard.server.dao.model.ModelConstants.OTA_PACKAGE_CONTENT_TYPE_COLUMN;
import static org.thingsboard.server.dao.model.ModelConstants.OTA_PACKAGE_DATA_SIZE_COLUMN;
import static org.thingsboard.server.dao.model.ModelConstants.OTA_PACKAGE_DEVICE_PROFILE_ID_COLUMN;
import static org.thingsboard.server.dao.model.ModelConstants.OTA_PACKAGE_FILE_NAME_COLUMN;
import static org.thingsboard.server.dao.model.ModelConstants.OTA_PACKAGE_TABLE_NAME;
import static org.thingsboard.server.dao.model.ModelConstants.OTA_PACKAGE_TENANT_ID_COLUMN;
import static org.thingsboard.server.dao.model.ModelConstants.OTA_PACKAGE_TILE_COLUMN;
import static org.thingsboard.server.dao.model.ModelConstants.OTA_PACKAGE_TYPE_COLUMN;
import static org.thingsboard.server.dao.model.ModelConstants.OTA_PACKAGE_VERSION_COLUMN;
import static org.thingsboard.server.dao.model.ModelConstants.SEARCH_TEXT_PROPERTY;
@Data
@EqualsAndHashCode(callSuper = true)
@Entity
@TypeDef(name = "json", typeClass = JsonStringType.class)
@Table(name = FIRMWARE_TABLE_NAME)
public class FirmwareInfoEntity extends BaseSqlEntity<FirmwareInfo> implements SearchTextEntity<FirmwareInfo> {
@Table(name = OTA_PACKAGE_TABLE_NAME)
public class OtaPackageInfoEntity extends BaseSqlEntity<OtaPackageInfo> implements SearchTextEntity<OtaPackageInfo> {
@Column(name = FIRMWARE_TENANT_ID_COLUMN)
@Column(name = OTA_PACKAGE_TENANT_ID_COLUMN)
private UUID tenantId;
@Column(name = FIRMWARE_DEVICE_PROFILE_ID_COLUMN)
@Column(name = OTA_PACKAGE_DEVICE_PROFILE_ID_COLUMN)
private UUID deviceProfileId;
@Enumerated(EnumType.STRING)
@Column(name = FIRMWARE_TYPE_COLUMN)
private FirmwareType type;
@Column(name = OTA_PACKAGE_TYPE_COLUMN)
private OtaPackageType type;
@Column(name = FIRMWARE_TITLE_COLUMN)
@Column(name = OTA_PACKAGE_TILE_COLUMN)
private String title;
@Column(name = FIRMWARE_VERSION_COLUMN)
@Column(name = OTA_PACKAGE_VERSION_COLUMN)
private String version;
@Column(name = FIRMWARE_FILE_NAME_COLUMN)
@Column(name = OTA_PACKAGE_FILE_NAME_COLUMN)
private String fileName;
@Column(name = FIRMWARE_CONTENT_TYPE_COLUMN)
@Column(name = OTA_PACKAGE_CONTENT_TYPE_COLUMN)
private String contentType;
@Enumerated(EnumType.STRING)
@Column(name = FIRMWARE_CHECKSUM_ALGORITHM_COLUMN)
@Column(name = OTA_PACKAGE_CHECKSUM_ALGORITHM_COLUMN)
private ChecksumAlgorithm checksumAlgorithm;
@Column(name = FIRMWARE_CHECKSUM_COLUMN)
@Column(name = OTA_PACKAGE_CHECKSUM_COLUMN)
private String checksum;
@Column(name = FIRMWARE_DATA_SIZE_COLUMN)
@Column(name = OTA_PACKAGE_DATA_SIZE_COLUMN)
private Long dataSize;
@Type(type = "json")
@Column(name = ModelConstants.FIRMWARE_ADDITIONAL_INFO_COLUMN)
@Column(name = ModelConstants.OTA_PACKAGE_ADDITIONAL_INFO_COLUMN)
private JsonNode additionalInfo;
@Column(name = SEARCH_TEXT_PROPERTY)
@ -102,11 +102,11 @@ public class FirmwareInfoEntity extends BaseSqlEntity<FirmwareInfo> implements S
@Transient
private boolean hasData;
public FirmwareInfoEntity() {
public OtaPackageInfoEntity() {
super();
}
public FirmwareInfoEntity(FirmwareInfo firmware) {
public OtaPackageInfoEntity(OtaPackageInfo firmware) {
this.createdTime = firmware.getCreatedTime();
this.setUuid(firmware.getUuidId());
this.tenantId = firmware.getTenantId().getId();
@ -124,9 +124,9 @@ public class FirmwareInfoEntity extends BaseSqlEntity<FirmwareInfo> implements S
this.additionalInfo = firmware.getAdditionalInfo();
}
public FirmwareInfoEntity(UUID id, long createdTime, UUID tenantId, UUID deviceProfileId, FirmwareType type, String title, String version,
String fileName, String contentType, ChecksumAlgorithm checksumAlgorithm, String checksum, Long dataSize,
Object additionalInfo, boolean hasData) {
public OtaPackageInfoEntity(UUID id, long createdTime, UUID tenantId, UUID deviceProfileId, OtaPackageType type, String title, String version,
String fileName, String contentType, ChecksumAlgorithm checksumAlgorithm, String checksum, Long dataSize,
Object additionalInfo, boolean hasData) {
this.id = id;
this.createdTime = createdTime;
this.tenantId = tenantId;
@ -154,8 +154,8 @@ public class FirmwareInfoEntity extends BaseSqlEntity<FirmwareInfo> implements S
}
@Override
public FirmwareInfo toData() {
FirmwareInfo firmware = new FirmwareInfo(new FirmwareId(id));
public OtaPackageInfo toData() {
OtaPackageInfo firmware = new OtaPackageInfo(new OtaPackageId(id));
firmware.setCreatedTime(createdTime);
firmware.setTenantId(new TenantId(tenantId));
if (deviceProfileId != null) {

366
dao/src/main/java/org/thingsboard/server/dao/ota/BaseOtaPackageService.java

@ -0,0 +1,366 @@
/**
* Copyright © 2016-2021 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.dao.ota;
import com.google.common.hash.HashFunction;
import com.google.common.hash.Hashing;
import com.google.common.util.concurrent.ListenableFuture;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.exception.ConstraintViolationException;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.thingsboard.server.cache.ota.OtaPackageDataCache;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.OtaPackage;
import org.thingsboard.server.common.data.OtaPackageInfo;
import org.thingsboard.server.common.data.Tenant;
import org.thingsboard.server.common.data.ota.ChecksumAlgorithm;
import org.thingsboard.server.common.data.ota.OtaPackageType;
import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.data.id.OtaPackageId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.dao.device.DeviceProfileDao;
import org.thingsboard.server.dao.exception.DataValidationException;
import org.thingsboard.server.dao.service.DataValidator;
import org.thingsboard.server.dao.service.PaginatedRemover;
import org.thingsboard.server.dao.tenant.TenantDao;
import java.nio.ByteBuffer;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import static org.thingsboard.server.common.data.CacheConstants.OTA_PACKAGE_CACHE;
import static org.thingsboard.server.dao.service.Validator.validateId;
import static org.thingsboard.server.dao.service.Validator.validatePageLink;
@Service
@Slf4j
@RequiredArgsConstructor
public class BaseOtaPackageService implements OtaPackageService {
public static final String INCORRECT_OTA_PACKAGE_ID = "Incorrect otaPackageId ";
public static final String INCORRECT_TENANT_ID = "Incorrect tenantId ";
private final TenantDao tenantDao;
private final DeviceProfileDao deviceProfileDao;
private final OtaPackageDao otaPackageDao;
private final OtaPackageInfoDao otaPackageInfoDao;
private final CacheManager cacheManager;
private final OtaPackageDataCache otaPackageDataCache;
@Override
public OtaPackageInfo saveOtaPackageInfo(OtaPackageInfo otaPackageInfo) {
log.trace("Executing saveOtaPackageInfo [{}]", otaPackageInfo);
otaPackageInfoValidator.validate(otaPackageInfo, OtaPackageInfo::getTenantId);
try {
OtaPackageId otaPackageId = otaPackageInfo.getId();
if (otaPackageId != null) {
Cache cache = cacheManager.getCache(OTA_PACKAGE_CACHE);
cache.evict(toOtaPackageInfoKey(otaPackageId));
otaPackageDataCache.evict(otaPackageId.toString());
}
return otaPackageInfoDao.save(otaPackageInfo.getTenantId(), otaPackageInfo);
} catch (Exception t) {
ConstraintViolationException e = extractConstraintViolationException(t).orElse(null);
if (e != null && e.getConstraintName() != null && e.getConstraintName().equalsIgnoreCase("ota_package_tenant_title_version_unq_key")) {
throw new DataValidationException("OtaPackage with such title and version already exists!");
} else {
throw t;
}
}
}
@Override
public OtaPackage saveOtaPackage(OtaPackage otaPackage) {
log.trace("Executing saveOtaPackage [{}]", otaPackage);
otaPackageValidator.validate(otaPackage, OtaPackageInfo::getTenantId);
try {
OtaPackageId otaPackageId = otaPackage.getId();
if (otaPackageId != null) {
Cache cache = cacheManager.getCache(OTA_PACKAGE_CACHE);
cache.evict(toOtaPackageInfoKey(otaPackageId));
otaPackageDataCache.evict(otaPackageId.toString());
}
return otaPackageDao.save(otaPackage.getTenantId(), otaPackage);
} catch (Exception t) {
ConstraintViolationException e = extractConstraintViolationException(t).orElse(null);
if (e != null && e.getConstraintName() != null && e.getConstraintName().equalsIgnoreCase("ota_package_tenant_title_version_unq_key")) {
throw new DataValidationException("OtaPackage with such title and version already exists!");
} else {
throw t;
}
}
}
@Override
public String generateChecksum(ChecksumAlgorithm checksumAlgorithm, ByteBuffer data) {
if (data == null || !data.hasArray() || data.array().length == 0) {
throw new DataValidationException("OtaPackage data should be specified!");
}
return getHashFunction(checksumAlgorithm).hashBytes(data.array()).toString();
}
private HashFunction getHashFunction(ChecksumAlgorithm checksumAlgorithm) {
switch (checksumAlgorithm) {
case MD5:
return Hashing.md5();
case SHA256:
return Hashing.sha256();
case SHA384:
return Hashing.sha384();
case SHA512:
return Hashing.sha512();
case CRC32:
return Hashing.crc32();
case MURMUR3_32:
return Hashing.murmur3_32();
case MURMUR3_128:
return Hashing.murmur3_128();
default:
throw new DataValidationException("Unknown checksum algorithm!");
}
}
@Override
public OtaPackage findOtaPackageById(TenantId tenantId, OtaPackageId otaPackageId) {
log.trace("Executing findOtaPackageById [{}]", otaPackageId);
validateId(otaPackageId, INCORRECT_OTA_PACKAGE_ID + otaPackageId);
return otaPackageDao.findById(tenantId, otaPackageId.getId());
}
@Override
@Cacheable(cacheNames = OTA_PACKAGE_CACHE, key = "{#otaPackageId}")
public OtaPackageInfo findOtaPackageInfoById(TenantId tenantId, OtaPackageId otaPackageId) {
log.trace("Executing findOtaPackageInfoById [{}]", otaPackageId);
validateId(otaPackageId, INCORRECT_OTA_PACKAGE_ID + otaPackageId);
return otaPackageInfoDao.findById(tenantId, otaPackageId.getId());
}
@Override
public ListenableFuture<OtaPackageInfo> findOtaPackageInfoByIdAsync(TenantId tenantId, OtaPackageId otaPackageId) {
log.trace("Executing findOtaPackageInfoByIdAsync [{}]", otaPackageId);
validateId(otaPackageId, INCORRECT_OTA_PACKAGE_ID + otaPackageId);
return otaPackageInfoDao.findByIdAsync(tenantId, otaPackageId.getId());
}
@Override
public PageData<OtaPackageInfo> findTenantOtaPackagesByTenantId(TenantId tenantId, PageLink pageLink) {
log.trace("Executing findTenantOtaPackagesByTenantId, tenantId [{}], pageLink [{}]", tenantId, pageLink);
validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
validatePageLink(pageLink);
return otaPackageInfoDao.findOtaPackageInfoByTenantId(tenantId, pageLink);
}
@Override
public PageData<OtaPackageInfo> findTenantOtaPackagesByTenantIdAndDeviceProfileIdAndTypeAndHasData(TenantId tenantId, DeviceProfileId deviceProfileId, OtaPackageType otaPackageType, boolean hasData, PageLink pageLink) {
log.trace("Executing findTenantOtaPackagesByTenantIdAndHasData, tenantId [{}], hasData [{}] pageLink [{}]", tenantId, hasData, pageLink);
validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
validatePageLink(pageLink);
return otaPackageInfoDao.findOtaPackageInfoByTenantIdAndDeviceProfileIdAndTypeAndHasData(tenantId, deviceProfileId, otaPackageType, hasData, pageLink);
}
@Override
public void deleteOtaPackage(TenantId tenantId, OtaPackageId otaPackageId) {
log.trace("Executing deleteOtaPackage [{}]", otaPackageId);
validateId(otaPackageId, INCORRECT_OTA_PACKAGE_ID + otaPackageId);
try {
Cache cache = cacheManager.getCache(OTA_PACKAGE_CACHE);
cache.evict(toOtaPackageInfoKey(otaPackageId));
otaPackageDataCache.evict(otaPackageId.toString());
otaPackageDao.removeById(tenantId, otaPackageId.getId());
} catch (Exception t) {
ConstraintViolationException e = extractConstraintViolationException(t).orElse(null);
if (e != null && e.getConstraintName() != null && e.getConstraintName().equalsIgnoreCase("fk_firmware_device")) {
throw new DataValidationException("The otaPackage referenced by the devices cannot be deleted!");
} else if (e != null && e.getConstraintName() != null && e.getConstraintName().equalsIgnoreCase("fk_firmware_device_profile")) {
throw new DataValidationException("The otaPackage referenced by the device profile cannot be deleted!");
} else if (e != null && e.getConstraintName() != null && e.getConstraintName().equalsIgnoreCase("fk_software_device")) {
throw new DataValidationException("The software referenced by the devices cannot be deleted!");
} else if (e != null && e.getConstraintName() != null && e.getConstraintName().equalsIgnoreCase("fk_software_device_profile")) {
throw new DataValidationException("The software referenced by the device profile cannot be deleted!");
} else {
throw t;
}
}
}
@Override
public void deleteOtaPackagesByTenantId(TenantId tenantId) {
log.trace("Executing deleteOtaPackagesByTenantId, tenantId [{}]", tenantId);
validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
tenantOtaPackageRemover.removeEntities(tenantId, tenantId);
}
private DataValidator<OtaPackageInfo> otaPackageInfoValidator = new DataValidator<>() {
@Override
protected void validateDataImpl(TenantId tenantId, OtaPackageInfo otaPackageInfo) {
validateImpl(otaPackageInfo);
}
@Override
protected void validateUpdate(TenantId tenantId, OtaPackageInfo otaPackage) {
OtaPackageInfo otaPackageOld = otaPackageInfoDao.findById(tenantId, otaPackage.getUuidId());
BaseOtaPackageService.validateUpdate(otaPackage, otaPackageOld);
}
};
private DataValidator<OtaPackage> otaPackageValidator = new DataValidator<>() {
@Override
protected void validateDataImpl(TenantId tenantId, OtaPackage otaPackage) {
validateImpl(otaPackage);
if (StringUtils.isEmpty(otaPackage.getFileName())) {
throw new DataValidationException("OtaPackage file name should be specified!");
}
if (StringUtils.isEmpty(otaPackage.getContentType())) {
throw new DataValidationException("OtaPackage content type should be specified!");
}
if (otaPackage.getChecksumAlgorithm() == null) {
throw new DataValidationException("OtaPackage checksum algorithm should be specified!");
}
if (StringUtils.isEmpty(otaPackage.getChecksum())) {
throw new DataValidationException("OtaPackage checksum should be specified!");
}
String currentChecksum;
currentChecksum = generateChecksum(otaPackage.getChecksumAlgorithm(), otaPackage.getData());
if (!currentChecksum.equals(otaPackage.getChecksum())) {
throw new DataValidationException("Wrong otaPackage file!");
}
}
@Override
protected void validateUpdate(TenantId tenantId, OtaPackage otaPackage) {
OtaPackage otaPackageOld = otaPackageDao.findById(tenantId, otaPackage.getUuidId());
BaseOtaPackageService.validateUpdate(otaPackage, otaPackageOld);
if (otaPackageOld.getData() != null && !otaPackageOld.getData().equals(otaPackage.getData())) {
throw new DataValidationException("Updating otaPackage data is prohibited!");
}
}
};
private static void validateUpdate(OtaPackageInfo otaPackage, OtaPackageInfo otaPackageOld) {
if (!otaPackageOld.getType().equals(otaPackage.getType())) {
throw new DataValidationException("Updating type is prohibited!");
}
if (!otaPackageOld.getTitle().equals(otaPackage.getTitle())) {
throw new DataValidationException("Updating otaPackage title is prohibited!");
}
if (!otaPackageOld.getVersion().equals(otaPackage.getVersion())) {
throw new DataValidationException("Updating otaPackage version is prohibited!");
}
if (!otaPackageOld.getDeviceProfileId().equals(otaPackage.getDeviceProfileId())) {
throw new DataValidationException("Updating otaPackage deviceProfile is prohibited!");
}
if (otaPackageOld.getFileName() != null && !otaPackageOld.getFileName().equals(otaPackage.getFileName())) {
throw new DataValidationException("Updating otaPackage file name is prohibited!");
}
if (otaPackageOld.getContentType() != null && !otaPackageOld.getContentType().equals(otaPackage.getContentType())) {
throw new DataValidationException("Updating otaPackage content type is prohibited!");
}
if (otaPackageOld.getChecksumAlgorithm() != null && !otaPackageOld.getChecksumAlgorithm().equals(otaPackage.getChecksumAlgorithm())) {
throw new DataValidationException("Updating otaPackage content type is prohibited!");
}
if (otaPackageOld.getChecksum() != null && !otaPackageOld.getChecksum().equals(otaPackage.getChecksum())) {
throw new DataValidationException("Updating otaPackage content type is prohibited!");
}
if (otaPackageOld.getDataSize() != null && !otaPackageOld.getDataSize().equals(otaPackage.getDataSize())) {
throw new DataValidationException("Updating otaPackage data size is prohibited!");
}
}
private void validateImpl(OtaPackageInfo otaPackageInfo) {
if (otaPackageInfo.getTenantId() == null) {
throw new DataValidationException("OtaPackage should be assigned to tenant!");
} else {
Tenant tenant = tenantDao.findById(otaPackageInfo.getTenantId(), otaPackageInfo.getTenantId().getId());
if (tenant == null) {
throw new DataValidationException("OtaPackage is referencing to non-existent tenant!");
}
}
if (otaPackageInfo.getDeviceProfileId() != null) {
DeviceProfile deviceProfile = deviceProfileDao.findById(otaPackageInfo.getTenantId(), otaPackageInfo.getDeviceProfileId().getId());
if (deviceProfile == null) {
throw new DataValidationException("OtaPackage is referencing to non-existent device profile!");
}
}
if (otaPackageInfo.getType() == null) {
throw new DataValidationException("Type should be specified!");
}
if (StringUtils.isEmpty(otaPackageInfo.getTitle())) {
throw new DataValidationException("OtaPackage title should be specified!");
}
if (StringUtils.isEmpty(otaPackageInfo.getVersion())) {
throw new DataValidationException("OtaPackage version should be specified!");
}
}
private PaginatedRemover<TenantId, OtaPackageInfo> tenantOtaPackageRemover =
new PaginatedRemover<>() {
@Override
protected PageData<OtaPackageInfo> findEntities(TenantId tenantId, TenantId id, PageLink pageLink) {
return otaPackageInfoDao.findOtaPackageInfoByTenantId(id, pageLink);
}
@Override
protected void removeEntity(TenantId tenantId, OtaPackageInfo entity) {
deleteOtaPackage(tenantId, entity.getId());
}
};
protected Optional<ConstraintViolationException> extractConstraintViolationException(Exception t) {
if (t instanceof ConstraintViolationException) {
return Optional.of((ConstraintViolationException) t);
} else if (t.getCause() instanceof ConstraintViolationException) {
return Optional.of((ConstraintViolationException) (t.getCause()));
} else {
return Optional.empty();
}
}
private static List<OtaPackageId> toOtaPackageInfoKey(OtaPackageId otaPackageId) {
return Collections.singletonList(otaPackageId);
}
}

6
dao/src/main/java/org/thingsboard/server/dao/firmware/FirmwareDao.java → dao/src/main/java/org/thingsboard/server/dao/ota/OtaPackageDao.java

@ -13,11 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.dao.firmware;
package org.thingsboard.server.dao.ota;
import org.thingsboard.server.common.data.Firmware;
import org.thingsboard.server.common.data.OtaPackage;
import org.thingsboard.server.dao.Dao;
public interface FirmwareDao extends Dao<Firmware> {
public interface OtaPackageDao extends Dao<OtaPackage> {
}

18
dao/src/main/java/org/thingsboard/server/dao/firmware/FirmwareInfoDao.java → dao/src/main/java/org/thingsboard/server/dao/ota/OtaPackageInfoDao.java

@ -13,25 +13,23 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.dao.firmware;
package org.thingsboard.server.dao.ota;
import org.thingsboard.server.common.data.FirmwareInfo;
import org.thingsboard.server.common.data.firmware.FirmwareType;
import org.thingsboard.server.common.data.OtaPackageInfo;
import org.thingsboard.server.common.data.ota.OtaPackageType;
import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.data.id.FirmwareId;
import org.thingsboard.server.common.data.id.OtaPackageId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.dao.Dao;
import java.util.UUID;
public interface OtaPackageInfoDao extends Dao<OtaPackageInfo> {
public interface FirmwareInfoDao extends Dao<FirmwareInfo> {
PageData<OtaPackageInfo> findOtaPackageInfoByTenantId(TenantId tenantId, PageLink pageLink);
PageData<FirmwareInfo> findFirmwareInfoByTenantId(TenantId tenantId, PageLink pageLink);
PageData<OtaPackageInfo> findOtaPackageInfoByTenantIdAndDeviceProfileIdAndTypeAndHasData(TenantId tenantId, DeviceProfileId deviceProfileId, OtaPackageType otaPackageType, boolean hasData, PageLink pageLink);
PageData<FirmwareInfo> findFirmwareInfoByTenantIdAndDeviceProfileIdAndTypeAndHasData(TenantId tenantId, DeviceProfileId deviceProfileId, FirmwareType firmwareType, boolean hasData, PageLink pageLink);
boolean isFirmwareUsed(FirmwareId firmwareId, FirmwareType type, DeviceProfileId deviceProfileId);
boolean isOtaPackageUsed(OtaPackageId otaPackageId, OtaPackageType otaPackageType, DeviceProfileId deviceProfileId);
}

20
dao/src/main/java/org/thingsboard/server/dao/sql/device/DeviceRepository.java

@ -96,23 +96,35 @@ public interface DeviceRepository extends PagingAndSortingRepository<DeviceEntit
Pageable pageable);
@Query("SELECT d FROM DeviceEntity d WHERE d.tenantId = :tenantId " +
"AND d.type = :type " +
"AND d.deviceProfileId = :deviceProfileId " +
"AND d.firmwareId = null " +
"AND LOWER(d.searchText) LIKE LOWER(CONCAT(:textSearch, '%'))")
Page<DeviceEntity> findByTenantIdAndTypeAndFirmwareIdIsNull(@Param("tenantId") UUID tenantId,
@Param("type") String type,
@Param("deviceProfileId") UUID deviceProfileId,
@Param("textSearch") String textSearch,
Pageable pageable);
@Query("SELECT d FROM DeviceEntity d WHERE d.tenantId = :tenantId " +
"AND d.type = :type " +
"AND d.deviceProfileId = :deviceProfileId " +
"AND d.softwareId = null " +
"AND LOWER(d.searchText) LIKE LOWER(CONCAT(:textSearch, '%'))")
Page<DeviceEntity> findByTenantIdAndTypeAndSoftwareIdIsNull(@Param("tenantId") UUID tenantId,
@Param("type") String type,
@Param("deviceProfileId") UUID deviceProfileId,
@Param("textSearch") String textSearch,
Pageable pageable);
@Query("SELECT count(*) FROM DeviceEntity d WHERE d.tenantId = :tenantId " +
"AND d.deviceProfileId = :deviceProfileId " +
"AND d.firmwareId = null")
Long countByTenantIdAndDeviceProfileIdAndFirmwareIdIsNull(@Param("tenantId") UUID tenantId,
@Param("deviceProfileId") UUID deviceProfileId);
@Query("SELECT count(*) FROM DeviceEntity d WHERE d.tenantId = :tenantId " +
"AND d.deviceProfileId = :deviceProfileId " +
"AND d.softwareId = null")
Long countByTenantIdAndDeviceProfileIdAndSoftwareIdIsNull(@Param("tenantId") UUID tenantId,
@Param("deviceProfileId") UUID deviceProfileId);
@Query("SELECT new org.thingsboard.server.dao.model.sql.DeviceInfoEntity(d, c.title, c.additionalInfo, p.name) " +
"FROM DeviceEntity d " +
"LEFT JOIN CustomerEntity c on c.id = d.customerId " +

36
dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceDao.java

@ -18,6 +18,8 @@ package org.thingsboard.server.dao.sql.device;
import com.google.common.util.concurrent.ListenableFuture;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
@ -27,6 +29,8 @@ import org.thingsboard.server.common.data.DeviceTransportType;
import org.thingsboard.server.common.data.EntitySubtype;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.ota.OtaPackageType;
import org.thingsboard.server.common.data.ota.OtaPackageUtil;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.dao.DaoUtil;
@ -155,23 +159,27 @@ public class JpaDeviceDao extends JpaAbstractSearchTextDao<DeviceEntity, Device>
}
@Override
public PageData<Device> findDevicesByTenantIdAndTypeAndEmptyFirmware(UUID tenantId, String type, PageLink pageLink) {
return DaoUtil.toPageData(
deviceRepository.findByTenantIdAndTypeAndFirmwareIdIsNull(
tenantId,
type,
Objects.toString(pageLink.getTextSearch(), ""),
DaoUtil.toPageable(pageLink)));
public PageData<Device> findDevicesByTenantIdAndTypeAndEmptyOtaPackage(UUID tenantId,
UUID deviceProfileId,
OtaPackageType type,
PageLink pageLink) {
Pageable pageable = DaoUtil.toPageable(pageLink);
String searchText = Objects.toString(pageLink.getTextSearch(), "");
Page<DeviceEntity> page = OtaPackageUtil.getByOtaPackageType(
() -> deviceRepository.findByTenantIdAndTypeAndFirmwareIdIsNull(tenantId, deviceProfileId, searchText, pageable),
() -> deviceRepository.findByTenantIdAndTypeAndSoftwareIdIsNull(tenantId, deviceProfileId, searchText, pageable),
type
);
return DaoUtil.toPageData(page);
}
@Override
public PageData<Device> findDevicesByTenantIdAndTypeAndEmptySoftware(UUID tenantId, String type, PageLink pageLink) {
return DaoUtil.toPageData(
deviceRepository.findByTenantIdAndTypeAndSoftwareIdIsNull(
tenantId,
type,
Objects.toString(pageLink.getTextSearch(), ""),
DaoUtil.toPageable(pageLink)));
public Long countDevicesByTenantIdAndDeviceProfileIdAndEmptyOtaPackage(UUID tenantId, UUID deviceProfileId, OtaPackageType type) {
return OtaPackageUtil.getByOtaPackageType(
() -> deviceRepository.countByTenantIdAndDeviceProfileIdAndFirmwareIdIsNull(tenantId, deviceProfileId),
() -> deviceRepository.countByTenantIdAndDeviceProfileIdAndSoftwareIdIsNull(tenantId, deviceProfileId),
type
);
}
@Override

60
dao/src/main/java/org/thingsboard/server/dao/sql/firmware/FirmwareInfoRepository.java

@ -1,60 +0,0 @@
/**
* Copyright © 2016-2021 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.dao.sql.firmware;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
import org.thingsboard.server.common.data.firmware.FirmwareType;
import org.thingsboard.server.dao.model.sql.FirmwareInfoEntity;
import java.util.UUID;
public interface FirmwareInfoRepository extends CrudRepository<FirmwareInfoEntity, UUID> {
@Query("SELECT new FirmwareInfoEntity(f.id, f.createdTime, f.tenantId, f.deviceProfileId, f.type, f.title, f.version, f.fileName, f.contentType, f.checksumAlgorithm, f.checksum, f.dataSize, f.additionalInfo, f.data IS NOT NULL) FROM FirmwareEntity f WHERE " +
"f.tenantId = :tenantId " +
"AND LOWER(f.searchText) LIKE LOWER(CONCAT(:searchText, '%'))")
Page<FirmwareInfoEntity> findAllByTenantId(@Param("tenantId") UUID tenantId,
@Param("searchText") String searchText,
Pageable pageable);
@Query("SELECT new FirmwareInfoEntity(f.id, f.createdTime, f.tenantId, f.deviceProfileId, f.type, f.title, f.version, f.fileName, f.contentType, f.checksumAlgorithm, f.checksum, f.dataSize, f.additionalInfo, f.data IS NOT NULL) FROM FirmwareEntity f WHERE " +
"f.tenantId = :tenantId " +
"AND f.deviceProfileId = :deviceProfileId " +
"AND f.type = :type " +
"AND ((f.data IS NOT NULL AND :hasData = true) OR (f.data IS NULL AND :hasData = false ))" +
"AND LOWER(f.searchText) LIKE LOWER(CONCAT(:searchText, '%'))")
Page<FirmwareInfoEntity> findAllByTenantIdAndTypeAndDeviceProfileIdAndHasData(@Param("tenantId") UUID tenantId,
@Param("deviceProfileId") UUID deviceProfileId,
@Param("type") FirmwareType type,
@Param("hasData") boolean hasData,
@Param("searchText") String searchText,
Pageable pageable);
@Query("SELECT new FirmwareInfoEntity(f.id, f.createdTime, f.tenantId, f.deviceProfileId, f.type, f.title, f.version, f.fileName, f.contentType, f.checksumAlgorithm, f.checksum, f.dataSize, f.additionalInfo, f.data IS NOT NULL) FROM FirmwareEntity f WHERE f.id = :id")
FirmwareInfoEntity findFirmwareInfoById(@Param("id") UUID id);
@Query(value = "SELECT exists(SELECT * " +
"FROM device_profile AS dp " +
"LEFT JOIN device AS d ON dp.id = d.device_profile_id " +
"WHERE dp.id = :deviceProfileId AND " +
"(('FIRMWARE' = :type AND (dp.firmware_id = :firmwareId OR d.firmware_id = :firmwareId)) " +
"OR ('SOFTWARE' = :type AND (dp.software_id = :firmwareId or d.software_id = :firmwareId))))", nativeQuery = true)
boolean isFirmwareUsed(@Param("firmwareId") UUID firmwareId, @Param("deviceProfileId") UUID deviceProfileId, @Param("type") String type);
}

94
dao/src/main/java/org/thingsboard/server/dao/sql/firmware/JpaFirmwareInfoDao.java

@ -1,94 +0,0 @@
/**
* Copyright © 2016-2021 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.dao.sql.firmware;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.FirmwareInfo;
import org.thingsboard.server.common.data.firmware.FirmwareType;
import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.data.id.FirmwareId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.dao.DaoUtil;
import org.thingsboard.server.dao.firmware.FirmwareInfoDao;
import org.thingsboard.server.dao.model.sql.FirmwareInfoEntity;
import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao;
import java.util.Objects;
import java.util.UUID;
@Slf4j
@Component
public class JpaFirmwareInfoDao extends JpaAbstractSearchTextDao<FirmwareInfoEntity, FirmwareInfo> implements FirmwareInfoDao {
@Autowired
private FirmwareInfoRepository firmwareInfoRepository;
@Override
protected Class<FirmwareInfoEntity> getEntityClass() {
return FirmwareInfoEntity.class;
}
@Override
protected CrudRepository<FirmwareInfoEntity, UUID> getCrudRepository() {
return firmwareInfoRepository;
}
@Override
public FirmwareInfo findById(TenantId tenantId, UUID id) {
return DaoUtil.getData(firmwareInfoRepository.findFirmwareInfoById(id));
}
@Override
public FirmwareInfo save(TenantId tenantId, FirmwareInfo firmwareInfo) {
FirmwareInfo savedFirmware = super.save(tenantId, firmwareInfo);
if (firmwareInfo.getId() == null) {
return savedFirmware;
} else {
return findById(tenantId, savedFirmware.getId().getId());
}
}
@Override
public PageData<FirmwareInfo> findFirmwareInfoByTenantId(TenantId tenantId, PageLink pageLink) {
return DaoUtil.toPageData(firmwareInfoRepository
.findAllByTenantId(
tenantId.getId(),
Objects.toString(pageLink.getTextSearch(), ""),
DaoUtil.toPageable(pageLink)));
}
@Override
public PageData<FirmwareInfo> findFirmwareInfoByTenantIdAndDeviceProfileIdAndTypeAndHasData(TenantId tenantId, DeviceProfileId deviceProfileId, FirmwareType firmwareType, boolean hasData, PageLink pageLink) {
return DaoUtil.toPageData(firmwareInfoRepository
.findAllByTenantIdAndTypeAndDeviceProfileIdAndHasData(
tenantId.getId(),
deviceProfileId.getId(),
firmwareType,
hasData,
Objects.toString(pageLink.getTextSearch(), ""),
DaoUtil.toPageable(pageLink)));
}
@Override
public boolean isFirmwareUsed(FirmwareId firmwareId, FirmwareType type, DeviceProfileId deviceProfileId) {
return firmwareInfoRepository.isFirmwareUsed(firmwareId.getId(), deviceProfileId.getId(), type.name());
}
}

20
dao/src/main/java/org/thingsboard/server/dao/sql/firmware/JpaFirmwareDao.java → dao/src/main/java/org/thingsboard/server/dao/sql/ota/JpaOtaPackageDao.java

@ -13,34 +13,34 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.dao.sql.firmware;
package org.thingsboard.server.dao.sql.ota;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.Firmware;
import org.thingsboard.server.dao.firmware.FirmwareDao;
import org.thingsboard.server.dao.model.sql.FirmwareEntity;
import org.thingsboard.server.common.data.OtaPackage;
import org.thingsboard.server.dao.ota.OtaPackageDao;
import org.thingsboard.server.dao.model.sql.OtaPackageEntity;
import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao;
import java.util.UUID;
@Slf4j
@Component
public class JpaFirmwareDao extends JpaAbstractSearchTextDao<FirmwareEntity, Firmware> implements FirmwareDao {
public class JpaOtaPackageDao extends JpaAbstractSearchTextDao<OtaPackageEntity, OtaPackage> implements OtaPackageDao {
@Autowired
private FirmwareRepository firmwareRepository;
private OtaPackageRepository otaPackageRepository;
@Override
protected Class<FirmwareEntity> getEntityClass() {
return FirmwareEntity.class;
protected Class<OtaPackageEntity> getEntityClass() {
return OtaPackageEntity.class;
}
@Override
protected CrudRepository<FirmwareEntity, UUID> getCrudRepository() {
return firmwareRepository;
protected CrudRepository<OtaPackageEntity, UUID> getCrudRepository() {
return otaPackageRepository;
}
}

94
dao/src/main/java/org/thingsboard/server/dao/sql/ota/JpaOtaPackageInfoDao.java

@ -0,0 +1,94 @@
/**
* Copyright © 2016-2021 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.dao.sql.ota;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.OtaPackageInfo;
import org.thingsboard.server.common.data.ota.OtaPackageType;
import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.data.id.OtaPackageId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.dao.DaoUtil;
import org.thingsboard.server.dao.ota.OtaPackageInfoDao;
import org.thingsboard.server.dao.model.sql.OtaPackageInfoEntity;
import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao;
import java.util.Objects;
import java.util.UUID;
@Slf4j
@Component
public class JpaOtaPackageInfoDao extends JpaAbstractSearchTextDao<OtaPackageInfoEntity, OtaPackageInfo> implements OtaPackageInfoDao {
@Autowired
private OtaPackageInfoRepository otaPackageInfoRepository;
@Override
protected Class<OtaPackageInfoEntity> getEntityClass() {
return OtaPackageInfoEntity.class;
}
@Override
protected CrudRepository<OtaPackageInfoEntity, UUID> getCrudRepository() {
return otaPackageInfoRepository;
}
@Override
public OtaPackageInfo findById(TenantId tenantId, UUID id) {
return DaoUtil.getData(otaPackageInfoRepository.findOtaPackageInfoById(id));
}
@Override
public OtaPackageInfo save(TenantId tenantId, OtaPackageInfo otaPackageInfo) {
OtaPackageInfo savedOtaPackage = super.save(tenantId, otaPackageInfo);
if (otaPackageInfo.getId() == null) {
return savedOtaPackage;
} else {
return findById(tenantId, savedOtaPackage.getId().getId());
}
}
@Override
public PageData<OtaPackageInfo> findOtaPackageInfoByTenantId(TenantId tenantId, PageLink pageLink) {
return DaoUtil.toPageData(otaPackageInfoRepository
.findAllByTenantId(
tenantId.getId(),
Objects.toString(pageLink.getTextSearch(), ""),
DaoUtil.toPageable(pageLink)));
}
@Override
public PageData<OtaPackageInfo> findOtaPackageInfoByTenantIdAndDeviceProfileIdAndTypeAndHasData(TenantId tenantId, DeviceProfileId deviceProfileId, OtaPackageType otaPackageType, boolean hasData, PageLink pageLink) {
return DaoUtil.toPageData(otaPackageInfoRepository
.findAllByTenantIdAndTypeAndDeviceProfileIdAndHasData(
tenantId.getId(),
deviceProfileId.getId(),
otaPackageType,
hasData,
Objects.toString(pageLink.getTextSearch(), ""),
DaoUtil.toPageable(pageLink)));
}
@Override
public boolean isOtaPackageUsed(OtaPackageId otaPackageId, OtaPackageType otaPackageType, DeviceProfileId deviceProfileId) {
return otaPackageInfoRepository.isOtaPackageUsed(otaPackageId.getId(), deviceProfileId.getId(), otaPackageType.name());
}
}

60
dao/src/main/java/org/thingsboard/server/dao/sql/ota/OtaPackageInfoRepository.java

@ -0,0 +1,60 @@
/**
* Copyright © 2016-2021 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.dao.sql.ota;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
import org.thingsboard.server.common.data.ota.OtaPackageType;
import org.thingsboard.server.dao.model.sql.OtaPackageInfoEntity;
import java.util.UUID;
public interface OtaPackageInfoRepository extends CrudRepository<OtaPackageInfoEntity, UUID> {
@Query("SELECT new OtaPackageInfoEntity(f.id, f.createdTime, f.tenantId, f.deviceProfileId, f.type, f.title, f.version, f.fileName, f.contentType, f.checksumAlgorithm, f.checksum, f.dataSize, f.additionalInfo, f.data IS NOT NULL) FROM OtaPackageEntity f WHERE " +
"f.tenantId = :tenantId " +
"AND LOWER(f.searchText) LIKE LOWER(CONCAT(:searchText, '%'))")
Page<OtaPackageInfoEntity> findAllByTenantId(@Param("tenantId") UUID tenantId,
@Param("searchText") String searchText,
Pageable pageable);
@Query("SELECT new OtaPackageInfoEntity(f.id, f.createdTime, f.tenantId, f.deviceProfileId, f.type, f.title, f.version, f.fileName, f.contentType, f.checksumAlgorithm, f.checksum, f.dataSize, f.additionalInfo, f.data IS NOT NULL) FROM OtaPackageEntity f WHERE " +
"f.tenantId = :tenantId " +
"AND f.deviceProfileId = :deviceProfileId " +
"AND f.type = :type " +
"AND ((f.data IS NOT NULL AND :hasData = true) OR (f.data IS NULL AND :hasData = false ))" +
"AND LOWER(f.searchText) LIKE LOWER(CONCAT(:searchText, '%'))")
Page<OtaPackageInfoEntity> findAllByTenantIdAndTypeAndDeviceProfileIdAndHasData(@Param("tenantId") UUID tenantId,
@Param("deviceProfileId") UUID deviceProfileId,
@Param("type") OtaPackageType type,
@Param("hasData") boolean hasData,
@Param("searchText") String searchText,
Pageable pageable);
@Query("SELECT new OtaPackageInfoEntity(f.id, f.createdTime, f.tenantId, f.deviceProfileId, f.type, f.title, f.version, f.fileName, f.contentType, f.checksumAlgorithm, f.checksum, f.dataSize, f.additionalInfo, f.data IS NOT NULL) FROM OtaPackageEntity f WHERE f.id = :id")
OtaPackageInfoEntity findOtaPackageInfoById(@Param("id") UUID id);
@Query(value = "SELECT exists(SELECT * " +
"FROM device_profile AS dp " +
"LEFT JOIN device AS d ON dp.id = d.device_profile_id " +
"WHERE dp.id = :deviceProfileId AND " +
"(('FIRMWARE' = :type AND (dp.firmware_id = :otaPackageId OR d.firmware_id = :otaPackageId)) " +
"OR ('SOFTWARE' = :type AND (dp.software_id = :otaPackageId or d.software_id = :otaPackageId))))", nativeQuery = true)
boolean isOtaPackageUsed(@Param("otaPackageId") UUID otaPackageId, @Param("deviceProfileId") UUID deviceProfileId, @Param("type") String type);
}

6
dao/src/main/java/org/thingsboard/server/dao/sql/firmware/FirmwareRepository.java → dao/src/main/java/org/thingsboard/server/dao/sql/ota/OtaPackageRepository.java

@ -13,12 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.dao.sql.firmware;
package org.thingsboard.server.dao.sql.ota;
import org.springframework.data.repository.CrudRepository;
import org.thingsboard.server.dao.model.sql.FirmwareEntity;
import org.thingsboard.server.dao.model.sql.OtaPackageEntity;
import java.util.UUID;
public interface FirmwareRepository extends CrudRepository<FirmwareEntity, UUID> {
public interface OtaPackageRepository extends CrudRepository<OtaPackageEntity, UUID> {
}

6
dao/src/main/java/org/thingsboard/server/dao/tenant/TenantServiceImpl.java

@ -35,7 +35,7 @@ import org.thingsboard.server.dao.device.DeviceService;
import org.thingsboard.server.dao.entity.AbstractEntityService;
import org.thingsboard.server.dao.entityview.EntityViewService;
import org.thingsboard.server.dao.exception.DataValidationException;
import org.thingsboard.server.dao.firmware.FirmwareService;
import org.thingsboard.server.dao.ota.OtaPackageService;
import org.thingsboard.server.dao.resource.ResourceService;
import org.thingsboard.server.dao.rule.RuleChainService;
import org.thingsboard.server.dao.service.DataValidator;
@ -94,7 +94,7 @@ public class TenantServiceImpl extends AbstractEntityService implements TenantSe
private ResourceService resourceService;
@Autowired
private FirmwareService firmwareService;
private OtaPackageService otaPackageService;
@Override
public Tenant findTenantById(TenantId tenantId) {
@ -150,7 +150,7 @@ public class TenantServiceImpl extends AbstractEntityService implements TenantSe
ruleChainService.deleteRuleChainsByTenantId(tenantId);
apiUsageStateService.deleteApiUsageStateByTenantId(tenantId);
resourceService.deleteResourcesByTenantId(tenantId);
firmwareService.deleteFirmwaresByTenantId(tenantId);
otaPackageService.deleteOtaPackagesByTenantId(tenantId);
tenantDao.removeById(tenantId, tenantId.getId());
deleteEntityRelations(tenantId, tenantId);
}

14
dao/src/main/resources/sql/schema-entities-hsql.sql

@ -160,8 +160,8 @@ CREATE TABLE IF NOT EXISTS rule_node_state (
CONSTRAINT fk_rule_node_state_node_id FOREIGN KEY (rule_node_id) REFERENCES rule_node(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS firmware (
id uuid NOT NULL CONSTRAINT firmware_pkey PRIMARY KEY,
CREATE TABLE IF NOT EXISTS ota_package (
id uuid NOT NULL CONSTRAINT ota_package_pkey PRIMARY KEY,
created_time bigint NOT NULL,
tenant_id uuid NOT NULL,
device_profile_id uuid ,
@ -176,7 +176,7 @@ CREATE TABLE IF NOT EXISTS firmware (
data_size bigint,
additional_info varchar,
search_text varchar(255),
CONSTRAINT firmware_tenant_title_version_unq_key UNIQUE (tenant_id, title, version)
CONSTRAINT ota_package_tenant_title_version_unq_key UNIQUE (tenant_id, title, version)
);
CREATE TABLE IF NOT EXISTS device_profile (
@ -202,8 +202,8 @@ CREATE TABLE IF NOT EXISTS device_profile (
CONSTRAINT device_provision_key_unq_key UNIQUE (provision_device_key),
CONSTRAINT fk_default_rule_chain_device_profile FOREIGN KEY (default_rule_chain_id) REFERENCES rule_chain(id),
CONSTRAINT fk_default_dashboard_device_profile FOREIGN KEY (default_dashboard_id) REFERENCES dashboard(id),
CONSTRAINT fk_firmware_device_profile FOREIGN KEY (firmware_id) REFERENCES firmware(id),
CONSTRAINT fk_software_device_profile FOREIGN KEY (software_id) REFERENCES firmware(id)
CONSTRAINT fk_firmware_device_profile FOREIGN KEY (firmware_id) REFERENCES ota_package(id),
CONSTRAINT fk_software_device_profile FOREIGN KEY (software_id) REFERENCES ota_package(id)
);
CREATE TABLE IF NOT EXISTS device (
@ -222,8 +222,8 @@ CREATE TABLE IF NOT EXISTS device (
software_id uuid,
CONSTRAINT device_name_unq_key UNIQUE (tenant_id, name),
CONSTRAINT fk_device_profile FOREIGN KEY (device_profile_id) REFERENCES device_profile(id),
CONSTRAINT fk_firmware_device FOREIGN KEY (firmware_id) REFERENCES firmware(id),
CONSTRAINT fk_software_device FOREIGN KEY (software_id) REFERENCES firmware(id)
CONSTRAINT fk_firmware_device FOREIGN KEY (firmware_id) REFERENCES ota_package(id),
CONSTRAINT fk_software_device FOREIGN KEY (software_id) REFERENCES ota_package(id)
);
CREATE TABLE IF NOT EXISTS device_credentials (

14
dao/src/main/resources/sql/schema-entities.sql

@ -178,8 +178,8 @@ CREATE TABLE IF NOT EXISTS rule_node_state (
CONSTRAINT fk_rule_node_state_node_id FOREIGN KEY (rule_node_id) REFERENCES rule_node(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS firmware (
id uuid NOT NULL CONSTRAINT firmware_pkey PRIMARY KEY,
CREATE TABLE IF NOT EXISTS ota_package (
id uuid NOT NULL CONSTRAINT ota_package_pkey PRIMARY KEY,
created_time bigint NOT NULL,
tenant_id uuid NOT NULL,
device_profile_id uuid ,
@ -194,7 +194,7 @@ CREATE TABLE IF NOT EXISTS firmware (
data_size bigint,
additional_info varchar,
search_text varchar(255),
CONSTRAINT firmware_tenant_title_version_unq_key UNIQUE (tenant_id, title, version)
CONSTRAINT ota_package_tenant_title_version_unq_key UNIQUE (tenant_id, title, version)
-- CONSTRAINT fk_device_profile_firmware FOREIGN KEY (device_profile_id) REFERENCES device_profile(id) ON DELETE CASCADE
);
@ -221,8 +221,8 @@ CREATE TABLE IF NOT EXISTS device_profile (
CONSTRAINT device_provision_key_unq_key UNIQUE (provision_device_key),
CONSTRAINT fk_default_rule_chain_device_profile FOREIGN KEY (default_rule_chain_id) REFERENCES rule_chain(id),
CONSTRAINT fk_default_dashboard_device_profile FOREIGN KEY (default_dashboard_id) REFERENCES dashboard(id),
CONSTRAINT fk_firmware_device_profile FOREIGN KEY (firmware_id) REFERENCES firmware(id),
CONSTRAINT fk_software_device_profile FOREIGN KEY (software_id) REFERENCES firmware(id)
CONSTRAINT fk_firmware_device_profile FOREIGN KEY (firmware_id) REFERENCES ota_package(id),
CONSTRAINT fk_software_device_profile FOREIGN KEY (software_id) REFERENCES ota_package(id)
);
-- We will use one-to-many relation in the first release and extend this feature in case of user requests
@ -250,8 +250,8 @@ CREATE TABLE IF NOT EXISTS device (
software_id uuid,
CONSTRAINT device_name_unq_key UNIQUE (tenant_id, name),
CONSTRAINT fk_device_profile FOREIGN KEY (device_profile_id) REFERENCES device_profile(id),
CONSTRAINT fk_firmware_device FOREIGN KEY (firmware_id) REFERENCES firmware(id),
CONSTRAINT fk_software_device FOREIGN KEY (software_id) REFERENCES firmware(id)
CONSTRAINT fk_firmware_device FOREIGN KEY (firmware_id) REFERENCES ota_package(id),
CONSTRAINT fk_software_device FOREIGN KEY (software_id) REFERENCES ota_package(id)
);
CREATE TABLE IF NOT EXISTS device_credentials (

4
dao/src/test/java/org/thingsboard/server/dao/service/AbstractServiceTest.java

@ -54,7 +54,7 @@ import org.thingsboard.server.dao.edge.EdgeService;
import org.thingsboard.server.dao.entity.EntityService;
import org.thingsboard.server.dao.entityview.EntityViewService;
import org.thingsboard.server.dao.event.EventService;
import org.thingsboard.server.dao.firmware.FirmwareService;
import org.thingsboard.server.dao.ota.OtaPackageService;
import org.thingsboard.server.dao.relation.RelationService;
import org.thingsboard.server.dao.resource.ResourceService;
import org.thingsboard.server.dao.rule.RuleChainService;
@ -160,7 +160,7 @@ public abstract class AbstractServiceTest {
@Autowired
protected FirmwareService firmwareService;
protected OtaPackageService otaPackageService;
public class IdComparator<D extends HasId> implements Comparator<D> {
@Override

11
dao/src/test/java/org/thingsboard/server/dao/service/BaseDeviceProfileServiceTest.java

@ -28,10 +28,9 @@ import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.DeviceProfileInfo;
import org.thingsboard.server.common.data.DeviceTransportType;
import org.thingsboard.server.common.data.Firmware;
import org.thingsboard.server.common.data.OtaPackage;
import org.thingsboard.server.common.data.Tenant;
import org.thingsboard.server.common.data.firmware.FirmwareType;
import org.thingsboard.server.common.data.firmware.ChecksumAlgorithm;
import org.thingsboard.server.common.data.ota.ChecksumAlgorithm;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
@ -45,7 +44,7 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;
import static org.thingsboard.server.common.data.firmware.FirmwareType.FIRMWARE;
import static org.thingsboard.server.common.data.ota.OtaPackageType.FIRMWARE;
public class BaseDeviceProfileServiceTest extends AbstractServiceTest {
@ -99,7 +98,7 @@ public class BaseDeviceProfileServiceTest extends AbstractServiceTest {
Assert.assertEquals(deviceProfile.isDefault(), savedDeviceProfile.isDefault());
Assert.assertEquals(deviceProfile.getDefaultRuleChainId(), savedDeviceProfile.getDefaultRuleChainId());
Firmware firmware = new Firmware();
OtaPackage firmware = new OtaPackage();
firmware.setTenantId(tenantId);
firmware.setDeviceProfileId(savedDeviceProfile.getId());
firmware.setType(FIRMWARE);
@ -110,7 +109,7 @@ public class BaseDeviceProfileServiceTest extends AbstractServiceTest {
firmware.setChecksumAlgorithm(ChecksumAlgorithm.SHA256);
firmware.setChecksum("4bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a");
firmware.setData(ByteBuffer.wrap(new byte[]{1}));
Firmware savedFirmware = firmwareService.saveFirmware(firmware);
OtaPackage savedFirmware = otaPackageService.saveOtaPackage(firmware);
deviceProfile.setFirmwareId(savedFirmware.getId());

14
dao/src/test/java/org/thingsboard/server/dao/service/BaseDeviceServiceTest.java

@ -28,10 +28,10 @@ import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.DeviceInfo;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.EntitySubtype;
import org.thingsboard.server.common.data.Firmware;
import org.thingsboard.server.common.data.OtaPackage;
import org.thingsboard.server.common.data.Tenant;
import org.thingsboard.server.common.data.TenantProfile;
import org.thingsboard.server.common.data.firmware.ChecksumAlgorithm;
import org.thingsboard.server.common.data.ota.ChecksumAlgorithm;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageData;
@ -46,7 +46,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static org.thingsboard.server.common.data.firmware.FirmwareType.FIRMWARE;
import static org.thingsboard.server.common.data.ota.OtaPackageType.FIRMWARE;
import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID;
public abstract class BaseDeviceServiceTest extends AbstractServiceTest {
@ -189,7 +189,7 @@ public abstract class BaseDeviceServiceTest extends AbstractServiceTest {
Assert.assertEquals(20, deviceCredentials.getCredentialsId().length());
Firmware firmware = new Firmware();
OtaPackage firmware = new OtaPackage();
firmware.setTenantId(tenantId);
firmware.setDeviceProfileId(device.getDeviceProfileId());
firmware.setType(FIRMWARE);
@ -200,7 +200,7 @@ public abstract class BaseDeviceServiceTest extends AbstractServiceTest {
firmware.setChecksumAlgorithm(ChecksumAlgorithm.SHA256);
firmware.setChecksum("4bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a");
firmware.setData(ByteBuffer.wrap(new byte[]{1}));
Firmware savedFirmware = firmwareService.saveFirmware(firmware);
OtaPackage savedFirmware = otaPackageService.saveOtaPackage(firmware);
savedDevice.setFirmwareId(savedFirmware.getId());
@ -223,7 +223,7 @@ public abstract class BaseDeviceServiceTest extends AbstractServiceTest {
DeviceProfile savedProfile = deviceProfileService.saveDeviceProfile(deviceProfile);
Assert.assertNotNull(savedProfile);
Firmware firmware = new Firmware();
OtaPackage firmware = new OtaPackage();
firmware.setTenantId(tenantId);
firmware.setDeviceProfileId(savedProfile.getId());
firmware.setType(FIRMWARE);
@ -234,7 +234,7 @@ public abstract class BaseDeviceServiceTest extends AbstractServiceTest {
firmware.setChecksumAlgorithm(ChecksumAlgorithm.SHA256);
firmware.setChecksum("4bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a");
firmware.setData(ByteBuffer.wrap(new byte[]{1}));
Firmware savedFirmware = firmwareService.saveFirmware(firmware);
OtaPackage savedFirmware = otaPackageService.saveOtaPackage(firmware);
savedDevice.setFirmwareId(savedFirmware.getId());

246
dao/src/test/java/org/thingsboard/server/dao/service/BaseFirmwareServiceTest.java → dao/src/test/java/org/thingsboard/server/dao/service/BaseOtaPackageServiceTest.java

@ -25,10 +25,10 @@ import org.junit.rules.ExpectedException;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.Firmware;
import org.thingsboard.server.common.data.FirmwareInfo;
import org.thingsboard.server.common.data.OtaPackage;
import org.thingsboard.server.common.data.OtaPackageInfo;
import org.thingsboard.server.common.data.Tenant;
import org.thingsboard.server.common.data.firmware.ChecksumAlgorithm;
import org.thingsboard.server.common.data.ota.ChecksumAlgorithm;
import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageData;
@ -40,9 +40,9 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static org.thingsboard.server.common.data.firmware.FirmwareType.FIRMWARE;
import static org.thingsboard.server.common.data.ota.OtaPackageType.FIRMWARE;
public abstract class BaseFirmwareServiceTest extends AbstractServiceTest {
public abstract class BaseOtaPackageServiceTest extends AbstractServiceTest {
public static final String TITLE = "My firmware";
private static final String FILE_NAME = "filename.txt";
@ -52,7 +52,7 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest {
private static final String CHECKSUM = "4bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a";
private static final ByteBuffer DATA = ByteBuffer.wrap(new byte[]{1});
private IdComparator<FirmwareInfo> idComparator = new IdComparator<>();
private IdComparator<OtaPackageInfo> idComparator = new IdComparator<>();
private TenantId tenantId;
@ -82,7 +82,7 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest {
@Test
public void testSaveFirmware() {
Firmware firmware = new Firmware();
OtaPackage firmware = new OtaPackage();
firmware.setTenantId(tenantId);
firmware.setDeviceProfileId(deviceProfileId);
firmware.setType(FIRMWARE);
@ -93,7 +93,7 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest {
firmware.setChecksumAlgorithm(CHECKSUM_ALGORITHM);
firmware.setChecksum(CHECKSUM);
firmware.setData(DATA);
Firmware savedFirmware = firmwareService.saveFirmware(firmware);
OtaPackage savedFirmware = otaPackageService.saveOtaPackage(firmware);
Assert.assertNotNull(savedFirmware);
Assert.assertNotNull(savedFirmware.getId());
@ -105,23 +105,23 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest {
Assert.assertEquals(firmware.getData(), savedFirmware.getData());
savedFirmware.setAdditionalInfo(JacksonUtil.newObjectNode());
firmwareService.saveFirmware(savedFirmware);
otaPackageService.saveOtaPackage(savedFirmware);
Firmware foundFirmware = firmwareService.findFirmwareById(tenantId, savedFirmware.getId());
OtaPackage foundFirmware = otaPackageService.findOtaPackageById(tenantId, savedFirmware.getId());
Assert.assertEquals(foundFirmware.getTitle(), savedFirmware.getTitle());
firmwareService.deleteFirmware(tenantId, savedFirmware.getId());
otaPackageService.deleteOtaPackage(tenantId, savedFirmware.getId());
}
@Test
public void testSaveFirmwareInfoAndUpdateWithData() {
FirmwareInfo firmwareInfo = new FirmwareInfo();
OtaPackageInfo firmwareInfo = new OtaPackageInfo();
firmwareInfo.setTenantId(tenantId);
firmwareInfo.setDeviceProfileId(deviceProfileId);
firmwareInfo.setType(FIRMWARE);
firmwareInfo.setTitle(TITLE);
firmwareInfo.setVersion(VERSION);
FirmwareInfo savedFirmwareInfo = firmwareService.saveFirmwareInfo(firmwareInfo);
OtaPackageInfo savedFirmwareInfo = otaPackageService.saveOtaPackageInfo(firmwareInfo);
Assert.assertNotNull(savedFirmwareInfo);
Assert.assertNotNull(savedFirmwareInfo.getId());
@ -129,7 +129,7 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest {
Assert.assertEquals(firmwareInfo.getTenantId(), savedFirmwareInfo.getTenantId());
Assert.assertEquals(firmwareInfo.getTitle(), savedFirmwareInfo.getTitle());
Firmware firmware = new Firmware(savedFirmwareInfo.getId());
OtaPackage firmware = new OtaPackage(savedFirmwareInfo.getId());
firmware.setCreatedTime(firmwareInfo.getCreatedTime());
firmware.setTenantId(tenantId);
firmware.setDeviceProfileId(deviceProfileId);
@ -142,24 +142,24 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest {
firmware.setChecksum(CHECKSUM);
firmware.setData(DATA);
firmwareService.saveFirmware(firmware);
otaPackageService.saveOtaPackage(firmware);
savedFirmwareInfo = firmwareService.findFirmwareInfoById(tenantId, savedFirmwareInfo.getId());
savedFirmwareInfo = otaPackageService.findOtaPackageInfoById(tenantId, savedFirmwareInfo.getId());
savedFirmwareInfo.setAdditionalInfo(JacksonUtil.newObjectNode());
firmwareService.saveFirmwareInfo(savedFirmwareInfo);
otaPackageService.saveOtaPackageInfo(savedFirmwareInfo);
Firmware foundFirmware = firmwareService.findFirmwareById(tenantId, firmware.getId());
OtaPackage foundFirmware = otaPackageService.findOtaPackageById(tenantId, firmware.getId());
firmware.setAdditionalInfo(JacksonUtil.newObjectNode());
Assert.assertEquals(foundFirmware.getTitle(), firmware.getTitle());
Assert.assertTrue(foundFirmware.isHasData());
firmwareService.deleteFirmware(tenantId, savedFirmwareInfo.getId());
otaPackageService.deleteOtaPackage(tenantId, savedFirmwareInfo.getId());
}
@Test
public void testSaveFirmwareWithEmptyTenant() {
Firmware firmware = new Firmware();
OtaPackage firmware = new OtaPackage();
firmware.setDeviceProfileId(deviceProfileId);
firmware.setType(FIRMWARE);
firmware.setTitle(TITLE);
@ -171,13 +171,13 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest {
firmware.setData(DATA);
thrown.expect(DataValidationException.class);
thrown.expectMessage("Firmware should be assigned to tenant!");
firmwareService.saveFirmware(firmware);
thrown.expectMessage("OtaPackage should be assigned to tenant!");
otaPackageService.saveOtaPackage(firmware);
}
@Test
public void testSaveFirmwareWithEmptyType() {
Firmware firmware = new Firmware();
OtaPackage firmware = new OtaPackage();
firmware.setTenantId(tenantId);
firmware.setDeviceProfileId(deviceProfileId);
firmware.setTitle(TITLE);
@ -190,12 +190,12 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest {
thrown.expect(DataValidationException.class);
thrown.expectMessage("Type should be specified!");
firmwareService.saveFirmware(firmware);
otaPackageService.saveOtaPackage(firmware);
}
@Test
public void testSaveFirmwareWithEmptyTitle() {
Firmware firmware = new Firmware();
OtaPackage firmware = new OtaPackage();
firmware.setTenantId(tenantId);
firmware.setDeviceProfileId(deviceProfileId);
firmware.setType(FIRMWARE);
@ -207,13 +207,13 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest {
firmware.setData(DATA);
thrown.expect(DataValidationException.class);
thrown.expectMessage("Firmware title should be specified!");
firmwareService.saveFirmware(firmware);
thrown.expectMessage("OtaPackage title should be specified!");
otaPackageService.saveOtaPackage(firmware);
}
@Test
public void testSaveFirmwareWithEmptyFileName() {
Firmware firmware = new Firmware();
OtaPackage firmware = new OtaPackage();
firmware.setTenantId(tenantId);
firmware.setDeviceProfileId(deviceProfileId);
firmware.setType(FIRMWARE);
@ -225,13 +225,13 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest {
firmware.setData(DATA);
thrown.expect(DataValidationException.class);
thrown.expectMessage("Firmware file name should be specified!");
firmwareService.saveFirmware(firmware);
thrown.expectMessage("OtaPackage file name should be specified!");
otaPackageService.saveOtaPackage(firmware);
}
@Test
public void testSaveFirmwareWithEmptyContentType() {
Firmware firmware = new Firmware();
OtaPackage firmware = new OtaPackage();
firmware.setTenantId(tenantId);
firmware.setDeviceProfileId(deviceProfileId);
firmware.setType(FIRMWARE);
@ -243,13 +243,13 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest {
firmware.setData(DATA);
thrown.expect(DataValidationException.class);
thrown.expectMessage("Firmware content type should be specified!");
firmwareService.saveFirmware(firmware);
thrown.expectMessage("OtaPackage content type should be specified!");
otaPackageService.saveOtaPackage(firmware);
}
@Test
public void testSaveFirmwareWithEmptyData() {
Firmware firmware = new Firmware();
OtaPackage firmware = new OtaPackage();
firmware.setTenantId(tenantId);
firmware.setDeviceProfileId(deviceProfileId);
firmware.setType(FIRMWARE);
@ -261,13 +261,13 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest {
firmware.setChecksum(CHECKSUM);
thrown.expect(DataValidationException.class);
thrown.expectMessage("Firmware data should be specified!");
firmwareService.saveFirmware(firmware);
thrown.expectMessage("OtaPackage data should be specified!");
otaPackageService.saveOtaPackage(firmware);
}
@Test
public void testSaveFirmwareWithInvalidTenant() {
Firmware firmware = new Firmware();
OtaPackage firmware = new OtaPackage();
firmware.setTenantId(new TenantId(Uuids.timeBased()));
firmware.setDeviceProfileId(deviceProfileId);
firmware.setType(FIRMWARE);
@ -280,13 +280,13 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest {
firmware.setData(DATA);
thrown.expect(DataValidationException.class);
thrown.expectMessage("Firmware is referencing to non-existent tenant!");
firmwareService.saveFirmware(firmware);
thrown.expectMessage("OtaPackage is referencing to non-existent tenant!");
otaPackageService.saveOtaPackage(firmware);
}
@Test
public void testSaveFirmwareWithInvalidDeviceProfileId() {
Firmware firmware = new Firmware();
OtaPackage firmware = new OtaPackage();
firmware.setTenantId(tenantId);
firmware.setDeviceProfileId(new DeviceProfileId(Uuids.timeBased()));
firmware.setType(FIRMWARE);
@ -299,13 +299,13 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest {
firmware.setData(DATA);
thrown.expect(DataValidationException.class);
thrown.expectMessage("Firmware is referencing to non-existent device profile!");
firmwareService.saveFirmware(firmware);
thrown.expectMessage("OtaPackage is referencing to non-existent device profile!");
otaPackageService.saveOtaPackage(firmware);
}
@Test
public void testSaveFirmwareWithEmptyChecksum() {
Firmware firmware = new Firmware();
OtaPackage firmware = new OtaPackage();
firmware.setTenantId(tenantId);
firmware.setDeviceProfileId(deviceProfileId);
firmware.setType(FIRMWARE);
@ -317,21 +317,21 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest {
firmware.setData(DATA);
thrown.expect(DataValidationException.class);
thrown.expectMessage("Firmware checksum should be specified!");
firmwareService.saveFirmware(firmware);
thrown.expectMessage("OtaPackage checksum should be specified!");
otaPackageService.saveOtaPackage(firmware);
}
@Test
public void testSaveFirmwareInfoWithExistingTitleAndVersion() {
FirmwareInfo firmwareInfo = new FirmwareInfo();
OtaPackageInfo firmwareInfo = new OtaPackageInfo();
firmwareInfo.setTenantId(tenantId);
firmwareInfo.setDeviceProfileId(deviceProfileId);
firmwareInfo.setType(FIRMWARE);
firmwareInfo.setTitle(TITLE);
firmwareInfo.setVersion(VERSION);
firmwareService.saveFirmwareInfo(firmwareInfo);
otaPackageService.saveOtaPackageInfo(firmwareInfo);
FirmwareInfo newFirmwareInfo = new FirmwareInfo();
OtaPackageInfo newFirmwareInfo = new OtaPackageInfo();
newFirmwareInfo.setTenantId(tenantId);
newFirmwareInfo.setDeviceProfileId(deviceProfileId);
newFirmwareInfo.setType(FIRMWARE);
@ -339,13 +339,13 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest {
newFirmwareInfo.setVersion(VERSION);
thrown.expect(DataValidationException.class);
thrown.expectMessage("Firmware with such title and version already exists!");
firmwareService.saveFirmwareInfo(newFirmwareInfo);
thrown.expectMessage("OtaPackage with such title and version already exists!");
otaPackageService.saveOtaPackageInfo(newFirmwareInfo);
}
@Test
public void testSaveFirmwareWithExistingTitleAndVersion() {
Firmware firmware = new Firmware();
OtaPackage firmware = new OtaPackage();
firmware.setTenantId(tenantId);
firmware.setDeviceProfileId(deviceProfileId);
firmware.setType(FIRMWARE);
@ -356,9 +356,9 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest {
firmware.setChecksumAlgorithm(CHECKSUM_ALGORITHM);
firmware.setChecksum(CHECKSUM);
firmware.setData(DATA);
firmwareService.saveFirmware(firmware);
otaPackageService.saveOtaPackage(firmware);
Firmware newFirmware = new Firmware();
OtaPackage newFirmware = new OtaPackage();
newFirmware.setTenantId(tenantId);
newFirmware.setDeviceProfileId(deviceProfileId);
newFirmware.setType(FIRMWARE);
@ -371,13 +371,13 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest {
newFirmware.setData(DATA);
thrown.expect(DataValidationException.class);
thrown.expectMessage("Firmware with such title and version already exists!");
firmwareService.saveFirmware(newFirmware);
thrown.expectMessage("OtaPackage with such title and version already exists!");
otaPackageService.saveOtaPackage(newFirmware);
}
@Test
public void testDeleteFirmwareWithReferenceByDevice() {
Firmware firmware = new Firmware();
OtaPackage firmware = new OtaPackage();
firmware.setTenantId(tenantId);
firmware.setDeviceProfileId(deviceProfileId);
firmware.setType(FIRMWARE);
@ -388,7 +388,7 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest {
firmware.setChecksumAlgorithm(CHECKSUM_ALGORITHM);
firmware.setChecksum(CHECKSUM);
firmware.setData(DATA);
Firmware savedFirmware = firmwareService.saveFirmware(firmware);
OtaPackage savedFirmware = otaPackageService.saveOtaPackage(firmware);
Device device = new Device();
device.setTenantId(tenantId);
@ -399,17 +399,17 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest {
try {
thrown.expect(DataValidationException.class);
thrown.expectMessage("The firmware referenced by the devices cannot be deleted!");
firmwareService.deleteFirmware(tenantId, savedFirmware.getId());
thrown.expectMessage("The otaPackage referenced by the devices cannot be deleted!");
otaPackageService.deleteOtaPackage(tenantId, savedFirmware.getId());
} finally {
deviceService.deleteDevice(tenantId, savedDevice.getId());
firmwareService.deleteFirmware(tenantId, savedFirmware.getId());
otaPackageService.deleteOtaPackage(tenantId, savedFirmware.getId());
}
}
@Test
public void testUpdateDeviceProfileIdWithReferenceByDevice() {
Firmware firmware = new Firmware();
public void testUpdateDeviceProfileId() {
OtaPackage firmware = new OtaPackage();
firmware.setTenantId(tenantId);
firmware.setDeviceProfileId(deviceProfileId);
firmware.setType(FIRMWARE);
@ -420,23 +420,15 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest {
firmware.setChecksumAlgorithm(CHECKSUM_ALGORITHM);
firmware.setChecksum(CHECKSUM);
firmware.setData(DATA);
Firmware savedFirmware = firmwareService.saveFirmware(firmware);
Device device = new Device();
device.setTenantId(tenantId);
device.setName("My device");
device.setDeviceProfileId(deviceProfileId);
device.setFirmwareId(savedFirmware.getId());
Device savedDevice = deviceService.saveDevice(device);
OtaPackage savedFirmware = otaPackageService.saveOtaPackage(firmware);
try {
thrown.expect(DataValidationException.class);
thrown.expectMessage("Can`t update deviceProfileId because firmware is already in use!");
thrown.expectMessage("Updating otaPackage deviceProfile is prohibited!");
savedFirmware.setDeviceProfileId(null);
firmwareService.saveFirmware(savedFirmware);
otaPackageService.saveOtaPackage(savedFirmware);
} finally {
deviceService.deleteDevice(tenantId, savedDevice.getId());
firmwareService.deleteFirmware(tenantId, savedFirmware.getId());
otaPackageService.deleteOtaPackage(tenantId, savedFirmware.getId());
}
}
@ -445,38 +437,7 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest {
DeviceProfile deviceProfile = this.createDeviceProfile(tenantId, "Test Device Profile");
DeviceProfile savedDeviceProfile = deviceProfileService.saveDeviceProfile(deviceProfile);
Firmware firmware = new Firmware();
firmware.setTenantId(tenantId);
firmware.setDeviceProfileId(savedDeviceProfile.getId());
firmware.setType(FIRMWARE);
firmware.setTitle(TITLE);
firmware.setVersion(VERSION);
firmware.setFileName(FILE_NAME);
firmware.setContentType(CONTENT_TYPE);
firmware.setChecksumAlgorithm(CHECKSUM_ALGORITHM);
firmware.setChecksum(CHECKSUM);
firmware.setData(DATA);
Firmware savedFirmware = firmwareService.saveFirmware(firmware);
savedDeviceProfile.setFirmwareId(savedFirmware.getId());
deviceProfileService.saveDeviceProfile(savedDeviceProfile);
try {
thrown.expect(DataValidationException.class);
thrown.expectMessage("The firmware referenced by the device profile cannot be deleted!");
firmwareService.deleteFirmware(tenantId, savedFirmware.getId());
} finally {
deviceProfileService.deleteDeviceProfile(tenantId, savedDeviceProfile.getId());
firmwareService.deleteFirmware(tenantId, savedFirmware.getId());
}
}
@Test
public void testUpdateDeviceProfileIdWithReferenceByDeviceProfile() {
DeviceProfile deviceProfile = this.createDeviceProfile(tenantId, "Test Device Profile");
DeviceProfile savedDeviceProfile = deviceProfileService.saveDeviceProfile(deviceProfile);
Firmware firmware = new Firmware();
OtaPackage firmware = new OtaPackage();
firmware.setTenantId(tenantId);
firmware.setDeviceProfileId(savedDeviceProfile.getId());
firmware.setType(FIRMWARE);
@ -487,25 +448,24 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest {
firmware.setChecksumAlgorithm(CHECKSUM_ALGORITHM);
firmware.setChecksum(CHECKSUM);
firmware.setData(DATA);
Firmware savedFirmware = firmwareService.saveFirmware(firmware);
OtaPackage savedFirmware = otaPackageService.saveOtaPackage(firmware);
savedDeviceProfile.setFirmwareId(savedFirmware.getId());
deviceProfileService.saveDeviceProfile(savedDeviceProfile);
try {
thrown.expect(DataValidationException.class);
thrown.expectMessage("Can`t update deviceProfileId because firmware is already in use!");
savedFirmware.setDeviceProfileId(null);
firmwareService.saveFirmware(savedFirmware);
thrown.expectMessage("The otaPackage referenced by the device profile cannot be deleted!");
otaPackageService.deleteOtaPackage(tenantId, savedFirmware.getId());
} finally {
deviceProfileService.deleteDeviceProfile(tenantId, savedDeviceProfile.getId());
firmwareService.deleteFirmware(tenantId, savedFirmware.getId());
otaPackageService.deleteOtaPackage(tenantId, savedFirmware.getId());
}
}
@Test
public void testFindFirmwareById() {
Firmware firmware = new Firmware();
OtaPackage firmware = new OtaPackage();
firmware.setTenantId(tenantId);
firmware.setDeviceProfileId(deviceProfileId);
firmware.setType(FIRMWARE);
@ -516,33 +476,33 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest {
firmware.setChecksumAlgorithm(CHECKSUM_ALGORITHM);
firmware.setChecksum(CHECKSUM);
firmware.setData(DATA);
Firmware savedFirmware = firmwareService.saveFirmware(firmware);
OtaPackage savedFirmware = otaPackageService.saveOtaPackage(firmware);
Firmware foundFirmware = firmwareService.findFirmwareById(tenantId, savedFirmware.getId());
OtaPackage foundFirmware = otaPackageService.findOtaPackageById(tenantId, savedFirmware.getId());
Assert.assertNotNull(foundFirmware);
Assert.assertEquals(savedFirmware, foundFirmware);
firmwareService.deleteFirmware(tenantId, savedFirmware.getId());
otaPackageService.deleteOtaPackage(tenantId, savedFirmware.getId());
}
@Test
public void testFindFirmwareInfoById() {
FirmwareInfo firmware = new FirmwareInfo();
OtaPackageInfo firmware = new OtaPackageInfo();
firmware.setTenantId(tenantId);
firmware.setDeviceProfileId(deviceProfileId);
firmware.setType(FIRMWARE);
firmware.setTitle(TITLE);
firmware.setVersion(VERSION);
FirmwareInfo savedFirmware = firmwareService.saveFirmwareInfo(firmware);
OtaPackageInfo savedFirmware = otaPackageService.saveOtaPackageInfo(firmware);
FirmwareInfo foundFirmware = firmwareService.findFirmwareInfoById(tenantId, savedFirmware.getId());
OtaPackageInfo foundFirmware = otaPackageService.findOtaPackageInfoById(tenantId, savedFirmware.getId());
Assert.assertNotNull(foundFirmware);
Assert.assertEquals(savedFirmware, foundFirmware);
firmwareService.deleteFirmware(tenantId, savedFirmware.getId());
otaPackageService.deleteOtaPackage(tenantId, savedFirmware.getId());
}
@Test
public void testDeleteFirmware() {
Firmware firmware = new Firmware();
OtaPackage firmware = new OtaPackage();
firmware.setTenantId(tenantId);
firmware.setDeviceProfileId(deviceProfileId);
firmware.setType(FIRMWARE);
@ -553,20 +513,20 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest {
firmware.setChecksumAlgorithm(CHECKSUM_ALGORITHM);
firmware.setChecksum(CHECKSUM);
firmware.setData(DATA);
Firmware savedFirmware = firmwareService.saveFirmware(firmware);
OtaPackage savedFirmware = otaPackageService.saveOtaPackage(firmware);
Firmware foundFirmware = firmwareService.findFirmwareById(tenantId, savedFirmware.getId());
OtaPackage foundFirmware = otaPackageService.findOtaPackageById(tenantId, savedFirmware.getId());
Assert.assertNotNull(foundFirmware);
firmwareService.deleteFirmware(tenantId, savedFirmware.getId());
foundFirmware = firmwareService.findFirmwareById(tenantId, savedFirmware.getId());
otaPackageService.deleteOtaPackage(tenantId, savedFirmware.getId());
foundFirmware = otaPackageService.findOtaPackageById(tenantId, savedFirmware.getId());
Assert.assertNull(foundFirmware);
}
@Test
public void testFindTenantFirmwaresByTenantId() {
List<FirmwareInfo> firmwares = new ArrayList<>();
List<OtaPackageInfo> firmwares = new ArrayList<>();
for (int i = 0; i < 165; i++) {
Firmware firmware = new Firmware();
OtaPackage firmware = new OtaPackage();
firmware.setTenantId(tenantId);
firmware.setDeviceProfileId(deviceProfileId);
firmware.setType(FIRMWARE);
@ -578,16 +538,16 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest {
firmware.setChecksum(CHECKSUM);
firmware.setData(DATA);
FirmwareInfo info = new FirmwareInfo(firmwareService.saveFirmware(firmware));
OtaPackageInfo info = new OtaPackageInfo(otaPackageService.saveOtaPackage(firmware));
info.setHasData(true);
firmwares.add(info);
}
List<FirmwareInfo> loadedFirmwares = new ArrayList<>();
List<OtaPackageInfo> loadedFirmwares = new ArrayList<>();
PageLink pageLink = new PageLink(16);
PageData<FirmwareInfo> pageData;
PageData<OtaPackageInfo> pageData;
do {
pageData = firmwareService.findTenantFirmwaresByTenantId(tenantId, pageLink);
pageData = otaPackageService.findTenantOtaPackagesByTenantId(tenantId, pageLink);
loadedFirmwares.addAll(pageData.getData());
if (pageData.hasNext()) {
pageLink = pageLink.nextPageLink();
@ -599,19 +559,19 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest {
Assert.assertEquals(firmwares, loadedFirmwares);
firmwareService.deleteFirmwaresByTenantId(tenantId);
otaPackageService.deleteOtaPackagesByTenantId(tenantId);
pageLink = new PageLink(31);
pageData = firmwareService.findTenantFirmwaresByTenantId(tenantId, pageLink);
pageData = otaPackageService.findTenantOtaPackagesByTenantId(tenantId, pageLink);
Assert.assertFalse(pageData.hasNext());
Assert.assertTrue(pageData.getData().isEmpty());
}
@Test
public void testFindTenantFirmwaresByTenantIdAndHasData() {
List<FirmwareInfo> firmwares = new ArrayList<>();
List<OtaPackageInfo> firmwares = new ArrayList<>();
for (int i = 0; i < 165; i++) {
FirmwareInfo firmwareInfo = new FirmwareInfo();
OtaPackageInfo firmwareInfo = new OtaPackageInfo();
firmwareInfo.setTenantId(tenantId);
firmwareInfo.setDeviceProfileId(deviceProfileId);
firmwareInfo.setType(FIRMWARE);
@ -622,14 +582,14 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest {
firmwareInfo.setChecksumAlgorithm(CHECKSUM_ALGORITHM);
firmwareInfo.setChecksum(CHECKSUM);
firmwareInfo.setDataSize((long) DATA.array().length);
firmwares.add(firmwareService.saveFirmwareInfo(firmwareInfo));
firmwares.add(otaPackageService.saveOtaPackageInfo(firmwareInfo));
}
List<FirmwareInfo> loadedFirmwares = new ArrayList<>();
List<OtaPackageInfo> loadedFirmwares = new ArrayList<>();
PageLink pageLink = new PageLink(16);
PageData<FirmwareInfo> pageData;
PageData<OtaPackageInfo> pageData;
do {
pageData = firmwareService.findTenantFirmwaresByTenantIdAndDeviceProfileIdAndTypeAndHasData(tenantId, deviceProfileId, FIRMWARE, false, pageLink);
pageData = otaPackageService.findTenantOtaPackagesByTenantIdAndDeviceProfileIdAndTypeAndHasData(tenantId, deviceProfileId, FIRMWARE, false, pageLink);
loadedFirmwares.addAll(pageData.getData());
if (pageData.hasNext()) {
pageLink = pageLink.nextPageLink();
@ -642,7 +602,7 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest {
Assert.assertEquals(firmwares, loadedFirmwares);
firmwares.forEach(f -> {
Firmware firmware = new Firmware(f.getId());
OtaPackage firmware = new OtaPackage(f.getId());
firmware.setCreatedTime(f.getCreatedTime());
firmware.setTenantId(f.getTenantId());
firmware.setDeviceProfileId(deviceProfileId);
@ -655,14 +615,14 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest {
firmware.setChecksum(CHECKSUM);
firmware.setData(DATA);
firmware.setDataSize((long) DATA.array().length);
firmwareService.saveFirmware(firmware);
otaPackageService.saveOtaPackage(firmware);
f.setHasData(true);
});
loadedFirmwares = new ArrayList<>();
pageLink = new PageLink(16);
do {
pageData = firmwareService.findTenantFirmwaresByTenantIdAndDeviceProfileIdAndTypeAndHasData(tenantId, deviceProfileId, FIRMWARE, true, pageLink);
pageData = otaPackageService.findTenantOtaPackagesByTenantIdAndDeviceProfileIdAndTypeAndHasData(tenantId, deviceProfileId, FIRMWARE, true, pageLink);
loadedFirmwares.addAll(pageData.getData());
if (pageData.hasNext()) {
pageLink = pageLink.nextPageLink();
@ -674,10 +634,10 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest {
Assert.assertEquals(firmwares, loadedFirmwares);
firmwareService.deleteFirmwaresByTenantId(tenantId);
otaPackageService.deleteOtaPackagesByTenantId(tenantId);
pageLink = new PageLink(31);
pageData = firmwareService.findTenantFirmwaresByTenantId(tenantId, pageLink);
pageData = otaPackageService.findTenantOtaPackagesByTenantId(tenantId, pageLink);
Assert.assertFalse(pageData.hasNext());
Assert.assertTrue(pageData.getData().isEmpty());
}

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save