Added ability to autogenerate checksum for firmware
This commit is contained in:
parent
7ce1fc77c9
commit
8a5a4f0995
@ -115,7 +115,7 @@ public class FirmwareController extends BaseController {
|
|||||||
@ResponseBody
|
@ResponseBody
|
||||||
public Firmware saveFirmwareData(@PathVariable(FIRMWARE_ID) String strFirmwareId,
|
public Firmware saveFirmwareData(@PathVariable(FIRMWARE_ID) String strFirmwareId,
|
||||||
@RequestParam(required = false) String checksum,
|
@RequestParam(required = false) String checksum,
|
||||||
@RequestParam(required = false) String checksumAlgorithm,
|
@RequestParam() String checksumAlgorithm,
|
||||||
@RequestBody MultipartFile file) throws ThingsboardException {
|
@RequestBody MultipartFile file) throws ThingsboardException {
|
||||||
checkParameter(FIRMWARE_ID, strFirmwareId);
|
checkParameter(FIRMWARE_ID, strFirmwareId);
|
||||||
try {
|
try {
|
||||||
@ -129,18 +129,17 @@ public class FirmwareController extends BaseController {
|
|||||||
firmware.setVersion(info.getVersion());
|
firmware.setVersion(info.getVersion());
|
||||||
firmware.setAdditionalInfo(info.getAdditionalInfo());
|
firmware.setAdditionalInfo(info.getAdditionalInfo());
|
||||||
|
|
||||||
byte[] data = file.getBytes();
|
ByteBuffer data = ByteBuffer.wrap(file.getBytes());
|
||||||
if (StringUtils.isEmpty(checksumAlgorithm)) {
|
if (StringUtils.isEmpty(checksum)) {
|
||||||
checksumAlgorithm = "sha256";
|
checksum = firmwareService.generateChecksum(checksumAlgorithm, data);
|
||||||
checksum = Hashing.sha256().hashBytes(data).toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
firmware.setChecksumAlgorithm(checksumAlgorithm);
|
firmware.setChecksumAlgorithm(checksumAlgorithm);
|
||||||
firmware.setChecksum(checksum);
|
firmware.setChecksum(checksum);
|
||||||
firmware.setFileName(file.getOriginalFilename());
|
firmware.setFileName(file.getOriginalFilename());
|
||||||
firmware.setContentType(file.getContentType());
|
firmware.setContentType(file.getContentType());
|
||||||
firmware.setData(ByteBuffer.wrap(data));
|
firmware.setData(data);
|
||||||
firmware.setDataSize((long) data.length);
|
firmware.setDataSize((long) data.array().length);
|
||||||
return firmwareService.saveFirmware(firmware);
|
return firmwareService.saveFirmware(firmware);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw handleException(e);
|
throw handleException(e);
|
||||||
|
|||||||
@ -22,12 +22,16 @@ import org.thingsboard.server.common.data.id.TenantId;
|
|||||||
import org.thingsboard.server.common.data.page.PageData;
|
import org.thingsboard.server.common.data.page.PageData;
|
||||||
import org.thingsboard.server.common.data.page.PageLink;
|
import org.thingsboard.server.common.data.page.PageLink;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
public interface FirmwareService {
|
public interface FirmwareService {
|
||||||
|
|
||||||
FirmwareInfo saveFirmwareInfo(FirmwareInfo firmwareInfo);
|
FirmwareInfo saveFirmwareInfo(FirmwareInfo firmwareInfo);
|
||||||
|
|
||||||
Firmware saveFirmware(Firmware firmware);
|
Firmware saveFirmware(Firmware firmware);
|
||||||
|
|
||||||
|
String generateChecksum(String checksumAlgorithm, ByteBuffer data);
|
||||||
|
|
||||||
Firmware findFirmwareById(TenantId tenantId, FirmwareId firmwareId);
|
Firmware findFirmwareById(TenantId tenantId, FirmwareId firmwareId);
|
||||||
|
|
||||||
FirmwareInfo findFirmwareInfoById(TenantId tenantId, FirmwareId firmwareId);
|
FirmwareInfo findFirmwareInfoById(TenantId tenantId, FirmwareId firmwareId);
|
||||||
|
|||||||
@ -456,9 +456,6 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
|
|||||||
deviceSessionCtx.getPayloadAdaptor()
|
deviceSessionCtx.getPayloadAdaptor()
|
||||||
.convertToPublish(deviceSessionCtx, firmwareChunk, requestId, chunk)
|
.convertToPublish(deviceSessionCtx, firmwareChunk, requestId, chunk)
|
||||||
.ifPresent(deviceSessionCtx.getChannel()::writeAndFlush);
|
.ifPresent(deviceSessionCtx.getChannel()::writeAndFlush);
|
||||||
if (firmwareChunk != null && chunkSize != firmwareChunk.length) {
|
|
||||||
scheduler.schedule(() -> processDisconnect(ctx), 60, TimeUnit.SECONDS);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.trace("[{}] Failed to send firmware response!", sessionId, e);
|
log.trace("[{}] Failed to send firmware response!", sessionId, e);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -101,6 +101,32 @@ public class BaseFirmwareService implements FirmwareService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String generateChecksum(String checksumAlgorithm, ByteBuffer data) {
|
||||||
|
|
||||||
|
if (data == null || !data.hasArray() || data.array().length == 0) {
|
||||||
|
throw new DataValidationException("Firmware data should be specified!");
|
||||||
|
}
|
||||||
|
|
||||||
|
HashFunction hashFunction;
|
||||||
|
switch (checksumAlgorithm) {
|
||||||
|
case "sha256":
|
||||||
|
hashFunction = Hashing.sha256();
|
||||||
|
break;
|
||||||
|
case "md5":
|
||||||
|
hashFunction = Hashing.md5();
|
||||||
|
break;
|
||||||
|
case "crc32":
|
||||||
|
hashFunction = Hashing.crc32();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new DataValidationException("Unknown checksum algorithm!");
|
||||||
|
}
|
||||||
|
|
||||||
|
return hashFunction.hashBytes(data.array()).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Firmware findFirmwareById(TenantId tenantId, FirmwareId firmwareId) {
|
public Firmware findFirmwareById(TenantId tenantId, FirmwareId firmwareId) {
|
||||||
log.trace("Executing findFirmwareById [{}]", firmwareId);
|
log.trace("Executing findFirmwareById [{}]", firmwareId);
|
||||||
@ -217,11 +243,6 @@ public class BaseFirmwareService implements FirmwareService {
|
|||||||
throw new DataValidationException("Firmware content type should be specified!");
|
throw new DataValidationException("Firmware content type should be specified!");
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteBuffer data = firmware.getData();
|
|
||||||
if (data == null || !data.hasArray() || data.array().length == 0) {
|
|
||||||
throw new DataValidationException("Firmware data should be specified!");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (StringUtils.isEmpty(firmware.getChecksumAlgorithm())) {
|
if (StringUtils.isEmpty(firmware.getChecksumAlgorithm())) {
|
||||||
throw new DataValidationException("Firmware checksum algorithm should be specified!");
|
throw new DataValidationException("Firmware checksum algorithm should be specified!");
|
||||||
}
|
}
|
||||||
@ -229,22 +250,7 @@ public class BaseFirmwareService implements FirmwareService {
|
|||||||
throw new DataValidationException("Firmware checksum should be specified!");
|
throw new DataValidationException("Firmware checksum should be specified!");
|
||||||
}
|
}
|
||||||
|
|
||||||
HashFunction hashFunction;
|
String currentChecksum = generateChecksum(firmware.getChecksumAlgorithm(), firmware.getData());
|
||||||
switch (firmware.getChecksumAlgorithm()) {
|
|
||||||
case "sha256":
|
|
||||||
hashFunction = Hashing.sha256();
|
|
||||||
break;
|
|
||||||
case "md5":
|
|
||||||
hashFunction = Hashing.md5();
|
|
||||||
break;
|
|
||||||
case "crc32":
|
|
||||||
hashFunction = Hashing.crc32();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new DataValidationException("Unknown checksum algorithm!");
|
|
||||||
}
|
|
||||||
|
|
||||||
String currentChecksum = hashFunction.hashBytes(data.array()).toString();
|
|
||||||
|
|
||||||
if (!currentChecksum.equals(firmware.getChecksum())) {
|
if (!currentChecksum.equals(firmware.getChecksum())) {
|
||||||
throw new DataValidationException("Wrong firmware file!");
|
throw new DataValidationException("Wrong firmware file!");
|
||||||
|
|||||||
@ -20,7 +20,7 @@ import { PageLink } from '@shared/models/page/page-link';
|
|||||||
import { defaultHttpOptionsFromConfig, defaultHttpUploadOptions, RequestConfig } from '@core/http/http-utils';
|
import { defaultHttpOptionsFromConfig, defaultHttpUploadOptions, RequestConfig } from '@core/http/http-utils';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { PageData } from '@shared/models/page/page-data';
|
import { PageData } from '@shared/models/page/page-data';
|
||||||
import { Firmware, FirmwareInfo } from '@shared/models/firmware.models';
|
import { ChecksumAlgorithm, Firmware, FirmwareInfo } from '@shared/models/firmware.models';
|
||||||
import { catchError, map, mergeMap } from 'rxjs/operators';
|
import { catchError, map, mergeMap } from 'rxjs/operators';
|
||||||
import { deepClone, isDefinedAndNotNull } from '@core/utils';
|
import { deepClone, isDefinedAndNotNull } from '@core/utils';
|
||||||
|
|
||||||
@ -100,16 +100,16 @@ export class FirmwareService {
|
|||||||
return this.http.post<Firmware>('/api/firmware', firmware, defaultHttpOptionsFromConfig(config));
|
return this.http.post<Firmware>('/api/firmware', firmware, defaultHttpOptionsFromConfig(config));
|
||||||
}
|
}
|
||||||
|
|
||||||
public uploadFirmwareFile(firmwareId: string, file: File, checksumAlgorithm?: string,
|
public uploadFirmwareFile(firmwareId: string, file: File, checksumAlgorithm: ChecksumAlgorithm,
|
||||||
checksum?: string, config?: RequestConfig): Observable<any> {
|
checksum?: string, config?: RequestConfig): Observable<any> {
|
||||||
if (!config) {
|
if (!config) {
|
||||||
config = {};
|
config = {};
|
||||||
}
|
}
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append('file', file);
|
formData.append('file', file);
|
||||||
let url = `/api/firmware/${firmwareId}`;
|
let url = `/api/firmware/${firmwareId}?checksumAlgorithm=${checksumAlgorithm}`;
|
||||||
if (checksumAlgorithm && checksum) {
|
if (checksum) {
|
||||||
url += `?checksumAlgorithm=${checksumAlgorithm}&checksum=${checksum}`;
|
url += `&checksum=${checksum}`;
|
||||||
}
|
}
|
||||||
return this.http.post(url, formData,
|
return this.http.post(url, formData,
|
||||||
defaultHttpUploadOptions(config.ignoreLoading, config.ignoreErrors, config.resendRequest));
|
defaultHttpUploadOptions(config.ignoreLoading, config.ignoreErrors, config.resendRequest));
|
||||||
|
|||||||
@ -72,7 +72,6 @@
|
|||||||
<mat-label translate>firmware.checksum-algorithm</mat-label>
|
<mat-label translate>firmware.checksum-algorithm</mat-label>
|
||||||
<input *ngIf="!isAdd" matInput formControlName="checksumAlgorithm" type="text" [readonly]="isEdit">
|
<input *ngIf="!isAdd" matInput formControlName="checksumAlgorithm" type="text" [readonly]="isEdit">
|
||||||
<mat-select formControlName="checksumAlgorithm" *ngIf="isAdd">
|
<mat-select formControlName="checksumAlgorithm" *ngIf="isAdd">
|
||||||
<mat-option [value]=null></mat-option>
|
|
||||||
<mat-option *ngFor="let checksumAlgorithm of checksumAlgorithms" [value]="checksumAlgorithm">
|
<mat-option *ngFor="let checksumAlgorithm of checksumAlgorithms" [value]="checksumAlgorithm">
|
||||||
{{ checksumAlgorithmTranslationMap.get(checksumAlgorithm) }}
|
{{ checksumAlgorithmTranslationMap.get(checksumAlgorithm) }}
|
||||||
</mat-option>
|
</mat-option>
|
||||||
@ -80,11 +79,7 @@
|
|||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<mat-form-field class="mat-block" fxFlex>
|
<mat-form-field class="mat-block" fxFlex>
|
||||||
<mat-label translate>firmware.checksum</mat-label>
|
<mat-label translate>firmware.checksum</mat-label>
|
||||||
<input matInput formControlName="checksum" type="text" [readonly]="!isAdd"
|
<input matInput formControlName="checksum" type="text" [readonly]="!isAdd">
|
||||||
[required]="entityForm.get('checksumAlgorithm').value != null">
|
|
||||||
<mat-error *ngIf="entityForm.get('checksumAlgorithm').hasError('required')">
|
|
||||||
{{ 'firmware.checksum-required' | translate }}
|
|
||||||
</mat-error>
|
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
<section *ngIf="isAdd" style="padding-top: 8px">
|
<section *ngIf="isAdd" style="padding-top: 8px">
|
||||||
|
|||||||
@ -23,7 +23,6 @@ import { EntityTableConfig } from '@home/models/entity/entities-table-config.mod
|
|||||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||||
import { EntityComponent } from '@home/components/entity/entity.component';
|
import { EntityComponent } from '@home/components/entity/entity.component';
|
||||||
import { ChecksumAlgorithm, ChecksumAlgorithmTranslationMap, Firmware } from '@shared/models/firmware.models';
|
import { ChecksumAlgorithm, ChecksumAlgorithmTranslationMap, Firmware } from '@shared/models/firmware.models';
|
||||||
import { distinctUntilChanged, map, takeUntil } from 'rxjs/operators';
|
|
||||||
import { ActionNotificationShow } from '@core/notification/notification.actions';
|
import { ActionNotificationShow } from '@core/notification/notification.actions';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -45,26 +44,6 @@ export class FirmwaresComponent extends EntityComponent<Firmware> implements OnI
|
|||||||
super(store, fb, entityValue, entitiesTableConfigValue);
|
super(store, fb, entityValue, entitiesTableConfigValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
|
||||||
super.ngOnInit();
|
|
||||||
if (this.isAdd) {
|
|
||||||
this.entityForm.get('checksumAlgorithm').valueChanges.pipe(
|
|
||||||
map(algorithm => !!algorithm),
|
|
||||||
distinctUntilChanged(),
|
|
||||||
takeUntil(this.destroy$)
|
|
||||||
).subscribe(
|
|
||||||
setAlgorithm => {
|
|
||||||
if (setAlgorithm) {
|
|
||||||
this.entityForm.get('checksum').setValidators([Validators.maxLength(1020), Validators.required]);
|
|
||||||
} else {
|
|
||||||
this.entityForm.get('checksum').clearValidators();
|
|
||||||
}
|
|
||||||
this.entityForm.get('checksum').updateValueAndValidity({emitEvent: false});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
super.ngOnDestroy();
|
super.ngOnDestroy();
|
||||||
this.destroy$.next();
|
this.destroy$.next();
|
||||||
@ -83,7 +62,7 @@ export class FirmwaresComponent extends EntityComponent<Firmware> implements OnI
|
|||||||
const form = this.fb.group({
|
const form = this.fb.group({
|
||||||
title: [entity ? entity.title : '', [Validators.required, Validators.maxLength(255)]],
|
title: [entity ? entity.title : '', [Validators.required, Validators.maxLength(255)]],
|
||||||
version: [entity ? entity.version : '', [Validators.required, Validators.maxLength(255)]],
|
version: [entity ? entity.version : '', [Validators.required, Validators.maxLength(255)]],
|
||||||
checksumAlgorithm: [entity ? entity.checksumAlgorithm : null],
|
checksumAlgorithm: [entity && entity.checksumAlgorithm ? entity.checksumAlgorithm : ChecksumAlgorithm.SHA256],
|
||||||
checksum: [entity ? entity.checksum : '', Validators.maxLength(1020)],
|
checksum: [entity ? entity.checksum : '', Validators.maxLength(1020)],
|
||||||
additionalInfo: this.fb.group(
|
additionalInfo: this.fb.group(
|
||||||
{
|
{
|
||||||
|
|||||||
@ -38,8 +38,8 @@ export interface FirmwareInfo extends BaseData<FirmwareId> {
|
|||||||
version?: string;
|
version?: string;
|
||||||
hasData?: boolean;
|
hasData?: boolean;
|
||||||
fileName: string;
|
fileName: string;
|
||||||
checksum?: ChecksumAlgorithm;
|
checksum?: string;
|
||||||
checksumAlgorithm?: string;
|
checksumAlgorithm: ChecksumAlgorithm;
|
||||||
contentType: string;
|
contentType: string;
|
||||||
dataSize?: number;
|
dataSize?: number;
|
||||||
additionalInfo?: any;
|
additionalInfo?: any;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user