kasa

package module
v0.0.0-...-034aad4 Latest Latest
Warning

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

Go to latest
Published: Apr 16, 2024 License: BSD-2-Clause Imports: 8 Imported by: 1

README

LICENSE GoReportCard GoDoc

go-kasa

Go library to control TP-Link Kasa devices. This library uses the local API, not the cloud API. It uses UDP rather than TCP where possible for better performance.

Includes a small cli tool

This is still a work-in-progress, but works for most operations.

CLI install

Make sure you have Go version 1.18 or newer installed on your system. See The Go install instructions for details.

In your shell (terminal on macOS, PowerShell on Windows, lots of options on Linux and UNIX systems...) go install github.com/cloudkucooland/go-kasa/cmd/kasa@latest

This will place the kasa binary in ~/go/bin/kasa Make sure ~/go/bin is in your shell's path

If you need to control your Kasa devices from Apple HomeKit, I have built a bridge which works well.

https://github.com/cloudkucooland/HomeKitBrigdges/

CLI examples

discover devices on the local subnets

% kasa discover
read udp [::]:48781: i/o timeout
found 25 devices
  192.168.1.144: HS220(US)             Fireplace Can Dimmer [state: 0] [brightness:  25]
  192.168.1.145: HS200(US)           Dining Room Chandelier [state: 0] [brightness:   0]
  192.168.1.161: HS200(US)            Back Porch Floodlight [state: 1] [brightness:   0]
  192.168.1.162: HS200(US)                   Breakfast Nook [state: 0] [brightness:   0]
  192.168.1.163: HS220(US)        Master Bath Shower Lights [state: 0] [brightness:  50]
  192.168.1.164: HS220(US)           Master Bath Can Lights [state: 0] [brightness:  50]
  192.168.1.165: HS200(US)              Master Bath Mirrors [state: 0] [brightness:   0]
  192.168.1.166: HS200(US)               Front Door Pendant [state: 0] [brightness:   0]
  192.168.1.167: HS200(US)                       Front Room [state: 0] [brightness:   0]
  192.168.1.170: HS210(US)                  Front Hallway 1 [state: 0] [brightness:   0]
  192.168.1.171: HS210(US)                  Front Hallway 2 [state: 0] [brightness:   0]
  192.168.1.172: HS220(US)             Master Bedroom Light [state: 0] [brightness:  40]
  192.168.1.175: HS200(US)               Laundry Room Light [state: 1] [brightness:   0]
  192.168.1.176: HS200(US)       Laundry Room Extractor Fan [state: 0] [brightness:   0]
  192.168.1.177: HS200(US)               Hallway Side Light [state: 1] [brightness:   0]
  192.168.1.178: HS200(US)      Living Room Overhead Lights [state: 0] [brightness:   0]
  192.168.1.179: HS200(US)                  Living Room Fan [state: 0] [brightness:   0]
  192.168.1.180: HS200(US)               Kitchen Sink Light [state: 0] [brightness:   0]
  192.168.1.183: KP303(US) TP-LINK_Power Strip_2BAB
    ID: 8006D442E080440F22A89B072F2E67FB1D9B3DFE02               Guppie Light [state: 0]
    ID: 8006D442E080440F22A89B072F2E67FB1D9B3DFE01              Guppie Heater [state: 1]
    ID: 8006D442E080440F22A89B072F2E67FB1D9B3DFE00              Guppie Filter [state: 1]
  192.168.1.184: KP303(US) TP-LINK_Power Strip_2C77
    ID: 8006972A91D031658289D308866206E11D9B838A02               Edgar Heater [state: 1]
    ID: 8006972A91D031658289D308866206E11D9B838A01              Edgar Bubbler [state: 1]
    ID: 8006972A91D031658289D308866206E11D9B838A00               Edgar Filter [state: 1]
  192.168.1.185: KP303(US) TP-LINK_Power Strip_34EC
    ID: 800661DA15771003D2531C57BE527BA61D9B40E400               Gofish Light [state: 0]
    ID: 800661DA15771003D2531C57BE527BA61D9B40E401              Gofish Heater [state: 1]
    ID: 800661DA15771003D2531C57BE527BA61D9B40E402              Gofish Filter [state: 1]
  192.168.1.187: HS103(US)                Living Room Spare [state: 0] [brightness:   0]
  192.168.1.188: HS103(US)                Scot Bedside Lamp [state: 0] [brightness:   0]
  192.168.1.189: HS103(US)                 Jen Bedside Lamp [state: 0] [brightness:   0]
  192.168.1.193: HS103(US)              Scot’s Office Spare [state: 0] [brightness:   0]

disable the cloud service for all devices on the local subnets

% kasa nocloud 255.255.255.255

toggle one switch

% kasa switch 192.168.1.171 false

adjust the brightness on a dimmer switch

% kasa brightness 192.168.1.164 100

show dimmer status and timeings for all dimmer-enabled devices (this needs to be prettier...)

% kasa getalldimmer
read udp [::]:58322: i/o timeout
192.168.1.172: &{MinThreshold:0 FadeOnTime:2000 FadeOffTime:2000 GentleOnTime:3000 GentleOffTime:10000 RampRate:30 BulbType:1 ErrCode:0 ErrMsg:}
192.168.1.163: &{MinThreshold:1 FadeOnTime:1000 FadeOffTime:2000 GentleOnTime:3000 GentleOffTime:60000 RampRate:30 BulbType:1 ErrCode:0 ErrMsg:}
192.168.1.144: &{MinThreshold:9 FadeOnTime:1000 FadeOffTime:1000 GentleOnTime:3000 GentleOffTime:10000 RampRate:30 BulbType:0 ErrCode:0 ErrMsg:}
192.168.1.164: &{MinThreshold:0 FadeOnTime:1000 FadeOffTime:2000 GentleOnTime:3000 GentleOffTime:30000 RampRate:30 BulbType:1 ErrCode:0 ErrMsg:}

details about a single device

% kasa info 192.168.1.144
Alias:		Fireplace Can Dimmer
DevName:	Wi-Fi Smart Dimmer
Model:		HS220(US) [2.0]
Device ID:	xxx
OEM ID:		xxx
Hardware ID:	xxx
Software:	1.0.5 Build 201211 Rel.085320
MIC:		IOT.SMARTPLUGSWITCH
MAC:		60:32:B1:00:00:00
LED Off:	0
Active Mode:	none
Relay:	0	Brightness:	25%

Get real-time usage

% kasa emeter 192.168.1.203
CurrentMA:	1807
VoltageMV:	122209
PowerMW:	175494
TotalWH:	2097

Get daily stats for a month (Feb 2021)

% kasa emeter 192.168.1.203 02 2021
2021-02-06 Total WH:	842
2021-02-07 Total WH:	1257

Get Countdown Rules (needs to be prettier)

% kasa countdown 192.168.1.206
{ID:8725326BB2D0C0DD8D521379163C7D67 Name:TooFar Enable:0 Delay:0 Active:1 Remaining:0}

Clear Countdown rules

% kasa countdown 192.168.1.206 delete

Documentation

Index

Constants

View Source
const (
	CmdSetRelayState = `{"system":{"set_relay_state":{"state":%d}}}` // 0 or 1
	CmdGetSysinfo    = `{"system":{"get_sysinfo":{}}}`
	CmdReboot        = `{"system":{"reboot":{"delay":2}}}`
	CmdLEDOff        = `{"system":{"set_led_off":{"off":%d}}}` // off = 1, on = 0
	CmdDeviceAlias   = `{"system":{"set_dev_alias":{"alias":"%s"}}}`
	CmdSetMode       = `{"system":{"set_mode":{"mode":"%s"}}}` // "none", "count_down", ???

	CmdGetEmeter           = `{"emeter":{"get_realtime":{}}}`
	CmdGetEmeterGetDaystat = `{"emeter":{"get_daystat":{"month":%d,"year":%d}}}`
	CmdGetEmeterVgain      = `{"emeter":{"get_vgain_igain":{}}}`
	CmdSetEmeterVgain      = `{"emeter":{"set_vgain_igain":{"vgain":%d,"igain":%d}}}`       // int, int
	CmdEmeterCalibration   = `{"emeter":{"start_calibration":{"vtarget":%d,"itarget":%d}}}` // int, int
	CmdEmeterGetMonth      = `{"emeter":{"get_daystat":{"month":%d,"year":%d}}}`            // 1-12, 4-digit-year
	CmdEmeterGetYear       = `{"emeter":{"get_monthstat":{"year":%d}}}`                     // 4-digit-year
	CmdEmeterErase         = `{"emeter":{"erase_emeter_stat":null}}`

	CmdGetEmeterChild = `{"context":{"child_ids":["%s"]},"emeter":{"get_realtime":{}}}`

	CmdWifiStainfo = `{"netif":{"get_stainfo":{}}}`

	CmdSetRelayStateChild      = `{"context":{"child_ids":["%s"]},"system":{"set_relay_state":{"state":%d}}}` // index (e.g. ".....00"), 0/1
	CmdSetRelayStateChildMulti = `{"context":{"child_ids":[%s]},"system":{"set_relay_state":{"state":%d}}}`   // indexes (e.g. `"....00","....03"`), 0/1
	CmdChildAlias              = `{"context":{"child_ids":["%s"]},"system":{"set_dev_alias":{"alias":"%s"}}}` // index (e.g. "....01"), name

	CmdGetDimmer        = `{"smartlife.iot.dimmer":{"get_dimmer_parameters":{}}}`
	CmdSetBrightness    = `{"smartlife.iot.dimmer":{"set_brightness":{"brightness":%d}}}`    // 0-100
	CmdSetFadeOffTime   = `{"smartlife.iot.dimmer":{"set_fade_off_time":{"fadeTime":%d}}}`   // ms
	CmdSetFadeOnTime    = `{"smartlife.iot.dimmer":{"set_fade_on_time":{"fadeTime":%d}}}`    // ms
	CmdSetGentleOffTime = `{"smartlife.iot.dimmer":{"set_gentle_off_time":{"fadeTime":%d}}}` // ms
	CmdSetGentleOnTime  = `{"smartlife.iot.dimmer":{"set_gentle_on_time":{"fadeTime":%d}}}`  // ms

	CmdGetRules = `{"smartlife.iot.common.schedule":{"get_rules":{}}}`

	CmdGetCountdownRules = `{"count_down":{"get_rules":{}}}`
	CmdDeleteAllRules    = `{"count_down":{"delete_all_rules":{}}}`
	CmdAddCountdownRule  = `{"count_down":{"add_rule":{"enable":1,"delay":%d,"act":%d,"name":"%s"}}}` // 0-3600, 0/1, string

	CmdCloudUnbind    = `{"cnCloud":{"unbind":null}}`
	CmdSetServerURL   = `{"cnCloud":{"set_server_url":{"server":"%s"}}}`          // bare hostname, no protocol spec
	CmdSetServerCreds = `{"cnCloud":{"bind":{"username":"%s", "password":"%s"}}}` // alice@home.com / mikeisagoat
)

Request strings

Variables

This section is empty.

Functions

func BroadcastAddresses

func BroadcastAddresses() ([]net.IP, error)

BroadcastAddresses - probably belongs in its own library, get all broadcast addresses

func BroadcastDimmerParameters

func BroadcastDimmerParameters(timeout, probes int) (map[string]*DimmerParameters, error)

BroadcastDimmerParameters queries all devices on all attached subnets for dimmer state

func BroadcastDiscovery

func BroadcastDiscovery(timeout, probes int) (map[string]*Sysinfo, error)

BroadcastDiscovery pulls every attached subnet for kasa devices and returns whatever is discovered

func BroadcastEmeter

func BroadcastEmeter(timeout, probes int) (map[string]KasaDevice, error)

BroadcastEmeter pulls all devices on all attached subnets for emeter data

func BroadcastWifiParameters

func BroadcastWifiParameters(timeout, probes int) (map[string]*StaInfo, error)

BroadcastWifiParameters polls all devices on all attached subnets for wifi status. This is handy when you have one device that never wants to respond, seeing how its wifi status changes over time

func Scramble

func Scramble(plaintext string) []byte

Scramble is simpler. UDP doesn't require the length header, just allocates and write to a slice.

func ScrambleTCP

func ScrambleTCP(plaintext string) []byte

ScrambleTCP is for TCP, It writes the length in the first byte. It uses a binary buffer and writer.

func SetLogger

func SetLogger(l kasalogger)

SetLogger allows applications to register their own logging interface

func Unscramble

func Unscramble(ciphertext []byte) []byte

Unscramble turns the response from the Kasa into parsable JSON it works in place -- be careful with your buffers

Types

type AddRule

type AddRule struct {
	ID           string `json:"id"`
	ErrorCode    int8   `json:"err_code"`
	ErrorMessage string `json:"err_msg"`
}

AddRule is defined by kasa devices

type Child

type Child struct {
	ID         string `json:"id"`
	RelayState uint8  `json:"state"`
	Alias      string `json:"alias"`
	OnTime     int    `json:"on_time"`
}

Child is defined by kasa devices

type Countdown

type Countdown struct {
	GetRules GetRules `json:"get_rules"`
	DelRules DelRules `json:"delete_all_rules"`
	AddRule  AddRule  `json:"add_rule"`
}

Countdown is defined by kasa devices

type DelRules

type DelRules struct {
	ErrorCode    int8   `json:"err_code"`
	ErrorMessage string `json:"err_msg"`
}

DelRules is defined by kasa devices

type Device

type Device struct {
	IP string

	Port  int
	Debug bool
	// contains filtered or unexported fields
}

Device is the primary type, commands are called from the device

func NewDevice

func NewDevice(ip string) (*Device, error)

NewDevice sets up a new Kasa device for polling

func (*Device) AddCountdownRule

func (d *Device) AddCountdownRule(dur int, target bool, name string) error

AddCountdownRule adds a new countdown

func (*Device) ClearCountdownRules

func (d *Device) ClearCountdownRules() error

ClearCountdownRules resets all countdown rules on the device

func (*Device) DisableCloud

func (d *Device) DisableCloud() error

DisableCloud sets the device to "local only" mode. TODO: forget any cloud settings

func (*Device) EnableCloud

func (d *Device) EnableCloud(username, password string) error

Enable/Configure Cloud

func (*Device) GetCountdownRules

func (d *Device) GetCountdownRules() (*[]Rule, error)

GetCountdownRules returns a list of the countdown timers on a device

func (*Device) GetDimmerParameters

func (d *Device) GetDimmerParameters() (*DimmerParameters, error)

GetDimmerParameters returns the dimmer parameters from dimmer-capable devices

func (*Device) GetEmeter

func (d *Device) GetEmeter() (*EmeterRealtime, error)

GetEmeter returns emeter data from the device

func (*Device) GetEmeterChild

func (d *Device) GetEmeterChild(child string) (*EmeterRealtime, error)

GetEmeter returns emeter data from the device

func (*Device) GetEmeterMonth

func (d *Device) GetEmeterMonth(month, year int) (*EmeterDaystat, error)

GetEmeterMonth returns a single month's emeter data from the device

func (*Device) GetRules

func (d *Device) GetRules() (string, error)

GetRules returns the rule information from a device

func (*Device) GetSettings

func (d *Device) GetSettings() (*Sysinfo, error)

GetSettings gets the device sys info

func (*Device) GetWIFIStatus

func (d *Device) GetWIFIStatus() (*StaInfo, error)

GetWIFIStatus returns the WiFi station info

func (*Device) Reboot

func (d *Device) Reboot() error

Reboot instructs the device to reboot

func (*Device) SendRawCommand

func (d *Device) SendRawCommand(cmd string) error

func (*Device) SetAlias

func (d *Device) SetAlias(s string) error

SetAlias sets a device name

func (*Device) SetBrightness

func (d *Device) SetBrightness(newval int) error

SetBrightness adjust the brightness setting on a dimmer-capable device (1-100)

func (*Device) SetChildAlias

func (d *Device) SetChildAlias(childID, s string) error

SetChildAlias sets the name of an individual relay on a multi-relay device, I don't think this works

func (*Device) SetFadeOffTime

func (d *Device) SetFadeOffTime(newval int) error

func (*Device) SetFadeOnTime

func (d *Device) SetFadeOnTime(newval int) error

func (*Device) SetGentleOffTime

func (d *Device) SetGentleOffTime(newval int) error

func (*Device) SetGentleOnTime

func (d *Device) SetGentleOnTime(newval int) error

func (*Device) SetLEDOff

func (d *Device) SetLEDOff(t bool) error

SetLEDOff is insanely named... it should be SetLED, but I'm just going with what TP-Link called these things internally...

func (*Device) SetMode

func (d *Device) SetMode(m string) error

SetMode sets the target mode of the system

func (*Device) SetRelayState

func (d *Device) SetRelayState(newstate bool) error

SetRelayState changes the relay state of the device -- for multi-relay devices use SetRelayStateChild

func (*Device) SetRelayStateChild

func (d *Device) SetRelayStateChild(childID string, newstate bool) error

SetRelayStateChild adjusts a single relay on a multi-relay device

func (*Device) SetRelayStateChildMulti

func (d *Device) SetRelayStateChildMulti(newstate bool, children ...string) error

SetRelayStateChildMulti adjusts multiple relays on a multi-relay device

type Dimmer

type Dimmer struct {
	Parameters DimmerParameters `json:"get_dimmer_parameters"`
	ErrCode    int8             `json:"err_code"`
	ErrMsg     string           `json:"err_msg"`
}

Dimmer is defined by kasa devices

type DimmerParameters

type DimmerParameters struct {
	MinThreshold  uint16 `json:"minThreshold"`
	FadeOnTime    uint16 `json:"fadeOnTime"`
	FadeOffTime   uint16 `json:"fadeOffTime"`
	GentleOnTime  uint16 `json:"gentleOnTime"`
	GentleOffTime uint16 `json:"gentleOffTime"`
	RampRate      uint16 `json:"rampRate"`
	BulbType      uint8  `json:"bulb_type"`
	ErrCode       int8   `json:"err_code"`
	ErrMsg        string `json:"err_msg"`
}

DimmerParameters is defined by kasa devices

type EmeterDay

type EmeterDay struct {
	Year  uint16 `json:"year"`
	Month uint8  `json:"month"`
	Day   uint8  `json:"day"`
	WH    uint16 `json:"energy_wh"`
}

EmeterDay is defined by kasa devices

type EmeterDaystat

type EmeterDaystat struct {
	List    []EmeterDay `json:"day_list"`
	ErrCode int8        `json:"err_code"`
	ErrMsg  string      `json:"err_msg"`
}

EmeterDaystat is defined by kasa devices

type EmeterRealtime

type EmeterRealtime struct {
	Slot      uint8  `json:"slot_id"`
	CurrentMA uint   `json:"current_ma"`
	VoltageMV uint   `json:"voltage_mv"`
	PowerMW   uint   `json:"power_mw"`
	TotalWH   uint   `json:"total_wh"`
	ErrCode   int8   `json:"err_code"`
	ErrMsg    string `json:"err_msg"`
}

EmeterRealtime is defined by kasa devices

type EmeterSub

type EmeterSub struct {
	Realtime EmeterRealtime `json:"get_realtime"`
	DayStat  EmeterDaystat  `json:"get_daystat"`
	ErrCode  int8           `json:"err_code"`
	ErrMsg   string         `json:"err_msg"`
}

EmeterSub is defined by kasa devices

type GetRules

type GetRules struct {
	RuleList     []Rule `json:"rule_list"`
	ErrorCode    int8   `json:"err_code"`
	ErrorMessage string `json:"err_msg"`
}

GetRules is defined by kasa devices

type GetSysinfo

type GetSysinfo struct {
	Sysinfo Sysinfo `json:"get_sysinfo"`
}

GetSysinfo is defined by kasa devices

type KasaDevice

type KasaDevice struct {
	GetSysinfo GetSysinfo `json:"system"`
	Dimmer     Dimmer     `json:"smartlife.iot.dimmer"`
	NetIf      NetIf      `json:"netif"`
	Countdown  Countdown  `json:"count_down"`
	Emeter     EmeterSub  `json:"emeter"`
}

KasaDevice is the primary type, defined by kasa devices

type NetIf

type NetIf struct {
	StaInfo StaInfo `json:"get_stainfo"`
	ErrCode int8    `json:"err_code"`
	ErrMsg  string  `json:"err_msg"`
}

NetIf is defined by kasa devices {"netif":{"get_stainfo":{"ssid":"IoT8417","key_type":3,"rssi":-61,"err_code":0}}}

type Preset

type Preset struct {
	Index      uint8 `json:"index"`
	Brightness uint8 `json:"brightness"`
}

Preset is defined by kasa devices

type Rule

type Rule struct {
	ID        string `json:"id"`
	Name      string `json:"name"`
	Enable    uint8  `json:"enable"`
	Delay     uint16 `json:"delay"`
	Active    uint8  `json:"act"`
	Remaining uint16 `json:"remain"`
}

Rule is defined by kasa devices

type StaInfo

type StaInfo struct {
	SSID    string `json:"ssid"`
	KeyType int8   `json:"key_type"`
	RSSI    int8   `json:"rssi"`
	ErrCode int8   `json:"err_code"`
	ErrMsg  string `json:"err_msg"`
}

StaInfo is defined by kasa devices

type Sysinfo

type Sysinfo struct {
	SWVersion      string   `json:"sw_ver"`
	HWVersion      string   `json:"hw_ver"`
	Model          string   `json:"model"`
	DeviceID       string   `json:"deviceId"`
	OEMID          string   `json:"oemId"`
	HWID           string   `json:"hwId"`
	RSSI           int8     `json:"rssi"`
	Longitude      int      `json:"longitude_i"`
	Latitude       int      `json:"latitude_i"`
	Alias          string   `json:"alias"`
	Status         string   `json:"status"`
	MIC            string   `json:"mic_type"`
	Feature        string   `json:"feature"`
	MAC            string   `json:"mac"`
	Updating       uint8    `json""updating"`
	LEDOff         uint8    `json:"led_off"`
	RelayState     uint8    `json:"relay_state"`
	Brightness     uint8    `json:"brightness"`
	OnTime         int      `json:"on_time"`
	ActiveMode     string   `json:"active_mode"`
	DevName        string   `json:"dev_name"`
	Children       []Child  `json:"children"`
	NumChildren    uint8    `json:"child_num"`
	NTCState       int      `json:"ntc_state"`
	PreferredState []Preset `json:"preferred_state"`
	ErrCode        int8     `json:"error_code"`
}

Sysinfo is defined by kasa devices

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

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