|
|
|
@ -81,61 +81,39 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie |
|
|
|
|
|
|
|
@Input() |
|
|
|
ctx: WidgetContext; |
|
|
|
|
|
|
|
@Input() |
|
|
|
device: EntityId; |
|
|
|
|
|
|
|
@ViewChild('nameInput') nameInput: ElementRef; |
|
|
|
@ViewChild(MatSort, {static: false}) sort: MatSort; |
|
|
|
|
|
|
|
pageLink: PageLink; |
|
|
|
|
|
|
|
connectorType = ConnectorType; |
|
|
|
|
|
|
|
allowBasicConfig = new Set<ConnectorType>([ |
|
|
|
readonly ConnectorType = ConnectorType; |
|
|
|
readonly allowBasicConfig = new Set<ConnectorType>([ |
|
|
|
ConnectorType.MQTT, |
|
|
|
ConnectorType.OPCUA, |
|
|
|
ConnectorType.MODBUS, |
|
|
|
]); |
|
|
|
readonly gatewayLogLevel = Object.values(GatewayLogLevel); |
|
|
|
readonly displayedColumns = ['enabled', 'key', 'type', 'syncStatus', 'errors', 'actions']; |
|
|
|
readonly GatewayConnectorTypesTranslatesMap = GatewayConnectorDefaultTypesTranslatesMap; |
|
|
|
readonly ConnectorConfigurationModes = ConnectorConfigurationModes; |
|
|
|
|
|
|
|
gatewayLogLevel = Object.values(GatewayLogLevel); |
|
|
|
|
|
|
|
pageLink: PageLink; |
|
|
|
dataSource: MatTableDataSource<AttributeData>; |
|
|
|
|
|
|
|
displayedColumns = ['enabled', 'key', 'type', 'syncStatus', 'errors', 'actions']; |
|
|
|
|
|
|
|
gatewayConnectorDefaultTypes = GatewayConnectorDefaultTypesTranslatesMap; |
|
|
|
|
|
|
|
connectorConfigurationModes = ConnectorConfigurationModes; |
|
|
|
|
|
|
|
connectorForm: FormGroup; |
|
|
|
|
|
|
|
textSearchMode: boolean; |
|
|
|
|
|
|
|
activeConnectors: Array<string>; |
|
|
|
|
|
|
|
mode: ConnectorConfigurationModes = this.connectorConfigurationModes.BASIC; |
|
|
|
|
|
|
|
mode: ConnectorConfigurationModes = this.ConnectorConfigurationModes.BASIC; |
|
|
|
initialConnector: GatewayConnector; |
|
|
|
|
|
|
|
private inactiveConnectors: Array<string>; |
|
|
|
|
|
|
|
private attributeDataSource: AttributeDatasource; |
|
|
|
|
|
|
|
private inactiveConnectorsDataSource: AttributeDatasource; |
|
|
|
|
|
|
|
private serverDataSource: AttributeDatasource; |
|
|
|
|
|
|
|
private activeData: Array<any> = []; |
|
|
|
|
|
|
|
private inactiveData: Array<any> = []; |
|
|
|
|
|
|
|
private sharedAttributeData: Array<AttributeData> = []; |
|
|
|
|
|
|
|
private basicConfigSub: Subscription; |
|
|
|
|
|
|
|
private jsonConfigSub: Subscription; |
|
|
|
|
|
|
|
private subscriptionOptions: WidgetSubscriptionOptions = { |
|
|
|
callbacks: { |
|
|
|
onDataUpdated: () => this.ctx.ngZone.run(() => { |
|
|
|
@ -146,7 +124,6 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie |
|
|
|
}) |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
private destroy$ = new Subject<void>(); |
|
|
|
private subscription: IWidgetSubscription; |
|
|
|
private attributeUpdateSubject = new Subject<AttributeData>(); |
|
|
|
@ -162,101 +139,19 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie |
|
|
|
private utils: UtilsService, |
|
|
|
private cd: ChangeDetectorRef) { |
|
|
|
super(store); |
|
|
|
const sortOrder: SortOrder = {property: 'key', direction: Direction.ASC}; |
|
|
|
this.pageLink = new PageLink(1000, 0, null, sortOrder); |
|
|
|
this.attributeDataSource = new AttributeDatasource(this.attributeService, this.telemetryWsService, this.zone, this.translate); |
|
|
|
this.inactiveConnectorsDataSource = new AttributeDatasource(this.attributeService, this.telemetryWsService, this.zone, this.translate); |
|
|
|
this.serverDataSource = new AttributeDatasource(this.attributeService, this.telemetryWsService, this.zone, this.translate); |
|
|
|
this.dataSource = new MatTableDataSource<AttributeData>([]); |
|
|
|
this.connectorForm = this.fb.group({ |
|
|
|
mode: [ConnectorConfigurationModes.BASIC, []], |
|
|
|
name: ['', [Validators.required, this.uniqNameRequired(), Validators.pattern(noLeadTrailSpacesRegex)]], |
|
|
|
type: ['', [Validators.required]], |
|
|
|
enableRemoteLogging: [false, []], |
|
|
|
logLevel: ['', [Validators.required]], |
|
|
|
sendDataOnlyOnChange: [false, []], |
|
|
|
key: ['auto'], |
|
|
|
class: [''], |
|
|
|
configuration: [''], |
|
|
|
configurationJson: [{}, [Validators.required]], |
|
|
|
basicConfig: [{}] |
|
|
|
}); |
|
|
|
this.connectorForm.disable(); |
|
|
|
|
|
|
|
this.initDataSources(); |
|
|
|
this.initConnectorForm(); |
|
|
|
this.observeAttributeChange(); |
|
|
|
} |
|
|
|
|
|
|
|
ngAfterViewInit(): void { |
|
|
|
this.connectorForm.get('type').valueChanges.pipe( |
|
|
|
takeUntil(this.destroy$) |
|
|
|
).subscribe(type => { |
|
|
|
if (type && !this.initialConnector) { |
|
|
|
this.attributeService.getEntityAttributes(this.device, AttributeScope.CLIENT_SCOPE, |
|
|
|
[`${type.toUpperCase()}_DEFAULT_CONFIG`], {ignoreErrors: true}).subscribe(defaultConfig=>{ |
|
|
|
if (defaultConfig && defaultConfig.length) { |
|
|
|
this.connectorForm.get('configurationJson').setValue( |
|
|
|
isString(defaultConfig[0].value) ? |
|
|
|
JSON.parse(defaultConfig[0].value) : |
|
|
|
defaultConfig[0].value); |
|
|
|
this.cd.detectChanges(); |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
|
this.connectorForm.get('name').valueChanges.pipe( |
|
|
|
takeUntil(this.destroy$) |
|
|
|
).subscribe((name) => { |
|
|
|
if (this.connectorForm.get('type').value === ConnectorType.MQTT) { |
|
|
|
this.connectorForm.get('basicConfig').get('broker.name')?.setValue(name); |
|
|
|
} |
|
|
|
}); |
|
|
|
this.observeName(); |
|
|
|
|
|
|
|
this.dataSource.sort = this.sort; |
|
|
|
this.dataSource.sortingDataAccessor = (data: AttributeData, sortHeaderId: string) => { |
|
|
|
switch (sortHeaderId) { |
|
|
|
case 'syncStatus': |
|
|
|
return this.isConnectorSynced(data) ? 1 : 0; |
|
|
|
|
|
|
|
case 'enabled': |
|
|
|
return this.activeConnectors.includes(data.key) ? 1 : 0; |
|
|
|
|
|
|
|
case 'errors': |
|
|
|
const errors = this.getErrorsCount(data); |
|
|
|
if (typeof errors === 'string') { |
|
|
|
return this.sort.direction.toUpperCase() === Direction.DESC ? -1 : Infinity; |
|
|
|
} |
|
|
|
return errors; |
|
|
|
|
|
|
|
default: |
|
|
|
return data[sortHeaderId] || data.value[sortHeaderId]; |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
if (this.device) { |
|
|
|
if (this.device.id === NULL_UUID) { |
|
|
|
return; |
|
|
|
} |
|
|
|
forkJoin([ |
|
|
|
this.attributeService.getEntityAttributes(this.device, AttributeScope.SHARED_SCOPE, ['active_connectors']), |
|
|
|
this.attributeService.getEntityAttributes(this.device, AttributeScope.SERVER_SCOPE, ['inactive_connectors']) |
|
|
|
]).subscribe(attributes => { |
|
|
|
if (attributes.length) { |
|
|
|
this.activeConnectors = attributes[0].length ? attributes[0][0].value : []; |
|
|
|
this.activeConnectors = isString(this.activeConnectors) ? JSON.parse(this.activeConnectors as any) : this.activeConnectors; |
|
|
|
this.inactiveConnectors = attributes[1].length ? attributes[1][0].value : []; |
|
|
|
this.inactiveConnectors = isString(this.inactiveConnectors) |
|
|
|
? JSON.parse(this.inactiveConnectors as any) |
|
|
|
: this.inactiveConnectors; |
|
|
|
this.updateData(true); |
|
|
|
} else { |
|
|
|
this.activeConnectors = []; |
|
|
|
this.inactiveConnectors = []; |
|
|
|
this.updateData(true); |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
this.dataSource.sortingDataAccessor = this.getSortingDataAccessor(); |
|
|
|
|
|
|
|
this.loadConnectors(); |
|
|
|
this.observeModeChange(); |
|
|
|
} |
|
|
|
|
|
|
|
@ -267,65 +162,83 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie |
|
|
|
} |
|
|
|
|
|
|
|
saveConnector(): void { |
|
|
|
const value = { ...this.connectorForm.value }; |
|
|
|
value.configuration = camelCase(value.name) + '.json'; |
|
|
|
delete value.basicConfig; |
|
|
|
if (value.type !== ConnectorType.GRPC) { |
|
|
|
delete value.key; |
|
|
|
} |
|
|
|
if (value.type !== ConnectorType.CUSTOM) { |
|
|
|
delete value.class; |
|
|
|
} |
|
|
|
value.ts = new Date().getTime(); |
|
|
|
const attributesToSave = [{ |
|
|
|
key: value.name, |
|
|
|
value |
|
|
|
}]; |
|
|
|
const attributesToDelete = []; |
|
|
|
const value = this.getConnectorData(); |
|
|
|
const scope = (!this.initialConnector || this.activeConnectors.includes(this.initialConnector.name)) |
|
|
|
? AttributeScope.SHARED_SCOPE |
|
|
|
: AttributeScope.SERVER_SCOPE; |
|
|
|
let updateActiveConnectors = false; |
|
|
|
if (this.initialConnector && this.initialConnector.name !== value.name) { |
|
|
|
attributesToDelete.push({key: this.initialConnector.name}); |
|
|
|
updateActiveConnectors = true; |
|
|
|
const activeIndex = this.activeConnectors.indexOf(this.initialConnector.name); |
|
|
|
const inactiveIndex = this.inactiveConnectors.indexOf(this.initialConnector.name); |
|
|
|
if (activeIndex !== -1) { |
|
|
|
this.activeConnectors.splice(activeIndex, 1); |
|
|
|
} |
|
|
|
if (inactiveIndex !== -1) { |
|
|
|
this.inactiveConnectors.splice(inactiveIndex, 1); |
|
|
|
} |
|
|
|
} |
|
|
|
if (!this.activeConnectors.includes(value.name) && scope === AttributeScope.SHARED_SCOPE) { |
|
|
|
this.activeConnectors.push(value.name); |
|
|
|
updateActiveConnectors = true; |
|
|
|
? AttributeScope.SHARED_SCOPE |
|
|
|
: AttributeScope.SERVER_SCOPE; |
|
|
|
|
|
|
|
forkJoin(this.getEntityAttributeTasks(value, scope)).pipe(take(1)).subscribe(_ => { |
|
|
|
this.showToast(!this.initialConnector |
|
|
|
? this.translate.instant('gateway.connector-created') |
|
|
|
: this.translate.instant('gateway.connector-updated') |
|
|
|
); |
|
|
|
this.initialConnector = value; |
|
|
|
this.updateData(true); |
|
|
|
this.connectorForm.markAsPristine(); |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
private getEntityAttributeTasks(value: GatewayConnector, scope: AttributeScope): Observable<any>[] { |
|
|
|
const tasks = []; |
|
|
|
const attributesToSave = [{ key: value.name, value }]; |
|
|
|
const attributesToDelete = []; |
|
|
|
const shouldAddToConnectorsList = !this.activeConnectors.includes(value.name) && scope === AttributeScope.SHARED_SCOPE |
|
|
|
|| !this.inactiveConnectors.includes(value.name) && scope === AttributeScope.SERVER_SCOPE; |
|
|
|
const isNewConnector = this.initialConnector && this.initialConnector.name !== value.name; |
|
|
|
|
|
|
|
if (isNewConnector) { |
|
|
|
attributesToDelete.push({ key: this.initialConnector.name }); |
|
|
|
this.removeConnectorFromList(this.initialConnector.name, true); |
|
|
|
this.removeConnectorFromList(this.initialConnector.name, false); |
|
|
|
} |
|
|
|
if (!this.inactiveConnectors.includes(value.name) && scope === AttributeScope.SERVER_SCOPE) { |
|
|
|
this.inactiveConnectors.push(value.name); |
|
|
|
updateActiveConnectors = true; |
|
|
|
|
|
|
|
if (shouldAddToConnectorsList) { |
|
|
|
if (scope === AttributeScope.SHARED_SCOPE) { |
|
|
|
this.activeConnectors.push(value.name); |
|
|
|
} else { |
|
|
|
this.inactiveConnectors.push(value.name); |
|
|
|
} |
|
|
|
} |
|
|
|
const tasks = [this.attributeService.saveEntityAttributes(this.device, scope, attributesToSave)]; |
|
|
|
if (updateActiveConnectors) { |
|
|
|
|
|
|
|
if (isNewConnector || shouldAddToConnectorsList) { |
|
|
|
tasks.push(this.attributeService.saveEntityAttributes(this.device, scope, [{ |
|
|
|
key: scope === AttributeScope.SHARED_SCOPE ? 'active_connectors' : 'inactive_connectors', |
|
|
|
value: scope === AttributeScope.SHARED_SCOPE ? this.activeConnectors : this.inactiveConnectors |
|
|
|
}])); |
|
|
|
} |
|
|
|
|
|
|
|
tasks.push(this.attributeService.saveEntityAttributes(this.device, scope, attributesToSave)); |
|
|
|
|
|
|
|
if (attributesToDelete.length) { |
|
|
|
tasks.push(this.attributeService.deleteEntityAttributes(this.device, scope, attributesToDelete)); |
|
|
|
} |
|
|
|
forkJoin(tasks).subscribe(_ => { |
|
|
|
this.showToast(!this.initialConnector |
|
|
|
? this.translate.instant('gateway.connector-created') |
|
|
|
: this.translate.instant('gateway.connector-updated') |
|
|
|
); |
|
|
|
this.initialConnector = value; |
|
|
|
this.updateData(true); |
|
|
|
this.connectorForm.markAsPristine(); |
|
|
|
}); |
|
|
|
|
|
|
|
return tasks; |
|
|
|
} |
|
|
|
|
|
|
|
private removeConnectorFromList(connectorName: string, isActive: boolean): void { |
|
|
|
const list = isActive? this.activeConnectors : this.inactiveConnectors; |
|
|
|
const index = list.indexOf(connectorName); |
|
|
|
if (index !== -1) { |
|
|
|
list.splice(index, 1); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private getConnectorData(): GatewayConnector { |
|
|
|
const value = { ...this.connectorForm.value }; |
|
|
|
value.configuration = `${camelCase(value.name)}.json`; |
|
|
|
delete value.basicConfig; |
|
|
|
|
|
|
|
if (value.type !== ConnectorType.GRPC) { |
|
|
|
delete value.key; |
|
|
|
} |
|
|
|
if (value.type !== ConnectorType.CUSTOM) { |
|
|
|
delete value.class; |
|
|
|
} |
|
|
|
|
|
|
|
value.ts = Date.now(); |
|
|
|
|
|
|
|
return value; |
|
|
|
} |
|
|
|
|
|
|
|
private updateData(reload: boolean = false): void { |
|
|
|
@ -349,11 +262,11 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie |
|
|
|
|
|
|
|
isConnectorSynced(attribute: AttributeData) { |
|
|
|
const connectorData = attribute.value; |
|
|
|
if (!connectorData.ts) { |
|
|
|
if (!connectorData.ts || attribute.skipSync) { |
|
|
|
return false; |
|
|
|
} |
|
|
|
const clientIndex = this.activeData.findIndex(data => { |
|
|
|
const sharedData = data.value; |
|
|
|
const sharedData = typeof data.value === 'string' ? JSON.parse(data.value) : data.value; |
|
|
|
return sharedData.name === connectorData.name; |
|
|
|
}); |
|
|
|
if (clientIndex === -1) { |
|
|
|
@ -384,12 +297,31 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie |
|
|
|
} |
|
|
|
|
|
|
|
private combineData(): void { |
|
|
|
this.dataSource.data = [...this.activeData, ...this.inactiveData, ...this.sharedAttributeData].filter((item, index, self) => |
|
|
|
index === self.findIndex((t) => t.key === item.key) |
|
|
|
).map(attribute => { |
|
|
|
attribute.value = typeof attribute.value === 'string' ? JSON.parse(attribute.value) : attribute.value; |
|
|
|
return attribute; |
|
|
|
}); |
|
|
|
const combinedData = [ |
|
|
|
...this.activeData, |
|
|
|
...this.inactiveData, |
|
|
|
...this.sharedAttributeData |
|
|
|
]; |
|
|
|
|
|
|
|
const latestData = combinedData.reduce((acc, attribute) => { |
|
|
|
const existingItemIndex = acc.findIndex(item => item.key === attribute.key); |
|
|
|
|
|
|
|
if (existingItemIndex === -1) { |
|
|
|
acc.push(attribute); |
|
|
|
} else if ( |
|
|
|
attribute.lastUpdateTs > acc[existingItemIndex].lastUpdateTs && |
|
|
|
!this.isConnectorSynced(acc[existingItemIndex]) |
|
|
|
) { |
|
|
|
acc[existingItemIndex] = { ...attribute, skipSync: true }; |
|
|
|
} |
|
|
|
|
|
|
|
return acc; |
|
|
|
}, []); |
|
|
|
|
|
|
|
this.dataSource.data = latestData.map(attribute => ({ |
|
|
|
...attribute, |
|
|
|
value: typeof attribute.value === 'string' ? JSON.parse(attribute.value) : attribute.value |
|
|
|
})); |
|
|
|
} |
|
|
|
|
|
|
|
private clearOutConnectorForm(): void { |
|
|
|
@ -447,7 +379,7 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie |
|
|
|
|
|
|
|
returnType(attribute: AttributeData): string { |
|
|
|
const value = attribute.value; |
|
|
|
return this.gatewayConnectorDefaultTypes.get(value.type); |
|
|
|
return this.GatewayConnectorTypesTranslatesMap.get(value.type); |
|
|
|
} |
|
|
|
|
|
|
|
deleteConnector(attribute: AttributeData, $event: Event): void { |
|
|
|
@ -560,26 +492,97 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie |
|
|
|
} |
|
|
|
|
|
|
|
uniqNameRequired(): ValidatorFn { |
|
|
|
return (c: UntypedFormControl) => { |
|
|
|
const newName = c.value.trim().toLowerCase(); |
|
|
|
const found = this.dataSource.data.find((connectorAttr) => { |
|
|
|
const connectorData = connectorAttr.value; |
|
|
|
return connectorData.name.toLowerCase() === newName; |
|
|
|
}); |
|
|
|
if (found) { |
|
|
|
if (this.initialConnector && this.initialConnector.name.toLowerCase() === newName) { |
|
|
|
return null; |
|
|
|
} |
|
|
|
return { |
|
|
|
duplicateName: { |
|
|
|
valid: false |
|
|
|
} |
|
|
|
}; |
|
|
|
return (control: UntypedFormControl) => { |
|
|
|
const newName = control.value?.trim().toLowerCase(); |
|
|
|
const isDuplicate = this.dataSource.data.some(connectorAttr => connectorAttr.value.name.toLowerCase() === newName); |
|
|
|
const isSameAsInitial = this.initialConnector?.name.toLowerCase() === newName; |
|
|
|
|
|
|
|
if (isDuplicate && !isSameAsInitial) { |
|
|
|
return { duplicateName: { valid: false } }; |
|
|
|
} |
|
|
|
|
|
|
|
return null; |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
private initDataSources(): void { |
|
|
|
const sortOrder: SortOrder = {property: 'key', direction: Direction.ASC}; |
|
|
|
this.pageLink = new PageLink(1000, 0, null, sortOrder); |
|
|
|
this.attributeDataSource = new AttributeDatasource(this.attributeService, this.telemetryWsService, this.zone, this.translate); |
|
|
|
this.inactiveConnectorsDataSource = new AttributeDatasource(this.attributeService, this.telemetryWsService, this.zone, this.translate); |
|
|
|
this.serverDataSource = new AttributeDatasource(this.attributeService, this.telemetryWsService, this.zone, this.translate); |
|
|
|
this.dataSource = new MatTableDataSource<AttributeData>([]); |
|
|
|
} |
|
|
|
|
|
|
|
private initConnectorForm(): void { |
|
|
|
this.connectorForm = this.fb.group({ |
|
|
|
mode: [ConnectorConfigurationModes.BASIC], |
|
|
|
name: ['', [Validators.required, this.uniqNameRequired(), Validators.pattern(noLeadTrailSpacesRegex)]], |
|
|
|
type: ['', [Validators.required]], |
|
|
|
enableRemoteLogging: [false], |
|
|
|
logLevel: ['', [Validators.required]], |
|
|
|
sendDataOnlyOnChange: [false], |
|
|
|
key: ['auto'], |
|
|
|
class: [''], |
|
|
|
configuration: [''], |
|
|
|
configurationJson: [{}, [Validators.required]], |
|
|
|
basicConfig: [{}] |
|
|
|
}); |
|
|
|
this.connectorForm.disable(); |
|
|
|
} |
|
|
|
|
|
|
|
private observeName(): void { |
|
|
|
this.connectorForm.get('name').valueChanges |
|
|
|
.pipe( |
|
|
|
filter(() => this.connectorForm.get('type').value === ConnectorType.MQTT), |
|
|
|
takeUntil(this.destroy$) |
|
|
|
) |
|
|
|
.subscribe(name => this.connectorForm.get('basicConfig').get('broker.name')?.setValue(name)); |
|
|
|
} |
|
|
|
|
|
|
|
private getSortingDataAccessor(): (data: AttributeData, sortHeaderId: string) => string | number { |
|
|
|
return (data: AttributeData, sortHeaderId: string) => { |
|
|
|
switch (sortHeaderId) { |
|
|
|
case 'syncStatus': |
|
|
|
return this.isConnectorSynced(data) ? 1 : 0; |
|
|
|
|
|
|
|
case 'enabled': |
|
|
|
return this.activeConnectors.includes(data.key) ? 1 : 0; |
|
|
|
|
|
|
|
case 'errors': |
|
|
|
const errors = this.getErrorsCount(data); |
|
|
|
if (typeof errors === 'string') { |
|
|
|
return this.sort.direction.toUpperCase() === Direction.DESC ? -1 : Infinity; |
|
|
|
} |
|
|
|
return errors; |
|
|
|
|
|
|
|
default: |
|
|
|
return data[sortHeaderId] || data.value[sortHeaderId]; |
|
|
|
} |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
private loadConnectors(): void { |
|
|
|
if (!this.device || this.device.id === NULL_UUID) { |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
forkJoin([ |
|
|
|
this.attributeService.getEntityAttributes(this.device, AttributeScope.SHARED_SCOPE, ['active_connectors']), |
|
|
|
this.attributeService.getEntityAttributes(this.device, AttributeScope.SERVER_SCOPE, ['inactive_connectors']) |
|
|
|
]).pipe(takeUntil(this.destroy$)).subscribe(attributes => { |
|
|
|
this.activeConnectors = this.parseConnectors(attributes[0]); |
|
|
|
this.inactiveConnectors = this.parseConnectors(attributes[1]); |
|
|
|
|
|
|
|
this.updateData(true); |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
private parseConnectors(attribute: AttributeData[]): string[] { |
|
|
|
const connectors = attribute?.[0]?.value || []; |
|
|
|
return isString(connectors) ? JSON.parse(connectors) : connectors; |
|
|
|
} |
|
|
|
|
|
|
|
private observeModeChange(): void { |
|
|
|
this.connectorForm.get('mode').valueChanges |
|
|
|
.pipe(takeUntil(this.destroy$)) |
|
|
|
@ -636,7 +639,8 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie |
|
|
|
value: this.inactiveConnectors |
|
|
|
}]), |
|
|
|
this.attributeService.deleteEntityAttributes(this.device, scopeOld, [attribute]), |
|
|
|
this.attributeService.saveEntityAttributes(this.device, scopeNew, [attribute])]; |
|
|
|
this.attributeService.saveEntityAttributes(this.device, scopeNew, [attribute]) |
|
|
|
]; |
|
|
|
} |
|
|
|
|
|
|
|
private onDataUpdateError(e: any): void { |
|
|
|
@ -725,20 +729,17 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie |
|
|
|
if (this.connectorForm.disabled) { |
|
|
|
this.connectorForm.enable(); |
|
|
|
} |
|
|
|
if (!connector.configuration) { |
|
|
|
connector.configuration = ''; |
|
|
|
} |
|
|
|
if (!connector.key) { |
|
|
|
connector.key = 'auto'; |
|
|
|
} |
|
|
|
if (!connector.configurationJson) { |
|
|
|
connector.configurationJson = {} as ConnectorBaseConfig; |
|
|
|
} |
|
|
|
connector.basicConfig = connector.configurationJson; |
|
|
|
|
|
|
|
this.initialConnector = connector; |
|
|
|
const connectorState = { |
|
|
|
configuration: '', |
|
|
|
key: 'auto', |
|
|
|
configurationJson: {} as ConnectorBaseConfig, |
|
|
|
...connector, |
|
|
|
}; |
|
|
|
|
|
|
|
this.updateConnector(connector); |
|
|
|
connectorState.basicConfig = connectorState.configurationJson; |
|
|
|
this.initialConnector = connectorState; |
|
|
|
this.updateConnector(connectorState); |
|
|
|
} |
|
|
|
|
|
|
|
private updateConnector(connector: GatewayConnector): void { |
|
|
|
|