Reference
Every command the toolkit carries, with the same action in each language. Python and Node.js bind to the same core.
Find devices
scan
Look for devices and report what answers.
The scan runs in every enabled mode. scan_on restricts it to the modes you name, and enables none that the configuration leaves out.
let devices = govee.scan().await?;
let lan_only = govee.scan_on(&[Mode::Lan]).await?;govee scan
govee scan --mode landevices = await govee.scan()
lan_only = await govee.scan_on(["lan"])const devices = await govee.scan()
const lanOnly = await govee.scanOn(['lan'])devices
List the devices already known. It touches no network.
The lan cache answers from disk, so a device found once costs no scan on the next run.
for device in govee.devices() {
println!("{}", device.id());
}govee devicesfor device in govee.devices():
print(device.id)for (const device of govee.devices()) {
console.log(device.id)
}select
Name devices by identity, by SKU, by name or by group.
A target is an identity (1C:8B:…), a SKU (H6159), a name the configuration gives a device (kitchen), or a group the configuration gives (ambient). id:, sku:, name: and group: state the kind where the target alone does not. A SKU matches that model and no alias of it, and a name or a group matches whole. select reads the devices already known, so scan first. A handle for one device takes a name too, and reads it from the configuration with no scan.
let chosen = govee.select(["H6159", "kitchen"], None)?;
let kitchen = govee.device(&govee.target("kitchen")?);govee devices H6159
govee devices kitchen ambient
govee on kitchenchosen = govee.select(["H6159", "kitchen"])
kitchen = govee.device("kitchen")const chosen = govee.select(['H6159', 'kitchen'])
const kitchen = govee.device('kitchen')group
Send one command to every device of a group at once.
groups: in the configuration puts a device in a group. targets reads the members from the configuration with no scan. Each member answers one outcome over its own modes, and a member that fails stops no other one. group_on restricts every member to one mode. A member that does not enable it fails alone.
let ambient = govee.group(&govee.targets("ambient")?);
for outcome in ambient.brightness(40).await {
if let Err(error) = outcome.result {
eprintln!("{}: {error}", outcome.id);
}
}govee on ambient
govee brightness group:ambient 40identify
Light each device in turn, so a person maps an identity to a fixture in the room.
The device powers on, goes to the top of the brightness range its device file declares, and paints one color. govee identify walks a rig: every device goes off at once, one device at a time comes back on, and every device goes off again at the end. It walks the devices the targets name, or every device a scan finds. The walk drives lan, and the mode --mode names where it names one.
device.identify(&Identify::default()).await?;govee identify
govee identify H6159
govee identify 1C:8B:C4:A2:C0:46:64:6E kitchenawait device.identify()await device.identify()describe
Report what the device file declares for a model.
It reads no hardware. Use it to see the range of every argument before you send a value.
let spec = govee.device(&id).spec()?;govee describe DEVICEspec = govee.device(id).spec()const spec = govee.device(id).spec()status
Ask the device for its current state.
last_status returns the state already known and sends nothing.
let state = device.status().await?;
let cached = device.last_status();govee status DEVICEstate = await device.status()
cached = device.last_status()const state = await device.status()
const cached = device.lastStatus()watch
Follow events: a device appears, a mode changes health.
let mut events = govee.events();
while let Ok(event) = events.recv().await {
println!("{event:?}");
}govee watch
govee watch --jsonasync for event in govee.events():
print(event)for await (const event of govee.events()) {
console.log(event)
}for problem in govee.problems() {
eprintln!("{problem}");
}govee doctorfor problem in govee.problems():
print(problem)for (const problem of govee.problems()) {
console.error(problem)
}Control a light
power
Turn the device on or off.
device.power(true).await?;govee on DEVICE
govee off DEVICEawait device.power(True)await device.power(true)brightness
Set the brightness of the whole device.
The device file carries the range. A value outside it is an error, never a clamp. On a verified model 0 is clamped by the firmware to 1 and does not turn the device off.
device.brightness(40).await?;govee brightness DEVICE 40await device.brightness(40)await device.brightness(40)color
Set one color for the whole device.
device.color([255, 61, 0]).await?;govee color DEVICE "#ff3d00"await device.color((255, 61, 0))await device.color([255, 61, 0])color_temp
Set the white temperature, in kelvin.
It ends the color the device showed: white and color are two states that exclude each other. Where the mode carries the RGB rendering in the same frame, the core computes it and sends both.
device.color_temp(4000).await?;govee colortemp DEVICE 4000await device.color_temp(4000)await device.colorTemp(4000)segment
Paint the zones.
One color fills every zone. A list of colors states one zone each, which is how a mode that addresses every LED is painted pixel by pixel: ask for the native resolution and pass that many colors. With a list of zones, the zones you name take the one color and the rest stay as they are; that needs a mode that paints by mask. A count the unit renders as a smaller one is refused, and the message names the counts it refines at.
device.segment(&Paint {
zones: None,
colors: &frame,
resolution: Resolution::default(),
gradient: false,
}).await?;
device.segment(&Paint {
zones: None,
colors: &frame,
resolution: Resolution::Native,
gradient: false,
}).await?;govee segment DEVICE "#ff3d00"
govee segment DEVICE --zones 0,1,2 "#ff3d00"
# One color per LED, in zone order. `describe` reports how many.
govee segment DEVICE --resolution native "#ff3d00,#00a3ff,#000000,..."
# The same list, from a pipe or a file.
echo "#ff3d00,#00a3ff,#000000,..." | govee segment DEVICE --resolution native -await device.segment(colors=frame)
await device.segment(colors=frame, resolution="native")await device.segment(frame)
await device.segment(frame, null, "native")gradient
Set whether the firmware interpolates between zones, without painting.
The interpolation wraps from the last zone back to the first, so one lit zone at one end also lights the other. It is refused over a mode that carries the setting inside its painting frame: nothing there holds what the device shows, so the colors cannot be repainted under the other setting. Pass --gradient to segment over such a mode, which sets both at once.
device.gradient(true).await?;govee gradient DEVICE onawait device.gradient(True)await device.gradient(true)musicBLECLOUD
Play an effect the device renders from its own microphone.
The device listens and nothing streams from your host. The effect identifiers belong to the mode: the same number names another effect over another mode, and lan carries no music command at all. Nothing stops the effect — set a color, a temperature or the power to end it.
device.music(&Music {
effect: 3,
sensitivity: 60,
soft: false,
color: None,
}).await?;govee music DEVICE 3 --sensitivity 60await device.music(effect=3, sensitivity=60)await device.music(3, 60)Animate the segmentsLANBLE
open_stream
Open the segment channel and keep it armed.
The stream reports the zone count and the frame rate measured on the unit. It stays armed until you close it, and the colors end with it.
let stream = device.open_stream(StreamOptions::default()).await?;
println!("{} zones at {} Hz", stream.zones(), stream.rate_hz());# frames.txt: one frame per line, one color per zone.
govee stream DEVICE --resolution native < frames.txtstream = await device.open_stream()
print(stream.zones, stream.rate_hz)const stream = await device.openStream()
console.log(stream.zones, stream.rateHz)set_zone
Set one zone of the stream.
stream.set_zone(7, [255, 61, 0])?;# One frame per line, one color per zone.
echo "000000,ff3d00,000000" | govee stream DEVICE --resolution 3stream.set_zone(7, (255, 61, 0))stream.setZone(7, [255, 61, 0])set_all, fill and clear
Set every zone at once.
set_all takes one color per zone. fill gives every zone the same color. clear sets them to black.
stream.set_all(&frame)?;
stream.fill([255, 61, 0])?;
stream.clear()?;govee segment DEVICE "#000000"stream.set_all(frame)
stream.fill((255, 61, 0))
stream.clear()stream.setAll(frame)
stream.fill([255, 61, 0])
stream.clear()close
Close the channel.
A frame that a newer one replaces before it goes out is counted in frames_superseded. Nothing else disarms the channel.
println!("{} frames", stream.frames_sent());
stream.close().await?;# The stream ends when standard input ends.print(stream.frames_sent)
await stream.close()console.log(stream.framesSent)
await stream.close()Drive a rig over DMXLAN
govee-dmx profile
Print the channel table of one model, to patch a desk with.
Each personality is one table: full takes 6 channels, and segment and pixel take the zones the unit renders. It reads no hardware.
govee-dmx profile H6159
govee-dmx profile H6159 --personality segmentgovee-dmx patch
Scan the LAN and write the patch the node runs from.
The command appends: it gives the lowest free channels to each device that has no entry, and it moves no entry the file already carries, because an address is patched on the desk too. --patch names a file other than patch.yaml, and --dry-run writes nothing.
govee-dmx patch
govee-dmx patch --personality segment --universe 1
govee-dmx patch --dry-rungovee-dmx identify
Light each patched fixture in turn, so a person reads the rig.
The walk lights the fixtures in patch order, over lan. A target names the device of a fixture, in the grammar select reads, and a name reads the name: of the patch before the configuration. --universe and --address name fixtures by the channels they answer to: --address lights the fixture that answers to that channel, and not only the one that starts there.
govee-dmx identify
govee-dmx identify --address 33
govee-dmx identify --universe 1
govee-dmx identify H6159 kitchengovee-dmx run
Receive Art-Net on port 6454 and drive the patched devices.
The node answers every poll, so a desk lists it and patches it. --scan writes the missing entries first. --dry-run prints every packet and what each fixture reads out of it, and writes to no device.
govee-dmx run
govee-dmx run --scan
govee-dmx run --dry-run --debugRaw commands and setup
send
Send one entry of the device file, by name.
It works for a model this build has never heard of. The entry declares the type of every argument, and the range stays the core's to check. read is the same for an entry that returns an answer.
device.send("brightness", &args).await?;
let reply = device.read("status", &args).await?;govee send DEVICE brightness --arg level=40await device.send("brightness", level=40)
reply = await device.read("status")await device.send('brightness', { level: 40 })
const reply = await device.read('status')provision_wifiBLE
Put a new device on a Wi-Fi network, over Bluetooth.
This is how a device out of the box becomes reachable over lan. The password travels in plaintext with no key exchange: anything in Bluetooth range while it runs can read it.
device.provision_wifi(&credentials).await?;govee provision DEVICE --ssid my-networkawait device.provision_wifi("network name", "password")await device.provisionWifi("network name", "password")Choose a mode
Restrict a command to one mode.
It never enables a mode the configuration leaves out, and it never falls back. A device that no enabled mode reaches is an error.
let mode = device.serving_mode()?;
let health = device.health(Mode::Lan);govee on DEVICE --mode lanmode = device.serving_mode()
health = device.health("lan")const mode = device.servingMode()
const health = device.health('lan')