GEM driver for the Meross Smart Hub (msh300, msh400 Pro) and its paired sub-devices: sprinkler timers (mst100/mst200), thermostat valves (mts100/mts150/mts150p), temperature & humidity sensors (ms100/ms130), door/window sensors (ms200), water-leak sensors (ms400/ms405), and smoke alarms (ma151). The hub keeps talking to the Meross cloud — the Meross mobile app continues to work alongside GEM — but every GEM command and state read flows over signed HTTP /config on the hub's LAN address.
Prerequisites
- Meross Smart Hub on the same LAN, already onboarded via the Meross app at least once.
- Meross cloud account credentials. Used only during the one-time
pair command to fetch the per-account key and the hub's uuid; not used afterward.
Setup steps
- Add the device. In Devices, create a new device with driver
meross_hub. Set ip, username (Meross email), and password (Meross cloud password).
- Pair. Run the
pair command on the device. The driver logs into the Meross cloud, fetches the account key and this hub's uuid, and persists them as secure device attributes. After a successful pair the password can be cleared if desired. Pair also runs automatically on the first connect when both username and password are present — so reloading the device after entering the credentials is enough; the explicit pair command is the manual path (and the way to re-pair after a password change).
- Sync zones. Sub-devices are enumerated and matching GEM zones auto-created on every connect — one zone per sub-device, with
zone.address set to the 12-char Meross sub-device id and meross_subdevice_type recorded as a zone attribute. Run sync_zones only to force a re-scan after pairing a new sub-device in the Meross app without reloading the hub. Zones land on the subsystem that fits the sub-device — sprinklers on irrigation (falling back to water on older sites provisioned before the irrigation subsystem existed), thermostat valves and temperature/humidity sensors on climate, and door/window, water-leak, and smoke sensors on security. All are default subsystems, so this works on a stock install; if you deleted one of them, that sub-device's zone is skipped until the subsystem exists.
- Verify. State polling fires every
status_interval (default 10 s). Every zone gets state and battery; sprinkler zones also get flow_rate/elapsed_seconds, and thermostat zones also get temperature/setpoint/heating/system_mode. See Polled state, below, for the full per-type breakdown and current limits.
Polled state
Every poll cycle (status_interval, default 10 s) reads the hub's full digest plus a battery sweep and writes onto each sub-device's zone:
- All sub-devices —
battery (0–100) and a generic state (on while the digest reports the sub-device running, off when idle).
- Sprinkler timers (
mst100 / mst200) — also flow_rate and elapsed_seconds (the timer's current watering duration).
- Thermostat valves (
mts100 / mts150 / mts150p) — also temperature (room °C), setpoint (°C), heating (true while the valve is calling for heat), and system_mode (off / heat / cool / auto).
The temperature/humidity (ms100 / ms130), door/window contact (ms200), water-leak (ms400 / ms405), and smoke (ma151) sensors are paired and get their own zones, but their sensor-specific readings are not yet decoded into zone state — those zones currently surface only battery (the generic on/off flag is not meaningful for a passive sensor). Sprinkler and thermostat telemetry is fully wired; the other sensor readings are a known gap.
Attributes
Device — required
| Name | Type | Description |
|---|
ip | string | Hub LAN IP. |
username | string | Meross cloud email. Only used during pair. |
password | string (secure) | Meross cloud password. Only used during pair; can be cleared after. |
Device — optional
| Name | Type | Default | Description |
|---|
cloud_base | string | https://iotx-us.meross.com | Region: US/EU/AP. |
status_interval | int (ms) | 10000 | Polling cadence for Appliance.System.All. |
http_timeout | int (ms) | 5000 | Local HTTP request timeout. |
user_id | string (readonly) | — | Populated by pair. |
uuid | string (readonly) | — | Populated by pair. 32-char hex. |
key | string (secure, readonly) | — | Per-account shared secret. Populated by pair; used to sign every HTTP request. |
Zone — address
| Field | Description |
|---|
address | Meross sub-device id (12 hex chars, e.g. 1B008FAD9F7C). Auto-populated by sync_zones. |
Commands
| Name | Args | Description |
|---|
pair | — | One-time cloud login to fetch the account key + hub uuid. Re-runnable after a password change. |
sync_zones | — | Enumerate sub-devices on the hub and auto-create matching GEM zones. |
on / off / open / close / stop | address | Generic verbs. Sprinklers route through Appliance.Control.Water; everything else through Appliance.Hub.ToggleX. |
level | address, level (0-100) | Sub-devices are binary; level > 0 is treated as on. |
heat_setpoint / cool_setpoint | address, setpoint (°C) | Thermostat valves. Enter the setpoint in plain °C (e.g. 21.5); the driver scales it to the hub's internal format. (Values above 50 are assumed to already be in the hub's ×10 form and passed through.) |
system_mode | address, mode (auto / cool / heat / off) | |
fan_mode | address, mode (auto / on) | |
get_state | address | Fetch current ToggleX state for one sub-device. |
get_all | — | Dump Appliance.System.All for diagnostics. |
Known quirks
- The hub stays subscribed to
mqtt-us-X.meross.com. The driver never alters broker config — the Meross app keeps working alongside GEM.
- Commands return
SETACK immediately; the hub does not push real-time state changes over local HTTP. State is refreshed only by polling.
- Newer firmware advertises
Appliance.Encrypt.ECDHE. This driver speaks plaintext HTTP only — msh400 firmware 4.5.36 works as-is; newer encrypted-only firmware does not.
- The cloud login signs with a hard-coded Meross app secret and the
v1/Auth/signIn endpoint. Meross occasionally bumps that contract; if pair fails after a Meross app update the constant may need refreshing.
Troubleshooting
pair fails with bad credentials. Verify email/password against the Meross app and confirm cloud_base matches your region (iotx-us / iotx-eu / iotx-ap).
- Commands return error
5001 "sign error". The stored key is stale (typically because the user changed their Meross password). Re-run pair.
- No zones after
sync_zones. Use get_all to inspect digest.hub.subdevice. An empty array means no paired sub-devices, or that the hub is currently offline.
- Every command times out. Hub may be rebooting or off-network; ping
<ip> first. Otherwise raise http_timeout for slow networks.