====== 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 */