committed by
GitHub
43 changed files with 1097 additions and 513 deletions
@ -0,0 +1,29 @@ |
|||
/** |
|||
* Copyright © 2016-2021 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.common.data.device.profile.lwm2m.bootstrap; |
|||
|
|||
import io.swagger.annotations.ApiModel; |
|||
import io.swagger.annotations.ApiModelProperty; |
|||
import lombok.Data; |
|||
|
|||
@ApiModel |
|||
@Data |
|||
public class LwM2MServerSecurityConfigDefault extends LwM2MServerSecurityConfig { |
|||
@ApiModelProperty(position = 5, value = "Host for 'Security' mode (DTLS)", example = "0.0.0.0", readOnly = true) |
|||
protected String securityHost; |
|||
@ApiModelProperty(position = 6, value = "Port for 'Security' mode (DTLS): Lwm2m Server or Bootstrap Server", example = "5686 or 5688", readOnly = true) |
|||
protected Integer securityPort; |
|||
} |
|||
@ -0,0 +1,255 @@ |
|||
/** |
|||
* Copyright © 2016-2021 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.transport.lwm2m.bootstrap.store; |
|||
|
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.eclipse.leshan.core.Link; |
|||
import org.eclipse.leshan.core.node.LwM2mObject; |
|||
import org.eclipse.leshan.core.node.LwM2mPath; |
|||
import org.eclipse.leshan.core.request.*; |
|||
import org.eclipse.leshan.core.response.BootstrapDiscoverResponse; |
|||
import org.eclipse.leshan.core.response.BootstrapReadResponse; |
|||
import org.eclipse.leshan.core.response.LwM2mResponse; |
|||
import org.eclipse.leshan.server.bootstrap.BootstrapConfig; |
|||
import org.eclipse.leshan.server.bootstrap.BootstrapConfigStore; |
|||
import org.eclipse.leshan.server.bootstrap.BootstrapSession; |
|||
import org.eclipse.leshan.server.bootstrap.BootstrapTaskProvider; |
|||
import org.eclipse.leshan.server.bootstrap.BootstrapUtil; |
|||
|
|||
import java.net.InetSocketAddress; |
|||
import java.util.*; |
|||
import java.util.stream.Collectors; |
|||
|
|||
import static org.eclipse.leshan.server.bootstrap.BootstrapUtil.toWriteRequest; |
|||
|
|||
@Slf4j |
|||
public class LwM2MBootstrapConfigStoreTaskProvider implements BootstrapTaskProvider { |
|||
|
|||
private BootstrapConfigStore store; |
|||
|
|||
private Map<Integer, String> supportedObjects; |
|||
|
|||
/** |
|||
* Map<serverId, InstanceId> |
|||
*/ |
|||
protected Map<Integer, Integer> securityInstances; |
|||
protected Map<Integer, Integer> serverInstances; |
|||
protected Integer bootstrapServerIdOld; |
|||
protected Integer bootstrapServerIdNew; |
|||
|
|||
public LwM2MBootstrapConfigStoreTaskProvider(BootstrapConfigStore store) { |
|||
this.store = store; |
|||
} |
|||
|
|||
@Override |
|||
public Tasks getTasks(BootstrapSession session, List<LwM2mResponse> previousResponse) { |
|||
|
|||
BootstrapConfig config = store.get(session.getEndpoint(), session.getIdentity(), session); |
|||
if (config == null) { |
|||
return null; |
|||
} |
|||
if (previousResponse == null && shouldStartWithDiscover(config)) { |
|||
Tasks tasks = new Tasks(); |
|||
tasks.requestsToSend = new ArrayList<>(1); |
|||
tasks.requestsToSend.add(new BootstrapDiscoverRequest()); |
|||
tasks.last = false; |
|||
return tasks; |
|||
} else { |
|||
Tasks tasks = new Tasks(); |
|||
if (this.supportedObjects == null) { |
|||
initSupportedObjectsDefault(); |
|||
|
|||
} |
|||
// add supportedObjects
|
|||
tasks.supportedObjects = this.supportedObjects; |
|||
// handle bootstrap discover response
|
|||
if (previousResponse != null) { |
|||
if (previousResponse.get(0) instanceof BootstrapDiscoverResponse) { |
|||
BootstrapDiscoverResponse discoverResponse = (BootstrapDiscoverResponse) previousResponse.get(0); |
|||
if (discoverResponse.isSuccess()) { |
|||
this.initAfterBootstrapDiscover(discoverResponse); |
|||
findSecurityInstanceId(discoverResponse.getObjectLinks()); |
|||
} else { |
|||
log.info( |
|||
"Bootstrap Discover return error {} : to continue bootstrap session without autoIdForSecurityObject mode. {}", |
|||
discoverResponse, session); |
|||
} |
|||
if (this.securityInstances.get(0) == null) { |
|||
log.error( |
|||
"Unable to find bootstrap server instance in Security Object (0) in response {}: unable to continue bootstrap session with autoIdForSecurityObject mode. {}", |
|||
discoverResponse, session); |
|||
return null; |
|||
} |
|||
tasks.requestsToSend = new ArrayList<>(1); |
|||
tasks.requestsToSend.add(new BootstrapReadRequest("/1")); |
|||
tasks.last = false; |
|||
return tasks; |
|||
} |
|||
BootstrapReadResponse readResponse = (BootstrapReadResponse) previousResponse.get(0); |
|||
findServerInstanceId(readResponse); |
|||
// create requests from config
|
|||
tasks.requestsToSend = this.toRequests(config, |
|||
config.contentFormat != null ? config.contentFormat : session.getContentFormat()); |
|||
} else { |
|||
// create requests from config
|
|||
tasks.requestsToSend = BootstrapUtil.toRequests(config, |
|||
config.contentFormat != null ? config.contentFormat : session.getContentFormat()); |
|||
|
|||
} |
|||
return tasks; |
|||
} |
|||
} |
|||
|
|||
protected boolean shouldStartWithDiscover(BootstrapConfig config) { |
|||
return config.autoIdForSecurityObject; |
|||
} |
|||
|
|||
protected void findSecurityInstanceId(Link[] objectLinks) { |
|||
log.info("Object after discover: [{}]", objectLinks); |
|||
this.securityInstances = new HashMap<>(); |
|||
for (Link link : objectLinks) { |
|||
if (link.getUrl().startsWith("/0/")) { |
|||
try { |
|||
LwM2mPath path = new LwM2mPath(link.getUrl()); |
|||
if (path.isObjectInstance()) { |
|||
if (link.getAttributes().containsKey("ssid")) { |
|||
int serverId = Integer.valueOf(link.getAttributes().get("ssid")); |
|||
if (!this.securityInstances.containsKey(serverId)) { |
|||
this.securityInstances.put(serverId, path.getObjectInstanceId()); |
|||
} else { |
|||
log.error(String.format("Invalid lwm2mSecurityInstance by [{}]", path.getObjectInstanceId())); |
|||
} |
|||
this.securityInstances.put(Integer.valueOf(link.getAttributes().get("ssid")), path.getObjectInstanceId()); |
|||
} else { |
|||
if (!this.securityInstances.containsKey(0)) { |
|||
this.securityInstances.put(0, path.getObjectInstanceId()); |
|||
} else { |
|||
log.error(String.format("Invalid bootstrapSecurityInstance by [{}]", path.getObjectInstanceId())); |
|||
} |
|||
} |
|||
} |
|||
} catch (Exception e) { |
|||
// ignore if this is not a LWM2M path
|
|||
log.error("Invalid LwM2MPath starting by \"/0/\""); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
protected void findServerInstanceId(BootstrapReadResponse readResponse) { |
|||
this.serverInstances = new HashMap<>(); |
|||
((LwM2mObject) readResponse.getContent()).getInstances().values().forEach(instance -> { |
|||
serverInstances.put(((Long) instance.getResource(0).getValue()).intValue(), instance.getId()); |
|||
}); |
|||
if (this.securityInstances != null && this.securityInstances.size() > 0 && this.serverInstances != null && this.serverInstances.size() > 0) { |
|||
this.findBootstrapServerId(); |
|||
} |
|||
} |
|||
|
|||
protected void findBootstrapServerId() { |
|||
Map<Integer, Integer> filteredMap = this.serverInstances.entrySet() |
|||
.stream().filter(x -> !this.securityInstances.containsKey(x.getKey())) |
|||
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); |
|||
this.bootstrapServerIdOld = filteredMap.keySet().stream().findFirst().get(); |
|||
} |
|||
|
|||
public BootstrapConfigStore getStore() { |
|||
return this.store; |
|||
} |
|||
|
|||
private void initAfterBootstrapDiscover(BootstrapDiscoverResponse response) { |
|||
Link[] links = response.getObjectLinks(); |
|||
Arrays.stream(links).forEach(link -> { |
|||
LwM2mPath path = new LwM2mPath(link.getUrl()); |
|||
if (path != null && !path.isRoot() && path.getObjectId() < 3) { |
|||
if (path.isObject()) { |
|||
String ver = link.getAttributes().get("ver") != null ? link.getAttributes().get("ver") : "1.0"; |
|||
this.supportedObjects.put(path.getObjectId(), ver); |
|||
} |
|||
} |
|||
}); |
|||
} |
|||
|
|||
|
|||
public List<BootstrapDownlinkRequest<? extends LwM2mResponse>> toRequests(BootstrapConfig bootstrapConfig, |
|||
ContentFormat contentFormat) { |
|||
List<BootstrapDownlinkRequest<? extends LwM2mResponse>> requests = new ArrayList<>(); |
|||
List<BootstrapDownlinkRequest<? extends LwM2mResponse>> requestsDelete = new ArrayList<>(); |
|||
List<BootstrapDownlinkRequest<? extends LwM2mResponse>> requestsWrite = new ArrayList<>(); |
|||
boolean isBsServer = false; |
|||
boolean isLwServer = false; |
|||
/** Map<serverId, InstanceId> */ |
|||
Map<Integer, Integer> instances = new HashMap<>(); |
|||
// handle security
|
|||
int id = 0; |
|||
for (BootstrapConfig.ServerSecurity security : new TreeMap<>(bootstrapConfig.security).values()) { |
|||
if (security.bootstrapServer) { |
|||
requestsWrite.add(toWriteRequest(this.securityInstances.get(0), security, contentFormat)); |
|||
isBsServer = true; |
|||
this.bootstrapServerIdNew = security.serverId; |
|||
instances.put(security.serverId, this.securityInstances.get(0)); |
|||
} else { |
|||
if (id == this.securityInstances.get(0)) { |
|||
id++; |
|||
} |
|||
requestsWrite.add(toWriteRequest(id, security, contentFormat)); |
|||
instances.put(security.serverId, id); |
|||
isLwServer = true; |
|||
if (!isBsServer && this.securityInstances.containsKey(security.serverId) && id != this.securityInstances.get(security.serverId)) { |
|||
requestsDelete.add(new BootstrapDeleteRequest("/0/" + this.securityInstances.get(security.serverId))); |
|||
} |
|||
id++; |
|||
} |
|||
} |
|||
// handle server
|
|||
for (Map.Entry<Integer, BootstrapConfig.ServerConfig> server : bootstrapConfig.servers.entrySet()) { |
|||
int securityInstanceId = instances.get(server.getValue().shortId); |
|||
requestsWrite.add(toWriteRequest(securityInstanceId, server.getValue(), contentFormat)); |
|||
if (!isLwServer && this.bootstrapServerIdNew != null && server.getValue().shortId == this.bootstrapServerIdNew && |
|||
(this.bootstrapServerIdNew != this.bootstrapServerIdOld || securityInstanceId != this.serverInstances.get(this.bootstrapServerIdOld))) { |
|||
requestsDelete.add(new BootstrapDeleteRequest("/1/" + this.serverInstances.get(this.bootstrapServerIdOld))); |
|||
|
|||
} else { |
|||
if (!isBsServer && this.serverInstances.containsKey(server.getValue().shortId) && securityInstanceId != this.serverInstances.get(server.getValue().shortId)) { |
|||
requestsDelete.add(new BootstrapDeleteRequest("/1/" + this.serverInstances.get(server.getValue().shortId))); |
|||
} |
|||
} |
|||
} |
|||
// handle acl
|
|||
for (Map.Entry<Integer, BootstrapConfig.ACLConfig> acl : bootstrapConfig.acls.entrySet()) { |
|||
requestsWrite.add(toWriteRequest(acl.getKey(), acl.getValue(), contentFormat)); |
|||
} |
|||
// handle delete
|
|||
if (isBsServer & isLwServer) { |
|||
requests.add(new BootstrapDeleteRequest("/0")); |
|||
requests.add(new BootstrapDeleteRequest("/1")); |
|||
} else if (requestsDelete.size() > 0) { |
|||
requests.addAll(requestsDelete); |
|||
} |
|||
// handle write
|
|||
if (requestsWrite.size() > 0) { |
|||
requests.addAll(requestsWrite); |
|||
} |
|||
return (requests); |
|||
} |
|||
|
|||
private void initSupportedObjectsDefault() { |
|||
this.supportedObjects = new HashMap<>(); |
|||
this.supportedObjects.put(0, "1.1"); |
|||
this.supportedObjects.put(1, "1.1"); |
|||
this.supportedObjects.put(2, "1.0"); |
|||
} |
|||
} |
|||
@ -0,0 +1,55 @@ |
|||
<!-- |
|||
|
|||
Copyright © 2016-2021 The Thingsboard Authors |
|||
|
|||
Licensed under the Apache License, Version 2.0 (the "License"); |
|||
you may not use this file except in compliance with the License. |
|||
You may obtain a copy of the License at |
|||
|
|||
http://www.apache.org/licenses/LICENSE-2.0 |
|||
|
|||
Unless required by applicable law or agreed to in writing, software |
|||
distributed under the License is distributed on an "AS IS" BASIS, |
|||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
See the License for the specific language governing permissions and |
|||
limitations under the License. |
|||
|
|||
--> |
|||
<form [formGroup]="addConfigServerFormGroup" style="width: 400px;"> |
|||
<mat-toolbar fxLayout="row" color="primary"> |
|||
<h2 translate>device-profile.lwm2m.add-new-server-title</h2> |
|||
<span fxFlex></span> |
|||
<button mat-button mat-icon-button (click)="cancel()" type="button"> |
|||
<mat-icon class="material-icons">close</mat-icon> |
|||
</button> |
|||
</mat-toolbar> |
|||
<mat-progress-bar color="warn" mode="indeterminate" *ngIf="isLoading$ | async"> |
|||
</mat-progress-bar> |
|||
<div style="height: 4px;" *ngIf="!(isLoading$ | async)"></div> |
|||
<div mat-dialog-content fxLayout="column"> |
|||
<mat-form-field> |
|||
<mat-label>{{ 'device-profile.lwm2m.server-type' | translate }}</mat-label> |
|||
<mat-select formControlName="serverType"> |
|||
<mat-option *ngFor="let serverType of serverTypes" |
|||
[value]="serverType"> |
|||
{{ serverConfigTypeNamesMap.get(serverType) | translate }} |
|||
</mat-option> |
|||
</mat-select> |
|||
</mat-form-field> |
|||
</div> |
|||
<div mat-dialog-actions fxLayout="row"> |
|||
<span fxFlex></span> |
|||
<button mat-button color="primary" |
|||
type="button" |
|||
[disabled]="(isLoading$ | async)" |
|||
(click)="cancel()" cdkFocusInitial> |
|||
{{ 'action.cancel' | translate }} |
|||
</button> |
|||
<button mat-button mat-raised-button color="primary" |
|||
type="button" |
|||
[disabled]="(isLoading$ | async) || addConfigServerFormGroup.invalid" |
|||
(click)="addServerConfig()"> |
|||
{{ 'action.add' | translate }} |
|||
</button> |
|||
</div> |
|||
</form> |
|||
@ -0,0 +1,60 @@ |
|||
///
|
|||
/// Copyright © 2016-2021 The Thingsboard Authors
|
|||
///
|
|||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
|||
/// you may not use this file except in compliance with the License.
|
|||
/// You may obtain a copy of the License at
|
|||
///
|
|||
/// http://www.apache.org/licenses/LICENSE-2.0
|
|||
///
|
|||
/// Unless required by applicable law or agreed to in writing, software
|
|||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
|||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|||
/// See the License for the specific language governing permissions and
|
|||
/// limitations under the License.
|
|||
///
|
|||
|
|||
import { Component } from '@angular/core'; |
|||
import { DialogComponent } from '@shared/components/dialog.component'; |
|||
import { FormBuilder, FormGroup } from '@angular/forms'; |
|||
import { Store } from '@ngrx/store'; |
|||
import { AppState } from '@core/core.state'; |
|||
import { Router } from '@angular/router'; |
|||
import { MatDialogRef } from '@angular/material/dialog'; |
|||
import { |
|||
ServerConfigType, |
|||
ServerConfigTypeTranslationMap |
|||
} from '@home/components/profile/device/lwm2m/lwm2m-profile-config.models'; |
|||
|
|||
@Component({ |
|||
selector: 'tb-profile-lwm2m-bootstrap-add-config-server-dialog', |
|||
templateUrl: './lwm2m-bootstrap-add-config-server-dialog.component.html' |
|||
}) |
|||
export class Lwm2mBootstrapAddConfigServerDialogComponent extends DialogComponent<Lwm2mBootstrapAddConfigServerDialogComponent> { |
|||
|
|||
addConfigServerFormGroup: FormGroup; |
|||
|
|||
serverTypes = Object.values(ServerConfigType); |
|||
serverConfigTypeNamesMap = ServerConfigTypeTranslationMap; |
|||
|
|||
constructor(protected store: Store<AppState>, |
|||
protected router: Router, |
|||
private fb: FormBuilder, |
|||
public dialogRef: MatDialogRef<Lwm2mBootstrapAddConfigServerDialogComponent, boolean>, |
|||
) { |
|||
super(store, router, dialogRef); |
|||
this.addConfigServerFormGroup = this.fb.group({ |
|||
serverType: [ServerConfigType.LWM2M] |
|||
}); |
|||
} |
|||
|
|||
addServerConfig() { |
|||
this.dialogRef.close(this.addConfigServerFormGroup.get('serverType').value === ServerConfigType.BOOTSTRAP); |
|||
} |
|||
|
|||
cancel(): void { |
|||
this.dialogRef.close(null); |
|||
} |
|||
} |
|||
|
|||
|
|||
@ -0,0 +1,39 @@ |
|||
<!-- |
|||
|
|||
Copyright © 2016-2021 The Thingsboard Authors |
|||
|
|||
Licensed under the Apache License, Version 2.0 (the "License"); |
|||
you may not use this file except in compliance with the License. |
|||
You may obtain a copy of the License at |
|||
|
|||
http://www.apache.org/licenses/LICENSE-2.0 |
|||
|
|||
Unless required by applicable law or agreed to in writing, software |
|||
distributed under the License is distributed on an "AS IS" BASIS, |
|||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
See the License for the specific language governing permissions and |
|||
limitations under the License. |
|||
|
|||
--> |
|||
<div fxLayout="column"> |
|||
<mat-accordion multi="true"> |
|||
<div *ngFor="let serverConfig of serverConfigsFromArray().controls; trackBy: trackByParams; let $index = index;"> |
|||
<tb-profile-lwm2m-device-config-server |
|||
[formControl]="serverConfig" |
|||
(removeServer)="removeServerConfig($event, $index)"> |
|||
</tb-profile-lwm2m-device-config-server> |
|||
</div> |
|||
</mat-accordion> |
|||
<div *ngIf="!serverConfigsFromArray().controls.length" style="margin:32px 0"> |
|||
<span translate fxLayoutAlign="center center" |
|||
class="tb-prompt">device-profile.lwm2m.no-config-servers</span> |
|||
</div> |
|||
<div *ngIf="!disabled" style="padding-top: 16px;"> |
|||
<button mat-raised-button color="primary" |
|||
type="button" |
|||
(click)="addServerConfig()"> |
|||
<span>{{ (isBootstrapAdded() ? 'device-profile.lwm2m.add-lwm2m-server-config' : |
|||
'device-profile.lwm2m.add-server-config') | translate}}</span> |
|||
</button> |
|||
</div> |
|||
</div> |
|||
@ -0,0 +1,185 @@ |
|||
///
|
|||
/// Copyright © 2016-2021 The Thingsboard Authors
|
|||
///
|
|||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
|||
/// you may not use this file except in compliance with the License.
|
|||
/// You may obtain a copy of the License at
|
|||
///
|
|||
/// http://www.apache.org/licenses/LICENSE-2.0
|
|||
///
|
|||
/// Unless required by applicable law or agreed to in writing, software
|
|||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
|||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|||
/// See the License for the specific language governing permissions and
|
|||
/// limitations under the License.
|
|||
///
|
|||
|
|||
import { Component, forwardRef, Input, OnInit } from '@angular/core'; |
|||
import { |
|||
AbstractControl, |
|||
ControlValueAccessor, |
|||
FormArray, |
|||
FormBuilder, FormControl, |
|||
FormGroup, |
|||
NG_VALIDATORS, |
|||
NG_VALUE_ACCESSOR |
|||
} from '@angular/forms'; |
|||
import { of, Subscription } from 'rxjs'; |
|||
import { ServerSecurityConfig } from '@home/components/profile/device/lwm2m/lwm2m-profile-config.models'; |
|||
import { TranslateService } from '@ngx-translate/core'; |
|||
import { DialogService } from '@core/services/dialog.service'; |
|||
import { MatDialog } from '@angular/material/dialog'; |
|||
import { Lwm2mBootstrapAddConfigServerDialogComponent } from '@home/components/profile/device/lwm2m/lwm2m-bootstrap-add-config-server-dialog.component'; |
|||
import { mergeMap } from 'rxjs/operators'; |
|||
import { DeviceProfileService } from '@core/http/device-profile.service'; |
|||
import { Lwm2mSecurityType } from '@shared/models/lwm2m-security-config.models'; |
|||
|
|||
@Component({ |
|||
selector: 'tb-profile-lwm2m-bootstrap-config-servers', |
|||
templateUrl: './lwm2m-bootstrap-config-servers.component.html', |
|||
providers: [ |
|||
{ |
|||
provide: NG_VALUE_ACCESSOR, |
|||
useExisting: forwardRef(() => Lwm2mBootstrapConfigServersComponent), |
|||
multi: true |
|||
}, |
|||
{ |
|||
provide: NG_VALIDATORS, |
|||
useExisting: forwardRef(() => Lwm2mBootstrapConfigServersComponent), |
|||
multi: true, |
|||
} |
|||
] |
|||
}) |
|||
export class Lwm2mBootstrapConfigServersComponent implements OnInit, ControlValueAccessor { |
|||
|
|||
bootstrapConfigServersFormGroup: FormGroup; |
|||
|
|||
@Input() |
|||
disabled: boolean; |
|||
|
|||
private valueChangeSubscription: Subscription = null; |
|||
|
|||
private propagateChange = (v: any) => { }; |
|||
|
|||
constructor(public translate: TranslateService, |
|||
public matDialog: MatDialog, |
|||
private dialogService: DialogService, |
|||
private deviceProfileService: DeviceProfileService, |
|||
private fb: FormBuilder) { |
|||
} |
|||
|
|||
registerOnChange(fn: any): void { |
|||
this.propagateChange = fn; |
|||
} |
|||
|
|||
registerOnTouched(fn: any): void { |
|||
} |
|||
|
|||
ngOnInit() { |
|||
this.bootstrapConfigServersFormGroup = this.fb.group({ |
|||
serverConfigs: this.fb.array([]) |
|||
}); |
|||
} |
|||
|
|||
serverConfigsFromArray(): FormArray { |
|||
return this.bootstrapConfigServersFormGroup.get('serverConfigs') as FormArray; |
|||
} |
|||
|
|||
setDisabledState(isDisabled: boolean): void { |
|||
this.disabled = isDisabled; |
|||
if (this.disabled) { |
|||
this.bootstrapConfigServersFormGroup.disable({emitEvent: false}); |
|||
} else { |
|||
this.bootstrapConfigServersFormGroup.enable({emitEvent: false}); |
|||
} |
|||
} |
|||
|
|||
writeValue(serverConfigs: Array<ServerSecurityConfig> | null): void { |
|||
if (this.valueChangeSubscription) { |
|||
this.valueChangeSubscription.unsubscribe(); |
|||
} |
|||
const serverConfigsControls: Array<AbstractControl> = []; |
|||
if (serverConfigs) { |
|||
serverConfigs.forEach((serverConfig) => { |
|||
serverConfigsControls.push(this.fb.control(serverConfig)); |
|||
}); |
|||
} |
|||
this.bootstrapConfigServersFormGroup.setControl('serverConfigs', this.fb.array(serverConfigsControls)); |
|||
if (this.disabled) { |
|||
this.bootstrapConfigServersFormGroup.disable({emitEvent: false}); |
|||
} else { |
|||
this.bootstrapConfigServersFormGroup.enable({emitEvent: false}); |
|||
} |
|||
this.valueChangeSubscription = this.bootstrapConfigServersFormGroup.valueChanges.subscribe(() => { |
|||
this.updateModel(); |
|||
}); |
|||
} |
|||
|
|||
trackByParams(index: number): number { |
|||
return index; |
|||
} |
|||
|
|||
removeServerConfig($event: Event, index: number) { |
|||
if ($event) { |
|||
$event.stopPropagation(); |
|||
$event.preventDefault(); |
|||
} |
|||
this.dialogService.confirm( |
|||
this.translate.instant('device-profile.lwm2m.delete-server-title'), |
|||
this.translate.instant('device-profile.lwm2m.delete-server-text'), |
|||
this.translate.instant('action.no'), |
|||
this.translate.instant('action.yes'), |
|||
true |
|||
).subscribe((result) => { |
|||
if (result) { |
|||
this.serverConfigsFromArray().removeAt(index); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
addServerConfig(): void { |
|||
const addDialogObs = this.isBootstrapAdded() ? of(false) : |
|||
this.matDialog.open<Lwm2mBootstrapAddConfigServerDialogComponent>(Lwm2mBootstrapAddConfigServerDialogComponent, { |
|||
disableClose: true, |
|||
panelClass: ['tb-dialog', 'tb-fullscreen-dialog'] |
|||
}).afterClosed(); |
|||
const addServerConfigObs = addDialogObs.pipe( |
|||
mergeMap((isBootstrap) => { |
|||
if (isBootstrap === null) { |
|||
return of(null); |
|||
} |
|||
return this.deviceProfileService.getLwm2mBootstrapSecurityInfoBySecurityType(isBootstrap, Lwm2mSecurityType.NO_SEC); |
|||
}) |
|||
); |
|||
addServerConfigObs.subscribe((serverConfig) => { |
|||
if (serverConfig) { |
|||
serverConfig.securityMode = Lwm2mSecurityType.NO_SEC; |
|||
this.serverConfigsFromArray().push(this.fb.control(serverConfig)); |
|||
this.updateModel(); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
public validate(c: FormControl) { |
|||
return (this.bootstrapConfigServersFormGroup.valid) ? null : { |
|||
serverConfigs: { |
|||
valid: false, |
|||
}, |
|||
}; |
|||
} |
|||
|
|||
public isBootstrapAdded() { |
|||
const serverConfigsArray = this.serverConfigsFromArray().getRawValue(); |
|||
for (let i = 0; i < serverConfigsArray.length; i++) { |
|||
if (serverConfigsArray[i].bootstrapServerIs) { |
|||
return true; |
|||
} |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
private updateModel() { |
|||
const serverConfigs: Array<ServerSecurityConfig> = this.serverConfigsFromArray().value; |
|||
this.propagateChange(serverConfigs); |
|||
} |
|||
} |
|||
Loading…
Reference in new issue