diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-data-keys-panel/modbus-data-keys-panel.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-data-keys-panel/modbus-data-keys-panel.component.html
index fc94fe49ea..e84158c91b 100644
--- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-data-keys-panel/modbus-data-keys-panel.component.html
+++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-data-keys-panel/modbus-data-keys-panel.component.html
@@ -148,6 +148,62 @@
+
gateway.value
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-data-keys-panel/modbus-data-keys-panel.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-data-keys-panel/modbus-data-keys-panel.component.ts
index 3c61d351b7..094ef24dcb 100644
--- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-data-keys-panel/modbus-data-keys-panel.component.ts
+++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-data-keys-panel/modbus-data-keys-panel.component.ts
@@ -18,6 +18,7 @@ import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angu
import {
AbstractControl,
FormArray,
+ FormControl,
FormGroup,
UntypedFormArray,
UntypedFormBuilder,
@@ -32,7 +33,10 @@ import {
ModbusObjectCountByDataType,
ModbusValue,
ModbusValueKey,
+ ModifierType,
+ ModifierTypesMap,
noLeadTrailSpacesRegex,
+ nonZeroFloat,
} from '@home/components/widget/lib/gateway/gateway-widget.models';
import { CommonModule } from '@angular/common';
import { SharedModule } from '@shared/shared.module';
@@ -69,12 +73,17 @@ export class ModbusDataKeysPanelComponent implements OnInit, OnDestroy {
keysListFormArray: FormArray;
modbusDataTypes = Object.values(ModbusDataType);
+ modifierTypes: ModifierType[] = Object.values(ModifierType);
withFunctionCode = true;
+
+ enableModifiersControlMap = new Map>();
+ showModifiersMap = new Map();
functionCodesMap = new Map();
defaultFunctionCodes = [];
readonly ModbusEditableDataTypes = ModbusEditableDataTypes;
readonly ModbusFunctionCodeTranslationsMap = ModbusFunctionCodeTranslationsMap;
+ readonly ModifierTypesMap = ModifierTypesMap;
private destroy$ = new Subject();
@@ -101,6 +110,7 @@ export class ModbusDataKeysPanelComponent implements OnInit, OnDestroy {
}
addKey(): void {
+ const id = generateSecret(5);
const dataKeyFormGroup = this.fb.group({
tag: ['', [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]],
value: [{value: '', disabled: !this.isMaster}, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]],
@@ -108,9 +118,14 @@ export class ModbusDataKeysPanelComponent implements OnInit, OnDestroy {
address: [null, [Validators.required]],
objectsCount: [1, [Validators.required]],
functionCode: [{ value: this.getDefaultFunctionCodes()[0], disabled: !this.withFunctionCode }, [Validators.required]],
- id: [{value: generateSecret(5), disabled: true}],
+ modifierType: [{ value: ModifierType.MULTIPLIER, disabled: true }],
+ modifierValue: [{ value: 1, disabled: true }, [Validators.pattern(nonZeroFloat)]],
+ id: [{value: id, disabled: true}],
});
+ this.showModifiersMap.set(id, false);
+ this.enableModifiersControlMap.set(id, this.fb.control(false));
this.observeKeyDataType(dataKeyFormGroup);
+ this.observeEnableModifier(dataKeyFormGroup);
this.keysListFormArray.push(dataKeyFormGroup);
}
@@ -128,7 +143,17 @@ export class ModbusDataKeysPanelComponent implements OnInit, OnDestroy {
}
applyKeysData(): void {
- this.keysDataApplied.emit(this.keysListFormArray.value);
+ this.keysDataApplied.emit(this.mapKeysWithModifier());
+ }
+
+ private mapKeysWithModifier(): Array {
+ return this.keysListFormArray.value.map((keyData, i) => {
+ if (this.showModifiersMap.get(this.keysListFormArray.controls[i].get('id').value)) {
+ const { modifierType, modifierValue, ...value } = keyData;
+ return modifierType ? { ...value, [modifierType]: modifierValue } : value;
+ }
+ return keyData;
+ });
}
private prepareKeysFormArray(values: ModbusValue[]): UntypedFormArray {
@@ -138,6 +163,7 @@ export class ModbusDataKeysPanelComponent implements OnInit, OnDestroy {
values.forEach(value => {
const dataKeyFormGroup = this.createDataKeyFormGroup(value);
this.observeKeyDataType(dataKeyFormGroup);
+ this.observeEnableModifier(dataKeyFormGroup);
this.functionCodesMap.set(dataKeyFormGroup.get('id').value, this.getFunctionCodes(value.type));
keysControlGroups.push(dataKeyFormGroup);
@@ -148,7 +174,12 @@ export class ModbusDataKeysPanelComponent implements OnInit, OnDestroy {
}
private createDataKeyFormGroup(modbusValue: ModbusValue): FormGroup {
- const { tag, value, type, address, objectsCount, functionCode } = modbusValue;
+ const { tag, value, type, address, objectsCount, functionCode, multiplier, divider } = modbusValue;
+ const id = generateSecret(5);
+
+ const showModifier = this.shouldShowModifier(type);
+ this.showModifiersMap.set(id, showModifier);
+ this.enableModifiersControlMap.set(id, this.fb.control((multiplier || divider) && showModifier));
return this.fb.group({
tag: [tag, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]],
@@ -157,19 +188,54 @@ export class ModbusDataKeysPanelComponent implements OnInit, OnDestroy {
address: [address, [Validators.required]],
objectsCount: [objectsCount, [Validators.required]],
functionCode: [{ value: functionCode, disabled: !this.withFunctionCode }, [Validators.required]],
- id: [{ value: generateSecret(5), disabled: true }],
+ modifierType: [{
+ value: divider ? ModifierType.DIVIDER : ModifierType.MULTIPLIER,
+ disabled: !this.enableModifiersControlMap.get(id).value
+ }],
+ modifierValue: [
+ { value: multiplier ?? divider ?? 1, disabled: !this.enableModifiersControlMap.get(id).value },
+ [Validators.pattern(nonZeroFloat)]
+ ],
+ id: [{ value: id, disabled: true }],
});
}
+ private shouldShowModifier(type: ModbusDataType): boolean {
+ return !this.isMaster
+ && (this.keysType === ModbusValueKey.ATTRIBUTES || this.keysType === ModbusValueKey.TIMESERIES)
+ && (!this.ModbusEditableDataTypes.includes(type));
+ }
+
private observeKeyDataType(keyFormGroup: FormGroup): void {
keyFormGroup.get('type').valueChanges.pipe(takeUntil(this.destroy$)).subscribe(dataType => {
if (!this.ModbusEditableDataTypes.includes(dataType)) {
keyFormGroup.get('objectsCount').patchValue(ModbusObjectCountByDataType[dataType], {emitEvent: false});
}
+ const withModifier = this.shouldShowModifier(dataType);
+ this.showModifiersMap.set(keyFormGroup.get('id').value, withModifier);
this.updateFunctionCodes(keyFormGroup, dataType);
});
}
+ private observeEnableModifier(keyFormGroup: FormGroup): void {
+ this.enableModifiersControlMap.get(keyFormGroup.get('id').value).valueChanges
+ .pipe(takeUntil(this.destroy$))
+ .subscribe(showModifier => this.toggleModifierControls(keyFormGroup, showModifier));
+ }
+
+ private toggleModifierControls(keyFormGroup: FormGroup, enable: boolean): void {
+ const modifierTypeControl = keyFormGroup.get('modifierType');
+ const modifierValueControl = keyFormGroup.get('modifierValue');
+
+ if (enable) {
+ modifierTypeControl.enable();
+ modifierValueControl.enable();
+ } else {
+ modifierTypeControl.disable();
+ modifierValueControl.disable();
+ }
+ }
+
private updateFunctionCodes(keyFormGroup: FormGroup, dataType: ModbusDataType): void {
const functionCodes = this.getFunctionCodes(dataType);
this.functionCodesMap.set(keyFormGroup.get('id').value, functionCodes);
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts
index a2184089b1..fcc04beac6 100644
--- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts
+++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts
@@ -19,6 +19,7 @@ import { AttributeData } from '@shared/models/telemetry/telemetry.models';
export const noLeadTrailSpacesRegex = /^\S+(?: \S+)*$/;
export const integerRegex = /^[-+]?\d+$/;
+export const nonZeroFloat = /^-?(?!0(\.0+)?$)\d+(\.\d+)?$/;
export enum StorageTypes {
MEMORY = 'memory',
@@ -897,6 +898,30 @@ export enum MappingValueType {
BOOLEAN = 'boolean'
}
+export enum ModifierType {
+ DIVIDER = 'divider',
+ MULTIPLIER = 'multiplier',
+}
+
+export const ModifierTypesMap = new Map(
+ [
+ [
+ ModifierType.DIVIDER,
+ {
+ name: 'gateway.divider',
+ icon: 'mdi:division'
+ }
+ ],
+ [
+ ModifierType.MULTIPLIER,
+ {
+ name: 'gateway.multiplier',
+ icon: 'mdi:multiplication'
+ }
+ ],
+ ]
+);
+
export const mappingValueTypesMap = new Map(
[
[
@@ -1141,6 +1166,8 @@ export interface ModbusValue {
objectsCount: number;
address: number;
value?: string;
+ multiplier?: number;
+ divider?: number;
}
export interface ModbusSecurity {
diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json
index f5f26beeeb..d5476dc388 100644
--- a/ui-ngx/src/assets/locale/locale.constant-en_US.json
+++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json
@@ -2934,6 +2934,7 @@
"details": "Details",
"delete-mapping-title": "Delete mapping?",
"delete-slave-title": "Delete slave?",
+ "divider": "Divider",
"download-configuration-file": "Download configuration file",
"download-docker-compose": "Download docker-compose.yml for your gateway",
"enable-remote-logging": "Enable remote logging",
@@ -3089,8 +3090,11 @@
"min-pack-send-delay-required": "Min pack send delay is required",
"min-pack-send-delay-min": "Min pack send delay can not be less then 10",
"min-pack-send-delay-pattern": "Min pack send delay is not valid",
+ "multiplier": "Multiplier",
"mode": "Mode",
"model-name": "Model name",
+ "modifier": "Modifier",
+ "modifier-invalid": "Modifier is not valid",
"mqtt-version": "MQTT version",
"name": "Name",
"name-required": "Name is required.",
@@ -3493,7 +3497,8 @@
"objects-count": "Depends on the selected type.",
"address": "Register address to verify.",
"key": "Key to be used as the attribute key for the platform instance.",
- "data-keys": "For more information about function codes and data types click on help icon"
+ "data-keys": "For more information about function codes and data types click on help icon",
+ "modifier": "The retrieved value will be adjusted (by multiplying or dividing it) based on the specified modifier value."
}
}
},