📘 Návod: Načítání historie (Mervis server vs. naše DB) rozbalit / sbalit
Historie projektu může být uložená buď v naší DB (interní sběr, historySource: "internal"), nebo na Mervis serveru (historySource: "mervis_db"). Klient (web i iOS) nemá nic větvit — vždy volá jeden endpoint POST /api/history/unified, který sám podle nastavení projektu vybere zdroj a vrátí stejný tvar dat.
1) (volitelně) Zjisti zdroj a dostupné datapointy
Které projekty jsou Mervis a které interní – jedním voláním pro celou firmu:
curl "https://api.ldsadmin.cz/api/history/project-settings-batch?companyId=30" \
-H "Authorization: Bearer <JWT>"
# → { "data": { "123": "mervis_db", "124": "internal" } }
Seznam datapointů (GUID + název + jednotka) pro výběr v UI – funguje pro oba zdroje:
curl "https://api.ldsadmin.cz/api/history/internal-dps/123" \
-H "Authorization: Bearer <JWT>"
# → { "data": [ { "dpId": "<guid>", "dpName": "Napětí L1", "unit": "V", "elementKey": "..." } ] }
2) Načti historii (jeden endpoint pro Mervis i naši DB)
curl -X POST "https://api.ldsadmin.cz/api/history/unified" \
-H "Authorization: Bearer <JWT>" \
-H "Content-Type: application/json" \
-d '{
"projectId": 123,
"dpIds": ["<mervis-guid-1>", "<mervis-guid-2>"],
"from": "2026-06-26T00:00:00Z",
"to": "2026-06-27T00:00:00Z"
}'
Odpověď – stejná struktura pro oba zdroje
Liší se jen pole source ("mervis_db" = z Mervisu, "internal" = z naší DB):
{
"success": true,
"source": "mervis_db", // nebo "internal"
"projectId": 123,
"datapointCount": 2,
"truncated": 50, // přítomno jen když jsi poslal > 50 dpIds
"data": [
{
"dpId": "<guid>",
"dpName": "Napětí L1",
"unit": "V",
"values": [
{ "ts": "2026-06-26T00:01:00Z", "value": 231.4 },
{ "ts": "2026-06-26T00:02:00Z", "value": 230.9 }
]
}
]
}
iOS (Swift / URLSession) – dávkování po 50 a retry na 504
struct HistoryPoint: Decodable { let ts: String; let value: Double?; let valueText: String? }
struct HistorySeries: Decodable { let dpId: String; let dpName: String?; let unit: String?; let values: [HistoryPoint] }
struct HistoryResponse: Decodable { let success: Bool; let source: String?; let data: [HistorySeries] }
func loadHistory(projectId: Int, dpIds: [String], from: Date, to: Date,
token: String) async throws -> [HistorySeries] {
let iso = ISO8601DateFormatter()
var result: [HistorySeries] = []
// Server limituje na 50 datapointů → posílej po dávkách.
for chunk in stride(from: 0, to: dpIds.count, by: 50).map({ Array(dpIds[$0..<min($0+50, dpIds.count)]) }) {
let url = URL(string: "https://api.ldsadmin.cz/api/history/unified")!
var req = URLRequest(url: url)
req.httpMethod = "POST"
req.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
req.setValue("application/json", forHTTPHeaderField: "Content-Type")
req.timeoutInterval = 120 // Mervis SOAP bývá pomalý
req.httpBody = try JSONSerialization.data(withJSONObject: [
"projectId": projectId,
"dpIds": chunk,
"from": iso.string(from: from),
"to": iso.string(from: to)
])
let (data, resp) = try await URLSession.shared.data(for: req)
let code = (resp as? HTTPURLResponse)?.statusCode ?? 0
// 504 = Mervis je pomalý/timeout → zkus menší rozsah (např. půlku)
if code == 504 {
let mid = from.addingTimeInterval(to.timeIntervalSince(from) / 2)
result += try await loadHistory(projectId: projectId, dpIds: chunk, from: from, to: mid, token: token)
result += try await loadHistory(projectId: projectId, dpIds: chunk, from: mid, to: to, token: token)
continue
}
guard code == 200 else { throw URLError(.badServerResponse) }
result += try JSONDecoder().decode(HistoryResponse.self, from: data).data
}
return result
}
💡 Doporučení: používej vždy
/api/history/unified, ne /api/history/mervis ani /api/history/internal. Když admin přepne zdroj projektu, unified se přizpůsobí automaticky a klient nemusíš měnit.⚠️ Limity: max 50 dpIds na request (přebytek se ořízne → pole
truncated). Mervis SOAP má timeout 110 s – při překročení vrací HTTP 504 s { "isTimeout": true }; reaguj zmenšením časového rozsahu. Mervis data jsou downsamplovaná (≤24 h: max 5000 bodů/sérii, jinak 800). valueText (stavové/textové hodnoty) plní jen interní zdroj.Autorizace: JWT + oprávnění view_history. Časy from/to v ISO 8601 (UTC).