Skip to content

Commit

Permalink
Merge remote-tracking branch 'refs/remotes/origin/hotfix/certificates…
Browse files Browse the repository at this point in the history
…' into hotfix/certificates
  • Loading branch information
cristipogacean committed May 8, 2020
2 parents b6bbc48 + 08a2dc4 commit 214c819
Show file tree
Hide file tree
Showing 8 changed files with 233 additions and 38 deletions.
7 changes: 7 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@ tab_width = 4
end_of_line = crlf
insert_final_newline = false

# JSON files, shell scripts
[*.json, *.sh]

# New line preferences
end_of_line = lf
insert_final_newline = true

#### .NET Coding Conventions ####

# Organize usings
Expand Down
37 changes: 37 additions & 0 deletions samples/src/Microsoft.Azure.IIoT.App/src/Models/ListNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
// ------------------------------------------------------------

namespace Microsoft.Azure.IIoT.App.Services {
using System;
using Microsoft.Azure.IIoT.OpcUa.Api.Core.Models;
using Microsoft.Azure.IIoT.OpcUa.Api.Publisher.Models;
using System.Collections.Generic;
Expand Down Expand Up @@ -34,5 +35,41 @@ public ListNode() {
public PublishedItemApiModel PublishedItem { get; set; }

public bool Publishing { get; set; }

/// <summary>
/// PublishingInterval
/// </summary>
public string RequestedPublishingInterval {
get => (PublishedItem?.PublishingInterval ?? TimeSpan.MinValue)
== TimeSpan.MinValue ?
null : PublishedItem.PublishingInterval.Value.TotalMilliseconds.ToString();
set {
PublishedItem.PublishingInterval = string.IsNullOrWhiteSpace(value) ? TimeSpan.MinValue : TimeSpan.FromMilliseconds(Convert.ToDouble(value));
}
}

/// <summary>
/// SamplingInterval
/// </summary>
public string RequestedSamplingInterval {
get => (PublishedItem?.SamplingInterval ?? TimeSpan.MinValue)
== TimeSpan.MinValue ?
null : PublishedItem.SamplingInterval.Value.TotalMilliseconds.ToString();
set {
PublishedItem.SamplingInterval = string.IsNullOrWhiteSpace(value) ? TimeSpan.MinValue : TimeSpan.FromMilliseconds(Convert.ToDouble(value));
}
}

/// <summary>
/// HeartbeatInterval
/// </summary>
public string RequestedHeartbeatInterval {
get => (PublishedItem?.HeartbeatInterval ?? TimeSpan.MinValue)
== TimeSpan.MinValue ?
null : PublishedItem.HeartbeatInterval.Value.TotalSeconds.ToString();
set {
PublishedItem.HeartbeatInterval = string.IsNullOrWhiteSpace(value) ? TimeSpan.MinValue : TimeSpan.FromSeconds(Convert.ToDouble(value));
}
}
}
}
128 changes: 98 additions & 30 deletions samples/src/Microsoft.Azure.IIoT.App/src/Pages/Browser.razor
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
<th>Node Type</th>
<th>Value</th>
<th>Publishing</th>
<th>Publishing Config</th>
<th>
@if (PagedNodeList.Results.Count > 0)
{
Expand Down Expand Up @@ -115,6 +116,7 @@
else if (node.NodeClass == NodeClass.Method)
{
<td>
@{_drawerType = drawer.Action;}
<a href="javascript: void(0)" @onclick="@(() => OpenDrawer(node))">
@node.NodeClass
</a>
Expand Down Expand Up @@ -150,16 +152,36 @@
@if (node.NodeClass == NodeClass.Variable)
{
<td>
<input type="checkbox" checked=@node.Publishing @onchange="@((EventArgs) => SetPublishing(EndpointId, node, EventArgs))" />
<a href="javascript: void(0)" @onclick="@(() => OpenDrawer(node))">
@{string output = (node.Publishing == true && node.PublishedItem != null) ? $"On, sampling {node.PublishedItem?.SamplingInterval.Value.TotalMilliseconds} ms" : "Off";}
@output
</a>
<input type="checkbox" checked=@node.Publishing @onchange="@((EventArgs) => SetPublishingAsync(EndpointId, node, EventArgs))" />
@{string output = (node.Publishing == true) ? "On" : "Off";}
@output
</td>
<td>
@{_drawerType = drawer.Publisher;}
@if (node.Publishing == true && node.PublishedItem != null)
{
<label>Sampling:</label><a href="javascript: void(0)" @onclick="@(() => OpenDrawer(node))">
@(node.PublishedItem.SamplingInterval?.TotalMilliseconds.ToString() ?? "1000") ms<br />
</a>
<label>Publishing: </label><a href="javascript: void(0)" @onclick="@(() => OpenDrawer(node))">
@(node.PublishedItem.PublishingInterval?.TotalMilliseconds.ToString() ?? "1000") ms<br />
</a>
<label>HeartBeat: </label><a href="jpavascript: void(0)" @onclick="@(() => OpenDrawer(node))">
@(node.PublishedItem.HeartbeatInterval == null ? "-" : node.PublishedItem.HeartbeatInterval?.TotalSeconds.ToString() + " sec")
<br />
</a>
}
else
{
<label>N/A</label>
}

</td>
}
else
{
<td>N/A</td>
<td>N/A</td>
}
</tr>
}
Expand All @@ -170,7 +192,14 @@
<ErrorMessage PageError="@PagedNodeList.Error" Status="@null"></ErrorMessage>

<Drawer HeaderText="Select Action" ObjectData="@NodeData" IsOpened="@IsOpened" CloseDrawer="@(() => CloseDrawer())">
<_DrawerActionContent NodeData="@NodeData" EndpointId="@EndpointId" PagedNodeList="@PagedNodeList" Credential="@Credential"></_DrawerActionContent>
@if (_drawerType == drawer.Action)
{
<_DrawerActionContent NodeData="@NodeData" EndpointId="@EndpointId" PagedNodeList="@PagedNodeList" Credential="@Credential"></_DrawerActionContent>
}
else
{
<_DrawerPublisherContent NodeData="@NodeData" Onclick="((NodeData) => ClickHandler((ListNode)NodeData))"></_DrawerPublisherContent>
}
</Drawer>

<Pager Result=@NodeList PageChanged=@(async(Page) => await PagerPageChanged(Page)) />
Expand Down Expand Up @@ -204,6 +233,12 @@
private string _tableView = "visible";
private string _tableEmpty = "displayNone";
private List<string> _parentId { get; set; }
private enum drawer
{
Action = 0,
Publisher
}
private drawer _drawerType { get; set; }


/// <summary>
Expand Down Expand Up @@ -332,41 +367,65 @@
CommonHelper.Spinner = "";
}

/// <summary>
/// Manage Publishing a node
/// </summary>
/// <param name="endpointId"></param>
/// <param name="node"></param>
private async Task SetPublishingAsync(string endpointId, ListNode node, ChangeEventArgs ev)
{
if ((bool)ev?.Value)
{
await PublishNodeAsync(endpointId, node);
}
else
{
await UnPublishNodeAsync(endpointId, node);
}
}

/// <summary>
/// Publish a node
/// </summary>
/// <param name="endpointId"></param>
/// <param name="node"></param>
private async Task SetPublishing(string endpointId, ListNode node, ChangeEventArgs ev)
private async Task PublishNodeAsync(string endpointId, ListNode node)
{
if ((bool)ev.Value)
node.Publishing = true;
var publishingInterval = node.PublishedItem?.PublishingInterval == null ? TimeSpan.FromMilliseconds(1000) : node.PublishedItem.PublishingInterval;
var samplingInterval = node.PublishedItem?.SamplingInterval == null ? TimeSpan.FromMilliseconds(1000) : node.PublishedItem.SamplingInterval;
var heartbeatInterval = node.PublishedItem?.HeartbeatInterval;
var result = await Publisher.StartPublishingAsync(endpointId, node.Id, node.NodeName, samplingInterval, publishingInterval, heartbeatInterval, Credential);
if (result)
{
var result = await Publisher.StartPublishingAsync(endpointId, node.Id, node.NodeName, 1000, 1000, Credential);
if (result)
node.PublishedItem = new OpcUa.Api.Publisher.Models.PublishedItemApiModel()
{
node.PublishedItem = new OpcUa.Api.Publisher.Models.PublishedItemApiModel()
{
NodeId = node.Id,
DisplayName = node.NodeName,
PublishingInterval = TimeSpan.FromMilliseconds(1000),
SamplingInterval = TimeSpan.FromMilliseconds(1000)
};
node.Publishing = true;
}
else
{
node.PublishedItem = null;
node.Publishing = false;
}
NodeId = node.Id,
DisplayName = node.NodeName,
PublishingInterval = publishingInterval,
SamplingInterval = samplingInterval,
HeartbeatInterval = heartbeatInterval
};
}
else
{
var result = await Publisher.StopPublishingAsync(endpointId, node.Id, Credential);
if (result)
{
node.PublishedItem = null;
node.Publishing = false;
}
node.PublishedItem = null;
node.Publishing = false;
}
}

/// <summary>
/// UnPublish a node
/// </summary>
/// <param name="endpointId"></param>
/// <param name="node"></param>
private async Task UnPublishNodeAsync(string endpointId, ListNode node)
{
var result = await Publisher.StopPublishingAsync(endpointId, node.Id, Credential);
if (result)
{
node.PublishedItem = null;
node.Publishing = false;
}
}

Expand Down Expand Up @@ -409,6 +468,15 @@
return Task.CompletedTask;
}

/// <summary>
/// ClickHandler
/// </summary>
async Task ClickHandler(ListNode node)
{
CloseDrawer();
await PublishNodeAsync(EndpointId, node);
}

/// <summary>
/// Dispose
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
<th>Security Policy</th>
<th>Security Level</th>
<th>Endpoint State</th>
<th>Toggle Endpoint</th>
<th>Activation Status</th>
<th> </th>
<th>
Expand Down Expand Up @@ -77,7 +78,8 @@
<td>@endpoint.EndpointModel.Registration.Endpoint.Url</td>
}
<td>@endpoint.EndpointModel.Registration.Endpoint.SecurityMode</td>
<td>@endpoint.EndpointModel.Registration.Endpoint.SecurityPolicy</td>
@{ var securityPolicy = endpoint.EndpointModel.Registration.Endpoint.SecurityPolicy[(endpoint.EndpointModel.Registration.Endpoint.SecurityPolicy.LastIndexOf("#") + 1)..endpoint.EndpointModel.Registration.Endpoint.SecurityPolicy.Length];}
<td>@securityPolicy</td>
<td>@endpoint.EndpointModel.Registration.SecurityLevel</td>
<td>@(endpoint.EndpointModel.EndpointState?.ToString() ?? "Disconnected")</td>
<td>
Expand All @@ -93,7 +95,7 @@
<input type="checkbox" checked
@onchange="async eventArgs => { await SetActivation(endpoint.EndpointModel.Registration.Id, eventArgs.Value); }" />
}
@endpoint.EndpointModel.ActivationState.ToString()
<label>Active</label>
}
else
{
Expand All @@ -106,9 +108,10 @@
<input type="checkbox"
@onchange="async eventArgs => { await SetActivation(endpoint.EndpointModel.Registration.Id, eventArgs.Value); }" />
}
@endpoint.EndpointModel.ActivationState.ToString()
<label></label>
}
</td>
<td>@endpoint.EndpointModel.ActivationState.ToString()</td>
<td>
<a class="ellipsis-space" href='publishedNodes/@endpoint.EndpointModel.Registration.Id'>Published Nodes</a>
</td>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
@*------------------------------------------------------------
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License (MIT). See License.txt in the repo root for license information.
------------------------------------------------------------*@

@using Microsoft.Azure.IIoT.App.Services
@using Microsoft.AspNetCore.Components;
@using OpcUa.Api.Publisher.Models;

@inject Registry RegistryHelper

<div class="drawer-content list-group">
<div class="list-group-item text-justify list-group-item-heading">
<b>Enter configuration parameters.</b>
<br><b>To apply default config leave the input field blank and click on apply</b>
</div>
<hr />
<div class="list-group-item text-left">
<div class="label">
Node Id:
<div class="body">@NodeData.Id</div>
</div><br />
<div class="label">
Display Name:
<div class="body">@NodeData.NodeName</div>
</div><br />
<form>
<div class="form-group">
<div class="label">Publishing Interval ms</div>
<input @bind="@NodeData.RequestedPublishingInterval" aria-label="PublishingInterval" type="text" class="form-control" placeholder="@(NodeData.RequestedPublishingInterval)" />
</div><br />
<div class="form-group">
<div class="label">Sampling Interval ms </div>
<input @bind="@NodeData.RequestedSamplingInterval" aria-label="SamplingInterval" type="text" class="form-control" placeholder="@(NodeData.RequestedSamplingInterval)" />
</div><br />
<div class="form-group">
<div class="label">Heartbeat Interval sec</div>
<input @bind="@NodeData.RequestedHeartbeatInterval" aria-label="HeartbeatInterval" type="text" class="form-control" placeholder="@(NodeData.RequestedHeartbeatInterval)" />
</div><br />
<hr />
<div>
<button @onclick="@(async() => await UpdatePublishedNodeConfigAsync(NodeData))" type="button" class="btn btn-primary shadow-none">Apply</button>
</div>
</form>
</div>
</div>

@code {
[Parameter]
public ListNode NodeData { get; set; }

[Parameter]
public EventCallback Onclick { get; set; }

/// <summary>
/// OnInitialized
/// </summary>
protected override void OnInitialized()
{
if (NodeData.PublishedItem == null)
{
NodeData.PublishedItem = new PublishedItemApiModel();
}
}


/// <summary>
/// Close Drawer and update discovery
/// </summary>
/// <param name="discoverer"></param>
private async Task UpdatePublishedNodeConfigAsync(ListNode node)
{
await Onclick.InvokeAsync(node);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,15 +76,16 @@ public async Task<PagedResult<PublishedItemApiModel>> PublishedAsync(string endp
/// <param name="publishingInterval"></param>
/// <returns>ErrorStatus</returns>
public async Task<bool> StartPublishingAsync(string endpointId, string nodeId, string displayName,
int samplingInterval, int publishingInterval, CredentialModel credential = null) {
TimeSpan? samplingInterval, TimeSpan? publishingInterval, TimeSpan? heartBeatInterval, CredentialModel credential = null) {

try {
var requestApiModel = new PublishStartRequestApiModel() {
Item = new PublishedItemApiModel() {
NodeId = nodeId,
DisplayName = displayName,
SamplingInterval = TimeSpan.FromMilliseconds(samplingInterval),
PublishingInterval = TimeSpan.FromMilliseconds(publishingInterval)
SamplingInterval = samplingInterval,
PublishingInterval = publishingInterval,
HeartbeatInterval = heartBeatInterval
}
};

Expand Down
Loading

0 comments on commit 214c819

Please sign in to comment.