Big Ass Fans
The Big Ass Fans driver controls i6 and Haiku smart ceiling fans — fan speed, direction, the Whoosh oscillation mode, and, on fans fitted with an integrated light, the light's on/off, brightness, and color temperature. GEM talks to each fan directly over the fan's own local network protocol (TCP, port 31415), so there is no Big Ass Fans cloud account and no hub in the middle.
One Big Ass Fans GEM device acts as a controller that finds every fan on the network for
you. Each discovered fan becomes its own GEM zone that GEM creates for you, and a fan that
has an integrated light gets a second zone for that light. You never add or address a zone by
hand — power the fans up on the same network as GEM, enable the device, and run the scan
command; the zones appear.
Fans announce themselves over mDNS / Bonjour (the _api._tcp service). The GEM device has
no IP-address field because it doesn't need one: it listens for the fans' announcements and
connects to each on its own. The one hard requirement is that GEM and the fans sit on the same
local network (same VLAN / subnet) so those announcements reach GEM.
Adding a fan GEM has never seen is an explicit step — run the scan command. Fans that
already have zones reconnect and follow IP changes on their own, with no scan needed. See
Which fans GEM adopts.
Prerequisites
- Big Ass Fans i6 or Haiku hardware on the same LAN as GEM, with no VLAN isolation between them — mDNS must be able to travel from the fans to the GEM controller. (If they must live on separate VLANs, an mDNS reflector / Avahi reflector has to bridge them, or GEM won't see the fans.)
- Each fan paired and working in the Big Ass Fans mobile app at least once before you add it to GEM. GEM discovers and controls fans the app has already set up; it does not perform the initial Wi-Fi onboarding.
Setup — adding the controller
- Open Devices, add a device, and choose the Big Ass Fans (i6, Haiku) driver.
- There are no connection fields to fill in — discovery is automatic. Save and enable the device.
- Run the
scancommand from the device's Commands tab. It sweeps the network over mDNS, returns what it found (name, IP, device id, model, API version), and adopts each fan it finds — creating a zone per fan (see below). Give it the length of the sweep, 10 seconds by default. - Adding another fan later? Run
scanagain. Fans that already have zones need nothing — they reconnect on their own whenever they reappear on the network.
The driver remembers each fan's IP (in the zone's fan_ip attribute) and reconnects straight to
it on the next restart, even before mDNS answers. A DHCP reservation per fan keeps that
stored address valid so reconnection is instant and reliable after a reboot.
How zones are created
When the device connects to a fan, GEM creates a fan zone for it. The first time that fan reports light data, GEM adds a light zone as well:
| What's discovered | Zone goes in subsystem | On-screen control | Zone address |
|---|---|---|---|
| The fan itself | Fans | Fan control (speed, direction) | the fan's device id |
| The fan's integrated light (if any) | Lights | Dimmer control | <device id>:light |
- The fan zone's address is the fan's Big Ass Fans device id (its mDNS UUID); its on-screen label is the fan's name from the app. GEM fills both in — you don't type them.
- A light zone is created only when the fan actually reports a light module. Fans without an integrated light never get a light zone, and light commands sent to such a fan are silently ignored.
- The zone name is built from the fan's own name with no device prefix, so it competes with every zone name on the system. If the name is already taken, GEM appends the fan's device id rather than failing the create — the label is unaffected. See auto-created zones.
- You can move a zone to a different subsystem afterward in Zones if your site organizes fans or lights differently.
The fan zone goes in your standard Fans subsystem and the light zone in your standard Lights subsystem. If a site has renamed or removed those default subsystems, the new zone follows the closest-named subsystem instead — check there if a fan or its light doesn't appear where you expect.
Which fans GEM adopts
mDNS announcements are unauthenticated — anything on the network can announce itself as a Big Ass Fan, under as many different device ids as it likes. So GEM does not turn every announcement into a zone. It adopts a fan when:
- it already has a zone — the normal case. Configured fans reconnect whenever they reappear and GEM follows their IP if it changes, with no scan and no window. This covers everything on a site that is already commissioned, including fans whose zone you have disabled.
- you ran
scan— the sweep adopts what it finds, and adoption stays open for 5 minutes after it ends. allow_passive_adoptis on — the standing opt-in, off by default. Turn it on if fans are added to the site often enough that running a scan is friction, and you are comfortable with any announcing device becoming a zone.
Anything else is logged once (ignoring undiscovered fan, with the device id and IP) and otherwise ignored — no zone, no connection, no reconnect timer. A single device also holds at most 64 fans; past that, new ids are refused and a warning is logged, while already-known fans keep working.
Nothing changes for fans that already have zones — they reconnect exactly as before. The only
new step is adding a fan GEM has never seen, which now needs a scan (already step 3 of
setup) or the opt-in above.
Speed, state, and the 0–7 scale
Big Ass Fans run on an internal 0–7 speed scale. GEM maps that to the familiar 0–100 level and to the Off / Low / Medium / High state you see on the fan control:
- A level of 0–100 is converted to a speed step by rounding down — any level above 0 runs at least speed 1. Rounding down keeps the fan control's preset levels on their intended speeds: 33% → speed 2 (Low), 66% → speed 4 (Medium), 100% → speed 7 (High).
- The level GEM reports back rounds up from the running speed, so a reported level always converts back to the same speed — the control and the fan stay in agreement.
- The state label is derived from the running speed and the three speed-preset attributes: off when the fan is off, low up to the Low Speed value, medium up to Medium Speed, and high above that.
The three preset speeds are device attributes you can tune (see Attributes). Their defaults are Low = 2, Medium = 4, High = 6 on the 0–7 scale.
on runs the fan at Medium, not HighThe plain on command (and the fan control's on button) starts the fan at the Medium
Speed preset — not full speed. Use high (or set a level) when you want maximum airflow.
Keeping state current
GEM polls every connected fan for its status once a minute, and it also re-reads a fan immediately after sending it a command, so a change you make from GEM updates on screen without waiting for the next poll. Alongside speed and state, each fan reports its onboard temperature (°C) and humidity (%RH), plus occupancy from its motion sensor — GEM records these on the fan zone so they can drive triggers and automations. If a fan drops off the network, GEM retries the connection about every 30 seconds until it returns.
Commands
Driver-declared commands appear on the device's Commands tab and can be used in macros,
triggers, and on UI buttons. Every command except scan takes the target zone's address,
which GEM fills in from the zone you pick.
The same command names — on, off, level — apply to both the fan zone and the light
zone; GEM routes each to the fan or to the light based on which zone you target. The remaining
commands act only on their respective zone type.
Fan (target a fan zone)
| Command | Action |
|---|---|
on | Start the fan at the Medium Speed preset. |
off | Stop the fan. |
high / medium / low | Start the fan at the High / Medium / Low Speed preset (default speeds 6 / 4 / 2). |
level (arg level) | Set fan speed by percentage. 0 stops the fan; 1–100 rounds down to a 1–7 speed step (never below speed 1). |
direction (arg direction) | Set rotation. forward (downdraft / summer) or reverse (updraft / winter). |
whoosh (arg value) | Toggle Whoosh — a natural-breeze mode that gently varies the speed. Any value except off, false, or 0 turns it on. |
Light (target the light zone)
| Command | Action |
|---|---|
on | Turn the integrated light on, restoring its last brightness. |
off | Turn the integrated light off. |
level (arg level) | Set brightness, 0–100. 0 turns the light off. |
color_temp (arg value) | Set the light's color temperature in kelvin (warmer to cooler, e.g. 2700–5000). |
Discovery
| Command | Action |
|---|---|
scan (arg timeout) | Sweep the network for Big Ass Fans over mDNS, return the discoverable list (name, IP, device id, model, API version), and adopt what it finds — this is how a fan GEM has never seen gets its zone. Takes no address. Default sweep length is 10 000 ms; pass timeout (ms) to lengthen it. Adoption stays open for 5 minutes after the sweep ends, so a fan powered up while you are working is still picked up. |
Attributes
Device — optional
These tune how the speed presets behave. They take effect on the running fans, so adjusting one
changes what on / high / medium / low send and where the Low/Medium/High state boundaries
fall.
| Attribute | Type | Default | Description |
|---|---|---|---|
high_speed | int | 6 | Speed (1–7) used by the High button and the high command, and the upper bound for the "high" state. |
medium_speed | int | 4 | Speed (1–7) used by on and the medium command, and the boundary for the "medium" state. |
low_speed | int | 2 | Speed (1–7) used by the low command, and the boundary for the "low" state. |
allow_passive_adopt | boolean | off | Adopt a fan GEM has never seen straight from its mDNS announcement, with no scan. See Which fans GEM adopts. |
Zone
GEM populates these as it discovers and polls each fan — you don't set them by hand:
| Attribute | Applies to | Description |
|---|---|---|
fan_ip | fan zone | The fan's last-known IP, used to reconnect on restart before mDNS answers. |
state | both | Fan: off / low / medium / high. Light: on / off. |
level | both | Fan speed or light brightness as 0–100. |
direction | fan zone | forward or reverse. |
whoosh | fan zone | Whether Whoosh mode is on. |
occupied | fan zone | The fan's motion sensor — true when it detects occupancy. |
temperature | fan zone | Onboard temperature reading, in °C. |
humidity | fan zone | Onboard relative humidity, in %RH. |
color_temp | light zone | The light's current color temperature, in kelvin. |
These names are cataloged, so they autocomplete in the Attribute editor and can drive attribute
triggers — for example, fire a macro when a fan's occupied becomes true, or when the zone's
temperature crosses a threshold.
Troubleshooting
| Symptom | Check |
|---|---|
| No zones appear after enabling the device | Run the scan command — adopting a fan GEM has never seen is an explicit step. If scan returns nothing, the fans must be on the same VLAN/subnet as GEM so mDNS reaches it; confirm they're visible from a workstation on that network with avahi-browse _api._tcp (or an equivalent Bonjour browser). |
| A newly installed fan hasn't appeared | Run scan again. Only fans that already have zones are picked up automatically; a fan GEM has never seen waits for a scan, or for allow_passive_adopt to be turned on. |
| The device log says ignoring undiscovered fan | That is this rule working: something announced itself as a fan and GEM has no zone for it. Run scan if it is yours. If the device id is not one of your fans, something on the network is advertising as a Big Ass Fan. |
| A fan is found but has no light zone | That fan has no integrated light module — GEM only creates a light zone for fans that report one. Confirm the light works from the Big Ass Fans app. |
| Light commands return an error | Same cause — the fan likely has no light. Target a fan that reports a light module. |
The fan won't run at full speed from on | By design — on runs the Medium Speed preset. Use high, or raise the Medium Speed attribute, or send a higher level. |
| State drifts after the fan is used from its wall remote or the app | GEM polls once a minute; give it up to a minute to re-sync, or operate the fan from GEM so it re-reads immediately. |
| A fan stops responding after a reboot | Its IP may have changed. Give each fan a DHCP reservation so the stored fan_ip stays valid and reconnection is reliable. |
See also
- Devices — adding and enabling the controller device.
- Zones — the per-fan and per-light zones the driver auto-creates.
- Subsystems — the Fans and Lights subsystems the zones land in.
- Commands — running and scripting the fan and light commands.
- Attributes — tuning the speed presets and reading live fan state.
- Macros and Triggers — automating fans and reacting to occupancy, temperature, and humidity.