SpotLogic is a cloud service that computes a charge and discharge plan for a photovoltaic battery over the spot electricity market. It is a calculation service, not a data source: the control unit sends battery telemetry together with the PV generation forecast, the house consumption forecast and the import and export prices, and SpotLogic answers with the command for the current time slot. This template connects TapHome to the SpotLogic API over HTTPS (spotlogic.cz, port 443) with a Packet Parser HTTP module. It reads the command and uploads the telemetry; it does not control the inverter — the command is connected to the inverter with the installer’s own smart rules.
There is nothing to wire. Setting up the service means activating SpotLogic for the site, collecting the battery and grid parameters, giving the control unit outgoing internet access and preparing the forecast and price series.
SpotLogic needs forecast and price series in every telemetry upload (PV generation and house consumption for today and tomorrow, import and export prices). This template cannot fill them on its own — see Forecast and price series. Until they are filled, SpotLogic rejects the telemetry with HTTP 422, does not compute a plan, and the command stays at No plan.
Configuration
1. Activate SpotLogic and keep the credentials
SpotLogic sends the PLC ID and the access token by e-mail when the device is activated. The token is secret, bound to exactly one PLC ID and valid for the subscription period. Both travel only in the query string of each request (?plc_id=…&token=…), as the SpotLogic contract requires — never in the request body.
Keep the token out of shared documents and public repositories. A wrong PLC ID and token pair, an invalid token or an expired subscription all end with HTTP 401, and SpotLogic deliberately does not say which of the three it was.
2. Collect the battery and grid parameters
SpotLogic plans only with the numbers it receives in the telemetry. Before the import, look them up in the inverter and battery documentation and in the grid connection contract:
| Value | Where it comes from | Unit |
|---|---|---|
| Battery capacity | battery data sheet; must be greater than 0 | kWh |
| Battery max power | one value for charging and discharging | kW |
| Max grid import power | size of the main breaker; 0 means the site never imports | kW |
| Max grid export power | export limit of the grid connection; 0 means the site never exports | kW |
| Hard battery floor | lowest state of charge allowed by the inverter manufacturer, default 10 | % |
| Battery reserve | reserve the plan never sells to the grid from (for example for unpredictable consumption), default 10 | % |
The current state of charge of the battery must also be available in TapHome, typically from the inverter’s own integration, so that a smart rule can write it into this template (see Uploading telemetry below).
3. Network and clock of the control unit
- The control unit needs outgoing internet access over HTTPS to
spotlogic.czon port 443. SpotLogic does not connect back to the control unit — the forecast and price series travel in the body of the telemetry upload, so no inbound port has to be opened. - The telemetry carries the time of sending from the control unit clock, and SpotLogic builds the plan window from it. A few minutes of drift is harmless; hours of drift move the whole plan to the wrong slots. Keep the control unit clock correct.
- The time zone (IANA name, for example
Europe/Prague) decides where “today” ends and “tomorrow” begins. Enter the zone of the site.
4. Import parameters
The template is imported into the Packet Parser interface of the TapHome app, and the following parameters are filled in at import:
| Parameter | Meaning | Unit |
|---|---|---|
| PLC ID, access token | from the activation e-mail | — |
| Time zone | IANA name, default Europe/Prague; day boundaries of the plan come from it | — |
| Battery capacity | must be greater than 0 | kWh |
| Battery max power | one value for charging and discharging | kW |
| Max grid import / export power | 0 means the site never imports / never exports | kW |
| Max state of charge | recorded by SpotLogic only, the current planner does not enforce it | % |
| Hard battery floor | floor from the inverter manufacturer, default 10 | % |
Numbers are written with a decimal point (a comma is converted). The PLC ID and the token are stored in the module variables PlcId and Token. All values stay editable afterwards as module variables.
5. Checking the credentials
The interactive API documentation of SpotLogic (on spotlogic.cz under /docs) has an Authorize dialog for the PLC ID and the token, and its TapHome telemetry example is complete: with valid credentials SpotLogic accepts it with HTTP 202. Update its time of sending (TimeStampUnix) to the current time first. Accepted example data are buffered for a plan like real telemetry, so this check belongs before the command is connected to the inverter.
An HTTP 422 answer about an incomplete forecast horizon also proves that the PLC ID and the token are correct — a wrong token gives HTTP 401.
Device capabilities
Reading the command (every 20 s)
The module polls GET /api/v1/dispatch every 20 seconds and the devices parse the answer:
- SpotLogic command — command for the slot in progress (
action_id):
| Value | TapHome value | SpotLogic name | Meaning |
|---|---|---|---|
| 0 | No plan | no_plan | No usable plan — keep the inverter in its own safe mode |
| 1 | Self-use | self_use | Self-consumption: charge from PV surplus, discharge to cover the house |
| 2 | Force charge | force_charge | Charge the battery at maximum power |
| 3 | Force discharge to grid | force_discharge | Discharge the battery to the grid at maximum power |
| 4 | Self-use, no discharging | self_use_ChargeOnly | Self-consumption, charging allowed, discharging forbidden |
| 5 | Self-use, no charging | self_use_DischargeOnly | Self-consumption, discharging allowed, charging forbidden |
| 6 | Stop PV (reserved) | stopPV | Reserved — not issued by the current planner |
| 7 | Grid charge without PV (reserved) | ChargeMaxNoPV | Reserved — not issued by the current planner |
Service attributes show the command name and when the command ends (local time).
- SpotLogic target state of charge — state of charge (%) the plan expects at the end of the slot. Stop forced charging or discharging when the battery reaches it; with self-use do not charge above it. SpotLogic adds that with
self_use_DischargeOnlythe battery should not be discharged below it. The value is a result of the plan, not a setpoint that has to be forced, and it may temporarily be lower than the battery reserve after the house consumed the reserve. - SpotLogic next command — the command of the following slot, with its start time as a service attribute.
- SpotLogic plan age — age of the served plan in seconds. It can drive a fallback smart rule: when it grows well above the recompute interval, the plan is not being recomputed.
The answer HTTP 404 no_plan is not an error: the command is 0 and the device shows an information message. SpotLogic asks to switch to the inverter’s own safe mode in that state and never to repeat the last known command from memory. HTTP 401 (wrong PLC ID or token, expired subscription) sets an error on the devices and on the module; SpotLogic asks not to repeat such calls, so fix the credentials.
Uploading telemetry (about every 2 minutes)
The module sends POST /api/v1/optimize with PLCtype: "taphome" at most every 2 minutes. It sends the time of sending, the time zone, the battery and grid parameters and two values from devices:
- Battery state of charge (input) — write the current state of charge 0–100 % from the inverter with a smart rule (when the inverter template gives 0–1, multiply by 100). It is rounded to a whole percent, because SpotLogic rejects fractional values. Until it has a value, nothing is sent and the module shows a warning.
- Battery reserve for SpotLogic — the
SOCminreserve, default 10 %: the level the plan never sells to the grid from.
The module service attributes show the result of the last upload, the recompute interval reported by SpotLogic (default 900 s), when the plan was computed, the plan run and the API version. A rejected upload (HTTP 422) is a module error with the message SpotLogic returned. The upload answer never contains the plan — SpotLogic computes it in the background and the module picks it up with the next command reading.
Forecast and price series
SpotLogic expects six series in the body, each as pairs [unix_ts, value]:
| Module variable | Content | Contract |
|---|---|---|
PvForecastTod, PvForecastTom | PV generation today / tomorrow, kWh per hour | hourly, without gaps, from the current hour to the end of tomorrow |
LoadForecastTod, LoadForecastTom | house consumption today / tomorrow, kWh per hour | the same |
PriceImp, PriceExp | import / export price, CZK/kWh | constant cadence (hourly or 15 minutes), today is enough, negative prices allowed |
The variables hold the series as JSON text, for example [[1788645600,0.0],[1788649200,0.42]], and are inserted into the body unchanged; the default [] is an empty series. The integration itself works; what it needs is the data. TapHome cannot yet share one JSON text between scripts, and a smart rule script cannot send HTTP requests. The six series — about 500 values together — therefore have to be collected from other scripts (for example a forecast or spot-price template) and handed over to this module through hundreds of helper devices, or built in the module read script itself. The integration becomes really practical once TapHome adds a text variable shared between scripts — see the idea Text variable and HTTP from smart rule scripts. Until then, fill the six variables and the template works as is. The script explains this in a comment at its top and at the place where the series are inserted.
Where the data come from is up to the installer; SpotLogic names these typical sources:
- PV generation — a PV forecast service fed with the location, orientation and tilt of the panels and the installed power, or the inverter manufacturer’s cloud.
- House consumption — the site’s own history: hourly consumption averaged by hour of day and type of day (working day, weekend, holiday) is enough to start with.
- Prices — the spot price recalculated by the supply contract (import, for example spot plus a margin) and by the contract for selling surplus energy (export).
A day with a daylight-saving change has 23 or 25 hours, so a complete PV or consumption series has 47, 48 or 49 values. Samples older than one hour before the current hour are cropped, as are samples beyond the end of tomorrow; a series that ends before the end of tomorrow is rejected.
Troubleshooting
| Symptom | Cause and solution |
|---|---|
| Command stays at No plan | No plan has been computed yet, or the telemetry is rejected. Check the module error and the service attribute Last telemetry upload. A plan older than 60 minutes is not served either. After the first accepted upload the plan can take a while — at least one recompute interval. |
| Module error HTTP 422 | The telemetry violates the SpotLogic data contract; the message says which part. Most often the forecast or price series are missing or do not cover the period up to the end of tomorrow. |
| Error HTTP 401 | PLC ID and token do not match or the subscription expired. Correct the module variables PlcId and Token. |
| Warning “Telemetry not sent” | The state of charge has not been written yet, or a battery or grid parameter is empty. |
| Plan age keeps growing | New telemetry is not reaching SpotLogic or its data sources fail; the last valid plan stays in force until it is 60 minutes old. |
| Error HTTP 500 or 502 | Server error or failing data source on the SpotLogic side; the last valid plan stays in force. SpotLogic recommends repeating both with growing delays; the module simply repeats both requests on the next poll. |
| Plan steers the wrong hours | The control unit clock or the time zone is wrong — the plan window is built from the time of sending and the declared zone. |