Expose events and controls from Govee devices to an MQTT broker, especially for HomeAssistant
10K+
Expose multiple Govee devices and events to an MQTT broker, primarily designed to work with Home Assistant. Forked from dlashua/govee2mqtt
A few notes:
devices x (86400 / GOVEE_DEVICE_INTERVAL) for the polling loop, plus 86400 / GOVEE_LIST_INTERVAL for the device list itself, plus one call per sensor per rescan (a sensor's readings are checked before it is adopted), plus one call per command you send.
The GOVEE_DEVICE_INTERVAL default of 30 only suits a handful of devices - 28 devices would spend 80,640 calls/day on state polls alone, and even at 180 seconds it is 13,440. Around 360 seconds is what 28 devices need to stay comfortably inside the quota.light.<name>_group), but they cannot report their own state - see Device Groups Are Write-OnlyFor docker-compose, use the configuration included in this repository.
Using the docker image, mount your configuration volume at /config and include a config.yaml file (see the included config.yaml.sample file as a template).
The recommended way to configure govee2mqtt is via the config.yaml file. See config.yaml.sample for a complete example with all available options.
mqtt:
host: 10.10.10.1
port: 1883
username: mqtt
password: password
qos: 0
protocol_version: "5" # MQTT protocol version: 3.1.1/3 or 5
prefix: govee
discovery_prefix: homeassistant
# TLS settings (optional)
tls_enabled: false
tls_ca_cert: filename
tls_cert: filename
tls_key: filename
govee:
api_key: xxxxx-xxx-xxxxxx # see https://developer.govee.com/reference/apply-you-govee-api-key
device_interval: 30 # polling interval; estimate 30 sec per 10 devices due to API rate limits
device_boost_interval: 2 # faster polling after state changes
device_list_interval: 300 # how often to refresh device list
timezone: America/New_York # see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
While the config file is recommended, environment variables are also supported. See ENVIRONMENT_VARIABLES.md for the full list of available environment variables.
The Govee API has significant limitations that affect what this integration can do. These are not bugs in govee2mqtt - they are limitations of the Govee API itself. See the Govee API documentation for reference.
The Govee API does not report the current state of these settings, so govee2mqtt cannot know their initial state on startup:
Groups you create in the Govee app (BaseGroup / SameModeGroup) show up in the device list, but
/device/state and /device/scenes both reject them with devices not exist. They are adopted as
on/off-only lights, and because there is no state to read, govee2mqtt never polls them — the entity
reflects the last command it sent, not what the group is really doing. Change a group from the Govee
app or turn off one of its members and Home Assistant will not notice.
The API also under-reports groups in two ways. It never says what is in one — the payload is a
name and powerSwitch, which would look identical for a group of humidifiers — so the light domain
is an assumption. And it advertises only powerSwitch even where the Govee app can clearly do more:
a Same Model group (all members identical) offers the full capability set in the app, and a
General Group (mixed members, e.g. "Bedroom Red") offers on/off, colour, brightness and scenes.
Neither shows up in the API, and whether /device/control would accept them anyway is untested.
Group entities are named for what they are — light.great_room_lamps_group rather than
light.great_room_lamps_light —
both because it reads better and because a group sharing a name with a real device would otherwise
contest its entity_id and be handed a _2 suffix permanently.
A sensor with no WiFi path (an H5074, for instance, with no Govee gateway) is listed by
/user/devices but answers online: false with an empty string for every reading, so the cloud
API can see that it exists and never what it says. govee2mqtt does not adopt a sensor that reports
nothing — entities that can never hold a value are worse than no entities, and polling them costs
API quota to keep learning nothing. If such a sensor later gains a gateway it is adopted on the
next rescan. Home Assistant's own Govee BLE integration reads these directly over Bluetooth.
The API sometimes reports incorrect capabilities for devices. For example, the H6042 Smart TV Light Bar reports MusicMode options that don't actually work when sent back to the API, while the mobile app offers completely different (working) options.
Docker is the only supported way of deploying the application. The app should run directly via Python but this is not supported.
A few people have kindly requested a way to donate a small amount of money. If you feel so inclined I've set up a "Buy Me A Coffee" page where you can donate a small sum. Please do not feel obligated to donate in any way - I work on the app because it's useful to myself and others, not for any financial gain - but any token of appreciation is much appreciated 🙂
unique_id contractHome Assistant assigns an entity_id once, at first discovery, and keys its registry on
unique_id. It never reassigns that entity_id afterwards — not when the entity is renamed, and
not when discovery is cleared and republished. This was verified directly: clearing the retained
discovery topic, waiting 25 seconds, and republishing restores the identical entity_id.
Two rules follow, and breaking either one strands an entity permanently:
Never reuse a unique_id for a different entity. If a component's meaning changes, mint a
new unique_id deliberately.
Every component publishes an explicit def_ent_id, derived from its stable component key
rather than its display name. Without it HA derives the entity_id from the display name, so
renaming a component in a later release leaves its entity_id describing the old name — and a
differently-named component can end up owning it.
This option used to be obj_id (object_id). HA Core 2026.4 removed it, after deprecating
it in 2025.10; it is not aliased, so a payload still publishing obj_id silently loses control
of its entity_ids. The replacement, default_entity_id/def_ent_id, takes a full
entity_id (light.great_room_lamps_light) rather than a bare slug. mqtt_helper.obj_id()
still computes the slug; mqtt_helper.apply_default_entity_ids() pairs it with each component's
domain at publish time.
It cannot be fixed from this service, because no MQTT message can reassign an entity_id. Rename
it in Home Assistant under Settings → Devices & Services → Entities. If two entities have
swapped ids, rename the squatter first to free the id, then rename the correct entity into it.
The Reset discovery button clears and republishes retained discovery and sweeps orphaned
configs for devices that no longer exist. It does not reassign entity_ids.
Content type
Image
Digest
sha256:d778b78f3…
Size
146.4 MB
Last updated
4 days ago
docker pull graystorm/govee2mqtt