-
-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #16 from qJake/http-fix
Fix HTTP bug, add Logbook client
- Loading branch information
Showing
8 changed files
with
349 additions
and
68 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
using HADotNet.Core; | ||
using HADotNet.Core.Clients; | ||
using NUnit.Framework; | ||
using System; | ||
using System.Threading.Tasks; | ||
|
||
namespace Tests | ||
{ | ||
public class LogbookTests | ||
{ | ||
private Uri Instance { get; set; } | ||
private string ApiKey { get; set; } | ||
|
||
[SetUp] | ||
public void Setup() | ||
{ | ||
Instance = new Uri(Environment.GetEnvironmentVariable("HADotNet:Tests:Instance")); | ||
ApiKey = Environment.GetEnvironmentVariable("HADotNet:Tests:ApiKey"); | ||
|
||
ClientFactory.Initialize(Instance, ApiKey); | ||
} | ||
|
||
[Test] | ||
public async Task ShouldRetrieveAllLogbookEntries() | ||
{ | ||
var client = ClientFactory.GetClient<LogbookClient>(); | ||
|
||
var logEntries = await client.GetLogbookEntries(); | ||
|
||
Assert.IsNotNull(logEntries); | ||
Assert.IsNotEmpty(logEntries[0].EntityId); | ||
Assert.AreNotEqual(0, logEntries.Count); | ||
Assert.AreNotEqual(string.Empty, logEntries[0].EntityId); | ||
} | ||
|
||
[Test] | ||
public async Task ShouldRetrieveLogbookEntriesByEntityId() | ||
{ | ||
var client = ClientFactory.GetClient<LogbookClient>(); | ||
|
||
var history = await client.GetLogbookEntries("light.jakes_office"); | ||
|
||
Assert.IsNotNull(history); | ||
Assert.IsNotEmpty(history.EntityId); | ||
} | ||
|
||
[Test] | ||
public async Task ShouldRetrieveLogbookEntriesByStartDate() | ||
{ | ||
var client = ClientFactory.GetClient<LogbookClient>(); | ||
|
||
var logEntries = await client.GetLogbookEntries(DateTimeOffset.Now.Subtract(TimeSpan.FromDays(2))); | ||
|
||
Assert.IsNotNull(logEntries); | ||
Assert.IsNotEmpty(logEntries[0].EntityId); | ||
Assert.AreNotEqual(0, logEntries.Count); | ||
Assert.AreNotEqual(string.Empty, logEntries[0].EntityId); | ||
} | ||
|
||
[Test] | ||
public async Task ShouldRetrieveLogbookEntriesByStartAndEndDate() | ||
{ | ||
var client = ClientFactory.GetClient<LogbookClient>(); | ||
|
||
var logEntries = await client.GetLogbookEntries(DateTimeOffset.Now.Subtract(TimeSpan.FromDays(2)), DateTimeOffset.Now.Subtract(new TimeSpan(1, 12, 0, 0))); | ||
|
||
Assert.IsNotNull(logEntries); | ||
Assert.IsNotEmpty(logEntries[0].EntityId); | ||
Assert.AreNotEqual(0, logEntries.Count); | ||
Assert.AreNotEqual(string.Empty, logEntries[0].EntityId); | ||
} | ||
|
||
[Test] | ||
public async Task ShouldRetrieveLogbookEntriesByStartDateAndDuration() | ||
{ | ||
var client = ClientFactory.GetClient<LogbookClient>(); | ||
|
||
var logEntries = await client.GetLogbookEntries(DateTimeOffset.Now.Subtract(TimeSpan.FromDays(2)), TimeSpan.FromHours(18)); | ||
|
||
Assert.IsNotNull(logEntries); | ||
Assert.IsNotEmpty(logEntries[0].EntityId); | ||
Assert.AreNotEqual(0, logEntries.Count); | ||
Assert.AreNotEqual(string.Empty, logEntries[0].EntityId); | ||
} | ||
|
||
[Test] | ||
public async Task ShouldRetrieveLogbookEntriesByStartAndEndDateAndEntityId() | ||
{ | ||
var client = ClientFactory.GetClient<LogbookClient>(); | ||
|
||
var history = await client.GetLogbookEntries("group.family_room_lights", DateTimeOffset.Now.Subtract(TimeSpan.FromDays(2)), DateTimeOffset.Now.Subtract(new TimeSpan(1, 12, 0, 0))); | ||
|
||
Assert.IsNotNull(history); | ||
Assert.IsNotEmpty(history.EntityId); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
using HADotNet.Core.Models; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
|
||
namespace HADotNet.Core.Clients | ||
{ | ||
/// <summary> | ||
/// Provides access to the Logbook API for retrieving and querying for change events. | ||
/// </summary> | ||
public sealed class LogbookClient : BaseClient | ||
{ | ||
/// <summary> | ||
/// Initializes a new instance of the <see cref="LogbookClient" />. | ||
/// </summary> | ||
/// <param name="instance">The Home Assistant base instance URL.</param> | ||
/// <param name="apiKey">The Home Assistant long-lived access token.</param> | ||
public LogbookClient(Uri instance, string apiKey) : base(instance, apiKey) { } | ||
|
||
/// <summary> | ||
/// Retrieves a list of ALL logbook states for all entities for the past 1 day. | ||
/// </summary> | ||
/// <returns>A <see cref="List{LogbookObject}"/> representing a 24-hour history snapshot for all entities.</returns> | ||
public async Task<List<LogbookObject>> GetLogbookEntries() => await Get<List<LogbookObject>>("/api/logbook"); | ||
|
||
/// <summary> | ||
/// Retrieves a list of ALL historical states for all entities for the specified day (<paramref name="startDate" /> + 24 hours). WARNING: On larger HA installs, this can return 300+ entities, over 4 MB of data, and take 20+ seconds. | ||
/// </summary> | ||
/// <returns>A <see cref="List{LogbookObject}"/> representing a 24-hour history snapshot starting from <paramref name="startDate" /> for all entities.</returns> | ||
public async Task<List<LogbookObject>> GetLogbookEntries(DateTimeOffset startDate) => await Get<List<LogbookObject>>($"/api/logbook/{startDate.UtcDateTime:yyyy-MM-dd\\THH:mm:ss\\+00\\:00}"); | ||
|
||
/// <summary> | ||
/// Retrieves a list of ALL historical states for all entities for the specified time range, from <paramref name="startDate" /> to <paramref name="endDate" />. WARNING: On larger HA installs, for multiple days, this can return A LOT of data and potentially take a LONG time to return. Use with caution! | ||
/// </summary> | ||
/// <returns>A <see cref="List{LogbookObject}"/> representing a 24-hour history snapshot, from <paramref name="startDate" /> to <paramref name="endDate" />, for all entities.</returns> | ||
public async Task<List<LogbookObject>> GetLogbookEntries(DateTimeOffset startDate, DateTimeOffset endDate) => await Get<List<LogbookObject>>($"/api/logbook/{startDate.UtcDateTime:yyyy-MM-dd\\THH:mm:ss\\+00\\:00}?end_time={Uri.EscapeDataString(endDate.UtcDateTime.ToString("yyyy-MM-dd\\THH:mm:ss\\+00\\:00"))}"); | ||
|
||
/// <summary> | ||
/// Retrieves a list of ALL historical states for all entities for the specified time range, from <paramref name="startDate" />, for the specified <paramref name="duration" />. WARNING: On larger HA installs, for multiple days, this can return A LOT of data and potentially take a LONG time to return. Use with caution! | ||
/// </summary> | ||
/// <returns>A <see cref="List{LogbookObject}"/> representing a 24-hour history snapshot, from <paramref name="startDate" />, for the specified <paramref name="duration" />, for all entities.</returns> | ||
public async Task<List<LogbookObject>> GetLogbookEntries(DateTimeOffset startDate, TimeSpan duration) => await GetLogbookEntries(startDate, startDate.Add(duration)); | ||
|
||
/// <summary> | ||
/// Retrieves a list of historical states for the specified <paramref name="entityId" /> for the specified time range, from <paramref name="startDate" /> to <paramref name="endDate" />. | ||
/// </summary> | ||
/// <param name="entityId">The entity ID to filter on.</param> | ||
/// <param name="startDate">The earliest history entry to retrieve.</param> | ||
/// <param name="endDate">The most recent history entry to retrieve.</param> | ||
/// <returns>A <see cref="LogbookObject"/> of history snapshots for the specified <paramref name="entityId" />, from <paramref name="startDate" /> to <paramref name="endDate" />.</returns> | ||
public async Task<LogbookObject> GetLogbookEntries(string entityId, DateTimeOffset startDate, DateTimeOffset endDate) => (await Get<List<LogbookObject>>($"/api/logbook/{startDate.UtcDateTime:yyyy-MM-dd\\THH:mm:ss\\+00\\:00}?entity={entityId}&end_time={Uri.EscapeDataString(endDate.UtcDateTime.ToString("yyyy-MM-dd\\THH:mm:ss\\+00\\:00"))}")).First(); | ||
|
||
/// <summary> | ||
/// Retrieves a list of historical states for the specified <paramref name="entityId" /> for the past 1 day. | ||
/// </summary> | ||
/// <param name="entityId">The entity ID to retrieve state history for.</param> | ||
/// <returns>A <see cref="LogbookObject"/> representing a 24-hour history snapshot for the specified <paramref name="entityId" />.</returns> | ||
public async Task<LogbookObject> GetLogbookEntries(string entityId) => (await Get<List<LogbookObject>>($"/api/logbook?entity={entityId}")).First(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
using Newtonsoft.Json; | ||
using System; | ||
|
||
namespace HADotNet.Core.Models | ||
{ | ||
/// <summary> | ||
/// Represents a logbook entry object. The only consistently available properties are <see cref="Timestamp" />, <see cref="Name" />, and <see cref="EntityId" />. | ||
/// </summary> | ||
public class LogbookObject | ||
{ | ||
/// <summary> | ||
/// Gets or sets the entity ID for this entry. | ||
/// </summary> | ||
[JsonProperty("entity_id")] | ||
public string EntityId { get; set; } | ||
|
||
/// <summary> | ||
/// Gets or sets the domain. | ||
/// </summary> | ||
[JsonProperty("domain")] | ||
public string Domain { get; set; } | ||
|
||
/// <summary> | ||
/// Gets or sets the context user ID associated with this entry. | ||
/// </summary> | ||
[JsonProperty("context_user_id")] | ||
public string ContextUserId { get; set; } | ||
|
||
/// <summary> | ||
/// Gets or sets the context entity ID associated with this entry. (For example, which automation triggered this change?) | ||
/// </summary> | ||
[JsonProperty("context_entity_id")] | ||
public string ContextEntityId { get; set; } | ||
|
||
/// <summary> | ||
/// Gets or sets the friendly name for the <see cref="ContextEntityId" />. This is sometimes the same as <see cref="ContextName" />. | ||
/// </summary> | ||
[JsonProperty("context_entity_id_name")] | ||
public string ContextEntityIdName { get; set; } | ||
|
||
/// <summary> | ||
/// Gets or sets the type of associated change, for example, if an automation triggered this event, the value is 'automation_triggered'. | ||
/// </summary> | ||
[JsonProperty("context_event_type")] | ||
public string ContextEventType { get; set; } | ||
|
||
/// <summary> | ||
/// Gets or sets the domain associated with the context entity. For example, if an automation triggered this change, the value is 'automation'. | ||
/// </summary> | ||
[JsonProperty("context_domain")] | ||
public string ContextDomain { get; set; } | ||
|
||
/// <summary> | ||
/// Gets or sets the name associated with the context entity (e.g. the name of the automation). This is sometimes the same as <see cref="ContextEntityIdName" />. | ||
/// </summary> | ||
[JsonProperty("context_name")] | ||
public string ContextName { get; set; } | ||
|
||
/// <summary> | ||
/// Gets or sets the new state that the entity transitioned to. | ||
/// </summary> | ||
[JsonProperty("state")] | ||
public string State { get; set; } | ||
|
||
/// <summary> | ||
/// Gets or sets the source for this logbook entry (i.e. what triggered this change). | ||
/// </summary> | ||
[JsonProperty("source")] | ||
public string Source { get; set; } | ||
|
||
/// <summary> | ||
/// Gets or sets the message, a brief description of what happened. | ||
/// </summary> | ||
[JsonProperty("message")] | ||
public string Message { get; set; } | ||
|
||
/// <summary> | ||
/// Gets or sets the category name for this entry. | ||
/// </summary> | ||
[JsonProperty("name")] | ||
public string Name { get; set; } | ||
|
||
/// <summary> | ||
/// Gets or sets the timestmap when this entry occurred.. | ||
/// </summary> | ||
[JsonProperty("when")] | ||
public DateTimeOffset Timestamp { get; set; } | ||
} | ||
} |
Oops, something went wrong.