Skip to content

Smdn.TPSmartHomeDevices.Primitives version 1.1.0-preview2

Pre-release
Pre-release
Compare
Choose a tag to compare
@smdn smdn released this 16 Jan 15:41
· 44 commits to main since this release
e373bc2

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.Primitives/Smdn.TPSmartHomeDevices.Primitives-net6.0.apilist.cs b/doc/api-list/Smdn.TPSmartHomeDevices.Primitives/Smdn.TPSmartHomeDevices.Primitives-net6.0.apilist.cs
index c08ab54..31f14b3 100644
--- a/doc/api-list/Smdn.TPSmartHomeDevices.Primitives/Smdn.TPSmartHomeDevices.Primitives-net6.0.apilist.cs
+++ b/doc/api-list/Smdn.TPSmartHomeDevices.Primitives/Smdn.TPSmartHomeDevices.Primitives-net6.0.apilist.cs
@@ -1,124 +1,142 @@
-// Smdn.TPSmartHomeDevices.Primitives.dll (Smdn.TPSmartHomeDevices.Primitives-1.1.0-preview1)
+// Smdn.TPSmartHomeDevices.Primitives.dll (Smdn.TPSmartHomeDevices.Primitives-1.1.0-preview2)
 //   Name: Smdn.TPSmartHomeDevices.Primitives
 //   AssemblyVersion: 1.1.0.0
-//   InformationalVersion: 1.1.0-preview1+d9122eb664899e2e3470e87efca152f3456eb904
+//   InformationalVersion: 1.1.0-preview2+e153b40ab2e10cbae4165a6013f9be14e5465b75
 //   TargetFramework: .NETCoreApp,Version=v6.0
 //   Configuration: Release
 //   Referenced assemblies:
 //     Microsoft.Extensions.DependencyInjection.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60
+//     Smdn.Fundamental.PrintableEncoding.Hexadecimal, Version=3.0.1.0, Culture=neutral
+//     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.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
 //     System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
 #nullable enable annotations
 
 using System;
 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 Smdn.TPSmartHomeDevices;
 using Smdn.TPSmartHomeDevices.Json;
 
 namespace Smdn.TPSmartHomeDevices {
   public interface IDeviceEndPoint {
     ValueTask<EndPoint?> ResolveAsync(CancellationToken cancellationToken = default);
   }
 
   public interface IDeviceEndPointFactory<TAddress> where TAddress : notnull {
     IDeviceEndPoint Create(TAddress address);
   }
 
+  public interface IDeviceInfo {
+    string? FirmwareVersion { get; }
+    string? HardwareVersion { get; }
+    ReadOnlySpan<byte> Id { get; }
+    PhysicalAddress? MacAddress { get; }
+    string? ModelName { get; }
+  }
+
   public interface IDynamicDeviceEndPoint : IDeviceEndPoint {
     void Invalidate();
   }
 
-  public interface IMulticolorSmartLight : ISmartDevice {
-    ValueTask SetBrightnessAsync(int brightness, TimeSpan transitionPeriod, CancellationToken cancellationToken);
+  public interface IMulticolorSmartLight : ISmartLight {
     ValueTask SetColorAsync(int hue, int saturation, int? brightness, TimeSpan transitionPeriod, CancellationToken cancellationToken);
     ValueTask SetColorTemperatureAsync(int colorTemperature, int? brightness, TimeSpan transitionPeriod, CancellationToken cancellationToken);
     virtual ValueTask SetOnOffStateAsync(bool newOnOffState, TimeSpan transitionPeriod, CancellationToken cancellationToken) {}
     virtual ValueTask TurnOffAsync(TimeSpan transitionPeriod, CancellationToken cancellationToken) {}
     virtual ValueTask TurnOnAsync(TimeSpan transitionPeriod, CancellationToken cancellationToken) {}
   }
 
   public interface ISmartDevice {
+    ValueTask<IDeviceInfo> GetDeviceInfoAsync(CancellationToken cancellationToken = default);
     ValueTask<bool> GetOnOffStateAsync(CancellationToken cancellationToken);
     ValueTask SetOnOffStateAsync(bool newOnOffState, CancellationToken cancellationToken);
     virtual ValueTask TurnOffAsync(CancellationToken cancellationToken = default) {}
     virtual ValueTask TurnOnAsync(CancellationToken cancellationToken = default) {}
   }
 
-  public interface ISmartPlug : ISmartDevice {
+  public interface ISmartLight : ISmartDevice {
+    ValueTask SetBrightnessAsync(int brightness, TimeSpan transitionPeriod, CancellationToken cancellationToken);
   }
 
   public static class DeviceEndPoint {
     public static IDeviceEndPoint Create(EndPoint endPoint) {}
     public static IDeviceEndPoint Create(IPAddress ipAddress) {}
     public static IDeviceEndPoint Create(string host) {}
     public static IDeviceEndPoint Create<TAddress>(TAddress address, IDeviceEndPointFactory<TAddress> endPointFactory) where TAddress : notnull {}
   }
 
   public static class DeviceEndPointFactoryServiceCollectionExtensions {
     public static IServiceCollection AddDeviceEndPointFactory<TAddress>(this IServiceCollection services, IDeviceEndPointFactory<TAddress> endPointFactory) where TAddress : notnull {}
   }
 
   public class DeviceEndPointResolutionException : Exception {
     public DeviceEndPointResolutionException(IDeviceEndPoint deviceEndPoint) {}
     public DeviceEndPointResolutionException(IDeviceEndPoint deviceEndPoint, string message, Exception? innerException) {}
 
     public IDeviceEndPoint DeviceEndPoint { get; }
   }
 
   public static class IDeviceEndPointExtensions {
     public static ValueTask<EndPoint> ResolveOrThrowAsync(this IDeviceEndPoint deviceEndPoint, int defaultPort, CancellationToken cancellationToken = default) {}
   }
 
   public sealed class StaticDeviceEndPoint : IDeviceEndPoint {
     public StaticDeviceEndPoint(EndPoint endPoint) {}
 
     public ValueTask<EndPoint?> ResolveAsync(CancellationToken cancellationToken = default) {}
     public override string? ToString() {}
   }
 }
 
 namespace Smdn.TPSmartHomeDevices.Json {
+  public sealed class Base16ByteArrayJsonConverter : JsonConverter<byte[]> {
+    public Base16ByteArrayJsonConverter() {}
+
+    public override byte[]? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {}
+    public override void Write(Utf8JsonWriter writer, byte[]? @value, JsonSerializerOptions options) {}
+  }
+
   public sealed class GeolocationInDecimalDegreesJsonConverter : JsonConverter<decimal?> {
     public GeolocationInDecimalDegreesJsonConverter() {}
 
     public override decimal? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {}
     public override void Write(Utf8JsonWriter writer, decimal? @value, JsonSerializerOptions options) {}
   }
 
   public sealed class MacAddressJsonConverter : JsonConverter<PhysicalAddress> {
     public MacAddressJsonConverter() {}
 
     public override PhysicalAddress? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {}
     public override void Write(Utf8JsonWriter writer, PhysicalAddress @value, JsonSerializerOptions options) {}
   }
 
   public sealed class TimeSpanInMinutesJsonConverter : TimeSpanJsonConverter {
     public TimeSpanInMinutesJsonConverter() {}
 
     protected override TimeSpan ToTimeSpan(int @value) {}
   }
 
   public sealed class TimeSpanInSecondsJsonConverter : TimeSpanJsonConverter {
     public TimeSpanInSecondsJsonConverter() {}
 
     protected override TimeSpan ToTimeSpan(int @value) {}
   }
 
   public abstract class TimeSpanJsonConverter : JsonConverter<TimeSpan?> {
     protected TimeSpanJsonConverter() {}
 
     public override TimeSpan? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {}
     protected abstract TimeSpan ToTimeSpan(int @value);
     public override void Write(Utf8JsonWriter writer, TimeSpan? @value, JsonSerializerOptions options) {}
   }
 }
 // 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.Primitives/Smdn.TPSmartHomeDevices.Primitives-net8.0.apilist.cs b/doc/api-list/Smdn.TPSmartHomeDevices.Primitives/Smdn.TPSmartHomeDevices.Primitives-net8.0.apilist.cs
new file mode 100644
index 0000000..4502c32
--- /dev/null
+++ b/doc/api-list/Smdn.TPSmartHomeDevices.Primitives/Smdn.TPSmartHomeDevices.Primitives-net8.0.apilist.cs
@@ -0,0 +1,142 @@
+// Smdn.TPSmartHomeDevices.Primitives.dll (Smdn.TPSmartHomeDevices.Primitives-1.1.0-preview2)
+//   Name: Smdn.TPSmartHomeDevices.Primitives
+//   AssemblyVersion: 1.1.0.0
+//   InformationalVersion: 1.1.0-preview2+e153b40ab2e10cbae4165a6013f9be14e5465b75
+//   TargetFramework: .NETCoreApp,Version=v8.0
+//   Configuration: Release
+//   Referenced assemblies:
+//     Microsoft.Extensions.DependencyInjection.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60
+//     Smdn.Fundamental.PrintableEncoding.Hexadecimal, Version=3.0.1.0, Culture=neutral
+//     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.Runtime, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+//     System.Text.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
+#nullable enable annotations
+
+using System;
+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 Smdn.TPSmartHomeDevices;
+using Smdn.TPSmartHomeDevices.Json;
+
+namespace Smdn.TPSmartHomeDevices {
+  public interface IDeviceEndPoint {
+    ValueTask<EndPoint?> ResolveAsync(CancellationToken cancellationToken = default);
+  }
+
+  public interface IDeviceEndPointFactory<TAddress> where TAddress : notnull {
+    IDeviceEndPoint Create(TAddress address);
+  }
+
+  public interface IDeviceInfo {
+    string? FirmwareVersion { get; }
+    string? HardwareVersion { get; }
+    ReadOnlySpan<byte> Id { get; }
+    PhysicalAddress? MacAddress { get; }
+    string? ModelName { get; }
+  }
+
+  public interface IDynamicDeviceEndPoint : IDeviceEndPoint {
+    void Invalidate();
+  }
+
+  public interface IMulticolorSmartLight : ISmartLight {
+    ValueTask SetColorAsync(int hue, int saturation, int? brightness, TimeSpan transitionPeriod, CancellationToken cancellationToken);
+    ValueTask SetColorTemperatureAsync(int colorTemperature, int? brightness, TimeSpan transitionPeriod, CancellationToken cancellationToken);
+    virtual ValueTask SetOnOffStateAsync(bool newOnOffState, TimeSpan transitionPeriod, CancellationToken cancellationToken) {}
+    virtual ValueTask TurnOffAsync(TimeSpan transitionPeriod, CancellationToken cancellationToken) {}
+    virtual ValueTask TurnOnAsync(TimeSpan transitionPeriod, CancellationToken cancellationToken) {}
+  }
+
+  public interface ISmartDevice {
+    ValueTask<IDeviceInfo> GetDeviceInfoAsync(CancellationToken cancellationToken = default);
+    ValueTask<bool> GetOnOffStateAsync(CancellationToken cancellationToken);
+    ValueTask SetOnOffStateAsync(bool newOnOffState, CancellationToken cancellationToken);
+    virtual ValueTask TurnOffAsync(CancellationToken cancellationToken = default) {}
+    virtual ValueTask TurnOnAsync(CancellationToken cancellationToken = default) {}
+  }
+
+  public interface ISmartLight : ISmartDevice {
+    ValueTask SetBrightnessAsync(int brightness, TimeSpan transitionPeriod, CancellationToken cancellationToken);
+  }
+
+  public static class DeviceEndPoint {
+    public static IDeviceEndPoint Create(EndPoint endPoint) {}
+    public static IDeviceEndPoint Create(IPAddress ipAddress) {}
+    public static IDeviceEndPoint Create(string host) {}
+    public static IDeviceEndPoint Create<TAddress>(TAddress address, IDeviceEndPointFactory<TAddress> endPointFactory) where TAddress : notnull {}
+  }
+
+  public static class DeviceEndPointFactoryServiceCollectionExtensions {
+    public static IServiceCollection AddDeviceEndPointFactory<TAddress>(this IServiceCollection services, IDeviceEndPointFactory<TAddress> endPointFactory) where TAddress : notnull {}
+  }
+
+  public class DeviceEndPointResolutionException : Exception {
+    public DeviceEndPointResolutionException(IDeviceEndPoint deviceEndPoint) {}
+    public DeviceEndPointResolutionException(IDeviceEndPoint deviceEndPoint, string message, Exception? innerException) {}
+
+    public IDeviceEndPoint DeviceEndPoint { get; }
+  }
+
+  public static class IDeviceEndPointExtensions {
+    public static ValueTask<EndPoint> ResolveOrThrowAsync(this IDeviceEndPoint deviceEndPoint, int defaultPort, CancellationToken cancellationToken = default) {}
+  }
+
+  public sealed class StaticDeviceEndPoint : IDeviceEndPoint {
+    public StaticDeviceEndPoint(EndPoint endPoint) {}
+
+    public ValueTask<EndPoint?> ResolveAsync(CancellationToken cancellationToken = default) {}
+    public override string? ToString() {}
+  }
+}
+
+namespace Smdn.TPSmartHomeDevices.Json {
+  public sealed class Base16ByteArrayJsonConverter : JsonConverter<byte[]> {
+    public Base16ByteArrayJsonConverter() {}
+
+    public override byte[]? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {}
+    public override void Write(Utf8JsonWriter writer, byte[]? @value, JsonSerializerOptions options) {}
+  }
+
+  public sealed class GeolocationInDecimalDegreesJsonConverter : JsonConverter<decimal?> {
+    public GeolocationInDecimalDegreesJsonConverter() {}
+
+    public override decimal? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {}
+    public override void Write(Utf8JsonWriter writer, decimal? @value, JsonSerializerOptions options) {}
+  }
+
+  public sealed class MacAddressJsonConverter : JsonConverter<PhysicalAddress> {
+    public MacAddressJsonConverter() {}
+
+    public override PhysicalAddress? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {}
+    public override void Write(Utf8JsonWriter writer, PhysicalAddress @value, JsonSerializerOptions options) {}
+  }
+
+  public sealed class TimeSpanInMinutesJsonConverter : TimeSpanJsonConverter {
+    public TimeSpanInMinutesJsonConverter() {}
+
+    protected override TimeSpan ToTimeSpan(int @value) {}
+  }
+
+  public sealed class TimeSpanInSecondsJsonConverter : TimeSpanJsonConverter {
+    public TimeSpanInSecondsJsonConverter() {}
+
+    protected override TimeSpan ToTimeSpan(int @value) {}
+  }
+
+  public abstract class TimeSpanJsonConverter : JsonConverter<TimeSpan?> {
+    protected TimeSpanJsonConverter() {}
+
+    public override TimeSpan? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {}
+    protected abstract TimeSpan ToTimeSpan(int @value);
+    public override void Write(Utf8JsonWriter writer, TimeSpan? @value, JsonSerializerOptions options) {}
+  }
+}
+// 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.Primitives/Smdn.TPSmartHomeDevices.Primitives-netstandard2.0.apilist.cs b/doc/api-list/Smdn.TPSmartHomeDevices.Primitives/Smdn.TPSmartHomeDevices.Primitives-netstandard2.0.apilist.cs
index ea57885..3bc1464 100644
--- a/doc/api-list/Smdn.TPSmartHomeDevices.Primitives/Smdn.TPSmartHomeDevices.Primitives-netstandard2.0.apilist.cs
+++ b/doc/api-list/Smdn.TPSmartHomeDevices.Primitives/Smdn.TPSmartHomeDevices.Primitives-netstandard2.0.apilist.cs
@@ -1,118 +1,136 @@
-// Smdn.TPSmartHomeDevices.Primitives.dll (Smdn.TPSmartHomeDevices.Primitives-1.1.0-preview1)
+// Smdn.TPSmartHomeDevices.Primitives.dll (Smdn.TPSmartHomeDevices.Primitives-1.1.0-preview2)
 //   Name: Smdn.TPSmartHomeDevices.Primitives
 //   AssemblyVersion: 1.1.0.0
-//   InformationalVersion: 1.1.0-preview1+d9122eb664899e2e3470e87efca152f3456eb904
+//   InformationalVersion: 1.1.0-preview2+e153b40ab2e10cbae4165a6013f9be14e5465b75
 //   TargetFramework: .NETStandard,Version=v2.0
 //   Configuration: Release
 //   Referenced assemblies:
 //     Microsoft.Extensions.DependencyInjection.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60
+//     Smdn.Fundamental.PrintableEncoding.Hexadecimal, Version=3.0.1.0, Culture=neutral
+//     System.Memory, Version=4.0.1.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
 //     System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
 //     System.Threading.Tasks.Extensions, Version=4.2.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
 //     netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
 #nullable enable annotations
 
 using System;
 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 Smdn.TPSmartHomeDevices;
 using Smdn.TPSmartHomeDevices.Json;
 
 namespace Smdn.TPSmartHomeDevices {
   public interface IDeviceEndPoint {
     ValueTask<EndPoint?> ResolveAsync(CancellationToken cancellationToken = default);
   }
 
   public interface IDeviceEndPointFactory<TAddress> where TAddress : notnull {
     IDeviceEndPoint Create(TAddress address);
   }
 
+  public interface IDeviceInfo {
+    string? FirmwareVersion { get; }
+    string? HardwareVersion { get; }
+    ReadOnlySpan<byte> Id { get; }
+    PhysicalAddress? MacAddress { get; }
+    string? ModelName { get; }
+  }
+
   public interface IDynamicDeviceEndPoint : IDeviceEndPoint {
     void Invalidate();
   }
 
-  public interface IMulticolorSmartLight : ISmartDevice {
-    ValueTask SetBrightnessAsync(int brightness, TimeSpan transitionPeriod, CancellationToken cancellationToken);
+  public interface IMulticolorSmartLight : ISmartLight {
     ValueTask SetColorAsync(int hue, int saturation, int? brightness, TimeSpan transitionPeriod, CancellationToken cancellationToken);
     ValueTask SetColorTemperatureAsync(int colorTemperature, int? brightness, TimeSpan transitionPeriod, CancellationToken cancellationToken);
   }
 
   public interface ISmartDevice {
+    ValueTask<IDeviceInfo> GetDeviceInfoAsync(CancellationToken cancellationToken = default);
     ValueTask<bool> GetOnOffStateAsync(CancellationToken cancellationToken);
     ValueTask SetOnOffStateAsync(bool newOnOffState, CancellationToken cancellationToken);
   }
 
-  public interface ISmartPlug : ISmartDevice {
+  public interface ISmartLight : ISmartDevice {
+    ValueTask SetBrightnessAsync(int brightness, TimeSpan transitionPeriod, CancellationToken cancellationToken);
   }
 
   public static class DeviceEndPoint {
     public static IDeviceEndPoint Create(EndPoint endPoint) {}
     public static IDeviceEndPoint Create(IPAddress ipAddress) {}
     public static IDeviceEndPoint Create(string host) {}
     public static IDeviceEndPoint Create<TAddress>(TAddress address, IDeviceEndPointFactory<TAddress> endPointFactory) where TAddress : notnull {}
   }
 
   public static class DeviceEndPointFactoryServiceCollectionExtensions {
     public static IServiceCollection AddDeviceEndPointFactory<TAddress>(this IServiceCollection services, IDeviceEndPointFactory<TAddress> endPointFactory) where TAddress : notnull {}
   }
 
   public class DeviceEndPointResolutionException : Exception {
     public DeviceEndPointResolutionException(IDeviceEndPoint deviceEndPoint) {}
     public DeviceEndPointResolutionException(IDeviceEndPoint deviceEndPoint, string message, Exception? innerException) {}
 
     public IDeviceEndPoint DeviceEndPoint { get; }
   }
 
   public static class IDeviceEndPointExtensions {
     public static ValueTask<EndPoint> ResolveOrThrowAsync(this IDeviceEndPoint deviceEndPoint, int defaultPort, CancellationToken cancellationToken = default) {}
   }
 
   public sealed class StaticDeviceEndPoint : IDeviceEndPoint {
     public StaticDeviceEndPoint(EndPoint endPoint) {}
 
     public ValueTask<EndPoint?> ResolveAsync(CancellationToken cancellationToken = default) {}
     public override string? ToString() {}
   }
 }
 
 namespace Smdn.TPSmartHomeDevices.Json {
+  public sealed class Base16ByteArrayJsonConverter : JsonConverter<byte[]> {
+    public Base16ByteArrayJsonConverter() {}
+
+    public override byte[]? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {}
+    public override void Write(Utf8JsonWriter writer, byte[]? @value, JsonSerializerOptions options) {}
+  }
+
   public sealed class GeolocationInDecimalDegreesJsonConverter : JsonConverter<decimal?> {
     public GeolocationInDecimalDegreesJsonConverter() {}
 
     public override decimal? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {}
     public override void Write(Utf8JsonWriter writer, decimal? @value, JsonSerializerOptions options) {}
   }
 
   public sealed class MacAddressJsonConverter : JsonConverter<PhysicalAddress> {
     public MacAddressJsonConverter() {}
 
     public override PhysicalAddress? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {}
     public override void Write(Utf8JsonWriter writer, PhysicalAddress @value, JsonSerializerOptions options) {}
   }
 
   public sealed class TimeSpanInMinutesJsonConverter : TimeSpanJsonConverter {
     public TimeSpanInMinutesJsonConverter() {}
 
     protected override TimeSpan ToTimeSpan(int @value) {}
   }
 
   public sealed class TimeSpanInSecondsJsonConverter : TimeSpanJsonConverter {
     public TimeSpanInSecondsJsonConverter() {}
 
     protected override TimeSpan ToTimeSpan(int @value) {}
   }
 
   public abstract class TimeSpanJsonConverter : JsonConverter<TimeSpan?> {
     protected TimeSpanJsonConverter() {}
 
     public override TimeSpan? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {}
     protected abstract TimeSpan ToTimeSpan(int @value);
     public override void Write(Utf8JsonWriter writer, TimeSpan? @value, JsonSerializerOptions options) {}
   }
 }
 // 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.Primitives/Smdn.TPSmartHomeDevices.Primitives-netstandard2.1.apilist.cs b/doc/api-list/Smdn.TPSmartHomeDevices.Primitives/Smdn.TPSmartHomeDevices.Primitives-netstandard2.1.apilist.cs
index 41e5cc8..921ef3c 100644
--- a/doc/api-list/Smdn.TPSmartHomeDevices.Primitives/Smdn.TPSmartHomeDevices.Primitives-netstandard2.1.apilist.cs
+++ b/doc/api-list/Smdn.TPSmartHomeDevices.Primitives/Smdn.TPSmartHomeDevices.Primitives-netstandard2.1.apilist.cs
@@ -1,117 +1,134 @@
-// Smdn.TPSmartHomeDevices.Primitives.dll (Smdn.TPSmartHomeDevices.Primitives-1.1.0-preview1)
+// Smdn.TPSmartHomeDevices.Primitives.dll (Smdn.TPSmartHomeDevices.Primitives-1.1.0-preview2)
 //   Name: Smdn.TPSmartHomeDevices.Primitives
 //   AssemblyVersion: 1.1.0.0
-//   InformationalVersion: 1.1.0-preview1+d9122eb664899e2e3470e87efca152f3456eb904
+//   InformationalVersion: 1.1.0-preview2+e153b40ab2e10cbae4165a6013f9be14e5465b75
 //   TargetFramework: .NETStandard,Version=v2.1
 //   Configuration: Release
 //   Referenced assemblies:
 //     Microsoft.Extensions.DependencyInjection.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60
+//     Smdn.Fundamental.PrintableEncoding.Hexadecimal, Version=3.0.1.0, Culture=neutral
 //     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.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 Smdn.TPSmartHomeDevices;
 using Smdn.TPSmartHomeDevices.Json;
 
 namespace Smdn.TPSmartHomeDevices {
   public interface IDeviceEndPoint {
     ValueTask<EndPoint?> ResolveAsync(CancellationToken cancellationToken = default);
   }
 
   public interface IDeviceEndPointFactory<TAddress> where TAddress : notnull {
     IDeviceEndPoint Create(TAddress address);
   }
 
+  public interface IDeviceInfo {
+    string? FirmwareVersion { get; }
+    string? HardwareVersion { get; }
+    ReadOnlySpan<byte> Id { get; }
+    PhysicalAddress? MacAddress { get; }
+    string? ModelName { get; }
+  }
+
   public interface IDynamicDeviceEndPoint : IDeviceEndPoint {
     void Invalidate();
   }
 
-  public interface IMulticolorSmartLight : ISmartDevice {
-    ValueTask SetBrightnessAsync(int brightness, TimeSpan transitionPeriod, CancellationToken cancellationToken);
+  public interface IMulticolorSmartLight : ISmartLight {
     ValueTask SetColorAsync(int hue, int saturation, int? brightness, TimeSpan transitionPeriod, CancellationToken cancellationToken);
     ValueTask SetColorTemperatureAsync(int colorTemperature, int? brightness, TimeSpan transitionPeriod, CancellationToken cancellationToken);
   }
 
   public interface ISmartDevice {
+    ValueTask<IDeviceInfo> GetDeviceInfoAsync(CancellationToken cancellationToken = default);
     ValueTask<bool> GetOnOffStateAsync(CancellationToken cancellationToken);
     ValueTask SetOnOffStateAsync(bool newOnOffState, CancellationToken cancellationToken);
   }
 
-  public interface ISmartPlug : ISmartDevice {
+  public interface ISmartLight : ISmartDevice {
+    ValueTask SetBrightnessAsync(int brightness, TimeSpan transitionPeriod, CancellationToken cancellationToken);
   }
 
   public static class DeviceEndPoint {
     public static IDeviceEndPoint Create(EndPoint endPoint) {}
     public static IDeviceEndPoint Create(IPAddress ipAddress) {}
     public static IDeviceEndPoint Create(string host) {}
     public static IDeviceEndPoint Create<TAddress>(TAddress address, IDeviceEndPointFactory<TAddress> endPointFactory) where TAddress : notnull {}
   }
 
   public static class DeviceEndPointFactoryServiceCollectionExtensions {
     public static IServiceCollection AddDeviceEndPointFactory<TAddress>(this IServiceCollection services, IDeviceEndPointFactory<TAddress> endPointFactory) where TAddress : notnull {}
   }
 
   public class DeviceEndPointResolutionException : Exception {
     public DeviceEndPointResolutionException(IDeviceEndPoint deviceEndPoint) {}
     public DeviceEndPointResolutionException(IDeviceEndPoint deviceEndPoint, string message, Exception? innerException) {}
 
     public IDeviceEndPoint DeviceEndPoint { get; }
   }
 
   public static class IDeviceEndPointExtensions {
     public static ValueTask<EndPoint> ResolveOrThrowAsync(this IDeviceEndPoint deviceEndPoint, int defaultPort, CancellationToken cancellationToken = default) {}
   }
 
   public sealed class StaticDeviceEndPoint : IDeviceEndPoint {
     public StaticDeviceEndPoint(EndPoint endPoint) {}
 
     public ValueTask<EndPoint?> ResolveAsync(CancellationToken cancellationToken = default) {}
     public override string? ToString() {}
   }
 }
 
 namespace Smdn.TPSmartHomeDevices.Json {
+  public sealed class Base16ByteArrayJsonConverter : JsonConverter<byte[]> {
+    public Base16ByteArrayJsonConverter() {}
+
+    public override byte[]? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {}
+    [...] public override <unknown> Write(...) {}
+  }
+
   public sealed class GeolocationInDecimalDegreesJsonConverter : JsonConverter<decimal?> {
     public GeolocationInDecimalDegreesJsonConverter() {}
 
     public override decimal? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {}
     [...] public override <unknown> Write(...) {}
   }
 
   public sealed class MacAddressJsonConverter : JsonConverter<PhysicalAddress> {
     public MacAddressJsonConverter() {}
 
     public override PhysicalAddress? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {}
     [...] public override <unknown> Write(...) {}
   }
 
   public sealed class TimeSpanInMinutesJsonConverter : TimeSpanJsonConverter {
     public TimeSpanInMinutesJsonConverter() {}
 
     protected override TimeSpan ToTimeSpan(int @value) {}
   }
 
   public sealed class TimeSpanInSecondsJsonConverter : TimeSpanJsonConverter {
     public TimeSpanInSecondsJsonConverter() {}
 
     protected override TimeSpan ToTimeSpan(int @value) {}
   }
 
   public abstract class TimeSpanJsonConverter : JsonConverter<TimeSpan?> {
     protected TimeSpanJsonConverter() {}
 
     public override TimeSpan? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {}
     protected abstract TimeSpan ToTimeSpan(int @value);
     [...] public override <unknown> Write(...) {}
   }
 }
 // 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.Primitives/Smdn.TPSmartHomeDevices.Json/Base16ByteArrayJsonConverter.cs b/src/Smdn.TPSmartHomeDevices.Primitives/Smdn.TPSmartHomeDevices.Json/Base16ByteArrayJsonConverter.cs
new file mode 100644
index 0000000..ddfad66
--- /dev/null
+++ b/src/Smdn.TPSmartHomeDevices.Primitives/Smdn.TPSmartHomeDevices.Json/Base16ByteArrayJsonConverter.cs
@@ -0,0 +1,44 @@
+// SPDX-FileCopyrightText: 2023 smdn <smdn@smdn.jp>
+// SPDX-License-Identifier: MIT
+using System;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+
+using Smdn.Formats;
+
+namespace Smdn.TPSmartHomeDevices.Json;
+
+public sealed class Base16ByteArrayJsonConverter : JsonConverter<byte[]?> {
+  public override byte[]? Read(
+    ref Utf8JsonReader reader,
+    Type typeToConvert,
+    JsonSerializerOptions options
+  )
+  {
+    var str = reader.TokenType switch {
+      JsonTokenType.Null => null,
+      JsonTokenType.String => reader.GetString(),
+      _ => null,
+    };
+
+    if (str is null)
+      return null;
+    if (str.Length == 0)
+      return Array.Empty<byte>();
+    if ((str.Length & 0b1) != 0b0)
+      return null; // length must be 2n
+
+    var result = new byte[str.Length / 2];
+
+    return Hexadecimal.TryDecode(str.AsSpan(), result.AsSpan(), out var length) && length == result.Length
+      ? result
+      : null;
+  }
+
+  public override void Write(
+    Utf8JsonWriter writer,
+    byte[]? value,
+    JsonSerializerOptions options
+  )
+    => throw new NotImplementedException();
+}
diff --git a/src/Smdn.TPSmartHomeDevices.Primitives/Smdn.TPSmartHomeDevices.Primitives.csproj b/src/Smdn.TPSmartHomeDevices.Primitives/Smdn.TPSmartHomeDevices.Primitives.csproj
index 8bc7374..8764b46 100644
--- a/src/Smdn.TPSmartHomeDevices.Primitives/Smdn.TPSmartHomeDevices.Primitives.csproj
+++ b/src/Smdn.TPSmartHomeDevices.Primitives/Smdn.TPSmartHomeDevices.Primitives.csproj
@@ -4,9 +4,9 @@ SPDX-License-Identifier: MIT
 -->
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
-    <TargetFrameworks>netstandard2.0;netstandard2.1;net6.0</TargetFrameworks>
+    <TargetFrameworks>netstandard2.0;netstandard2.1;net6.0;net8.0</TargetFrameworks>
     <VersionPrefix>1.1.0</VersionPrefix>
-    <VersionSuffix>preview1</VersionSuffix>
+    <VersionSuffix>preview2</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>
@@ -39,6 +39,7 @@ This library does not provide any specific implementations to operate Kasa and T
   <ItemGroup>
     <PackageReference Include="System.Text.Json" Version="6.0.0" />
     <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="6.0.0" />
+    <PackageReference Include="Smdn.Fundamental.PrintableEncoding.Hexadecimal" Version="3.0.1" />
   </ItemGroup>
 
   <ItemGroup>
diff --git a/src/Smdn.TPSmartHomeDevices.Primitives/Smdn.TPSmartHomeDevices/IDeviceInfo.cs b/src/Smdn.TPSmartHomeDevices.Primitives/Smdn.TPSmartHomeDevices/IDeviceInfo.cs
new file mode 100644
index 0000000..be028aa
--- /dev/null
+++ b/src/Smdn.TPSmartHomeDevices.Primitives/Smdn.TPSmartHomeDevices/IDeviceInfo.cs
@@ -0,0 +1,26 @@
+// SPDX-FileCopyrightText: 2024 smdn <smdn@smdn.jp>
+// SPDX-License-Identifier: MIT
+using System;
+using System.Net.NetworkInformation;
+
+namespace Smdn.TPSmartHomeDevices;
+
+/// <summary>
+/// Represents smart device information.
+/// </summary>
+public interface IDeviceInfo {
+  /// <summary>Gets the device's ID.</summary>
+  ReadOnlySpan<byte> Id { get; }
+
+  /// <summary>Gets the device's model name.</summary>
+  string? ModelName { get; }
+
+  /// <summary>Gets the string that represents device's firmware version.</summary>
+  string? FirmwareVersion { get; }
+
+  /// <summary>Gets the string that represents device's hardware version.</summary>
+  string? HardwareVersion { get; }
+
+  /// <summary>Gets the device's MAC address.</summary>
+  PhysicalAddress? MacAddress { get; }
+}
diff --git a/src/Smdn.TPSmartHomeDevices.Primitives/Smdn.TPSmartHomeDevices/IMulticolorSmartLight.cs b/src/Smdn.TPSmartHomeDevices.Primitives/Smdn.TPSmartHomeDevices/IMulticolorSmartLight.cs
index 2eab066..4b4f61e 100644
--- a/src/Smdn.TPSmartHomeDevices.Primitives/Smdn.TPSmartHomeDevices/IMulticolorSmartLight.cs
+++ b/src/Smdn.TPSmartHomeDevices.Primitives/Smdn.TPSmartHomeDevices/IMulticolorSmartLight.cs
@@ -9,42 +9,7 @@ namespace Smdn.TPSmartHomeDevices;
 /// <summary>
 /// Provides a mechanism for abstracting the multicolor smart light including smart bulb, smart strip, etc. that can be specified in any one color and its functionality.
 /// </summary>
-public interface IMulticolorSmartLight : ISmartDevice {
-  /// <summary>
-  /// Turns the light on and sets the light brightness.
-  /// </summary>
-  /// <remarks>
-  ///   <para>
-  ///   If the device does not support gradual state transitions, the parameter <paramref name="transitionPeriod"/> is ignored and the new state is set immediately.
-  ///   </para>
-  ///   <para>
-  ///   The device cannot be turned off by setting the <paramref name="brightness"/> to <c>0</c>.
-  ///   Use <see cref="ISmartDevice.SetOnOffStateAsync(bool, CancellationToken)"/> to turn off the device.
-  ///   </para>
-  /// </remarks>
-  /// <param name="brightness">
-  /// The brightness in percent value, in range of 1~100[%].
-  /// </param>
-  /// <param name="transitionPeriod">
-  /// The <see cref="TimeSpan" /> value that indicates the time interval between completion of gradual state transition.
-  /// If the value is <see cref="TimeSpan.Zero"/>, the state transition will be performed immediately rather than gradual change.
-  /// </param>
-  /// <param name="cancellationToken">
-  /// The <see cref="CancellationToken" /> to monitor for cancellation requests.
-  /// The default value is <see langword="default" />.
-  /// </param>
-  /// <exception cref="ArgumentOutOfRangeException">
-  ///   <list type="bullet">
-  ///     <item><description><paramref name="brightness"/> is less than 1 or greater than 100.</description></item>
-  ///     <item><description><paramref name="transitionPeriod"/> is less than <see cref="TimeSpan.Zero"/>.</description></item>
-  ///   </list>
-  /// </exception>
-  ValueTask SetBrightnessAsync(
-    int brightness,
-    TimeSpan transitionPeriod,
-    CancellationToken cancellationToken
-  );
-
+public interface IMulticolorSmartLight : ISmartLight {
   /// <summary>
   /// Turns the light on and sets the light color to the specified color temperature.
   /// </summary>
diff --git a/src/Smdn.TPSmartHomeDevices.Primitives/Smdn.TPSmartHomeDevices/ISmartDevice.cs b/src/Smdn.TPSmartHomeDevices.Primitives/Smdn.TPSmartHomeDevices/ISmartDevice.cs
index cc3aab6..37937c7 100644
--- a/src/Smdn.TPSmartHomeDevices.Primitives/Smdn.TPSmartHomeDevices/ISmartDevice.cs
+++ b/src/Smdn.TPSmartHomeDevices.Primitives/Smdn.TPSmartHomeDevices/ISmartDevice.cs
@@ -56,4 +56,19 @@ public interface ISmartDevice {
   ValueTask<bool> GetOnOffStateAsync(
     CancellationToken cancellationToken
   );
+
+  /// <summary>
+  /// Gets the device information.
+  /// </summary>
+  /// <param name="cancellationToken">
+  /// The <see cref="CancellationToken" /> to monitor for cancellation requests.
+  /// The default value is <see langword="default" />.
+  /// </param>
+  /// <returns>
+  /// A <see cref="ValueTask{IDeviceInfo}"/> representing the result of method.
+  /// </returns>
+  /// <seealso cref="IDeviceInfo"/>
+  ValueTask<IDeviceInfo> GetDeviceInfoAsync(
+    CancellationToken cancellationToken = default
+  );
 }
diff --git a/src/Smdn.TPSmartHomeDevices.Primitives/Smdn.TPSmartHomeDevices/ISmartLight.cs b/src/Smdn.TPSmartHomeDevices.Primitives/Smdn.TPSmartHomeDevices/ISmartLight.cs
new file mode 100644
index 0000000..8099565
--- /dev/null
+++ b/src/Smdn.TPSmartHomeDevices.Primitives/Smdn.TPSmartHomeDevices/ISmartLight.cs
@@ -0,0 +1,47 @@
+// SPDX-FileCopyrightText: 2024 smdn <smdn@smdn.jp>
+// SPDX-License-Identifier: MIT
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Smdn.TPSmartHomeDevices;
+
+/// <summary>
+/// Provides a mechanism for abstracting the smart light without the color toning capability, including smart bulb, smart strip, etc. and its functionality.
+/// </summary>
+public interface ISmartLight : ISmartDevice {
+  /// <summary>
+  /// Turns the light on and sets the light brightness.
+  /// </summary>
+  /// <remarks>
+  ///   <para>
+  ///   If the device does not support gradual state transitions, the parameter <paramref name="transitionPeriod"/> is ignored and the new state is set immediately.
+  ///   </para>
+  ///   <para>
+  ///   The device cannot be turned off by setting the <paramref name="brightness"/> to <c>0</c>.
+  ///   Use <see cref="ISmartDevice.SetOnOffStateAsync(bool, CancellationToken)"/> to turn off the device.
+  ///   </para>
+  /// </remarks>
+  /// <param name="brightness">
+  /// The brightness in percent value, in range of 1~100[%].
+  /// </param>
+  /// <param name="transitionPeriod">
+  /// The <see cref="TimeSpan" /> value that indicates the time interval between completion of gradual state transition.
+  /// If the value is <see cref="TimeSpan.Zero"/>, the state transition will be performed immediately rather than gradual change.
+  /// </param>
+  /// <param name="cancellationToken">
+  /// The <see cref="CancellationToken" /> to monitor for cancellation requests.
+  /// The default value is <see langword="default" />.
+  /// </param>
+  /// <exception cref="ArgumentOutOfRangeException">
+  ///   <list type="bullet">
+  ///     <item><description><paramref name="brightness"/> is less than 1 or greater than 100.</description></item>
+  ///     <item><description><paramref name="transitionPeriod"/> is less than <see cref="TimeSpan.Zero"/>.</description></item>
+  ///   </list>
+  /// </exception>
+  ValueTask SetBrightnessAsync(
+    int brightness,
+    TimeSpan transitionPeriod,
+    CancellationToken cancellationToken
+  );
+}
diff --git a/src/Smdn.TPSmartHomeDevices.Primitives/Smdn.TPSmartHomeDevices/ISmartPlug.cs b/src/Smdn.TPSmartHomeDevices.Primitives/Smdn.TPSmartHomeDevices/ISmartPlug.cs
index 10bebb4..3597cf9 100644
--- a/src/Smdn.TPSmartHomeDevices.Primitives/Smdn.TPSmartHomeDevices/ISmartPlug.cs
+++ b/src/Smdn.TPSmartHomeDevices.Primitives/Smdn.TPSmartHomeDevices/ISmartPlug.cs
@@ -1,9 +1,12 @@
 // SPDX-FileCopyrightText: 2024 smdn <smdn@smdn.jp>
 // SPDX-License-Identifier: MIT
+#if false
 namespace Smdn.TPSmartHomeDevices;
 
 /// <summary>
 /// Provides a mechanism for abstracting the smart plug and its functionality.
 /// </summary>
 public interface ISmartPlug : ISmartDevice {
+  // TODO: define interface members
 }
+#endif

Notes

Full Changelog: releases/Smdn.TPSmartHomeDevices.Primitives-1.1.0-preview1...releases/Smdn.TPSmartHomeDevices.Primitives-1.1.0-preview2