Vizio SmartCast TV
The Vizio driver controls SmartCast TVs through the local HTTPS API with a PIN-pair handshake that mints a long-lived bearer token. One GEM device represents one TV.
Status
PIN pairing, power, volume, mute, current-input read/write, navigation keys, and raw key passthrough are implemented. Picture-mode and audio-mode setpoints, app launching ("Cast to Netflix"), and on-screen content metadata are out of scope for this driver — use the TV remote or the SmartCast mobile app for those.
Prerequisites
- SmartCast TV (2016+) with Power Mode = Quick Start enabled in the TV settings — Eco mode powers down the API when the screen is off.
- Static IP or DHCP reservation on the TV.
- Physical access to the TV during initial pairing — a 4-digit PIN displays on-screen.
- TCP
7345(older firmware) or9000(newer SmartCast) reachable from the GEM host.
Setup
- Reserve the TV's IP in DHCP.
- In System > Devices, create a device with driver
vizio_smartcast. Set:ip— TV IPport—7345(older) or9000(newer)- Leave
auth_tokenblank for now.
- Turn the TV on. From the Script Console run:
The TV will display a 4-digit PIN.await gem.command({device: <device_id>, action: 'pair_start'});
- Within the pairing window, run:
On success the response isawait gem.command({device: <device_id>, action: 'pair_finish', args: {pin: '1234'}});
{status: 'paired', message: 'auth_token saved.'}. The bearer token is stored encrypted as theauth_tokenattribute and the driver re-authenticates automatically. - Verify:
await gem.command({device: <device_id>, action: 'get_power'});await gem.command({device: <device_id>, action: 'get_current_input'});
If pair_start returns 404, the TV is on the other port — flip port between 7345 and 9000 and retry.
Attribute reference
Device attributes
| Attribute | Type | Required | Description |
|---|---|---|---|
ip | string | yes | TV LAN IP. |
auth_token | string (secure) | for control | Bearer token returned by pair_finish. Sent as the AUTH request header. |
port | int | no | 7345 (older) or 9000 (newer SmartCast). Default 7345. |
device_id | string | no | Identifier the TV stores against the issued token. Defaults to gem-<device id>. |
device_name | string | no | Friendly name shown in the TV pairing list. Default GEM Controller. |
status_interval | int | no | Poll interval in milliseconds. Default 10000. |
The driver reflects the following attributes onto the device:
| Attribute | Type | Source |
|---|---|---|
power_state | string | on / off from /state/device/power_mode/. |
current_input | string | HDMI-1, HDMI-2, CAST, SMARTCAST, etc. |
volume | int | 0-100. |
Zone address format
This driver does not use zones — each TV is its own device.
Commands
| Command | Args | Notes |
|---|---|---|
power_on / power_off / power_toggle | — | Power keypress. |
volume_up / volume_down | — | |
volume | level (0-100) | Absolute set via MODIFY+HASHVAL on /menu_native/dynamic/tv_settings/audio/volume. |
mute_on / mute_off / mute_toggle | — | |
get_inputs | — | Returns the full input list — pass the NAME field to set_input. |
get_current_input | — | |
set_input | input | Exact input NAME (case-sensitive, e.g. HDMI-1). |
nav | key | One of up, down, left, right, ok, back, exit, menu, info. |
send_key | codeset, code | Raw KEYPRESS for codes not exposed above. |
pair_start / pair_finish / pair_cancel | pin (finish) | Pairing flow — see Setup. |
Known limitations
- App launching (Netflix, YouTube, etc.) requires the deeper SmartCast app catalog API which Vizio has rotated multiple times — not implemented.
- Picture/audio preset setpoints are reachable via raw
send_keybut no convenience commands are wrapped. - Re-pairing produces a fresh
auth_token; old tokens stop working silently. Plan to re-run the pair flow if you ever factory-reset the TV.
Troubleshooting
| Symptom | Check |
|---|---|
pair_start returns 404 | Wrong port. Flip port between 7345 and 9000 and retry. |
| 401 or empty responses on commands | auth_token was rotated. Re-run pair_start + pair_finish. |
Power state always reads off | TV is in Eco power mode; switch to Quick Start so the API stays reachable when the screen is off. |
set_input does nothing | Run get_inputs and pass the exact NAME (case-sensitive, hyphen-separated, e.g. HDMI-1). |
Volume command returns {error: 'failed to read current volume'} | The TV needs an authenticated GET to mint a fresh HASHVAL — confirm auth_token is set and not stale. |