Commit 8a5a4f0995048ed1d7787bb91bccab135220a7c3

Authored by zbeacon
1 parent 7ce1fc77

Added ability to autogenerate checksum for firmware

... ... @@ -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;
... ...