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,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;