---
title: "SpotLogic – battery optimisation over the spot market (HTTP API)"
description: "SpotLogic API w chmurze (HTTPS): odczyt polecenia baterii wg cen spot, docelowego stanu naładowania i wieku planu; wysyłanie telemetrii. Wymaga prognoz."
url: "https://taphome.com/pl/compatibility/spotlogic-energy-optimizer-http/"
language: pl
lastmod: 2026-11-10
generator: hugo
ai:
  topics: ["http","cloud-api","data-service","energy-management","battery-storage","spot-prices","photovoltaic"]
  questions: ["Jak zintegrować SpotLogic z TapHome?","Co odczytuje i wysyła szablon SpotLogic dla TapHome?","Jak połączyć TapHome z SpotLogic API przez HTTPS?","Skąd wziąć PLC ID i token dostępu SpotLogic?","Dlaczego polecenie SpotLogic pozostaje na No plan?","Dlaczego SpotLogic odrzuca telemetrię z HTTP 422?","Jakich serii prognoz i cen SpotLogic potrzebuje od TapHome?","Czy szablon SpotLogic steruje falownikiem solarnym bezpośrednio?"]
---

# SpotLogic – battery optimisation over the spot market (HTTP API)

Komunikacja: Packet Parser → HTTP

## Poradnik integracji

SpotLogic to usługa w chmurze, która oblicza plan ładowania i rozładowania baterii fotowoltaicznej według cen na rynku spot energii elektrycznej. Jest to usługa obliczeniowa, a nie źródło danych: jednostka sterująca wysyła telemetrię baterii razem z prognozą produkcji PV, prognozą zużycia domu oraz cenami zakupu i sprzedaży energii, a SpotLogic odpowiada poleceniem dla bieżącego przedziału czasowego. Ten szablon łączy TapHome z SpotLogic API przez HTTPS (`spotlogic.cz`, port 443) za pomocą modułu HTTP Packet Parser. **Odczytuje** polecenie i **wysyła** telemetrię; nie steruje falownikiem solarnym — polecenie łączy się z falownikiem solarnym za pomocą własnych smart rules instalatora.

Nie trzeba niczego okablować. Uruchomienie usługi obejmuje aktywację SpotLogic dla obiektu, zebranie parametrów baterii i sieci, zapewnienie jednostce sterującej wychodzącego dostępu do internetu oraz przygotowanie serii prognoz i cen.

> [!WARNING]
> SpotLogic wymaga serii prognoz i cen w każdym wysłaniu telemetrii (produkcja PV i zużycie domu na dziś i jutro, ceny zakupu i sprzedaży). Ten szablon nie potrafi wypełnić ich sam — zobacz [Serie prognoz i cen](https://taphome.com/pl/compatibility/spotlogic-energy-optimizer-http/#serie-prognoz-i-cen). Dopóki nie są wypełnione, SpotLogic odrzuca telemetrię z HTTP 422, nie oblicza planu, a polecenie pozostaje na **No plan**.

## Konfiguracja

### 1. Aktywuj SpotLogic i zachowaj dane dostępowe

SpotLogic wysyła **PLC ID** i **token dostępu** e-mailem przy aktywacji urządzenia. Token jest tajny, przypisany do dokładnie jednego PLC ID i ważny przez okres subskrypcji. Oba są przesyłane wyłącznie w query string każdego żądania (`?plc_id=…&token=…`), tak jak wymaga tego kontrakt SpotLogic — nigdy w treści żądania.

> [!WARNING]
> Nie umieszczaj tokena we współdzielonych dokumentach ani w publicznych repozytoriach. Błędna para PLC ID i token, nieważny token lub wygasła subskrypcja kończą się zawsze HTTP 401, a SpotLogic celowo nie informuje, który z tych trzech przypadków wystąpił.

### 2. Zbierz parametry baterii i sieci

SpotLogic planuje wyłącznie na podstawie liczb otrzymanych w telemetrii. Przed importem sprawdź je w dokumentacji falownika solarnego i baterii oraz w umowie przyłączeniowej:

| Wartość | Skąd pochodzi | Jednostka |
|---|---|---|
| Pojemność baterii | karta katalogowa baterii; musi być większa od 0 | kWh |
| Maksymalna moc baterii | jedna wartość dla ładowania i rozładowania | kW |
| Maksymalna moc poboru z sieci | wielkość zabezpieczenia głównego; `0` oznacza, że obiekt nigdy nie pobiera z sieci | kW |
| Maksymalna moc oddawania do sieci | limit oddawania energii przyłącza; `0` oznacza, że obiekt nigdy nie oddaje do sieci | kW |
| Twarda dolna granica baterii | najniższy stan naładowania dopuszczony przez producenta falownika solarnego, domyślnie 10 | % |
| Rezerwa baterii | rezerwa, z której plan nigdy nie sprzedaje do sieci (na przykład na nieprzewidywalne zużycie), domyślnie 10 | % |

W TapHome musi być dostępny także **bieżący stan naładowania** baterii, zwykle z własnej integracji falownika solarnego, aby smart rule mogła zapisać go do tego szablonu (zobacz Wysyłanie telemetrii poniżej).

### 3. Sieć i zegar jednostki sterującej

- Jednostka sterująca potrzebuje wychodzącego dostępu do internetu przez HTTPS do `spotlogic.cz` na porcie 443. SpotLogic nie łączy się zwrotnie z jednostką sterującą — serie prognoz i cen są przesyłane w treści wysłania telemetrii, więc nie trzeba otwierać żadnego portu przychodzącego.
- Telemetria zawiera czas wysłania z zegara jednostki sterującej, a SpotLogic buduje na jego podstawie okno planu. Kilka minut odchyłki nie szkodzi; odchyłka rzędu godzin przesuwa cały plan na niewłaściwe przedziały czasowe. Dbaj o poprawny zegar jednostki sterującej.
- Strefa czasowa (nazwa IANA, na przykład `Europe/Prague`) decyduje, gdzie kończy się „dziś”, a zaczyna „jutro”. Wpisz strefę czasową obiektu.

### 4. Parametry importu

Szablon importuje się w interfejsie Packet Parser aplikacji TapHome, a przy imporcie wypełnia się następujące parametry:

| Parametr | Znaczenie | Jednostka |
|---|---|---|
| PLC ID, token dostępu | z e-maila aktywacyjnego | — |
| Strefa czasowa | nazwa IANA, domyślnie `Europe/Prague`; wynikają z niej granice dni planu | — |
| Pojemność baterii | musi być większa od 0 | kWh |
| Maksymalna moc baterii | jedna wartość dla ładowania i rozładowania | kW |
| Maksymalna moc poboru / oddawania do sieci | `0` oznacza, że obiekt nigdy nie pobiera / nigdy nie oddaje do sieci | kW |
| Maksymalny stan naładowania | SpotLogic tylko go zapisuje, obecny planer go nie egzekwuje | % |
| Twarda dolna granica baterii | granica od producenta falownika solarnego, domyślnie 10 | % |

Liczby zapisuje się z kropką dziesiętną (przecinek jest zamieniany). PLC ID i token są przechowywane w zmiennych modułu `PlcId` i `Token`. Wszystkie wartości można potem dalej edytować jako zmienne modułu.

### 5. Sprawdzenie danych dostępowych

Interaktywna dokumentacja API SpotLogic (na `spotlogic.cz` pod `/docs`) ma okno **Authorize** dla PLC ID i tokena, a jej przykład telemetrii TapHome jest kompletny: przy poprawnych danych dostępowych SpotLogic przyjmuje go z HTTP 202. Najpierw zaktualizuj w nim czas wysłania (`TimeStampUnix`) na bieżący. Przyjęte dane przykładowe są buforowane do planu tak jak prawdziwa telemetria, dlatego to sprawdzenie należy wykonać przed połączeniem polecenia z falownikiem solarnym.

> [!TIP]
> Odpowiedź HTTP 422 o niepełnym horyzoncie prognozy także dowodzi, że PLC ID i token są poprawne — błędny token daje HTTP 401.

## Funkcje urządzenia

### Odczyt polecenia (co 20 s)

Moduł odpytuje `GET /api/v1/dispatch` co 20 sekund, a urządzenia przetwarzają odpowiedź:

- **SpotLogic command** — polecenie dla trwającego przedziału czasowego (`action_id`):

| Wartość | Wartość w TapHome | Nazwa w SpotLogic | Znaczenie |
|---|---|---|---|
| 0 | No plan | `no_plan` | Brak użytecznego planu — pozostaw falownik solarny w jego własnym trybie bezpiecznym |
| 1 | Self-use | `self_use` | Autokonsumpcja: ładowanie z nadwyżki PV, rozładowanie na pokrycie zużycia domu |
| 2 | Force charge | `force_charge` | Ładowanie baterii z maksymalną mocą |
| 3 | Force discharge to grid | `force_discharge` | Rozładowanie baterii do sieci z maksymalną mocą |
| 4 | Self-use, no discharging | `self_use_ChargeOnly` | Autokonsumpcja, ładowanie dozwolone, rozładowanie zabronione |
| 5 | Self-use, no charging | `self_use_DischargeOnly` | Autokonsumpcja, rozładowanie dozwolone, ładowanie zabronione |
| 6 | Stop PV (reserved) | `stopPV` | Zarezerwowane — obecny planer go nie wydaje |
| 7 | Grid charge without PV (reserved) | `ChargeMaxNoPV` | Zarezerwowane — obecny planer go nie wydaje |

  Atrybuty serwisowe pokazują nazwę polecenia i czas jego zakończenia (czas lokalny).
- **SpotLogic target state of charge** — stan naładowania (%), którego plan oczekuje na końcu przedziału czasowego. Zakończ wymuszone ładowanie lub rozładowanie, gdy bateria go osiągnie; przy autokonsumpcji nie ładuj powyżej niego. SpotLogic dodaje, że przy `self_use_DischargeOnly` bateria nie powinna być rozładowywana poniżej niego. Wartość jest wynikiem planu, a nie wartością zadaną, którą trzeba wymusić, i może przejściowo być niższa niż rezerwa baterii, gdy dom zużył rezerwę.
- **SpotLogic next command** — polecenie następnego przedziału czasowego, z czasem jego rozpoczęcia jako atrybutem serwisowym.
- **SpotLogic plan age** — wiek udostępnionego planu w sekundach. Może sterować awaryjną smart rule: gdy rośnie wyraźnie powyżej interwału ponownego przeliczania, plan nie jest przeliczany.

Odpowiedź HTTP 404 `no_plan` **nie jest błędem**: polecenie ma wartość 0, a urządzenie pokazuje komunikat informacyjny. SpotLogic prosi, aby w tym stanie przełączyć falownik solarny na jego własny tryb bezpieczny i nigdy nie powtarzać ostatniego znanego polecenia z pamięci. HTTP 401 (błędny PLC ID lub token, wygasła subskrypcja) ustawia błąd na urządzeniach i na module; SpotLogic prosi, aby nie powtarzać takich wywołań, więc popraw dane dostępowe.

### Wysyłanie telemetrii (mniej więcej co 2 minuty)

Moduł wysyła `POST /api/v1/optimize` z `PLCtype: "taphome"` najwyżej co 2 minuty. Wysyła czas wysłania, strefę czasową, parametry baterii i sieci oraz dwie wartości z urządzeń:

- **Battery state of charge (input)** — zapisz do niego bieżący stan naładowania 0–100 % z falownika solarnego za pomocą smart rule (gdy szablon falownika solarnego podaje 0–1, pomnóż przez 100). Wartość jest zaokrąglana do pełnego procenta, ponieważ SpotLogic odrzuca wartości ułamkowe. Dopóki nie ma wartości, nic nie jest wysyłane, a moduł pokazuje ostrzeżenie.
- **Battery reserve for SpotLogic** — rezerwa `SOCmin`, domyślnie 10 %: poziom, z którego plan nigdy nie sprzedaje do sieci.

Atrybuty serwisowe modułu pokazują wynik ostatniego wysłania, interwał ponownego przeliczania zgłoszony przez SpotLogic (domyślnie 900 s), czas obliczenia planu, przebieg planu i wersję API. Odrzucone wysłanie (HTTP 422) to błąd modułu z komunikatem zwróconym przez SpotLogic. Odpowiedź na wysłanie nigdy nie zawiera planu — SpotLogic oblicza go w tle, a moduł pobiera go przy następnym odczycie polecenia.

### Serie prognoz i cen

SpotLogic oczekuje w treści sześciu serii, każdej jako par `[unix_ts, value]`:

| Zmienna modułu | Zawartość | Kontrakt |
|---|---|---|
| `PvForecastTod`, `PvForecastTom` | produkcja PV dziś / jutro, kWh na godzinę | godzinowo, bez luk, od bieżącej godziny do końca jutra |
| `LoadForecastTod`, `LoadForecastTom` | zużycie domu dziś / jutro, kWh na godzinę | tak samo |
| `PriceImp`, `PriceExp` | cena zakupu / sprzedaży, CZK/kWh | stały krok (godzinowo lub 15 minut), wystarczy dzień dzisiejszy, ceny ujemne dozwolone |

Zmienne przechowują serie jako tekst JSON, na przykład `[[1788645600,0.0],[1788649200,0.42]]`, i są wstawiane do treści bez zmian; wartość domyślna `[]` to pusta seria. Sama integracja działa; potrzebuje tylko danych. TapHome nie potrafi jeszcze współdzielić jednego tekstu JSON między skryptami, a skrypt smart rule nie może wysyłać żądań HTTP. Sześć serii — łącznie około 500 wartości — trzeba więc zebrać z innych skryptów (na przykład z szablonu prognozy lub cen spot) i przekazać do tego modułu przez setki urządzeń pomocniczych albo zbudować bezpośrednio w skrypcie odczytu modułu. Integracja stanie się naprawdę praktyczna, gdy TapHome doda zmienną tekstową współdzieloną między skryptami — zobacz pomysł [Zmienna tekstowa i HTTP ze skryptów smart rules](https://taphome.com/pl/ideas/script-data-http/). Do tego czasu wypełnij sześć zmiennych, a szablon zadziała bez zmian. Skrypt wyjaśnia to w komentarzu na początku oraz w miejscu, w którym serie są wstawiane.

Skąd pochodzą dane, decyduje instalator; SpotLogic wymienia te typowe źródła:

- **Produkcja PV** — usługa predykcji zysków solarnych zasilana lokalizacją, orientacją i nachyleniem paneli oraz mocą zainstalowaną, albo chmura producenta falownika solarnego.
- **Zużycie domu** — własna historia obiektu: na początek wystarczy godzinowe zużycie uśrednione według godziny dnia i rodzaju dnia (dzień roboczy, weekend, święto).
- **Ceny** — cena spot przeliczona według umowy na dostawę energii (zakup, na przykład spot plus marża) i według umowy na sprzedaż nadwyżek energii (sprzedaż).

Dzień ze zmianą czasu ma 23 lub 25 godzin, więc kompletna seria PV lub zużycia ma 47, 48 lub 49 wartości. Próbki starsze niż godzina przed bieżącą godziną są obcinane, podobnie jak próbki po końcu jutra; seria kończąca się przed końcem jutra jest odrzucana.

## Rozwiązywanie problemów

| Objaw | Przyczyna i rozwiązanie |
|---|---|
| Polecenie pozostaje na **No plan** | Plan nie został jeszcze obliczony albo telemetria jest odrzucana. Sprawdź błąd modułu i atrybut serwisowy Last telemetry upload. Plan starszy niż 60 minut również nie jest udostępniany. Po pierwszym przyjętym wysłaniu obliczenie planu może chwilę potrwać — co najmniej jeden interwał ponownego przeliczania. |
| Błąd modułu HTTP 422 | Telemetria narusza kontrakt danych SpotLogic; komunikat mówi, którą część. Najczęściej brakuje serii prognoz lub cen albo nie pokrywają one okresu do końca jutra. |
| Błąd HTTP 401 | PLC ID i token nie pasują do siebie albo subskrypcja wygasła. Popraw zmienne modułu `PlcId` i `Token`. |
| Ostrzeżenie „Telemetry not sent” | Stan naładowania nie został jeszcze zapisany albo jakiś parametr baterii lub sieci jest pusty. |
| Wiek planu stale rośnie | Nowa telemetria nie dociera do SpotLogic albo zawodzą jego źródła danych; ostatni ważny plan obowiązuje, dopóki nie osiągnie 60 minut. |
| Błąd HTTP 500 lub 502 | Błąd serwera lub awaria źródła danych po stronie SpotLogic; ostatni ważny plan nadal obowiązuje. SpotLogic zaleca powtarzanie obu z rosnącymi odstępami; moduł po prostu powtarza oba żądania przy następnym odpytaniu. |
| Plan steruje niewłaściwymi godzinami | Zegar jednostki sterującej lub strefa czasowa są błędne — okno planu jest budowane z czasu wysłania i zadeklarowanej strefy czasowej. |

## Dostępne urządzenia 6

Te urządzenia pojawią się w TapHome po imporcie.

SpotLogic Moduł

Atrybuty serwisowe

|                         |
|-------------------------|
| Last telemetry upload   |
| Plan recompute interval |
| Plan computed at        |
| Plan run                |
| API version             |

Zmienne niestandardowe

|                                  |
|----------------------------------|
| `PlcId` (string)                 |
| `Token` (string)                 |
| `TimeZone` (string)              |
| `BatCapacity` (string)           |
| `BatPmax` (string)               |
| `GridImportPmax` (string)        |
| `GridExportPmax` (string)        |
| `SocMax` (string)                |
| `SocHardMin` (string)            |
| `SocNow` (numeric) = -1          |
| `SocMin` (numeric) = 10          |
| `PvForecastTod` (string) = \[]   |
| `PvForecastTom` (string) = \[]   |
| `LoadForecastTod` (string) = \[] |
| `LoadForecastTom` (string) = \[] |
| `PriceImp` (string) = \[]        |
| `PriceExp` (string) = \[]        |
| `DispatchJson` (string)          |
| `DispatchCode` (numeric)         |
| `OptimizeJson` (string)          |
| `OptimizeCode` (numeric)         |
| `OptimizeAt` (string)            |
| `LastOptimizeUnix` (numeric)     |

Odczyt (moduł)

```taphome
# =============================================================================
#  STATUS: WORKING, BUT THE DATA MUST BE BROUGHT IN BY HAND
# =============================================================================
#  The integration itself works - dispatch reading, action_id -> inverter mode
#  mapping, next command, plan diagnostics and error reporting are finished.
#  What it needs is the data: six series (PV forecast, load forecast, import and
#  export spot price; ~500 values, hourly or 15-minute, horizon now -> end of
#  tomorrow) as JSON text [[unix_ts, value], ...] in the module variables
#  PvForecastTod ... PriceExp (see below).
#  Until TapHome ships a shared variable between scripts, those series must be
#  collected from other scripts and handed over through hundreds of helper
#  devices - that is why the integration is only really practical once that
#  feature lands.
#  Tracking: https://taphome.com/cs/ideas/script-data-http/  (TapHome idea FR-003)
#  In the meantime: fill the six variables below and the template works as is.
# =============================================================================

# 1) GET /api/v1/dispatch - the command for the slot in progress (module poll ~20 s).
#    plc_id and token travel ONLY in the query string (SpotLogic contract).
VAR r := SENDHTTPREQUEST("/api/v1/dispatch?plc_id=" + PlcId + "&token=" + Token);
DispatchCode := r.StatusCode;
DispatchJson := r.Content;
IF r.StatusCode = 401
    ADDERROR(1, "SpotLogic rejected the PLC ID or the token (HTTP 401) - check the module variables PlcId and Token; the subscription may have expired. Not retried by SpotLogic rules, fix the credentials.");
ELSEIF r.StatusCode != 200 AND r.StatusCode != 404
    VAR dmsg := PARSEJSON(r.Content, "$.message", true);
    ADDERROR(2, "SpotLogic dispatch failed: HTTP " + r.StatusCode + IF(ISNULL(dmsg), "", " " + dmsg));
END

# 2) POST /api/v1/optimize - telemetry, at most every ~2 min (SpotLogic asks for no more often).
datetime now := NOW();
VAR nowUnix := now.UNIXTIME;
IF nowUnix - LastOptimizeUnix >= 115
    LastOptimizeUnix := nowUnix;
    VAR cap := TODOUBLE(REPLACE(BatCapacity, ",", "."));
    VAR bp := TODOUBLE(REPLACE(BatPmax, ",", "."));
    VAR gi := TODOUBLE(REPLACE(GridImportPmax, ",", "."));
    VAR ge := TODOUBLE(REPLACE(GridExportPmax, ",", "."));
    VAR smax := TODOUBLE(SocMax);
    VAR shard := TODOUBLE(SocHardMin);
    IF SocNow < 0 OR SocNow > 100
        OptimizeCode := -1;
    ELSEIF ISNAN(cap) OR ISNAN(bp) OR ISNAN(gi) OR ISNAN(ge) OR ISNAN(smax) OR ISNAN(shard) OR LENGTH(PlcId) = 0 OR LENGTH(Token) = 0
        OptimizeCode := -2;
    ELSE
        # Forecast and price series: module variables PvForecastTod, PvForecastTom,
        # LoadForecastTod, LoadForecastTom, PriceImp, PriceExp hold JSON text
        # [[unix_ts, value], ...]. The template does NOT fill them - see the banner
        # at the top of this script. Until they are filled, SpotLogic answers 422.
        VAR body := "{\"PLCtype\":\"taphome\"";
        body := body + ",\"TimeZone\":\"" + TimeZone + "\"";
        body := body + ",\"TimeStampUnix\":" + TOSTRING(nowUnix, "F0");
        body := body + ",\"BatCapacity\":" + TOSTRING(cap, "F2");
        body := body + ",\"BatPmax\":" + TOSTRING(bp, "F2");
        body := body + ",\"GridImportPmax\":" + TOSTRING(gi, "F2");
        body := body + ",\"GridExportPmax\":" + TOSTRING(ge, "F2");
        body := body + ",\"SOCnow\":" + TOSTRING(SocNow, "F0");
        body := body + ",\"SOCmin\":" + TOSTRING(SocMin, "F0");
        body := body + ",\"SOCmax\":" + TOSTRING(smax, "F0");
        body := body + ",\"SOChardmin\":" + TOSTRING(shard, "F0");
        body := body + ",\"PvForecastTod\":" + PvForecastTod;
        body := body + ",\"PvForecastTom\":" + PvForecastTom;
        body := body + ",\"LoadForecastTod\":" + LoadForecastTod;
        body := body + ",\"LoadForecastTom\":" + LoadForecastTom;
        body := body + ",\"PriceImp\":" + PriceImp;
        body := body + ",\"PriceExp\":" + PriceExp + "}";
        VAR o := SENDHTTPREQUEST("/api/v1/optimize?plc_id=" + PlcId + "&token=" + Token, "POST", body, "Content-Type: application/json");
        OptimizeCode := o.StatusCode;
        OptimizeJson := o.Content;
        OptimizeAt := TOSTRING(now, "yyyy-MM-dd HH:mm:ss");
    END
END

# The outcome of the last telemetry upload is reported on every run, not only on the upload run.
VAR omsg := "";
IF LENGTH(OptimizeJson) > 0
    omsg := PARSEJSON(OptimizeJson, "$.message", true);
    IF ISNULL(omsg)
        omsg := "";
    END
END
IF OptimizeCode = -1
    ADDWARNING(3, "Telemetry not sent: the device Battery state of charge (input) has no value 0-100 yet - write it from the inverter with a smart rule.");
ELSEIF OptimizeCode = -2
    ADDWARNING(7, "Telemetry not sent: fill the module variables PlcId, Token, BatCapacity, BatPmax, GridImportPmax, GridExportPmax, SocMax and SocHardMin (numbers with a decimal point).");
ELSEIF OptimizeCode = 401
    ADDERROR(4, "SpotLogic rejected the telemetry: PLC ID or token invalid (HTTP 401).");
ELSEIF OptimizeCode = 422
    ADDERROR(5, "SpotLogic rejected the telemetry (HTTP 422): " + omsg + " - the forecast and price series (module variables PvForecastTod ... PriceExp) must be filled, see the template description.");
ELSEIF OptimizeCode != 0 AND OptimizeCode != 202
    ADDERROR(6, "SpotLogic telemetry upload failed: HTTP " + OptimizeCode + " " + omsg);
END
```

Atrybuty serwisowe

Last telemetry upload

```taphome
IF(OptimizeCode = 0, "not sent yet", IF(OptimizeCode < 0, "waiting for inputs", "HTTP " + OptimizeCode + " at " + OptimizeAt))
```

Plan recompute interval

```taphome
VAR v := PARSEJSON(OptimizeJson, "$.data.recompute_interval_sec", true);
IF ISNULL(v)
    RETURN("-");
END
RETURN(TOSTRING(v, "F0") + " s");
```

Plan computed at

```taphome
VAR s := PARSEJSON(DispatchJson, "$.meta.plan_created_at", true);
IF ISNULL(s)
    RETURN("-");
END
datetime t := DATETIME(s);
VAR l := t.LOCALDATETIME;
RETURN(TOSTRING(l, "yyyy-MM-dd HH:mm"));
```

Plan run

```taphome
VAR v := PARSEJSON(DispatchJson, "$.meta.run_id", true);
RETURN(IF(ISNULL(v), "-", v));
```

API version

```taphome
VAR v := PARSEJSON(DispatchJson, "$.meta.version.api", true);
RETURN(IF(ISNULL(v), "-", v));
```

SpotLogic command Przełącznik wielowartościowy

Wartości / Stany: No plan · Self-use · Force charge · Force discharge to grid · Self-use, no discharging · Self-use, no charging · Stop PV (reserved) · Grid charge without PV (reserved)

Odczyt stanu przełącznika

```taphome
IF DispatchCode = 0
    RETURN(NaN);
END
IF DispatchCode = 401
    ADDERROR(1, "SpotLogic rejected the PLC ID or the token (HTTP 401) - check the module variables PlcId and Token.");
    RETURN(NaN);
END
IF DispatchCode = 404
    ADDINFO(2, "No usable plan yet (no_plan) - keep the inverter in its own safe mode.");
    RETURN(0);
END
IF DispatchCode != 200
    ADDERROR(3, "Command not available: HTTP " + DispatchCode);
    RETURN(NaN);
END
VAR id := PARSEJSON(DispatchJson, "$.data.command.action_id", true);
IF ISNULL(id)
    ADDERROR(4, "Unexpected SpotLogic answer: data.command.action_id is missing.");
    RETURN(NaN);
END
RETURN(id);
```

Atrybuty serwisowe

Command name

```taphome
VAR v := PARSEJSON(DispatchJson, "$.data.command.action_name", true);
IF ISNULL(v)
    v := PARSEJSON(DispatchJson, "$.data.action_name", true);
END
RETURN(IF(ISNULL(v), "-", v));
```

Command valid until

```taphome
VAR s := PARSEJSON(DispatchJson, "$.data.command.valid_until", true);
IF ISNULL(s)
    RETURN("-");
END
datetime t := DATETIME(s);
VAR l := t.LOCALDATETIME;
RETURN(TOSTRING(l, "yyyy-MM-dd HH:mm"));
```

SpotLogic target state of charge Zmienna

Odczyt

```taphome
IF DispatchCode = 0
    RETURN(NaN);
END
IF DispatchCode = 401
    ADDERROR(1, "SpotLogic rejected the PLC ID or the token (HTTP 401) - check the module variables PlcId and Token.");
    RETURN(NaN);
END
IF DispatchCode != 200
    RETURN(NaN);
END
VAR v := PARSEJSON(DispatchJson, "$.data.command.target_soc_percent", true);
IF ISNULL(v)
    RETURN(NaN);
END
RETURN(v);
```

SpotLogic next command Przełącznik wielowartościowy

Wartości / Stany: No plan · Self-use · Force charge · Force discharge to grid · Self-use, no discharging · Self-use, no charging · Stop PV (reserved) · Grid charge without PV (reserved)

Odczyt stanu przełącznika

```taphome
IF DispatchCode = 0
    RETURN(NaN);
END
IF DispatchCode = 401
    ADDERROR(1, "SpotLogic rejected the PLC ID or the token (HTTP 401) - check the module variables PlcId and Token.");
    RETURN(NaN);
END
IF DispatchCode = 404
    RETURN(0);
END
IF DispatchCode != 200
    ADDERROR(3, "Next command not available: HTTP " + DispatchCode);
    RETURN(NaN);
END
VAR id := PARSEJSON(DispatchJson, "$.data.context.next_action_id", true);
IF ISNULL(id)
    RETURN(NaN);
END
RETURN(id);
```

Atrybuty serwisowe

Next command name

```taphome
VAR v := PARSEJSON(DispatchJson, "$.data.context.next_action_name", true);
RETURN(IF(ISNULL(v), "-", v));
```

Next command starts

```taphome
VAR s := PARSEJSON(DispatchJson, "$.data.context.next_action_time", true);
IF ISNULL(s)
    RETURN("-");
END
datetime t := DATETIME(s);
VAR l := t.LOCALDATETIME;
RETURN(TOSTRING(l, "yyyy-MM-dd HH:mm"));
```

SpotLogic plan age Zmienna

Odczyt

```taphome
IF DispatchCode = 0
    RETURN(NaN);
END
IF DispatchCode = 401
    ADDERROR(1, "SpotLogic rejected the PLC ID or the token (HTTP 401) - check the module variables PlcId and Token.");
    RETURN(NaN);
END
IF DispatchCode != 200
    RETURN(NaN);
END
VAR v := PARSEJSON(DispatchJson, "$.meta.plan_age_sec", true);
IF ISNULL(v)
    RETURN(NaN);
END
RETURN(v);
```

Battery state of charge (input) Zmienna

Odczyt

```taphome
IF(SocNow < 0, NaN, SocNow)
```

Zapis

```taphome
SocNow := Va;
```

Battery reserve for SpotLogic Zmienna

Odczyt

```taphome
RETURN(SocMin);
```

Zapis

```taphome
SocMin := Va;
```

**Połączenie:** Packet Parser → HTTP

## Parametry importu

Te wartości podajesz podczas importu pliku XML.

| Pytanie w aplikacji                                         | Domyślnie           |
|-------------------------------------------------------------|---------------------|
| SpotLogic PLC ID (from the activation e-mail)               | Podaj przy imporcie |
| SpotLogic access token (from the activation e-mail, secret) | Podaj przy imporcie |
| Time zone (IANA name)                                       | `Europe/Prague`     |
| Battery capacity \[kWh]                                     | Podaj przy imporcie |
| Battery max charge and discharge power \[kW]                | Podaj przy imporcie |
| Max grid import power \[kW] (0 = never import)              | Podaj przy imporcie |
| Max grid export power \[kW] (0 = never export)              | Podaj przy imporcie |
| Max state of charge \[%] (recorded only)                    | `100`               |
| Hard battery floor from the inverter manufacturer \[%]      | `10`                |

## Powiązana dokumentacja

- [Integracja Packet Parser](https://taphome.com/pl/compatibility/packet-parser-guide/)
- [Packet Parser (HTTP, TCP, UDP, FTP, MQTT)](https://taphome.com/pl/docs/integration/packet-parser/)
- [Funkcje Packet parser](https://taphome.com/pl/docs/script/packet-parser/)
- [Funkcje parsowania](https://taphome.com/pl/docs/script/parsing-functions/)

