Merge branch 'improvements/4097-modbus-adjustments' into improvements/050824-gateway
This commit is contained in:
commit
844c36f10d
@ -99,6 +99,9 @@ import * as TbJsonPipe from '@shared/pipe/tbJson.pipe';
|
|||||||
import * as TruncatePipe from '@shared/pipe/truncate.pipe';
|
import * as TruncatePipe from '@shared/pipe/truncate.pipe';
|
||||||
import * as ImagePipe from '@shared/pipe/image.pipe';
|
import * as ImagePipe from '@shared/pipe/image.pipe';
|
||||||
|
|
||||||
|
import * as EllipsisChipListDirective from '@shared/directives/ellipsis-chip-list.directive';
|
||||||
|
import * as TruncateWithTooltipDirective from '@shared/directives/truncate-with-tooltip.directive';
|
||||||
|
|
||||||
import * as coercion from '@shared/decorators/coercion';
|
import * as coercion from '@shared/decorators/coercion';
|
||||||
import * as enumerable from '@shared/decorators/enumerable';
|
import * as enumerable from '@shared/decorators/enumerable';
|
||||||
import * as TbInject from '@shared/decorators/tb-inject';
|
import * as TbInject from '@shared/decorators/tb-inject';
|
||||||
@ -422,6 +425,9 @@ class ModulesMap implements IModulesMap {
|
|||||||
'@shared/pipe/truncate.pipe': TruncatePipe,
|
'@shared/pipe/truncate.pipe': TruncatePipe,
|
||||||
'@shared/pipe/image.pipe': ImagePipe,
|
'@shared/pipe/image.pipe': ImagePipe,
|
||||||
|
|
||||||
|
'@shared/directives/ellipsis-chip-list.directive': EllipsisChipListDirective,
|
||||||
|
'@shared/directives/truncate-with-tooltip.directive': TruncateWithTooltipDirective,
|
||||||
|
|
||||||
'@shared/decorators/coercion': coercion,
|
'@shared/decorators/coercion': coercion,
|
||||||
'@shared/decorators/enumerable': enumerable,
|
'@shared/decorators/enumerable': enumerable,
|
||||||
'@shared/decorators/tb-inject': TbInject,
|
'@shared/decorators/tb-inject': TbInject,
|
||||||
|
|||||||
@ -26,12 +26,16 @@
|
|||||||
<mat-expansion-panel class="tb-settings" [expanded]="last">
|
<mat-expansion-panel class="tb-settings" [expanded]="last">
|
||||||
<mat-expansion-panel-header fxLayout="row wrap">
|
<mat-expansion-panel-header fxLayout="row wrap">
|
||||||
<mat-panel-title>
|
<mat-panel-title>
|
||||||
<div class="title-container">
|
<div *ngIf="isMaster else tagName" class="title-container" tbTruncateWithTooltip>
|
||||||
<span *ngIf="isMaster else tagName">
|
{{ keyControl.get('tag').value }}{{ '-' }}{{ keyControl.get('value').value }}
|
||||||
{{ keyControl.get('tag').value }}{{ '-' }}{{ keyControl.get('value').value }}
|
|
||||||
</span>
|
|
||||||
<ng-template #tagName>{{ keyControl.get('tag').value }}</ng-template>
|
|
||||||
</div>
|
</div>
|
||||||
|
<ng-template #tagName>
|
||||||
|
<div class="tb-flex">
|
||||||
|
<div class="title-container" tbTruncateWithTooltip>{{ 'gateway.key' | translate }}: {{ keyControl.get('tag').value }}</div>
|
||||||
|
<div class="title-container">{{ 'gateway.address' | translate }}: {{ keyControl.get('address').value }}</div>
|
||||||
|
<div class="title-container">{{ 'gateway.type' | translate }}: {{ keyControl.get('type').value }}</div>
|
||||||
|
</div>
|
||||||
|
</ng-template>
|
||||||
</mat-panel-title>
|
</mat-panel-title>
|
||||||
</mat-expansion-panel-header>
|
</mat-expansion-panel-header>
|
||||||
<ng-template matExpansionPanelContent>
|
<ng-template matExpansionPanelContent>
|
||||||
|
|||||||
@ -20,10 +20,7 @@
|
|||||||
max-width: 700px;
|
max-width: 700px;
|
||||||
|
|
||||||
.title-container {
|
.title-container {
|
||||||
max-width: 11vw;
|
width: 12vw;
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.key-panel {
|
.key-panel {
|
||||||
|
|||||||
@ -40,6 +40,7 @@ import { generateSecret } from '@core/utils';
|
|||||||
import { coerceBoolean } from '@shared/decorators/coercion';
|
import { coerceBoolean } from '@shared/decorators/coercion';
|
||||||
import { takeUntil } from 'rxjs/operators';
|
import { takeUntil } from 'rxjs/operators';
|
||||||
import { Subject } from 'rxjs';
|
import { Subject } from 'rxjs';
|
||||||
|
import { TruncateWithTooltipDirective } from '@shared/directives/truncate-with-tooltip.directive';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'tb-modbus-data-keys-panel',
|
selector: 'tb-modbus-data-keys-panel',
|
||||||
@ -50,6 +51,7 @@ import { Subject } from 'rxjs';
|
|||||||
CommonModule,
|
CommonModule,
|
||||||
SharedModule,
|
SharedModule,
|
||||||
GatewayHelpLinkPipe,
|
GatewayHelpLinkPipe,
|
||||||
|
TruncateWithTooltipDirective,
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class ModbusDataKeysPanelComponent implements OnInit, OnDestroy {
|
export class ModbusDataKeysPanelComponent implements OnInit, OnDestroy {
|
||||||
@ -78,8 +80,9 @@ export class ModbusDataKeysPanelComponent implements OnInit, OnDestroy {
|
|||||||
private destroy$ = new Subject<void>();
|
private destroy$ = new Subject<void>();
|
||||||
|
|
||||||
private readonly defaultReadFunctionCodes = [3, 4];
|
private readonly defaultReadFunctionCodes = [3, 4];
|
||||||
private readonly defaultWriteFunctionCodes = [5, 6, 15, 16];
|
private readonly bitsReadFunctionCodes = [1, 2];
|
||||||
private readonly stringAttrUpdatesWriteFunctionCodes = [6, 16];
|
private readonly defaultWriteFunctionCodes = [6, 16];
|
||||||
|
private readonly bitsWriteFunctionCodes = [5, 15];
|
||||||
|
|
||||||
constructor(private fb: UntypedFormBuilder) {}
|
constructor(private fb: UntypedFormBuilder) {}
|
||||||
|
|
||||||
@ -177,23 +180,23 @@ export class ModbusDataKeysPanelComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private getFunctionCodes(dataType: ModbusDataType): number[] {
|
private getFunctionCodes(dataType: ModbusDataType): number[] {
|
||||||
|
const writeFunctionCodes = [
|
||||||
|
...(dataType === ModbusDataType.BITS ? this.bitsWriteFunctionCodes : []), ...this.defaultWriteFunctionCodes
|
||||||
|
];
|
||||||
|
|
||||||
if (this.keysType === ModbusValueKey.ATTRIBUTES_UPDATES) {
|
if (this.keysType === ModbusValueKey.ATTRIBUTES_UPDATES) {
|
||||||
return dataType === ModbusDataType.STRING
|
return writeFunctionCodes.sort((a, b) => a - b);
|
||||||
? this.stringAttrUpdatesWriteFunctionCodes
|
|
||||||
: this.defaultWriteFunctionCodes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const functionCodes = [...this.defaultReadFunctionCodes];
|
const functionCodes = [...this.defaultReadFunctionCodes];
|
||||||
if (dataType === ModbusDataType.BITS) {
|
if (dataType === ModbusDataType.BITS) {
|
||||||
const bitsFunctionCodes = [1, 2];
|
functionCodes.push(...this.bitsReadFunctionCodes);
|
||||||
functionCodes.push(...bitsFunctionCodes);
|
|
||||||
functionCodes.sort();
|
|
||||||
}
|
}
|
||||||
if (this.keysType === ModbusValueKey.RPC_REQUESTS) {
|
if (this.keysType === ModbusValueKey.RPC_REQUESTS) {
|
||||||
functionCodes.push(...this.defaultWriteFunctionCodes);
|
functionCodes.push(...writeFunctionCodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
return functionCodes;
|
return functionCodes.sort((a, b) => a - b);
|
||||||
}
|
}
|
||||||
|
|
||||||
private getDefaultFunctionCodes(): number[] {
|
private getDefaultFunctionCodes(): number[] {
|
||||||
|
|||||||
@ -16,6 +16,9 @@
|
|||||||
|
|
||||||
-->
|
-->
|
||||||
<div class="tb-master-table tb-absolute-fill">
|
<div class="tb-master-table tb-absolute-fill">
|
||||||
|
<div class="tb-form-panel no-border no-padding padding-top">
|
||||||
|
<div class="tb-form-hint tb-primary-fill tb-flex center">{{ 'gateway.hints.modbus-master' | translate }}</div>
|
||||||
|
</div>
|
||||||
<div fxFlex fxLayout="column" class="tb-master-table-content">
|
<div fxFlex fxLayout="column" class="tb-master-table-content">
|
||||||
<mat-toolbar class="mat-mdc-table-toolbar" [fxShow]="!textSearchMode">
|
<mat-toolbar class="mat-mdc-table-toolbar" [fxShow]="!textSearchMode">
|
||||||
<div class="mat-toolbar-tools">
|
<div class="mat-toolbar-tools">
|
||||||
|
|||||||
@ -40,6 +40,8 @@ import {
|
|||||||
import {
|
import {
|
||||||
ModbusMasterConfig,
|
ModbusMasterConfig,
|
||||||
ModbusProtocolLabelsMap,
|
ModbusProtocolLabelsMap,
|
||||||
|
ModbusSlaveInfo,
|
||||||
|
ModbusValues,
|
||||||
SlaveConfig
|
SlaveConfig
|
||||||
} from '@home/components/widget/lib/gateway/gateway-widget.models';
|
} from '@home/components/widget/lib/gateway/gateway-widget.models';
|
||||||
import { isDefinedAndNotNull } from '@core/utils';
|
import { isDefinedAndNotNull } from '@core/utils';
|
||||||
@ -150,12 +152,12 @@ export class ModbusMasterTableComponent implements ControlValueAccessor, AfterVi
|
|||||||
}
|
}
|
||||||
const withIndex = isDefinedAndNotNull(index);
|
const withIndex = isDefinedAndNotNull(index);
|
||||||
const value = withIndex ? this.slaves.at(index).value : {};
|
const value = withIndex ? this.slaves.at(index).value : {};
|
||||||
this.dialog.open<ModbusSlaveDialogComponent, any, any>(ModbusSlaveDialogComponent, {
|
this.dialog.open<ModbusSlaveDialogComponent, ModbusSlaveInfo, ModbusValues>(ModbusSlaveDialogComponent, {
|
||||||
disableClose: true,
|
disableClose: true,
|
||||||
panelClass: ['tb-dialog', 'tb-fullscreen-dialog'],
|
panelClass: ['tb-dialog', 'tb-fullscreen-dialog'],
|
||||||
data: {
|
data: {
|
||||||
value,
|
value,
|
||||||
buttonTitle: withIndex ? 'action.add' : 'action.apply'
|
buttonTitle: withIndex ? 'action.apply' : 'action.add'
|
||||||
}
|
}
|
||||||
}).afterClosed()
|
}).afterClosed()
|
||||||
.pipe(take(1), takeUntil(this.destroy$))
|
.pipe(take(1), takeUntil(this.destroy$))
|
||||||
|
|||||||
@ -28,7 +28,7 @@
|
|||||||
</mat-toolbar>
|
</mat-toolbar>
|
||||||
<div mat-dialog-content [formGroup]="slaveConfigFormGroup" class="tb-form-panel">
|
<div mat-dialog-content [formGroup]="slaveConfigFormGroup" class="tb-form-panel">
|
||||||
<div class="tb-form-row column-xs" fxLayoutAlign="space-between center">
|
<div class="tb-form-row column-xs" fxLayoutAlign="space-between center">
|
||||||
<div class="fixed-title-width tb-required" translate>gateway.name</div>
|
<div class="fixed-title-width slave-name-label tb-required" translate>gateway.name</div>
|
||||||
<div class="tb-flex no-gap">
|
<div class="tb-flex no-gap">
|
||||||
<mat-form-field class="tb-flex no-gap" appearance="outline" subscriptSizing="dynamic">
|
<mat-form-field class="tb-flex no-gap" appearance="outline" subscriptSizing="dynamic">
|
||||||
<input matInput name="value" formControlName="name" placeholder="{{ 'gateway.set' | translate }}"/>
|
<input matInput name="value" formControlName="name" placeholder="{{ 'gateway.set' | translate }}"/>
|
||||||
|
|||||||
@ -18,4 +18,9 @@
|
|||||||
width: 80vw;
|
width: 80vw;
|
||||||
max-width: 900px;
|
max-width: 900px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.slave-name-label {
|
||||||
|
margin-right: 16px;
|
||||||
|
color: rgba(0, 0, 0, 0.87);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
18
ui-ngx/src/app/shared/directives/public-api.ts
Normal file
18
ui-ngx/src/app/shared/directives/public-api.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
///
|
||||||
|
/// Copyright © 2016-2024 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.
|
||||||
|
///
|
||||||
|
|
||||||
|
export * from './truncate-with-tooltip.directive';
|
||||||
|
export * from './ellipsis-chip-list.directive';
|
||||||
@ -105,8 +105,6 @@ export class TruncateWithTooltipDirective implements OnInit, AfterViewInit, OnDe
|
|||||||
|
|
||||||
private showTooltip(): void {
|
private showTooltip(): void {
|
||||||
this.tooltip.message = this.text;
|
this.tooltip.message = this.text;
|
||||||
|
|
||||||
this.renderer.setAttribute(this.elementRef.nativeElement, 'matTooltip', this.text);
|
|
||||||
this.tooltip.show();
|
this.tooltip.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -19,3 +19,4 @@ export * from './decorators/public-api';
|
|||||||
export * from './models/public-api';
|
export * from './models/public-api';
|
||||||
export * from './pipe/public-api';
|
export * from './pipe/public-api';
|
||||||
export * from './shared.module';
|
export * from './shared.module';
|
||||||
|
export * from './directives/public-api';
|
||||||
|
|||||||
@ -3326,7 +3326,8 @@
|
|||||||
"write-register": "Write Register",
|
"write-register": "Write Register",
|
||||||
"write-registers": "Write Registers",
|
"write-registers": "Write Registers",
|
||||||
"hints": {
|
"hints": {
|
||||||
"modbus-server": "Starting with version 3.0, Gateway can run as a Modbus slave.",
|
"modbus-master": "Configuration sections for connecting to Modbus servers and reading data from them.",
|
||||||
|
"modbus-server": "Configuration section for the Modbus server, storing data and sending updates to the platform when changes occur or at fixed intervals.",
|
||||||
"remote-configuration": "Enables remote configuration and management of the gateway",
|
"remote-configuration": "Enables remote configuration and management of the gateway",
|
||||||
"remote-shell": "Enables remote control of the operating system with the gateway from the Remote Shell widget",
|
"remote-shell": "Enables remote control of the operating system with the gateway from the Remote Shell widget",
|
||||||
"host": "Hostname or IP address of platform server",
|
"host": "Hostname or IP address of platform server",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user