Browse Source

connectors templates

pull/10011/head
Maksym Dudnik 3 years ago
parent
commit
6ee6ccaa36
  1. 54
      ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc-connector-template-dialog.html
  2. 62
      ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc-connector-template-dialog.ts
  3. 19
      ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc-connector-templates.component.html
  4. 5
      ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc-connector-templates.component.scss
  5. 69
      ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc-connector-templates.component.ts
  6. 136
      ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc-connector.component.html
  7. 181
      ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc-connector.component.ts
  8. 7
      ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc.component.html
  9. 141
      ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc.component.ts
  10. 15
      ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts
  11. 5
      ui-ngx/src/app/modules/home/components/widget/widget-components.module.ts
  12. 69
      ui-ngx/src/assets/locale/locale.constant-en_US.json

54
ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc-connector-template-dialog.html

@ -0,0 +1,54 @@
<!--
Copyright © 2016-2023 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.
-->
<mat-toolbar color="primary">
<h2 translate>gateway.rpc.save-template</h2>
<span fxFlex></span>
<button mat-icon-button
(click)="close()"
type="button">
<mat-icon class="material-icons">close</mat-icon>
</button>
</mat-toolbar>
<div mat-dialog-content style="width: 600px" class="mat-content" fxLayout="column">
<mat-form-field class="mat-block tb-value-type" style="flex-grow: 0">
<mat-label translate>gateway.rpc.template-name</mat-label>
<input matInput [formControl]="templateNameCtrl" required/>
<mat-error
*ngIf="templateNameCtrl.hasError('required')">
{{ 'gateway.rpc.template-name-required' | translate }}
</mat-error>
</mat-form-field>
<div class="mat-mdc-form-field-error"
style="margin-top: -15px; padding-left: 10px; font-size: 14px;"
*ngIf="validateDuplicateName(templateNameCtrl)">
{{ 'gateway.rpc.template-name-duplicate' | translate }}
</div>
</div>
<div mat-dialog-actions fxLayoutAlign="end center">
<button mat-button
type="button"
(click)="close()">
{{ 'action.cancel' | translate }}
</button>
<button mat-raised-button color="primary"
type="button"
[disabled]="!templateNameCtrl.valid"
(click)="save()">
{{ 'action.save' | translate }}
</button>
</div>

62
ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc-connector-template-dialog.ts

@ -0,0 +1,62 @@
///
/// Copyright © 2016-2023 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, Inject } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { DialogComponent } from '@shared/components/dialog.component';
import { Router } from '@angular/router';
import { FormBuilder, FormControl, UntypedFormControl, Validators } from '@angular/forms';
import { RPCTemplate, SaveRPCTemplateData } from '@home/components/widget/lib/gateway/gateway-widget.models';
@Component({
selector: 'gateway-service-rpc-connector-template-dialog',
templateUrl: './gateway-service-rpc-connector-template-dialog.html'
})
export class GatewayServiceRPCConnectorTemplateDialogComponent extends DialogComponent<GatewayServiceRPCConnectorTemplateDialogComponent, boolean> {
config: {
[key: string]: any;
};
templates: Array<RPCTemplate>;
templateNameCtrl: FormControl;
constructor(protected store: Store<AppState>,
protected router: Router,
@Inject(MAT_DIALOG_DATA) public data: SaveRPCTemplateData,
public dialogRef: MatDialogRef<GatewayServiceRPCConnectorTemplateDialogComponent, boolean>,
public fb: FormBuilder) {
super(store, router, dialogRef);
this.config = this.data.config;
this.templates = this.data.templates;
this.templateNameCtrl = this.fb.control('', [Validators.required])
}
validateDuplicateName(c: UntypedFormControl) {
const name = c.value.trim();
return !!this.templates.find((template) => template.name === name);
};
close(): void {
this.dialogRef.close();
}
save(): void {
this.dialogRef.close(this.templateNameCtrl.value);
}
}

19
ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc-connector-templates.component.html

@ -22,13 +22,10 @@
{{template.name}}
</mat-panel-title>
<mat-panel-description>
<button mat-icon-button matTooltip="Delete" (click)="deleteTemplate($event)">
<button mat-icon-button matTooltip="Delete" (click)="deleteTemplate($event, template)">
<mat-icon class="material-icons">delete</mat-icon>
</button>
<button mat-icon-button matTooltip="Copy" (click)="copyTemplate($event)">
<mat-icon class="material-icons">content_copy</mat-icon>
</button>
<button mat-icon-button matTooltip="Use" (click)="useTemplate($event)">
<button mat-icon-button matTooltip="Use" (click)="applyTemplate($event, template)">
<mat-icon class="material-icons">play_arrow</mat-icon>
</button>
</mat-panel-description>
@ -37,13 +34,15 @@
<ng-container
*ngFor="let config of template.config | keyvalue : originalOrder"
[ngTemplateOutlet]="RPCTemplateRef"
[ngTemplateOutletContext]="{ $implicit: config, padding: false }">
[ngTemplateOutletContext]="{ $implicit: config, innerValue: false }">
</ng-container>
<ng-template #RPCTemplateRef let-config let-padding='padding'>
<ng-template #RPCTemplateRef let-config let-innerValue='innerValue'>
<div [fxLayout]="isObject(config.value) ? 'column': 'row'"
[fxLayoutAlign]="!isObject(config.value) ? 'space-between center' : ''"
[ngStyle]="{'padding-left': padding ? '16px': '0'}">
<div class="template-key">{{config.key}}</div>
[ngStyle]="{'padding-left': innerValue ? '16px': '0'}">
<div class="template-key">
{{!innerValue ? ('gateway.rpc.' + config.key | translate) : config.key}}
</div>
<div *ngIf="!isObject(config.value) else RPCObjectRow"
[ngClass]="{'boolean-true': config.value === true,
'boolean-false': config.value === false }">
@ -52,7 +51,7 @@
<ng-container
*ngFor="let subConfig of config.value | keyvalue : originalOrder"
[ngTemplateOutlet]="RPCTemplateRef"
[ngTemplateOutletContext]="{ $implicit: subConfig, padding: true }">
[ngTemplateOutletContext]="{ $implicit: subConfig, innerValue: true }">
</ng-container>
</ng-template>
</div>

5
ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc-connector-templates.component.scss

@ -50,6 +50,11 @@
background-color: rgba(25, 128, 56, 0.08);
}
mat-expansion-panel {
margin-top: 10px;
overflow: visible;
}
.mat-expansion-panel-header-description {
flex-direction: row-reverse;
align-items: center;

69
ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc-connector-templates.component.ts

@ -15,9 +15,16 @@
///
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { ConnectorType, RPCTemplate } from '@home/components/widget/lib/gateway/gateway-widget.models';
import { TranslateService } from '@ngx-translate/core';
import {
ConnectorType,
RPCTemplate
} from '@home/components/widget/lib/gateway/gateway-widget.models';
import { KeyValue } from '@angular/common';
import { EntityType } from '@shared/models/entity-type.models';
import { AttributeScope } from '@shared/models/telemetry/telemetry.models';
import { AttributeService } from '@core/http/attribute.service';
import { WidgetContext } from '@home/models/widget-component.models';
import { MatDialog } from '@angular/material/dialog';
@Component({
selector: 'tb-gateway-service-rpc-connector-templates',
@ -29,52 +36,52 @@ export class GatewayServiceRPCConnectorTemplatesComponent implements OnInit {
@Input()
connectorType: ConnectorType;
@Input()
ctx: WidgetContext;
@Output()
saveTemplate: EventEmitter<any> = new EventEmitter();
rpcTemplates: Array<RPCTemplate> = [];
constructor(private translate: TranslateService) {
this.rpcTemplates.push(
{
name: 'Test Template',
config: {
fieldString: 'string',
fieldNumber: 666,
fieldBool: true,
fieldArray: [111, 222, 333, "String", "444"],
fieldObj: {
subKey1: 'dasd',
subKey2: 666,
}
}
}
)
}
@Output()
useTemplate: EventEmitter<any> = new EventEmitter();
ngOnInit() {
@Input()
rpcTemplates: Array<RPCTemplate>;
constructor(private attributeService: AttributeService) {
}
public useTemplate($event: Event): void {
$event.stopPropagation();
console.log("useTemplate")
ngOnInit() {
}
public copyTemplate($event: Event): void {
public applyTemplate($event: Event, template: RPCTemplate): void {
$event.stopPropagation();
console.log("copyTemplate")
this.useTemplate.emit(template);
}
public deleteTemplate($event: Event): void {
public deleteTemplate($event: Event, template: RPCTemplate): void {
$event.stopPropagation();
console.log("deleteTemplate")
const index = this.rpcTemplates.findIndex(data => {
return data.name == template.name;
})
this.rpcTemplates.splice(index, 1);
const key = `${this.connectorType}_template`;
this.attributeService.saveEntityAttributes(
{
id: this.ctx.defaultSubscription.targetDeviceId,
entityType: EntityType.DEVICE
}
, AttributeScope.SERVER_SCOPE, [{
key,
value: this.rpcTemplates
}]).subscribe(() => {
})
}
public originalOrder = (a: KeyValue<string, any>, b: KeyValue<string, any>): number => {
public originalOrder = (a, b): number => {
return 0;
}
public isObject(value: any) {
return value !== null && typeof value === 'object' && !Array.isArray(value);
}

136
ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc-connector.component.html

@ -16,7 +16,8 @@
-->
<div fxLayout="column" class="command-form" [formGroup]="commandForm">
<div class="mat-subtitle-1 title">{{ 'gateway.rpc.title' | translate: {type: gatewayConnectorDefaultTypesTranslates.get(connectorType)} }}</div>
<div
class="mat-subtitle-1 title">{{ 'gateway.rpc.title' | translate: {type: gatewayConnectorDefaultTypesTranslates.get(connectorType)} }}</div>
<ng-template [ngIf]="connectorType">
<ng-container [ngSwitch]="connectorType">
<ng-template [ngSwitchCase]="ConnectorType.MQTT">
@ -26,27 +27,26 @@
placeholder="echo"/>
</mat-form-field>
<mat-form-field>
<mat-label>{{ 'gateway.rpc.request-topic-expression' | translate }}</mat-label>
<mat-label>{{ 'gateway.rpc.requestTopicExpression' | translate }}</mat-label>
<input matInput formControlName="requestTopicExpression"
placeholder="sensor/${deviceName}/request/${methodName}/${requestId}"/>
</mat-form-field>
<mat-form-field>
<mat-label>{{ 'gateway.rpc.response-topic-expression' | translate }}</mat-label>
<mat-label>{{ 'gateway.rpc.responseTopicExpression' | translate }}</mat-label>
<input matInput formControlName="responseTopicExpression"
placeholder="sensor/${deviceName}/response/${methodName}/${requestId}"/>
</mat-form-field>
<mat-form-field>
<mat-label>{{ 'gateway.rpc.response-timeout' | translate }}</mat-label>
<mat-label>{{ 'gateway.rpc.responseTimeout' | translate }}</mat-label>
<input matInput formControlName="responseTimeout" type="number"
placeholder="10000" min="10" step="1"/>
</mat-form-field>
<mat-form-field>
<mat-label>{{ 'gateway.rpc.value-expression' | translate }}</mat-label>
<mat-label>{{ 'gateway.rpc.valueExpression' | translate }}</mat-label>
<input matInput formControlName="valueExpression"
placeholder="${params}"/>
</mat-form-field>
</ng-template>
<ng-template [ngSwitchCase]="ConnectorType.MODBUS">
<mat-form-field>
<mat-label>{{ 'gateway.rpc.tag' | translate }}</mat-label>
@ -62,7 +62,7 @@
</mat-select>
</mat-form-field>
<mat-form-field fxFlex="50" class="mat-block">
<mat-label>{{ 'gateway.rpc.function-code' | translate }}</mat-label>
<mat-label>{{ 'gateway.rpc.functionCode' | translate }}</mat-label>
<mat-select formControlName="functionCode">
<mat-option *ngFor="let code of codesArray" [value]="code">
{{ code }}
@ -77,20 +77,19 @@
placeholder="1" step="1"/>
</mat-form-field>
<mat-form-field fxFlex="50">
<mat-label>{{ 'gateway.rpc.objects-count' | translate }}</mat-label>
<mat-label>{{ 'gateway.rpc.objectsCount' | translate }}</mat-label>
<input matInput formControlName="objectsCount" type="number" min="0"
placeholder="31" step="1"/>
</mat-form-field>
</div>
</ng-template>
<ng-template [ngSwitchCase]="ConnectorType.BACNET">
<mat-form-field>
<mat-label>{{ 'gateway.rpc.method-rpc' | translate }}</mat-label>
<mat-label>{{ 'gateway.rpc.methodRPC' | translate }}</mat-label>
<input matInput formControlName="method" placeholder="set_state"/>
</mat-form-field>
<mat-form-field class="mat-block">
<mat-label>{{ 'gateway.rpc.request-type' | translate }}</mat-label>
<mat-label>{{ 'gateway.rpc.requestType' | translate }}</mat-label>
<mat-select formControlName="requestType">
<mat-option *ngFor="let type of bACnetRequestTypes" [value]="type">
{{bACnetRequestTypesTranslates.get(type) | translate}}
@ -98,13 +97,13 @@
</mat-select>
</mat-form-field>
<mat-form-field>
<mat-label>{{ 'gateway.rpc.request-timeout' | translate }}</mat-label>
<mat-label>{{ 'gateway.rpc.requestTimeout' | translate }}</mat-label>
<input matInput formControlName="requestTimeout" type="number"
min="10" step="1" placeholder="1000"/>
</mat-form-field>
<div fxFlex fxLayout="row" fxLayoutGap="10px">
<mat-form-field fxFlex="50" class="mat-block">
<mat-label>{{ 'gateway.rpc.object-type' | translate }}</mat-label>
<mat-label>{{ 'gateway.rpc.objectType' | translate }}</mat-label>
<mat-select formControlName="objectType">
<mat-option *ngFor="let type of bACnetObjectTypes" [value]="type">
{{bACnetObjectTypesTranslates.get(type) | translate}}
@ -118,22 +117,21 @@
</mat-form-field>
</div>
<mat-form-field class="mat-block">
<mat-label>{{ 'gateway.rpc.property-id' | translate }}</mat-label>
<mat-label>{{ 'gateway.rpc.propertyId' | translate }}</mat-label>
<input matInput formControlName="propertyId" placeholder="presentValue"/>
</mat-form-field>
</ng-template>
<ng-template [ngSwitchCase]="ConnectorType.BLE">
<mat-form-field>
<mat-label>{{ 'gateway.rpc.method-rpc' | translate }}</mat-label>
<mat-label>{{ 'gateway.rpc.methodRPC' | translate }}</mat-label>
<input matInput formControlName="methodRPC" placeholder="rpcMethod1"/>
</mat-form-field>
<mat-form-field>
<mat-label>{{ 'gateway.rpc.characteristic-uuid' | translate }}</mat-label>
<mat-label>{{ 'gateway.rpc.characteristicUUID' | translate }}</mat-label>
<input matInput formControlName="characteristicUUID" placeholder="00002A00-0000-1000-8000-00805F9B34FB"/>
</mat-form-field>
<mat-form-field class="mat-block">
<mat-label>{{ 'gateway.rpc.method-processing' | translate }}</mat-label>
<mat-label>{{ 'gateway.rpc.methodProcessing' | translate }}</mat-label>
<mat-select formControlName="methodProcessing">
<mat-option *ngFor="let type of bLEMethods" [value]="type">
{{bLEMethodsTranslates.get(type) | translate}}
@ -141,35 +139,34 @@
</mat-select>
</mat-form-field>
<mat-slide-toggle class="mat-slide" formControlName="withResponse">
{{ 'gateway.rpc.with-response' | translate }}
{{ 'gateway.rpc.withResponse' | translate }}
</mat-slide-toggle>
</ng-template>
<ng-template [ngSwitchCase]="ConnectorType.CAN">
<mat-form-field>
<mat-label>{{ 'gateway.rpc.method-rpc' | translate }}</mat-label>
<mat-label>{{ 'gateway.rpc.methodRPC' | translate }}</mat-label>
<input matInput formControlName="method" placeholder="sendSameData"/>
</mat-form-field>
<mat-form-field>
<mat-label>{{ 'gateway.rpc.node-id' | translate }}</mat-label>
<mat-label>{{ 'gateway.rpc.nodeID' | translate }}</mat-label>
<input matInput formControlName="nodeID" type="number" placeholder="4" min="0" step="1"/>
</mat-form-field>
<mat-slide-toggle class="mat-slide margin" formControlName="isExtendedID">
{{ 'gateway.rpc.is-extended-id' | translate }}
{{ 'gateway.rpc.isExtendedID' | translate }}
</mat-slide-toggle>
<mat-slide-toggle class="mat-slide margin" formControlName="isFD">
{{ 'gateway.rpc.is-fd' | translate }}
{{ 'gateway.rpc.isFD' | translate }}
</mat-slide-toggle>
<mat-slide-toggle class="mat-slide margin" formControlName="bitrateSwitch">
{{ 'gateway.rpc.bitrate-switch' | translate }}
{{ 'gateway.rpc.bitrateSwitch' | translate }}
</mat-slide-toggle>
<div fxFlex fxLayout="row" fxLayoutGap="10px">
<mat-form-field fxFlex="50">
<mat-label>{{ 'gateway.rpc.data-length' | translate }}</mat-label>
<mat-label>{{ 'gateway.rpc.dataLength' | translate }}</mat-label>
<input matInput formControlName="dataLength" type="number" placeholder="2" min="1" step="1"/>
</mat-form-field>
<mat-form-field class="mat-block" fxFlex="50">
<mat-label>{{ 'gateway.rpc.data-byte-order' | translate }}</mat-label>
<mat-label>{{ 'gateway.rpc.dataByteorder' | translate }}</mat-label>
<mat-select formControlName="dataByteorder">
<mat-option *ngFor="let order of cANByteOrders" [value]="order">
{{ order | translate }}
@ -179,59 +176,55 @@
</div>
<div fxFlex fxLayout="row" fxLayoutGap="10px">
<mat-form-field fxFlex="50">
<mat-label>{{ 'gateway.rpc.data-before' | translate }}</mat-label>
<mat-label>{{ 'gateway.rpc.dataBefore' | translate }}</mat-label>
<input matInput formControlName="dataBefore" placeholder="00AA"/>
</mat-form-field>
<mat-form-field fxFlex="50">
<mat-label>{{ 'gateway.rpc.data-after' | translate }}</mat-label>
<mat-label>{{ 'gateway.rpc.dataAfter' | translate }}</mat-label>
<input matInput formControlName="dataAfter" placeholder="0102"/>
</mat-form-field>
</div>
<mat-form-field>
<mat-label>{{ 'gateway.rpc.data-in-hex' | translate }}</mat-label>
<mat-label>{{ 'gateway.rpc.dataInHEX' | translate }}</mat-label>
<input matInput formControlName="dataInHEX"
placeholder="aa bb cc dd ee ff aa bb aa bb cc d ee ff"/>
</mat-form-field>
<mat-form-field>
<mat-label>{{ 'gateway.rpc.data-expression' | translate }}</mat-label>
<mat-label>{{ 'gateway.rpc.dataExpression' | translate }}</mat-label>
<input matInput formControlName="dataExpression"
placeholder="userSpeed if maxAllowedSpeed > userSpeed else maxAllowedSpeed"/>
</mat-form-field>
</ng-template>
<ng-template [ngSwitchCase]="ConnectorType.FTP">
<mat-form-field>
<mat-label>{{ 'gateway.rpc.method-filter' | translate }}</mat-label>
<mat-label>{{ 'gateway.rpc.methodFilter' | translate }}</mat-label>
<input matInput formControlName="methodFilter" placeholder="read"/>
</mat-form-field>
<mat-form-field>
<mat-label>{{ 'gateway.rpc.value-expression' | translate }}</mat-label>
<mat-label>{{ 'gateway.rpc.valueExpression' | translate }}</mat-label>
<input matInput formControlName="valueExpression" placeholder="${params}"/>
</mat-form-field>
</ng-template>
<ng-template [ngSwitchCase]="ConnectorType.OCPP">
<mat-form-field>
<mat-label>{{ 'gateway.rpc.method-rpc' | translate }}</mat-label>
<mat-label>{{ 'gateway.rpc.methodRPC' | translate }}</mat-label>
<input matInput formControlName="methodRPC" placeholder="rpc1"/>
</mat-form-field>
<mat-form-field>
<mat-label>{{ 'gateway.rpc.value-expression' | translate }}</mat-label>
<mat-label>{{ 'gateway.rpc.valueExpression' | translate }}</mat-label>
<input matInput formControlName="valueExpression" placeholder="${params}"/>
</mat-form-field>
<mat-slide-toggle class="mat-slide margin" formControlName="withResponse">
{{ 'gateway.rpc.with-response' | translate }}
{{ 'gateway.rpc.withResponse' | translate }}
</mat-slide-toggle>
</ng-template>
<ng-template [ngSwitchCase]="ConnectorType.SOCKET">
<mat-form-field>
<mat-label>{{ 'gateway.rpc.method-rpc' | translate }}</mat-label>
<mat-label>{{ 'gateway.rpc.methodRPC' | translate }}</mat-label>
<input matInput formControlName="methodRPC" placeholder="rpcMethod1"/>
</mat-form-field>
<mat-form-field class="mat-block">
<mat-label>{{ 'gateway.rpc.method-processing' | translate }}</mat-label>
<mat-label>{{ 'gateway.rpc.methodProcessing' | translate }}</mat-label>
<mat-select formControlName="methodProcessing">
<mat-option *ngFor="let method of socketMethodProcessings" [value]="method">
{{ SocketMethodProcessingsTranslates.get(method) | translate }}
@ -247,27 +240,25 @@
</mat-select>
</mat-form-field>
<mat-slide-toggle class="mat-slide margin" formControlName="withResponse">
{{ 'gateway.rpc.with-response' | translate }}
{{ 'gateway.rpc.withResponse' | translate }}
</mat-slide-toggle>
</ng-template>
<ng-template [ngSwitchCase]="ConnectorType.XMPP">
<mat-form-field>
<mat-label>{{ 'gateway.rpc.method-rpc' | translate }}</mat-label>
<mat-label>{{ 'gateway.rpc.methodRPC' | translate }}</mat-label>
<input matInput formControlName="methodRPC" placeholder="rpc1"/>
</mat-form-field>
<mat-form-field>
<mat-label>{{ 'gateway.rpc.value-expression' | translate }}</mat-label>
<mat-label>{{ 'gateway.rpc.valueExpression' | translate }}</mat-label>
<input matInput formControlName="valueExpression" placeholder="${params}"/>
</mat-form-field>
<mat-slide-toggle class="mat-slide margin" formControlName="withResponse">
{{ 'gateway.rpc.with-response' | translate }}
{{ 'gateway.rpc.withResponse' | translate }}
</mat-slide-toggle>
</ng-template>
<ng-template [ngSwitchCase]="ConnectorType.SNMP">
<mat-form-field>
<mat-label>{{ 'gateway.rpc.request-filter' | translate }}</mat-label>
<mat-label>{{ 'gateway.rpc.requestFilter' | translate }}</mat-label>
<input matInput formControlName="requestFilter" placeholder="setData"/>
</mat-form-field>
<mat-form-field class="mat-block">
@ -298,15 +289,14 @@
</button>
</fieldset>
</ng-template>
<ng-template [ngSwitchCase]="ConnectorType.REST">
<mat-form-field>
<mat-label>{{ 'gateway.rpc.method-filter' | translate }}</mat-label>
<mat-label>{{ 'gateway.rpc.methodFilter' | translate }}</mat-label>
<input matInput formControlName="methodFilter" placeholder="post_attributes"/>
</mat-form-field>
<div fxFlex fxLayout="row" fxLayoutGap="10px">
<mat-form-field class="mat-block" fxFlex="33">
<mat-label>{{ 'gateway.rpc.http-method' | translate }}</mat-label>
<mat-label>{{ 'gateway.rpc.HTTPMethod' | translate }}</mat-label>
<mat-select formControlName="HTTPMethod">
<mat-option *ngFor="let method of hTTPMethods" [value]="method">
{{ method }}
@ -314,14 +304,14 @@
</mat-select>
</mat-form-field>
<mat-form-field fxFlex>
<mat-label>{{ 'gateway.rpc.request-url' | translate }}</mat-label>
<mat-label>{{ 'gateway.rpc.requestUrlExpression' | translate }}</mat-label>
<input matInput formControlName="requestUrlExpression"
placeholder="http://127.0.0.1:5000/my_devices"/>
</mat-form-field>
</div>
<div fxFlex fxLayout="row" fxLayoutGap="10px">
<mat-form-field fxFlex="33">
<mat-label>{{ 'gateway.rpc.response-timeout' | translate }}</mat-label>
<mat-label>{{ 'gateway.rpc.responseTimeout' | translate }}</mat-label>
<input matInput formControlName="responseTimeout" type="number"
step="1" min="10" placeholder="10"/>
</mat-form-field>
@ -337,11 +327,11 @@
</mat-form-field>
</div>
<mat-form-field>
<mat-label>{{ 'gateway.rpc.value-expression' | translate }}</mat-label>
<mat-label>{{ 'gateway.rpc.valueExpression' | translate }}</mat-label>
<input matInput formControlName="valueExpression" placeholder="${params}"/>
</mat-form-field>
<fieldset class="fields border" fxLayout="column" fxLayoutGap="10px" formArrayName="httpHeaders">
<span class="fields-label">{{ 'gateway.rpc.http-headers' | translate }}</span>
<span class="fields-label">{{ 'gateway.rpc.httpHeaders' | translate }}</span>
<div class="border" fxLayout="column" fxLayoutGap="10px" *ngIf="getFormArrayControls('httpHeaders').length">
<div fxLayout="row" fxLayoutGap="10px" fxLayoutAlign="center center">
<span fxFlex class="title">{{ 'gateway.rpc.header-name' | translate }}</span>
@ -405,15 +395,14 @@
</button>
</fieldset>
</ng-template>
<ng-template [ngSwitchCase]="ConnectorType.REQUEST">
<mat-form-field>
<mat-label>{{ 'gateway.rpc.method-filter' | translate }}</mat-label>
<mat-label>{{ 'gateway.rpc.methodFilter' | translate }}</mat-label>
<input matInput formControlName="methodFilter" placeholder="echo"/>
</mat-form-field>
<div fxFlex fxLayout="row" fxLayoutGap="10px">
<mat-form-field class="mat-block" fxFlex="33">
<mat-label>{{ 'gateway.rpc.method' | translate }}</mat-label>
<mat-label>{{ 'gateway.rpc.httpMethod' | translate }}</mat-label>
<mat-select formControlName="httpMethod">
<mat-option *ngFor="let method of hTTPMethods" [value]="method">
{{ method }}
@ -421,13 +410,13 @@
</mat-select>
</mat-form-field>
<mat-form-field fxFlex>
<mat-label>{{ 'gateway.rpc.request-url' | translate }}</mat-label>
<mat-label>{{ 'gateway.rpc.requestUrlExpression' | translate }}</mat-label>
<input matInput formControlName="requestUrlExpression" placeholder="http://127.0.0.1:5000/my_devices"/>
</mat-form-field>
</div>
<div fxFlex fxLayout="row" fxLayoutGap="10px">
<mat-form-field fxFlex="33">
<mat-label>{{ 'gateway.rpc.response-timeout' | translate }}</mat-label>
<mat-label>{{ 'gateway.rpc.responseTimeout' | translate }}</mat-label>
<input matInput formControlName="responseTimeout" type="number"
step="1" min="10" placeholder="10"/>
</mat-form-field>
@ -443,15 +432,15 @@
</mat-form-field>
</div>
<mat-form-field>
<mat-label>{{ 'gateway.rpc.request-value-expression' | translate }}</mat-label>
<mat-label>{{ 'gateway.rpc.requestValueExpression' | translate }}</mat-label>
<input matInput formControlName="requestValueExpression" placeholder="${params}"/>
</mat-form-field>
<mat-form-field>
<mat-label>{{ 'gateway.rpc.response-value-expression' | translate }}</mat-label>
<mat-label>{{ 'gateway.rpc.responseValueExpression' | translate }}</mat-label>
<input matInput formControlName="responseValueExpression" placeholder="${temp}"/>
</mat-form-field>
<fieldset class="fields border" fxLayout="column" fxLayoutGap="10px" formArrayName="httpHeaders">
<span class="fields-label">{{ 'gateway.rpc.http-headers' | translate }}</span>
<span class="fields-label">{{ 'gateway.rpc.httpHeaders' | translate }}</span>
<div class="border" fxLayout="column" fxLayoutGap="10px" *ngIf="getFormArrayControls('httpHeaders').length">
<div fxLayout="row" fxLayoutGap="10px" fxLayoutAlign="center center">
<span fxFlex class="title">{{ 'gateway.rpc.header-name' | translate }}</span>
@ -483,7 +472,6 @@
</button>
</fieldset>
</ng-template>
<ng-template [ngSwitchCase]="ConnectorType.OPCUA_ASYNCIO">
<ng-container *ngTemplateOutlet="OPCUAForm"></ng-container>
</ng-template>
@ -513,11 +501,27 @@
</button>
</fieldset>
</ng-template>
<ng-template ngSwitchDefault>
{{'dsadas'}}
<mat-form-field>
<mat-label>{{ 'gateway.statistics.command' | translate }}</mat-label>
<input matInput formControlName="command"/>
</mat-form-field>
<mat-form-field fxFlex>
<mat-label>{{ 'widget-config.datasource-parameters' | translate }}</mat-label>
<input matInput formControlName="params" type="JSON"/>
<mat-icon class="material-icons-outlined" aria-hidden="false" aria-label="help-icon"
matIconSuffix style="cursor:pointer;"
(click)="openEditJSONDialog($event)"
matTooltip="{{ 'gateway.rpc-command-edit-params' | translate }}">edit
</mat-icon>
</mat-form-field>
</ng-template>
</ng-container>
</ng-template>
<div class="template-actions" fxFlex fxLayout="row" fxLayoutAlign="end center" fxLayoutGap="10px">
<button mat-raised-button
(click)="sendCommand.emit()"
(click)="save()"
[disabled]="commandForm.invalid">
{{ 'gateway.rpc-command-save-template' | translate }}
</button>

181
ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc-connector.component.ts

@ -14,27 +14,57 @@
/// limitations under the License.
///
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { FormArray, FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms';
import { Component, EventEmitter, forwardRef, Input, OnInit, Output } from '@angular/core';
import {
BACnetObjectTypes, BACnetObjectTypesTranslates,
BACnetRequestTypes, BACnetRequestTypesTranslates, BLEMethods, BLEMethodsTranslates,
ControlValueAccessor,
FormArray,
FormBuilder,
FormControl,
FormGroup,
NG_VALUE_ACCESSOR,
Validators
} from '@angular/forms';
import {
BACnetObjectTypes,
BACnetObjectTypesTranslates,
BACnetRequestTypes,
BACnetRequestTypesTranslates,
BLEMethods,
BLEMethodsTranslates,
CANByteOrders,
ConnectorType, GatewayConnectorDefaultTypesTranslates, HTTPMethods,
ConnectorType,
GatewayConnectorDefaultTypesTranslates,
HTTPMethods,
ModbusCommandTypes,
RPCCommand,
SNMPMethods, SNMPMethodsTranslations,
RPCTemplateConfig,
SNMPMethods,
SNMPMethodsTranslations,
SocketEncodings,
SocketMethodProcessings, SocketMethodProcessingsTranslates
SocketMethodProcessings,
SocketMethodProcessingsTranslates
} from '@home/components/widget/lib/gateway/gateway-widget.models';
import { TranslateService } from "@ngx-translate/core";
import { MatDialog } from '@angular/material/dialog';
import {
JsonObjectEditDialogComponent,
JsonObjectEditDialogData
} from '@shared/components/dialog/json-object-edit-dialog.component';
import { jsonRequired } from '@shared/components/json-object-edit.component';
import { deepClone } from '@core/utils';
@Component({
selector: 'tb-gateway-service-rpc-connector',
templateUrl: './gateway-service-rpc-connector.component.html',
styleUrls: ['./gateway-service-rpc-connector.component.scss']
styleUrls: ['./gateway-service-rpc-connector.component.scss'],
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => GatewayServiceRPCConnectorComponent),
multi: true
}
]
})
export class GatewayServiceRPCConnectorComponent implements OnInit {
export class GatewayServiceRPCConnectorComponent implements OnInit, ControlValueAccessor {
@Input()
connectorType: ConnectorType;
@ -42,6 +72,9 @@ export class GatewayServiceRPCConnectorComponent implements OnInit {
@Output()
sendCommand: EventEmitter<RPCCommand> = new EventEmitter();
@Output()
saveTemplate: EventEmitter<RPCTemplateConfig> = new EventEmitter();
commandForm: FormGroup;
codesArray: Array<number> = [1, 2, 3, 4, 5, 6, 15, 16];
@ -74,14 +107,41 @@ export class GatewayServiceRPCConnectorComponent implements OnInit {
'(\\#[-a-z\\d_]*)?$', // fragment locator
'i'
);
private propagateChange = (v: any) => {
}
constructor(private fb: FormBuilder,
private translate: TranslateService) {
private dialog: MatDialog,) {
}
ngOnInit() {
this.commandForm = this.connectorParamsFormGroupByType(this.connectorType)
this.commandForm = this.connectorParamsFormGroupByType(this.connectorType);
this.commandForm.valueChanges.subscribe(value => {
const httpHeaders = {};
const security = {};
switch (this.connectorType) {
case ConnectorType.REST:
value.httpHeaders.forEach(data => {
httpHeaders[data.headerName] = data.value;
})
value.httpHeaders = httpHeaders;
value.security.forEach(data => {
security[data.securityName] = data.value;
})
value.security = security;
break;
case ConnectorType.REQUEST:
value.httpHeaders.forEach(data => {
httpHeaders[data.headerName] = data.value;
})
value.httpHeaders = httpHeaders;
break;
}
if (this.commandForm.valid) {
this.propagateChange({...this.commandForm.value,...value});
}
})
}
connectorParamsFormGroupByType(type: ConnectorType): FormGroup {
@ -206,6 +266,13 @@ export class GatewayServiceRPCConnectorComponent implements OnInit {
method: [null, [Validators.required]],
arguments: this.fb.array([]),
})
break;
default:
formGroup = this.fb.group({
command: [null, [Validators.required]],
params: ['{}', [jsonRequired]],
})
}
return formGroup;
}
@ -213,7 +280,7 @@ export class GatewayServiceRPCConnectorComponent implements OnInit {
addSNMPoid(value: string = null) {
const oidsFA = this.commandForm.get('oid') as FormArray;
if (oidsFA) {
oidsFA.push(this.fb.control(value, [Validators.required]));
oidsFA.push(this.fb.control(value, [Validators.required]), {emitEvent: false});
}
}
@ -229,7 +296,7 @@ export class GatewayServiceRPCConnectorComponent implements OnInit {
value: [value.value, [Validators.required]]
})
if (headerFA) {
headerFA.push(formGroup);
headerFA.push(formGroup, {emitEvent: false});
}
}
@ -245,7 +312,7 @@ export class GatewayServiceRPCConnectorComponent implements OnInit {
value: [value.value, [Validators.required]]
})
if (securityFA) {
securityFA.push(formGroup);
securityFA.push(formGroup, {emitEvent: false});
}
}
@ -261,7 +328,7 @@ export class GatewayServiceRPCConnectorComponent implements OnInit {
addOCPUAArguments(value: string = null) {
const oidsFA = this.commandForm.get('arguments') as FormArray;
if (oidsFA) {
oidsFA.push(this.fb.control(value));
oidsFA.push(this.fb.control(value), {emitEvent: false});
}
}
@ -269,4 +336,86 @@ export class GatewayServiceRPCConnectorComponent implements OnInit {
const oidsFA = this.commandForm.get('arguments') as FormArray;
oidsFA.removeAt(index);
}
openEditJSONDialog($event: Event) {
if ($event) {
$event.stopPropagation();
}
this.dialog.open<JsonObjectEditDialogComponent, JsonObjectEditDialogData, object>(JsonObjectEditDialogComponent, {
disableClose: true,
panelClass: ['tb-dialog', 'tb-fullscreen-dialog'],
data: {
jsonValue: JSON.parse(this.commandForm.get('params').value),
required: true
}
}).afterClosed().subscribe(
(res) => {
if (res) {
this.commandForm.get('params').setValue(JSON.stringify(res));
}
}
);
}
save() {
this.saveTemplate.emit();
}
registerOnChange(fn: any): void {
this.propagateChange = fn;
}
registerOnTouched(fn: any): void {
}
clearFromArrayByName(name: string) {
const formArray = this.commandForm.get(name) as FormArray;
while (formArray.length !== 0) {
formArray.removeAt(0)
}
}
writeValue(value: RPCTemplateConfig): void {
if (typeof value == "object") {
value = deepClone(value);
switch (this.connectorType) {
case ConnectorType.SNMP:
this.clearFromArrayByName("oids");
value.oids.forEach(value => {
this.addSNMPoid(value)
})
delete value.oids;
break;
case ConnectorType.REQUEST:
this.clearFromArrayByName("httpHeaders");
value.httpHeaders && Object.entries(value.httpHeaders).forEach(httpHeader => {
this.addHTTPHeader({headerName: httpHeader[0], value: httpHeader[1] as string})
})
delete value.httpHeaders;
break;
case ConnectorType.REST:
this.clearFromArrayByName("httpHeaders");
this.clearFromArrayByName("security");
value.security && Object.entries(value.security).forEach(securityHeader => {
this.addHTTPSecurity({securityName: securityHeader[0], value: securityHeader[1] as string})
})
delete value.security;
value.httpHeaders && Object.entries(value.httpHeaders).forEach(httpHeader => {
this.addHTTPHeader({headerName: httpHeader[0], value: httpHeader[1] as string})
})
delete value.httpHeaders;
break;
case ConnectorType.OPCUA:
case ConnectorType.OPCUA_ASYNCIO:
this.clearFromArrayByName("arguments");
value.arguments.forEach(value => {
this.addOCPUAArguments(value)
})
delete value.arguments;
break;
}
this.commandForm.patchValue(value, {onlySelf: false});
}
}
}

7
ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc.component.html

@ -41,7 +41,8 @@
</button>
</ng-container>
<ng-template #connectorForm>
<tb-gateway-service-rpc-connector [connectorType]="connectorType" (sendCommand)="sendCommand()"/>
<tb-gateway-service-rpc-connector formControlName="params" [connectorType]="connectorType"
(sendCommand)="sendCommand()" (saveTemplate)="saveTemplate()"/>
</ng-template>
</div>
<section class="result-block" [formGroup]="commandForm">
@ -52,4 +53,6 @@
<tb-json-content [contentType]="contentTypes.JSON" readonly="true" formControlName="result"></tb-json-content>
</section>
</div>
<tb-gateway-service-rpc-connector-templates fxFlex="30" *ngIf="isConnector" class="border"></tb-gateway-service-rpc-connector-templates>
<tb-gateway-service-rpc-connector-templates fxFlex="30" *ngIf="isConnector" class="border" [rpcTemplates]="templates"
[ctx]="ctx" [connectorType]="connectorType" (useTemplate)="useTemplate($event)">
</tb-gateway-service-rpc-connector-templates>

141
ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc.component.ts

@ -14,17 +14,28 @@
/// limitations under the License.
///
import { OnInit, Component, Input } from '@angular/core';
import { ChangeDetectorRef, Component, Input, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { MatDialog, MatDialogRef } from '@angular/material/dialog';
import { WidgetContext } from '@home/models/widget-component.models';
import { ContentType } from '@shared/models/constants';
import {
JsonObjectEditDialogComponent,
JsonObjectEditDialogData
} from '@shared/components/dialog/json-object-edit-dialog.component';
import { jsonRequired } from '@shared/components/json-object-edit.component';
import { ConnectorType, RPCCommand } from '@home/components/widget/lib/gateway/gateway-widget.models';
import {
ConnectorType,
RPCCommand,
RPCTemplate,
RPCTemplateConfig,
SaveRPCTemplateData
} from '@home/components/widget/lib/gateway/gateway-widget.models';
import {
GatewayServiceRPCConnectorTemplateDialogComponent
} from '@home/components/widget/lib/gateway/gateway-service-rpc-connector-template-dialog';
import { AttributeService } from '@core/http/attribute.service';
import { AttributeScope } from '@shared/models/telemetry/telemetry.models';
import { EntityType } from '@shared/models/entity-type.models';
import { DatasourceType, widgetType } from '@shared/models/widget.models';
import { IWidgetSubscription, WidgetSubscriptionOptions } from '@core/api/widget-api.models';
import { UtilsService } from '@core/services/utils.service';
@Component({
selector: 'tb-gateway-service-rpc',
@ -58,9 +69,27 @@ export class GatewayServiceRPCComponent implements OnInit {
];
public connectorType: ConnectorType;
public templates: Array<RPCTemplate> = [];
private subscription: IWidgetSubscription;
private subscriptionOptions: WidgetSubscriptionOptions = {
callbacks: {
onDataUpdated: () => this.ctx.ngZone.run(() => {
this.updateTemplates()
}),
onDataUpdateError: (subscription, e) => this.ctx.ngZone.run(() => {
this.onDataUpdateError(e);
}),
dataLoading: () => {
}
}
};
constructor(private fb: FormBuilder,
private dialog: MatDialog) {
private dialog: MatDialog,
private utils: UtilsService,
private cd: ChangeDetectorRef,
private attributeService: AttributeService) {
this.commandForm = this.fb.group({
command: [null, [Validators.required]],
time: [60, [Validators.required, Validators.min(1)]],
@ -75,6 +104,17 @@ export class GatewayServiceRPCComponent implements OnInit {
this.commandForm.get('command').setValue(this.RPCCommands[0]);
} else {
this.connectorType = this.ctx.stateController.getStateParams().connector_rpc.value.type;
const subscriptionInfo = [{
type: DatasourceType.entity,
entityType: EntityType.DEVICE,
entityId: this.ctx.defaultSubscription.targetDeviceId,
entityName: 'Connector',
attributes: [{name: `${this.connectorType}_template`}]
}];
this.ctx.subscriptionApi.createSubscriptionFromInfo(widgetType.latest, subscriptionInfo,
this.subscriptionOptions, false, true).subscribe(subscription => {
this.subscription = subscription;
})
}
}
@ -82,7 +122,9 @@ export class GatewayServiceRPCComponent implements OnInit {
this.resultTime = null;
const formValues = value || this.commandForm.value;
const commandPrefix = this.isConnector ? `${this.connectorType}_` : 'gateway_';
this.ctx.controlApi.sendTwoWayCommand(commandPrefix + formValues.command.toLowerCase(), formValues.params, formValues.time).subscribe({
const command = !this.isConnector ? formValues.command.toLowerCase() : this.getCommandFromParamsByType(formValues.params);
const params = formValues.params;
this.ctx.controlApi.sendTwoWayCommand(commandPrefix + command, params, formValues.time).subscribe({
next: resp => {
this.resultTime = new Date().getTime();
this.commandForm.get('result').setValue(JSON.stringify(resp))
@ -95,23 +137,86 @@ export class GatewayServiceRPCComponent implements OnInit {
});
}
openEditJSONDialog($event: Event) {
if ($event) {
$event.stopPropagation();
getCommandFromParamsByType(params: RPCTemplateConfig) {
switch (this.connectorType) {
case ConnectorType.MQTT:
case ConnectorType.FTP:
case ConnectorType.SNMP:
case ConnectorType.REST:
case ConnectorType.REQUEST:
return params.methodFilter;
case ConnectorType.MODBUS:
return params.tag;
case ConnectorType.BACNET:
case ConnectorType.CAN:
case ConnectorType.OPCUA:
case ConnectorType.OPCUA_ASYNCIO:
return params.method;
case ConnectorType.BLE:
case ConnectorType.OCPP:
case ConnectorType.SOCKET:
case ConnectorType.XMPP:
return params.methodRPC;
default:
return params.command;
}
this.dialog.open<JsonObjectEditDialogComponent, JsonObjectEditDialogData, object>(JsonObjectEditDialogComponent, {
}
saveTemplate() {
this.dialog.open<GatewayServiceRPCConnectorTemplateDialogComponent, SaveRPCTemplateData>
(GatewayServiceRPCConnectorTemplateDialogComponent, {
disableClose: true,
panelClass: ['tb-dialog', 'tb-fullscreen-dialog'],
data: {
jsonValue: JSON.parse(this.commandForm.get('params').value),
required: true
}
data: {config: this.commandForm.value.params, templates: this.templates}
}).afterClosed().subscribe(
(res) => {
if (res) {
this.commandForm.get('params').setValue(JSON.stringify(res));
const templateAttribute: RPCTemplate = {
name: res,
config: this.commandForm.value.params
}
const templatesArray = this.templates;
const existingIndex = templatesArray.findIndex(template=>{
return template.name == templateAttribute.name;
})
if (existingIndex > -1 ){
templatesArray.splice(existingIndex, 1)
}
templatesArray.push(templateAttribute)
const key = `${this.connectorType}_template`;
this.attributeService.saveEntityAttributes(
{
id: this.ctx.defaultSubscription.targetDeviceId,
entityType: EntityType.DEVICE
}
, AttributeScope.SERVER_SCOPE, [{
key,
value: templatesArray
}]).subscribe(() => {
})
}
);
}
useTemplate($event) {
this.commandForm.get('params').patchValue($event.config);
}
private updateTemplates() {
this.templates = this.subscription.data[0].data[0][1].length ?
JSON.parse(this.subscription.data[0].data[0][1]) : [];
if (this.templates.length && this.commandForm.get('params').value == "{}") {
this.commandForm.get('params').patchValue(this.templates[0].config);
}
this.cd.detectChanges();
}
private onDataUpdateError(e: any) {
const exceptionData = this.utils.parseException(e);
let errorText = exceptionData.name;
if (exceptionData.message) {
errorText += ': ' + exceptionData.message;
}
console.error(errorText);
}
}

15
ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts

@ -261,10 +261,17 @@ export enum SocketEncodings {
}
export interface RPCTemplate {
name: string;
config: {
[key: string]: any;
};
name?: string;
config: RPCTemplateConfig;
}
export interface RPCTemplateConfig {
[key: string]: any;
}
export interface SaveRPCTemplateData {
config: RPCTemplateConfig,
templates: Array<RPCTemplate>
}
export interface LogLink {

5
ui-ngx/src/app/modules/home/components/widget/widget-components.module.ts

@ -74,6 +74,9 @@ import { ValueChartCardWidgetComponent } from '@home/components/widget/lib/cards
import { ProgressBarWidgetComponent } from '@home/components/widget/lib/cards/progress-bar-widget.component';
import { LiquidLevelWidgetComponent } from '@home/components/widget/lib/indicator/liquid-level-widget.component';
import { DoughnutWidgetComponent } from '@home/components/widget/lib/chart/doughnut-widget.component';
import {
GatewayServiceRPCConnectorTemplateDialogComponent
} from '@home/components/widget/lib/gateway/gateway-service-rpc-connector-template-dialog';
@NgModule({
declarations:
@ -107,6 +110,7 @@ import { DoughnutWidgetComponent } from '@home/components/widget/lib/chart/dough
DeviceGatewayCommandComponent,
GatewayConfigurationComponent,
GatewayRemoteConfigurationDialogComponent,
GatewayServiceRPCConnectorTemplateDialogComponent,
ValueCardWidgetComponent,
AggregatedValueCardWidgetComponent,
CountWidgetComponent,
@ -154,6 +158,7 @@ import { DoughnutWidgetComponent } from '@home/components/widget/lib/chart/dough
DeviceGatewayCommandComponent,
GatewayConfigurationComponent,
GatewayRemoteConfigurationDialogComponent,
GatewayServiceRPCConnectorTemplateDialogComponent,
ValueCardWidgetComponent,
AggregatedValueCardWidgetComponent,
CountWidgetComponent,

69
ui-ngx/src/assets/locale/locale.constant-en_US.json

@ -2776,54 +2776,54 @@
"rpc": {
"title": "{{type}} Connector RPC parameters",
"templates-title": "Connector RPC Templates",
"method-filter": "Method filter",
"request-topic-expression": "Request topic expression",
"response-topic-expression": "Response topic expression",
"response-timeout": "Response Time",
"value-expression": "Value Expression",
"methodFilter": "Method filter",
"requestTopicExpression": "Request topic expression",
"responseTopicExpression": "Response topic expression",
"responseTimeout": "Response Time",
"valueExpression": "Value Expression",
"tag": "Tag",
"type": "Type",
"function-code": "Function Code",
"objects-count": "Objects Count",
"functionCode": "Function Code",
"objectsCount": "Objects Count",
"address": "Address",
"method": "Method",
"request-type": "Request Type",
"request-timeout": "Request Timeout",
"object-type": "Object type",
"requestType": "Request Type",
"requestTimeout": "Request Timeout",
"objectType": "Object type",
"identifier": "Identifier",
"property-id": "Property ID",
"method-rpc": "Method RPC name",
"with-response": "With Response",
"characteristic-uuid": "Characteristic UUID",
"method-processing": "Method Processing",
"node-id": "Node ID",
"is-extended-id": "Is Extended ID",
"is-fd": "Is FD",
"bitrate-switch": "Bitrate Switch",
"data-in-hex": "Data In HEX",
"data-length": "Data Length",
"data-byte-order": "Data Byte Order",
"data-before": "Data Before",
"data-after": "Data After",
"data-expression": "Data Expression",
"propertyId": "Property ID",
"methodRPC": "Method RPC name",
"withResponse": "With Response",
"characteristicUUID": "Characteristic UUID",
"methodProcessing": "Method Processing",
"nodeID": "Node ID",
"isExtendedID": "Is Extended ID",
"isFD": "Is FD",
"bitrateSwitch": "Bitrate Switch",
"dataInHEX": "Data In HEX",
"dataLength": "Data Length",
"dataByteorder": "Data Byte Order",
"dataBefore": "Data Before",
"dataAfter": "Data After",
"dataExpression": "Data Expression",
"encoding": "Encoding",
"oid": "OID",
"add-oid": "Add OID",
"add-header": "Add header",
"add-security": "Add security",
"remove": "Remove",
"request-filter": "Request Filter",
"request-url": "Request URL Expression",
"http-method": "HTTP Method",
"requestFilter": "Request Filter",
"requestUrlExpression": "Request URL Expression",
"HTTPMethod": "HTTP Method",
"timeout": "Timeout",
"tries": "Tries",
"http-headers": "HTTP Headers",
"httpHeaders": "HTTP Headers",
"header-name": "Header name",
"security-name": "Security name",
"value": "Value",
"security": "Security",
"response-value-expression": "Response Value Expression",
"request-value-expression": "Request Value Expression",
"responseValueExpression": "Response Value Expression",
"requestValueExpression": "Request Value Expression",
"arguments": "Arguments",
"add-argument": "Add argument",
"write-property": "Write property",
@ -2843,7 +2843,12 @@
"multi-get": "Multiget",
"get-next": "Get next",
"bulk-get": "Bulk get",
"walk": "Walk"
"walk": "Walk",
"save-template": "Save template",
"template-name": "Template name",
"template-name-required": "Template name is required.",
"template-name-duplicate": "The name is already used."
},
"other": "Other",

Loading…
Cancel
Save