diff --git a/HADotNet.Core.Tests/HADotNet.Core.Tests.csproj b/HADotNet.Core.Tests/HADotNet.Core.Tests.csproj
index 458e4a2..96099c0 100644
--- a/HADotNet.Core.Tests/HADotNet.Core.Tests.csproj
+++ b/HADotNet.Core.Tests/HADotNet.Core.Tests.csproj
@@ -5,6 +5,10 @@
false
+
+ TRACE
+
+
diff --git a/HADotNet.Core.Tests/InfoTests.cs b/HADotNet.Core.Tests/InfoTests.cs
index 632208b..ba1a613 100644
--- a/HADotNet.Core.Tests/InfoTests.cs
+++ b/HADotNet.Core.Tests/InfoTests.cs
@@ -1,10 +1,18 @@
using System;
using System.Threading.Tasks;
using HADotNet.Core.Clients;
+using HADotNet.Core.Domain;
using NUnit.Framework;
namespace HADotNet.Core.Tests
{
+ ///
+ /// Tests for the Supervisor Info endpoints.
+ ///
+ ///
+ /// NOTE: If you want to test against a non-Supervisor instance, you'll need to set
+ /// the compilation symbol TEST_ENV_HA_CORE which will test for the correct exception.
+ ///
public class InfoTests
{
private Uri Instance { get; set; }
@@ -22,25 +30,33 @@ public void Setup()
[Test]
public async Task ShouldRetrieveSupervisorInfo()
{
- var client = ClientFactory.GetClient();
-
+ var client = ClientFactory.GetClient();
+
+#if TEST_ENV_HA_CORE
+ Assert.ThrowsAsync(async () => await client.GetSupervisorInfo());
+#else
var info = await client.GetSupervisorInfo();
Assert.AreEqual("ok", info.Result);
Assert.IsNotNull(info.Data);
Assert.IsNotNull(info.Data.Version);
+#endif
}
[Test]
public async Task ShouldRetrieveHostInfo()
{
- var client = ClientFactory.GetClient();
-
+ var client = ClientFactory.GetClient();
+
+#if TEST_ENV_HA_CORE
+ Assert.ThrowsAsync(async () => await client.GetHostInfo());
+#else
var info = await client.GetHostInfo();
Assert.AreEqual("ok", info.Result);
Assert.IsNotNull(info.Data);
Assert.IsNotNull(info.Data.OperatingSystem);
+#endif
}
[Test]
@@ -48,11 +64,15 @@ public async Task ShouldRetrieveCoreInfo()
{
var client = ClientFactory.GetClient();
+#if TEST_ENV_HA_CORE
+ Assert.ThrowsAsync(async () => await client.GetCoreInfo());
+#else
var info = await client.GetCoreInfo();
Assert.AreEqual("ok", info.Result);
Assert.IsNotNull(info.Data);
Assert.IsNotNull(info.Data.Version);
+#endif
}
}
}
diff --git a/HADotNet.Core/BaseClient.cs b/HADotNet.Core/BaseClient.cs
index a9182ef..c84be87 100644
--- a/HADotNet.Core/BaseClient.cs
+++ b/HADotNet.Core/BaseClient.cs
@@ -1,6 +1,7 @@
using System;
using System.Net;
using System.Threading.Tasks;
+using HADotNet.Core.Domain;
using Newtonsoft.Json;
using RestSharp;
@@ -55,7 +56,7 @@ protected async Task Get(string path) where T : class
return JsonConvert.DeserializeObject(resp.Content);
}
- throw new Exception($"Unexpected response code {(int)resp.StatusCode} from Home Assistant API endpoint {path}.");
+ throw new HttpResponseException((int)resp.StatusCode, resp.ResponseStatus.ToString(), resp.ResponseUri.PathAndQuery, $"Unexpected GET response code {(int)resp.StatusCode} from Home Assistant API endpoint {path}.");
}
///
@@ -98,7 +99,7 @@ protected async Task Post(string path, object body, bool isRawBody = false
return JsonConvert.DeserializeObject(resp.Content);
}
- throw new Exception($"Unexpected response code {(int)resp.StatusCode} from Home Assistant API endpoint {path}.");
+ throw new HttpResponseException((int)resp.StatusCode, resp.ResponseStatus.ToString(), resp.ResponseUri.PathAndQuery, $"Unexpected POST response code {(int)resp.StatusCode} from Home Assistant API endpoint {path}.");
}
///
@@ -128,7 +129,7 @@ protected async Task Delete(string path) where T : class
return JsonConvert.DeserializeObject(resp.Content);
}
- throw new Exception($"Unexpected response code {(int)resp.StatusCode} from Home Assistant API endpoint {path}.");
+ throw new HttpResponseException((int)resp.StatusCode, resp.ResponseStatus.ToString(), resp.ResponseUri.PathAndQuery, $"Unexpected DELETE response code {(int)resp.StatusCode} from Home Assistant API endpoint {path}.");
}
///
@@ -147,7 +148,7 @@ protected async Task Delete(string path)
if (!(resp.StatusCode == HttpStatusCode.OK || resp.StatusCode == HttpStatusCode.NoContent))
{
- throw new Exception($"Unexpected response code {(int)resp.StatusCode} from Home Assistant API endpoint {path}.");
+ throw new HttpResponseException((int)resp.StatusCode, resp.ResponseStatus.ToString(), resp.ResponseUri.PathAndQuery, $"Unexpected DELETE response code {(int)resp.StatusCode} from Home Assistant API endpoint {path}.");
}
}
}
diff --git a/HADotNet.Core/Clients/InfoClient.cs b/HADotNet.Core/Clients/InfoClient.cs
index 1812f18..d274676 100644
--- a/HADotNet.Core/Clients/InfoClient.cs
+++ b/HADotNet.Core/Clients/InfoClient.cs
@@ -1,5 +1,6 @@
using System;
using System.Threading.Tasks;
+using HADotNet.Core.Domain;
using HADotNet.Core.Models;
namespace HADotNet.Core.Clients
@@ -20,18 +21,48 @@ public InfoClient(Uri instance, string apiKey) : base(instance, apiKey) { }
/// Retrieves Supervisor information.
///
/// A representing Supervisor informatio.
- public async Task> GetSupervisorInfo() => await Get>("/api/hassio/supervisor/info");
+ public async Task> GetSupervisorInfo()
+ {
+ try
+ {
+ return await Get>("/api/hassio/supervisor/info");
+ }
+ catch (HttpResponseException hrex) when (hrex.StatusCode == 404)
+ {
+ throw new SupervisorNotFoundException("This does not appear to be a Home Assistant Supervisor instance. See inner exception for more details.", hrex);
+ }
+ }
///
/// Retrieves Host information.
///
/// A representing Host informatio.
- public async Task> GetHostInfo() => await Get>("/api/hassio/host/info");
+ public async Task> GetHostInfo()
+ {
+ try
+ {
+ return await Get>("/api/hassio/host/info");
+ }
+ catch (HttpResponseException hrex) when (hrex.StatusCode == 404)
+ {
+ throw new SupervisorNotFoundException("This does not appear to be a Home Assistant Supervisor instance. See inner exception for more details.", hrex);
+ }
+ }
///
/// Retrieves Core information.
///
/// A representing Host informatio.
- public async Task> GetCoreInfo() => await Get>("/api/hassio/core/info");
+ public async Task> GetCoreInfo()
+ {
+ try
+ {
+ return await Get>("/api/hassio/core/info");
+ }
+ catch (HttpResponseException hrex) when (hrex.StatusCode == 404)
+ {
+ throw new SupervisorNotFoundException("This does not appear to be a Home Assistant Supervisor instance. See inner exception for more details.", hrex);
+ }
+ }
}
}
diff --git a/HADotNet.Core/Domain/HttpResponseException.cs b/HADotNet.Core/Domain/HttpResponseException.cs
new file mode 100644
index 0000000..2811033
--- /dev/null
+++ b/HADotNet.Core/Domain/HttpResponseException.cs
@@ -0,0 +1,63 @@
+using System;
+
+namespace HADotNet.Core.Domain
+{
+ ///
+ /// Represents a failed HTTP call to a Home Assistant endpoint.
+ ///
+ public class HttpResponseException : Exception
+ {
+ ///
+ /// Gets the status code for the HTTP response.
+ ///
+ public int StatusCode { get; }
+
+ ///
+ /// Gets the network description, if the error was at the network level.
+ ///
+ public string NetworkDescription { get; }
+
+ ///
+ /// Gets the original request path.
+ ///
+ public string RequestPath { get; }
+
+ ///
+ /// Gets the error response body.
+ ///
+ public string ResponseBody { get; }
+
+ ///
+ /// Initializes a new HttpResponseException.
+ ///
+ public HttpResponseException(int statusCode, string networkDescription, string requestPath, string responseBody)
+ {
+ StatusCode = statusCode;
+ NetworkDescription = networkDescription;
+ RequestPath = requestPath;
+ ResponseBody = responseBody;
+ }
+
+ ///
+ /// Initializes a new HttpResponseException.
+ ///
+ public HttpResponseException(int statusCode, string networkDescription, string requestPath, string responseBody, string message) : base(message)
+ {
+ StatusCode = statusCode;
+ NetworkDescription = networkDescription;
+ RequestPath = requestPath;
+ ResponseBody = responseBody;
+ }
+
+ ///
+ /// Initializes a new HttpResponseException.
+ ///
+ public HttpResponseException(int statusCode, string networkDescription, string requestPath, string responseBody, string message, Exception innerException) : base(message, innerException)
+ {
+ StatusCode = statusCode;
+ NetworkDescription = networkDescription;
+ RequestPath = requestPath;
+ ResponseBody = responseBody;
+ }
+ }
+}
diff --git a/HADotNet.Core/Domain/SupervisorNotFoundException.cs b/HADotNet.Core/Domain/SupervisorNotFoundException.cs
new file mode 100644
index 0000000..21c6af6
--- /dev/null
+++ b/HADotNet.Core/Domain/SupervisorNotFoundException.cs
@@ -0,0 +1,31 @@
+using System;
+
+namespace HADotNet.Core.Domain
+{
+ ///
+ /// The exception that occurs when a Supervisor-only API call is made to a non-Supervisor environment.
+ ///
+ public class SupervisorNotFoundException : Exception
+ {
+ ///
+ /// Initializes a new instance of the SupervisorNotFoundException.
+ ///
+ public SupervisorNotFoundException()
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the SupervisorNotFoundException.
+ ///
+ public SupervisorNotFoundException(string message) : base(message)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the SupervisorNotFoundException.
+ ///
+ public SupervisorNotFoundException(string message, Exception innerException) : base(message, innerException)
+ {
+ }
+ }
+}
diff --git a/HADotNet.Core/HADotNet.Core.csproj b/HADotNet.Core/HADotNet.Core.csproj
index 39d97bd..2609c95 100644
--- a/HADotNet.Core/HADotNet.Core.csproj
+++ b/HADotNet.Core/HADotNet.Core.csproj
@@ -12,15 +12,15 @@
home-assistant external api library
HADotNet Core Library
true
- 1.4.1
+ 1.5.0
Apache-2.0
https://github.com/qJake/HADotNet
https://github.com/qJake/HADotNet.git
git
7.3
- 1.4.1.0
- 1.4.1.0
+ 1.5.0.0
+ 1.5.0.0
diff --git a/HADotNet.Core/Models/AddonObject.cs b/HADotNet.Core/Models/AddonObject.cs
index ff89ef4..beb56f6 100644
--- a/HADotNet.Core/Models/AddonObject.cs
+++ b/HADotNet.Core/Models/AddonObject.cs
@@ -14,13 +14,13 @@ public class AddonObject
public string Description { get; set; }
///
- /// True
if icon is available, otherwise False
.
+ /// True if icon is available, otherwise False.
///
[JsonProperty("icon")]
public bool Icon { get; set; }
///
- /// True
if logo is available, otherwise False
.
+ /// True if logo is available, otherwise False.
///
[JsonProperty("logo")]
public bool Logo { get; set; }
@@ -50,7 +50,7 @@ public class AddonObject
public string State { get; set; }
///
- /// True
if update is available, otherwise False
.
+ /// True if update is available, otherwise False.
///
[JsonProperty("update_available")]
public bool UpdateAvailable { get; set; }
diff --git a/HADotNet.Core/Models/HostInfoObject.cs b/HADotNet.Core/Models/HostInfoObject.cs
index 1f4d125..648ef00 100644
--- a/HADotNet.Core/Models/HostInfoObject.cs
+++ b/HADotNet.Core/Models/HostInfoObject.cs
@@ -9,43 +9,43 @@ namespace HADotNet.Core.Models
public class HostInfoObject
{
///
- /// Gets or sets the chassis.
+ /// Gets or sets the chassis type.
///
[JsonProperty("chassis")]
public string Chassis { get; set; }
///
- /// Gets or sets the CPE.
+ /// Gets or sets the CPE string.
///
[JsonProperty("cpe")]
public string Cpe { get; set; }
///
- /// Gets or sets the deployment.
+ /// Gets or sets the deployment type (e.g. production).
///
[JsonProperty("deployment")]
public string Deployment { get; set; }
///
- /// Gets or sets the disk free.
+ /// Gets or sets the disk free, expressed in GB.
///
[JsonProperty("disk_free")]
public double DiskFree { get; set; }
///
- /// Gets or sets the disk total.
+ /// Gets or sets the disk total, expressed in GB.
///
[JsonProperty("disk_total")]
public double DiskTotal { get; set; }
///
- /// Gets or sets the disk used.
+ /// Gets or sets the disk used, expressed in GB.
///
[JsonProperty("disk_used")]
public double DiskUsed { get; set; }
///
- /// Gets or sets the features.
+ /// Gets or sets the feature list.
///
[JsonProperty("features")]
public IList Features { get; set; }
@@ -57,7 +57,7 @@ public class HostInfoObject
public string Hostname { get; set; }
///
- /// Gets or sets the kernel.
+ /// Gets or sets the kernel version.
///
[JsonProperty("kernel")]
public string Kernel { get; set; }
diff --git a/README.md b/README.md
index 321ab7e..9af1626 100644
--- a/README.md
+++ b/README.md
@@ -26,6 +26,7 @@ A simple, straighforward .NET Standard library for the [Home Assistant](https://
* Logbook API
* Services API
* States API
+* Supervisor API (Supervisor-based installations only)
* Template API
## Getting Started