Code Monkey home page Code Monkey logo

kasa's Introduction

Kasa

Nuget GitHub Workflow Status Coveralls

Control TP-Link Kasa smart outlets/plugs

Table of Contents
  1. Quick Start
  2. Prerequisites
  3. Installation
  4. Configuration
  5. Commands
  6. Exceptions
  7. References

Kasa EP10

Quick Start

using IKasaOutlet kasa = new KasaOutlet("192.168.1.100");
if (!await kasa.System.IsOutletOn()) {
    await kasa.System.SetOutletOn(true);
}

Prerequisites

Installation

You can install this library into your project from NuGet Gallery:

  • dotnet add package Kasa
  • Install-Package Kasa
  • Go to Project › Manage NuGet Packages in Visual Studio and search for Kasa

Configuration

  1. Connect your Kasa device to your wi-fi network.
  2. Get your device's hostname.
    • You can find its IP address in your router's client or DHCP lists. The MAC address will match the one printed on the device and shown in Device Info in the Kasa Smart app.
    • You can also scan for servers exposing TCP port 9999.
      nmap --open -pT:9999 192.168.1.0/24
    • You can also use its FQDN if you assigned one.
  3. Construct a new KasaOutlet instance in your project, passing the device's hostname as a constructor parameter.
    using IKasaOutlet kasa = new KasaOutlet(hostname: "192.168.1.100");

IKasaOutlet instances can be reused to send multiple commands over the lifetime of your application. You can add one to your dependency injection context and retain it for as long as you like. Remember to Dispose() it when you're done using it, so that it can tear down the TCP socket.

Connections

The KasaOutlet instance will try to transparently handle the TCP connection for you. It will automatically ensure the TCP socket is connected to the Kasa device's server before sending any commands.

If the connection drops, for example if the device reboots, it will automatically attempt to reconnect multiple times before sending the next command, with a delay between attempts. The number of attempts and delay duration can be adjusted using the options below.

Optionally, you may manually connect before sending any commands, if you want to connect early to test the connection or ensure lower latency for the first command:

await kasa.Connect();

Options

You can customize the KasaOutlet instance by setting optional properties to control logging, timeouts, and retries.

using IKasaOutlet kasa = new KasaOutlet(hostname: "192.168.1.100") {
    LoggerFactory = loggerFactory,
    MaxAttempts = 20,
    RetryDelay = TimeSpan.FromSeconds(1),
    SendTimeout = TimeSpan.FromSeconds(2),
    ReceiveTimeout = TimeSpan.FromSeconds(2)
};

Logging

This library will emit log messages at the Debug level when it connects and disconnects from the Kasa device's TCP server. It will also emit Trace messages with the raw, stringified JSON objects sent and received on the TCP socket.

Microsoft.Extensions.Logging.ILoggerFactory instances can be injected from an ASP.NET Core Builder or .NET Generic Host Builder, or created manually.

ASP.NET Core
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<IKasaOutlet>(services => new KasaOutlet("192.168.1.100") {
    LoggerFactory = services.GetRequiredService<ILoggerFactory>()
});
appsettings.json
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Kasa": "Trace"
    }
  }
}
.NET Generic Host
Host.CreateDefaultBuilder(args).ConfigureServices(services => {
    services.AddSingleton<IKasaOutlet>(s => new KasaOutlet("192.168.1.100") {
        LoggerFactory = s.GetRequiredService<ILoggerFactory>()
    });
});
appsettings.json
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Kasa": "Trace"
    }
  }
}
Manual
ILoggerFactory loggerFactory = LoggerFactory.Create(builder => builder
    .AddFilter("Kasa", LogLevel.Trace)
    .AddConsole());

using IKasaOutlet kasa = new KasaOutlet("192.168.1.100") {
    LoggerFactory = loggerFactory
};
Third-party logging providers

You can also adapt other logging providers, such as NLog, to consume the logs produced by KasaOutlet.

ConsoleTarget consoleLog = new();
LoggingConfiguration nlogConfig = new();
nlogConfig.AddRule(NLog.LogLevel.Trace, NLog.LogLevel.Fatal, consoleLog);
LogManager.Configuration = nlogConfig;

ILoggerFactory loggerFactory = LoggerFactory.Create(builder => builder
    .ClearProviders()
    .SetMinimumLevel(LogLevel.Trace)
    .AddNLog());

using IKasaOutlet kasa = new KasaOutlet("192.168.1.100") {
    LoggerFactory = loggerFactory,
};

Commands

All commands are asynchronous, so you should await the returned Task to get the result.

More information about each command, including the parameters accepted and data returned, is available in their class and method comments.

System

Commands that get or set system properties, like status, name, and whether the outlet is on or off.

IsOutletOn

Get whether the outlet on the device can supply power to any connected electrical consumers or not.

This is unrelated to whether the entire Kasa device is running. If you can connect to it, it's running.

bool isOn = await kasa.System.IsOutletOn();
Console.WriteLine($"Is on: {isOn}");
Is on: true

SetOutletOn

Turn on or off the device's outlet so it can supply power to any connected electrical consumers or not.

You can also toggle the outlet by pressing the physical button on the device. This call is idempotent: if you try to turn the outlet on and it's already on, the call will have no effect.

The state is persisted across restarts. If the device loses power, it will restore the previous outlet power state when it turns on again.

This call is unrelated to turning the entire Kasa device on or off. To reboot the device, use Reboot.

await kasa.System.SetOutletOn(true);

GetName

The name or alias of the device that you chose during setup.

string name = await kasa.System.GetName();
Console.WriteLine($"Name: {name}");
Name: Washing Machine

SetName

Change the alias of this device. This will appear in the Kasa mobile app.

await kasa.System.SetName("My Outlet");

GetInfo

Get data about the device, including hardware, software, configuration, and current state.

SystemInfo systemInfo = await kasa.System.GetInfo();
Console.WriteLine($"Operating mode: {systemInfo.OperatingMode}");
Console.WriteLine($"Model name: {systemInfo.ModelName}");
Console.WriteLine($"Model family: {systemInfo.ModelFamily}");
Console.WriteLine($"RSSI: {systemInfo.Rssi}");
Console.WriteLine($"Features: {string.Join(", ", systemInfo.Features)}");
Console.WriteLine($"MAC address: {systemInfo.MacAddress}");
Console.WriteLine($"Device ID: {systemInfo.DeviceId}");
Console.WriteLine($"Updating: {systemInfo.Updating}");
Console.WriteLine($"Software version: {systemInfo.SoftwareVersion}");
Console.WriteLine($"Hardware version: {systemInfo.HardwareVersion}");
Console.WriteLine($"Hardware ID: {systemInfo.HardwareId}");
Console.WriteLine($"OEM ID: {systemInfo.OemId}");
Operating mode: Schedule
Model name: EP10(US)
Model family: Smart Wi-Fi Plug Mini
RSSI: -49
Features: Timer
MAC address: 5CA6E64EF3EF
Device ID: 8006C153CFEBDE93CD3572549B5A47611F49F0D2
Updating: False
Software version: 1.0.2 Build 200915 Rel.085940
Hardware version: 1.0
Hardware ID: AE6865C67F6A54B756C0B5812472C825
OEM ID: 41372DE62C896B2C0E93C20D70B62DDB

IsIndicatorLightOn

Outlets have a physical status light that shows whether they are supplying power to consumers or not.

This light can be disabled even when the outlet is on, for example if it's annoyingly bright in a room where you're trying to watch a movie or go to sleep.

bool isIndicatorLightOn = await kasa.System.IsIndicatorLightOn();
Console.WriteLine($"Is indicator light on: {isIndicatorLightOn}");
Is indicator light on: true

SetIndicatorLightOn

Outlets have a physical status light that shows whether they are supplying power to consumers or not.

This light can be disabled even when the outlet is on, for example if it's annoyingly bright in a room where you're trying to watch a movie or go to sleep.

await kasa.System.SetIndicatorLightOn(true);

Reboot

Restart the device.

Rebooting will interrupt power to any connected consumers for roughly 108 milliseconds. It takes about 8 seconds for a KP125 to completely reboot and resume responding to API requests, and about 14 seconds for an EP10.

The existing outlet power state will be retained after rebooting, so if it was on before rebooting, it will turn on again after rebooting, and there is no need to explicitly call SetOutletOn to reestablish the previous state.

By default, this client will automatically reconnect to the outlet after it reboots, which can be tuned using the MaxAttempts and RetryDelay properties.

await kasa.System.Reboot(TimeSpan.FromSeconds(5));

Time

Commands that deal with the device's internal clock that keeps track of the current date and time. This is unrelated to schedules and timers that control when the outlet turns on or off.

GetTime

Get the current local time from the device's internal clock.

DateTime time = await kasa.Time.GetTime();
Console.WriteLine($"Device time: {time:F}");
Device time: Saturday, June 11, 2022 3:48:21 am

GetTimeWithZoneOffset

Get the current time and time zone from the device's internal clock.

DateTimeOffset dateTime = await kasa.Time.GetTimeWithZoneOffset();
Console.WriteLine($"Device time: {dateTime:O}");
Device time: 2022-06-11T03:56:03.0000000-07:00

GetTimeZones

Get a list of possible time zones that the device is in.

This may return multiple possibilities instead of one time zone because, unfortunately, Kasa devices internally represent multiple time zones with non-unique identifiers. For example, Central Standard Time is unambiguously stored as 13 on the Kasa device, so this method will only return that time zone.

However, Eastern Standard Time is stored as 18 on the Kasa device, which collides with 18 that it also uses to represent Eastern Standard Time (Mexico), Turks and Caicos Standard Time, Haiti Standard Time, and Easter Island Standard Time, so this method will return all five possibilities since they cannot be distinguished based on the information provided by the device.

IEnumerable<TimeZoneInfo> timeZones = await kasa.Time.GetTimeZones();
Console.WriteLine($"Device time zone may be {string.Join(" or ", timeZones.Select(zone => zone.Id))}");
Device time zone may be Yukon Standard Time or Pacific Standard Time

SetTimeZone

Configure the device to use a specific time zone.

await kasa.Time.SetTimeZone(TimeZoneInfo.Local);

Energy Meter

Commands that deal with the energy meter present in some Kasa devices, such as the KP125 and KP115.

To determine if your device has an energy meter, you can call (await kasaOutlet.System.GetInfo()).Features.Contains(Feature.EnergyMeter).

GetInstantaneousPowerUsage

Fetch a point-in-time measurement of the instantaneous electrical usage of the outlet.

PowerUsage usage = await kasa.EnergyMeter.GetInstantaneousPowerUsage();
Console.WriteLine($"Attached consumer is currently using {usage.Current:N0} mA, {usage.Voltage / 1000.0:N3} V, and {usage.Power:N0} mW.");
Console.WriteLine($"It has used {usage.CumulativeEnergySinceBoot / 1000.0:N3} kWh since the Kasa device last booted.");
Attached consumer is currently using 0 mA, 123.069 V, and 0 mW.
It has used 0.433 kWh since the Kasa device last booted.

GetDailyEnergyUsage

Fetch a historical report of cumulative energy usage, grouped by day, from a given month and year.

DateTimeOffset now = DateTimeOffset.Now;
if (await kasa.EnergyMeter.GetDailyEnergyUsage(now.Year, now.Month) is { } days) {
    int monthStart = (int) new DateTime(now.Year, now.Month, 1).DayOfWeek;
    Console.Write(string.Join(null, Enumerable.Repeat("           | ", monthStart)));
    for (int day = 0; day < days.Count; day++) {
        int      usage = days[day];
        DateTime date  = new(now.Year, now.Month, day + 1);
        Console.Write($"{date:dd}: {usage,3:N0} Wh{(day % 7 == monthStart ? "\n" : " | ")}");
    }
}
           |            |            | 01:   0 Wh | 02:  22 Wh | 03: 182 Wh | 04:  10 Wh
05: 181 Wh | 06:   7 Wh | 07:   8 Wh | 08:   7 Wh | 09:   7 Wh | 10:   8 Wh | 11:   1 Wh
12:   0 Wh | 13:   0 Wh | 14:   0 Wh | 15:   0 Wh | 16:   0 Wh | 17:   0 Wh | 18:   0 Wh
19:   0 Wh | 20:   0 Wh | 21:   0 Wh | 22:   0 Wh | 23:   0 Wh | 24:   0 Wh | 25:   0 Wh
26:   0 Wh | 27:   0 Wh | 28:   0 Wh | 29:   0 Wh | 30:   0 Wh |

GetMonthlyEnergyUsage

Fetch a historical report of cumulative energy usage, grouped by month, from a given year.

DateTimeOffset now = DateTimeOffset.Now;
if (await kasa.EnergyMeter.GetMonthlyEnergyUsage(now.Year) is { } months) {
    for (int month = 0; month < 12; month++) {
        int      usage = months[month];
        DateTime date  = new(now.Year, month + 1, 1);
        Console.Write($"{date:MM}: {usage,3:N0} Wh{(month % 3 == 2 ? "\n" : " | ")}");
    }
}
01:   0 Wh | 02:   0 Wh | 03:   0 Wh
04:   0 Wh | 05:   0 Wh | 06: 433 Wh
07:   0 Wh | 08:   0 Wh | 09:   0 Wh
10:   0 Wh | 11:   0 Wh | 12:   0 Wh

DeleteHistoricalUsage

Clear all energy usage data for all days, months, and years, and begin gathering new data from a fresh start.

After calling this method, subsequent calls to GetDailyEnergyUsage and GetMonthlyEnergyUsage will return null for past months and years, respectively. The current month and year's data will be reset to 0, respectively. In addition, subsequent calls to GetInstantaneousPowerUsage will return 0 for CumulativeEnergySinceBoot, although it will not affect the point-in-time, non-historical measurements Current, Voltage, and Power.

await kasa.EnergyMeter.DeleteHistoricalUsage();

Exceptions

All known exceptions thrown by this library are documented in the comments of each method.

Each command can throw two main exceptions:

  • NetworkException if the TCP socket connection failed and could not be automatically recovered. Check the inner SocketException or IOException for the cause.
  • ResponseParsingException if the TCP server returned JSON that could not be deserialized, possibly because the API changed or the device is unsupported.

Some methods also throw other exceptions in specific cases, such as ArgumentOutOfRangeException or TimeZoneNotFoundException.

References

kasa's People

Contributors

aldaviva avatar lostmsu avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.