alexactl

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 19, 2026 License: MIT Imports: 27 Imported by: 0

README

alexactl

CI Go Reference License

A Go library for controlling Amazon Echo / Alexa devices and skill-discovered smart-home endpoints (lights, switches, locks, thermostats, fans, …).

Status: v0.1.0 — MVP. Mirrors functionality of the Python library aioamazondevices. The API is still stabilizing pre-1.0; expect breaking changes in MINOR releases. See CHANGELOG.md for per-release detail.

Install

go get github.com/Fishwaldo/alexactl

Quickstart

package main

import (
    "context"
    "fmt"
    "log"

    "github.com/Fishwaldo/alexactl"
)

func main() {
    ctx := context.Background()

    client, err := alexactl.NewClient()
    if err != nil {
        log.Fatal(err)
    }

    session, err := client.Auth.Login(ctx, "you@example.com", "your-password",
        alexactl.OTPProviderFunc(func(ctx context.Context) (string, error) {
            var otp string
            fmt.Print("Enter Amazon OTP: ")
            fmt.Scanln(&otp)
            return otp, nil
        }))
    if err != nil {
        log.Fatal(err)
    }
    _ = session // persist to disk for next run

    devices, err := client.Devices.List(ctx)
    if err != nil {
        log.Fatal(err)
    }
    for _, d := range devices {
        fmt.Printf("%s (%s, online=%v)\n", d.AccountName, d.SerialNumber, d.Online)
    }
}
Smart-home control

Capability-gated typed accessors on *Device return nil if the device does not advertise the corresponding Alexa interface — callers write capability-conditional code without sniffing strings:

for _, d := range devices {
    if pc := d.Power(); pc != nil {
        _ = pc.On(ctx)
    }
    if bc := d.Brightness(); bc != nil {
        _ = bc.Set(ctx, 80) // 0..100
    }
    if cc := d.Color(); cc != nil {
        _ = cc.Set(ctx, alexactl.ColorFromRGB(255, 64, 0))
    }
    if lc := d.Lock(); lc != nil {
        _ = lc.Lock(ctx)
    }
    if tc := d.Thermostat(); tc != nil {
        _ = tc.SetTarget(ctx, 21, alexactl.TemperatureScaleCelsius)
    }
    if mc := d.Mode("Apparatus.FanSpeed"); mc != nil {
        _ = mc.Set(ctx, "L3")
    }
}

See cmd/alexactl/ for a full CLI example.

CLI test harness

cmd/alexactl/ is a Cobra/Viper CLI mirroring the Python library_test.py. Build and use:

go build -o alexactl ./cmd/alexactl

# Interactive login (prompts for OTP)
./alexactl login --email you@example.com --password 'your-password'

# Inventory + state
./alexactl devices list
./alexactl devices list --detail
./alexactl sensors list

# Media (Echo speakers). Every single-device command takes --device
# (serial or friendly name); omit it to use the configured default-device.
./alexactl speak    "hello"        --device "Kitchen"
./alexactl announce "dinner ready" --device "Kitchen"
./alexactl volume   30             --device "Kitchen"
./alexactl music    AMAZON_MUSIC "miles davis" --device "Kitchen"
./alexactl sound play amzn_sfx_doorbell_01     --device "Kitchen"
./alexactl dnd set  on             --device "Kitchen"

# Smart-home control
./alexactl devices power      on --device "Lamp"
./alexactl devices brightness 80 --device "Lamp"
./alexactl devices color      ff4000 --device "Lamp"
./alexactl devices lock       --device "Front Door"
./alexactl devices thermostat set-target 21 c --device "Hallway"
./alexactl devices mode set   Apparatus.FanSpeed L3 --device "AC"

Configuration can also be supplied via ./config.yaml:

email: you@example.com
password: your-password
session_file: session.json
site: https://www.amazon.com

Environment variables use the AMZ_ prefix (e.g., AMZ_EMAIL, AMZ_PASSWORD).

Feature parity vs aioamazondevices

Feature Phase Status
OAuth + MFA login, session persistence 1
Device listing 1
Speak / Announce / SetVolume 1
Music, Sounds, Skills, Routines 2
Sensors, DnD, Notifications, History 2
HTTP/2 push events 3
Smart-home: Power, Brightness, Color, ColorTemp 4
Smart-home: Thermostat, Lock 4
Smart-home: Mode (typed) + Range/Toggle (stubbed) 4 ✅¹

¹ Device.Range and Device.Toggle accessors are wired into the capability-gate but their write methods return ErrControllerNotImplemented pending a confirmed HAR capture of the wire payloads. File an issue with a HAR if you have a device that exposes either controller.

License

MIT. See LICENSE.

This library is heavily inspired by aioamazondevices, which is licensed under Apache-2.0. See NOTICE for attribution.

Documentation

Overview

Package alexactl is a Go client for Amazon Echo / Alexa devices.

It provides functional parity with the Python aioamazondevices library (https://github.com/chemelli74/aioamazondevices) using idiomatic Go.

Index

Constants

View Source
const (
	// ClassRealtime — live device state. Default TTL 15s.
	ClassRealtime = cache.ClassRealtime
	// ClassShort — schedules, lists, DnD. Default TTL 5m.
	ClassShort = cache.ClassShort
	// ClassLong — catalogues, devices. Default TTL 1h.
	ClassLong = cache.ClassLong
)
View Source
const UpstreamVersion = "14.2.0"

UpstreamVersion records the version of aioamazondevices whose behavior this library mirrors. Bumped when this library catches up to a new upstream tag.

Variables

View Source
var (
	// ErrCannotAuthenticate is returned when the credentials are rejected
	// or a previously valid session is no longer usable.
	ErrCannotAuthenticate = errors.New("alexactl: cannot authenticate")

	// ErrCannotConnect is returned when network-level errors prevent any
	// response from being received.
	ErrCannotConnect = errors.New("alexactl: cannot connect")

	// ErrCannotRetrieveData is returned when Amazon returns a non-OK HTTP
	// status that isn't an auth failure.
	ErrCannotRetrieveData = errors.New("alexactl: cannot retrieve data")

	// ErrCannotRegisterDevice is returned when /auth/register fails during
	// the OAuth flow.
	ErrCannotRegisterDevice = errors.New("alexactl: cannot register device")

	// ErrDeviceNotFound is returned when callers reference a device by
	// serial number that isn't present in the cache.
	ErrDeviceNotFound = errors.New("alexactl: device not found")

	// ErrWrongMethod is returned when callers invoke a login method that
	// doesn't match the available state (e.g., Restore without a Session).
	ErrWrongMethod = errors.New("alexactl: wrong login method")

	// ErrReauthRequired signals that the caller must run Auth.Login again.
	// Surfaced by the Phase-3 push event stream before the channel closes.
	ErrReauthRequired = errors.New("alexactl: reauth required")

	// ErrCannotControlDevice is returned when Amazon's setEndpointFeatures
	// mutation responds with a structured error for one of the requested
	// FeatureControl entries (e.g. "INVALID_VALUE" for out-of-range
	// brightness, "ENDPOINT_UNREACHABLE" for an offline smart plug).
	// Wrapped errors carry the upstream `code` and `message` via the
	// formatted string; callers can `errors.Is(err, ErrCannotControlDevice)`
	// to distinguish protocol-level rejections from transport errors
	// (which return ErrCannotConnect / ErrCannotRetrieveData).
	ErrCannotControlDevice = errors.New("alexactl: cannot control device")

	// ErrCannotRestartDevice is returned when the reboot endpoint rejects
	// a DevicesService.Restart call. Mirrors upstream CannotRestartDevice.
	ErrCannotRestartDevice = errors.New("alexactl: cannot restart device")

	// ErrControllerNotImplemented is returned by typed control accessors
	// whose wire payload shape has not yet been confirmed against real
	// hardware. The stub Device.Range / Device.Toggle
	// accessors return this sentinel — when callers see it, the
	// stub also emits a WARN log directing them to file an issue with a
	// HAR capture so we can wire the real path.
	//
	//	if err := dvc.Range("FanSpeed").Set(ctx, 5.0); errors.Is(err, ErrControllerNotImplemented) {
	//	    // expected — Range write surface is HAR-capture-gated
	//	}
	ErrControllerNotImplemented = errors.New("alexactl: typed controller not yet wired — HAR capture needed")

	// ErrListItemNotFound is returned by *List write methods (Complete,
	// Uncomplete, Delete, Rename) when the passed *ListItem is nil or
	// belongs to a different *List than the receiver. Distinct from
	// transport-level 4xx errors so callers can branch on it directly:
	//
	//	if errors.Is(err, ErrListItemNotFound) {
	//	    // we passed the wrong item to the wrong list; reload and retry
	//	}
	ErrListItemNotFound = errors.New("alexactl: list item not found")

	// ErrAlarmNotFound is returned by *AlarmsService write methods
	// (Update, Delete, Enable, Disable, Snooze) when the passed *Alarm
	// is nil or belongs to a different *AlarmsService than the receiver.
	// Distinct from transport-level 4xx errors so callers can branch
	// on it directly:
	//
	//	if errors.Is(err, ErrAlarmNotFound) {
	//	    // wrong item; reload and retry
	//	}
	ErrAlarmNotFound = errors.New("alexactl: alarm not found")

	// ErrReminderNotFound is the same sentinel as ErrAlarmNotFound but
	// for *RemindersService write methods.
	ErrReminderNotFound = errors.New("alexactl: reminder not found")

	// ErrTimerNotFound is the same sentinel as ErrAlarmNotFound but
	// for *TimersService write methods.
	ErrTimerNotFound = errors.New("alexactl: timer not found")
)

Sentinel errors. Use errors.Is to match a category.

View Source
var ErrInvalidDropInStatus = fmt.Errorf("not a valid DropInStatus, try [%s]", strings.Join(_DropInStatusNames, ", "))
View Source
var ErrInvalidKind = fmt.Errorf("not a valid Kind, try [%s]", strings.Join(_KindNames, ", "))
View Source
var ErrInvalidListItemStatus = fmt.Errorf("not a valid ListItemStatus, try [%s]", strings.Join(_ListItemStatusNames, ", "))
View Source
var ErrInvalidListType = fmt.Errorf("not a valid ListType, try [%s]", strings.Join(_ListTypeNames, ", "))
View Source
var ErrInvalidLockState = fmt.Errorf("not a valid LockState, try [%s]", strings.Join(_LockStateNames, ", "))
View Source
var ErrInvalidMediaCommand = fmt.Errorf("not a valid MediaCommand, try [%s]", strings.Join(_MediaCommandNames, ", "))
View Source
var ErrInvalidPushMessageType = fmt.Errorf("not a valid PushMessageType, try [%s]", strings.Join(_PushMessageTypeNames, ", "))
View Source
var ErrInvalidSequenceType = fmt.Errorf("not a valid SequenceType, try [%s]", strings.Join(_SequenceTypeNames, ", "))
View Source
var ErrInvalidTemperatureScale = fmt.Errorf("not a valid TemperatureScale, try [%s]", strings.Join(_TemperatureScaleNames, ", "))
View Source
var ErrInvalidThermostatMode = fmt.Errorf("not a valid ThermostatMode, try [%s]", strings.Join(_ThermostatModeNames, ", "))
View Source
var Version = "dev"

Version is the build version of this library. It defaults to "dev" for builds made outside CI; release builds override it at link time via

-ldflags "-X github.com/Fishwaldo/alexactl.Version=<version>"

set by the GitHub release workflow on tag push. Treat version.go as the single source of truth — read this var rather than hard-coding a version.

Functions

func AlarmServerShape

func AlarmServerShape(a *Alarm) map[string]any

AlarmServerShape returns a defensive copy of the raw server dict cached on the *Alarm. Exported for CLI debugging only — production callers should rely on the typed fields.

func DropInStatusNames

func DropInStatusNames() []string

DropInStatusNames returns a list of possible string values of DropInStatus.

func KindNames

func KindNames() []string

KindNames returns a list of possible string values of Kind.

func ListItemStatusNames

func ListItemStatusNames() []string

ListItemStatusNames returns a list of possible string values of ListItemStatus.

func ListTypeNames

func ListTypeNames() []string

ListTypeNames returns a list of possible string values of ListType.

func LockStateNames

func LockStateNames() []string

LockStateNames returns a list of possible string values of LockState.

func MediaCommandNames

func MediaCommandNames() []string

MediaCommandNames returns a list of possible string values of MediaCommand.

func PushMessageTypeNames

func PushMessageTypeNames() []string

PushMessageTypeNames returns a list of possible string values of PushMessageType.

func ReminderServerShape

func ReminderServerShape(r *Reminder) map[string]any

ReminderServerShape mirrors AlarmServerShape for *Reminder.

func SequenceTypeNames

func SequenceTypeNames() []string

SequenceTypeNames returns a list of possible string values of SequenceType.

func TemperatureScaleNames

func TemperatureScaleNames() []string

TemperatureScaleNames returns a list of possible string values of TemperatureScale.

func ThermostatModeNames

func ThermostatModeNames() []string

ThermostatModeNames returns a list of possible string values of ThermostatMode.

func TimerServerShape

func TimerServerShape(t *Timer) map[string]any

TimerServerShape mirrors AlarmServerShape for *Timer.

Types

type APIError

type APIError struct {
	// Category is one of the sentinel errors above.
	Category error

	// Method is the HTTP method of the failed request (e.g. "GET", "POST").
	// Empty when the failure was not tied to a specific HTTP call.
	Method string

	// StatusCode is the HTTP status returned, or 0 if the failure was
	// pre-response (e.g., network error).
	StatusCode int

	// URL is the absolute URL of the failed request.
	URL string
}

APIError carries HTTP-level detail about a failed request. Its Unwrap returns one of the sentinel category errors above so callers can errors.Is against a category, and errors.As to extract details.

APIError intentionally does NOT include the response body — callers may log errors through non-scrubbing loggers, and response bodies can echo back credential material (tokens, cookies, OTPs). Use logs at the HTTP layer for body diagnostics.

func (*APIError) Error

func (e *APIError) Error() string

Error implements error.

Format depends on which fields are populated:

  • Method != "" or StatusCode != 0: "<category>: <method> <status> <url>"
  • URL != "": "<category>: <url>"
  • otherwise: "<category>"

This avoids the misleading "<category>: 0 " rendering when the failure was not tied to a specific HTTP call (e.g., pre-request validation).

func (*APIError) Unwrap

func (e *APIError) Unwrap() error

Unwrap returns the Category sentinel so errors.Is matches.

type Alarm

type Alarm struct {
	ID                 string
	DeviceSerialNumber string
	DeviceType         string
	FireAt             time.Time
	Label              string
	Sound              string
	Recurrence         *Recurrence
	Status             string // "ON" | "OFF" | "PAUSED"
	Version            int
	CreatedAt          time.Time
	UpdatedAt          time.Time
	// contains filtered or unexported fields
}

Alarm is a clock-time wake event tied to a specific device.

type AlarmsService

type AlarmsService struct {
	// contains filtered or unexported fields
}

AlarmsService manages clock-time alarms on Echo devices.

Wire endpoints (cookie + CSRF auth on alexa.amazon.<tld>):

GET    /api/notifications                       — shared read (filtered to Alarm + MusicAlarm)
PUT    /api/notifications/createAlarm           — Create
PUT    /api/notifications/<id>                  — Update / Enable / Disable / Snooze
DELETE /api/notifications/<id>                  — Delete

MusicAlarm wire entries are normalised to typed *Alarm at parse time (same shape, different label). The label-field fallback is musicAlarmLabel when alarmLabel is empty.

Safe for concurrent use.

func (*AlarmsService) Create

func (s *AlarmsService) Create(ctx context.Context, a *Alarm) (*Alarm, error)

Create posts a new alarm. The Alarm must have DeviceSerialNumber and FireAt set; DeviceType is auto-populated from the Devices cache. Returns *Alarm with server-assigned ID + Version + serverShape. On success the alarm is appended to the matching cached *Device.Alarms slice (if the device is in cache).

Returns ErrDeviceNotFound (without hitting the network) when the serial isn't in the cache.

func (*AlarmsService) Delete

func (s *AlarmsService) Delete(ctx context.Context, a *Alarm) error

Delete removes the alarm both server-side and from the matching cached *Device.Alarms slice. Returns ErrAlarmNotFound for nil or wrong-parent items.

func (*AlarmsService) Disable

func (s *AlarmsService) Disable(ctx context.Context, a *Alarm) error

Disable flips status to OFF. No-op + nil if already OFF.

func (*AlarmsService) Enable

func (s *AlarmsService) Enable(ctx context.Context, a *Alarm) error

Enable flips status to ON. No-op + nil if already ON.

func (*AlarmsService) Get

func (s *AlarmsService) Get(ctx context.Context) ([]*Alarm, error)

Get fetches every active alarm on the account, sorted by FireAt ascending. Entries with status != "ON" are dropped.

func (*AlarmsService) Snooze

func (s *AlarmsService) Snooze(ctx context.Context, a *Alarm, dur time.Duration) error

Snooze pushes the next fire by dur. Maps to the snoozedToTime field.

func (*AlarmsService) Update

func (s *AlarmsService) Update(ctx context.Context, a *Alarm) error

Update sends the cached serverShape echo with mutated user-set fields. On success the *Alarm is rewritten in place; on error, untouched.

type AudioPlayerStateEvent

type AudioPlayerStateEvent struct {
	// contains filtered or unexported fields
}

AudioPlayerStateEvent reports a device's audio-player state transition.

func NewAudioPlayerStateEvent

func NewAudioPlayerStateEvent(b PushEventBase) *AudioPlayerStateEvent

NewAudioPlayerStateEvent — decoder constructor.

func (*AudioPlayerStateEvent) RawPayload

func (b *AudioPlayerStateEvent) RawPayload() map[string]any

func (*AudioPlayerStateEvent) SerialNumber

func (b *AudioPlayerStateEvent) SerialNumber() string

func (*AudioPlayerStateEvent) Type

func (b *AudioPlayerStateEvent) Type() PushMessageType

type AuthService

type AuthService struct {
	// contains filtered or unexported fields
}

AuthService implements the Amazon Alexa OAuth + MFA login flow.

func (*AuthService) Login

func (s *AuthService) Login(ctx context.Context, email, password string, otp OTPProvider) (*Session, error)

Login performs the full interactive OAuth+PKCE+MFA flow. The OTPProvider is invoked only after Amazon serves the MFA form.

On success, the returned Session is also stored in s for subsequent service calls. Callers should persist it to disk (mode 0600).

func (*AuthService) Restore

func (s *AuthService) Restore(ctx context.Context) (*Session, error)

Restore re-validates a Session previously passed via WithSession. It refreshes the access token and re-fetches the customer ID if missing.

func (*AuthService) Session

func (s *AuthService) Session() *Session

Session returns the current session, or nil if no login/restore has completed. Returned pointer is immutable; AuthService swaps in a new pointer on refresh rather than mutating in place.

type BluetoothStatusEvent

type BluetoothStatusEvent struct {
	// contains filtered or unexported fields
}

BluetoothStatusEvent reports a device's Bluetooth state change.

func NewBluetoothStatusEvent

func NewBluetoothStatusEvent(b PushEventBase) *BluetoothStatusEvent

NewBluetoothStatusEvent — decoder constructor.

func (*BluetoothStatusEvent) RawPayload

func (b *BluetoothStatusEvent) RawPayload() map[string]any

func (*BluetoothStatusEvent) SerialNumber

func (b *BluetoothStatusEvent) SerialNumber() string

func (*BluetoothStatusEvent) Type

func (b *BluetoothStatusEvent) Type() PushMessageType

type BrightnessControl

type BrightnessControl struct {
	// contains filtered or unexported fields
}

BrightnessControl is the typed accessor returned by Device.Brightness() for devices that expose Alexa.BrightnessController. Set takes an absolute percentage [0..100]; Adjust takes a signed delta in the same units. Both clamp the local optimistic update to the valid range; out-of-range inputs to Set are clamped before sending, matching upstream's tolerance for out-of-range inputs.

func (*BrightnessControl) Adjust

func (c *BrightnessControl) Adjust(ctx context.Context, delta int) error

Adjust issues an adjustBrightness directive with the given signed delta. The local optimistic update clamps the resulting value to [0,100]. If the device reports no current Sensors["brightness"] value, Adjust still sends — Amazon resolves the absolute target using the device's actual current value — but skips the optimistic update.

func (*BrightnessControl) Set

func (c *BrightnessControl) Set(ctx context.Context, percent int) error

Set issues a setBrightness directive at the given absolute percentage. Inputs are clamped to [0,100] before sending — Amazon rejects out-of-range values with INVALID_VALUE, so clamping preserves the caller's intent without a round-trip failure.

type CacheClass

type CacheClass = cache.CacheClass

CacheClass re-exports cache.CacheClass so callers don't import the internal package directly.

type Client

type Client struct {
	Auth           *AuthService
	Devices        *DevicesService
	Media          *MediaService
	Sequence       *SequenceService
	DnD            *DnDService
	Sensors        *SensorsService
	History        *HistoryService
	Push           *PushService
	Lists          *ListsService
	Alarms         *AlarmsService
	Reminders      *RemindersService
	Timers         *TimersService
	Communications *CommunicationsService
	// contains filtered or unexported fields
}

Client is the entry point for the alexactl library. Construct with NewClient; safe for concurrent use.

func NewClient

func NewClient(opts ...Option) (*Client, error)

NewClient constructs a Client. It performs no I/O.

The first network call happens when the caller invokes Auth.Login, Auth.Restore, or any service method.

func (*Client) SnapshotCaches

func (c *Client) SnapshotCaches(ctx context.Context) error

SnapshotCaches persists every registered cache via the configured Persistence adapter. Returns nil when no adapter is configured. Callers typically invoke this on shutdown or from a periodic ticker.

type Color

type Color struct {
	Hue        float64
	Saturation float64
	Brightness float64
}

Color is the HSV-encoded color value Amazon's Alexa.ColorController speaks natively. Hue is in degrees [0, 360); Saturation and Brightness are unit floats [0, 1]. Use ColorFromRGB to construct from an 8-bit RGB triple, ToRGB to convert back.

This is the wire shape — Amazon's setColor mutation accepts payload {"color": {"hue": <h>, "saturation": <s>, "brightness": <b>}} with these exact field names and ranges.

func ColorFromRGB

func ColorFromRGB(r, g, b uint8) Color

ColorFromRGB converts an 8-bit-per-channel RGB triple to HSV. Standard HSV formula — see e.g. https://en.wikipedia.org/wiki/HSL_and_HSV. Pure red gives Hue=0 (not 360); pure gray gives Hue=0 and Saturation=0; pure black gives Brightness=0.

func (Color) ToRGB

func (c Color) ToRGB() (uint8, uint8, uint8)

ToRGB converts HSV back to an 8-bit-per-channel RGB triple. Inverse of ColorFromRGB modulo ±1-per-channel rounding error (HSV→RGB is not exactly invertible on the 8-bit integer grid).

type ColorControl

type ColorControl struct {
	// contains filtered or unexported fields
}

ColorControl is the typed accessor returned by Device.Color() for devices that expose Alexa.ColorController. Currently exposes only Set; Adjust/Increase/Decrease are not part of Amazon's ColorController schema.

func (*ColorControl) Set

func (c *ColorControl) Set(ctx context.Context, color Color) error

Set issues a setColor directive with the given HSV color. On HTTP success and no structured error, Device.Sensors["color"].Value is set to a map[string]any with {"hue", "saturation", "brightness"} matching the read-path shape from sensors.go.

type ColorTempControl

type ColorTempControl struct {
	// contains filtered or unexported fields
}

ColorTempControl is the typed accessor returned by Device.ColorTemperature() for devices that expose Alexa.ColorTemperatureController. Set takes an absolute kelvin value; Increase/Decrease step in device-defined increments (no payload — the device decides the step size).

func (*ColorTempControl) Decrease

func (c *ColorTempControl) Decrease(ctx context.Context) error

Decrease issues a decreaseColorTemperature directive. Same caveats as Increase — no optimistic update.

func (*ColorTempControl) Increase

func (c *ColorTempControl) Increase(ctx context.Context) error

Increase issues an increaseColorTemperature directive. The device chooses the step size; we don't get the new value back synchronously, so no optimistic update is applied. The next sensor refresh reflects the new value.

func (*ColorTempControl) Set

func (c *ColorTempControl) Set(ctx context.Context, kelvin int) error

Set issues a setColorTemperature directive at the given absolute kelvin value. On success, Sensors["colorTemperature"].Value is set to kelvin.

Inputs are NOT clamped — Amazon's per-device supported range varies (typical incandescent: ~2700K; daylight: ~6500K) and the device will respond with INVALID_VALUE if asked for an unreachable temperature, which surfaces as ErrCannotControlDevice.

type CommunicationsService

type CommunicationsService struct {
	// contains filtered or unexported fields
}

CommunicationsService toggles per-device communications, announcement, and drop-in preferences via Amazon's global comms host. Bearer-authed.

Safe for concurrent use.

func (*CommunicationsService) GetPreferences

func (s *CommunicationsService) GetPreferences(ctx context.Context, devices []*Device) (map[string]map[string]string, error)

GetPreferences fetches allowed comms preferences per device serial. Devices in a speaker group (WHA) or AQMs are skipped. Per-device fetch failures are logged and skipped, not fatal.

func (*CommunicationsService) SetAnnouncementStatus

func (s *CommunicationsService) SetAnnouncementStatus(ctx context.Context, d *Device, on bool) error

SetAnnouncementStatus enables/disables announcements for the device.

func (*CommunicationsService) SetCommunicationStatus

func (s *CommunicationsService) SetCommunicationStatus(ctx context.Context, d *Device, on bool) error

SetCommunicationStatus enables/disables calling+messaging for the device.

func (*CommunicationsService) SetDropInStatus

func (s *CommunicationsService) SetDropInStatus(ctx context.Context, d *Device, status DropInStatus) error

SetDropInStatus sets the drop-in permission (All / Home / Off).

type ConnectionStatusEvent

type ConnectionStatusEvent struct {
	// contains filtered or unexported fields
}

ConnectionStatusEvent reports a device's cloud connection state change.

func NewConnectionStatusEvent

func NewConnectionStatusEvent(b PushEventBase) *ConnectionStatusEvent

NewConnectionStatusEvent — decoder constructor.

func (*ConnectionStatusEvent) RawPayload

func (b *ConnectionStatusEvent) RawPayload() map[string]any

func (*ConnectionStatusEvent) SerialNumber

func (b *ConnectionStatusEvent) SerialNumber() string

func (*ConnectionStatusEvent) Type

func (b *ConnectionStatusEvent) Type() PushMessageType

type CustomerInfo

type CustomerInfo struct {
	HomeRegion string `json:"home_region"` // "NA" | "EU" | "FE" | ...
	AccountID  string `json:"account_id"`
	Name       string `json:"name"`
	GivenName  string `json:"given_name"`
}

CustomerInfo carries the Amazon account customer metadata returned at registration time.

type Device

type Device struct {
	AccountName           string
	SerialNumber          string
	DeviceType            string
	DeviceFamily          string
	DeviceOwnerCustomerID string
	HouseholdDevice       bool
	Online                bool
	Capabilities          []string          // raw Amazon capability strings
	ClusterMembers        map[string]string // serial -> device type ("" if unknown)
	Manufacturer          string
	Model                 string
	SoftwareVersion       string
	HardwareVersion       string
	EntityID              string
	EndpointID            string
	Sensors               map[string]*DeviceSensor // populated by SensorsService during Refresh
	SchedulesSupported    bool
	MediaPlayerSupported  bool

	// CommunicationSettings is reserved for future enrichment that would
	// attach the allowed comms preferences (keys: "communications",
	// "dropin", "announcements"; values are the per-pref state) to each
	// device. It is NOT currently populated:
	// Client.Communications.GetPreferences returns the preference data
	// directly as a standalone map keyed by serial and never writes back
	// to *Device. This field is always nil today.
	CommunicationSettings map[string]string

	// Typed schedule slices populated by DevicesService.Refresh's
	// sensors-enrichment hook (one shared /api/notifications fetch routed
	// across all devices). Slice is nil for devices that don't support
	// schedules (SchedulesSupported == false).
	Alarms    []*Alarm
	Reminders []*Reminder
	Timers    []*Timer

	// Smart-home endpoint classification and description fields.
	//
	// Kind is the canonical device-class (KindLight, KindThermostat, …).
	// Derived from DisplayCategories.primary via amzconst.DisplayCategoryToKind
	// for non-Echo endpoints; Echos are tagged KindEcho regardless of the
	// GraphQL-reported DisplayCategory.
	Kind Kind

	// DisplayCategories carries every Alexa DisplayCategory reported for
	// this endpoint (e.g. ["THERMOSTAT", "AIR_CONDITIONER",
	// "TEMPERATURE_SENSOR"] for an AC unit). Useful for UI consumers that
	// want to render composite-device hints. Empty for Echos that aren't
	// surfaced via the GraphQL endpoint graph.
	DisplayCategories []string

	// AlexaInterfaces lists the Alexa capability interfaces Amazon
	// advertises for this endpoint (e.g. "Alexa.PowerController",
	// "Alexa.BrightnessController"). Sourced from
	// AlexaEnabledMetadata.capabilities; empty when the endpoint isn't
	// ALEXA_VOICE_ENABLED.
	AlexaInterfaces []string

	// Operations lists the operation names Amazon's directive system
	// accepts for this endpoint (e.g. ["turnOn", "turnOff",
	// "setBrightness"]). The schema-level manifest of what the
	// setEndpointFeatures mutation would accept. The discovery query
	// populates this from Endpoint.operations; it drives typed control
	// surfaces.
	Operations []string
	// contains filtered or unexported fields
}

Device describes one Amazon Echo (or Alexa-enabled) device. Returned by DevicesService.List as a read-only snapshot — mutations on a *Device do NOT update the client's internal cache. Call DevicesService.Refresh to re-fetch.

func (*Device) Brightness

func (d *Device) Brightness() *BrightnessControl

Brightness returns a typed brightness-controller accessor, or nil when the device does not advertise Alexa.BrightnessController, has no EndpointID, or has no smartHomeClient back-reference.

func (*Device) Color

func (d *Device) Color() *ColorControl

Color returns a typed color-controller accessor, or nil when the device does not advertise Alexa.ColorController, has no EndpointID, or has no smartHomeClient back-reference. Same nil-on-no-capability semantics as Power() / Brightness().

func (*Device) ColorTemperature

func (d *Device) ColorTemperature() *ColorTempControl

ColorTemperature returns a typed color-temperature accessor, or nil when the device does not advertise Alexa.ColorTemperatureController, has no EndpointID, or has no smartHomeClient back-reference.

func (*Device) HasCapability

func (d *Device) HasCapability(c string) bool

HasCapability reports whether the device advertises the given capability.

func (*Device) IsCluster

func (d *Device) IsCluster() bool

IsCluster reports whether the device is grouped with other devices (e.g., a stereo pair or Echo group).

func (*Device) Lock

func (d *Device) Lock() *LockControl

Lock returns a typed lock-controller accessor, or nil when the device does not advertise Alexa.LockController in AlexaInterfaces, has no EndpointID, or has no back-reference to a smartHomeClient (e.g. a *Device built by hand outside NewClient).

Callers MUST nil-check: dvc.Lock().Lock(ctx) panics if Lock() returned nil. This is intentional — a silent no-op on non-controllable devices would mask programmer error.

func (*Device) Mode

func (d *Device) Mode(instance string) *ModeControl

Mode returns a typed mode-controller accessor, or nil when the device does not advertise Alexa.ModeController, has no EndpointID, or has no smartHomeClient back-reference. Callers MUST nil-check.

instance is the feature instance identifier (e.g. "Pure.FanSpeed", "Apparatus.FanDirection", "Genesis.ColorPalette"). It's required — ModeController is always instance-scoped on the wire.

func (*Device) Power

func (d *Device) Power() *PowerControl

Power returns a typed power-controller accessor, or nil when the device does not advertise Alexa.PowerController in AlexaInterfaces, has no EndpointID, or has no back-reference to a smartHomeClient (e.g. a *Device built by hand outside NewClient).

Callers MUST nil-check: dvc.Power().On(ctx) panics if Power() returned nil. This is intentional — a silent no-op on non-controllable devices would mask programmer error.

func (*Device) Range

func (d *Device) Range(instance string) *RangeControl

Range returns a typed range-controller accessor, or nil when the device does not advertise Alexa.RangeController, has no EndpointID, or has no smartHomeClient back-reference.

instance is the feature instance identifier (e.g. "Apparatus. Humidity", "Skill.FanSpeed"). Required.

WRITE PATH IS STUBBED — see ErrControllerNotImplemented and the WARN log emitted by Set / Adjust.

func (*Device) SendDirective

func (d *Device) SendDirective(ctx context.Context, featureName, instance, operationName string, payload map[string]any) error

SendDirective issues an arbitrary feature-control directive via the same setEndpointFeatures mutation the typed accessors use. Useful for Alexa interfaces we haven't shipped a typed accessor for and for exploring unverified wire shapes (Range/Mode/Toggle payloads pre-typed-accessor).

instance is the feature's instance identifier when the feature supports multiple instances per device (Mode, Range, Toggle); pass "" when the feature is singleton (Power, Brightness, etc.).

dvc.SendDirective(ctx, "power", "", "turnOn", nil)
dvc.SendDirective(ctx, "brightness", "", "setBrightness", map[string]any{"brightness": 60})
dvc.SendDirective(ctx, "mode", "Pure.FanSpeed", "setMode", map[string]any{"mode": "FanSpeed.High"})

HISTORICAL NOTE: previously routed through the experimental setEndpointFeaturesV2 mutation, which Amazon gates per-customer ("setEndpointFeaturesV2 is not enabled for customerId=..."). The V1 mutation already accepts arbitrary string featureName / operationName values (the schema enums are validated server-side at the call site, not by the binding), so V1 is strictly more available and equivalent in capability.

On structured error, returns ErrCannotControlDevice with the upstream code + message in the formatted error string. On transport failure (network, 5xx, malformed JSON), returns ErrCannotConnect. No optimistic local Sensors update — the directive shape isn't known statically.

Returns ErrDeviceNotFound if the device has no EndpointID or no smartHomeClient back-reference (e.g. a *Device built outside the Client lifecycle).

func (*Device) Thermostat

func (d *Device) Thermostat() *ThermostatControl

Thermostat returns a typed thermostat-controller accessor, or nil when the device does not advertise Alexa.ThermostatController, has no EndpointID, or has no smartHomeClient back-reference.

func (*Device) Toggle

func (d *Device) Toggle(instance string) *ToggleControl

Toggle returns a typed toggle-controller accessor, or nil when the device does not advertise Alexa.ToggleController, has no EndpointID, or has no smartHomeClient back-reference.

instance is the toggle's instance identifier (e.g. "Skill.Ionizer", "Skill.ChildLock", "Skill.Swing"). Required.

WRITE PATH IS STUBBED — see ErrControllerNotImplemented and the WARN log emitted by On / Off.

type DeviceInfo

type DeviceInfo struct {
	DeviceSerialNumber string `json:"device_serial_number"`
	DeviceType         string `json:"device_type"`
}

DeviceInfo identifies the virtual Alexa client device that this Session is registered as.

type DeviceSensor

type DeviceSensor struct {
	Name      string
	Value     any // string | int | float64
	Error     bool
	ErrorType string
	ErrorMsg  string
	Scale     string

	// Fields that surface the feature's action space.
	//
	// Configuration carries the typed Feature.configuration values
	// (e.g. ThermostatConfiguration.supportedModes). Map keys are
	// configuration-variant-specific; common keys are documented per
	// feature. Empty when the feature has no Configuration or we don't
	// extract it.
	Configuration map[string]any

	// Operations lists the feature-level operation names the directive
	// system accepts for this sensor's feature (e.g. ["setBrightness",
	// "adjustBrightness"] for a brightness sensor). Empty when the
	// feature exposes no operations.
	Operations []string
}

DeviceSensor is a single sensor reading. Populated by SensorsService during Refresh.

type DevicesService

type DevicesService struct {
	// contains filtered or unexported fields
}

DevicesService discovers Amazon devices associated with the account and enriches them with GraphQL endpoint metadata.

func (*DevicesService) Get

func (s *DevicesService) Get(ctx context.Context, serial string) (*Device, error)

Get returns the device with the given serial. Refreshes the cache if stale. Returns nil and an error wrapping ErrCannotRetrieveData if not found after a refresh.

func (*DevicesService) Inspect

func (s *DevicesService) Inspect(ctx context.Context, serial string) (*Device, error)

Inspect issues a per-endpoint deep query (endpointAllFeatures) for the given serial and updates the cached *Device in place with fresh feature + property + operation + configuration data. Returns the updated device. Use this when a caller wants the full state for one device without paying for a list-wide Refresh.

If serial is not in the cache, Inspect returns an error wrapping ErrDeviceNotFound; the caller should call Refresh first.

func (*DevicesService) List

func (s *DevicesService) List(ctx context.Context) ([]*Device, error)

List returns all enrichable Amazon devices for the account, including Air Quality Monitors. The result is sorted by serial number and is a fresh slice; mutations don't affect the cache.

Cached for the Long-class TTL; call Refresh to force a re-fetch.

func (*DevicesService) Refresh

func (s *DevicesService) Refresh(ctx context.Context, opts ...RefreshOption) error

Refresh forces a re-fetch of the device list, including the GraphQL endpoint enrichment. WithoutSensors bypasses the cache loader (which always runs sensors) and writes the no-sensors result straight into the cache.

func (*DevicesService) Restart

func (s *DevicesService) Restart(ctx context.Context, d *Device) error

Restart reboots the given device via Amazon's reboot endpoint. The device drops offline for ~30s and reconnects. Requires the account's OAuth access token (bearer-authed, not cookie-authed).

Returns an error wrapping ErrCannotRestartDevice on a non-2xx response, ErrCannotAuthenticate if no access token is available, or ErrCannotConnect on transport failure.

type DnDService

type DnDService struct {
	// contains filtered or unexported fields
}

DnDService gets and sets the per-device Do Not Disturb flag.

Backed by two endpoints on alexa.amazon.<domain>:

  • GET /api/dnd/device-status-list — read all devices' DnD state
  • PUT /api/dnd/status — toggle DnD on one device

Safe for concurrent use.

func (*DnDService) Set

func (s *DnDService) Set(ctx context.Context, d *Device, enabled bool) error

Set toggles the Do Not Disturb flag for one device. The change applies only to the supplied device's specific (serial, deviceType) pair — DnD is not a cluster-fanout operation in Amazon's API.

func (*DnDService) Status

func (s *DnDService) Status(ctx context.Context) (map[string]*DeviceSensor, error)

Status returns the Do Not Disturb state for every device on the account, keyed by device serial number. Cached for the Short-class TTL. Returned map is a defensive copy.

type DropInStatus

type DropInStatus string

DropInStatus is the drop-in permission level reported/set for a device.

ENUM(

DropInStatusAll="All",
DropInStatusHome="Home",
DropInStatusOff="Off"

)

const (
	// DropInStatusAll is a DropInStatus of type DropInStatusAll.
	DropInStatusAll DropInStatus = "All"
	// DropInStatusHome is a DropInStatus of type DropInStatusHome.
	DropInStatusHome DropInStatus = "Home"
	// DropInStatusOff is a DropInStatus of type DropInStatusOff.
	DropInStatusOff DropInStatus = "Off"
)

func DropInStatusValues

func DropInStatusValues() []DropInStatus

DropInStatusValues returns a list of the values for DropInStatus

func ParseDropInStatus

func ParseDropInStatus(name string) (DropInStatus, error)

ParseDropInStatus attempts to convert a string to a DropInStatus.

func (*DropInStatus) AppendText

func (x *DropInStatus) AppendText(b []byte) ([]byte, error)

AppendText appends the textual representation of itself to the end of b (allocating a larger slice if necessary) and returns the updated slice.

Implementations must not retain b, nor mutate any bytes within b[:len(b)].

func (DropInStatus) IsValid

func (x DropInStatus) IsValid() bool

IsValid provides a quick way to determine if the typed value is part of the allowed enumerated values

func (DropInStatus) MarshalText

func (x DropInStatus) MarshalText() ([]byte, error)

MarshalText implements the text marshaller method.

func (DropInStatus) String

func (x DropInStatus) String() string

String implements the Stringer interface.

func (*DropInStatus) UnmarshalText

func (x *DropInStatus) UnmarshalText(text []byte) error

UnmarshalText implements the text unmarshaller method.

type EqualizerStateChangeEvent

type EqualizerStateChangeEvent struct {
	// contains filtered or unexported fields
}

EqualizerStateChangeEvent reports a device's equalizer setting change.

func NewEqualizerStateChangeEvent

func NewEqualizerStateChangeEvent(b PushEventBase) *EqualizerStateChangeEvent

NewEqualizerStateChangeEvent — decoder constructor.

func (*EqualizerStateChangeEvent) RawPayload

func (b *EqualizerStateChangeEvent) RawPayload() map[string]any

func (*EqualizerStateChangeEvent) SerialNumber

func (b *EqualizerStateChangeEvent) SerialNumber() string

func (*EqualizerStateChangeEvent) Type

func (b *EqualizerStateChangeEvent) Type() PushMessageType

type FeatureControl

type FeatureControl struct {
	EndpointID           string
	FeatureName          string
	FeatureOperationName string
	Instance             string
	Payload              map[string]any
}

FeatureControl is one entry in a setEndpointFeatures mutation. Payload is nil for no-payload operations (turnOn / turnOff); for operations that take a payload, the shape mirrors what the captured web-UI mutations send (e.g. {"brightness": 45} for setBrightness, {"color": {"hue": 348, "saturation": 0.91, "brightness": 1}} for setColor).

Instance is the optional feature instance discriminator (e.g. "Apparatus.FanSpeed" for a fan-speed mode). Left empty for Power and Brightness; may be populated for Range/Mode generic controllers.

type FeatureControlErrorResponse

type FeatureControlErrorResponse = alexagraphql.FeatureControlError

FeatureControlErrorResponse is the public alias for one error entry in the setEndpointFeatures response. Code is the upstream symbolic status (e.g. "INVALID_VALUE", "ENDPOINT_UNREACHABLE"); Message is the upstream human-readable string.

type FeatureControlResponse

type FeatureControlResponse = alexagraphql.FeatureControlSuccess

FeatureControlResponse is the public alias for one success entry in the setEndpointFeatures response. Callers inspect Code to confirm the directive landed (typically "SUCCESS").

type GenericActivityEvent

type GenericActivityEvent struct {
	// contains filtered or unexported fields
}

GenericActivityEvent reports a generic device activity (PUSH_ACTIVITY).

func NewGenericActivityEvent

func NewGenericActivityEvent(b PushEventBase) *GenericActivityEvent

NewGenericActivityEvent — decoder constructor.

func (*GenericActivityEvent) RawPayload

func (b *GenericActivityEvent) RawPayload() map[string]any

func (*GenericActivityEvent) SerialNumber

func (b *GenericActivityEvent) SerialNumber() string

func (*GenericActivityEvent) Type

func (b *GenericActivityEvent) Type() PushMessageType

type HistoryService

type HistoryService struct {
	// contains filtered or unexported fields
}

HistoryService fetches the user's vocal history (the last 7 days of utterances) per device. Backed by /alexa-privacy/apd/rah (POST, bearer-authed) with a CSRF token scraped from /alexa-privacy/apd/rvh.

Safe for concurrent use.

func (*HistoryService) Vocal

func (s *HistoryService) Vocal(ctx context.Context) (map[string]*VocalRecord, error)

Vocal returns the latest captured utterance per device serial, covering the last 7 days. Utterance types ASR_TIMEOUT, DEVICE_ARBITRATION, NO_EXPRESSED_INTENT, and WAKE_WORD_ONLY are filtered out before construction.

type ItemChangeEvent

type ItemChangeEvent struct {
	// contains filtered or unexported fields
}

ItemChangeEvent reports a change to an Alexa list item (shopping list, to-do, etc.).

func NewItemChangeEvent

func NewItemChangeEvent(b PushEventBase) *ItemChangeEvent

NewItemChangeEvent — decoder constructor.

func (*ItemChangeEvent) RawPayload

func (b *ItemChangeEvent) RawPayload() map[string]any

func (*ItemChangeEvent) SerialNumber

func (b *ItemChangeEvent) SerialNumber() string

func (*ItemChangeEvent) Type

func (b *ItemChangeEvent) Type() PushMessageType

type Kind

type Kind string

Kind is the device classification derived from its capabilities.

ENUM(

KindEcho="echo",
KindLight="light",
KindSwitch="switch",
KindDimmer="dimmer",
KindThermostat="thermostat",
KindLock="lock",
KindCamera="camera",
KindContact="contact_sensor",
KindMotion="motion_sensor",
KindAQM="air_quality_monitor",
KindSensor="sensor",
KindAirPurifier="air_purifier",
KindSecurityPanel="security_panel",
KindScene="scene",
KindOther="other"

)

const (
	// KindEcho is a Kind of type KindEcho.
	KindEcho Kind = "echo"
	// KindLight is a Kind of type KindLight.
	KindLight Kind = "light"
	// KindSwitch is a Kind of type KindSwitch.
	KindSwitch Kind = "switch"
	// KindDimmer is a Kind of type KindDimmer.
	KindDimmer Kind = "dimmer"
	// KindThermostat is a Kind of type KindThermostat.
	KindThermostat Kind = "thermostat"
	// KindLock is a Kind of type KindLock.
	KindLock Kind = "lock"
	// KindCamera is a Kind of type KindCamera.
	KindCamera Kind = "camera"
	// KindContact is a Kind of type KindContact.
	KindContact Kind = "contact_sensor"
	// KindMotion is a Kind of type KindMotion.
	KindMotion Kind = "motion_sensor"
	// KindAQM is a Kind of type KindAQM.
	KindAQM Kind = "air_quality_monitor"
	// KindSensor is a Kind of type KindSensor.
	KindSensor Kind = "sensor"
	// KindAirPurifier is a Kind of type KindAirPurifier.
	KindAirPurifier Kind = "air_purifier"
	// KindSecurityPanel is a Kind of type KindSecurityPanel.
	KindSecurityPanel Kind = "security_panel"
	// KindScene is a Kind of type KindScene.
	KindScene Kind = "scene"
	// KindOther is a Kind of type KindOther.
	KindOther Kind = "other"
)

func KindValues

func KindValues() []Kind

KindValues returns a list of the values for Kind

func ParseKind

func ParseKind(name string) (Kind, error)

ParseKind attempts to convert a string to a Kind.

func (*Kind) AppendText

func (x *Kind) AppendText(b []byte) ([]byte, error)

AppendText appends the textual representation of itself to the end of b (allocating a larger slice if necessary) and returns the updated slice.

Implementations must not retain b, nor mutate any bytes within b[:len(b)].

func (Kind) IsValid

func (x Kind) IsValid() bool

IsValid provides a quick way to determine if the typed value is part of the allowed enumerated values

func (Kind) MarshalText

func (x Kind) MarshalText() ([]byte, error)

MarshalText implements the text marshaller method.

func (Kind) String

func (x Kind) String() string

String implements the Stringer interface.

func (*Kind) UnmarshalText

func (x *Kind) UnmarshalText(text []byte) error

UnmarshalText implements the text unmarshaller method.

type List

type List struct {
	ID    string
	Name  string // empty for the default shopping list
	Type  ListType
	Items []*ListItem
	// contains filtered or unexported fields
}

List is one logical list on the v2 ToDo API. Items are loaded with the parent on Get; the slice is sorted active-first, then by Value.

func (*List) AddItem

func (l *List) AddItem(ctx context.Context, value string) (*ListItem, error)

AddItem POSTs a new item to this list as a KEYWORD item. On success the v2 API echoes the newly-created item nested under itemInfoList; the returned *ListItem is built from itemInfoList[0] so it carries the server-assigned itemId, version, and status. The cache is invalidated so the next Get(ctx) reconciles with the server's canonical state.

If the add succeeds (2xx) but the response omits itemInfoList, AddItem returns ErrCannotRetrieveData rather than a zero-ID item (which write methods could misuse); the item was created server-side and a fresh Get(ctx) will surface it.

On success the new *ListItem is appended to list.Items in place.

func (*List) Complete

func (l *List) Complete(ctx context.Context, item *ListItem) error

Complete marks the item completed. No-op + nil error if already completed. On success: item.Completed=true, item.Version bumped to the server's value from the itemInfo response.

func (*List) Delete

func (l *List) Delete(ctx context.Context, item *ListItem) error

Delete removes the item from the list both server-side and from list.Items locally on success. Returns ErrListItemNotFound if the item is nil or belongs to a different list.

func (*List) Rename

func (l *List) Rename(ctx context.Context, item *ListItem, newValue string) error

Rename rewrites the item's Value to newValue via an itemName attribute update. On success: item.Value rewritten, item.Version bumped from the itemInfo response.

func (*List) Uncomplete

func (l *List) Uncomplete(ctx context.Context, item *ListItem) error

Uncomplete is the inverse of Complete.

type ListItem

type ListItem struct {
	ID        string
	Value     string
	Completed bool
	Version   int // optimistic-concurrency token, required by every write call
	// contains filtered or unexported fields
}

ListItem is the user-meaningful subset of the server's v2 item dict.

type ListItemStatus

type ListItemStatus string

ListItemStatus is the completion state of a v2 ToDo list item.

ENUM(

ListItemStatusActive="ACTIVE",
ListItemStatusComplete="COMPLETE"

)

const (
	// ListItemStatusActive is a ListItemStatus of type ListItemStatusActive.
	ListItemStatusActive ListItemStatus = "ACTIVE"
	// ListItemStatusComplete is a ListItemStatus of type ListItemStatusComplete.
	ListItemStatusComplete ListItemStatus = "COMPLETE"
)

func ListItemStatusValues

func ListItemStatusValues() []ListItemStatus

ListItemStatusValues returns a list of the values for ListItemStatus

func ParseListItemStatus

func ParseListItemStatus(name string) (ListItemStatus, error)

ParseListItemStatus attempts to convert a string to a ListItemStatus.

func (*ListItemStatus) AppendText

func (x *ListItemStatus) AppendText(b []byte) ([]byte, error)

AppendText appends the textual representation of itself to the end of b (allocating a larger slice if necessary) and returns the updated slice.

Implementations must not retain b, nor mutate any bytes within b[:len(b)].

func (ListItemStatus) IsValid

func (x ListItemStatus) IsValid() bool

IsValid provides a quick way to determine if the typed value is part of the allowed enumerated values

func (ListItemStatus) MarshalText

func (x ListItemStatus) MarshalText() ([]byte, error)

MarshalText implements the text marshaller method.

func (ListItemStatus) String

func (x ListItemStatus) String() string

String implements the Stringer interface.

func (*ListItemStatus) UnmarshalText

func (x *ListItemStatus) UnmarshalText(text []byte) error

UnmarshalText implements the text unmarshaller method.

type ListType

type ListType string

ListType is the kind of Alexa list on the v2 ToDo API: the default shopping list (SHOP), a to-do list (TODO), or a user-named custom list (CUSTOM).

ENUM(

ListTypeShop="SHOP",
ListTypeTodo="TODO",
ListTypeCustom="CUSTOM"

)

const (
	// ListTypeShop is a ListType of type ListTypeShop.
	ListTypeShop ListType = "SHOP"
	// ListTypeTodo is a ListType of type ListTypeTodo.
	ListTypeTodo ListType = "TODO"
	// ListTypeCustom is a ListType of type ListTypeCustom.
	ListTypeCustom ListType = "CUSTOM"
)

func ListTypeValues

func ListTypeValues() []ListType

ListTypeValues returns a list of the values for ListType

func ParseListType

func ParseListType(name string) (ListType, error)

ParseListType attempts to convert a string to a ListType.

func (*ListType) AppendText

func (x *ListType) AppendText(b []byte) ([]byte, error)

AppendText appends the textual representation of itself to the end of b (allocating a larger slice if necessary) and returns the updated slice.

Implementations must not retain b, nor mutate any bytes within b[:len(b)].

func (ListType) IsValid

func (x ListType) IsValid() bool

IsValid provides a quick way to determine if the typed value is part of the allowed enumerated values

func (ListType) MarshalText

func (x ListType) MarshalText() ([]byte, error)

MarshalText implements the text marshaller method.

func (ListType) String

func (x ListType) String() string

String implements the Stringer interface.

func (*ListType) UnmarshalText

func (x *ListType) UnmarshalText(text []byte) error

UnmarshalText implements the text unmarshaller method.

type ListsService

type ListsService struct {
	// contains filtered or unexported fields
}

ListsService exposes the v2 /alexashoppinglists/api/v2/lists ToDo API on www.amazon.<tld>. Surfaces both the default unnamed SHOP list and any user-named TODO/CUSTOM list entries with full item CRUD.

AUTH: cookie-based — the session restorer already populates the cookie jar with at-main / sess-at-main / session-id / ubid-main / x-main scoped to .amazon.<tld>, so requests to www.amazon.<tld> pick them up transparently.

CACHING: Get(ctx) is served from the Short-class cache; item-mutation methods on *List invalidate it so the next Get triggers a fresh fetch.

SCOPE: items added via the new Alexa+ web UI ("Metis") may not appear here — that UI uses a separate conversational data store. Items added by voice (Echo devices), the iOS Alexa app, or the legacy web UI WILL appear.

Safe for concurrent use.

func (*ListsService) Get

func (s *ListsService) Get(ctx context.Context) ([]*List, error)

Get fetches every list on the account (the default SHOP list and any named TODO/CUSTOM entries) along with their items. The default shopping list (Type == ListTypeShop) sorts first; remaining lists are sorted by (Type, Name). Items within each list are sorted active-first, then by Value.

Cached for the Short-class TTL. Callers needing strictly-fresh data either pass DisableCache(ClassShort) at construction or invoke Invalidate() before Get().

func (*ListsService) Invalidate

func (s *ListsService) Invalidate()

Invalidate drops the cached lists snapshot. The next Get triggers a fresh fetch.

type LockControl

type LockControl struct {
	// contains filtered or unexported fields
}

LockControl is the typed accessor returned by Device.Lock() for devices that expose Alexa.LockController. Two methods — Lock and Unlock — each issue one payload-less setEndpointFeatures mutation. On HTTP success the corresponding Device.Sensors["lockState"] entry is updated optimistically; the next getEndpointState refresh overwrites with the canonical value.

Unlock may be unsupported per-device — some smart locks disable remote unlock for safety (BHMA/Z-Wave "auto-relock only" modes, Yale's "remote unlock disabled" setting, August's "owner-only" policy). In that case Amazon returns a structured error in the directive response which surfaces as a wrapped ErrCannotControlDevice. Lock() should always work where the controller is exposed.

No Toggle: lock/unlock asymmetry isn't useful — "flip whatever the current state is" semantics on a physical lock is dangerous UX. Callers wanting that behavior compose it from Sensors["lockState"] themselves.

func (*LockControl) Lock

func (c *LockControl) Lock(ctx context.Context) error

Lock issues a lock directive. On HTTP 200 with no structured error, Device.Sensors["lockState"].Value is set to "LOCKED".

func (*LockControl) Unlock

func (c *LockControl) Unlock(ctx context.Context) error

Unlock issues an unlock directive. On success, Sensors["lockState"] is set to "UNLOCKED". Unlock is the operation most likely to fail with a structured error — many locks disable remote unlock by policy. The error wraps ErrCannotControlDevice so callers can distinguish a refusal from a transport failure.

type LockState

type LockState string

LockState is the reported state of a smart lock.

ENUM(

LockStateLocked="LOCKED",
LockStateUnlocked="UNLOCKED",
LockStateJammed="JAMMED"

)

const (
	// LockStateLocked is a LockState of type LockStateLocked.
	LockStateLocked LockState = "LOCKED"
	// LockStateUnlocked is a LockState of type LockStateUnlocked.
	LockStateUnlocked LockState = "UNLOCKED"
	// LockStateJammed is a LockState of type LockStateJammed.
	LockStateJammed LockState = "JAMMED"
)

func LockStateValues

func LockStateValues() []LockState

LockStateValues returns a list of the values for LockState

func ParseLockState

func ParseLockState(name string) (LockState, error)

ParseLockState attempts to convert a string to a LockState.

func (*LockState) AppendText

func (x *LockState) AppendText(b []byte) ([]byte, error)

AppendText appends the textual representation of itself to the end of b (allocating a larger slice if necessary) and returns the updated slice.

Implementations must not retain b, nor mutate any bytes within b[:len(b)].

func (LockState) IsValid

func (x LockState) IsValid() bool

IsValid provides a quick way to determine if the typed value is part of the allowed enumerated values

func (LockState) MarshalText

func (x LockState) MarshalText() ([]byte, error)

MarshalText implements the text marshaller method.

func (LockState) String

func (x LockState) String() string

String implements the Stringer interface.

func (*LockState) UnmarshalText

func (x *LockState) UnmarshalText(text []byte) error

UnmarshalText implements the text unmarshaller method.

type MatterDeviceFoundEvent

type MatterDeviceFoundEvent struct {
	// contains filtered or unexported fields
}

MatterDeviceFoundEvent reports a Matter device discovered for setup. Not device-scoped (SerialNumber() returns "").

func NewMatterDeviceFoundEvent

func NewMatterDeviceFoundEvent(b PushEventBase) *MatterDeviceFoundEvent

NewMatterDeviceFoundEvent — decoder constructor.

func (*MatterDeviceFoundEvent) RawPayload

func (b *MatterDeviceFoundEvent) RawPayload() map[string]any

func (*MatterDeviceFoundEvent) SerialNumber

func (b *MatterDeviceFoundEvent) SerialNumber() string

func (*MatterDeviceFoundEvent) Type

func (b *MatterDeviceFoundEvent) Type() PushMessageType

type MediaChangeEvent

type MediaChangeEvent struct {
	// contains filtered or unexported fields
}

MediaChangeEvent reports a change of currently playing media.

func NewMediaChangeEvent

func NewMediaChangeEvent(b PushEventBase) *MediaChangeEvent

NewMediaChangeEvent — decoder constructor.

func (*MediaChangeEvent) RawPayload

func (b *MediaChangeEvent) RawPayload() map[string]any

func (*MediaChangeEvent) SerialNumber

func (b *MediaChangeEvent) SerialNumber() string

func (*MediaChangeEvent) Type

func (b *MediaChangeEvent) Type() PushMessageType

type MediaCommand

type MediaCommand string

MediaCommand is a media transport command name as it appears on the wire.

ENUM(

CmdPlay="PlayCommand",
CmdStop="StopSequence",
CmdPause="PauseCommand",
CmdNext="NextCommand",
CmdPrev="PreviousCommand",
CmdRewind="RewindCommand",
CmdForward="ForwardCommand"

)

const (
	// CmdPlay is a MediaCommand of type CmdPlay.
	CmdPlay MediaCommand = "PlayCommand"
	// CmdStop is a MediaCommand of type CmdStop.
	CmdStop MediaCommand = "StopSequence"
	// CmdPause is a MediaCommand of type CmdPause.
	CmdPause MediaCommand = "PauseCommand"
	// CmdNext is a MediaCommand of type CmdNext.
	CmdNext MediaCommand = "NextCommand"
	// CmdPrev is a MediaCommand of type CmdPrev.
	CmdPrev MediaCommand = "PreviousCommand"
	// CmdRewind is a MediaCommand of type CmdRewind.
	CmdRewind MediaCommand = "RewindCommand"
	// CmdForward is a MediaCommand of type CmdForward.
	CmdForward MediaCommand = "ForwardCommand"
)

func MediaCommandValues

func MediaCommandValues() []MediaCommand

MediaCommandValues returns a list of the values for MediaCommand

func ParseMediaCommand

func ParseMediaCommand(name string) (MediaCommand, error)

ParseMediaCommand attempts to convert a string to a MediaCommand.

func (*MediaCommand) AppendText

func (x *MediaCommand) AppendText(b []byte) ([]byte, error)

AppendText appends the textual representation of itself to the end of b (allocating a larger slice if necessary) and returns the updated slice.

Implementations must not retain b, nor mutate any bytes within b[:len(b)].

func (MediaCommand) IsValid

func (x MediaCommand) IsValid() bool

IsValid provides a quick way to determine if the typed value is part of the allowed enumerated values

func (MediaCommand) MarshalText

func (x MediaCommand) MarshalText() ([]byte, error)

MarshalText implements the text marshaller method.

func (MediaCommand) String

func (x MediaCommand) String() string

String implements the Stringer interface.

func (*MediaCommand) UnmarshalText

func (x *MediaCommand) UnmarshalText(text []byte) error

UnmarshalText implements the text unmarshaller method.

type MediaProgressChangeEvent

type MediaProgressChangeEvent struct {
	// contains filtered or unexported fields
}

MediaProgressChangeEvent reports playback-position progress within the current media.

func NewMediaProgressChangeEvent

func NewMediaProgressChangeEvent(b PushEventBase) *MediaProgressChangeEvent

NewMediaProgressChangeEvent — decoder constructor.

func (*MediaProgressChangeEvent) RawPayload

func (b *MediaProgressChangeEvent) RawPayload() map[string]any

func (*MediaProgressChangeEvent) SerialNumber

func (b *MediaProgressChangeEvent) SerialNumber() string

func (*MediaProgressChangeEvent) Type

func (b *MediaProgressChangeEvent) Type() PushMessageType

type MediaQueueChangeEvent

type MediaQueueChangeEvent struct {
	// contains filtered or unexported fields
}

MediaQueueChangeEvent reports a change to a device's media queue.

func NewMediaQueueChangeEvent

func NewMediaQueueChangeEvent(b PushEventBase) *MediaQueueChangeEvent

NewMediaQueueChangeEvent — decoder constructor.

func (*MediaQueueChangeEvent) RawPayload

func (b *MediaQueueChangeEvent) RawPayload() map[string]any

func (*MediaQueueChangeEvent) SerialNumber

func (b *MediaQueueChangeEvent) SerialNumber() string

func (*MediaQueueChangeEvent) Type

func (b *MediaQueueChangeEvent) Type() PushMessageType

type MediaService

type MediaService struct {
	// contains filtered or unexported fields
}

MediaService is the user-facing surface for Alexa media operations. Command facades (Speak/Announce/SetVolume/PlaySound/PlayMusic/...) route through SequenceService for batching + ParallelNode wrapping. State queries (DeviceVolumes/MediaStates/MusicProviders) call alexa.amazon.<domain> directly.

Safe for concurrent use.

func (*MediaService) Announce

func (s *MediaService) Announce(ctx context.Context, d *Device, text string) error

Announce broadcasts a message on the device's cluster. Cluster fanout lives inside the operation payload's target.devices field (not as per-member nodes), so this is a single Send + Flush.

func (*MediaService) CallRoutine

func (s *MediaService) CallRoutine(ctx context.Context, d *Device, name string) error

CallRoutine triggers a named routine via Sequence (lazy-loads the routines cache if empty). The single-device routine is fanned out per cluster member.

func (*MediaService) Control

func (s *MediaService) Control(ctx context.Context, d *Device, cmd MediaCommand) error

Control issues a media-playback control (Play/Pause/Next/Previous/ Rewind/FastForward/Stop) against the device's cluster.

Stop is special: upstream routes it through the Sequence pipeline (Alexa.DeviceControls.Stop) so that any in-flight Speak/Music ops are also halted as part of the same coalesced batch. All other commands POST directly to /api/np/command — no batching.

func (*MediaService) DeviceVolumes

func (s *MediaService) DeviceVolumes(ctx context.Context) (map[string]*VolumeState, error)

DeviceVolumes returns the current per-device volume + mute state. Cached for the Realtime-class TTL. Returned map is a defensive copy.

func (*MediaService) InfoSkill

func (s *MediaService) InfoSkill(ctx context.Context, d *Device, skill string) error

InfoSkill triggers one of the canonical Alexa info skills (Weather, Date, Time, ...). Unknown skill names are rejected without contacting Amazon.

func (*MediaService) InfoSkills

func (s *MediaService) InfoSkills() []string

InfoSkills returns the canonical list of "Info" skill names accepted by InfoSkill (e.g. "Alexa.Weather.Play"). The slice is a fresh copy.

func (*MediaService) LaunchSkill

func (s *MediaService) LaunchSkill(ctx context.Context, d *Device, skillName string) error

LaunchSkill launches a specific skill by name on each cluster member of d. skillName is the Alexa-skill identifier (e.g., "MySkill").

func (*MediaService) MediaStates

func (s *MediaService) MediaStates(ctx context.Context, devices []*Device) (map[string]*MediaState, error)

MediaStates returns the current playback state for each device that has MediaPlayerSupported=true. The /api/np/list-media-sessions endpoint takes one (serial, type) as the query string but returns snapshots for the whole account — so the raw response is cached under sentinel key "" for the Realtime-class TTL, and the caller's devices list filters the cached snapshot on read. If devices is empty, MediaStates returns an empty map without contacting Amazon.

The wire endpoint validates (serial, type) even though the response is account-wide, so the first caller's device is recorded and used as the loader's query parameters on subsequent cache misses.

func (*MediaService) MusicProviders

func (s *MediaService) MusicProviders(ctx context.Context) (map[string]MusicProvider, error)

MusicProviders returns the available music providers. Cached for the Long-class TTL and tagged "session" — account switches drop the cache automatically. Returned map is a defensive copy.

func (*MediaService) PlayMusic

func (s *MediaService) PlayMusic(ctx context.Context, d *Device, query, providerID string) error

PlayMusic asks each cluster member of d to play music from the named provider. providerID must be a known music provider — call MusicProviders() to enumerate. Unknown providers return an error without contacting Amazon.

func (*MediaService) PlaySound

func (s *MediaService) PlaySound(ctx context.Context, d *Device, soundID string) error

PlaySound triggers an Alexa sound on each cluster member of d. soundID must be present in Sounds(ctx); unknown IDs return "alexactl: sound %q not available" without contacting Amazon.

func (*MediaService) SetVolume

func (s *MediaService) SetVolume(ctx context.Context, d *Device, vol int) error

SetVolume sets a volume in [0, 100] on each cluster member.

func (*MediaService) Sounds

func (s *MediaService) Sounds(ctx context.Context) (map[string]Sound, error)

Sounds returns the live Alexa sound-effects catalogue keyed by Sound.ID. Cached per MediaService for the configured Long-class TTL (overridable via WithSoundsTTL). Concurrent callers share the in-flight fetch.

The returned map is a defensive copy.

func (*MediaService) Speak

func (s *MediaService) Speak(ctx context.Context, d *Device, text string) error

Speak utters text on the given device (and on each cluster member). One Sequence.Send per cluster member is buffered and a single Flush dispatches them in a single POST (optimised into a ParallelNode by the optimisation pass).

func (*MediaService) TextCommand

func (s *MediaService) TextCommand(ctx context.Context, d *Device, text string) error

TextCommand sends an arbitrary spoken-style command to each cluster member of d (e.g., "what time is it"). Same wire path as Speak but authored by amzn1.ask.1p.tellalexa.

type MediaSessionsUpdatedEvent

type MediaSessionsUpdatedEvent struct {
	// contains filtered or unexported fields
}

MediaSessionsUpdatedEvent reports a refresh of the device's media-sessions list.

func NewMediaSessionsUpdatedEvent

func NewMediaSessionsUpdatedEvent(b PushEventBase) *MediaSessionsUpdatedEvent

NewMediaSessionsUpdatedEvent — decoder constructor.

func (*MediaSessionsUpdatedEvent) RawPayload

func (b *MediaSessionsUpdatedEvent) RawPayload() map[string]any

func (*MediaSessionsUpdatedEvent) SerialNumber

func (b *MediaSessionsUpdatedEvent) SerialNumber() string

func (*MediaSessionsUpdatedEvent) Type

func (b *MediaSessionsUpdatedEvent) Type() PushMessageType

type MediaState

type MediaState struct {
	PlayerState          string // "PLAYING" | "PAUSED" | "IDLE" | ""
	NowPlayingURL        string // mainArt.largeUrl
	NowPlayingTitle      string // infoText.title
	NowPlayingLine1      string // infoText.subText1
	NowPlayingLine2      string // infoText.subText2
	NextEnabled          bool
	PreviousEnabled      bool
	PauseEnabled         bool
	SeekForwardEnabled   bool
	SeekBackEnabled      bool
	ShuffleEnabled       bool
	RepeatEnabled        bool
	MediaLength          time.Duration // 0 if absent
	MediaPosition        time.Duration // 0 if absent
	MediaPositionUpdated time.Time     // local capture time
	MediaProvider        string        // provider.providerName
	MediaProviderURL     string        // provider.providerLogo.url
}

MediaState is a per-device snapshot of the current /api/np/list-media-sessions entry. Returned by MediaService.MediaStates. Fields with no wire value are zero-valued strings/bools/durations/time.Time — Go's idiom rather than Python's Optional.

type MicrophoneStatusEvent

type MicrophoneStatusEvent struct {
	// contains filtered or unexported fields
}

MicrophoneStatusEvent reports a device's microphone (mute) state change.

func NewMicrophoneStatusEvent

func NewMicrophoneStatusEvent(b PushEventBase) *MicrophoneStatusEvent

NewMicrophoneStatusEvent — decoder constructor.

func (*MicrophoneStatusEvent) RawPayload

func (b *MicrophoneStatusEvent) RawPayload() map[string]any

func (*MicrophoneStatusEvent) SerialNumber

func (b *MicrophoneStatusEvent) SerialNumber() string

func (*MicrophoneStatusEvent) Type

func (b *MicrophoneStatusEvent) Type() PushMessageType

type ModeControl

type ModeControl struct {
	// contains filtered or unexported fields
}

ModeControl is the typed accessor returned by Device.Mode(instance) for devices that expose Alexa.ModeController. A single device can expose multiple Mode instances (a Sensibo air-conditioner has Apparatus.FanSpeed AND Apparatus.FanDirection, both addressed through ModeControl with different instance arguments).

Set posts {"mode": <wire-string>} via the V1 setEndpointFeatures mutation. The valid wire-string values per instance are advertised by the device in Sensors[<key>].Configuration["modeOptions"] when the deep query has populated it (see ModeConfiguration parsing).

Adjust posts {"modeDelta": <int>} for instances that support stepping. No optimistic update on Adjust because the resulting absolute mode depends on the device's current value.

func (*ModeControl) Adjust

func (c *ModeControl) Adjust(ctx context.Context, delta int) error

Adjust issues an adjustMode directive with the given signed delta. No optimistic update — the resulting absolute mode depends on the device's current value, which we don't read synchronously.

func (*ModeControl) Set

func (c *ModeControl) Set(ctx context.Context, value string) error

Set issues a setMode directive with the given mode value (e.g. "FanSpeed.High", "Spectrum"). On success, the matching sensor in Device.Sensors is updated optimistically — the sensor key is the canonical name from amzconst.ModeInstances if the instance is known, else "mode:<instance>" matching buildSensor's fallback.

Validates nothing client-side: the device's structured-error response surfaces invalid values via ErrCannotControlDevice with the upstream INVALID_VALUE code in the message.

type MusicProvider

type MusicProvider struct {
	ProviderID      string
	ProviderName    string
	Availability    string
	DefaultProvider bool
}

MusicProvider is one entry from MediaService.MusicProviders. Only providers that support Alexa.Music.PlaySearchPhrase AND have an availability of "AVAILABLE" are surfaced.

type NamedSnapshot

type NamedSnapshot = cache.NamedSnapshot

NamedSnapshot re-exports cache.NamedSnapshot for adapter authors.

type NotificationChangeEvent

type NotificationChangeEvent struct {
	// contains filtered or unexported fields
}

NotificationChangeEvent reports an alarm/timer/reminder change. Even notificationVersion duplicates are filtered by the decoder.

func NewNotificationChangeEvent

func NewNotificationChangeEvent(b PushEventBase) *NotificationChangeEvent

NewNotificationChangeEvent — decoder constructor.

func (*NotificationChangeEvent) RawPayload

func (b *NotificationChangeEvent) RawPayload() map[string]any

func (*NotificationChangeEvent) SerialNumber

func (b *NotificationChangeEvent) SerialNumber() string

func (*NotificationChangeEvent) Type

func (b *NotificationChangeEvent) Type() PushMessageType

type NowPlayingUpdatedEvent

type NowPlayingUpdatedEvent struct {
	// contains filtered or unexported fields
}

NowPlayingUpdatedEvent reports an update to the "now playing" metadata.

func NewNowPlayingUpdatedEvent

func NewNowPlayingUpdatedEvent(b PushEventBase) *NowPlayingUpdatedEvent

NewNowPlayingUpdatedEvent — decoder constructor.

func (*NowPlayingUpdatedEvent) RawPayload

func (b *NowPlayingUpdatedEvent) RawPayload() map[string]any

func (*NowPlayingUpdatedEvent) SerialNumber

func (b *NowPlayingUpdatedEvent) SerialNumber() string

func (*NowPlayingUpdatedEvent) Type

func (b *NowPlayingUpdatedEvent) Type() PushMessageType

type OTPProvider

type OTPProvider interface {
	OTP(ctx context.Context) (string, error)
}

OTPProvider supplies the MFA OTP code to AuthService.Login. The callback is invoked only AFTER Amazon has accepted the password and served the MFA form.

type OTPProviderFunc

type OTPProviderFunc func(ctx context.Context) (string, error)

OTPProviderFunc adapts a function to the OTPProvider interface.

func (OTPProviderFunc) OTP

func (f OTPProviderFunc) OTP(ctx context.Context) (string, error)

OTP implements OTPProvider.

type Option

type Option interface {
	// contains filtered or unexported methods
}

Option configures a Client.

func DisableCache

func DisableCache(class CacheClass) Option

DisableCache is sugar for WithCacheTTL(class, 0).

func WithCachePersistence

func WithCachePersistence(p Persistence) Option

WithCachePersistence wires a save/restore adapter. The library calls Persistence.Load once during NewClient and Persistence.Save on every Client.SnapshotCaches call. Errors from the adapter are logged at WARN and do not abort cache operations.

func WithCacheTTL

func WithCacheTTL(class CacheClass, d time.Duration) Option

WithCacheTTL overrides the TTL for one CacheClass. d <= 0 disables caching for that class entirely.

func WithHTTPClient

func WithHTTPClient(c *http.Client) Option

WithHTTPClient overrides the default *http.Client (which has a cookie jar and HTTP/2 enabled).

func WithLogger

func WithLogger(l *slog.Logger) Option

WithLogger sets the *slog.Logger used by the library. Defaults to slog.Default(). Pass slog.New(slog.DiscardHandler) to silence the library. The supplied logger's handler is wrapped by an internal scrub.Handler that redacts credential-key values from log attributes.

func WithPushCacheBridge

func WithPushCacheBridge() Option

WithPushCacheBridge enables push-event-driven cache invalidation. When set, NewClient subscribes to PushService and routes events to matching cache invalidations via an internal table.

func WithSession

func WithSession(s *Session) Option

WithSession restores a previously serialized Session, skipping the need for a fresh Auth.Login if the tokens are still valid.

func WithSite

func WithSite(site string) Option

WithSite overrides the default site ("https://www.amazon.com"). Useful for accounts whose home region differs from the US default. A change in site is also detected after first login (via customer_info.home_region).

func WithSoundsTTL deprecated

func WithSoundsTTL(d time.Duration) Option

WithSoundsTTL overrides the TTL for the media.sounds cache only. Other Long-class caches use the class default (or WithCacheTTL value). Zero or negative disables caching — every call hits the API.

Deprecated: prefer WithCacheTTL(ClassLong, d) when tuning the broader long-cache class. Removed at v3.0.0.

func WithUserAgent

func WithUserAgent(ua string) Option

WithUserAgent overrides the impersonated browser User-Agent string.

type Persistence

type Persistence = cache.Persistence

Persistence re-exports cache.Persistence so importing apps can write adapters without depending on the internal package.

func FilePersistence

func FilePersistence(path string) Persistence

FilePersistence re-exports cache.NewFilePersistence as the common single-instance-daemon adapter.

type PowerControl

type PowerControl struct {
	// contains filtered or unexported fields
}

PowerControl is the typed accessor returned by Device.Power() for devices that expose Alexa.PowerController. Its three methods — On, Off, Toggle — each issue one setEndpointFeatures mutation. On HTTP success the corresponding Device.Sensors["powerState"] entry is updated optimistically; the next getEndpointState refresh overwrites with the canonical value.

PowerControl is safe for concurrent use; it holds only pointers to state owned by the originating Device.

func (*PowerControl) Off

func (c *PowerControl) Off(ctx context.Context) error

Off issues a turnOff directive. On success, Sensors["powerState"] is set to "OFF".

func (*PowerControl) On

func (c *PowerControl) On(ctx context.Context) error

On issues a turnOn directive. On HTTP 200 with no structured error, Device.Sensors["powerState"].Value is set to "ON".

func (*PowerControl) Toggle

func (c *PowerControl) Toggle(ctx context.Context) error

Toggle reads the cached Sensors["powerState"] entry and issues the opposite directive. If no cached state exists (or the cached value is neither "ON" nor "OFF"), Toggle issues turnOn — the safer default for a powered-off device.

type PushEvent

type PushEvent interface {
	// Type returns the wire-level event identifier.
	Type() PushMessageType

	// SerialNumber returns the device-scoped serial number when the
	// payload includes one, or the empty string when the event is not
	// device-scoped (e.g., MatterDeviceFound carries a setup nonce
	// rather than a serial).
	SerialNumber() string

	// RawPayload returns the parsed JSON object that produced this
	// event. Callers MUST NOT mutate it — the decoder shares the
	// underlying map across all subscribers.
	RawPayload() map[string]any
}

PushEvent is the common interface implemented by every concrete push event type. Concrete event types live in this file. Switch on the concrete type with a type-switch when you need typed-field access; use RawPayload() when you need fields that have not yet been promoted to typed accessors.

func DecodeRenderingUpdate

func DecodeRenderingUpdate(part []byte) ([]PushEvent, error)

DecodeRenderingUpdate parses one part of the AVS directives stream (already extracted from its multipart envelope by the internal/http2stream.Reader) and returns zero or more typed events. The slice may be empty when the part contained only duplicate or malformed updates.

Unknown resourceId values produce *UnknownPushEvent rather than errors — known-unknowns are useful diagnostics for callers tailing the stream.

Lives in the root package (not internal/http2stream) so the stream sub-package has no dependency on the public event types and push.go can safely import internal/http2stream for Conn/Ping/Reader.

type PushEventBase

type PushEventBase = pushEventBase

PushEventBase is the exported alias for pushEventBase used only by the decoder helpers below. Callers should not use this type directly — switch on the concrete typed events instead.

func NewPushEventBase

func NewPushEventBase(serial string, raw map[string]any, kind PushMessageType) PushEventBase

NewPushEventBase is the helper that the internal/http2stream decoder uses to populate the embedded base of any typed push event. Exposed here (rather than letting the decoder reach unexported fields) because the decoder lives in a sub-package.

type PushMessageType

type PushMessageType string

PushMessageType is a push-event wire type sent over the event stream.

ENUM(

PushGenericActivity="PUSH_ACTIVITY",
PushConnectionStatus="PUSH_DOPPLER_CONNECTION_CHANGE",
PushBluetoothStatus="PUSH_BLUETOOTH_STATE_CHANGE",
PushMicrophoneStatus="PUSH_MICROPHONE_STATE",
PushNotificationChange="PUSH_NOTIFICATION_CHANGE",
PushAudioPlayerState="PUSH_AUDIO_PLAYER_STATE",
PushEqualizerStateChange="PUSH_EQUALIZER_STATE_CHANGE",
PushMediaQueueChange="PUSH_MEDIA_QUEUE_CHANGE",
PushMediaChange="PUSH_MEDIA_CHANGE",
PushMediaProgressChange="PUSH_MEDIA_PROGRESS_CHANGE",
PushVolumeChange="PUSH_VOLUME_CHANGE",
PushMediaSessionsUpdated="NotifyMediaSessionsUpdated",
PushNowPlayingUpdated="NotifyNowPlayingUpdated",
PushItemChange="PUSH_LIST_ITEM_CHANGE",
PushMatterDeviceFound="MATTER_SETUP_NOTIFICATION"

)

const (
	// PushGenericActivity is a PushMessageType of type PushGenericActivity.
	PushGenericActivity PushMessageType = "PUSH_ACTIVITY"
	// PushConnectionStatus is a PushMessageType of type PushConnectionStatus.
	PushConnectionStatus PushMessageType = "PUSH_DOPPLER_CONNECTION_CHANGE"
	// PushBluetoothStatus is a PushMessageType of type PushBluetoothStatus.
	PushBluetoothStatus PushMessageType = "PUSH_BLUETOOTH_STATE_CHANGE"
	// PushMicrophoneStatus is a PushMessageType of type PushMicrophoneStatus.
	PushMicrophoneStatus PushMessageType = "PUSH_MICROPHONE_STATE"
	// PushNotificationChange is a PushMessageType of type PushNotificationChange.
	PushNotificationChange PushMessageType = "PUSH_NOTIFICATION_CHANGE"
	// PushAudioPlayerState is a PushMessageType of type PushAudioPlayerState.
	PushAudioPlayerState PushMessageType = "PUSH_AUDIO_PLAYER_STATE"
	// PushEqualizerStateChange is a PushMessageType of type PushEqualizerStateChange.
	PushEqualizerStateChange PushMessageType = "PUSH_EQUALIZER_STATE_CHANGE"
	// PushMediaQueueChange is a PushMessageType of type PushMediaQueueChange.
	PushMediaQueueChange PushMessageType = "PUSH_MEDIA_QUEUE_CHANGE"
	// PushMediaChange is a PushMessageType of type PushMediaChange.
	PushMediaChange PushMessageType = "PUSH_MEDIA_CHANGE"
	// PushMediaProgressChange is a PushMessageType of type PushMediaProgressChange.
	PushMediaProgressChange PushMessageType = "PUSH_MEDIA_PROGRESS_CHANGE"
	// PushVolumeChange is a PushMessageType of type PushVolumeChange.
	PushVolumeChange PushMessageType = "PUSH_VOLUME_CHANGE"
	// PushMediaSessionsUpdated is a PushMessageType of type PushMediaSessionsUpdated.
	PushMediaSessionsUpdated PushMessageType = "NotifyMediaSessionsUpdated"
	// PushNowPlayingUpdated is a PushMessageType of type PushNowPlayingUpdated.
	PushNowPlayingUpdated PushMessageType = "NotifyNowPlayingUpdated"
	// PushItemChange is a PushMessageType of type PushItemChange.
	PushItemChange PushMessageType = "PUSH_LIST_ITEM_CHANGE"
	// PushMatterDeviceFound is a PushMessageType of type PushMatterDeviceFound.
	PushMatterDeviceFound PushMessageType = "MATTER_SETUP_NOTIFICATION"
)

func ParsePushMessageType

func ParsePushMessageType(name string) (PushMessageType, error)

ParsePushMessageType attempts to convert a string to a PushMessageType.

func PushMessageTypeValues

func PushMessageTypeValues() []PushMessageType

PushMessageTypeValues returns a list of the values for PushMessageType

func (*PushMessageType) AppendText

func (x *PushMessageType) AppendText(b []byte) ([]byte, error)

AppendText appends the textual representation of itself to the end of b (allocating a larger slice if necessary) and returns the updated slice.

Implementations must not retain b, nor mutate any bytes within b[:len(b)].

func (PushMessageType) IsValid

func (x PushMessageType) IsValid() bool

IsValid provides a quick way to determine if the typed value is part of the allowed enumerated values

func (PushMessageType) MarshalText

func (x PushMessageType) MarshalText() ([]byte, error)

MarshalText implements the text marshaller method.

func (PushMessageType) String

func (x PushMessageType) String() string

String implements the Stringer interface.

func (*PushMessageType) UnmarshalText

func (x *PushMessageType) UnmarshalText(text []byte) error

UnmarshalText implements the text unmarshaller method.

type PushService

type PushService struct {
	// contains filtered or unexported fields
}

PushService streams real-time push events from Amazon's AVS directives endpoint. Construct only via NewClient; safe for concurrent use across multiple Subscribe callers.

func (*PushService) Subscribe

func (s *PushService) Subscribe(ctx context.Context, opts ...SubscribeOption) (<-chan PushEvent, error)

Subscribe registers a new subscriber and returns its dedicated receive channel. Each call returns a NEW channel; one background goroutine maintains a single upstream stream and fans every parsed event out to all live subscribers.

The first Subscribe starts the stream loop. The last unsubscribe (all subscriber ctxs cancelled) stops it. Reauth-required closes all subscriber channels after delivering a *ReauthRequiredEvent.

type RangeControl

type RangeControl struct {
	// contains filtered or unexported fields
}

RangeControl is the typed accessor returned by Device.Range( instance) for devices that expose Alexa.RangeController. The write path is INTENTIONALLY STUBBED — the setRangeValue / adjustRangeValue wire payload shape has not been confirmed against real hardware, and shipping a best-guess shape would silently fail or behave unexpectedly on real devices.

Set and Adjust both log a WARN message asking the caller to file a GitHub issue with a HAR capture, then return ErrControllerNotImplemented. No network call is attempted.

The accessor (Device.Range) still gates correctly — it returns non-nil only for devices that advertise Alexa.RangeController via AlexaInterfaces (derived from sensor keys today). This lets callers write capability-conditional code that's already shaped for when the real wire path lands.

func (*RangeControl) Adjust

func (c *RangeControl) Adjust(ctx context.Context, delta float64) error

Adjust is the stub for adjustRangeValue. Logs a WARN and returns ErrControllerNotImplemented. Does not call the network.

func (*RangeControl) Set

func (c *RangeControl) Set(ctx context.Context, value float64) error

Set is the stub for setRangeValue. Logs a WARN and returns ErrControllerNotImplemented. Does not call the network.

type ReauthRequiredEvent

type ReauthRequiredEvent struct{}

ReauthRequiredEvent is delivered by PushService as the final event before the subscriber's channel closes whenever the stream returns 401/403 even after a token refresh attempt. The type is defined so callers can write `switch evt.(type)` against it.

func (*ReauthRequiredEvent) RawPayload

func (e *ReauthRequiredEvent) RawPayload() map[string]any

RawPayload implements PushEvent.

func (*ReauthRequiredEvent) SerialNumber

func (e *ReauthRequiredEvent) SerialNumber() string

SerialNumber implements PushEvent.

func (*ReauthRequiredEvent) Type

Type implements PushEvent.

type Recurrence

type Recurrence struct {
	// contains filtered or unexported fields
}

Recurrence wraps an RFC 5545 RRULE describing how an alarm or reminder repeats. Construct via the package-level helpers below (preferred for common cases) or RecurrenceRule for custom RRULE strings.

At Create/Update time the service layer appends BYHOUR / BYMINUTE / BYSECOND to the stored RRULE using the alarm/reminder's FireAt time-of-day, then sends it under rRuleData.recurrenceRules. Callers don't see this — the public surface is just the helpers below.

func RecurrenceDaily

func RecurrenceDaily() *Recurrence

RecurrenceDaily fires every day at the alarm/reminder's FireAt time.

func RecurrenceRule

func RecurrenceRule(rrule string) *Recurrence

RecurrenceRule is the raw-RRULE escape hatch for cases the typed helpers don't cover (monthly, custom intervals, etc.). The caller is responsible for the RRULE's correctness.

func RecurrenceWeekdays

func RecurrenceWeekdays() *Recurrence

RecurrenceWeekdays fires every Monday through Friday.

func RecurrenceWeekends

func RecurrenceWeekends() *Recurrence

RecurrenceWeekends fires every Saturday and Sunday.

func RecurrenceWeekly

func RecurrenceWeekly(days ...time.Weekday) *Recurrence

RecurrenceWeekly fires on the given days of the week. Days are deduplicated and emitted in canonical Mon-first order regardless of input order. At least one day must be supplied.

func (*Recurrence) Describe

func (r *Recurrence) Describe() string

Describe returns a short human-friendly description of the recurrence. Used by the CLI for display; the library doesn't otherwise depend on the format.

func (*Recurrence) RRule

func (r *Recurrence) RRule() string

RRule returns the canonical RFC 5545 RRULE string.

type RefreshOption

type RefreshOption interface {
	// contains filtered or unexported methods
}

RefreshOption tunes DevicesService.Refresh behavior. Returned by functional-option constructors below; pass to Refresh via variadic arguments.

func WithoutSensors

func WithoutSensors() RefreshOption

WithoutSensors instructs Refresh to skip the sensor-enrichment step. Useful for fast-path callers that don't need Device.Sensors populated. Online flags are then taken from the base /api/devices-v2/device response only.

type Reminder

type Reminder struct {
	ID                 string
	DeviceSerialNumber string
	DeviceType         string
	FireAt             time.Time
	Label              string // required — what Alexa speaks
	Recurrence         *Recurrence
	Status             string
	Acknowledged       bool
	Version            int
	CreatedAt          time.Time
	UpdatedAt          time.Time
	// contains filtered or unexported fields
}

Reminder is a labeled one-shot or recurring event Alexa speaks.

type RemindersService

type RemindersService struct {
	// contains filtered or unexported fields
}

RemindersService manages reminders (typed text labels that Alexa speaks at the scheduled time) on Echo devices.

Wire endpoints (cookie + CSRF auth on alexa.amazon.<tld>):

GET    /api/notifications                       — shared read (filtered to Reminder)
PUT    /api/notifications/createReminder        — Create
PUT    /api/notifications/<id>                  — Update / Enable / Disable / Acknowledge
DELETE /api/notifications/<id>                  — Delete

Safe for concurrent use.

func (*RemindersService) Acknowledge

func (s *RemindersService) Acknowledge(ctx context.Context, r *Reminder) error

Acknowledge flips followUpMetadata.followUpStatus to ACKNOWLEDGED. No-op + nil if already ACKNOWLEDGED.

func (*RemindersService) Create

func (s *RemindersService) Create(ctx context.Context, r *Reminder) (*Reminder, error)

Create posts a new reminder.

func (*RemindersService) Delete

func (s *RemindersService) Delete(ctx context.Context, r *Reminder) error

Delete removes the reminder from the account. Returns ErrReminderNotFound if r is nil or owned by a different service.

func (*RemindersService) Disable

func (s *RemindersService) Disable(ctx context.Context, r *Reminder) error

Disable flips status to OFF. No-op + nil if already OFF.

func (*RemindersService) Enable

func (s *RemindersService) Enable(ctx context.Context, r *Reminder) error

Enable flips status to ON. No-op + nil if already ON.

func (*RemindersService) Get

func (s *RemindersService) Get(ctx context.Context) ([]*Reminder, error)

Get fetches every active reminder on the account, sorted by FireAt ascending. Entries with status != "ON" are dropped.

func (*RemindersService) Update

func (s *RemindersService) Update(ctx context.Context, r *Reminder) error

Update sends the reminder's typed label/time/recurrence to the server, layered over the cached serverShape echo. Returns ErrReminderNotFound if r is nil or owned by a different service.

type SensorsService

type SensorsService struct {
	// contains filtered or unexported fields
}

SensorsService populates Device.Sensors (and rewrites Device.Online from the per-device reachability sensor) by POSTing the getEndpointState GraphQL operation to /nexus/v1/graphql.

Wired into DevicesService.Refresh as the post-enrichment step. Callers don't usually invoke Update directly; it's called for them.

Safe for concurrent use.

func (*SensorsService) Update

func (s *SensorsService) Update(
	ctx context.Context,
	devices map[string]*Device,
	endpoints map[string]string,
	dnd map[string]*DeviceSensor,
) error

Update fetches sensor state for the given endpoints and applies it to the devices map in place:

  • Sets device.Sensors to the parsed sensor map (replacing any existing entries). When no sensors are returned for a device, the existing Sensors map is marked with Error: true on every entry.
  • Sets device.Online from the "reachability" sensor's value ("OK" → true, anything else → false). When no reachability sensor is present, device.Online is set to false.
  • For speaker-group devices (DeviceFamily == amzconst.SpeakerGroupFamily), online is the AND of every cluster member's Online value.
  • If dnd is non-nil, copies each matching DnD entry onto device.Sensors["dnd"] for non-speaker-group devices.

devices and endpoints are the maps populated by DevicesService earlier in the refresh pipeline (devices keyed by serial; endpoints keyed by endpointID → serial). Errors fetching the sensor state surface to the caller; per-device parse problems are logged at debug and don't fail the operation.

type SequenceService

type SequenceService struct {
	// contains filtered or unexported fields
}

SequenceService dispatches Alexa sequence operations (Speak, Announcement, Sound, Music, TextCommand, LaunchSkill, Volume, Stop, Routines) to one or more devices via /api/behaviors/preview.

Operations issued via Send are buffered for up to SequenceBatchDelay (300ms) and posted as a single sequence. Identical operations on distinct devices are wrapped in a ParallelNode so Amazon executes them concurrently. Flush preempts the timer and drains synchronously.

Routines() lazy-loads and caches the enabled-routine set so that CallRoutine() can look up the startNode payload.

Safe for concurrent use.

func (*SequenceService) Flush

func (s *SequenceService) Flush(ctx context.Context) error

Flush forces any pending batch to be sent synchronously. Used by MediaService.Speak/Announce/SetVolume facades to preserve their Phase-1 sync semantics, and by callers wanting deterministic error-propagation. Idempotent on an empty buffer.

Flush bumps batchGen so any sleeping processBatch goroutine will notice its generation is stale and exit cleanly without re-draining the (now-empty) buffer.

func (*SequenceService) RefreshRoutines

func (s *SequenceService) RefreshRoutines(ctx context.Context) error

RefreshRoutines forces a re-fetch on the next Routines/CallRoutine.

func (*SequenceService) Routines

func (s *SequenceService) Routines(ctx context.Context) ([]string, error)

Routines returns the names of ENABLED routines on the account. First call fetches; subsequent calls within TTL return the cached names. Use RefreshRoutines to force a re-fetch.

func (*SequenceService) Send

func (s *SequenceService) Send(ctx context.Context, d *Device, kind SequenceType, body any, providerID string) error

Send enqueues an operation against a device for the next batch. The HTTP POST happens after sequenceBatchDelay (300ms) unless Flush is called sooner. Returns the build error synchronously (unknown messageType, missing session) but does NOT report the HTTP outcome — async failures are logged at WARN level. Callers wanting sync semantics call Flush after Send.

type SequenceType

type SequenceType string

SequenceType is an Alexa sequence command name as it appears on the wire.

ENUM(

SeqSpeak="Alexa.Speak",
SeqAnnouncement="AlexaAnnouncement",
SeqSound="Alexa.Sound",
SeqMusic="Alexa.Music.PlaySearchPhrase",
SeqTextCommand="Alexa.TextCommand",
SeqLaunchSkill="Alexa.Operation.SkillConnections.Launch",
SeqVolume="Alexa.DeviceControls.Volume",
SeqStop="Alexa.DeviceControls.Stop",
SeqRoutine="Pseudo.Type.Routines"

)

const (
	// SeqSpeak is a SequenceType of type SeqSpeak.
	SeqSpeak SequenceType = "Alexa.Speak"
	// SeqAnnouncement is a SequenceType of type SeqAnnouncement.
	SeqAnnouncement SequenceType = "AlexaAnnouncement"
	// SeqSound is a SequenceType of type SeqSound.
	SeqSound SequenceType = "Alexa.Sound"
	// SeqMusic is a SequenceType of type SeqMusic.
	SeqMusic SequenceType = "Alexa.Music.PlaySearchPhrase"
	// SeqTextCommand is a SequenceType of type SeqTextCommand.
	SeqTextCommand SequenceType = "Alexa.TextCommand"
	// SeqLaunchSkill is a SequenceType of type SeqLaunchSkill.
	SeqLaunchSkill SequenceType = "Alexa.Operation.SkillConnections.Launch"
	// SeqVolume is a SequenceType of type SeqVolume.
	SeqVolume SequenceType = "Alexa.DeviceControls.Volume"
	// SeqStop is a SequenceType of type SeqStop.
	SeqStop SequenceType = "Alexa.DeviceControls.Stop"
	// SeqRoutine is a SequenceType of type SeqRoutine.
	SeqRoutine SequenceType = "Pseudo.Type.Routines"
)

func ParseSequenceType

func ParseSequenceType(name string) (SequenceType, error)

ParseSequenceType attempts to convert a string to a SequenceType.

func SequenceTypeValues

func SequenceTypeValues() []SequenceType

SequenceTypeValues returns a list of the values for SequenceType

func (*SequenceType) AppendText

func (x *SequenceType) AppendText(b []byte) ([]byte, error)

AppendText appends the textual representation of itself to the end of b (allocating a larger slice if necessary) and returns the updated slice.

Implementations must not retain b, nor mutate any bytes within b[:len(b)].

func (SequenceType) IsValid

func (x SequenceType) IsValid() bool

IsValid provides a quick way to determine if the typed value is part of the allowed enumerated values

func (SequenceType) MarshalText

func (x SequenceType) MarshalText() ([]byte, error)

MarshalText implements the text marshaller method.

func (SequenceType) String

func (x SequenceType) String() string

String implements the Stringer interface.

func (*SequenceType) UnmarshalText

func (x *SequenceType) UnmarshalText(text []byte) error

UnmarshalText implements the text unmarshaller method.

type Session

type Session struct {
	// OAuth tokens
	AccessToken      string    `json:"access_token"`
	RefreshToken     string    `json:"refresh_token"`
	ADPToken         string    `json:"adp_token"`
	DevicePrivateKey string    `json:"device_private_key"`
	ExpiresAt        time.Time `json:"expires_at"`

	// Cookies re-applied per request.
	// WebsiteCookies is immutable after a Session is returned by NewClient/Auth.Login/Auth.Restore — services treat the map as read-only.
	WebsiteCookies  map[string]string `json:"website_cookies"`
	StoreAuthCookie string            `json:"store_authentication_cookie"`

	// Registered device identity
	DeviceInfo   DeviceInfo   `json:"device_info"`
	CustomerInfo CustomerInfo `json:"customer_info"`

	// Region / domain state
	Site              string `json:"site"`   // e.g. "https://www.amazon.com"
	Domain            string `json:"domain"` // e.g. "com", "co.jp"
	AccountCustomerID string `json:"account_customer_id"`

	// Phase-3 marker — true once device capabilities are registered.
	CapabilitiesRegistered bool `json:"capabilities_registered,omitempty"`
}

Session is the full authenticated state returned by AuthService.Login. Marshal it to disk with json.Marshal and pass it back via WithSession on the next run. Contains long-lived refresh tokens and cookies — protect the file (mode 0600 on POSIX).

func (*Session) Expired

func (s *Session) Expired(now time.Time) bool

Expired reports whether the access token has expired relative to now. Refresh-token lifetime is much longer; refresh logic lives in the HTTP wrapper.

type Sound

type Sound struct {
	ID                  string // wire id, pass to PlaySound (e.g. "amzn_sfx_doorbell_01")
	DisplayName         string // localized label (e.g. "Doorbell 1")
	Category            string // wire category token (e.g. "bell_and_buzzers")
	CategoryDisplayName string // localized category label (e.g. "Bells & Buzzers")
}

Sound is a single Alexa sound effect from the routine sound catalogue. Returned by MediaService.Sounds(ctx). Only entries with availability "AVAILABLE" on the wire are surfaced.

type SubscribeOption

type SubscribeOption interface {
	// contains filtered or unexported methods
}

SubscribeOption configures a single Subscribe call. Options are applied left-to-right; later options win on conflict.

func WithInitialSyncOnFirstEvent

func WithInitialSyncOnFirstEvent() SubscribeOption

WithInitialSyncOnFirstEvent requests a one-shot synthetic burst of *VolumeChangeEvent for each device known to the Devices service, delivered to this subscriber's channel the first time the stream emits any event. The burst lets callers reconstruct current volume state without waiting for users to interact with each device.

History.Vocal sync is documented in the spec but not wired in this release — History is available without exposing Vocal-grouped records.

func WithPushChannelCapacity

func WithPushChannelCapacity(n int) SubscribeOption

WithPushChannelCapacity overrides the per-subscriber channel buffer. Values < 1 are silently clamped to 1 (an unbuffered push channel would back-pressure into the shared upstream stream — refused).

type TemperatureScale

type TemperatureScale string

TemperatureScale is the unit a thermostat reports temperatures in.

ENUM(

TemperatureScaleCelsius="CELSIUS",
TemperatureScaleFahrenheit="FAHRENHEIT",
TemperatureScaleKelvin="KELVIN"

)

const (
	// TemperatureScaleCelsius is a TemperatureScale of type TemperatureScaleCelsius.
	TemperatureScaleCelsius TemperatureScale = "CELSIUS"
	// TemperatureScaleFahrenheit is a TemperatureScale of type TemperatureScaleFahrenheit.
	TemperatureScaleFahrenheit TemperatureScale = "FAHRENHEIT"
	// TemperatureScaleKelvin is a TemperatureScale of type TemperatureScaleKelvin.
	TemperatureScaleKelvin TemperatureScale = "KELVIN"
)

func ParseTemperatureScale

func ParseTemperatureScale(name string) (TemperatureScale, error)

ParseTemperatureScale attempts to convert a string to a TemperatureScale.

func TemperatureScaleValues

func TemperatureScaleValues() []TemperatureScale

TemperatureScaleValues returns a list of the values for TemperatureScale

func (*TemperatureScale) AppendText

func (x *TemperatureScale) AppendText(b []byte) ([]byte, error)

AppendText appends the textual representation of itself to the end of b (allocating a larger slice if necessary) and returns the updated slice.

Implementations must not retain b, nor mutate any bytes within b[:len(b)].

func (TemperatureScale) IsValid

func (x TemperatureScale) IsValid() bool

IsValid provides a quick way to determine if the typed value is part of the allowed enumerated values

func (TemperatureScale) MarshalText

func (x TemperatureScale) MarshalText() ([]byte, error)

MarshalText implements the text marshaller method.

func (TemperatureScale) String

func (x TemperatureScale) String() string

String implements the Stringer interface.

func (*TemperatureScale) UnmarshalText

func (x *TemperatureScale) UnmarshalText(text []byte) error

UnmarshalText implements the text unmarshaller method.

type ThermostatControl

type ThermostatControl struct {
	// contains filtered or unexported fields
}

ThermostatControl is the typed accessor returned by Device.Thermostat() for devices that expose Alexa.ThermostatController. Exposes three methods: SetTarget for absolute setpoint, AdjustTarget for signed delta, SetMode for thermostat mode (Heat/Cool/Auto/Off/Eco/EmHeat).

Per-device support varies — not every thermostat supports every mode. Querying the configuration first (Sensors["thermostatMode"]. Configuration["supportedModes"], populated by the deep inspect query) is the recommended way to discover supported modes before calling SetMode.

func (*ThermostatControl) AdjustTarget

func (c *ThermostatControl) AdjustTarget(ctx context.Context, delta float64, scale TemperatureScale) error

AdjustTarget issues an adjustTargetSetpoint directive with a signed delta in the given scale. No optimistic update — the resulting absolute value depends on the device's actual current setpoint, which we don't read synchronously. The next sensor refresh reflects the new absolute value.

func (*ThermostatControl) SetMode

func (c *ThermostatControl) SetMode(ctx context.Context, mode ThermostatMode) error

SetMode issues a setThermostatMode directive. The payload's thermostatMode field carries the wire string ("HEAT" / "COOL" / "AUTO" / "OFF" / "ECO" / "EM_HEAT"). On success, Sensors["thermostatMode"].Value is set to the wire string.

func (*ThermostatControl) SetTarget

func (c *ThermostatControl) SetTarget(ctx context.Context, value float64, scale TemperatureScale) error

SetTarget issues a setTargetSetpoint directive at the given absolute temperature in the given scale. On success, Sensors["targetSetpoint"].Value is set to value and .Scale to the scale's wire string ("CELSIUS" / "FAHRENHEIT" / "KELVIN").

type ThermostatMode

type ThermostatMode string

ThermostatMode is the operating mode a thermostat is set to.

ENUM(

ThermostatModeHeat="HEAT",
ThermostatModeCool="COOL",
ThermostatModeAuto="AUTO",
ThermostatModeOff="OFF",
ThermostatModeEco="ECO",
ThermostatModeEmHeat="EM_HEAT"

)

const (
	// ThermostatModeHeat is a ThermostatMode of type ThermostatModeHeat.
	ThermostatModeHeat ThermostatMode = "HEAT"
	// ThermostatModeCool is a ThermostatMode of type ThermostatModeCool.
	ThermostatModeCool ThermostatMode = "COOL"
	// ThermostatModeAuto is a ThermostatMode of type ThermostatModeAuto.
	ThermostatModeAuto ThermostatMode = "AUTO"
	// ThermostatModeOff is a ThermostatMode of type ThermostatModeOff.
	ThermostatModeOff ThermostatMode = "OFF"
	// ThermostatModeEco is a ThermostatMode of type ThermostatModeEco.
	ThermostatModeEco ThermostatMode = "ECO"
	// ThermostatModeEmHeat is a ThermostatMode of type ThermostatModeEmHeat.
	ThermostatModeEmHeat ThermostatMode = "EM_HEAT"
)

func ParseThermostatMode

func ParseThermostatMode(name string) (ThermostatMode, error)

ParseThermostatMode attempts to convert a string to a ThermostatMode.

func ThermostatModeValues

func ThermostatModeValues() []ThermostatMode

ThermostatModeValues returns a list of the values for ThermostatMode

func (*ThermostatMode) AppendText

func (x *ThermostatMode) AppendText(b []byte) ([]byte, error)

AppendText appends the textual representation of itself to the end of b (allocating a larger slice if necessary) and returns the updated slice.

Implementations must not retain b, nor mutate any bytes within b[:len(b)].

func (ThermostatMode) IsValid

func (x ThermostatMode) IsValid() bool

IsValid provides a quick way to determine if the typed value is part of the allowed enumerated values

func (ThermostatMode) MarshalText

func (x ThermostatMode) MarshalText() ([]byte, error)

MarshalText implements the text marshaller method.

func (ThermostatMode) String

func (x ThermostatMode) String() string

String implements the Stringer interface.

func (*ThermostatMode) UnmarshalText

func (x *ThermostatMode) UnmarshalText(text []byte) error

UnmarshalText implements the text unmarshaller method.

type Timer

type Timer struct {
	ID                 string
	DeviceSerialNumber string
	DeviceType         string
	Duration           time.Duration // total countdown length
	Label              string        // optional ("pasta")
	Remaining          time.Duration // read-only: time left until fire
	Sound              string        // optional
	FireAt             time.Time     // CreatedAt + Duration (= triggerTime)
	Status             string        // "ON"
	Version            int
	CreatedAt          time.Time
	// contains filtered or unexported fields
}

Timer is a countdown-from-creation event. Always one-shot — Amazon doesn't support recurring timers (use *Alarm with *Recurrence instead).

type TimersService

type TimersService struct {
	// contains filtered or unexported fields
}

TimersService manages countdown timers on Echo devices.

Wire endpoints (cookie + CSRF auth on alexa.amazon.<tld>):

GET    /api/notifications                       — shared read (filtered to Timer)
PUT    /api/notifications/createTimer           — Create
DELETE /api/notifications/<id>                  — Delete

No Update (duration is immutable once running — Delete + Create). No Pause / Resume (not exposed by the cookie-auth API; use Sequence.TextCommand(serial, "pause my timer") instead).

Safe for concurrent use.

func (*TimersService) Create

func (s *TimersService) Create(ctx context.Context, t *Timer) (*Timer, error)

Create posts a new timer. Timer must have DeviceSerialNumber and Duration set; DeviceType is auto-populated from the Devices cache. Returns ErrDeviceNotFound (without hitting the network) when the serial isn't in the cache.

func (*TimersService) Delete

func (s *TimersService) Delete(ctx context.Context, t *Timer) error

Delete cancels the timer. Returns ErrTimerNotFound if t is nil or owned by a different service.

func (*TimersService) Get

func (s *TimersService) Get(ctx context.Context) ([]*Timer, error)

Get fetches every active timer on the account, sorted by FireAt ascending. Entries with status != "ON" are dropped.

type ToggleControl

type ToggleControl struct {
	// contains filtered or unexported fields
}

ToggleControl is the typed accessor returned by Device.Toggle( instance) for devices that expose Alexa.ToggleController. The write path is INTENTIONALLY STUBBED — the toggle On/Off wire payload + operation-name shape has not been confirmed against real hardware (no devices on any test account expose a callable ToggleController). Rather than ship a best-guess shape, On / Off log a WARN message asking the caller to file a GitHub issue with a HAR capture, then return ErrControllerNotImplemented.

The accessor (Device.Toggle) gates correctly — it returns non-nil only for devices that advertise Alexa.ToggleController via AlexaInterfaces. This lets callers write capability-conditional code that's already shape-compatible with the future real implementation.

func (*ToggleControl) Off

func (c *ToggleControl) Off(ctx context.Context) error

Off is the stub for the toggle "turnOff" directive. Logs a WARN and returns ErrControllerNotImplemented. Does not call the network.

func (*ToggleControl) On

func (c *ToggleControl) On(ctx context.Context) error

On is the stub for the toggle "turnOn" directive. Logs a WARN and returns ErrControllerNotImplemented. Does not call the network.

type UnknownPushEvent

type UnknownPushEvent struct {
	// WireType is the literal resourceId string we received.
	WireType string
	// Serial is the device serial number if the payload happened to
	// include one in the expected place; otherwise empty.
	Serial string
	// Payload is the parsed JSON.
	Payload map[string]any
}

UnknownPushEvent is delivered whenever the decoder sees a resourceId it does not recognise. Surfaces unknown events rather than silently dropping them (better for debuggability than upstream's WARN-and-drop).

func (*UnknownPushEvent) RawPayload

func (e *UnknownPushEvent) RawPayload() map[string]any

RawPayload implements PushEvent.

func (*UnknownPushEvent) SerialNumber

func (e *UnknownPushEvent) SerialNumber() string

SerialNumber implements PushEvent.

func (*UnknownPushEvent) Type

Type returns the empty PushMessageType — by definition the wire string did not correspond to a known member. Callers inspect WireType directly for the raw resourceId.

type VocalRecord

type VocalRecord struct {
	// Timestamp is the time Amazon recorded the utterance, in UTC.
	Timestamp time.Time

	// HistoryType holds Amazon's classification string for the record:
	// the utteranceType when present (e.g., "GENERAL",
	// "ROUTINES_OR_TAP_TO_ALEXA"); otherwise recordType (e.g.,
	// "CustomerReview"); otherwise "Unknown". The four upstream
	// "ignore" utteranceType values (ASR_TIMEOUT, DEVICE_ARBITRATION,
	// NO_EXPRESSED_INTENT, WAKE_WORD_ONLY) are filtered out before
	// construction.
	HistoryType string

	// Intent is the Alexa intent that matched (may be empty for free-form
	// requests).
	Intent string

	// Title is Amazon's short description of the utterance.
	Title string

	// SubTitle is Amazon's longer description of the utterance.
	SubTitle string
}

VocalRecord is the latest utterance captured by Alexa for a single device, returned by HistoryService.Vocal. Mirrors the per-device latest-record output of upstream get_vocal_history.

type VolumeChangeEvent

type VolumeChangeEvent struct {
	Volume int
	Muted  bool
	// contains filtered or unexported fields
}

VolumeChangeEvent reports that a device's volume or mute state changed.

Volume is the post-change volume on 0..100; Muted is the post-change mute state. Both fields are decoded from the payload at construction time; if either is absent, the zero value is used.

func NewVolumeChangeEvent

func NewVolumeChangeEvent(base PushEventBase, volume int, muted bool) *VolumeChangeEvent

NewVolumeChangeEvent — decoder constructor.

func (*VolumeChangeEvent) RawPayload

func (b *VolumeChangeEvent) RawPayload() map[string]any

func (*VolumeChangeEvent) SerialNumber

func (b *VolumeChangeEvent) SerialNumber() string

func (*VolumeChangeEvent) Type

func (b *VolumeChangeEvent) Type() PushMessageType

type VolumeState

type VolumeState struct {
	Volume int // 0..100
	Muted  bool
}

VolumeState is the per-device volume snapshot returned by MediaService.DeviceVolumes.

Directories

Path Synopsis
cmd
alexa-introspect command
Command alexa-introspect runs the standard GraphQL introspection query against alexa.amazon.com/nexus/v1/graphql using a logged-in session loaded from session.json.
Command alexa-introspect runs the standard GraphQL introspection query against alexa.amazon.com/nexus/v1/graphql using a logged-in session loaded from session.json.
alexactl command
Command alexactl is the manual CLI smoke-test harness for alexactl.
Command alexactl is the manual CLI smoke-test harness for alexactl.
alexactl/cmd
Package cmd implements the cobra commands for the alexactl CLI, a manual exercise harness for the alexactl library.
Package cmd implements the cobra commands for the alexactl CLI, a manual exercise harness for the alexactl library.
internal
alexagraphql
Package alexagraphql contains the auto-generated typed GraphQL client used by alexactl to talk to alexa.amazon.com's /nexus/v1/graphql endpoint.
Package alexagraphql contains the auto-generated typed GraphQL client used by alexactl to talk to alexa.amazon.com's /nexus/v1/graphql endpoint.
amzconst
Package amzconst holds constants modeled on aioamazondevices' const/ subpackage.
Package amzconst holds constants modeled on aioamazondevices' const/ subpackage.
cache
Package cache provides a generic, in-memory cache with class-based TTLs, single-flight loader semantics, tag invalidation, and a persistence-adapter contract for save/restore between runs.
Package cache provides a generic, in-memory cache with class-based TTLs, single-flight loader semantics, tag invalidation, and a persistence-adapter contract for save/restore between runs.
http2stream
Package http2stream parses Amazon's AVS directives stream.
Package http2stream parses Amazon's AVS directives stream.
httpwrapper
Package httpwrapper provides the authenticated HTTP request layer used by all public services in the alexactl package.
Package httpwrapper provides the authenticated HTTP request layer used by all public services in the alexactl package.
locale
Package locale maps an Amazon country code (e.g., "US", "JP", "GB") to a BCP-47 language tag (e.g., "en-US", "ja-JP", "en-GB").
Package locale maps an Amazon country code (e.g., "US", "JP", "GB") to a BCP-47 language tag (e.g., "en-US", "ja-JP", "en-GB").
oauth
Package oauth holds helpers used by the AuthService to perform the Amazon iOS-app OAuth flow: PKCE verifier/challenge generation and HTML form scraping for the login pages.
Package oauth holds helpers used by the AuthService to perform the Amazon iOS-app OAuth flow: PKCE verifier/challenge generation and HTML form scraping for the login pages.
scrub
Package scrub redacts sensitive fields from log payloads before they are emitted via slog.
Package scrub redacts sensitive fields from log payloads before they are emitted via slog.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL