Commit 8a5a4f0995048ed1d7787bb91bccab135220a7c3
1 parent
7ce1fc77
Added ability to autogenerate checksum for firmware
Showing
8 changed files
with
46 additions
and
66 deletions
@@ -115,7 +115,7 @@ public class FirmwareController extends BaseController { | @@ -115,7 +115,7 @@ public class FirmwareController extends BaseController { | ||
115 | @ResponseBody | 115 | @ResponseBody |
116 | public Firmware saveFirmwareData(@PathVariable(FIRMWARE_ID) String strFirmwareId, | 116 | public Firmware saveFirmwareData(@PathVariable(FIRMWARE_ID) String strFirmwareId, |
117 | @RequestParam(required = false) String checksum, | 117 | @RequestParam(required = false) String checksum, |
118 | - @RequestParam(required = false) String checksumAlgorithm, | 118 | + @RequestParam() String checksumAlgorithm, |
119 | @RequestBody MultipartFile file) throws ThingsboardException { | 119 | @RequestBody MultipartFile file) throws ThingsboardException { |
120 | checkParameter(FIRMWARE_ID, strFirmwareId); | 120 | checkParameter(FIRMWARE_ID, strFirmwareId); |
121 | try { | 121 | try { |
@@ -129,18 +129,17 @@ public class FirmwareController extends BaseController { | @@ -129,18 +129,17 @@ public class FirmwareController extends BaseController { | ||
129 | firmware.setVersion(info.getVersion()); | 129 | firmware.setVersion(info.getVersion()); |
130 | firmware.setAdditionalInfo(info.getAdditionalInfo()); | 130 | firmware.setAdditionalInfo(info.getAdditionalInfo()); |
131 | 131 | ||
132 | - byte[] data = file.getBytes(); | ||
133 | - if (StringUtils.isEmpty(checksumAlgorithm)) { | ||
134 | - checksumAlgorithm = "sha256"; | ||
135 | - checksum = Hashing.sha256().hashBytes(data).toString(); | 132 | + ByteBuffer data = ByteBuffer.wrap(file.getBytes()); |
133 | + if (StringUtils.isEmpty(checksum)) { | ||
134 | + checksum = firmwareService.generateChecksum(checksumAlgorithm, data); | ||
136 | } | 135 | } |
137 | 136 | ||
138 | firmware.setChecksumAlgorithm(checksumAlgorithm); | 137 | firmware.setChecksumAlgorithm(checksumAlgorithm); |
139 | firmware.setChecksum(checksum); | 138 | firmware.setChecksum(checksum); |
140 | firmware.setFileName(file.getOriginalFilename()); | 139 | firmware.setFileName(file.getOriginalFilename()); |
141 | firmware.setContentType(file.getContentType()); | 140 | firmware.setContentType(file.getContentType()); |
142 | - firmware.setData(ByteBuffer.wrap(data)); | ||
143 | - firmware.setDataSize((long) data.length); | 141 | + firmware.setData(data); |
142 | + firmware.setDataSize((long) data.array().length); | ||
144 | return firmwareService.saveFirmware(firmware); | 143 | return firmwareService.saveFirmware(firmware); |
145 | } catch (Exception e) { | 144 | } catch (Exception e) { |
146 | throw handleException(e); | 145 | throw handleException(e); |
@@ -22,12 +22,16 @@ import org.thingsboard.server.common.data.id.TenantId; | @@ -22,12 +22,16 @@ import org.thingsboard.server.common.data.id.TenantId; | ||
22 | import org.thingsboard.server.common.data.page.PageData; | 22 | import org.thingsboard.server.common.data.page.PageData; |
23 | import org.thingsboard.server.common.data.page.PageLink; | 23 | import org.thingsboard.server.common.data.page.PageLink; |
24 | 24 | ||
25 | +import java.nio.ByteBuffer; | ||
26 | + | ||
25 | public interface FirmwareService { | 27 | public interface FirmwareService { |
26 | 28 | ||
27 | FirmwareInfo saveFirmwareInfo(FirmwareInfo firmwareInfo); | 29 | FirmwareInfo saveFirmwareInfo(FirmwareInfo firmwareInfo); |
28 | 30 | ||
29 | Firmware saveFirmware(Firmware firmware); | 31 | Firmware saveFirmware(Firmware firmware); |
30 | 32 | ||
33 | + String generateChecksum(String checksumAlgorithm, ByteBuffer data); | ||
34 | + | ||
31 | Firmware findFirmwareById(TenantId tenantId, FirmwareId firmwareId); | 35 | Firmware findFirmwareById(TenantId tenantId, FirmwareId firmwareId); |
32 | 36 | ||
33 | FirmwareInfo findFirmwareInfoById(TenantId tenantId, FirmwareId firmwareId); | 37 | FirmwareInfo findFirmwareInfoById(TenantId tenantId, FirmwareId firmwareId); |
@@ -456,9 +456,6 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement | @@ -456,9 +456,6 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement | ||
456 | deviceSessionCtx.getPayloadAdaptor() | 456 | deviceSessionCtx.getPayloadAdaptor() |
457 | .convertToPublish(deviceSessionCtx, firmwareChunk, requestId, chunk) | 457 | .convertToPublish(deviceSessionCtx, firmwareChunk, requestId, chunk) |
458 | .ifPresent(deviceSessionCtx.getChannel()::writeAndFlush); | 458 | .ifPresent(deviceSessionCtx.getChannel()::writeAndFlush); |
459 | - if (firmwareChunk != null && chunkSize != firmwareChunk.length) { | ||
460 | - scheduler.schedule(() -> processDisconnect(ctx), 60, TimeUnit.SECONDS); | ||
461 | - } | ||
462 | } catch (Exception e) { | 459 | } catch (Exception e) { |
463 | log.trace("[{}] Failed to send firmware response!", sessionId, e); | 460 | log.trace("[{}] Failed to send firmware response!", sessionId, e); |
464 | } | 461 | } |
@@ -102,6 +102,32 @@ public class BaseFirmwareService implements FirmwareService { | @@ -102,6 +102,32 @@ public class BaseFirmwareService implements FirmwareService { | ||
102 | } | 102 | } |
103 | 103 | ||
104 | @Override | 104 | @Override |
105 | + public String generateChecksum(String checksumAlgorithm, ByteBuffer data) { | ||
106 | + | ||
107 | + if (data == null || !data.hasArray() || data.array().length == 0) { | ||
108 | + throw new DataValidationException("Firmware data should be specified!"); | ||
109 | + } | ||
110 | + | ||
111 | + HashFunction hashFunction; | ||
112 | + switch (checksumAlgorithm) { | ||
113 | + case "sha256": | ||
114 | + hashFunction = Hashing.sha256(); | ||
115 | + break; | ||
116 | + case "md5": | ||
117 | + hashFunction = Hashing.md5(); | ||
118 | + break; | ||
119 | + case "crc32": | ||
120 | + hashFunction = Hashing.crc32(); | ||
121 | + break; | ||
122 | + default: | ||
123 | + throw new DataValidationException("Unknown checksum algorithm!"); | ||
124 | + } | ||
125 | + | ||
126 | + return hashFunction.hashBytes(data.array()).toString(); | ||
127 | + } | ||
128 | + | ||
129 | + | ||
130 | + @Override | ||
105 | public Firmware findFirmwareById(TenantId tenantId, FirmwareId firmwareId) { | 131 | public Firmware findFirmwareById(TenantId tenantId, FirmwareId firmwareId) { |
106 | log.trace("Executing findFirmwareById [{}]", firmwareId); | 132 | log.trace("Executing findFirmwareById [{}]", firmwareId); |
107 | validateId(firmwareId, INCORRECT_FIRMWARE_ID + firmwareId); | 133 | validateId(firmwareId, INCORRECT_FIRMWARE_ID + firmwareId); |
@@ -217,11 +243,6 @@ public class BaseFirmwareService implements FirmwareService { | @@ -217,11 +243,6 @@ public class BaseFirmwareService implements FirmwareService { | ||
217 | throw new DataValidationException("Firmware content type should be specified!"); | 243 | throw new DataValidationException("Firmware content type should be specified!"); |
218 | } | 244 | } |
219 | 245 | ||
220 | - ByteBuffer data = firmware.getData(); | ||
221 | - if (data == null || !data.hasArray() || data.array().length == 0) { | ||
222 | - throw new DataValidationException("Firmware data should be specified!"); | ||
223 | - } | ||
224 | - | ||
225 | if (StringUtils.isEmpty(firmware.getChecksumAlgorithm())) { | 246 | if (StringUtils.isEmpty(firmware.getChecksumAlgorithm())) { |
226 | throw new DataValidationException("Firmware checksum algorithm should be specified!"); | 247 | throw new DataValidationException("Firmware checksum algorithm should be specified!"); |
227 | } | 248 | } |
@@ -229,22 +250,7 @@ public class BaseFirmwareService implements FirmwareService { | @@ -229,22 +250,7 @@ public class BaseFirmwareService implements FirmwareService { | ||
229 | throw new DataValidationException("Firmware checksum should be specified!"); | 250 | throw new DataValidationException("Firmware checksum should be specified!"); |
230 | } | 251 | } |
231 | 252 | ||
232 | - HashFunction hashFunction; | ||
233 | - switch (firmware.getChecksumAlgorithm()) { | ||
234 | - case "sha256": | ||
235 | - hashFunction = Hashing.sha256(); | ||
236 | - break; | ||
237 | - case "md5": | ||
238 | - hashFunction = Hashing.md5(); | ||
239 | - break; | ||
240 | - case "crc32": | ||
241 | - hashFunction = Hashing.crc32(); | ||
242 | - break; | ||
243 | - default: | ||
244 | - throw new DataValidationException("Unknown checksum algorithm!"); | ||
245 | - } | ||
246 | - | ||
247 | - String currentChecksum = hashFunction.hashBytes(data.array()).toString(); | 253 | + String currentChecksum = generateChecksum(firmware.getChecksumAlgorithm(), firmware.getData()); |
248 | 254 | ||
249 | if (!currentChecksum.equals(firmware.getChecksum())) { | 255 | if (!currentChecksum.equals(firmware.getChecksum())) { |
250 | throw new DataValidationException("Wrong firmware file!"); | 256 | throw new DataValidationException("Wrong firmware file!"); |
@@ -20,7 +20,7 @@ import { PageLink } from '@shared/models/page/page-link'; | @@ -20,7 +20,7 @@ import { PageLink } from '@shared/models/page/page-link'; | ||
20 | import { defaultHttpOptionsFromConfig, defaultHttpUploadOptions, RequestConfig } from '@core/http/http-utils'; | 20 | import { defaultHttpOptionsFromConfig, defaultHttpUploadOptions, RequestConfig } from '@core/http/http-utils'; |
21 | import { Observable } from 'rxjs'; | 21 | import { Observable } from 'rxjs'; |
22 | import { PageData } from '@shared/models/page/page-data'; | 22 | import { PageData } from '@shared/models/page/page-data'; |
23 | -import { Firmware, FirmwareInfo } from '@shared/models/firmware.models'; | 23 | +import { ChecksumAlgorithm, Firmware, FirmwareInfo } from '@shared/models/firmware.models'; |
24 | import { catchError, map, mergeMap } from 'rxjs/operators'; | 24 | import { catchError, map, mergeMap } from 'rxjs/operators'; |
25 | import { deepClone, isDefinedAndNotNull } from '@core/utils'; | 25 | import { deepClone, isDefinedAndNotNull } from '@core/utils'; |
26 | 26 | ||
@@ -100,16 +100,16 @@ export class FirmwareService { | @@ -100,16 +100,16 @@ export class FirmwareService { | ||
100 | return this.http.post<Firmware>('/api/firmware', firmware, defaultHttpOptionsFromConfig(config)); | 100 | return this.http.post<Firmware>('/api/firmware', firmware, defaultHttpOptionsFromConfig(config)); |
101 | } | 101 | } |
102 | 102 | ||
103 | - public uploadFirmwareFile(firmwareId: string, file: File, checksumAlgorithm?: string, | 103 | + public uploadFirmwareFile(firmwareId: string, file: File, checksumAlgorithm: ChecksumAlgorithm, |
104 | checksum?: string, config?: RequestConfig): Observable<any> { | 104 | checksum?: string, config?: RequestConfig): Observable<any> { |
105 | if (!config) { | 105 | if (!config) { |
106 | config = {}; | 106 | config = {}; |
107 | } | 107 | } |
108 | const formData = new FormData(); | 108 | const formData = new FormData(); |
109 | formData.append('file', file); | 109 | formData.append('file', file); |
110 | - let url = `/api/firmware/${firmwareId}`; | ||
111 | - if (checksumAlgorithm && checksum) { | ||
112 | - url += `?checksumAlgorithm=${checksumAlgorithm}&checksum=${checksum}`; | 110 | + let url = `/api/firmware/${firmwareId}?checksumAlgorithm=${checksumAlgorithm}`; |
111 | + if (checksum) { | ||
112 | + url += `&checksum=${checksum}`; | ||
113 | } | 113 | } |
114 | return this.http.post(url, formData, | 114 | return this.http.post(url, formData, |
115 | defaultHttpUploadOptions(config.ignoreLoading, config.ignoreErrors, config.resendRequest)); | 115 | defaultHttpUploadOptions(config.ignoreLoading, config.ignoreErrors, config.resendRequest)); |
@@ -72,7 +72,6 @@ | @@ -72,7 +72,6 @@ | ||
72 | <mat-label translate>firmware.checksum-algorithm</mat-label> | 72 | <mat-label translate>firmware.checksum-algorithm</mat-label> |
73 | <input *ngIf="!isAdd" matInput formControlName="checksumAlgorithm" type="text" [readonly]="isEdit"> | 73 | <input *ngIf="!isAdd" matInput formControlName="checksumAlgorithm" type="text" [readonly]="isEdit"> |
74 | <mat-select formControlName="checksumAlgorithm" *ngIf="isAdd"> | 74 | <mat-select formControlName="checksumAlgorithm" *ngIf="isAdd"> |
75 | - <mat-option [value]=null></mat-option> | ||
76 | <mat-option *ngFor="let checksumAlgorithm of checksumAlgorithms" [value]="checksumAlgorithm"> | 75 | <mat-option *ngFor="let checksumAlgorithm of checksumAlgorithms" [value]="checksumAlgorithm"> |
77 | {{ checksumAlgorithmTranslationMap.get(checksumAlgorithm) }} | 76 | {{ checksumAlgorithmTranslationMap.get(checksumAlgorithm) }} |
78 | </mat-option> | 77 | </mat-option> |
@@ -80,11 +79,7 @@ | @@ -80,11 +79,7 @@ | ||
80 | </mat-form-field> | 79 | </mat-form-field> |
81 | <mat-form-field class="mat-block" fxFlex> | 80 | <mat-form-field class="mat-block" fxFlex> |
82 | <mat-label translate>firmware.checksum</mat-label> | 81 | <mat-label translate>firmware.checksum</mat-label> |
83 | - <input matInput formControlName="checksum" type="text" [readonly]="!isAdd" | ||
84 | - [required]="entityForm.get('checksumAlgorithm').value != null"> | ||
85 | - <mat-error *ngIf="entityForm.get('checksumAlgorithm').hasError('required')"> | ||
86 | - {{ 'firmware.checksum-required' | translate }} | ||
87 | - </mat-error> | 82 | + <input matInput formControlName="checksum" type="text" [readonly]="!isAdd"> |
88 | </mat-form-field> | 83 | </mat-form-field> |
89 | </div> | 84 | </div> |
90 | <section *ngIf="isAdd" style="padding-top: 8px"> | 85 | <section *ngIf="isAdd" style="padding-top: 8px"> |
@@ -23,7 +23,6 @@ import { EntityTableConfig } from '@home/models/entity/entities-table-config.mod | @@ -23,7 +23,6 @@ import { EntityTableConfig } from '@home/models/entity/entities-table-config.mod | ||
23 | import { FormBuilder, FormGroup, Validators } from '@angular/forms'; | 23 | import { FormBuilder, FormGroup, Validators } from '@angular/forms'; |
24 | import { EntityComponent } from '@home/components/entity/entity.component'; | 24 | import { EntityComponent } from '@home/components/entity/entity.component'; |
25 | import { ChecksumAlgorithm, ChecksumAlgorithmTranslationMap, Firmware } from '@shared/models/firmware.models'; | 25 | import { ChecksumAlgorithm, ChecksumAlgorithmTranslationMap, Firmware } from '@shared/models/firmware.models'; |
26 | -import { distinctUntilChanged, map, takeUntil } from 'rxjs/operators'; | ||
27 | import { ActionNotificationShow } from '@core/notification/notification.actions'; | 26 | import { ActionNotificationShow } from '@core/notification/notification.actions'; |
28 | 27 | ||
29 | @Component({ | 28 | @Component({ |
@@ -45,26 +44,6 @@ export class FirmwaresComponent extends EntityComponent<Firmware> implements OnI | @@ -45,26 +44,6 @@ export class FirmwaresComponent extends EntityComponent<Firmware> implements OnI | ||
45 | super(store, fb, entityValue, entitiesTableConfigValue); | 44 | super(store, fb, entityValue, entitiesTableConfigValue); |
46 | } | 45 | } |
47 | 46 | ||
48 | - ngOnInit() { | ||
49 | - super.ngOnInit(); | ||
50 | - if (this.isAdd) { | ||
51 | - this.entityForm.get('checksumAlgorithm').valueChanges.pipe( | ||
52 | - map(algorithm => !!algorithm), | ||
53 | - distinctUntilChanged(), | ||
54 | - takeUntil(this.destroy$) | ||
55 | - ).subscribe( | ||
56 | - setAlgorithm => { | ||
57 | - if (setAlgorithm) { | ||
58 | - this.entityForm.get('checksum').setValidators([Validators.maxLength(1020), Validators.required]); | ||
59 | - } else { | ||
60 | - this.entityForm.get('checksum').clearValidators(); | ||
61 | - } | ||
62 | - this.entityForm.get('checksum').updateValueAndValidity({emitEvent: false}); | ||
63 | - } | ||
64 | - ); | ||
65 | - } | ||
66 | - } | ||
67 | - | ||
68 | ngOnDestroy() { | 47 | ngOnDestroy() { |
69 | super.ngOnDestroy(); | 48 | super.ngOnDestroy(); |
70 | this.destroy$.next(); | 49 | this.destroy$.next(); |
@@ -83,7 +62,7 @@ export class FirmwaresComponent extends EntityComponent<Firmware> implements OnI | @@ -83,7 +62,7 @@ export class FirmwaresComponent extends EntityComponent<Firmware> implements OnI | ||
83 | const form = this.fb.group({ | 62 | const form = this.fb.group({ |
84 | title: [entity ? entity.title : '', [Validators.required, Validators.maxLength(255)]], | 63 | title: [entity ? entity.title : '', [Validators.required, Validators.maxLength(255)]], |
85 | version: [entity ? entity.version : '', [Validators.required, Validators.maxLength(255)]], | 64 | version: [entity ? entity.version : '', [Validators.required, Validators.maxLength(255)]], |
86 | - checksumAlgorithm: [entity ? entity.checksumAlgorithm : null], | 65 | + checksumAlgorithm: [entity && entity.checksumAlgorithm ? entity.checksumAlgorithm : ChecksumAlgorithm.SHA256], |
87 | checksum: [entity ? entity.checksum : '', Validators.maxLength(1020)], | 66 | checksum: [entity ? entity.checksum : '', Validators.maxLength(1020)], |
88 | additionalInfo: this.fb.group( | 67 | additionalInfo: this.fb.group( |
89 | { | 68 | { |
@@ -38,8 +38,8 @@ export interface FirmwareInfo extends BaseData<FirmwareId> { | @@ -38,8 +38,8 @@ export interface FirmwareInfo extends BaseData<FirmwareId> { | ||
38 | version?: string; | 38 | version?: string; |
39 | hasData?: boolean; | 39 | hasData?: boolean; |
40 | fileName: string; | 40 | fileName: string; |
41 | - checksum?: ChecksumAlgorithm; | ||
42 | - checksumAlgorithm?: string; | 41 | + checksum?: string; |
42 | + checksumAlgorithm: ChecksumAlgorithm; | ||
43 | contentType: string; | 43 | contentType: string; |
44 | dataSize?: number; | 44 | dataSize?: number; |
45 | additionalInfo?: any; | 45 | additionalInfo?: any; |