Skip to content

api

import "github.com/dahui/z13ctl/api"

Package api provides the public client interface for the z13ctl daemon. It contains the shared protocol types and socket client functions used by CLI commands, GUI frontends, and any other tool that communicates with the z13ctl daemon over its Unix socket.

Index

Constants

const (
    // EventGUIToggle is emitted when the Armoury Crate button is pressed.
    EventGUIToggle = "gui-toggle"

    // EventPowerSource is emitted when the machine moves between mains and
    // battery power. It fires on the transition itself, so it is useful whether
    // or not autoswitch is configured — a client can drive a plug/battery
    // indicator from it alone.
    EventPowerSource = "power-source"

    // EventStateChanged is emitted when the active profile, its settings, the
    // saved profiles, or the autoswitch configuration change — whatever the
    // cause: this client, another client, the CLI, autoswitch, or a resume.
    // A client displaying profile, TDP, fan curve, or undervolt values should
    // re-read them with SendGetState when it arrives.
    //
    // Lighting is deliberately excluded. A brightness slider drag would emit a
    // burst of events describing values the client just set itself.
    EventStateChanged = "state-changed"
)

DefaultCustomProfile is the name of the custom profile created implicitly by the first fan curve, TDP, or undervolt setting made while a stock profile is active. It is reserved and cannot be chosen as a user-supplied name.

const DefaultCustomProfile = "custom"

Variables

AllEvents lists every event name the daemon can emit. Subscribing with an empty event list is equivalent to subscribing to all of them.

var AllEvents = []string{EventGUIToggle, EventPowerSource, EventStateChanged}

StockProfiles are the firmware performance profiles that can be written to platform_profile. They are reserved: a custom profile can never take one of these names, so selecting one always reaches the firmware profile.

var StockProfiles = []string{"quiet", "balanced", "performance"}

func IsStockProfileName

func IsStockProfileName(name string) bool

IsStockProfileName reports whether name is one of the reserved firmware profile names.

func SendApply

func SendApply(device, color, color2, mode, speed string, brightness int) (bool, error)

SendApply sends an apply command to the daemon. color and color2 must be "RRGGBB" hex strings. device may be "keyboard", "lightbar", a /dev/hidrawN path, or "" to target all devices. Returns (true, nil) on success, (false, nil) if the daemon is not running (caller should fall back to direct HID access).

Example

package main

import (
    "fmt"

    "github.com/dahui/z13ctl/api"
)

func main() {
    // Apply a static red color at full brightness to all devices.
    handled, err := api.SendApply("", "FF0000", "000000", "static", "normal", 3)
    if !handled {
        fmt.Println("daemon not running, falling back to direct HID access")
        return
    }
    if err != nil {
        fmt.Println("error:", err)
        return
    }
    fmt.Println("applied")
}

func SendAutoswitchGet

func SendAutoswitchGet() (handled bool, value string, err error)

SendAutoswitchGet queries the daemon for the autoswitch configuration. Returns a JSON AutoswitchState. Returns (false, "", nil) if the daemon is not running.

Example

package main

import (
    "encoding/json"
    "fmt"

    "github.com/dahui/z13ctl/api"
)

func main() {
    handled, value, err := api.SendAutoswitchGet()
    if !handled {
        fmt.Println("daemon not running")
        return
    }
    if err != nil {
        fmt.Println("error:", err)
        return
    }
    var st struct {
        api.AutoswitchState
        OnAC bool `json:"on_ac"`
    }
    if err := json.Unmarshal([]byte(value), &st); err != nil {
        fmt.Println("error:", err)
        return
    }
    fmt.Println(st.Enabled, st.AC, st.Battery, st.OnAC)
}

func SendAutoswitchSet

func SendAutoswitchSet(enabled bool, ac, battery string) (bool, error)

SendAutoswitchSet configures automatic profile selection by power source. An empty ac or battery target leaves the profile alone on that source.

Example

package main

import (
    "fmt"

    "github.com/dahui/z13ctl/api"
)

func main() {
    // Balanced on AC, a custom profile on battery. An empty target leaves that
    // side to the desktop's own power management.
    handled, err := api.SendAutoswitchSet(true, "balanced", "battery-uv")
    if !handled {
        fmt.Println("daemon not running")
        return
    }
    if err != nil {
        fmt.Println("error:", err)
        return
    }
    fmt.Println("autoswitch configured")
}

func SendBatteryLimitGet

func SendBatteryLimitGet() (handled bool, limit int, err error)

SendBatteryLimitGet queries the daemon for the current battery charge limit by reading sysfs (not cached daemon state). Intended for GUI/plugin callers. Returns (false, 0, nil) if the daemon is not running.

Example

package main

import (
    "fmt"

    "github.com/dahui/z13ctl/api"
)

func main() {
    // Read the current battery charge limit.
    handled, limit, err := api.SendBatteryLimitGet()
    if !handled {
        fmt.Println("daemon not running")
        return
    }
    if err != nil {
        fmt.Println("error:", err)
        return
    }
    fmt.Println("battery limit:", limit)
}

func SendBatteryLimitSet

func SendBatteryLimitSet(limit int) (bool, error)

SendBatteryLimitSet sends a battery limit set command to the daemon.

Example

package main

import (
    "fmt"

    "github.com/dahui/z13ctl/api"
)

func main() {
    // Limit battery charge to 80%.
    handled, err := api.SendBatteryLimitSet(80)
    if !handled {
        fmt.Println("daemon not running")
        return
    }
    if err != nil {
        fmt.Println("error:", err)
        return
    }
    fmt.Println("battery limit set")
}

func SendBootSoundGet

func SendBootSoundGet() (handled bool, value int, err error)

SendBootSoundGet queries the daemon for the current boot sound setting by reading sysfs. Returns (false, 0, nil) if the daemon is not running.

Example

package main

import (
    "fmt"

    "github.com/dahui/z13ctl/api"
)

func main() {
    // Read the current boot sound setting.
    handled, value, err := api.SendBootSoundGet()
    if !handled {
        fmt.Println("daemon not running")
        return
    }
    if err != nil {
        fmt.Println("error:", err)
        return
    }
    fmt.Println("boot sound:", value)
}

func SendBootSoundSet

func SendBootSoundSet(value int) (bool, error)

SendBootSoundSet sends a boot sound set command to the daemon.

Example

package main

import (
    "fmt"

    "github.com/dahui/z13ctl/api"
)

func main() {
    // Disable the POST boot sound.
    handled, err := api.SendBootSoundSet(0)
    if !handled {
        fmt.Println("daemon not running")
        return
    }
    if err != nil {
        fmt.Println("error:", err)
        return
    }
    fmt.Println("boot sound set")
}

func SendBrightness

func SendBrightness(device string, level int) (bool, error)

SendBrightness sends a brightness-only command to the daemon. device may be "keyboard", "lightbar", a /dev/hidrawN path, or "" to target all devices.

Example

package main

import (
    "fmt"

    "github.com/dahui/z13ctl/api"
)

func main() {
    // Set brightness to medium on the keyboard only.
    handled, err := api.SendBrightness("keyboard", 2)
    if !handled {
        fmt.Println("daemon not running, falling back to direct HID access")
        return
    }
    if err != nil {
        fmt.Println("error:", err)
        return
    }
    fmt.Println("brightness set")
}

func SendFanCurveGet

func SendFanCurveGet() (handled bool, value string, err error)

SendFanCurveGet queries the daemon for the current fan curve data. Returns JSON value string with both fans' curve and mode.

Example

package main

import (
    "fmt"

    "github.com/dahui/z13ctl/api"
)

func main() {
    // Read the current fan curve for both fans via the daemon.
    handled, value, err := api.SendFanCurveGet()
    if !handled {
        fmt.Println("daemon not running")
        return
    }
    if err != nil {
        fmt.Println("error:", err)
        return
    }
    fmt.Println("fan curve:", value)
}

func SendFanCurveReset

func SendFanCurveReset() (bool, error)

SendFanCurveReset resets both fans to firmware auto mode.

Example

package main

import (
    "fmt"

    "github.com/dahui/z13ctl/api"
)

func main() {
    // Reset both fans to firmware auto mode.
    handled, err := api.SendFanCurveReset()
    if !handled {
        fmt.Println("daemon not running")
        return
    }
    if err != nil {
        fmt.Println("error:", err)
        return
    }
    fmt.Println("fan curves reset")
}

func SendFanCurveResetFor

func SendFanCurveResetFor(profile string) (bool, error)

SendFanCurveResetFor clears the fan curve from the named custom profile. An empty profile means the active one, which also releases both fans to firmware auto mode.

Example

package main

import (
    "fmt"

    "github.com/dahui/z13ctl/api"
)

func main() {
    // Clear the fan curve from a stored profile, so it no longer controls fans.
    handled, err := api.SendFanCurveResetFor("battery-uv")
    if !handled {
        fmt.Println("daemon not running")
        return
    }
    if err != nil {
        fmt.Println("error:", err)
        return
    }
    fmt.Println("fan curve cleared")
}

func SendFanCurveSet

func SendFanCurveSet(curve string) (bool, error)

SendFanCurveSet sends a fan curve set command to the daemon, editing the active custom profile. The curve is applied to both fans simultaneously.

Example

package main

import (
    "fmt"

    "github.com/dahui/z13ctl/api"
)

func main() {
    // Set a custom 8-point fan curve (applied to both fans).
    handled, err := api.SendFanCurveSet("48:2,53:22,57:30,60:43,63:56,65:68,70:89,76:102")
    if !handled {
        fmt.Println("daemon not running")
        return
    }
    if err != nil {
        fmt.Println("error:", err)
        return
    }
    fmt.Println("fan curve set")
}

func SendFanCurveSetFor

func SendFanCurveSetFor(profile, curve string) (bool, error)

SendFanCurveSetFor stores a fan curve in the named custom profile. An empty profile means the active one, in which case the curve is also written to hardware; naming a profile that is not active only records it.

Example

package main

import (
    "fmt"

    "github.com/dahui/z13ctl/api"
)

func main() {
    // An empty profile name edits the active profile and writes hardware, which
    // is exactly what SendFanCurveSet does.
    handled, err := api.SendFanCurveSetFor("battery-uv", "30:40%,40:45%,50:50%,60:60%,70:70%,80:85%,90:100%,100:100%")
    if !handled {
        fmt.Println("daemon not running")
        return
    }
    if err != nil {
        fmt.Println("error:", err)
        return
    }
    fmt.Println("stored in battery-uv")
}

func SendOff

func SendOff(device string) (bool, error)

SendOff sends an off command to the daemon. device may be "keyboard", "lightbar", a /dev/hidrawN path, or "" to target all devices.

Example

package main

import (
    "fmt"

    "github.com/dahui/z13ctl/api"
)

func main() {
    // Turn off lighting on all devices.
    handled, err := api.SendOff("")
    if !handled {
        fmt.Println("daemon not running, falling back to direct HID access")
        return
    }
    if err != nil {
        fmt.Println("error:", err)
        return
    }
    fmt.Println("lights off")
}

func SendPanelOverdriveGet

func SendPanelOverdriveGet() (handled bool, value int, err error)

SendPanelOverdriveGet queries the daemon for the current panel overdrive setting by reading sysfs. Returns (false, 0, nil) if the daemon is not running.

Example

package main

import (
    "fmt"

    "github.com/dahui/z13ctl/api"
)

func main() {
    // Read the current panel overdrive setting.
    handled, value, err := api.SendPanelOverdriveGet()
    if !handled {
        fmt.Println("daemon not running")
        return
    }
    if err != nil {
        fmt.Println("error:", err)
        return
    }
    fmt.Println("panel overdrive:", value)
}

func SendPanelOverdriveSet

func SendPanelOverdriveSet(value int) (bool, error)

SendPanelOverdriveSet sends a panel overdrive set command to the daemon.

Example

package main

import (
    "fmt"

    "github.com/dahui/z13ctl/api"
)

func main() {
    // Enable panel refresh overdrive.
    handled, err := api.SendPanelOverdriveSet(1)
    if !handled {
        fmt.Println("daemon not running")
        return
    }
    if err != nil {
        fmt.Println("error:", err)
        return
    }
    fmt.Println("panel overdrive set")
}

func SendProfileCreate

func SendProfileCreate(name string) (bool, error)

SendProfileCreate creates an empty custom profile. It does not activate it.

Example

package main

import (
    "fmt"

    "github.com/dahui/z13ctl/api"
)

func main() {
    // Create an empty custom profile. It is not activated; add settings with
    // the *For variants, then select it with SendProfileSet.
    handled, err := api.SendProfileCreate("battery-uv")
    if !handled {
        fmt.Println("daemon not running")
        return
    }
    if err != nil {
        fmt.Println("error:", err)
        return
    }
    fmt.Println("profile created")
}

func SendProfileDelete

func SendProfileDelete(name string) (bool, error)

SendProfileDelete removes a saved custom profile. The daemon refuses to delete the active profile or one referenced by autoswitch.

Example

package main

import (
    "fmt"

    "github.com/dahui/z13ctl/api"
)

func main() {
    // The daemon refuses to delete the active profile or one referenced by
    // autoswitch.
    handled, err := api.SendProfileDelete("gaming")
    if !handled {
        fmt.Println("daemon not running")
        return
    }
    if err != nil {
        fmt.Println("error:", err)
        return
    }
    fmt.Println("profile deleted")
}

func SendProfileGet

func SendProfileGet() (handled bool, profile string, err error)

SendProfileGet queries the daemon for the current performance profile by reading sysfs (not cached daemon state). Intended for GUI/plugin callers. Returns (false, "", nil) if the daemon is not running.

Example

package main

import (
    "fmt"

    "github.com/dahui/z13ctl/api"
)

func main() {
    // Read the current performance profile from sysfs via the daemon.
    handled, profile, err := api.SendProfileGet()
    if !handled {
        fmt.Println("daemon not running")
        return
    }
    if err != nil {
        fmt.Println("error:", err)
        return
    }
    fmt.Println("profile:", profile)
}

func SendProfileList

func SendProfileList() (handled bool, value string, err error)

SendProfileList queries the daemon for the saved custom profiles. Returns a JSON array of CustomProfile. Returns (false, "", nil) if the daemon is not running.

Example

package main

import (
    "encoding/json"
    "fmt"

    "github.com/dahui/z13ctl/api"
)

func main() {
    handled, value, err := api.SendProfileList()
    if !handled {
        fmt.Println("daemon not running")
        return
    }
    if err != nil {
        fmt.Println("error:", err)
        return
    }
    var profiles []struct {
        api.CustomProfile
        Active bool `json:"active"`
    }
    if err := json.Unmarshal([]byte(value), &profiles); err != nil {
        fmt.Println("error:", err)
        return
    }
    for _, p := range profiles {
        fmt.Println(p.Name, p.Active)
    }
}

func SendProfileSave

func SendProfileSave(name string) (bool, error)

SendProfileSave copies the active custom profile under a new name. It does not activate the copy.

Example

package main

import (
    "fmt"

    "github.com/dahui/z13ctl/api"
)

func main() {
    // Copy the profile currently in force under a new name, leaving the
    // original active.
    handled, err := api.SendProfileSave("gaming")
    if !handled {
        fmt.Println("daemon not running")
        return
    }
    if err != nil {
        fmt.Println("error:", err)
        return
    }
    fmt.Println("profile copied")
}

func SendProfileSet

func SendProfileSet(profile string) (bool, error)

SendProfileSet sends a profile set command to the daemon.

Example

package main

import (
    "fmt"

    "github.com/dahui/z13ctl/api"
)

func main() {
    // Switch to the performance power profile.
    handled, err := api.SendProfileSet("performance")
    if !handled {
        fmt.Println("daemon not running")
        return
    }
    if err != nil {
        fmt.Println("error:", err)
        return
    }
    fmt.Println("profile set")
}

func SendTdpGet

func SendTdpGet() (handled bool, value string, err error)

SendTdpGet queries the daemon for current TDP/PPT values. Returns JSON value string.

Example

package main

import (
    "fmt"

    "github.com/dahui/z13ctl/api"
)

func main() {
    // Read current TDP/PPT values via the daemon.
    handled, value, err := api.SendTdpGet()
    if !handled {
        fmt.Println("daemon not running")
        return
    }
    if err != nil {
        fmt.Println("error:", err)
        return
    }
    fmt.Println("tdp:", value)
}

func SendTdpReset

func SendTdpReset() (bool, error)

SendTdpReset sends a TDP reset command to the daemon.

Example

package main

import (
    "fmt"

    "github.com/dahui/z13ctl/api"
)

func main() {
    // Reset to balanced profile, restoring its stock PPT and auto fan curves.
    handled, err := api.SendTdpReset()
    if !handled {
        fmt.Println("daemon not running")
        return
    }
    if err != nil {
        fmt.Println("error:", err)
        return
    }
    fmt.Println("tdp reset")
}

func SendTdpResetFor

func SendTdpResetFor(profile string) (bool, error)

SendTdpResetFor clears the TDP limits from the named custom profile. An empty profile means the active one, which also restores stock power limits.

Example

package main

import (
    "fmt"

    "github.com/dahui/z13ctl/api"
)

func main() {
    handled, err := api.SendTdpResetFor("battery-uv")
    if !handled {
        fmt.Println("daemon not running")
        return
    }
    if err != nil {
        fmt.Println("error:", err)
        return
    }
    fmt.Println("power limits cleared")
}

func SendTdpSet

func SendTdpSet(watts, pl1, pl2, pl3 string, force bool) (bool, error)

SendTdpSet sends a TDP set command to the daemon, editing the active custom profile.

Example

package main

import (
    "fmt"

    "github.com/dahui/z13ctl/api"
)

func main() {
    // Set TDP to 50W (all PPT values equal).
    handled, err := api.SendTdpSet("50", "", "", "", false)
    if !handled {
        fmt.Println("daemon not running")
        return
    }
    if err != nil {
        fmt.Println("error:", err)
        return
    }
    fmt.Println("tdp set")
}

func SendTdpSetFor

func SendTdpSetFor(profile, watts, pl1, pl2, pl3 string, force bool) (bool, error)

SendTdpSetFor stores TDP limits in the named custom profile. An empty profile means the active one, in which case the limits are also written to hardware; naming a profile that is not active only records them.

Example

package main

import (
    "fmt"

    "github.com/dahui/z13ctl/api"
)

func main() {
    // Store a 35W limit in a profile that is not running. Nothing is applied to
    // hardware, which is what makes it possible to build the profile autoswitch
    // selects on battery while still plugged in.
    handled, err := api.SendTdpSetFor("battery-uv", "35", "", "", "", false)
    if !handled {
        fmt.Println("daemon not running")
        return
    }
    if err != nil {
        fmt.Println("error:", err)
        return
    }
    fmt.Println("stored in battery-uv")
}

func SendUndervoltGet

func SendUndervoltGet() (handled bool, value string, err error)

SendUndervoltGet queries the daemon for the current Curve Optimizer offsets. Returns JSON value string. Returns (false, "", nil) if the daemon is not running.

Example

package main

import (
    "fmt"

    "github.com/dahui/z13ctl/api"
)

func main() {
    // Read current Curve Optimizer offsets from daemon state.
    handled, value, err := api.SendUndervoltGet()
    if !handled {
        fmt.Println("daemon not running")
        return
    }
    if err != nil {
        fmt.Println("error:", err)
        return
    }
    fmt.Println("undervolt:", value)
}

func SendUndervoltReset

func SendUndervoltReset() (bool, error)

SendUndervoltReset resets Curve Optimizer to stock (0).

Example

package main

import (
    "fmt"

    "github.com/dahui/z13ctl/api"
)

func main() {
    // Reset Curve Optimizer to stock (0).
    handled, err := api.SendUndervoltReset()
    if !handled {
        fmt.Println("daemon not running")
        return
    }
    if err != nil {
        fmt.Println("error:", err)
        return
    }
    fmt.Println("undervolt reset")
}

func SendUndervoltResetFor

func SendUndervoltResetFor(profile string) (bool, error)

SendUndervoltResetFor clears the Curve Optimizer offset from the named custom profile. An empty profile means the active one, which also resets hardware.

Example

package main

import (
    "fmt"

    "github.com/dahui/z13ctl/api"
)

func main() {
    handled, err := api.SendUndervoltResetFor("battery-uv")
    if !handled {
        fmt.Println("daemon not running")
        return
    }
    if err != nil {
        fmt.Println("error:", err)
        return
    }
    fmt.Println("undervolt cleared")
}

func SendUndervoltSet

func SendUndervoltSet(cpu string) (bool, error)

SendUndervoltSet sends a Curve Optimizer set command to the daemon, editing the active custom profile. cpu is a string representation of the CO offset (e.g. "-20").

Example

package main

import (
    "fmt"

    "github.com/dahui/z13ctl/api"
)

func main() {
    // Set CPU Curve Optimizer to -20.
    handled, err := api.SendUndervoltSet("-20")
    if !handled {
        fmt.Println("daemon not running")
        return
    }
    if err != nil {
        fmt.Println("error:", err)
        return
    }
    fmt.Println("undervolt set")
}

func SendUndervoltSetFor

func SendUndervoltSetFor(profile, cpu string) (bool, error)

SendUndervoltSetFor stores a Curve Optimizer offset in the named custom profile. An empty profile means the active one, in which case the offset is also applied to hardware; naming a profile that is not active only records it.

Example

package main

import (
    "fmt"

    "github.com/dahui/z13ctl/api"
)

func main() {
    handled, err := api.SendUndervoltSetFor("battery-uv", "-25")
    if !handled {
        fmt.Println("daemon not running")
        return
    }
    if err != nil {
        fmt.Println("error:", err)
        return
    }
    fmt.Println("stored in battery-uv")
}

func SocketPath

func SocketPath() string

SocketPath returns the runtime path for the daemon's Unix socket.

func Subscribe

func Subscribe(events []string) (eventCh <-chan string, cancel func(), err error)

Subscribe opens a long-lived subscription to the daemon and returns a channel that receives event name strings as they are streamed. Pass the events you want — EventGUIToggle, EventPowerSource, EventStateChanged — or nil for all of them. The daemon honours the list, so a client that asks only for EventGUIToggle will not be woken by anything else.

Events carry no payload by design: the name says what happened, and SendGetState answers with current truth. Switch on the name rather than treating every event alike —

for ev := range ch {
    switch ev {
    case api.EventGUIToggle:
        toggleWindow()
    case api.EventPowerSource, api.EventStateChanged:
        refreshFromGetState()
    }
}

The returned cancel func closes the underlying connection and stops the goroutine; the channel is closed when the connection drops or cancel is called. Returns (nil, nil, nil) if the daemon is not running.

Example

package main

import (
    "fmt"

    "github.com/dahui/z13ctl/api"
)

func main() {
    // Subscribe to Armoury Crate button press events.
    ch, cancel, err := api.Subscribe([]string{"gui-toggle"})
    if ch == nil {
        fmt.Println("daemon not running")
        return
    }
    if err != nil {
        fmt.Println("error:", err)
        return
    }
    defer cancel()
    for event := range ch {
        fmt.Println("received event:", event)
    }
}

type AutoswitchState

AutoswitchState configures automatic profile selection by power source. An empty AC or Battery target means "leave the profile alone on that source", which is how a caller hands one side back to power-profiles-daemon.

type AutoswitchState struct {
    Enabled bool   `json:"enabled"`
    AC      string `json:"ac,omitempty"`
    Battery string `json:"battery,omitempty"`
}

func (*AutoswitchState) Target

func (a *AutoswitchState) Target(onAC bool) string

Target returns the profile to apply for the given power source, or "" when autoswitch is disabled or that side is unconfigured.

type CustomProfile

CustomProfile is a named set of custom hardware settings. Each subsystem is a pointer so that nil means "this profile does not control that subsystem", which is what lets a profile stay loadable as new subsystems are added.

type CustomProfile struct {
    Name      string          `json:"name"`
    FanCurve  *FanCurveState  `json:"fan_curve,omitempty"`
    TDP       *TDPState       `json:"tdp,omitempty"`
    Undervolt *UndervoltState `json:"undervolt,omitempty"`
}

func (CustomProfile) Empty

func (p CustomProfile) Empty() bool

Empty reports whether the profile controls no subsystem at all. An empty profile cannot be activated: there would be nothing to apply.

type FanCurvePoint

FanCurvePoint represents one point on an 8-point fan curve.

type FanCurvePoint struct {
    Temp int `json:"temp"` // degrees Celsius
    PWM  int `json:"pwm"`  // 0–255 duty cycle
}

type FanCurveState

FanCurveState captures the fan curve and mode applied to both fans.

type FanCurveState struct {
    Mode   int             `json:"mode"`   // pwm_enable: 0=full-speed, 1=custom, 2=auto
    Points []FanCurvePoint `json:"points"` // 8 points
}

type LightingState

LightingState captures all parameters needed to reproduce one lighting zone.

type LightingState struct {
    Enabled    bool   `json:"enabled"`
    Mode       string `json:"mode"`
    Color      string `json:"color"`  // "RRGGBB" hex
    Color2     string `json:"color2"` // "RRGGBB" hex
    Speed      string `json:"speed"`
    Brightness int    `json:"brightness"` // 0–3
}

type State

State holds the last-applied settings for all controllable subsystems. It is returned by SendGetState and broadcast as part of daemon responses.

CustomProfiles is the source of truth for custom settings. FanCurve, TDP and Undervolt are a projection, retained so clients written against earlier versions keep working: they carry the active custom profile's settings, or the default "custom" profile's when a firmware profile is active — the same values selecting "custom" would recall. Undervolt.Active is what says whether an offset is applied to hardware right now; the values themselves survive a switch to a firmware profile so they can be recalled.

type State struct {
    Lighting           LightingState            `json:"lighting"`
    Devices            map[string]LightingState `json:"devices,omitempty"` // per-device overrides keyed by name
    Profile            string                   `json:"profile,omitempty"`
    Battery            int                      `json:"battery_limit,omitempty"`
    BootSound          int                      `json:"boot_sound,omitempty"`
    PanelOverdrive     int                      `json:"panel_overdrive,omitempty"`
    CustomProfiles     map[string]CustomProfile `json:"custom_profiles,omitempty"` // saved custom profiles keyed by name
    Autoswitch         *AutoswitchState         `json:"autoswitch,omitempty"`
    FanCurve           *FanCurveState           `json:"fan_curve,omitempty"`   // projection; see the type doc
    TDP                *TDPState                `json:"tdp,omitempty"`         // projection; see the type doc
    Undervolt          *UndervoltState          `json:"undervolt,omitempty"`   // projection; see the type doc
    UndervoltAvailable bool                     `json:"undervolt_available"`   // true if ryzen_smu is loaded
    OnAC               bool                     `json:"on_ac"`                 // true when running on mains power
    Temperature        int                      `json:"temperature,omitempty"` // APU temp, degrees Celsius
    FanRPM             int                      `json:"fan_rpm,omitempty"`     // fan1 speed in RPM
}

func SendGetState

func SendGetState() (bool, *State, error)

SendGetState fetches the daemon's full cached state for GUI initialization. Returns (false, nil, nil) if the daemon is not running.

Example

package main

import (
    "fmt"

    "github.com/dahui/z13ctl/api"
)

func main() {
    // Fetch the daemon's full cached state for GUI initialization.
    handled, state, err := api.SendGetState()
    if !handled {
        fmt.Println("daemon not running")
        return
    }
    if err != nil {
        fmt.Println("error:", err)
        return
    }
    fmt.Println("mode:", state.Lighting.Mode)
}

func (State) ActiveCustomProfile

func (s State) ActiveCustomProfile() (CustomProfile, bool)

ActiveCustomProfile returns the active custom profile and true, or the zero value and false when a stock profile is active.

func (State) InCustomProfile

func (s State) InCustomProfile() bool

InCustomProfile reports whether the active profile is a custom one.

func (State) IsCustomProfile

func (s State) IsCustomProfile(name string) bool

IsCustomProfile reports whether name identifies a z13ctl-managed custom profile: the default "custom" profile, or a saved named one.

Clients that check Profile == "custom" to decide whether custom controls apply must move to this — a named profile would otherwise read as stock.

A reserved firmware profile name is never custom, whatever the map contains. The check is deliberately ahead of the lookup so that a hand-edited state file cannot make a stock profile look custom to the fan curve reconciler.

type TDPState

TDPState captures all PPT (Package Power Tracking) values in watts.

type TDPState struct {
    PL1SPL       int `json:"pl1_spl"`       // Sustained Power Limit
    PL2SPPT      int `json:"pl2_sppt"`      // Short Boost
    FPPT         int `json:"fppt"`          // Fast Boost
    APUSPPT      int `json:"apu_sppt"`      // APU Short PPT
    PlatformSPPT int `json:"platform_sppt"` // Platform Short PPT
}

type UndervoltState

UndervoltState captures the AMD Curve Optimizer offset applied to the CPU. Values are non-positive integers (0 = stock, negative = undervolt). Active indicates whether the offset is currently applied to hardware.

type UndervoltState struct {
    CPUCO  int  `json:"cpu_co"` // all-core CPU Curve Optimizer offset
    Active bool `json:"active"` // true when CO is applied to hardware
}

Generated by gomarkdoc