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 | 115 | @ResponseBody |
116 | 116 | public Firmware saveFirmwareData(@PathVariable(FIRMWARE_ID) String strFirmwareId, |
117 | 117 | @RequestParam(required = false) String checksum, |
118 | - @RequestParam(required = false) String checksumAlgorithm, | |
118 | + @RequestParam() String checksumAlgorithm, | |
119 | 119 | @RequestBody MultipartFile file) throws ThingsboardException { |
120 | 120 | checkParameter(FIRMWARE_ID, strFirmwareId); |
121 | 121 | try { |
... | ... | @@ -129,18 +129,17 @@ public class FirmwareController extends BaseController { |
129 | 129 | firmware.setVersion(info.getVersion()); |
130 | 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 | 137 | firmware.setChecksumAlgorithm(checksumAlgorithm); |
139 | 138 | firmware.setChecksum(checksum); |
140 | 139 | firmware.setFileName(file.getOriginalFilename()); |
141 | 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 | 143 | return firmwareService.saveFirmware(firmware); |
145 | 144 | } catch (Exception e) { |
146 | 145 | throw handleException(e); | ... | ... |
... | ... | @@ -22,12 +22,16 @@ import org.thingsboard.server.common.data.id.TenantId; |
22 | 22 | import org.thingsboard.server.common.data.page.PageData; |
23 | 23 | import org.thingsboard.server.common.data.page.PageLink; |
24 | 24 | |
25 | +import java.nio.ByteBuffer; | |
26 | + | |
25 | 27 | public interface FirmwareService { |
26 | 28 | |
27 | 29 | FirmwareInfo saveFirmwareInfo(FirmwareInfo firmwareInfo); |
28 | 30 | |
29 | 31 | Firmware saveFirmware(Firmware firmware); |
30 | 32 | |
33 | + String generateChecksum(String checksumAlgorithm, ByteBuffer data); | |
34 | + | |
31 | 35 | Firmware findFirmwareById(TenantId tenantId, FirmwareId firmwareId); |
32 | 36 | |
33 | 37 | FirmwareInfo findFirmwareInfoById(TenantId tenantId, FirmwareId firmwareId); | ... | ... |
... | ... | @@ -456,9 +456,6 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement |
456 | 456 | deviceSessionCtx.getPayloadAdaptor() |
457 | 457 | .convertToPublish(deviceSessionCtx, firmwareChunk, requestId, chunk) |
458 | 458 | .ifPresent(deviceSessionCtx.getChannel()::writeAndFlush); |
459 | - if (firmwareChunk != null && chunkSize != firmwareChunk.length) { | |
460 | - scheduler.schedule(() -> processDisconnect(ctx), 60, TimeUnit.SECONDS); | |
461 | - } | |
462 | 459 | } catch (Exception e) { |
463 | 460 | log.trace("[{}] Failed to send firmware response!", sessionId, e); |
464 | 461 | } | ... | ... |
... | ... | @@ -102,6 +102,32 @@ public class BaseFirmwareService implements FirmwareService { |
102 | 102 | } |
103 | 103 | |
104 | 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 | 131 | public Firmware findFirmwareById(TenantId tenantId, FirmwareId firmwareId) { |
106 | 132 | log.trace("Executing findFirmwareById [{}]", firmwareId); |
107 | 133 | validateId(firmwareId, INCORRECT_FIRMWARE_ID + firmwareId); |
... | ... | @@ -217,11 +243,6 @@ public class BaseFirmwareService implements FirmwareService { |
217 | 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 | 246 | if (StringUtils.isEmpty(firmware.getChecksumAlgorithm())) { |
226 | 247 | throw new DataValidationException("Firmware checksum algorithm should be specified!"); |
227 | 248 | } |
... | ... | @@ -229,22 +250,7 @@ public class BaseFirmwareService implements FirmwareService { |
229 | 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 | 255 | if (!currentChecksum.equals(firmware.getChecksum())) { |
250 | 256 | throw new DataValidationException("Wrong firmware file!"); | ... | ... |
... | ... | @@ -20,7 +20,7 @@ import { PageLink } from '@shared/models/page/page-link'; |
20 | 20 | import { defaultHttpOptionsFromConfig, defaultHttpUploadOptions, RequestConfig } from '@core/http/http-utils'; |
21 | 21 | import { Observable } from 'rxjs'; |
22 | 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 | 24 | import { catchError, map, mergeMap } from 'rxjs/operators'; |
25 | 25 | import { deepClone, isDefinedAndNotNull } from '@core/utils'; |
26 | 26 | |
... | ... | @@ -100,16 +100,16 @@ export class FirmwareService { |
100 | 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 | 104 | checksum?: string, config?: RequestConfig): Observable<any> { |
105 | 105 | if (!config) { |
106 | 106 | config = {}; |
107 | 107 | } |
108 | 108 | const formData = new FormData(); |
109 | 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 | 114 | return this.http.post(url, formData, |
115 | 115 | defaultHttpUploadOptions(config.ignoreLoading, config.ignoreErrors, config.resendRequest)); | ... | ... |
... | ... | @@ -72,7 +72,6 @@ |
72 | 72 | <mat-label translate>firmware.checksum-algorithm</mat-label> |
73 | 73 | <input *ngIf="!isAdd" matInput formControlName="checksumAlgorithm" type="text" [readonly]="isEdit"> |
74 | 74 | <mat-select formControlName="checksumAlgorithm" *ngIf="isAdd"> |
75 | - <mat-option [value]=null></mat-option> | |
76 | 75 | <mat-option *ngFor="let checksumAlgorithm of checksumAlgorithms" [value]="checksumAlgorithm"> |
77 | 76 | {{ checksumAlgorithmTranslationMap.get(checksumAlgorithm) }} |
78 | 77 | </mat-option> |
... | ... | @@ -80,11 +79,7 @@ |
80 | 79 | </mat-form-field> |
81 | 80 | <mat-form-field class="mat-block" fxFlex> |
82 | 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 | 83 | </mat-form-field> |
89 | 84 | </div> |
90 | 85 | <section *ngIf="isAdd" style="padding-top: 8px"> | ... | ... |
... | ... | @@ -23,7 +23,6 @@ import { EntityTableConfig } from '@home/models/entity/entities-table-config.mod |
23 | 23 | import { FormBuilder, FormGroup, Validators } from '@angular/forms'; |
24 | 24 | import { EntityComponent } from '@home/components/entity/entity.component'; |
25 | 25 | import { ChecksumAlgorithm, ChecksumAlgorithmTranslationMap, Firmware } from '@shared/models/firmware.models'; |
26 | -import { distinctUntilChanged, map, takeUntil } from 'rxjs/operators'; | |
27 | 26 | import { ActionNotificationShow } from '@core/notification/notification.actions'; |
28 | 27 | |
29 | 28 | @Component({ |
... | ... | @@ -45,26 +44,6 @@ export class FirmwaresComponent extends EntityComponent<Firmware> implements OnI |
45 | 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 | 47 | ngOnDestroy() { |
69 | 48 | super.ngOnDestroy(); |
70 | 49 | this.destroy$.next(); |
... | ... | @@ -83,7 +62,7 @@ export class FirmwaresComponent extends EntityComponent<Firmware> implements OnI |
83 | 62 | const form = this.fb.group({ |
84 | 63 | title: [entity ? entity.title : '', [Validators.required, Validators.maxLength(255)]], |
85 | 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 | 66 | checksum: [entity ? entity.checksum : '', Validators.maxLength(1020)], |
88 | 67 | additionalInfo: this.fb.group( |
89 | 68 | { | ... | ... |
... | ... | @@ -38,8 +38,8 @@ export interface FirmwareInfo extends BaseData<FirmwareId> { |
38 | 38 | version?: string; |
39 | 39 | hasData?: boolean; |
40 | 40 | fileName: string; |
41 | - checksum?: ChecksumAlgorithm; | |
42 | - checksumAlgorithm?: string; | |
41 | + checksum?: string; | |
42 | + checksumAlgorithm: ChecksumAlgorithm; | |
43 | 43 | contentType: string; |
44 | 44 | dataSize?: number; |
45 | 45 | additionalInfo?: any; | ... | ... |