---
title: "SpotLogic – battery optimisation over the spot market (HTTP API)"
description: "API cloud SpotLogic prin HTTPS: citește comanda bateriei după piața spot, încărcarea țintă și vârsta planului; încarcă telemetria. Necesită predicții."
url: "https://taphome.com/ro/compatibility/spotlogic-energy-optimizer-http/"
language: ro
lastmod: 2026-11-10
generator: hugo
ai:
  topics: ["http","cloud-api","data-service","energy-management","battery-storage","spot-prices","photovoltaic"]
  questions: ["Cum se integrează SpotLogic cu TapHome?","Ce citește și ce încarcă șablonul SpotLogic pentru TapHome?","Cum se conectează TapHome la API-ul SpotLogic prin HTTPS?","De unde obțin PLC ID și tokenul de acces SpotLogic?","De ce rămâne comanda SpotLogic la No plan?","De ce respinge SpotLogic telemetria cu HTTP 422?","De ce serii de predicție și de prețuri are nevoie SpotLogic de la TapHome?","Controlează șablonul SpotLogic direct invertorul solar?"]
---

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

Comunicație: Packet Parser → HTTP

## Ghid de integrare

SpotLogic este un serviciu cloud care calculează un plan de încărcare și descărcare pentru bateria unui sistem fotovoltaic pe baza pieței spot de energie electrică. Este un serviciu de calcul, nu o sursă de date: unitatea de control trimite telemetria bateriei împreună cu predicția producției solare, predicția consumului casei și prețurile de import și de export, iar SpotLogic răspunde cu comanda pentru intervalul de timp curent. Acest șablon conectează TapHome la API-ul SpotLogic prin HTTPS (`spotlogic.cz`, portul 443) cu un modul Packet Parser HTTP. Șablonul **citește** comanda și **încarcă** telemetria; nu controlează invertorul solar — comanda se leagă de invertor prin smart rules proprii ale instalatorului.

Nu este nimic de cablat. Punerea în funcțiune a serviciului înseamnă activarea SpotLogic pentru amplasament, colectarea parametrilor bateriei și ai rețelei, asigurarea accesului la internet de ieșire pentru unitatea de control și pregătirea seriilor de predicție și de prețuri.

> [!WARNING]
> SpotLogic are nevoie de seriile de predicție și de prețuri la fiecare încărcare a telemetriei (producția solară și consumul casei pentru azi și mâine, prețurile de import și de export). Acest șablon nu le poate completa singur — consultați [Serii de predicție și de prețuri](https://taphome.com/ro/compatibility/spotlogic-energy-optimizer-http/#serii-de-predicție-și-de-prețuri). Până când nu sunt completate, SpotLogic respinge telemetria cu HTTP 422, nu calculează niciun plan, iar comanda rămâne la **No plan**.

## Configurare

### 1. Activarea SpotLogic și păstrarea datelor de acces

SpotLogic trimite prin e-mail **PLC ID** și **tokenul de acces** (access token) la activarea dispozitivului. Tokenul este secret, legat de exact un PLC ID și valabil pe durata abonamentului. Ambele se transmit numai în șirul de interogare (query string) al fiecărei cereri (`?plc_id=…&token=…`), așa cum cere contractul SpotLogic — niciodată în corpul cererii.

> [!WARNING]
> Nu puneți tokenul în documente partajate și în depozite publice de cod. O pereche greșită de PLC ID și token, un token invalid sau un abonament expirat se termină toate cu HTTP 401, iar SpotLogic nu spune intenționat care dintre cele trei a fost cauza.

### 2. Colectarea parametrilor bateriei și ai rețelei

SpotLogic planifică numai cu valorile pe care le primește în telemetrie. Înainte de import, căutați-le în documentația invertorului solar și a bateriei și în contractul de racordare la rețea:

| Valoare | Sursa | Unitate |
|---|---|---|
| Capacitatea bateriei | fișa tehnică a bateriei; trebuie să fie mai mare decât 0 | kWh |
| Puterea maximă a bateriei | o singură valoare pentru încărcare și descărcare | kW |
| Puterea maximă de import din rețea | dimensiunea întrerupătorului general; `0` înseamnă că amplasamentul nu importă niciodată | kW |
| Puterea maximă de export în rețea | limita de export a racordului la rețea; `0` înseamnă că amplasamentul nu exportă niciodată | kW |
| Limita minimă absolută a bateriei | cea mai mică stare de încărcare permisă de producătorul invertorului, implicit 10 | % |
| Rezerva bateriei | rezerva din care planul nu vinde niciodată în rețea (de exemplu pentru consum imprevizibil), implicit 10 | % |

**Starea de încărcare curentă** a bateriei trebuie să fie de asemenea disponibilă în TapHome, de obicei din integrarea proprie a invertorului, astfel încât un smart rule să o poată scrie în acest șablon (consultați mai jos Încărcarea telemetriei).

### 3. Rețeaua și ceasul unității de control

- Unitatea de control are nevoie de acces la internet de ieșire prin HTTPS către `spotlogic.cz` pe portul 443. SpotLogic nu se conectează înapoi la unitatea de control — seriile de predicție și de prețuri se transmit în corpul încărcării telemetriei, deci nu trebuie deschis niciun port de intrare.
- Telemetria conține momentul trimiterii după ceasul unității de control, iar SpotLogic construiește din el fereastra planului. Câteva minute de abatere nu contează; ore de abatere mută întregul plan pe intervale greșite. Mențineți ceasul unității de control corect.
- Fusul orar (nume IANA, de exemplu `Europe/Prague`) decide unde se termină „azi” și unde începe „mâine”. Introduceți fusul orar al amplasamentului.

### 4. Parametrii de import

Șablonul se importă în interfața Packet Parser din aplicația TapHome, iar la import se completează următorii parametri:

| Parametru | Semnificație | Unitate |
|---|---|---|
| PLC ID, access token | din e-mailul de activare | — |
| Time zone | nume IANA, implicit `Europe/Prague`; din el rezultă limitele zilelor planului | — |
| Battery capacity | trebuie să fie mai mare decât 0 | kWh |
| Battery max power | o singură valoare pentru încărcare și descărcare | kW |
| Max grid import / export power | `0` înseamnă că amplasamentul nu importă / nu exportă niciodată | kW |
| Max state of charge | doar înregistrată de SpotLogic, planificatorul actual nu o aplică | % |
| Hard battery floor | limita minimă de la producătorul invertorului, implicit 10 | % |

Numerele se scriu cu punct zecimal (virgula se convertește). PLC ID și tokenul se stochează în variabilele modulului `PlcId` și `Token`. Toate valorile rămân ulterior editabile ca variabile ale modulului.

### 5. Verificarea datelor de acces

Documentația interactivă a API-ului SpotLogic (pe `spotlogic.cz`, la `/docs`) are un dialog **Authorize** pentru PLC ID și token, iar exemplul de telemetrie TapHome din ea este complet: cu date de acces valide, SpotLogic îl acceptă cu HTTP 202. Actualizați mai întâi momentul trimiterii (`TimeStampUnix`) la ora curentă. Datele de exemplu acceptate sunt reținute pentru plan la fel ca telemetria reală, de aceea această verificare se face înainte ca comanda să fie legată de invertor.

> [!TIP]
> Un răspuns HTTP 422 despre un orizont de predicție incomplet dovedește și el că PLC ID și tokenul sunt corecte — un token greșit dă HTTP 401.

## Funcțiile dispozitivului

### Citirea comenzii (la fiecare 20 s)

Modulul interoghează `GET /api/v1/dispatch` la fiecare 20 de secunde, iar dispozitivele procesează răspunsul:

- **SpotLogic command** — comanda pentru intervalul în curs (`action_id`):

| Valoare | Valoare TapHome | Nume SpotLogic | Semnificație |
|---|---|---|---|
| 0 | No plan | `no_plan` | Niciun plan utilizabil — mențineți invertorul în propriul mod sigur |
| 1 | Self-use | `self_use` | Autoconsum: încărcare din surplusul fotovoltaic, descărcare pentru alimentarea casei |
| 2 | Force charge | `force_charge` | Încărcarea bateriei la putere maximă |
| 3 | Force discharge to grid | `force_discharge` | Descărcarea bateriei în rețea la putere maximă |
| 4 | Self-use, no discharging | `self_use_ChargeOnly` | Autoconsum, încărcarea permisă, descărcarea interzisă |
| 5 | Self-use, no charging | `self_use_DischargeOnly` | Autoconsum, descărcarea permisă, încărcarea interzisă |
| 6 | Stop PV (reserved) | `stopPV` | Rezervat — nu este emis de planificatorul actual |
| 7 | Grid charge without PV (reserved) | `ChargeMaxNoPV` | Rezervat — nu este emis de planificatorul actual |

  Atributele de service afișează numele comenzii și momentul în care se termină comanda (ora locală).
- **SpotLogic target state of charge** — starea de încărcare (%) pe care planul o așteaptă la sfârșitul intervalului. Opriți încărcarea sau descărcarea forțată când bateria o atinge; la autoconsum nu încărcați peste ea. SpotLogic adaugă că la `self_use_DischargeOnly` bateria nu trebuie descărcată sub ea. Valoarea este un rezultat al planului, nu o valoare de referință care trebuie impusă, și poate fi temporar mai mică decât rezerva bateriei după ce casa a consumat rezerva.
- **SpotLogic next command** — comanda intervalului următor, cu momentul de început ca atribut de service.
- **SpotLogic plan age** — vârsta planului servit, în secunde. Poate comanda un smart rule de rezervă: când crește mult peste intervalul de recalculare, planul nu se mai recalculează.

Răspunsul HTTP 404 `no_plan` **nu este o eroare**: comanda este 0, iar dispozitivul afișează un mesaj informativ. În această stare, SpotLogic cere trecerea invertorului în propriul mod sigur și niciodată repetarea din memorie a ultimei comenzi cunoscute. HTTP 401 (PLC ID sau token greșit, abonament expirat) setează o eroare pe dispozitive și pe modul; SpotLogic cere ca astfel de apeluri să nu fie repetate, deci corectați datele de acces.

### Încărcarea telemetriei (aproximativ la fiecare 2 minute)

Modulul trimite `POST /api/v1/optimize` cu `PLCtype: "taphome"` cel mult o dată la 2 minute. Trimite momentul trimiterii, fusul orar, parametrii bateriei și ai rețelei și două valori de la dispozitive:

- **Battery state of charge (input)** — scrieți cu un smart rule starea de încărcare curentă 0–100 % din invertor (când șablonul invertorului dă 0–1, înmulțiți cu 100). Valoarea se rotunjește la procent întreg, deoarece SpotLogic respinge valorile fracționare. Până când nu are o valoare, nu se trimite nimic, iar modulul afișează un avertisment.
- **Battery reserve for SpotLogic** — rezerva `SOCmin`, implicit 10 %: nivelul din care planul nu vinde niciodată în rețea.

Atributele de service ale modulului afișează rezultatul ultimei încărcări, intervalul de recalculare raportat de SpotLogic (implicit 900 s), momentul calculării planului, rularea planului și versiunea API. O încărcare respinsă (HTTP 422) este o eroare a modulului, cu mesajul returnat de SpotLogic. Răspunsul la încărcare nu conține niciodată planul — SpotLogic îl calculează în fundal, iar modulul îl preia la următoarea citire a comenzii.

### Serii de predicție și de prețuri

SpotLogic așteaptă în corpul cererii șase serii, fiecare ca perechi `[unix_ts, value]`:

| Variabila modulului | Conținut | Contract |
|---|---|---|
| `PvForecastTod`, `PvForecastTom` | producția solară azi / mâine, kWh pe oră | orar, fără goluri, de la ora curentă până la sfârșitul zilei de mâine |
| `LoadForecastTod`, `LoadForecastTom` | consumul casei azi / mâine, kWh pe oră | la fel |
| `PriceImp`, `PriceExp` | prețul de import / export, CZK/kWh | pas constant (orar sau 15 minute), ziua de azi este suficientă, prețurile negative sunt permise |

Variabilele păstrează seriile ca text JSON, de exemplu `[[1788645600,0.0],[1788649200,0.42]]`, și sunt inserate nemodificate în corpul cererii; valoarea implicită `[]` este o serie goală. Integrarea în sine funcționează; ceea ce îi trebuie sunt datele. TapHome nu poate încă partaja un text JSON între scripturi, iar un script de smart rule nu poate trimite cereri HTTP. De aceea cele șase serii — în total aproximativ 500 de valori — trebuie colectate din alte scripturi (de exemplu dintr-un șablon de predicție sau de prețuri spot) și transmise acestui modul prin sute de dispozitive auxiliare sau construite chiar în scriptul de citire al modulului. Integrarea devine cu adevărat practică atunci când TapHome va adăuga o variabilă text partajată între scripturi — consultați ideea [Variabilă text și HTTP din scripturile smart rules](https://taphome.com/ro/ideas/script-data-http/). Până atunci, completați cele șase variabile, iar șablonul funcționează așa cum este. Scriptul explică acest lucru într-un comentariu în partea de sus și în locul în care se inserează seriile.

Proveniența datelor este la latitudinea instalatorului; SpotLogic numește aceste surse tipice:

- **Producția solară** — un serviciu de predicție a producției solare, alimentat cu locația, orientarea și înclinarea panourilor și puterea instalată, sau cloudul producătorului invertorului.
- **Consumul casei** — istoricul propriu al amplasamentului: pentru început este suficient consumul orar mediat pe ora din zi și pe tipul zilei (zi lucrătoare, weekend, sărbătoare).
- **Prețurile** — prețul spot recalculat conform contractului de furnizare (import, de exemplu spot plus o marjă) și conform contractului de vânzare a surplusului de energie (export).

O zi cu trecere la ora de vară sau de iarnă are 23 sau 25 de ore, deci o serie completă de producție solară sau de consum are 47, 48 sau 49 de valori. Eșantioanele mai vechi de o oră înainte de ora curentă sunt eliminate, la fel ca eșantioanele de după sfârșitul zilei de mâine; o serie care se termină înainte de sfârșitul zilei de mâine este respinsă.

## Rezolvarea problemelor

| Simptom | Cauză și soluție |
|---|---|
| Comanda rămâne la **No plan** | Încă nu s-a calculat niciun plan sau telemetria este respinsă. Verificați eroarea modulului și atributul de service Last telemetry upload. Nici planul mai vechi de 60 de minute nu este servit. După prima încărcare acceptată, planul poate dura o vreme — cel puțin un interval de recalculare. |
| Eroare a modulului HTTP 422 | Telemetria încalcă contractul de date SpotLogic; mesajul spune care parte. Cel mai des lipsesc seriile de predicție sau de prețuri ori nu acoperă perioada până la sfârșitul zilei de mâine. |
| Eroare HTTP 401 | PLC ID și tokenul nu se potrivesc sau abonamentul a expirat. Corectați variabilele modulului `PlcId` și `Token`. |
| Avertismentul „Telemetry not sent” | Starea de încărcare nu a fost încă scrisă sau un parametru al bateriei ori al rețelei este gol. |
| Vârsta planului crește continuu | Telemetria nouă nu ajunge la SpotLogic sau sursele sale de date au căderi; ultimul plan valid rămâne în vigoare până la vârsta de 60 de minute. |
| Eroare HTTP 500 sau 502 | Eroare de server sau sursă de date defectă pe partea SpotLogic; ultimul plan valid rămâne în vigoare. SpotLogic recomandă repetarea ambelor cereri cu întârzieri crescătoare; modulul repetă pur și simplu ambele cereri la următoarea interogare. |
| Planul comandă orele greșite | Ceasul unității de control sau fusul orar este greșit — fereastra planului se construiește din momentul trimiterii și din fusul orar declarat. |

## Dispozitive disponibile 6

Aceste dispozitive apar în TapHome după import.

SpotLogic Modul

Atribute de service

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

Variabile personalizate

|                                  |
|----------------------------------|
| `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)     |

Citire (modul)

```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
```

Atribute de service

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 Comutator cu mai multe valori

Valori / Stări: 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)

Citirea stării comutatorului

```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);
```

Atribute de service

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 Variabilă

Citire

```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 Comutator cu mai multe valori

Valori / Stări: 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)

Citirea stării comutatorului

```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);
```

Atribute de service

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 Variabilă

Citire

```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) Variabilă

Citire

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

Scriere

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

Battery reserve for SpotLogic Variabilă

Citire

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

Scriere

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

**Conexiune:** Packet Parser → HTTP

## Parametri de import

Introduceți aceste valori când importați XML-ul.

| Solicitat în aplicație                                      | Implicit               |
|-------------------------------------------------------------|------------------------|
| SpotLogic PLC ID (from the activation e-mail)               | Se introduce la import |
| SpotLogic access token (from the activation e-mail, secret) | Se introduce la import |
| Time zone (IANA name)                                       | `Europe/Prague`        |
| Battery capacity \[kWh]                                     | Se introduce la import |
| Battery max charge and discharge power \[kW]                | Se introduce la import |
| Max grid import power \[kW] (0 = never import)              | Se introduce la import |
| Max grid export power \[kW] (0 = never export)              | Se introduce la import |
| Max state of charge \[%] (recorded only)                    | `100`                  |
| Hard battery floor from the inverter manufacturer \[%]      | `10`                   |

## Documentație asociată

- [Packet Parser Integration](https://taphome.com/ro/compatibility/packet-parser-guide/)
- [Packet Parser (HTTP, TCP, UDP, FTP, MQTT)](https://taphome.com/ro/docs/integration/packet-parser/)
- [Funcții Packet parser](https://taphome.com/ro/docs/script/packet-parser/)
- [Funcții de parsare](https://taphome.com/ro/docs/script/parsing-functions/)

