Skip to content

Commit

Permalink
Merge pull request #47 from pyrocumulus/net-batch-status
Browse files Browse the repository at this point in the history
Added methods to for adding Net batch status and Cumulative batch status
  • Loading branch information
pyrocumulus authored Nov 6, 2020
2 parents f411ad3 + 00ab503 commit e63460e
Show file tree
Hide file tree
Showing 11 changed files with 436 additions and 7 deletions.
104 changes: 104 additions & 0 deletions src/PVOutput.Net/Builders/BatchNetStatusPostBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Dawn;
using PVOutput.Net.Objects;
using PVOutput.Net.Objects.Core;
using PVOutput.Net.Objects.Modules;

namespace PVOutput.Net.Builders
{
/// <summary>
/// Builder that creates batch outputs to post to PVOutput.
/// </summary>
public sealed class BatchNetStatusPostBuilder
{
internal BatchNetStatusPost _statusPost { get; set; }

/// <summary>
/// Creates a new builder.
/// </summary>
public BatchNetStatusPostBuilder()
{
_statusPost = new BatchNetStatusPost();
}

/// <summary>
/// Sets the timestamp for the status.
/// </summary>
/// <param name="timestamp">Timestamp.</param>
/// <returns>The builder.</returns>
public BatchNetStatusPostBuilder SetTimeStamp(DateTime timestamp)
{
Guard.Argument(timestamp, nameof(timestamp)).IsNoFutureDate();

_statusPost.Timestamp = timestamp;
return this;
}

/// <summary>
/// Sets the net power exported for the status.
/// </summary>
/// <param name="powerExported">Net power exported consumed.</param>
/// <returns>The builder.</returns>
public BatchNetStatusPostBuilder SetPowerExported(int powerExported)
{
Guard.Argument(powerExported, nameof(powerExported)).Min(0);

_statusPost.PowerExported = powerExported;
return this;
}

/// <summary>
/// Sets the net power imported for the status.
/// </summary>
/// <param name="powerImported">Net power imported consumed.</param>
/// <returns>The builder.</returns>
public BatchNetStatusPostBuilder SetPowerImported(int powerImported)
{
Guard.Argument(powerImported, nameof(powerImported)).Min(0);

_statusPost.PowerImported = powerImported;
return this;
}

/// <summary>
/// Resets the builder to it's default state. Ready to build a new status.
/// </summary>
public void Reset() => _statusPost = new BatchNetStatusPost();

/// <summary>
/// Uses information within the builder to return the built status.
/// </summary>
/// <returns>The status.</returns>
public IBatchNetStatusPost Build()
{
ValidateStatus();
return _statusPost;
}

/// <summary>
/// Uses information within the builder to return the built status.
/// Resets the builder to it's default state after building.
/// </summary>
/// <returns>The status.</returns>
public IBatchNetStatusPost BuildAndReset()
{
IBatchNetStatusPost result = Build();
Reset();
return result;
}

[System.Diagnostics.CodeAnalysis.SuppressMessage("Globalization", "CA1303:Do not pass literals as localized parameters", Justification = "Exception messages are non translatable for now")]
private void ValidateStatus()
{
if (_statusPost.PowerExported == null
&& _statusPost.PowerImported == null)
{
throw new InvalidOperationException("Status has no power values");
}
}
}
}
3 changes: 1 addition & 2 deletions src/PVOutput.Net/Builders/StatusPostBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@ public StatusPostBuilder<TResultType> SetTimeStamp(DateTime timestamp)
Guard.Argument(timestamp, nameof(timestamp)).IsNoFutureDate();

_statusPost.Timestamp = timestamp;
return this;

return this;
}

/// <summary>
Expand Down
45 changes: 45 additions & 0 deletions src/PVOutput.Net/Modules/StatusService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Threading.Tasks;
using Dawn;
using PVOutput.Net.Builders;
using PVOutput.Net.Enums;
using PVOutput.Net.Objects;
using PVOutput.Net.Objects.Core;
using PVOutput.Net.Requests.Handler;
Expand Down Expand Up @@ -141,6 +142,50 @@ public Task<PVOutputArrayResponse<IBatchStatusPostResult>> AddBatchStatusAsync(I
return handler.ExecuteArrayRequestAsync<IBatchStatusPostResult>(new AddBatchStatusRequest() { StatusPosts = statuses }, loggingScope, cancellationToken);
}

/// <summary>
/// Adds multiple statuses to the owned system.
/// <para>See the official <see href="https://pvoutput.org/help.html#api-addbatchstatus">API information</see>.</para>
/// Use the <see cref="StatusPostBuilder{IBatchStatusPost}"/> to create <see cref="IBatchStatusPost"/> objects.
/// </summary>
/// <param name="statuses">The statuses to add.</param>
/// <param name="isCumulative">Sets whether or not the provided data is cumulative.</param>
/// <param name="cancellationToken">A cancellation token for the request.</param>
/// <returns>If the operation succeeded.</returns>
public Task<PVOutputArrayResponse<IBatchStatusPostResult>> AddBatchStatusAsync(IEnumerable<IBatchStatusPost> statuses, bool isCumulative, CancellationToken cancellationToken = default)
{
var loggingScope = new Dictionary<string, object>()
{
[LoggingEvents.RequestId] = LoggingEvents.StatusService_AddBatchStatus,
[LoggingEvents.Parameter_CumulativeType] = isCumulative
};

Guard.Argument(statuses, nameof(statuses)).NotNull().NotEmpty();

var handler = new RequestHandler(Client);
return handler.ExecuteArrayRequestAsync<IBatchStatusPostResult>(new AddBatchStatusRequest() { StatusPosts = statuses, Cumulative = isCumulative }, loggingScope, cancellationToken);
}

/// <summary>
/// Adds multiple statuses to the owned system.
/// <para>See the official <see href="https://pvoutput.org/help.html#api-addbatchstatus">API information</see>.</para>
/// Use the <see cref="StatusPostBuilder{IBatchStatusPost}"/> to create <see cref="IBatchStatusPost"/> objects.
/// </summary>
/// <param name="statuses">The statuses to add.</param>
/// <param name="cancellationToken">A cancellation token for the request.</param>
/// <returns>If the operation succeeded.</returns>
public Task<PVOutputArrayResponse<IBatchStatusPostResult>> AddBatchNetStatusAsync(IEnumerable<IBatchNetStatusPost> statuses, CancellationToken cancellationToken = default)
{
var loggingScope = new Dictionary<string, object>()
{
[LoggingEvents.RequestId] = LoggingEvents.StatusService_AddNetBatchStatus
};

Guard.Argument(statuses, nameof(statuses)).NotNull().NotEmpty();

var handler = new RequestHandler(Client);
return handler.ExecuteArrayRequestAsync<IBatchStatusPostResult>(new AddBatchNetStatusRequest() { StatusPosts = statuses }, loggingScope, cancellationToken);
}

/// <summary>
/// Deletes a status on the specified moment.
/// <para>See the official <see href="https://pvoutput.org/help.html#api-deletestatus">API information</see>.</para>
Expand Down
2 changes: 2 additions & 0 deletions src/PVOutput.Net/Objects/Core/LoggingEvents.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ internal class LoggingEvents
public const string Parameter_ApplicationId = "ApplicationId";
public const string Parameter_CallBackUrl = "CallBackUrl";
public const string Parameter_AlertType = "AlertType";
public const string Parameter_CumulativeType = "CumulativeType";

/*
* RequestHandler base events
Expand Down Expand Up @@ -88,6 +89,7 @@ internal class LoggingEvents
public static readonly EventId StatusService_AddStatus = new EventId(20804, "AddStatus");
public static readonly EventId StatusService_AddBatchStatus = new EventId(20805, "AddBatchStatus");
public static readonly EventId StatusService_DeleteStatus = new EventId(20806, "DeleteStatus");
public static readonly EventId StatusService_AddNetBatchStatus = new EventId(20807, "AddNetBatchStatus");
public static readonly EventId SupplyService_GetSupply = new EventId(20901, "GetSupply");
public static readonly EventId SystemService_GetOwnSystem = new EventId(21001, "GetOwnSystem");
public static readonly EventId SystemService_GetOtherSystem = new EventId(21002, "GetOtherSystem");
Expand Down
25 changes: 25 additions & 0 deletions src/PVOutput.Net/Objects/IBatchNetStatusPost.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using System;

namespace PVOutput.Net.Objects
{
/// <summary>
/// A single net batch status used for posting multiple statuses.
/// </summary>
public interface IBatchNetStatusPost
{
/// <summary>
/// Timestamp for the recorded status.
/// </summary>
DateTime Timestamp { get; set; }

/// <summary>
/// Total energy generated up to and including the timestamp.
/// </summary>
int? PowerExported { get; set; }

/// <summary>
/// Actual power being generated at the moment of the timestamp.
/// </summary>
int? PowerImported { get; set; }
}
}
15 changes: 15 additions & 0 deletions src/PVOutput.Net/Objects/Modules/BatchNetStatusPost.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PVOutput.Net.Objects.Modules
{
internal class BatchNetStatusPost : IBatchNetStatusPost
{
public DateTime Timestamp { get; set; }
public int? PowerExported { get; set; }
public int? PowerImported { get; set; }
}
}
49 changes: 49 additions & 0 deletions src/PVOutput.Net/Requests/Modules/AddBatchNetStatusRequest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using PVOutput.Net.Objects.Core;
using PVOutput.Net.Objects;
using PVOutput.Net.Requests.Base;

namespace PVOutput.Net.Requests.Modules
{
internal class AddBatchNetStatusRequest : PostRequest
{
public IEnumerable<IBatchNetStatusPost> StatusPosts { get; set; }

public override HttpMethod Method => HttpMethod.Post;

public override string UriTemplate => "addbatchstatus.jsp{?n,data}";

public override IDictionary<string, object> GetUriPathParameters() => new Dictionary<string, object>
{
["n"] = 1,
["data"] = FormatStatusPosts()
};

private string FormatStatusPosts()
{
var sb = new StringBuilder();

foreach (IBatchNetStatusPost status in StatusPosts)
{
sb.Append(FormatStatusPost(status)).Append(';');
}

return sb.ToString();
}

internal static string FormatStatusPost(IBatchNetStatusPost status)
{
var sb = new StringBuilder();
sb.Append(FormatHelper.GetDateAsString(status.Timestamp));
sb.Append(',');
sb.Append(FormatHelper.GetTimeAsString(status.Timestamp));
sb.Append(",-1,"); // Skip single field as per documentation
sb.Append(status.PowerExported);
sb.Append(",-1,"); // Skip single field as per documentation
sb.Append(status.PowerImported);
return sb.ToString();
}
}
}
8 changes: 3 additions & 5 deletions src/PVOutput.Net/Requests/Modules/AddBatchStatusRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,16 @@ internal class AddBatchStatusRequest : PostRequest
{
public IEnumerable<IBatchStatusPost> StatusPosts { get; set; }

public bool Net { get; set; }

public CumulativeStatusType Cumulative { get; set; }
public bool Cumulative { get; set; }

public override HttpMethod Method => HttpMethod.Post;

public override string UriTemplate => "addbatchstatus.jsp{?c1,n,data}";

public override IDictionary<string, object> GetUriPathParameters() => new Dictionary<string, object>
{
["c1"] = Cumulative != CumulativeStatusType.None ? (int?)Cumulative : null,
["n"] = Net ? 1 : 0,
["c1"] = Cumulative ? 1 : 0,
["n"] = 0,
["data"] = FormatStatusPosts()
};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using System;
using NUnit.Framework;
using PVOutput.Net.Requests.Modules;
using PVOutput.Net.Objects.Modules.Implementations;
using System.Threading.Tasks;
using PVOutput.Net.Objects;
using PVOutput.Net.Tests.Utils;
using System.Collections.Generic;
using System.Linq;
using RichardSzalay.MockHttp;
using PVOutput.Net.Builders;
using PVOutput.Net.Objects.Modules;

namespace PVOutput.Net.Tests.Modules.Status
{
public class AddBatchNetStatusRequestTests : BaseRequestsTest
{
private string[] GetSplitStatusPostLine(BatchNetStatusPost post) => AddBatchNetStatusRequest.FormatStatusPost(post).Split(',');

[Test]
public void Parameter_Timestamp_CreatesCorrectUriParameters()
{
var post = new BatchNetStatusPost() { Timestamp = new DateTime(2020, 2, 1, 13, 12, 20) };

string[] postArray = GetSplitStatusPostLine(post);
Assert.That(postArray[0], Is.EqualTo("20200201"));
Assert.That(postArray[1], Is.EqualTo("13:12"));
}

[Test]
public void Parameter_PowerExported_CreatesCorrectUriParameters()
{
var post = new BatchNetStatusPost() { PowerExported = 1111 };
string[] postArray = GetSplitStatusPostLine(post);
Assert.That(postArray[3], Is.EqualTo("1111"));
}

[Test]
public void Parameter_PowerImported_CreatesCorrectUriParameters()
{
var post = new BatchNetStatusPost() { PowerImported = 2222 };
string[] postArray = GetSplitStatusPostLine(post);
Assert.That(postArray[5], Is.EqualTo("2222"));
}
}
}
Loading

0 comments on commit e63460e

Please sign in to comment.