Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions client/src/app/_models/device.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ export class Tag {
sysType: TagSystemType;
/** Description */
description?: string;
/** Optional Unified Namespace path */
unsPath?: string | null;
/** Deadband to set changed value */
deadband?: TagDeadband;
/**
Expand Down
8 changes: 8 additions & 0 deletions client/src/app/_models/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ export class DaqStore {
type = DaqStoreType.SQlite;
varsion?: string;
url?: string;
host = '127.0.0.1';
tableName = 'meters';
configurationString = 'http::addr=localhost:9000;';
organization?: string;
credentials?: StoreCredentials;
bucket?: string;
Expand All @@ -74,6 +77,9 @@ export class DaqStore {
if (daqstore) {
this.type = daqstore.type;
this.url = daqstore.url;
this.host = daqstore.host;
this.tableName = daqstore.tableName || 'meters';
this.configurationString = daqstore.configurationString;
this.organization = daqstore.organization;
this.credentials = daqstore.credentials;
this.bucket = daqstore.bucket;
Expand All @@ -84,6 +90,7 @@ export class DaqStore {

isEquals(store: DaqStore) {
if (this.type === store.type && this.bucket === store.bucket && this.url === store.url &&
this.host === store.host && this.tableName === store.tableName && this.configurationString === store.configurationString &&
this.organization === store.organization && this.database === store.database &&
(this.credentials && StoreCredentials.isEquals(this.credentials, store.credentials)) && this.retention === store.retention) {
return true;
Expand Down Expand Up @@ -115,6 +122,7 @@ export enum DaqStoreType {
influxDB = 'influxDB',
influxDB18 = 'influxDB 1.8',
TDengine = 'TDengine' ,
questDB = 'questDB',
}

export enum influxDBVersionType {
Expand Down
10 changes: 9 additions & 1 deletion client/src/app/device/device-list/device-list.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,14 @@
<mat-cell *matCellDef="let element" matTooltip="{{element.description}}">{{ element.description }}</mat-cell>
</ng-container>

<!-- UNS Column -->
<ng-container matColumnDef="uns">
<mat-header-cell *matHeaderCellDef mat-sort-header> </mat-header-cell>
<mat-cell *matCellDef="let element">
<mat-icon *ngIf="element.unsPath" [matTooltip]="element.unsPath" matTooltipPosition="left">account_tree</mat-icon>
</mat-cell>
</ng-container>

<!-- Logger Column -->
<ng-container matColumnDef="logger">
<mat-header-cell *matHeaderCellDef mat-sort-header> </mat-header-cell>
Expand Down Expand Up @@ -159,4 +167,4 @@
</div>
<mat-paginator [pageSizeOptions]="[10, 25, 100]" [pageSize]="25" class="paginator"></mat-paginator>
</div>
</div>
</div>
9 changes: 5 additions & 4 deletions client/src/app/device/device-list/device-list.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ import { TagPropertyService } from '../tag-property/tag-property.service';
})
export class DeviceListComponent implements OnInit, AfterViewInit {

readonly defAllColumns = ['select', 'name', 'address', 'device', 'type', 'value', 'timestamp', 'description', 'warning', 'logger', 'options', 'remove'];
readonly defAllExtColumns = ['select', 'name', 'address', 'device', 'type', 'value', 'timestamp', 'quality', 'description', 'warning', 'logger', 'options', 'remove'];
readonly defAllColumns = ['select', 'name', 'address', 'device', 'type', 'value', 'timestamp', 'description', 'warning', 'uns', 'logger', 'options', 'remove'];
readonly defAllExtColumns = ['select', 'name', 'address', 'device', 'type', 'value', 'timestamp', 'quality', 'description', 'warning', 'uns', 'logger', 'options', 'remove'];
readonly defInternalColumns = ['select', 'name', 'device', 'type', 'value', 'timestamp', 'description', 'options', 'remove'];
readonly defGpipColumns = ['select', 'name', 'device', 'address', 'direction', 'value', 'timestamp', 'description', 'logger', 'options', 'remove'];
readonly defWebcamColumns = ['select', 'name', 'device', 'address', 'value', 'timestamp', 'description', 'logger', 'options', 'remove'];
readonly defGpipColumns = ['select', 'name', 'device', 'address', 'direction', 'value', 'timestamp', 'description', 'uns', 'logger', 'options', 'remove'];
readonly defWebcamColumns = ['select', 'name', 'device', 'address', 'value', 'timestamp', 'description', 'uns', 'logger', 'options', 'remove'];
readonly defAllRowWidth = 1400;
readonly defClientRowWidth = 1400;
readonly defInternalRowWidth = 1200;
Expand Down Expand Up @@ -383,6 +383,7 @@ export class DeviceListComponent implements OnInit, AfterViewInit {
tags[i].scaleReadParams = tagOption.scaleReadParams;
tags[i].scaleWriteFunction = tagOption.scaleWriteFunction;
tags[i].scaleWriteParams = tagOption.scaleWriteParams;
tags[i].unsPath = tagOption.unsPath;
}
this.projectService.setDeviceTags(this.deviceSelected);
}
Expand Down
7 changes: 7 additions & 0 deletions client/src/app/device/tag-options/tag-options.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ <h1 mat-dialog-title style="display:inline-block;cursor:move;" mat-dialog-dragga
<span>{{'device.tag-deadband' | translate}}</span>
<input numberOnly formControlName="deadband" type="number">
</div>
<div class="my-form-field item-block mt10">
<span>{{'device.tag-uns-path' | translate}}</span>
<input formControlName="unsPath" type="text">
<span *ngIf="formGroup.controls.unsPath.errors?.unsPathExists" class="form-input-error">
{{'msg.device-tag-exist' | translate}}
</span>
</div>
<div *ngIf="!isFuxaServerTag()">
<div class="my-form-field item-block mt10">
<span>{{'device.tag-scale' | translate}}</span>
Expand Down
43 changes: 41 additions & 2 deletions client/src/app/device/tag-options/tag-options.component.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ChangeDetectionStrategy, Component, Inject, OnDestroy, OnInit } from '@angular/core';
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { AbstractControl, UntypedFormBuilder, UntypedFormGroup, ValidationErrors, ValidatorFn, Validators } from '@angular/forms';
import { MatDialogRef as MatDialogRef, MAT_DIALOG_DATA as MAT_DIALOG_DATA } from '@angular/material/dialog';
import { FuxaServer, TagDaq, TagDeadband, TagDeadbandModeType, TagScale, TagScaleModeType } from '../../_models/device';
import { Utils} from '../../_helpers/utils';
Expand Down Expand Up @@ -56,6 +56,7 @@ export class TagOptionsComponent implements OnInit, OnDestroy {
scaleWriteFunction: null,
scaleReadExpression: null,
scaleWriteExpression: null,
unsPath: [null, [this.validateUnsPathUnique()]],
});

this.formGroup.controls.enabled.valueChanges.subscribe(enabled => {
Expand Down Expand Up @@ -88,6 +89,7 @@ export class TagOptionsComponent implements OnInit, OnDestroy {
//let scaleWriteParams = { value: null, valid: true };
let scaleReadExpression = { value: null, valid: true };
let scaleWriteExpression = { value: null, valid: true };
let unsPath = { value: null, valid: true, initialized: false };
for (let i = 0; i < this.data.tags.length; i++) {
if (!this.data.tags[i].daq) {
continue;
Expand Down Expand Up @@ -153,6 +155,14 @@ export class TagOptionsComponent implements OnInit, OnDestroy {
const tagParams = JSON.parse(this.data.tags[i].scaleWriteParams) as ScriptParam[];
const notValid = this.initializeScriptParams(script, tagParams, this.configedWriteParams);
}

const currentUnsPath = this.normalizeUnsPath(this.data.tags[i].unsPath);
if (!unsPath.initialized) {
unsPath.value = currentUnsPath;
unsPath.initialized = true;
} else if (unsPath.value !== currentUnsPath) {
unsPath.valid = false;
}
}
let values = {};
if (enabled.valid && enabled.value !== null) {
Expand Down Expand Up @@ -192,6 +202,9 @@ export class TagOptionsComponent implements OnInit, OnDestroy {
if (scaleWriteFunction.valid && scaleWriteFunction.value) {
values = {...values, scaleWriteFunction: scaleWriteFunction.value};
}
if (unsPath.valid && unsPath.initialized) {
values = {...values, unsPath: unsPath.value};
}

this.formGroup.patchValue(values);
if (this.data.device?.id === FuxaServer.id) {
Expand Down Expand Up @@ -274,7 +287,8 @@ export class TagOptionsComponent implements OnInit, OnDestroy {
scaleReadFunction: this.formGroup.value.scaleReadFunction,
scaleReadParams: readParamsStr,
scaleWriteFunction: this.formGroup.value.scaleWriteFunction,
scaleWriteParams: writeParamsStr
scaleWriteParams: writeParamsStr,
unsPath: this.normalizeUnsPath(this.formGroup.value.unsPath)
});
}

Expand Down Expand Up @@ -368,6 +382,30 @@ export class TagOptionsComponent implements OnInit, OnDestroy {
}
return true;
}

private validateUnsPathUnique(): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
const currentUnsPath = this.normalizeUnsPath(control?.value);
if (!currentUnsPath || !this.data?.device?.tags) {
return null;
}
const currentTagIds = new Set((this.data?.tags || []).map(t => t.id));
const exists = Object.values(this.data.device.tags).some((tag: any) =>
tag &&
!currentTagIds.has(tag.id) &&
this.normalizeUnsPath(tag.unsPath) === currentUnsPath
);
return exists ? { unsPathExists: true } : null;
};
}

private normalizeUnsPath(value: any): string | null {
if (Utils.isNullOrUndefined(value)) {
return null;
}
const normalized = String(value).trim();
return normalized.length ? normalized : null;
}
}

export interface TagOptionType {
Expand All @@ -379,4 +417,5 @@ export interface TagOptionType {
scaleReadParams?: string;
scaleWriteFunction?: string;
scaleWriteParams?: string;
unsPath?: string | null;
}
28 changes: 28 additions & 0 deletions client/src/app/editor/app-settings/app-settings.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,34 @@ <h1 mat-dialog-title style="display:inline-block;cursor:move;" mat-dialog-dragga
<input [(ngModel)]="settings.daqstore.credentials.password" placeholder="taosdata" class="input-row" type="text">
</div>
</div>
<div *ngSwitchCase="daqstoreType.questDB">
<div class="block mt20 w100">
<span>{{'dlg.app-settings-daqstore-queryconn' | translate}}</span>
</div>
<div class="my-form-field block mt15 w100">
<span>{{'dlg.app-settings-daqstore-questdb-host' | translate}}</span>
<input [(ngModel)]="settings.daqstore.host" placeholder="127.0.0.1" class="input-row" type="text">
</div>
<div class="my-form-field block mt15 w100">
<span>{{'dlg.app-settings-daqstore-database' | translate}}</span>
<input [(ngModel)]="settings.daqstore.tableName" placeholder="meters" class="input-row" type="text">
</div>
<div class="my-form-field block mt15 w100">
<span>{{'dlg.app-settings-daqstore-username' | translate}}</span>
<input [(ngModel)]="settings.daqstore.credentials.username" placeholder="admin" class="input-row" type="text">
</div>
<div class="my-form-field block mt15 w100">
<span>{{'dlg.app-settings-daqstore-password' | translate}}</span>
<input [(ngModel)]="settings.daqstore.credentials.password" placeholder="quest" class="input-row" type="text">
</div>
<div class="block mt20 w100">
<span>{{'dlg.app-settings-daqstore-ingestconn' | translate}}</span>
</div>
<div class="my-form-field block mt15 w100">
<span>{{'dlg.app-settings-daqstore-configurl' | translate}}</span>
<input [(ngModel)]="settings.daqstore.configurationString" placeholder="http::addr=localhost:9000;" class="input-row" type="text">
</div>
</div>
</div>
</div>
</div>
Expand Down
10 changes: 10 additions & 0 deletions client/src/assets/i18n/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -834,6 +834,8 @@
"device.tag-daq-changed": "Wert speichern, wenn geändert",
"device.tag-daq-interval": "Intervall für Speichern (Sek.)",
"device.tag-format": "Ziffern formatieren (2 = #.##)",

"device.tag-uns-path": "UNS Path",
"device.tag-scale": "Skalierungsmodus",
"device.tag-scale-mode-undefined": "Keine Skalierung",
"device.tag-scale-mode-undefined-tooltip": "Tag-Wert",
Expand Down Expand Up @@ -1240,6 +1242,11 @@
"dlg.app-settings-daqstore": "DAQ-Speicher",
"dlg.app-settings-daqstore-type": "Datenbanktyp",
"dlg.app-settings-daqstore-url": "URL",
"dlg.app-settings-daqstore-configurl": "Config URL",
"dlg.app-settings-daqstore-queryconn": "Query connection (PGWire)",

"dlg.app-settings-daqstore-questdb-host": "QuestDB Host",
"dlg.app-settings-daqstore-ingestconn": "Ingestion connection (ILP)",
"dlg.app-settings-daqstore-token": "Token",
"dlg.app-settings-daqstore-bucket": "Bucket",
"dlg.app-settings-daqstore-organization": "Organisation",
Expand Down Expand Up @@ -1306,3 +1313,6 @@
"msg.report-build-error": "Senden zum Erstellen des Berichts fehlgeschlagen!",
"msg.device-tags-request-result": "Lade {{value}} von {{current}}"
}



10 changes: 10 additions & 0 deletions client/src/assets/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -1154,6 +1154,8 @@

"device.tag-format": "Format digits (2 = #.##)",
"device.tag-deadband": "Deadband",

"device.tag-uns-path": "UNS Path",
"device.tag-scale": "Scale Mode / Convertion",
"device.tag-scale-mode-undefined": "No Scaling",
"device.tag-scale-mode-undefined-tooltip": "Tag Value",
Expand Down Expand Up @@ -1812,6 +1814,11 @@
"dlg.app-settings-daqstore": "DAQ storage",
"dlg.app-settings-daqstore-type": "Database type",
"dlg.app-settings-daqstore-url": "URL",
"dlg.app-settings-daqstore-configurl": "Config URL",
"dlg.app-settings-daqstore-queryconn": "Query connection (PGWire)",

"dlg.app-settings-daqstore-questdb-host": "QuestDB Host",
"dlg.app-settings-daqstore-ingestconn": "Ingestion connection (ILP)",
"dlg.app-settings-daqstore-token": "Token",
"dlg.app-settings-daqstore-bucket": "Bucket",
"dlg.app-settings-daqstore-organization": "Organization",
Expand Down Expand Up @@ -1931,3 +1938,6 @@
"msg.operation-unauthorized": "Operation Unauthorized!",
"msg.secret-code-required": "Secret code required to sign authentication tokens"
}



12 changes: 12 additions & 0 deletions client/src/assets/i18n/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,9 @@
"device-tag-dialog-title": "Etiqueta seleccionada",

"device.tag-options-title": "Opciones de etiquetas",


"device.tag-uns-path": "UNS Path",
"device.tag-daq-enabled": "Registration Enabled",
"device.tag-daq-changed": "Guardar valor si cambia",
"device.tag-daq-interval": "Intervalo para guardar valor (segundos)",
Expand Down Expand Up @@ -736,6 +739,12 @@
"dlg.app-settings-server-port": "Servidor esta escuchando el puerto",
"dlg.app-settings-alarms-clear": "Borrar todas las alarmas y el historias",
"dlg.app-settings-auth-token": "Autenticación con token",
"dlg.app-settings-daqstore-url": "URL",
"dlg.app-settings-daqstore-configurl": "Config URL",
"dlg.app-settings-daqstore-queryconn": "Query connection (PGWire)",

"dlg.app-settings-daqstore-questdb-host": "QuestDB Host",
"dlg.app-settings-daqstore-ingestconn": "Ingestion connection (ILP)",
"dlg.app-auth-disabled": "Deshabilitado",
"dlg.app-auth-expiration-15m": "Habilitado con token expira en 15 min.",
"dlg.app-auth-expiration-1h": "Habilitado con token expira en 1 hora.",
Expand Down Expand Up @@ -774,3 +783,6 @@
"msg.editor-mode-locked": "El editor ya esta abierto!",
"msg.alarms-clear-success": "Todas las alarmas han sido canceladas!"
}



10 changes: 10 additions & 0 deletions client/src/assets/i18n/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -1009,6 +1009,8 @@

"device.tag-format": "Format du nombre (2 = #.##)",
"device.tag-deadband": "Zone morte",

"device.tag-uns-path": "UNS Path",
"device.tag-scale": "Mode mise à l'échelle / Conversion",
"device.tag-scale-mode-undefined": "Pas de mise à l'échelle",
"device.tag-scale-mode-undefined-tooltip": "Valeur du tag",
Expand Down Expand Up @@ -1618,6 +1620,11 @@
"dlg.app-settings-daqstore": "Stockage DAQ",
"dlg.app-settings-daqstore-type": "Type de base de données",
"dlg.app-settings-daqstore-url": "URL",
"dlg.app-settings-daqstore-configurl": "Config URL",
"dlg.app-settings-daqstore-queryconn": "Query connection (PGWire)",

"dlg.app-settings-daqstore-questdb-host": "QuestDB Host",
"dlg.app-settings-daqstore-ingestconn": "Ingestion connection (ILP)",
"dlg.app-settings-daqstore-token": "Jeton",
"dlg.app-settings-daqstore-bucket": "Seau",
"dlg.app-settings-daqstore-organization": "Organisation",
Expand Down Expand Up @@ -1715,3 +1722,6 @@
"msg.texts-text-remove": "Souhaitez-vous supprimer le texte '{{value}}' ?",
"msg.operation-unauthorized": "Opération non autorisée !"
}



11 changes: 10 additions & 1 deletion client/src/assets/i18n/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -1031,6 +1031,8 @@

"device.tag-format": "桁数フォーマット (2 = #.##)",
"device.tag-deadband": "デッドバンド",

"device.tag-uns-path": "UNS Path",
"device.tag-scale": "スケーリングモード / 変換",
"device. tag-scale-mode-undefined": "スケーリングなし",
"device.tag-scale-mode-undefined-tooltip": "タグ値",
Expand Down Expand Up @@ -1652,6 +1654,11 @@
"dlg.app-settings-daqstore": "DAQストレージ",
"dlg.app-settings-daqstore-type": "データベースタイプ",
"dlg.app-settings-daqstore-url": "URL",
"dlg.app-settings-daqstore-configurl": "Config URL",
"dlg.app-settings-daqstore-queryconn": "Query connection (PGWire)",

"dlg.app-settings-daqstore-questdb-host": "QuestDB Host",
"dlg.app-settings-daqstore-ingestconn": "Ingestion connection (ILP)",
"dlg.app-settings-daqstore-token": "トークン",
"dlg.app-settings-daqstore-bucket": "バケット",
"dlg.app-settings-daqstore-organization": "組織",
Expand Down Expand Up @@ -1748,4 +1755,6 @@
"msg.text-name-exist": "テキスト名が既に存在します!",
"msg.texts-text-remove": "テキスト '{{value}}' を削除しますか?",
"msg.operation-unauthorized": "操作が許可されていません!"
}
}


Loading