Skip to content

Smdn.TPSmartHomeDevices.Kasa version 2.0.0-preview3

Pre-release
Pre-release
Compare
Choose a tag to compare
@smdn smdn released this 18 Jan 15:55
· 20 commits to main since this release
ea62d4b

Released package

Release notes

The full release notes are available at gist.

Change log

Change log in this release:

API changes

API changes in this release:
diff --git a/doc/api-list/Smdn.TPSmartHomeDevices.Kasa/Smdn.TPSmartHomeDevices.Kasa-net6.0.apilist.cs b/doc/api-list/Smdn.TPSmartHomeDevices.Kasa/Smdn.TPSmartHomeDevices.Kasa-net6.0.apilist.cs
index a2ebbd2..33148bd 100644
--- a/doc/api-list/Smdn.TPSmartHomeDevices.Kasa/Smdn.TPSmartHomeDevices.Kasa-net6.0.apilist.cs
+++ b/doc/api-list/Smdn.TPSmartHomeDevices.Kasa/Smdn.TPSmartHomeDevices.Kasa-net6.0.apilist.cs
@@ -1,289 +1,290 @@
-// Smdn.TPSmartHomeDevices.Kasa.dll (Smdn.TPSmartHomeDevices.Kasa-2.0.0-preview2)
+// Smdn.TPSmartHomeDevices.Kasa.dll (Smdn.TPSmartHomeDevices.Kasa-2.0.0-preview3)
 //   Name: Smdn.TPSmartHomeDevices.Kasa
 //   AssemblyVersion: 2.0.0.0
-//   InformationalVersion: 2.0.0-preview2+d001e07a3ea43a47290d9e9d2f4d582e14caa297
+//   InformationalVersion: 2.0.0-preview3+8f11224df269f7ecb743bef2e7c9b994a578c8dd
 //   TargetFramework: .NETCoreApp,Version=v6.0
 //   Configuration: Release
 //   Referenced assemblies:
 //     Microsoft.Extensions.DependencyInjection.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60
 //     Microsoft.Extensions.Logging.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60
 //     Microsoft.Win32.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
 //     Smdn.TPSmartHomeDevices.Primitives, Version=1.1.0.0, Culture=neutral
 //     System.Collections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
 //     System.ComponentModel, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
 //     System.Memory, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
 //     System.Net.NetworkInformation, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
 //     System.Net.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
 //     System.Net.Sockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
 //     System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
 //     System.Text.Encodings.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
 //     System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
 #nullable enable annotations
 
 using System;
 using System.Buffers;
 using System.Diagnostics.CodeAnalysis;
 using System.Net;
 using System.Net.NetworkInformation;
 using System.Text.Json;
 using System.Text.Json.Serialization;
 using System.Threading;
 using System.Threading.Tasks;
 using Microsoft.Extensions.DependencyInjection;
 using Microsoft.Extensions.Logging;
 using Smdn.TPSmartHomeDevices;
 using Smdn.TPSmartHomeDevices.Kasa;
 using Smdn.TPSmartHomeDevices.Kasa.Protocol;
 
 namespace Smdn.TPSmartHomeDevices.Kasa {
   public class HS105 :
     KasaDevice,
     ISmartDevice
   {
     public static HS105 Create<TAddress>(TAddress deviceAddress, IServiceProvider serviceProvider) where TAddress : notnull {}
 
     public HS105(IDeviceEndPoint deviceEndPoint, IServiceProvider? serviceProvider = null) {}
     public HS105(IPAddress ipAddress, IServiceProvider? serviceProvider = null) {}
     public HS105(PhysicalAddress macAddress, IServiceProvider serviceProvider) {}
     public HS105(string host, IServiceProvider? serviceProvider = null) {}
 
     public ValueTask<bool> GetOnOffStateAsync(CancellationToken cancellationToken = default) {}
     public ValueTask SetOnOffStateAsync(bool newOnOffState, CancellationToken cancellationToken = default) {}
     async ValueTask<IDeviceInfo> ISmartDevice.GetDeviceInfoAsync(CancellationToken cancellationToken) {}
     public ValueTask TurnOffAsync(CancellationToken cancellationToken = default) {}
     public ValueTask TurnOnAsync(CancellationToken cancellationToken = default) {}
   }
 
   public class KL130 :
     KasaDevice,
     IMulticolorSmartLight
   {
     public static KL130 Create<TAddress>(TAddress deviceAddress, IServiceProvider serviceProvider) where TAddress : notnull {}
 
     public KL130(IDeviceEndPoint deviceEndPoint, IServiceProvider? serviceProvider = null) {}
     public KL130(IPAddress ipAddress, IServiceProvider? serviceProvider = null) {}
     public KL130(PhysicalAddress macAddress, IServiceProvider serviceProvider) {}
     public KL130(string host, IServiceProvider? serviceProvider = null) {}
 
     public ValueTask<KL130LightState> GetLightStateAsync(CancellationToken cancellationToken = default) {}
     public ValueTask<bool> GetOnOffStateAsync(CancellationToken cancellationToken = default) {}
     public ValueTask SetBrightnessAsync(int brightness, TimeSpan transitionPeriod = default, CancellationToken cancellationToken = default) {}
     public ValueTask SetColorAsync(int hue, int saturation, int? brightness = null, TimeSpan transitionPeriod = default, CancellationToken cancellationToken = default) {}
     public ValueTask SetColorTemperatureAsync(int colorTemperature, int? brightness = null, TimeSpan transitionPeriod = default, CancellationToken cancellationToken = default) {}
     public ValueTask SetOnOffStateAsync(bool newOnOffState, TimeSpan transitionPeriod = default, CancellationToken cancellationToken = default) {}
     async ValueTask<IDeviceInfo> ISmartDevice.GetDeviceInfoAsync(CancellationToken cancellationToken) {}
     ValueTask ISmartDevice.SetOnOffStateAsync(bool newOnOffState, CancellationToken cancellationToken) {}
     public ValueTask TurnOffAsync(TimeSpan transitionPeriod = default, CancellationToken cancellationToken = default) {}
     public ValueTask TurnOnAsync(TimeSpan transitionPeriod = default, CancellationToken cancellationToken = default) {}
   }
 
   public class KasaDevice : IDisposable {
     protected readonly struct NullParameter {
     }
 
     protected static readonly JsonEncodedText MethodTextGetSysInfo; // = "get_sysinfo"
     protected static readonly JsonEncodedText ModuleTextSystem; // = "system"
 
     public static KasaDevice Create(IDeviceEndPoint deviceEndPoint, IServiceProvider? serviceProvider = null) {}
     public static KasaDevice Create(IPAddress ipAddress, IServiceProvider? serviceProvider = null) {}
     public static KasaDevice Create(PhysicalAddress macAddress, IServiceProvider serviceProvider) {}
     public static KasaDevice Create(string host, IServiceProvider? serviceProvider = null) {}
     public static KasaDevice Create<TAddress>(TAddress deviceAddress, IServiceProvider serviceProvider) where TAddress : notnull {}
 
     protected KasaDevice(IDeviceEndPoint deviceEndPoint, IServiceProvider? serviceProvider) {}
     protected KasaDevice(IPAddress ipAddress, IServiceProvider? serviceProvider) {}
     protected KasaDevice(PhysicalAddress macAddress, IServiceProvider serviceProvider) {}
     protected KasaDevice(string host, IServiceProvider? serviceProvider) {}
 
+    public IDeviceEndPoint EndPoint { get; }
     public bool IsConnected { get; }
     [MemberNotNullWhen(false, "deviceEndPoint")]
     protected bool IsDisposed { [MemberNotNullWhen(false, "deviceEndPoint")] get; }
 
     protected virtual void Dispose(bool disposing) {}
     public void Dispose() {}
     public ValueTask<KasaDeviceInfo?> GetDeviceInfoAsync(CancellationToken cancellationToken = default) {}
     protected ValueTask<TSysInfo> GetSysInfoAsync<TSysInfo>(Func<JsonElement, TSysInfo> composeResult, CancellationToken cancellationToken = default) {}
     public ValueTask<EndPoint> ResolveEndPointAsync(CancellationToken cancellationToken = default) {}
     protected ValueTask SendRequestAsync<TMethodParameter>(JsonEncodedText module, JsonEncodedText method, TMethodParameter parameters, CancellationToken cancellationToken) {}
     protected ValueTask<TMethodResult> SendRequestAsync<TMethodParameter, TMethodResult>(JsonEncodedText module, JsonEncodedText method, TMethodParameter parameters, Func<JsonElement, TMethodResult> composeResult, CancellationToken cancellationToken) {}
     protected ValueTask<TMethodResult> SendRequestAsync<TMethodResult>(JsonEncodedText module, JsonEncodedText method, Func<JsonElement, TMethodResult> composeResult, CancellationToken cancellationToken) {}
     public override string? ToString() {}
   }
 
   public abstract class KasaDeviceExceptionHandler {
     internal protected static readonly KasaDeviceExceptionHandler Default; // = "Smdn.TPSmartHomeDevices.Kasa.KasaDeviceDefaultExceptionHandler"
 
     protected KasaDeviceExceptionHandler() {}
 
     public abstract KasaDeviceExceptionHandling DetermineHandling(KasaDevice device, Exception exception, int attempt, ILogger? logger);
   }
 
   public static class KasaDeviceExceptionHandlerServiceCollectionExtensions {
     public static IServiceCollection AddKasaDeviceExceptionHandler(this IServiceCollection services, KasaDeviceExceptionHandler exceptionHandler) {}
   }
 
   public class KasaDeviceInfo : IDeviceInfo {
     public KasaDeviceInfo() {}
 
     public string? Description { get; }
     [JsonConverter(typeof(Base16ByteArrayJsonConverter))]
     [JsonPropertyName("fwId")]
     public byte[]? FirmwareId { get; init; }
     [JsonPropertyName("sw_ver")]
     public string? FirmwareVersion { get; init; }
     [JsonConverter(typeof(Base16ByteArrayJsonConverter))]
     [JsonPropertyName("hwId")]
     public byte[]? HardwareId { get; init; }
     [JsonPropertyName("hw_ver")]
     public string? HardwareVersion { get; init; }
     [JsonConverter(typeof(Base16ByteArrayJsonConverter))]
     [JsonPropertyName("deviceId")]
     public byte[]? Id { get; init; }
     [Obsolete("This property is intended to be used only for JSON deserialization. Refer 'Description' to get the value.")]
     [JsonPropertyName("description")]
     public string? JsonPropertyDescription { get; set; }
     [Obsolete("This property is intended to be used only for JSON deserialization. Refer 'Description' to get the value.")]
     [JsonPropertyName("dev_name")]
     public string? JsonPropertyDevName { get; set; }
     [Obsolete("This property is intended to be used only for JSON deserialization. Refer 'MacAddress' to get the value.")]
     [JsonConverter(typeof(MacAddressJsonConverter))]
     [JsonPropertyName("mac")]
     public PhysicalAddress? JsonPropertyMac { get; init; }
     [Obsolete("This property is intended to be used only for JSON deserialization. Refer 'MacAddress' to get the value.")]
     [JsonConverter(typeof(MacAddressJsonConverter))]
     [JsonPropertyName("mic_mac")]
     public PhysicalAddress? JsonPropertyMicMac { get; init; }
     [Obsolete("This property is intended to be used only for JSON deserialization. Refer 'TypeName' to get the value.")]
     [JsonPropertyName("mic_type")]
     public string? JsonPropertyMicType { get; set; }
     [Obsolete("This property is intended to be used only for JSON deserialization. Refer 'TypeName' to get the value.")]
     [JsonPropertyName("type")]
     public string? JsonPropertyType { get; set; }
     public PhysicalAddress? MacAddress { get; }
     [JsonPropertyName("model")]
     public string? ModelName { get; init; }
     [JsonPropertyName("rssi")]
     public decimal? NetworkRssi { get; init; }
     [JsonConverter(typeof(Base16ByteArrayJsonConverter))]
     [JsonPropertyName("oemId")]
     public byte[]? OemId { get; init; }
     ReadOnlySpan<byte> IDeviceInfo.Id { get; }
     [JsonIgnore]
     public DateTimeOffset TimeStamp { get; }
     public string? TypeName { get; }
   }
 
   public class KasaDisconnectedException : KasaProtocolException {
     public KasaDisconnectedException(string message, EndPoint deviceEndPoint, Exception? innerException) {}
   }
 
   public class KasaErrorResponseException : KasaUnexpectedResponseException {
     public KasaErrorResponseException(EndPoint deviceEndPoint, string requestModule, string requestMethod, int rawErrorCode) {}
 
     public int RawErrorCode { get; }
   }
 
   public class KasaIncompleteResponseException : KasaUnexpectedResponseException {
     public KasaIncompleteResponseException(string message, EndPoint deviceEndPoint, string requestModule, string requestMethod, Exception? innerException) {}
   }
 
   public abstract class KasaProtocolException : InvalidOperationException {
     protected KasaProtocolException(string message, EndPoint deviceEndPoint, Exception? innerException) {}
 
     public EndPoint DeviceEndPoint { get; }
   }
 
   public class KasaUnexpectedResponseException : KasaProtocolException {
     public KasaUnexpectedResponseException(string message, EndPoint deviceEndPoint, string requestModule, string requestMethod, Exception? innerException) {}
 
     public string RequestMethod { get; }
     public string RequestModule { get; }
   }
 
   public readonly struct KL130LightState {
     [MemberNotNullWhen(true, "IsOn")]
     [JsonPropertyName("brightness")]
     public int? Brightness { [MemberNotNullWhen(true, "IsOn")] get; [MemberNotNullWhen(true, "IsOn")] init; }
     [MemberNotNullWhen(true, "IsOn")]
     [JsonPropertyName("color_temp")]
     public int? ColorTemperature { [MemberNotNullWhen(true, "IsOn")] get; [MemberNotNullWhen(true, "IsOn")] init; }
     [MemberNotNullWhen(true, "IsOn")]
     [JsonPropertyName("hue")]
     public int? Hue { [MemberNotNullWhen(true, "IsOn")] get; [MemberNotNullWhen(true, "IsOn")] init; }
     [JsonConverter(typeof(KasaNumericalBooleanJsonConverter))]
     [JsonPropertyName("on_off")]
     public bool IsOn { get; init; }
     [MemberNotNullWhen(true, "IsOn")]
     [JsonPropertyName("mode")]
     public string? Mode { [MemberNotNullWhen(true, "IsOn")] get; [MemberNotNullWhen(true, "IsOn")] init; }
     [MemberNotNullWhen(true, "IsOn")]
     [JsonPropertyName("saturation")]
     public int? Saturation { [MemberNotNullWhen(true, "IsOn")] get; [MemberNotNullWhen(true, "IsOn")] init; }
   }
 
   public readonly struct KasaDeviceExceptionHandling {
     public static readonly KasaDeviceExceptionHandling InvalidateEndPointAndRetry; // = "{ShouldRetry=True, RetryAfter=00:00:00, ShouldReconnect=False, ShouldInvalidateEndPoint=True}"
     public static readonly KasaDeviceExceptionHandling InvalidateEndPointAndThrow; // = "{ShouldRetry=False, RetryAfter=00:00:00, ShouldReconnect=False, ShouldInvalidateEndPoint=True}"
     public static readonly KasaDeviceExceptionHandling Retry; // = "{ShouldRetry=True, RetryAfter=00:00:00, ShouldReconnect=False, ShouldInvalidateEndPoint=False}"
     public static readonly KasaDeviceExceptionHandling RetryAfterReconnect; // = "{ShouldRetry=True, RetryAfter=00:00:00, ShouldReconnect=True, ShouldInvalidateEndPoint=False}"
     public static readonly KasaDeviceExceptionHandling Throw; // = "{ShouldRetry=False, RetryAfter=00:00:00, ShouldReconnect=False, ShouldInvalidateEndPoint=False}"
 
     public static KasaDeviceExceptionHandling CreateRetry(TimeSpan retryAfter, bool shouldReconnect = false) {}
 
     public TimeSpan RetryAfter { get; init; }
     public bool ShouldInvalidateEndPoint { get; init; }
     public bool ShouldReconnect { get; init; }
     public bool ShouldRetry { get; init; }
 
     public override string ToString() {}
   }
 }
 
 namespace Smdn.TPSmartHomeDevices.Kasa.Json {
   public sealed class KasaNumericalBooleanJsonConverter : JsonConverter<bool> {
     public KasaNumericalBooleanJsonConverter() {}
 
     public override bool Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {}
     public override void Write(Utf8JsonWriter writer, bool @value, JsonSerializerOptions options) {}
   }
 }
 
 namespace Smdn.TPSmartHomeDevices.Kasa.Protocol {
   public sealed class KasaClient : IDisposable {
     public const int DefaultPort = 9999;
 
     public KasaClient(EndPoint endPoint, ILogger? logger = null) {}
 
     public EndPoint EndPoint { get; }
     public bool IsConnected { get; }
 
     public void Dispose() {}
     public ValueTask<TMethodResult> SendAsync<TMethodParameter, TMethodResult>(JsonEncodedText module, JsonEncodedText method, TMethodParameter parameter, Func<JsonElement, TMethodResult> composeResult, CancellationToken cancellationToken = default) {}
   }
 
   public static class KasaJsonSerializer {
     public const byte InitialKey = 171;
 
     public static void DecryptInPlace(Span<byte> body) {}
     public static JsonElement Deserialize(ArrayBufferWriter<byte> buffer, JsonEncodedText module, JsonEncodedText method, ILogger? logger = null) {}
     public static void EncryptInPlace(Span<byte> body) {}
     public static void Serialize<TMethodParameter>(ArrayBufferWriter<byte> buffer, JsonEncodedText module, JsonEncodedText method, TMethodParameter parameter, ILogger? logger = null) {}
   }
 
   public class KasaMessageBodyTooShortException : KasaMessageException {
     public KasaMessageBodyTooShortException(int indicatedLength, int actualLength) {}
 
     public int ActualLength { get; }
     public int IndicatedLength { get; }
   }
 
   public class KasaMessageException : SystemException {
     public KasaMessageException(string message) {}
   }
 
   public class KasaMessageHeaderTooShortException : KasaMessageException {
     public KasaMessageHeaderTooShortException(string message) {}
   }
 }
 // API list generated by Smdn.Reflection.ReverseGenerating.ListApi.MSBuild.Tasks v1.3.2.0.
 // Smdn.Reflection.ReverseGenerating.ListApi.Core v1.2.0.0 (https://github.com/smdn/Smdn.Reflection.ReverseGenerating)
diff --git a/doc/api-list/Smdn.TPSmartHomeDevices.Kasa/Smdn.TPSmartHomeDevices.Kasa-net8.0.apilist.cs b/doc/api-list/Smdn.TPSmartHomeDevices.Kasa/Smdn.TPSmartHomeDevices.Kasa-net8.0.apilist.cs
index 57bd208..6fd773a 100644
--- a/doc/api-list/Smdn.TPSmartHomeDevices.Kasa/Smdn.TPSmartHomeDevices.Kasa-net8.0.apilist.cs
+++ b/doc/api-list/Smdn.TPSmartHomeDevices.Kasa/Smdn.TPSmartHomeDevices.Kasa-net8.0.apilist.cs
@@ -1,269 +1,270 @@
-// Smdn.TPSmartHomeDevices.Kasa.dll (Smdn.TPSmartHomeDevices.Kasa-2.0.0-preview2)
+// Smdn.TPSmartHomeDevices.Kasa.dll (Smdn.TPSmartHomeDevices.Kasa-2.0.0-preview3)
 //   Name: Smdn.TPSmartHomeDevices.Kasa
 //   AssemblyVersion: 2.0.0.0
-//   InformationalVersion: 2.0.0-preview2+d001e07a3ea43a47290d9e9d2f4d582e14caa297
+//   InformationalVersion: 2.0.0-preview3+8f11224df269f7ecb743bef2e7c9b994a578c8dd
 //   TargetFramework: .NETCoreApp,Version=v8.0
 //   Configuration: Release
 //   Referenced assemblies:
 //     Microsoft.Extensions.DependencyInjection.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60
 //     Microsoft.Extensions.Logging.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60
 //     Microsoft.Win32.Primitives, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
 //     Smdn.TPSmartHomeDevices.Primitives, Version=1.1.0.0, Culture=neutral
 //     System.Collections, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
 //     System.ComponentModel, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
 //     System.Memory, Version=8.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
 //     System.Net.NetworkInformation, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
 //     System.Net.Primitives, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
 //     System.Net.Sockets, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
 //     System.Runtime, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
 //     System.Text.Encodings.Web, Version=8.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
 //     System.Text.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
 #nullable enable annotations
 
 using System;
 using System.Buffers;
 using System.Diagnostics.CodeAnalysis;
 using System.Net;
 using System.Net.NetworkInformation;
 using System.Text.Json;
 using System.Text.Json.Serialization;
 using System.Threading;
 using System.Threading.Tasks;
 using Microsoft.Extensions.DependencyInjection;
 using Microsoft.Extensions.Logging;
 using Smdn.TPSmartHomeDevices;
 using Smdn.TPSmartHomeDevices.Kasa;
 using Smdn.TPSmartHomeDevices.Kasa.Protocol;
 
 namespace Smdn.TPSmartHomeDevices.Kasa {
   public class HS105 :
     KasaDevice,
     ISmartDevice
   {
     public static HS105 Create<TAddress>(TAddress deviceAddress, IServiceProvider serviceProvider) where TAddress : notnull {}
 
     public HS105(IDeviceEndPoint deviceEndPoint, IServiceProvider? serviceProvider = null) {}
     public HS105(IPAddress ipAddress, IServiceProvider? serviceProvider = null) {}
     public HS105(PhysicalAddress macAddress, IServiceProvider serviceProvider) {}
     public HS105(string host, IServiceProvider? serviceProvider = null) {}
 
     public ValueTask<bool> GetOnOffStateAsync(CancellationToken cancellationToken = default) {}
     public ValueTask SetOnOffStateAsync(bool newOnOffState, CancellationToken cancellationToken = default) {}
     async ValueTask<IDeviceInfo> ISmartDevice.GetDeviceInfoAsync(CancellationToken cancellationToken) {}
     public ValueTask TurnOffAsync(CancellationToken cancellationToken = default) {}
     public ValueTask TurnOnAsync(CancellationToken cancellationToken = default) {}
   }
 
   public class KL130 :
     KasaDevice,
     IMulticolorSmartLight
   {
     public static KL130 Create<TAddress>(TAddress deviceAddress, IServiceProvider serviceProvider) where TAddress : notnull {}
 
     public KL130(IDeviceEndPoint deviceEndPoint, IServiceProvider? serviceProvider = null) {}
     public KL130(IPAddress ipAddress, IServiceProvider? serviceProvider = null) {}
     public KL130(PhysicalAddress macAddress, IServiceProvider serviceProvider) {}
     public KL130(string host, IServiceProvider? serviceProvider = null) {}
 
     public ValueTask<KL130LightState> GetLightStateAsync(CancellationToken cancellationToken = default) {}
     public ValueTask<bool> GetOnOffStateAsync(CancellationToken cancellationToken = default) {}
     public ValueTask SetBrightnessAsync(int brightness, TimeSpan transitionPeriod = default, CancellationToken cancellationToken = default) {}
     public ValueTask SetColorAsync(int hue, int saturation, int? brightness = null, TimeSpan transitionPeriod = default, CancellationToken cancellationToken = default) {}
     public ValueTask SetColorTemperatureAsync(int colorTemperature, int? brightness = null, TimeSpan transitionPeriod = default, CancellationToken cancellationToken = default) {}
     public ValueTask SetOnOffStateAsync(bool newOnOffState, TimeSpan transitionPeriod = default, CancellationToken cancellationToken = default) {}
     async ValueTask<IDeviceInfo> ISmartDevice.GetDeviceInfoAsync(CancellationToken cancellationToken) {}
     ValueTask ISmartDevice.SetOnOffStateAsync(bool newOnOffState, CancellationToken cancellationToken) {}
     public ValueTask TurnOffAsync(TimeSpan transitionPeriod = default, CancellationToken cancellationToken = default) {}
     public ValueTask TurnOnAsync(TimeSpan transitionPeriod = default, CancellationToken cancellationToken = default) {}
   }
 
   public class KasaDevice : IDisposable {
     protected readonly struct NullParameter {
     }
 
     protected static readonly JsonEncodedText MethodTextGetSysInfo; // = "get_sysinfo"
     protected static readonly JsonEncodedText ModuleTextSystem; // = "system"
 
     public static KasaDevice Create(IDeviceEndPoint deviceEndPoint, IServiceProvider? serviceProvider = null) {}
     public static KasaDevice Create(IPAddress ipAddress, IServiceProvider? serviceProvider = null) {}
     public static KasaDevice Create(PhysicalAddress macAddress, IServiceProvider serviceProvider) {}
     public static KasaDevice Create(string host, IServiceProvider? serviceProvider = null) {}
     public static KasaDevice Create<TAddress>(TAddress deviceAddress, IServiceProvider serviceProvider) where TAddress : notnull {}
 
     protected KasaDevice(IDeviceEndPoint deviceEndPoint, IServiceProvider? serviceProvider) {}
     protected KasaDevice(IPAddress ipAddress, IServiceProvider? serviceProvider) {}
     protected KasaDevice(PhysicalAddress macAddress, IServiceProvider serviceProvider) {}
     protected KasaDevice(string host, IServiceProvider? serviceProvider) {}
 
+    public IDeviceEndPoint EndPoint { get; }
     public bool IsConnected { get; }
     [MemberNotNullWhen(false, "deviceEndPoint")]
     protected bool IsDisposed { [MemberNotNullWhen(false, "deviceEndPoint")] get; }
 
     protected virtual void Dispose(bool disposing) {}
     public void Dispose() {}
     public ValueTask<KasaDeviceInfo?> GetDeviceInfoAsync(CancellationToken cancellationToken = default) {}
     protected ValueTask<TSysInfo> GetSysInfoAsync<TSysInfo>(Func<JsonElement, TSysInfo> composeResult, CancellationToken cancellationToken = default) {}
     public ValueTask<EndPoint> ResolveEndPointAsync(CancellationToken cancellationToken = default) {}
     protected ValueTask SendRequestAsync<TMethodParameter>(JsonEncodedText module, JsonEncodedText method, TMethodParameter parameters, CancellationToken cancellationToken) {}
     protected ValueTask<TMethodResult> SendRequestAsync<TMethodParameter, TMethodResult>(JsonEncodedText module, JsonEncodedText method, TMethodParameter parameters, Func<JsonElement, TMethodResult> composeResult, CancellationToken cancellationToken) {}
     protected ValueTask<TMethodResult> SendRequestAsync<TMethodResult>(JsonEncodedText module, JsonEncodedText method, Func<JsonElement, TMethodResult> composeResult, CancellationToken cancellationToken) {}
     public override string? ToString() {}
   }
 
   public abstract class KasaDeviceExceptionHandler {
     internal protected static readonly KasaDeviceExceptionHandler Default; // = "Smdn.TPSmartHomeDevices.Kasa.KasaDeviceDefaultExceptionHandler"
 
     protected KasaDeviceExceptionHandler() {}
 
     public abstract KasaDeviceExceptionHandling DetermineHandling(KasaDevice device, Exception exception, int attempt, ILogger? logger);
   }
 
   public static class KasaDeviceExceptionHandlerServiceCollectionExtensions {
     public static IServiceCollection AddKasaDeviceExceptionHandler(this IServiceCollection services, KasaDeviceExceptionHandler exceptionHandler) {}
   }
 
   public class KasaDeviceInfo : IDeviceInfo {
     public KasaDeviceInfo() {}
 
     public string? Description { get; }
     [JsonConverter(typeof(Base16ByteArrayJsonConverter))]
     [JsonPropertyName("fwId")]
     public byte[]? FirmwareId { get; init; }
     [JsonPropertyName("sw_ver")]
     public string? FirmwareVersion { get; init; }
     [JsonConverter(typeof(Base16ByteArrayJsonConverter))]
     [JsonPropertyName("hwId")]
     public byte[]? HardwareId { get; init; }
     [JsonPropertyName("hw_ver")]
     public string? HardwareVersion { get; init; }
     [JsonConverter(typeof(Base16ByteArrayJsonConverter))]
     [JsonPropertyName("deviceId")]
     public byte[]? Id { get; init; }
     public PhysicalAddress? MacAddress { get; }
     [JsonPropertyName("model")]
     public string? ModelName { get; init; }
     [JsonPropertyName("rssi")]
     public decimal? NetworkRssi { get; init; }
     [JsonConverter(typeof(Base16ByteArrayJsonConverter))]
     [JsonPropertyName("oemId")]
     public byte[]? OemId { get; init; }
     ReadOnlySpan<byte> IDeviceInfo.Id { get; }
     [JsonIgnore]
     public DateTimeOffset TimeStamp { get; }
     public string? TypeName { get; }
   }
 
   public class KasaDisconnectedException : KasaProtocolException {
     public KasaDisconnectedException(string message, EndPoint deviceEndPoint, Exception? innerException) {}
   }
 
   public class KasaErrorResponseException : KasaUnexpectedResponseException {
     public KasaErrorResponseException(EndPoint deviceEndPoint, string requestModule, string requestMethod, int rawErrorCode) {}
 
     public int RawErrorCode { get; }
   }
 
   public class KasaIncompleteResponseException : KasaUnexpectedResponseException {
     public KasaIncompleteResponseException(string message, EndPoint deviceEndPoint, string requestModule, string requestMethod, Exception? innerException) {}
   }
 
   public abstract class KasaProtocolException : InvalidOperationException {
     protected KasaProtocolException(string message, EndPoint deviceEndPoint, Exception? innerException) {}
 
     public EndPoint DeviceEndPoint { get; }
   }
 
   public class KasaUnexpectedResponseException : KasaProtocolException {
     public KasaUnexpectedResponseException(string message, EndPoint deviceEndPoint, string requestModule, string requestMethod, Exception? innerException) {}
 
     public string RequestMethod { get; }
     public string RequestModule { get; }
   }
 
   public readonly struct KL130LightState {
     [MemberNotNullWhen(true, "IsOn")]
     [JsonPropertyName("brightness")]
     public int? Brightness { [MemberNotNullWhen(true, "IsOn")] get; [MemberNotNullWhen(true, "IsOn")] init; }
     [MemberNotNullWhen(true, "IsOn")]
     [JsonPropertyName("color_temp")]
     public int? ColorTemperature { [MemberNotNullWhen(true, "IsOn")] get; [MemberNotNullWhen(true, "IsOn")] init; }
     [MemberNotNullWhen(true, "IsOn")]
     [JsonPropertyName("hue")]
     public int? Hue { [MemberNotNullWhen(true, "IsOn")] get; [MemberNotNullWhen(true, "IsOn")] init; }
     [JsonConverter(typeof(KasaNumericalBooleanJsonConverter))]
     [JsonPropertyName("on_off")]
     public bool IsOn { get; init; }
     [MemberNotNullWhen(true, "IsOn")]
     [JsonPropertyName("mode")]
     public string? Mode { [MemberNotNullWhen(true, "IsOn")] get; [MemberNotNullWhen(true, "IsOn")] init; }
     [MemberNotNullWhen(true, "IsOn")]
     [JsonPropertyName("saturation")]
     public int? Saturation { [MemberNotNullWhen(true, "IsOn")] get; [MemberNotNullWhen(true, "IsOn")] init; }
   }
 
   public readonly struct KasaDeviceExceptionHandling {
     public static readonly KasaDeviceExceptionHandling InvalidateEndPointAndRetry; // = "{ShouldRetry=True, RetryAfter=00:00:00, ShouldReconnect=False, ShouldInvalidateEndPoint=True}"
     public static readonly KasaDeviceExceptionHandling InvalidateEndPointAndThrow; // = "{ShouldRetry=False, RetryAfter=00:00:00, ShouldReconnect=False, ShouldInvalidateEndPoint=True}"
     public static readonly KasaDeviceExceptionHandling Retry; // = "{ShouldRetry=True, RetryAfter=00:00:00, ShouldReconnect=False, ShouldInvalidateEndPoint=False}"
     public static readonly KasaDeviceExceptionHandling RetryAfterReconnect; // = "{ShouldRetry=True, RetryAfter=00:00:00, ShouldReconnect=True, ShouldInvalidateEndPoint=False}"
     public static readonly KasaDeviceExceptionHandling Throw; // = "{ShouldRetry=False, RetryAfter=00:00:00, ShouldReconnect=False, ShouldInvalidateEndPoint=False}"
 
     public static KasaDeviceExceptionHandling CreateRetry(TimeSpan retryAfter, bool shouldReconnect = false) {}
 
     public TimeSpan RetryAfter { get; init; }
     public bool ShouldInvalidateEndPoint { get; init; }
     public bool ShouldReconnect { get; init; }
     public bool ShouldRetry { get; init; }
 
     public override string ToString() {}
   }
 }
 
 namespace Smdn.TPSmartHomeDevices.Kasa.Json {
   public sealed class KasaNumericalBooleanJsonConverter : JsonConverter<bool> {
     public KasaNumericalBooleanJsonConverter() {}
 
     public override bool Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {}
     public override void Write(Utf8JsonWriter writer, bool @value, JsonSerializerOptions options) {}
   }
 }
 
 namespace Smdn.TPSmartHomeDevices.Kasa.Protocol {
   public sealed class KasaClient : IDisposable {
     public const int DefaultPort = 9999;
 
     public KasaClient(EndPoint endPoint, ILogger? logger = null) {}
 
     public EndPoint EndPoint { get; }
     public bool IsConnected { get; }
 
     public void Dispose() {}
     public ValueTask<TMethodResult> SendAsync<TMethodParameter, TMethodResult>(JsonEncodedText module, JsonEncodedText method, TMethodParameter parameter, Func<JsonElement, TMethodResult> composeResult, CancellationToken cancellationToken = default) {}
   }
 
   public static class KasaJsonSerializer {
     public const byte InitialKey = 171;
 
     public static void DecryptInPlace(Span<byte> body) {}
     public static JsonElement Deserialize(ArrayBufferWriter<byte> buffer, JsonEncodedText module, JsonEncodedText method, ILogger? logger = null) {}
     public static void EncryptInPlace(Span<byte> body) {}
     public static void Serialize<TMethodParameter>(ArrayBufferWriter<byte> buffer, JsonEncodedText module, JsonEncodedText method, TMethodParameter parameter, ILogger? logger = null) {}
   }
 
   public class KasaMessageBodyTooShortException : KasaMessageException {
     public KasaMessageBodyTooShortException(int indicatedLength, int actualLength) {}
 
     public int ActualLength { get; }
     public int IndicatedLength { get; }
   }
 
   public class KasaMessageException : SystemException {
     public KasaMessageException(string message) {}
   }
 
   public class KasaMessageHeaderTooShortException : KasaMessageException {
     public KasaMessageHeaderTooShortException(string message) {}
   }
 }
 // API list generated by Smdn.Reflection.ReverseGenerating.ListApi.MSBuild.Tasks v1.3.2.0.
 // Smdn.Reflection.ReverseGenerating.ListApi.Core v1.2.0.0 (https://github.com/smdn/Smdn.Reflection.ReverseGenerating)
diff --git a/doc/api-list/Smdn.TPSmartHomeDevices.Kasa/Smdn.TPSmartHomeDevices.Kasa-netstandard2.1.apilist.cs b/doc/api-list/Smdn.TPSmartHomeDevices.Kasa/Smdn.TPSmartHomeDevices.Kasa-netstandard2.1.apilist.cs
index 95addcf..24f4581 100644
--- a/doc/api-list/Smdn.TPSmartHomeDevices.Kasa/Smdn.TPSmartHomeDevices.Kasa-netstandard2.1.apilist.cs
+++ b/doc/api-list/Smdn.TPSmartHomeDevices.Kasa/Smdn.TPSmartHomeDevices.Kasa-netstandard2.1.apilist.cs
@@ -1,275 +1,276 @@
-// Smdn.TPSmartHomeDevices.Kasa.dll (Smdn.TPSmartHomeDevices.Kasa-2.0.0-preview2)
+// Smdn.TPSmartHomeDevices.Kasa.dll (Smdn.TPSmartHomeDevices.Kasa-2.0.0-preview3)
 //   Name: Smdn.TPSmartHomeDevices.Kasa
 //   AssemblyVersion: 2.0.0.0
-//   InformationalVersion: 2.0.0-preview2+d001e07a3ea43a47290d9e9d2f4d582e14caa297
+//   InformationalVersion: 2.0.0-preview3+8f11224df269f7ecb743bef2e7c9b994a578c8dd
 //   TargetFramework: .NETStandard,Version=v2.1
 //   Configuration: Release
 //   Referenced assemblies:
 //     Microsoft.Extensions.DependencyInjection.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60
 //     Microsoft.Extensions.Logging.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60
 //     Smdn.TPSmartHomeDevices.Primitives, Version=1.1.0.0, Culture=neutral
 //     System.Text.Encodings.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
 //     System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
 //     netstandard, Version=2.1.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
 #nullable enable annotations
 
 using System;
 using System.Buffers;
 using System.Net;
 using System.Net.NetworkInformation;
 using System.Text.Json;
 using System.Text.Json.Serialization;
 using System.Threading;
 using System.Threading.Tasks;
 using Microsoft.Extensions.DependencyInjection;
 using Microsoft.Extensions.Logging;
 using Smdn.TPSmartHomeDevices;
 using Smdn.TPSmartHomeDevices.Kasa;
 using Smdn.TPSmartHomeDevices.Kasa.Protocol;
 
 namespace Smdn.TPSmartHomeDevices.Kasa {
   public class HS105 :
     KasaDevice,
     ISmartDevice
   {
     public static HS105 Create<TAddress>(TAddress deviceAddress, IServiceProvider serviceProvider) where TAddress : notnull {}
 
     public HS105(IDeviceEndPoint deviceEndPoint, IServiceProvider? serviceProvider = null) {}
     public HS105(IPAddress ipAddress, IServiceProvider? serviceProvider = null) {}
     public HS105(PhysicalAddress macAddress, IServiceProvider serviceProvider) {}
     public HS105(string host, IServiceProvider? serviceProvider = null) {}
 
     public ValueTask<bool> GetOnOffStateAsync(CancellationToken cancellationToken = default) {}
     public ValueTask SetOnOffStateAsync(bool newOnOffState, CancellationToken cancellationToken = default) {}
     async ValueTask<IDeviceInfo> ISmartDevice.GetDeviceInfoAsync(CancellationToken cancellationToken) {}
     public ValueTask TurnOffAsync(CancellationToken cancellationToken = default) {}
     public ValueTask TurnOnAsync(CancellationToken cancellationToken = default) {}
   }
 
   public class KL130 :
     KasaDevice,
     IMulticolorSmartLight
   {
     public static KL130 Create<TAddress>(TAddress deviceAddress, IServiceProvider serviceProvider) where TAddress : notnull {}
 
     public KL130(IDeviceEndPoint deviceEndPoint, IServiceProvider? serviceProvider = null) {}
     public KL130(IPAddress ipAddress, IServiceProvider? serviceProvider = null) {}
     public KL130(PhysicalAddress macAddress, IServiceProvider serviceProvider) {}
     public KL130(string host, IServiceProvider? serviceProvider = null) {}
 
     public ValueTask<KL130LightState> GetLightStateAsync(CancellationToken cancellationToken = default) {}
     public ValueTask<bool> GetOnOffStateAsync(CancellationToken cancellationToken = default) {}
     public ValueTask SetBrightnessAsync(int brightness, TimeSpan transitionPeriod = default, CancellationToken cancellationToken = default) {}
     public ValueTask SetColorAsync(int hue, int saturation, int? brightness = null, TimeSpan transitionPeriod = default, CancellationToken cancellationToken = default) {}
     public ValueTask SetColorTemperatureAsync(int colorTemperature, int? brightness = null, TimeSpan transitionPeriod = default, CancellationToken cancellationToken = default) {}
     public ValueTask SetOnOffStateAsync(bool newOnOffState, TimeSpan transitionPeriod = default, CancellationToken cancellationToken = default) {}
     async ValueTask<IDeviceInfo> ISmartDevice.GetDeviceInfoAsync(CancellationToken cancellationToken) {}
     ValueTask ISmartDevice.SetOnOffStateAsync(bool newOnOffState, CancellationToken cancellationToken) {}
     public ValueTask TurnOffAsync(TimeSpan transitionPeriod = default, CancellationToken cancellationToken = default) {}
     public ValueTask TurnOnAsync(TimeSpan transitionPeriod = default, CancellationToken cancellationToken = default) {}
   }
 
   public class KasaDevice : IDisposable {
     protected readonly struct NullParameter {
     }
 
     protected static readonly JsonEncodedText MethodTextGetSysInfo;
     protected static readonly JsonEncodedText ModuleTextSystem;
 
     public static KasaDevice Create(IDeviceEndPoint deviceEndPoint, IServiceProvider? serviceProvider = null) {}
     public static KasaDevice Create(IPAddress ipAddress, IServiceProvider? serviceProvider = null) {}
     public static KasaDevice Create(PhysicalAddress macAddress, IServiceProvider serviceProvider) {}
     public static KasaDevice Create(string host, IServiceProvider? serviceProvider = null) {}
     public static KasaDevice Create<TAddress>(TAddress deviceAddress, IServiceProvider serviceProvider) where TAddress : notnull {}
 
     protected KasaDevice(IDeviceEndPoint deviceEndPoint, IServiceProvider? serviceProvider) {}
     protected KasaDevice(IPAddress ipAddress, IServiceProvider? serviceProvider) {}
     protected KasaDevice(PhysicalAddress macAddress, IServiceProvider serviceProvider) {}
     protected KasaDevice(string host, IServiceProvider? serviceProvider) {}
 
+    public IDeviceEndPoint EndPoint { get; }
     public bool IsConnected { get; }
     protected bool IsDisposed { get; }
 
     protected virtual void Dispose(bool disposing) {}
     public void Dispose() {}
     public ValueTask<KasaDeviceInfo?> GetDeviceInfoAsync(CancellationToken cancellationToken = default) {}
     protected ValueTask<TSysInfo> GetSysInfoAsync<TSysInfo>(Func<JsonElement, TSysInfo> composeResult, CancellationToken cancellationToken = default) {}
     public ValueTask<EndPoint> ResolveEndPointAsync(CancellationToken cancellationToken = default) {}
     protected ValueTask SendRequestAsync<TMethodParameter>(JsonEncodedText module, JsonEncodedText method, TMethodParameter parameters, CancellationToken cancellationToken) {}
     protected ValueTask<TMethodResult> SendRequestAsync<TMethodParameter, TMethodResult>(JsonEncodedText module, JsonEncodedText method, TMethodParameter parameters, Func<JsonElement, TMethodResult> composeResult, CancellationToken cancellationToken) {}
     protected ValueTask<TMethodResult> SendRequestAsync<TMethodResult>(JsonEncodedText module, JsonEncodedText method, Func<JsonElement, TMethodResult> composeResult, CancellationToken cancellationToken) {}
     public override string? ToString() {}
   }
 
   public abstract class KasaDeviceExceptionHandler {
     internal protected static readonly KasaDeviceExceptionHandler Default; // = "Smdn.TPSmartHomeDevices.Kasa.KasaDeviceDefaultExceptionHandler"
 
     protected KasaDeviceExceptionHandler() {}
 
     public abstract KasaDeviceExceptionHandling DetermineHandling(KasaDevice device, Exception exception, int attempt, ILogger? logger);
   }
 
   public static class KasaDeviceExceptionHandlerServiceCollectionExtensions {
     public static IServiceCollection AddKasaDeviceExceptionHandler(this IServiceCollection services, KasaDeviceExceptionHandler exceptionHandler) {}
   }
 
   public class KasaDeviceInfo : IDeviceInfo {
     public KasaDeviceInfo() {}
 
     public string? Description { get; }
     [JsonConverter(typeof(Base16ByteArrayJsonConverter))]
     [JsonPropertyName("fwId")]
     public byte[]? FirmwareId { get; init; }
     [JsonPropertyName("sw_ver")]
     public string? FirmwareVersion { get; init; }
     [JsonConverter(typeof(Base16ByteArrayJsonConverter))]
     [JsonPropertyName("hwId")]
     public byte[]? HardwareId { get; init; }
     [JsonPropertyName("hw_ver")]
     public string? HardwareVersion { get; init; }
     [JsonConverter(typeof(Base16ByteArrayJsonConverter))]
     [JsonPropertyName("deviceId")]
     public byte[]? Id { get; init; }
     [Obsolete("This property is intended to be used only for JSON deserialization. Refer 'Description' to get the value.")]
     [JsonPropertyName("description")]
     public string? JsonPropertyDescription { get; set; }
     [Obsolete("This property is intended to be used only for JSON deserialization. Refer 'Description' to get the value.")]
     [JsonPropertyName("dev_name")]
     public string? JsonPropertyDevName { get; set; }
     [Obsolete("This property is intended to be used only for JSON deserialization. Refer 'MacAddress' to get the value.")]
     [JsonConverter(typeof(MacAddressJsonConverter))]
     [JsonPropertyName("mac")]
     public PhysicalAddress? JsonPropertyMac { get; init; }
     [Obsolete("This property is intended to be used only for JSON deserialization. Refer 'MacAddress' to get the value.")]
     [JsonConverter(typeof(MacAddressJsonConverter))]
     [JsonPropertyName("mic_mac")]
     public PhysicalAddress? JsonPropertyMicMac { get; init; }
     [Obsolete("This property is intended to be used only for JSON deserialization. Refer 'TypeName' to get the value.")]
     [JsonPropertyName("mic_type")]
     public string? JsonPropertyMicType { get; set; }
     [Obsolete("This property is intended to be used only for JSON deserialization. Refer 'TypeName' to get the value.")]
     [JsonPropertyName("type")]
     public string? JsonPropertyType { get; set; }
     public PhysicalAddress? MacAddress { get; }
     [JsonPropertyName("model")]
     public string? ModelName { get; init; }
     [JsonPropertyName("rssi")]
     public decimal? NetworkRssi { get; init; }
     [JsonConverter(typeof(Base16ByteArrayJsonConverter))]
     [JsonPropertyName("oemId")]
     public byte[]? OemId { get; init; }
     ReadOnlySpan<byte> IDeviceInfo.Id { get; }
     [JsonIgnore]
     public DateTimeOffset TimeStamp { get; }
     public string? TypeName { get; }
   }
 
   public class KasaDisconnectedException : KasaProtocolException {
     public KasaDisconnectedException(string message, EndPoint deviceEndPoint, Exception? innerException) {}
   }
 
   public class KasaErrorResponseException : KasaUnexpectedResponseException {
     public KasaErrorResponseException(EndPoint deviceEndPoint, string requestModule, string requestMethod, int rawErrorCode) {}
 
     public int RawErrorCode { get; }
   }
 
   public class KasaIncompleteResponseException : KasaUnexpectedResponseException {
     public KasaIncompleteResponseException(string message, EndPoint deviceEndPoint, string requestModule, string requestMethod, Exception? innerException) {}
   }
 
   public abstract class KasaProtocolException : InvalidOperationException {
     protected KasaProtocolException(string message, EndPoint deviceEndPoint, Exception? innerException) {}
 
     public EndPoint DeviceEndPoint { get; }
   }
 
   public class KasaUnexpectedResponseException : KasaProtocolException {
     public KasaUnexpectedResponseException(string message, EndPoint deviceEndPoint, string requestModule, string requestMethod, Exception? innerException) {}
 
     public string RequestMethod { get; }
     public string RequestModule { get; }
   }
 
   public readonly struct KL130LightState {
     [JsonPropertyName("brightness")]
     public int? Brightness { get; init; }
     [JsonPropertyName("color_temp")]
     public int? ColorTemperature { get; init; }
     [JsonPropertyName("hue")]
     public int? Hue { get; init; }
     [JsonConverter(typeof(KasaNumericalBooleanJsonConverter))]
     [JsonPropertyName("on_off")]
     public bool IsOn { get; init; }
     [JsonPropertyName("mode")]
     public string? Mode { get; init; }
     [JsonPropertyName("saturation")]
     public int? Saturation { get; init; }
   }
 
   public readonly struct KasaDeviceExceptionHandling {
     public static readonly KasaDeviceExceptionHandling InvalidateEndPointAndRetry; // = "{ShouldRetry=True, RetryAfter=00:00:00, ShouldReconnect=False, ShouldInvalidateEndPoint=True}"
     public static readonly KasaDeviceExceptionHandling InvalidateEndPointAndThrow; // = "{ShouldRetry=False, RetryAfter=00:00:00, ShouldReconnect=False, ShouldInvalidateEndPoint=True}"
     public static readonly KasaDeviceExceptionHandling Retry; // = "{ShouldRetry=True, RetryAfter=00:00:00, ShouldReconnect=False, ShouldInvalidateEndPoint=False}"
     public static readonly KasaDeviceExceptionHandling RetryAfterReconnect; // = "{ShouldRetry=True, RetryAfter=00:00:00, ShouldReconnect=True, ShouldInvalidateEndPoint=False}"
     public static readonly KasaDeviceExceptionHandling Throw; // = "{ShouldRetry=False, RetryAfter=00:00:00, ShouldReconnect=False, ShouldInvalidateEndPoint=False}"
 
     public static KasaDeviceExceptionHandling CreateRetry(TimeSpan retryAfter, bool shouldReconnect = false) {}
 
     public TimeSpan RetryAfter { get; init; }
     public bool ShouldInvalidateEndPoint { get; init; }
     public bool ShouldReconnect { get; init; }
     public bool ShouldRetry { get; init; }
 
     public override string ToString() {}
   }
 }
 
 namespace Smdn.TPSmartHomeDevices.Kasa.Json {
   public sealed class KasaNumericalBooleanJsonConverter : JsonConverter<bool> {
     public KasaNumericalBooleanJsonConverter() {}
 
     public override bool Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {}
     [...] public override <unknown> Write(...) {}
   }
 }
 
 namespace Smdn.TPSmartHomeDevices.Kasa.Protocol {
   public sealed class KasaClient : IDisposable {
     public const int DefaultPort = 9999;
 
     public KasaClient(EndPoint endPoint, ILogger? logger = null) {}
 
     public EndPoint EndPoint { get; }
     public bool IsConnected { get; }
 
     public void Dispose() {}
     public ValueTask<TMethodResult> SendAsync<TMethodParameter, TMethodResult>(JsonEncodedText module, JsonEncodedText method, TMethodParameter parameter, Func<JsonElement, TMethodResult> composeResult, CancellationToken cancellationToken = default) {}
   }
 
   public static class KasaJsonSerializer {
     public const byte InitialKey = 171;
 
     public static void DecryptInPlace(Span<byte> body) {}
     public static JsonElement Deserialize(ArrayBufferWriter<byte> buffer, JsonEncodedText module, JsonEncodedText method, ILogger? logger = null) {}
     public static void EncryptInPlace(Span<byte> body) {}
     public static void Serialize<TMethodParameter>(ArrayBufferWriter<byte> buffer, JsonEncodedText module, JsonEncodedText method, TMethodParameter parameter, ILogger? logger = null) {}
   }
 
   public class KasaMessageBodyTooShortException : KasaMessageException {
     public KasaMessageBodyTooShortException(int indicatedLength, int actualLength) {}
 
     public int ActualLength { get; }
     public int IndicatedLength { get; }
   }
 
   public class KasaMessageException : SystemException {
     public KasaMessageException(string message) {}
   }
 
   public class KasaMessageHeaderTooShortException : KasaMessageException {
     public KasaMessageHeaderTooShortException(string message) {}
   }
 }
 // API list generated by Smdn.Reflection.ReverseGenerating.ListApi.MSBuild.Tasks v1.3.2.0.
 // Smdn.Reflection.ReverseGenerating.ListApi.Core v1.2.0.0 (https://github.com/smdn/Smdn.Reflection.ReverseGenerating)

Full changes

Full changes in this release:
diff --git a/src/Smdn.TPSmartHomeDevices.Kasa/Smdn.TPSmartHomeDevices.Kasa.csproj b/src/Smdn.TPSmartHomeDevices.Kasa/Smdn.TPSmartHomeDevices.Kasa.csproj
index 7b81cee..703a947 100644
--- a/src/Smdn.TPSmartHomeDevices.Kasa/Smdn.TPSmartHomeDevices.Kasa.csproj
+++ b/src/Smdn.TPSmartHomeDevices.Kasa/Smdn.TPSmartHomeDevices.Kasa.csproj
@@ -6,7 +6,7 @@ SPDX-License-Identifier: MIT
   <PropertyGroup>
     <TargetFrameworks>net8.0;net6.0;netstandard2.1</TargetFrameworks>
     <VersionPrefix>2.0.0</VersionPrefix>
-    <VersionSuffix>preview2</VersionSuffix>
+    <VersionSuffix>preview3</VersionSuffix>
     <PackageValidationBaselineVersion>1.0.0</PackageValidationBaselineVersion>
     <RootNamespace/> <!-- empty the root namespace so that the namespace is determined only by the directory name, for code style rule IDE0030 -->
     <Nullable>enable</Nullable>
@@ -38,7 +38,7 @@ SPDX-License-Identifier: MIT
 
   <ItemGroup>
     <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.0" />
-    <ProjectOrPackageReference ReferencePackageVersion="1.1.0-preview2" Include="..\Smdn.TPSmartHomeDevices.Primitives\Smdn.TPSmartHomeDevices.Primitives.csproj" />
+    <ProjectOrPackageReference ReferencePackageVersion="1.1.0-preview3" Include="..\Smdn.TPSmartHomeDevices.Primitives\Smdn.TPSmartHomeDevices.Primitives.csproj" />
   </ItemGroup>
 
   <ItemGroup>
diff --git a/src/Smdn.TPSmartHomeDevices.Kasa/Smdn.TPSmartHomeDevices.Kasa/KasaDevice.cs b/src/Smdn.TPSmartHomeDevices.Kasa/Smdn.TPSmartHomeDevices.Kasa/KasaDevice.cs
index 0bb2213..906cf80 100644
--- a/src/Smdn.TPSmartHomeDevices.Kasa/Smdn.TPSmartHomeDevices.Kasa/KasaDevice.cs
+++ b/src/Smdn.TPSmartHomeDevices.Kasa/Smdn.TPSmartHomeDevices.Kasa/KasaDevice.cs
@@ -50,6 +50,19 @@ public partial class KasaDevice : IDisposable {
 
   private IDeviceEndPoint deviceEndPoint; // if null, it indicates a 'disposed' state.
 
+  /// <summary>
+  /// Gets the <see cref="IDeviceEndPoint"/> representing a endpoint of smart device,
+  /// which will be used to resolve the actual endpoint used to communicate with smart devices.
+  /// </summary>
+  /// <exception cref="ObjectDisposedException">The device has been disposed.</exception>
+  public IDeviceEndPoint EndPoint {
+    get {
+      ThrowIfDisposed();
+
+      return deviceEndPoint;
+    }
+  }
+
 #if SYSTEM_DIAGNOSTICS_CODEANALYSIS_MEMBERNOTNULLWHENATTRIBUTE
   [MemberNotNullWhen(false, nameof(deviceEndPoint))]
 #endif

Notes

Full Changelog: releases/Smdn.TPSmartHomeDevices.Kasa-2.0.0-preview2...releases/Smdn.TPSmartHomeDevices.Kasa-2.0.0-preview3