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.1.0.tar.gz (13.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.1.0-py3-none-any.whl (12.1 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: gmg_local-0.1.0.tar.gz
  • Upload date:
  • Size: 13.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.1.0.tar.gz
Algorithm Hash digest
SHA256 785fe8db6414b45f216aa6641259e413246eccad32196df9c17dc6100b98b9b3
MD5 b3a62a322648a22b2427c5ebe8952d5e
BLAKE2b-256 c8f9c1b1ea2afb425a6770124a283fface7d4c5234029de64668c9064831e118

See more details on using hashes here.

Provenance

The following attestation bundles were made for gmg_local-0.1.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.1.0-py3-none-any.whl.

File metadata

  • Download URL: gmg_local-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 12.1 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.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b8ab0acb9b7e1bc78a9601230445c23b4d2e71aeda0ddd9480da7f8db54be83b
MD5 3114a825bb9288544271cbe91923a6f0
BLAKE2b-256 bf4b6a65a3156ab64fa0835bda716bb029112f04ba4a2324cb186360f0eed887

See more details on using hashes here.

Provenance

The following attestation bundles were made for gmg_local-0.1.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