====== Mervis DB ======
{{ :cs:sw:01-mervis:mervis_db.png?nolink&400 |}}
Mervis DB je vysoce optimalizovaná databáze určená pro dlouhodobé ukládání dat z jednotek, aplikací a mnoha jiných zařízení, které využívají otevřeného API databáze.
Hlavní využití s jednotkami Unipi je ukládání historických dat a jejich analýza pomocí [[cs:sw:01-mervis:05-mervis-scada|Mervis SCADA]].
===== Služba je dostupná v cloudové i lokální variantě =====
Součást Mervis SCADA (cloud)\\
Standardním způsobem použití Mervis DB je varianta cloudové služby. Přístupové údaje k Mervis DB jsou vygenerovány **společně s projektem Mervis SCADA** a jsou určeny pro všechny PLC, jenž jsou k tomuto SCADA projektu připojeny.
Pro nasazení Mervis DB společně s Mervis SCADA pokračujte návodem [[cs:sw:01-mervis:mervis-scada-project-hidden|]].
----
Pouze Mervis DB (cloud)\\
Cloudovou službu Mervis DB je možné provozovat **i samostatně**, bez Mervis SCADA. Přístupové údaje jsou v tomto případě generovány individuálně a jejich platnost je nutné předem dohodnout.
Máte-li zájem pouze o Mervis DB, [[https://www.unipi.technology/cs/kontakty|kontaktujte naše obchodní oddělení]] pro individuální nabídku.
Návod k nastavení jednotky pro ukládání dat do Mervis DB naleznete v návodu: [[cs:sw:01-mervis:storing-data-to-mervis-db-hidden|]]
----
Varianta lokální instalace\\
Službu Mervis DB lze provozovat i na lokálním serveru. Pro více informací kontaktujte naše [[info@unipi.technology|obchodní oddělení]].
/*
Minimální požadavky serveru Mervis DB pro lokální instalaci:
* OS: Windows 7 nebo Windows Server 2012 a nainstalovaný framework .NET4.5
* IIS - doporučeno
* HDD: 2 GB + prostor pro data
* RAM: 1 GB
*/
===== Migrace a správa dat =====
V rámci placené služby nabízíme také několik variant správy dat:
* Přesun dat mezi účty Mervis DB, včetně možné úpravy časové značky
* Import dat z Excelového, nebo CSV souboru
* Export dat do Excelového, nebo CSV souboru
* Vymazání nechtěných dat z Mervis DB
V případě zájmu o některou z výše zmíněných služeb kontaktujte naše [[info@unipi.technology|obchodní oddělení]].
\\
{{cs:sw:01-mervis:migrace_mervis-db_cz.png?direct|}}
===== Mervis DB Viewer =====
K prohlížení ukládaných dat z cloudové instance Mervis DB na serverech Unipi lze využít Mervis DB Viewer. Jedná se o on-line aplikaci, která se spojí s databází a zobrazí dle zadaných parametrů (např. časového rozmězí) data která obsahuje.
URL adresa: [[https://db.unipi.technology/viewer]].
{{cs:sw:01-mervis:db-mervis-info-viewer.png?direct|}}
===== API =====
Mervis DB nabízí otevřené rozhraní protokolu SOAP. Odpovídající WSDL je k ke stažení:
* {{:cs:sw:01-mervis:mervisdb_wsdl-2017-07-12.zip|}}
Pro speciální použití existují i další rozhraní pro komunikaci s Mervis DB - pro jejich použití a popis kontaktujte prosím [[cs:contact:00-start|technickou podporu]].
==== Seznam základních podporovaných funkcí ====
^ Funkce ^ Popis ^
| SaveData | Uloží jeden, nebo více záznamů z jedné nebo více proměnných. |
| GetData/GetDataAsync | Přečte jeden, nebo více záznamů z jedné nebo více proměnných. |
| GetParticularData/GetParticulatDataAsync | Optimalizovaná metoda pro čtení „speciálních“ dat - poslední hodnota, poslední hodnota po určitém časovém okamžiku atd. |
| GetVariables | Získá seznam proměnných. |
| GetAllVariables | |
| ServerAlive | Zastaralé |
| DeleteVariables | |
| DeleteData | |
| EnsureVariables | |
| GetTransformedData/GetTransformedDataAsync | Metoda čtení agregovaných výsledků s daným časovým obdobím, agregace může být min, max, integrál, vážený průměr, první, poslední a medián |
| GetServerVersion | |
| GetVariableStats | Zastaralé |
| GetVariableStatsAsync | Zastaralé |
| CheckCredentials | |
==== Vlastnosti objektu ====
* (UTC)TimeStamp - UTC časová značka záznamu
* GoodThrough - UTC časová značka konce platnosti konkrétního záznamu
* Interval - časová perioda (v sekundách), kdy má být zaznamenána další hodnota
==== Příklady použití ====
=== C# ===
{{cs:sw:01-mervis:mervis_db_csharp.png?direct|}}
Příklady ke stažení: \\
* {{cs:sw:01-mervis:mervisdb_getdata_example.zip|}}
* {{cs:sw:01-mervis:mervisdb_savedata_example.zip|}}
Příklad kódu: \\
using System;
using System.Linq;
using System.Threading.Tasks;
using MervisDb_GetData_Example.MervisDbService;
namespace MervisDb_GetData_Example {
class Program {
static void Main(string[] args) {
//
// Demo of asynchronous methods.
//
var task = Task.Run(async() => {
//
// Create access to the real server.
// Without SSL connections, you have to remove binding parameters "" in the App.config.
// The client is automatically generated from the WSDL file available here: https://kb.mervis.info/doku.php/en:mervis-db:10-api
//
using(HistoryDbAccessClient client = new HistoryDbAccessClient("HistoryAccess", "http://db.unipi.technology/dbaccess")) {
// Authentication credetials in the database.
Credentials credentials = new Credentials {
Name = "XXXX", Password = "YYYY"
};
// Specification of the variables through Key-Value.
// Here we use 2 variables.
KeyValuePair[][] keys = new KeyValuePair[][] {
new KeyValuePair[] {
new KeyValuePair {
Key = "DPGuid", Value = "338E2882-D72B-4D17-A241-73E8BC30F458"
}, new KeyValuePair {
Key = "StationName", Value = "AAABBB"
}
},
new KeyValuePair[] {
new KeyValuePair {
Key = "DPGuid", Value = "CC80211D-3D29-4CC2-91A2-F69483D566B5"
}, new KeyValuePair {
Key = "StationName", Value = "AAABBB"
}
}
};
// From-To dates. The dates must be specified in the UTC time zone.
DateTime utcTo = DateTime.UtcNow;
DateTime utcFrom = DateTime.UtcNow.AddDays(-1);
// Retrieving the data goes through cycling of values and variables. The server returns recommended values needed for the the next cycle.
int variableOffset = 0; // the offset of the variable
int variableCount = 10; // maximal number of variables returned in one request
int valueOffset; // the offset of the value
int valueCount = 1000; // maximal values in on request
Console.WriteLine("Reading values...");
do {
valueOffset = 0;
do {
// Execute the request.
var result = await client.GetDataAsyncAsync(credentials, keys, utcFrom, utcTo, variableOffset, variableCount, valueOffset, valueCount);
// Check the return code. "0;OK" is what we want.
if (!result.ReturnCode.StartsWith("0;")) {
Console.WriteLine("Error on reading: {0}", result.ReturnCode);
}
// Cycle through the data and print it out.
foreach(var valRecord in result.Data) {
Console.WriteLine("Variable: {0}", String.Concat(valRecord.Keys.Select((i) => {
return String.Format("{0}={1}; ", i.Key, i.Value);
})));
foreach(var value in valRecord.Vals) {
Console.WriteLine("{0}->{1} [{2}] {3}", value.Ts, value.Gt, value.Hvt, value.Dv /* Use value type according to the Hvt (History Value Type) */ );
}
}
valueOffset = result.NextValueOffset;
variableOffset = result.NextVariableOffset;
}
while (valueOffset != -1);
}
while (variableOffset != -1);
}
});
Console.WriteLine("DB communication is running in background");
try {
task.Wait();
} catch (Exception exc) {
Console.WriteLine("Exception: {0}", exc.ToString());
}
Console.WriteLine("DB communication finished");
Console.ReadLine();
}
}
}
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using MervisDb_SaveData_Example.MervisDbService;
namespace MervisDb_SaveData_Example
{
class Program
{
static void Main(string[] args)
{
//
// Demo of asynchronous methods.
//
var task = Task.Run(async () =>
{
//
// Create access to the real server.
// Without SSL connections, you have to remove binding parameters "" in the App.config.
// The client is automatically generated from the WSDL file available here: https://kb.mervis.info/doku.php/en:mervis-db:10-api
//
using (HistoryDbAccessClient client = new HistoryDbAccessClient("HistoryAccess", "http://db.unipi.technology/dbaccess"))
{
// Authentication credetials in the database.
Credentials credentials = new Credentials { Name = "XXXX", Password = "YYYY" };
// Adding records...
List records = new List();
DateTime utcTimeStamp = new DateTime(2018, 1, 1, 12, 0, 0, DateTimeKind.Utc);
// Each value is stored in a ValueRecord structure
ValueRecord rec = new ValueRecord();
rec.UtcTimeStamp = utcTimeStamp; // time stamp of the value, UTC date time must be used
rec.HistoryValueType = HistoryValueType.Double; // type of the value
rec.DoubleValue = 23.4; // value itself
rec.Interval = 60.0; // sampling period in seconds. When the difference of timestamps of subsequent values if greater than 1.1 multiple of the interval, the data should be considered incomplete.
rec.Keys = new KeyValuePair[] // identification of the variable. At least one key-value pair must be "IsKey" to identify a variable.
{
new KeyValuePair { IsKey = true, Key = "Root", Value = "Building A"},
new KeyValuePair { IsKey = true, Key = "Level1", Value = "Floor 1"},
new KeyValuePair { IsKey = true, Key = "Level2", Value = "Room 7"},
new KeyValuePair { IsKey = true, Key = "Level3", Value = "Temperature"},
new KeyValuePair { IsKey = false, Key = "Description", Value = "Temperature in the room 7"},
new KeyValuePair { IsKey = false, Key = "Unit", Value = "°C"},
};
records.Add(rec);
// Save data method returns the number of stored records
int recordsSaved = await client.SaveDataAsync(credentials, records.ToArray());
Console.WriteLine("Records saved: {0}", recordsSaved);
}
});
Console.WriteLine("DB communication is running in background");
try
{
task.Wait();
}
catch (Exception exc)
{
Console.WriteLine("Exception: {0}", exc.ToString());
}
Console.WriteLine("DB communication finished");
Console.ReadLine();
}
}
}
using System;
using System.Linq;
using System.Threading.Tasks;
using MervisDb_GetTransformedData_Example.MervisDbService;
namespace MervisDb_GetTransformedData_Example
{
class Program
{
static void Main(string[] args)
{
//
// Demo of asynchronous method.
//
var task = Task.Run(async () =>
{
//
// Create access to the real server.
// Without SSL connections, you have to remove binding parameters "" in the App.config.
// The client is automatically generated from the WSDL file available here: https://kb.mervis.info/doku.php/en:mervis-db:10-api
//
using (HistoryDbAccessClient client = new HistoryDbAccessClient("HistoryAccess", "http://db.unipi.technology/dbaccess"))
{
// Authentication credentials in the database.
Credentials credentials = new Credentials { Name = "XXXXX", Password = "YYYYY" };
// Specification of the variables through Key-Value.
// Here we use 2 variables.
KeyValuePair[][] variableKeys = new KeyValuePair[][] {
new KeyValuePair[] {
new KeyValuePair (false, /*Key*/ "DPGuid", /*Value*/ "338E2882-D72B-4D17-A241-73E8BC30F458"),
new KeyValuePair (false, /*Key*/ "StationName", /*Value*/ "AAABBB")
},
new KeyValuePair[] {
new KeyValuePair (false, /*Key*/ "DPGuid", /*Value*/ "CC80211D-3D29-4CC2-91A2-F69483D566B5"),
new KeyValuePair (false, /*Key*/ "StationName", /*Value*/ "AAABBB")
}
};
// Aggregation request
var aggregation = new AggregationRequest();
aggregation.Types = new AggregationType[] { AggregationType.Last };
aggregation.Interpolation = InterpolationType.None;
//aggregation.MaxNeighborDistance = ..only for interpolation;
aggregation.IsoPattern = new string[] { "PT15M" }; // 15 min period (ISO 8601 duration pattern)
aggregation.From = new DateTime(2018, 11, 24, 0, 0, 0, 0, DateTimeKind.Unspecified);
aggregation.To = new DateTime(2018, 11, 25, 0, 0, 0, 0, DateTimeKind.Unspecified);
aggregation.TimeZone = @"Europe/Prague";
// Retrieving the data goes through cycling of intervals and variables. The server returns recommended intervals needed for the the next cycle.
int variableOffset = 0; // the offset of the variable
int variableCount = 10; // maximal number of variables returned in one request
int intervalOffset; // the offset of the interval
int intervalCount = 1000; // maximal values in on request
Console.WriteLine("Reading values...");
do
{
intervalOffset = 0;
do
{
// Execute the request.
var result = await client.GetTransformedDataAsyncAsync(credentials, aggregation, variableKeys, variableOffset, variableCount, intervalOffset, intervalCount);
// Check the return code. "0;OK" is what we want.
if (!result.ReturnCode.StartsWith("0;"))
{
Console.WriteLine("Error on reading: {0}", result.ReturnCode);
}
// Cycle through the data and print it out.
if (result.Data != null)
{
foreach (VariableAggregate vag in result.Data)
{
Console.WriteLine("Variable: {0}", String.Concat(vag.Keys.Select((i) => { return String.Format("{0}={1}; ", i.Key, i.Value); })));
foreach (Interval value in vag.Data)
{
Console.Write(" {0}->{1} quality: {2:0.00} ", value.Begin, value.End, value.DataQuality);
if (value.Last != null)
{
Console.Write(" Last Value: {0} (stamp {1}, origin {2})", value.Last.Value, value.Last.Stamp, value.Last.Origin);
}
Console.WriteLine();
}
}
}
variableOffset = result.NextVariableOffset;
intervalOffset = result.NextIntervalOffset;
} while (intervalOffset != -1);
} while (variableOffset != -1);
}
});
Console.WriteLine("DB communication is running in background");
try
{
task.Wait();
}
catch (Exception exc)
{
Console.WriteLine("Exception: {0}", exc.ToString());
}
Console.WriteLine("DB communication finished");
Console.ReadLine();
}
}
}
=== Matlab ===
{{cs:sw:01-mervis:mervisdb_matlab_api.png?direct|}}
== Podporované funkce: ==
^ Funkce ^ Popis ^
| SaveData | Uloží jeden, nebo více záznamů z jedné nebo více proměnných. |
| GetData | Přečte jeden, nebo více záznamů z jedné nebo více proměnných. |
| GetDataUnmerged | Přečte jeden, nebo více záznamů z jedné nebo více proměnných. Umožňuje nastavit více možností než funkce GetData. |
| GetDataOrigin | Přečte data přesně tak, jak jsou uložena v databázi. |
| DeleteVariable | Smažte celou proměnnou nebo určitý interval. |
| GetRequiredTimestamp | Získej časovou značku v závislosti na nastavení vstupu. |
== Toolbox ==
Pro komunikaci Matlabu s Mervis DB potřebujete nainstalovat toolbox:
* {{cs:sw:01-mervis:mervisdb_matlabtoolbox.zip|}}
* Zobrazení nápovědy ke každé z funkcí je možné:
help MervisDatabse.supported_function_name
== Kód ==
% Instance of Mervis DB
mervisDB = MervisDatabase('username', 'password', 'dbUrl');
% Time interval definition
from = localMatlab2utcMatlab(datenum(2017, 1, 1)); %1.1.2017 in utc
to = localMatlab2utcMatlab(datenum(2017, 31, 1)); %31.1.2017 in utc
samplePeriod = 5*60; % 5 minutes
outputTimeZone = 'Local'; % possible 'Local' or 'Utc' parameter;
% Specifying varibles to download
varKeys1 = {'DPGuid', '338E2882-D72B-4D17-A241-73E8BC30F458';...
'StationName', 'XXXXXXX'}; % Keys definition of first variable
varKeys2 = {'DPGuid', 'CC80211D-3D29-4CC2-91A2-F69483D566B5';...
'StationName', 'YYYYYYY'}; % Keys definition of second variable
variable1 = MervisDbVariable(varKeys1); % Create MervisDbVariable object from defined keys
variable2 = MervisDbVariable(varKeys2);
arrayOfVarKeys = [variable1; variable2]; % array of MervisDbVariables objects
% help for function getData
help MervisDatabase.getData
% Download required data
[data, time] = mervisDB.getData(arrayOfVarKeys, from, to, samplePeriod, outputTimeZone);
% Get all variables with defined keys
allVaribales = mervisDB.getAllVars(varKeys1);
=== PHP ===
== Kód ==
SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_GZIP,
'trace' => 0,
'features' => SOAP_SINGLE_ELEMENT_ARRAYS
));
$soapClient->__setLocation('http://db.unipi.technology/dbaccess');
$credentials = array(
'Name' => 'XXXXXXX',
'Password' => 'YYYYYYY'
);
$utcTZ = new DateTimezone('UTC'); //all time realted values are expected in UTC
$utcFrom = new DateTime('-120minutes', $utcTZ); //
$utcTo = new DateTime('now', $utcTZ); //
$valOffset = 0;
$valCount = 20; //how many values should be returned in one request at most. Recommended value: 5000
$varOffset = 0;
$varCount = 4; //how many variable should be returned in on request at most
$variablesKey = array(
array(
array(
'IsKey' => true,
'Key' => 'DPGuid',
'Value' => '338E2882-D72B-4D17-A241-73E8BC30F458'
),
array(
'IsKey' => true,
'Key' => 'StationName',
'Value' => 'AAAAAAAAAA'
)
),
array(
array(
'IsKey' => true,
'Key' => 'DPGuid',
'Value' => 'CC80211D-3D29-4CC2-91A2-F69483D566B5'
),
array(
'IsKey' => true,
'Key' => 'StationName',
'Value' => 'BBBBBBB'
)
)
);
echo "Reading values from: {$utcFrom->format('c')} to: {$utcTo->format('c')}\n\n";
$counter = 0;
do {
$response = null;
$valOffset = 0;
do {
$response = $soapClient->GetData(array(
'credentials' => $credentials,
'variablesKey' => $variablesKey,
'utcFrom' => $utcFrom->format('Y-m-d\TH:i:s\Z'),
'utcTo' => $utcTo->format('Y-m-d\TH:i:s\Z'),
'valueOffset' => $valOffset,
'valueCount' => $valCount,
'variableCount' => $varCount,
'variableOffset' => $varOffset
));
$valOffset = $response->nextValueOffset;
$varOffset = $response->nextVariableOffset;
foreach ($response->GetDataResult->Mvr as $varArray) {
foreach ($varArray->Keys->KeyValuePair as $kvp) //the set of keys depends on the source of the data
{
if ($kvp->Key == 'DPName') {
echo "\n{$kvp->Value}\n";
$counter++;
}
}
if (isset($varArray->Vals->I)) {
foreach ($varArray->Vals->I as $val) {
echo " t: {$val->Ts} Interval: {$val->Ivl} {$valOffset} {$varOffset}\n";
}
} else {
echo "empty\n";
}
}
} while ($response->nextValueOffset != -1); //-1 - no more data available
} while ($response->nextVariableOffset != -1); //-1 - no more data available
}
catch (Exception $e) {
print_r($e);
}
?>
/*
===== Excel Exporter =====
K dispozici je také nástroj pro příkazovou řádku s názvem Excel Exporter, který může z vašich dat v Mervis DB vytvořit plně přizpůsobitelný soubor aplikace Microsoft Excel.
Jeho základem je šablona XLSX souboru, ve kterém můžete pomocí speciální syntaxe umisťovat data z Mervis DB.
==== Příklad: ====
V tomto příkladu si ukážeme, jak exportovat jednu proměnnou z Mervis DB do Excelového souboru.
Obrázek
=== Soubor s konfigurací ===
Nejprve je třeba vytvořit konfigurační soubor XML, kde se definuje mapování mezi sadou klíčů popisujících jednotlivé proměnné Mervis DB a některými názvy proměnných, které budou použity později v šabloně aplikace Excel.
Můžete také definovat název výstupního souboru a také zda má být soubor pouze aktualizován nebo přepsán.
exceldemo.xlsx
exceldemo_[yyyy-MM-dd_HH-mm].xlsx
false
=== Excelová šablona ===
Pomocí jednoduchého jazyka šablony můžete definovat, které hodnoty z Mervis DB se maji umístit na jaké místo ve výstupním souboru aplikace Excel.
[YEAR:2016|MONTH:1|DAY:15|HOUR:12|MINUTE:0|VARIABLE:OutsideTemperature]
Libovolnou z hodnot definujících čas lze vynechat a bude nahrazena aktuálním datem, časem nebo hodnotami předanými prostřednictvím parametrů příkazového řádku.
obrázek
=== Spuštění exportéru ===
.\ESG.RcWareDb.DataExporter\ESG.RcWareDb.DataExporter.exe tmpPath:"ExcelDemo.xml" srvUrl:"http://db.unipi.technology/dbaccess" srvUser:"exceldemo" srvPsw:"pfi4cj4qrj" timeTolerance:300 toleranceType:before
Pro více informací spusťte:
.\ESG.RcWareDb.DataExporter\ESG.RcWareDb.DataExporter.exe --help
=== Výstup ===
Výstupní soubor je definován v konfiguračním souboru XML. Ukázkový výstup by měl vypadat následovně:
obrázek
=== Celý příklad ke stažení: ===
Příklad: excelexporterdemo.zip
*/