This custom integration connects your Marstek battery system (via the Marstek cloud API) to Home Assistant, pulling live data and exposing it as sensor entities.
Automatic login & token refresh
Logs in to the Marstek cloud API using your credentials, hashes your password (MD5) before sending, and automatically refreshes the token if it expires.
Configurable scan interval
Set how often the integration polls the API (10–3600 seconds) during initial setup or later via the Options menu.
Battery metrics exposed as sensors
soc – State of charge (%)charge – Charge power (W)discharge – Discharge power (W)load – Load power (W)profit – Profit (€)version – Firmware versionsn – Serial numberreport_time – Timestamp of last reporttotal_charge – Total charge per device (kWh).
Cross-device total charge sensor
total_charge_all_devices – Sum of total charges across all batteries (kWh).
Diagnostic sensors
last_update – Time of last successful updateapi_latency – API call duration in millisecondsconnection_status – Online/offline status
Device registry integration
Each battery appears as a device in HA with model, serial number, firmware version, and manufacturer.
Editable battery capacity
Configure the default capacity (in kWh) for each battery during setup or later via the Options menu.
Smart device filtering
Automatically filters out non-compatible or irrelevant device types (e.g., "HME-3") from the device list.
marstek_cloud folder into your Home Assistant custom_components directory.Here’s how the integration works internally:
config_flow.py collects your email, password, scan interval, and default battery capacities.__init__.py creates:aiohttp session for async HTTP calls.MarstekAPI instance for talking to the cloud API.MarstekCoordinator (subclass of DataUpdateCoordinator) that schedules periodic updates.MarstekAPI._get_token():https://eu.hamedata.com/app/Solar/v2_get_device.php.token.MarstekAPI.get_devices():https://eu.hamedata.com/ems/api/v1/getDeviceList with the token.8 (no access permission), it clears the cached token and logs the error. A new token will be obtained automatically on the next update cycle._async_update_data():api.get_devices() to fetch the latest battery list.sensor.py: MarstekSensor per metric in SENSOR_TYPES. MarstekDiagnosticSensor per metric in DIAGNOSTIC_SENSORS. MarstekDeviceTotalChargeSensor for the total charge per device. MarstekTotalChargeSensor for the cross-device total charge. devid_fieldname). async_update() on entities when needed.Login:
POST https://eu.hamedata.com/app/Solar/v2_get_device.php?pwd=<MD5_PASSWORD>&mailbox=<EMAIL>
Get Devices:
GET https://eu.hamedata.com/ems/api/v1/getDeviceList?token=<TOKEN>
sequenceDiagram
participant HA as Home Assistant
participant CF as Config Flow
participant CO as Coordinator
participant API as Marstek API
participant ENT as Sensor Entities
HA->>CF: User enters email, password, scan interval, capacities
CF-->>HA: Store credentials, scan interval, capacities
HA->>CO: Create coordinator with API client
CO->>API: POST login (MD5 password)
API-->>CO: Return token
loop Every scan_interval seconds
CO->>API: GET device list (token)
alt Token expired
API-->>CO: Error (invalid token)
CO->>API: POST login (refresh token)
API-->>CO: Return new token
CO->>API: GET device list (retry)
end
API-->>CO: Return device data
CO-->>ENT: Update all sensor values
ENT-->>HA: Display updated metrics
end
$ claude mcp add marstek_cloud \
-- python -m otcore.mcp_server <graph>