Skip to main content

gmg-local

Local UDP client for Green Mountain Grills Wi-Fi pellet grills.

No cloud account, no vendor API, no internet. It talks to the grill on your LAN and nothing else.

Not on PyPI yet - built and tested, awaiting a decision to publish. Origin and attribution: NOTICE.md.

from gmg_local import discover

for grill in discover():
    state = grill.status()
    print(grill.serial_number, state["temp"], "F")

Why this exists

Every public Python implementation of this protocol froze on 2023-01-28. The most-installed Home Assistant integration for these grills reads grill temperature from a single byte, so a 350 °F grill reports as 94 °F - the one number the device exists to tell you.

u16(94, 1) == 350   # not 94

Install

pip install -e .          # from a clone; not on PyPI yet

Requires Python 3.11+. No dependencies.

API

discover(timeout=1, ip_bind_address="0.0.0.0", target=None) Broadcast for grills. Pass target to unicast across VLANs, where broadcast dies at the L2 edge.
Grill.status(retries=5) One poll, decoded. Retries on silence and on junk.
Grill.set_temp(f) / set_temp_probe(f, n) Targets, in Fahrenheit.
Grill.power_on() / power_on_cool() / power_off() Cold smoke is power_on_cool.
parse_status(frame) Pure. No sockets, no clock - testable without a grill.
poll_interval_for(state) 10s while cooking, 60s while off.

What the status frame contains

A healthy grill answers UR001! with 52 bytes; this library decodes through byte 33.

offset field notes
2, 4, 6 grill temp, probe 1, setpoint 16-bit LE pairs
8 API version
16, 18 probe 2 temp and setpoint
24-27 warn state 32-bit LE
28 probe 1 setpoint
30 power state 0 Off, 1 On, 2 Fan, 3 Cold Smoke
32 fire state 0 Default, 1 Off, 2 Startup, 3 Running, 4 Cool Down, 5 Fail, 198 Cold Smoke
33 fire state progress see below
34-51 undecoded gmg 0.0.4 labels 48 and 50 as pellet alarms - unverified

Byte 33

Emitted as fireStatePercentage. GMG's own cloud API names this field fireStateProgress, paired with fireState.

It is a four-step progress marker through whatever fire state the grill is currently in. Across a full instrumented cycle it ran 25 → 50 → 75 → 100 during Startup, hitting 100 at the exact second the grill switched to Running, then 75 → 50 → 0 through Cool Down, hitting 0 as the fan stopped.

Two readings are ruled out by that data:

  • Not a startup-stage index. A stage counter does not run backwards.
  • Not a pellet-hopper level. A hopper does not fill during ignition and empty when the fan stops. One public implementation labels it hopper_pct and ships it as a pellet gauge; it reads 100% on a hot grill and 0% on a cold one.

What each 25% step physically means is unknown, and is not in the packet. Display the step number; do not invent labels.

Things the hardware does that will surprise you

  • Probe writes are silently discarded while the grill is off. Write 203, read back 0. No error, no acknowledgement.
  • The grill serves one client at a time. Concurrent conversations lose messages, so all I/O here is serialised behind a lock.
  • Short datagrams happen. They are a transport artifact, not data. Parsing one either raises or invents fields; this library retries instead.
  • Temperature keeps rising after the fire is cut - roughly 18 °F over a minute in one observed shutdown.

Tests

pip install -e ".[dev]" && pytest

The fixtures are reconstructed - real decoded observations re-encoded at the documented offsets - not captured frames. They prove the parser is self-consistent with observed behaviour, not that the offsets are correct. Offsets are corroborated across four independent implementations.

Preserving a genuine 52-byte capture is the prerequisite for decoding bytes 34-51, and should replace these fixtures when one exists.

Credits

See NOTICE.md. Original integration by jwhitby91; protocol cross-checked against brandenc40/green-mountain-grill and Christopher McKay's gmg.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

gmg_local-0.2.0.tar.gz (19.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

gmg_local-0.2.0-py3-none-any.whl (12.3 kB view details)

Uploaded Python 3

File details

Details for the file gmg_local-0.2.0.tar.gz.

File metadata

  • Download URL: gmg_local-0.2.0.tar.gz
  • Upload date:
  • Size: 19.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for gmg_local-0.2.0.tar.gz
Algorithm Hash digest
SHA256 54a08c1cf0202bcaa37ebb0ea68c8a510ea936d0cbb2c0c878688b43ab7b808b
MD5 70770074878dea5ab065aecce1f80f38
BLAKE2b-256 e768ddb5f2d0a0cc9044a00ddb450a4bb1dc59a3f204b7f0e1b44aa319ce8a08

See more details on using hashes here.

Provenance

The following attestation bundles were made for gmg_local-0.2.0.tar.gz:

Publisher: publish.yml on y3klab/gmg-local

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file gmg_local-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: gmg_local-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 12.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for gmg_local-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a80fbbb91a41e6ce1e482c1c78bc5386d58c8eb96c84ec572365bda85fcb9f52
MD5 f0b998c78c4dd5fd6f6dd69b3544322f
BLAKE2b-256 38c4432df3ad3f5a4451f6c24332417c7e53c7dd55b1c3ee5b642ed9e71fc1dc

See more details on using hashes here.

Provenance

The following attestation bundles were made for gmg_local-0.2.0-py3-none-any.whl:

Publisher: publish.yml on y3klab/gmg-local

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page