DHI.Services.MIKECloud for Time Series — Internal Developer Guide¶
Use MIKECloud as a Time Series backend. CRUD + values over
Timeseriesdatasets. For platform/auth/path rules, see MIKECloud Core.
What you get¶
Repository
DHI.Services.Provider.MIKECloud.GroupedTimeSeriesRepositoryGrouped & updatable repo over MIKECloud:- Read: list series/groups, fetch entities, values (optionally by range)
- Write: create series, append/set, remove ranges, delete series
SDK clients under the hood: ProjectClient, DatasetClient, TimeSeriesClient
Identity & path rules¶
FullName (ID) format:
<dataset>/<timeSeriesName>
<sub1>/<dataset>/<timeSeriesName>
<sub1>/<sub2>/<dataset>/<timeSeriesName>
- Leading
/is allowed; provider trims it. - Last segment = time series name; the preceding path resolves a Timeseries dataset.
- Add: creates missing subprojects (folders); the dataset must already exist (not auto-created).
Groups & listing
- Datasets are shown as groups and end with
/when listed: e.g.,/Ops/North/Telemetry/. - Append
;nonrecursiveto restrict list calls to direct children.
Capabilities & behaviors¶
| Operation / Area | Support | Notes |
|---|---|---|
| Get(series) | ✓ | Populates Unit, Quantity via EUMWrapper; DataType when present |
| GetValues(series [from,to]) | ✓ | Returns TimeSeriesDataWFlag<double,object>; flags are null |
| Add(series) | ✓ | Creates MIKECloud time series (EUM-mapped unit/item), then uploads initial values |
| SetValues(series, data) | ✓ | Appends values; no client-side de-dup |
| RemoveValues(series, from,to) | ✓ | Deletes values in range (or all with min/max) |
| Remove(series) | ✓ | Deletes series |
| Update(series) | ✓ | Current SDK path = delete + recreate (reads existing values, re-adds with new headers/metadata) |
| GetAll / GetByGroup / GetFullNames | ✓ | Lists across subprojects; datasets & subprojects end with / |
| Contains(series) | ✓ | Query by Item == name within dataset |
| ContainsGroup(path) | ✓ | True if dataset or path exists |
Type & unit mapping
- EUM mapping both ways:
- Write:
EUMWrapper.GetUnitTag(unitAbbrev, out unitKey)→eumUnitEUMWrapper.GetItemTypeTag(quantityKey, out itemKey)→eumItem - Read:
eumGetUnitAbbreviation,eumGetItemTypeKey→Unit,Quantity
- Write:
TimeSeriesDataType: numeric values align with MIKECloud; semantics (resample, smoothing, etc.) live in your analysis code/Web API.
Time: use UTC for consistency.
Connecting¶
Direct (code)
var repo = new GroupedTimeSeriesRepository(
"apiKey=<APIKEY>;projectId=<PROJECTID>;environment=Prod");
var svc = new DHI.Services.TimeSeries.GroupedUpdatableTimeSeriesService<string,double>(repo);
ServiceLocator.Register(svc, "mc-ts");
Web API (Connections module)
{
"$type": "DHI.Services.TimeSeries.WebApi.GroupedUpdatableTimeSeriesServiceConnection, DHI.Services.TimeSeries.WebApi",
"RepositoryType": "DHI.Services.Provider.MIKECloud.GroupedTimeSeriesRepository, DHI.Services.Provider.MIKECloud",
"ConnectionString": "apiKey=[env:MIKECLOUD_APIKEY];projectId=[env:MIKECLOUD_PROJECT];environment=Prod",
"Name": "Time Series via MIKECloud",
"Id": "mc-ts"
}
Routes then appear as: /api/timeseries/mc-ts/...
Code recipes¶
Create, write, read values¶
var tsRepo = new GroupedTimeSeriesRepository(conn);
var ts = new TimeSeries<string,double>(
id: null,
name: "WaterLevel",
group: "/Hydro/Observations/") {
Unit = "m",
Quantity = "WL",
DataType = TimeSeriesDataType.Instantaneous,
Data = new TimeSeriesData<double>()
};
ts.Data.Append(new DateTime(2025,9,1,0,0,0, DateTimeKind.Utc), 1.23);
tsRepo.Add(ts);
var values = tsRepo.GetValues("/Hydro/Observations/WaterLevel",
new DateTime(2025,9,1), new DateTime(2025,9,30)).Value;
Replace a window (avoid overlaps)¶
tsRepo.RemoveValues("/Hydro/Observations/WaterLevel",
new DateTime(2025,9,2), new DateTime(2025,9,3));
tsRepo.SetValues("/Hydro/Observations/WaterLevel", newData);
Troubleshooting & notes¶
- Dataset existence: provider creates subprojects but not datasets. Provision the
Timeseriesdataset first. - Project not found / bad env: constructor throws
ArgumentException. - Listings:
GetAll()& recursiveGetFullNames()can span large trees; prefer;nonrecursiveor targeted groups. - Update: current path is delete+recreate—if you only change values, prefer
RemoveValues+SetValues.