Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
en:mervis-db:10-api [2017/06/14 16:35]
m.chlupac
en:mervis-db:10-api [2026/07/14 10:36] (current)
z.moustis
Line 1: Line 1:
 +====== API ======
 +
 +Mervis DB supports open [[https://en.wikipedia.org/wiki/SOAP|SOAP]] API described by this WSDL:
 +
 +  * {{:en:mervis-db:mervisdb_wsdl-2026-04-01.xml|mervisdb_wsdl-2026-04-01.xml}}
 +
 +Contact [[:en:help:20-support|technical support]] for other non-public APIs that can be used for your projects.
 +
 ===== List of supported functions ===== ===== List of supported functions =====
  
 ^Function^Description| ^Function^Description|
 ^SaveData|Save one or multiple records from one or multiple variables| ^SaveData|Save one or multiple records from one or multiple variables|
-^GetData|Read one or multiple records from one or multiple variables.| +^GetData/GetDataAsync|Read one or multiple records from one or multiple variables.| 
-^GetParticularData|Optimized method for reading of "special" data - last value, last value after certain time moment etc.|+^GetParticularData/GetParticulatDataAsync|Optimized method for reading of "special" data - last value, last value after certain time moment etc.|
 ^GetVariables|Get the list of variables.| ^GetVariables|Get the list of variables.|
-^ | | +^GetAllVariables| | 
-^ | |+^ServerAlive|Obsolete| 
 +^DeleteVariables| | 
 +^DeleteData| | 
 +^ReplaceData|Delete data from time range and save one or multiple records from one or multiple variables in one API call| 
 +^EnsureVariables| | 
 +^GetTransformedData/GetTransformedDataAsync|Method for reading of aggregated results with given time period, the aggregation may be Min, Max, Integral, Weighted average, First, Last and Median | 
 +^GetServerVersion| | 
 +^GetVariableStats|Obsolete| 
 +^GetVariableStatsAsync|Obsolete| 
 +^CheckCredentials| |
  
-===== Examples :todo: =====+===== Object Properties ===== 
 +  * (UTC)TimeStamp - UTC time stamp of the record 
 +  * GoodThrough - UTC time stamp of the end of validity of particular record 
 +  * Interval - period of time (in seconds) when next value should be recorded
  
-  * C# 
-  * PHP 
-  * Matlab 
  
-\\+===== Examples =====
  
 +==== C# ====
  
 +{{ :en:mervis-db:mervis_db_csharp.png?direct&800 |}}
 +
 +=== Download ===
 +
 +
 +{{ :en:mervis-db:mervisdb_getdata_example.zip |}}\\
 +{{ :en:mervis-db:mervisdb_savedata_example.zip |}}
 +
 +=== Code ===
 +
 +
 +<code csharp MervisDB_GetData_Example.cs>
 +using ESG.Core.Access.Client;
 +using ESG.Db.Server.Shared;
 +using ESG.Db.ServerAccess;
 +using System;
 +using System.Collections.Generic;
 +using System.Linq;
 +using System.Threading.Tasks;
 +
 +namespace DbClientTest
 +{
 + class Program
 + {
 + static async Task Main(string[] args)
 + {
 + try
 + {
 + //
 + // Create access to the real server.
 + // Without SSL connections, you have to remove binding parameters "<security mode="Transport"/>" 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(HistoryDbAccessClient.EndpointConfiguration.HistoryAccess, "https://localhost:9876/RcWareDbAccess"))
 + {
 + // 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.
 + ESG.Db.Server.Shared.KeyValuePair[][] keys = new ESG.Db.Server.Shared.KeyValuePair[][] {
 + new ESG.Db.Server.Shared.KeyValuePair[] {
 + new ESG.Db.Server.Shared.KeyValuePair(true, "DPGuid","338E2882-D72B-4D17-A241-73E8BC30F458"),
 + new ESG.Db.Server.Shared.KeyValuePair(true, "StationName", "AAABBB")
 + },
 +    new ESG.Db.Server.Shared.KeyValuePair[] {
 + new ESG.Db.Server.Shared.KeyValuePair(true, "DPGuid", "CC80211D-3D29-4CC2-91A2-F69483D566B5"),
 + new ESG.Db.Server.Shared.KeyValuePair(true, "StationName", "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.Values)
 + {
 + Console.WriteLine("{0}->{1} [{2}] {3}", value.UtcTimeStamp, value.GoodThrough, value.HistoryValueType, value.DoubleValue /* Use value type according to the Hvt (History Value Type) */ );
 + }
 + }
 +
 + valueOffset = result.NextValueOffset;
 + variableOffset = result.NextVariableOffset;
 + }
 + while (valueOffset != -1);
 + }
 + while (variableOffset != -1);
 + }
 +
 + }
 + catch (Exception exc)
 + {
 + Console.WriteLine("Exception: {0}", exc.ToString());
 + }
 +
 + Console.WriteLine("DB communication finished");
 +
 + Console.ReadLine();
 + }
 +
 + }
 +}
 +</code>
 +
 +<code csharp MervisDB_SaveData_Example.cs>
 +using System;
 +using System.Collections.Generic;
 +using System.Threading.Tasks;
 +using MervisDb_SaveData_Example.MervisDbService;
 +
 +namespace MervisDb_SaveData_Example
 +{
 + class Program
 + {
 + static async Task Main(string[] args)
 + {
 + try
 + {
 + //
 + // Create access to the real server.
 + // Without SSL connections, you have to remove binding parameters "<security mode="Transport"/>" 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(HistoryDbAccessClient.EndpointConfiguration.HistoryAccess, "https://localhost:9876/RcWareDbAccess"))
 + {
 + // Authentication credetials in the database.
 + Credentials credentials = new Credentials { Name = "XXXX", Password = "YYYY" };
 +
 + // Adding records...
 + List<ValueRecord> records = new List<ValueRecord>();
 +
 + 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 ESG.Db.Server.Shared.KeyValuePair[] // identification of the variable. At least one key-value pair must be "IsKey" to identify a variable.
 + {
 + new ESG.Db.Server.Shared.KeyValuePair(true, "Root", "Building A"),
 + new ESG.Db.Server.Shared.KeyValuePair(true, "Level1", "Floor 1"),
 + new ESG.Db.Server.Shared.KeyValuePair(true, "Level2", "Room 7"),
 + new ESG.Db.Server.Shared.KeyValuePair(true, "Level3", "Temperature"),
 + new ESG.Db.Server.Shared.KeyValuePair(false, "Description", "Temperature in the room 7"),
 + new ESG.Db.Server.Shared.KeyValuePair(false, "Unit", "°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);
 + }
 +
 + }
 + catch (Exception exc)
 + {
 + Console.WriteLine("Exception: {0}", exc.ToString());
 + }
 +
 + Console.WriteLine("DB communication finished");
 +
 + Console.ReadLine();
 + }
 + }
 +}
 +</code>
 +
 +<code csharp MervisDb_ReplaceData_Example.cs>
 +using ESG.Core.Access.Client;
 +using ESG.Db.Server.Shared;
 +using ESG.Db.ServerAccess;
 +using System;
 +using System.Collections.Generic;
 +
 +namespace DbClientTest
 +{
 + class Program
 + {
 + static async Task Main(string[] args)
 + {
 + RcWareDbClient dbClient = new RcWareDbClient(false, "RcWareDbAccess", new Uri("http://localhost:9876/RcWareDbAccess"));
 + dbClient.Credentials = new ESG.Db.Server.Shared.Credentials("xxxxxxx", "xxxxxxx");
 +
 + DateTime utcNow = DateTime.UtcNow.Subtract(TimeSpan.FromMinutes(5));
 +
 + ESG.Db.Server.Shared.KeyValuePair[] varKeysNew = new ESG.Db.Server.Shared.KeyValuePair[]
 + {
 + new ESG.Db.Server.Shared.KeyValuePair(true, "DPGuid", "51111111-1234-1234-1234-123456789012"),
 + new ESG.Db.Server.Shared.KeyValuePair(true, "StationName", "db_replace_test")
 + };
 +
 + ESG.Db.Server.Shared.KeyValuePair[] varKeys1 = new ESG.Db.Server.Shared.KeyValuePair[]
 + {
 + new ESG.Db.Server.Shared.KeyValuePair(true, "DPGuid", "60ace716-5e1e-4cf8-ab05-947dce0caf77"),
 + new ESG.Db.Server.Shared.KeyValuePair(true, "SoftPlcRtId", "db_replace_test")
 + };
 +
 + ESG.Db.Server.Shared.KeyValuePair[] varKeys = varKeys1;
 +
 + // generate some records
 + List<ValueRecord> recsToSave = new List<ValueRecord>();
 + TimeSpan recsLength = TimeSpan.FromMinutes(2);
 + int recsPerMinute = 4;
 +
 + Random r = new Random((int)DateTime.UtcNow.Ticks);
 + double rBase = r.NextDouble() * 10;
 +
 + for (int i = 0; i < (recsLength.TotalSeconds / 60) * recsPerMinute; i++)
 + {
 + recsToSave.Add(new ValueRecord(utcNow - recsLength + TimeSpan.FromMinutes(i * (1.0 / recsPerMinute)), rBase + ((i % 2) + 1) * (-4)));
 + recsToSave[recsToSave.Count - 1].Keys = varKeys;
 + recsToSave[recsToSave.Count - 1].Interval = 60 / recsPerMinute;
 +
 + recsToSave.Add(new ValueRecord(utcNow - recsLength + TimeSpan.FromMinutes(i * (1.0 / recsPerMinute)), rBase + ((i % 2) + 1) * (-4)));
 + recsToSave[recsToSave.Count - 1].Keys = varKeysNew;
 + recsToSave[recsToSave.Count - 1].Interval = 60 / recsPerMinute;
 + }
 +
 + var res = await dbClient.ReplaceDataAsync(new List<ESG.Db.Server.Shared.KeyValuePair[]> { varKeys }, utcNow.Subtract(recsLength), utcNow, recsToSave.ToArray());
 + }
 + }
 +}
 +</code>
 +
 +<code csharp MervisDb_GetTransformedData_Example.cs>
 +using System;
 +using System.Linq;
 +using System.Threading.Tasks;
 +using MervisDb_GetTransformedData_Example.MervisDbService;
 +
 +namespace MervisDb_GetTransformedData_Example
 +{
 + class Program
 + {
 + static async Task Main(string[] args)
 + {
 + //
 + // Create access to the real server.
 + // Without SSL connections, you have to remove binding parameters "<security mode="Transport"/>" 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
 + //
 + try
 + {
 + using (HistoryDbAccessClient client = new HistoryDbAccessClient(HistoryDbAccessClient.EndpointConfiguration.HistoryAccess, "http://localhost:9876/RcWareDbAccess"))
 + {
 + // 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.
 + ESG.Db.Server.Shared.KeyValuePair[][] variableKeys = new ESG.Db.Server.Shared.KeyValuePair[][] {
 + new ESG.Db.Server.Shared.KeyValuePair[] {
 + new ESG.Db.Server.Shared.KeyValuePair (/*IsKeyId*/ false, /*Key*/ "DPGuid", /*Value*/ "338E2882-D72B-4D17-A241-73E8BC30F458"),
 + new ESG.Db.Server.Shared.KeyValuePair (/*IsKeyId*/ false, /*Key*/ "StationName", /*Value*/ "AAABBB")
 + },
 + new ESG.Db.Server.Shared.KeyValuePair[] {
 + new ESG.Db.Server.Shared.KeyValuePair (/*IsKeyId*/ false, /*Key*/ "DPGuid", /*Value*/ "CC80211D-3D29-4CC2-91A2-F69483D566B5"),
 + new ESG.Db.Server.Shared.KeyValuePair (/*IsKeyId*/ 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");
 +
 + }
 + catch (Exception exc)
 + {
 + Console.WriteLine("Exception: {0}", exc.ToString());
 + }
 +
 + Console.WriteLine("DB communication finished");
 +
 + Console.ReadLine();
 + }
 + }
 +}
 +</code>
 +
 +
 +==== Matlab ====
 +
 +{{  :en:mervis-db:mervisdb_matlab_api.png?direct&800  }}
 +
 +=== Supported functions ===
 +
 +^Function^Description|
 +^SaveData|Save one or multiple records from one or multiple variables|
 +^GetData|Read one or multiple records from one or multiple variables.|
 +^GetDataUnmerged|Read one or multiple records from one or multiple variables. Allow more setting options than GetData function|
 +^GetDataOrigin|Read data exactly as are stored in the database.|
 +^DeleteVariable|Delete entire variable or some certain interval.|
 +^GetRequiredTimestamp|Get time stamp depending on input options.|
 +
 +=== Toolbox ===
 +
 +You need to import specialized toolbox to communicate with Mervis DB from Matlab:
 +
 +  * {{:en:mervis-db:mervisdb_matlabtoolbox.zip|mervisdb_matlabtoolbox.zip}}.
 +  * There is a help available for all toolbox functions. To display the help use:
 +
 +<code matlab>
 +help MervisDatabase.supported_function_name
 +</code>
 +
 +=== Code ===
 +
 +
 +
 +<code matlab MervisDB_GetData_example.m>
 +% 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);
 +</code>
 +
 +==== PHP ====
 +
 +=== Code ===
 +
 +
 +<code php MervisDB_GetData_example.php>
 +<?php
 +/*
 +Mervis DB PHP example - getdata
 +*/
 +try {
 +
 +  $soapClient = new SoapClient('./wsdl/singlewsdl.xml', array(
 +    'compression' => SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_GZIP,
 +    'trace' => 0,
 +    'features' => SOAP_SINGLE_ELEMENT_ARRAYS
 +  ));
 +  $soapClient->__setLocation('http://localhost:9876/RcWareDbAccess');
 +
 +  $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);
 +}
 +?>
 +</code>
 +
 +\\
  • © Energocentrum Plus, s.r.o. 2017 - 2026