Kontaktné údaje
- info@ipesoft.com
- +421 907 703 854
- Obchodná 9076/3D
010 08 Žilina
Slovensko
© Copyright IPESOFT 2023

Dnes by som chcel ukázať, ako jednoducho sa dajú dostať údaje z D2000 do databázy.
Zadanie od zákazníka bolo jednoduché: Majú zoznam cca 30 meraných bodov, ktorých hodnoty potrebujú dostať do tabuľky v SQL databáze. Pričom:
Najskôr sme si zo zákazníkom zadefinovali formát tabuľky v databáze. Tabuľka sensor_data bude mať stĺpce:

Podľa formátu sme navrhli Definíciu štruktúry SD.sensor_data s rovnakými názvami stĺpcov:

Vytvorili sme objekt scada_data typu Databáza, zadali definované DSN a užívateľské meno.
Dôležitá poznámka: so zákazníkom sme sa dohodli, že časové značky budú v čase UTC+1 hod (čo zodpovedá slovenskému zimnému času). Výhoda oproti použitiu lokálneho času je, že sa nemusia riešiť nejednoznačné časy pri prechode letného času na zimný. Preto je na objekte scada_data nakonfigurované „Use monotonic time“ a offset 1 hodina.

Ako SQL databázový server použil zákazník PostgreSQL. Na aplikačnom serveri D2000 bolo potrebné nakonfigurovať 64-bitové DSN (keďže bol použitý 64-bitový DBManager), ktorého meno (scada_data) je použité v konfigurácii objektu scada_data typu Databáza v D2000.

V pokročilých nastaveniach DSN (strana 2) je nutné nastaviť parameter „Level of rollback on errors“ na hodnotu „Statement“, aby zlyhanie jednej operácie v rámci transakcie nespôsobilo zlyhanie celej transakcie.

No a chýba nám ešte objekt typu Tabuľka, ktorý bude reprezentovať samotnú tabuľku sensor_data v SQL databáze. Pri jeho konfigurácii sa využije zadefinovaná Definícia štruktúry. Názvy stĺpcov v tabuľke musia byť identické s názvami stĺpcov v Definícii štruktúry, pričom na poradí stĺpcov nezáleží.
Názov tabuľky je zadaný ako „.sensor_data“. Bodka na začiatku spôsobí, že DBManager nebude prefixovať názov tabuľky menom užívateľa (scada_user), keďže PostgreSQL oddeľuje užívateľov a schémy (na rozdiel od Oracle alebo Sybase SQL Anywhere).
Poznámka: PostgreSQL má špecifické správanie čo sa týka názvov stĺpcov, ak sú v zadané v úvodzovkách (citlivosť na malé/veľké písmená). Preto je odporúčané v prípade PostgreSQL spúšťať proces DBManager so štartovacím parametrom /NQ, aby nepoužíval úvodzovky (No Quotes).

V zadaní bolo, že máme do databázy kopírovať hodnoty cca 30 meraných bodov. Aby sme ich v skripte nemuseli referencovať po jednom (a volať procedúru „pumpuj“ pre každý z nich), je výhodné pripojiť tieto merané body do štruktúrovanej premennej a následne v skripte prejsť všetky riadky štruktúrovanej premenej za použitia skriptu.
Takže vytvoríme si ešte jednu pomocnú definíciu štruktúry SD.sensor_list, ktorá bude mať stĺpec Object typu Objekt.

Do štruktúry SV.sensor_list, ktorá využíva definíciu štruktúry SD.sensor_list, sme pripojili všetky požadované merané body.

Posledným krokom je napísanie samotného ESL skriptu (eventu) E.data_pump, ktorý raz za 15 minút bude vkladať dáta do tabuľky sensor_data. Tento skript bude spúšťaný na zmenu minúty (systémový objekt Min).

Čo si môžeme všimnúť?
Pre záujemcov prikladám ESL skript aj v textovej podobe 😊
;*********************************************************
; DESCRIPTION: Data pump to PostgreSQL database
; AUTHOR: Humaj
; LAST CHANGE: 2026 07 01
;*********************************************************
BEGIN
PRAGMA "ENABLE_INOUT_BY_REF"
INT _intvl = 900 ; size of interval (900 sec)
IF %Mod(Min, _intvl/60) # 0 THEN ; only export every 15 minutes
RETURN
ENDIF
INT _i, _idx, _ret
TIME _currTime = Min\TIM - %ModTime(Min\TIM, _intvl) ; current time (aligned to 15 min)
RECORD NOALIAS (SD.sensor_data) _dta
REDIM _dta [SV.sensor_list\DIM] ; resize to structure with I/O tags
FOR _i RANGE SV.sensor_list DO_LOOP
IF SV.sensor_list [_i]^Object\VLD THEN ; only valid value is copied to DB
IF _currTime - SV.sensor_list [_i]^Object\TIM < _intvl THEN ; if it was change in last 15 minutes
_idx := _idx + 1
_dta[_idx]^sensorid := %HBJToStr(SV.sensor_list [_i]^Object\HBJ)
_dta[_idx]^time := SV.sensor_list [_i]^Object\TIM
_dta[_idx]^value := SV.sensor_list [_i]^Object
ENDIF
ENDIF
END_LOOP
IF _idx < SV.sensor_list\DIM THEN
REDIM _dta [_idx] ; reduce size of _dta to filled-in rows only
ENDIF
DBS_INSERT DB.sensor_data, _dta, _ret
END
Čo dodať?
Navrhnuté riešenie demonštruje niekoľko vecí:
Čo som nedemonštroval, ale čitateľ si to môže vyskúšať sám – takto vytvorený ESL skript je možné v prostredí ESL editora komfortne ladiť – zobrazovať obsah lokálnych premenných, krokovať, nastavovať breakpointy – a to bez ohľadu na to, či je ESL skript vykonávaný na lokálnom alebo vzdialenom počítači.
V niektorom z budúcich blogov by som chcel ukázať ďalší skript, ktorý vie pracovať s históriou. Ďalšou požiadavkou zákazníka totiž bolo preniesť aj dáta z minulosti (ktoré sa nachádzajú v archívoch meraných bodov) a prípadne preniesť dáta za špecifikovanú dobu výpadku, ktorý môže byť spôsobený napríklad odstávkou servera s PostgreSQL databázou.
1.7.2026, Ing. Peter Humaj, www.ipesoft.com