Skip to content

scttfrdmn/kasa

Repository files navigation

kasa

A Go library for controlling TP-Link Kasa smart home devices using the local protocol.

Features

  • Local Control: Communicates directly with devices on your network (no cloud required)
  • Device Discovery: Automatic UDP broadcast discovery
  • Full HS300 Support: Per-plug power monitoring for power strips
  • Energy Monitoring: Read voltage, current, power consumption, and total energy
  • Device Management: Control and monitor multiple devices simultaneously
  • Clean API: Well-structured, idiomatic Go interfaces

Supported Devices

  • HS300 - 6-outlet power strip with per-plug power monitoring
  • KP303 - 3-outlet power strip (on/off control)
  • HS110 - Smart plug with energy monitoring
  • HS105/HS103 - Basic smart plugs
  • KP115 - Smart plug with energy monitoring

Most TP-Link Kasa devices using the local protocol should work.

Installation

go get github.com/scttfrdmn/kasa

Quick Start

Discover Devices

package main

import (
    "context"
    "fmt"
    "time"

    "github.com/scttfrdmn/kasa"
)

func main() {
    ctx := context.Background()
    devices, err := kasa.DiscoverDevices(ctx, 5*time.Second)
    if err != nil {
        panic(err)
    }

    for _, dev := range devices {
        fmt.Printf("Found: %s (%s) at %s\n", dev.Name, dev.Model, dev.IP)
    }
}

Read Device Information

client := kasa.NewClient(10 * time.Second)

// Get system information
data, err := client.GetSysInfo("192.168.1.100", kasa.DefaultPort)
if err != nil {
    panic(err)
}

sysInfo, err := kasa.ParseSysInfoResponse(data)
if err != nil {
    panic(err)
}

fmt.Printf("Device: %s\n", sysInfo.System.GetSysInfo.Alias)
fmt.Printf("Model: %s\n", sysInfo.System.GetSysInfo.Model)

Read Energy Monitoring Data

// Get energy meter data
data, err := client.GetEnergyMeter("192.168.1.100", kasa.DefaultPort)
if err != nil {
    panic(err)
}

energy, err := kasa.ParseEnergyMeterResponse(data)
if err != nil {
    panic(err)
}

fmt.Printf("Voltage: %.1f V\n", energy.GetVoltage())
fmt.Printf("Current: %.2f A\n", energy.GetCurrent())
fmt.Printf("Power: %.1f W\n", energy.GetPower())
fmt.Printf("Total: %.2f kWh\n", energy.GetTotal())

Per-Plug Power Monitoring (HS300)

// Get per-plug energy data
plugID := "800636EE67F78B4ADB2452AECE8C2ACE24CB7BC400"
data, err := client.GetPlugEnergyMeter("192.168.1.100", kasa.DefaultPort, plugID)
if err != nil {
    panic(err)
}

energy, err := kasa.ParseEnergyMeterResponse(data)
if err != nil {
    panic(err)
}

fmt.Printf("Plug Power: %.1f W\n", energy.GetPower())

Device Manager (High-Level API)

manager := kasa.NewManager()

// Add devices
manager.AddDevice("192.168.1.100", kasa.DefaultPort, "Living Room Strip")
manager.AddDevice("192.168.1.101", kasa.DefaultPort, "Kitchen Plug")

// Start background polling
ctx := context.Background()
go manager.StartPolling(ctx, 3*time.Second)

// Wait a moment for first poll
time.Sleep(time.Second)

// Get device information
devices := manager.GetDevices()
for _, dev := range devices {
    fmt.Printf("%s: %.1f W\n", dev.Name, dev.EnergyData.Power)

    // Per-plug information for power strips
    for _, plug := range dev.Plugs {
        status := "OFF"
        if plug.State {
            status = "ON"
        }
        fmt.Printf("  Plug %d (%s): %s", plug.Index+1, plug.Name, status)

        if plug.EnergyData != nil {
            fmt.Printf(" - %.1f W", plug.EnergyData.Power)
        }
        fmt.Println()
    }
}

Examples

The repository includes several example applications:

Dashboard

A real-time terminal dashboard for monitoring your devices:

cd cmd/dashboard
go build
./dashboard

Features:

  • Auto-discovery or manual configuration
  • Real-time power monitoring
  • Per-plug status and consumption (HS300)
  • Interactive TUI with device navigation

Network Scanner

Scan your network for all Kasa devices:

cd examples/scan
go build
./scan

Debug Tool

Inspect raw device responses:

cd examples/debug
go build
./debug 192.168.1.100

Protocol Details

The TP-Link Kasa protocol uses:

  • Port: TCP/UDP 9999
  • Encryption: Autokey XOR cipher (initialization key: 0xAB)
  • Format: 4-byte big-endian length prefix + encrypted JSON payload

Commands

// System info (device details, plug states)
{"system":{"get_sysinfo":null}}

// Energy meter (whole device)
{"emeter":{"get_realtime":null}}

// Per-plug energy (HS300)
{"context":{"child_ids":["PLUG_ID"]},"emeter":{"get_realtime":{}}}

// Turn on/off
{"system":{"set_relay_state":{"state":1}}}  // 1=on, 0=off

API Documentation

Core Types

Device

Represents a Kasa smart device with all state information.

type Device struct {
    Name        string
    Model       string
    IP          string
    Port        int
    HardwareVer string
    SoftwareVer string
    DeviceID    string
    LastUpdate  time.Time
    Status      DeviceStatus
    Plugs       []PlugStatus
    EnergyData  *EnergyData
}

PlugStatus

Status of an individual plug on a power strip.

type PlugStatus struct {
    Index      int
    ID         string
    Name       string
    State      bool // true = on, false = off
    OnTime     int  // Seconds the plug has been on
    EnergyData *EnergyData // Per-plug energy data (HS300)
}

EnergyData

Real-time energy monitoring data.

type EnergyData struct {
    Voltage float64 // Voltage in volts
    Current float64 // Current in amps
    Power   float64 // Power in watts
    Total   float64 // Total energy consumed in kWh
}

Client Functions

  • NewClient(timeout time.Duration) *Client - Create a new client
  • SendCommand(ip string, port int, command []byte) ([]byte, error) - Send raw command
  • GetSysInfo(ip string, port int) ([]byte, error) - Get system information
  • GetEnergyMeter(ip string, port int) ([]byte, error) - Get energy meter data
  • GetPlugEnergyMeter(ip string, port int, childID string) ([]byte, error) - Get per-plug energy

Discovery Functions

  • DiscoverDevices(ctx context.Context, timeout time.Duration) ([]DiscoveredDevice, error) - Discover devices on network

Manager Functions

  • NewManager() *Manager - Create device manager
  • AddDevice(ip string, port int, name string) - Add device to monitor
  • RemoveDevice(ip string) - Remove device from monitoring
  • GetDevices() []*Device - Get all monitored devices
  • StartPolling(ctx context.Context, interval time.Duration) - Start background polling

Protocol Functions

  • Encrypt(plaintext []byte) []byte - Encrypt using Kasa XOR cipher
  • Decrypt(ciphertext []byte) []byte - Decrypt using Kasa XOR cipher
  • BuildGetSysInfoCommand() []byte - Build sysinfo command
  • BuildGetEnergyMeterCommand() []byte - Build energy meter command
  • BuildGetPlugEnergyCommand(childID string) []byte - Build per-plug energy command
  • ParseSysInfoResponse(data []byte) (*SysInfoResponse, error) - Parse sysinfo response
  • ParseEnergyMeterResponse(data []byte) (*EnergyMeterResponse, error) - Parse energy response

Project Structure

kasa/
├── README.md              # This file
├── go.mod                 # Go module definition
├── protocol.go            # Protocol constants
├── encryption.go          # XOR cipher implementation
├── command.go             # Command builders
├── types.go               # Data structures and response parsing
├── client.go              # Low-level TCP client
├── manager.go             # High-level device manager
├── discovery.go           # UDP device discovery
├── cmd/
│   └── dashboard/         # Terminal dashboard application
└── examples/
    ├── scan/              # Network scanner
    └── debug/             # Debug tool

Acknowledgments

Protocol implementation based on reverse engineering work by:

License

Apache License 2.0 - see LICENSE file for details.

Copyright 2026 Scott Friedman

Contributing

Contributions welcome! Please feel free to submit a Pull Request.

About

Go library for controlling TP-Link Kasa smart home devices using the local protocol

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages