Skip to content

Commit

Permalink
Added Http PUT functionality
Browse files Browse the repository at this point in the history
- Added PUT functionality to MTConnectHttpServer to accept adding observations through the URL query string
- Added an ShdrMTConnectHttpServer class in the MTConnect.NET-SHDR project to implement SHDR lines sent as Query parameters
- Updated the default MTConnectHttpServer to use the ShdrMTConnectHttpServer class in the MTConnect-Agent-Http application
  • Loading branch information
PatrickRitchie committed Apr 13, 2022
1 parent 28e8afa commit 310fec4
Show file tree
Hide file tree
Showing 6 changed files with 207 additions and 6 deletions.
2 changes: 1 addition & 1 deletion applications/Agents/MTConnect-Agent-Http/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ private static void Init(MTConnectAgentConfiguration configuration, bool verbose
StartMetrics();

// Start the Http Server
var server = new MTConnectHttpServer(_agent);
var server = new ShdrMTConnectHttpServer(_agent);

if (verboseLogging)
{
Expand Down
1 change: 0 additions & 1 deletion src/MTConnect.NET-Common/Agents/MTConnectAgent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3371,6 +3371,5 @@ private void DeviceMetricsUpdated(object sender, DeviceMetrics deviceMetrics)
}

#endregion

}
}
27 changes: 27 additions & 0 deletions src/MTConnect.NET-HTTP/Http/MTConnectHttpObservationInput.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright (c) 2022 TrakHound Inc., All Rights Reserved.

// This file is subject to the terms and conditions defined in
// file 'LICENSE.txt', which is part of this source code package.

namespace MTConnect.Http
{
/// <summary>
/// An Observation that is attempting to be added to an MTConnect Agent from an Http interface
/// </summary>
public struct MTConnectHttpObservationInput
{
public string DeviceUuid { get; set; }

public string DataItemKey { get; set; }

public string Input { get; set; }


public MTConnectHttpObservationInput(string deviceUuid, string dataItemKey, string input)
{
DeviceUuid = deviceUuid;
DataItemKey = dataItemKey;
Input = input;
}
}
}
97 changes: 93 additions & 4 deletions src/MTConnect.NET-HTTP/Http/MTConnectHttpServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

using MTConnect.Agents;
using MTConnect.Agents.Configuration;
using MTConnect.Errors;
using System;
using System.Collections.Generic;
using System.IO;
Expand Down Expand Up @@ -215,7 +216,6 @@ private void ListenerCallback(IAsyncResult result)

if (uri != null)
{

switch (method)
{
case "GET":
Expand All @@ -237,9 +237,7 @@ private void ListenerCallback(IAsyncResult result)

if (_configuration != null && _configuration.AllowPut)
{
Console.WriteLine("PUT");

contextClosure.Response.StatusCode = 200;
await ProcessPut(request, response);
}
else
{
Expand Down Expand Up @@ -387,6 +385,28 @@ private async Task WriteResponse(MTConnectHttpResponse mtconnectResponse, HttpLi
}
}

/// <summary>
/// Write a string to the HttpListenerResponse Output Stream
/// </summary>
private async Task WriteResponse(string content, HttpListenerResponse httpResponse, HttpStatusCode statusCode, string contentType = MimeTypes.XML)
{
if (httpResponse != null)
{
try
{
using (var stream = httpResponse.OutputStream)
{
httpResponse.ContentType = contentType;
httpResponse.StatusCode = (int)statusCode;

var bytes = Encoding.ASCII.GetBytes(content);
await stream.WriteAsync(bytes, 0, bytes.Length);
}
}
catch { }
}
}


/// <summary>
/// An Agent responds to a Probe Request with an MTConnectDevices Response Document that contains the
Expand Down Expand Up @@ -747,6 +767,75 @@ private async Task ProcessAsset(HttpListenerRequest httpRequest, HttpListenerRes
}


private async Task ProcessPut(HttpListenerRequest httpRequest, HttpListenerResponse httpResponse)
{
if (httpRequest != null && httpRequest.Url != null && httpResponse != null)
{
if (httpRequest.QueryString != null && httpRequest.QueryString.Count > 0)
{
var urlSegments = GetUriSegments(httpRequest.Url);

// Read DeviceKey from URL Path
var deviceKey = httpRequest.Url.LocalPath?.Trim('/');
if (urlSegments.Length > 1)
{
deviceKey = urlSegments[urlSegments.Length - 1];
}

// Get list of KeyValuePairs from Url Query
var items = new List<KeyValuePair<string, string>>();
foreach (var key in httpRequest.QueryString.AllKeys)
{
var urlValue = httpRequest.QueryString[key];
if (!string.IsNullOrEmpty(urlValue))
{
// Decode the input that was read from the URL
var value = System.Web.HttpUtility.UrlDecode(urlValue);

// Add to list of items
items.Add(new KeyValuePair<string, string>(key, value));
}
}

if (!items.IsNullOrEmpty())
{
var success = false;

foreach (var item in items)
{
// Call the OnObservationInput method that is intended to be overridden by a derived class
success = await OnObservationInput(deviceKey, item.Key, item.Value);
if (!success) break;
}

if (success)
{
// Write the "<success/>" respone to the Http Response Stream
// along with a 200 Status Code
await WriteResponse("<success/>", httpResponse, HttpStatusCode.OK);
}
else
{
// Return MTConnectError Response Document along with a 404 Http Status Code
var errorDocument = await _mtconnectAgent.GetErrorAsync(ErrorCode.UNSUPPORTED, $"Cannot find device: {deviceKey}");
var mtconnectResponse = new MTConnectHttpResponse(errorDocument, 404, DocumentFormat.XML, 0, null);
await WriteResponse(mtconnectResponse, httpResponse);
}
}
}
}
}

/// <summary>
/// Method run when an Observation is attempted to be added to the MTConnect Agent from an HTTP PUT request
/// </summary>
/// <returns>Returns False if a Device cannot be found from the specified DeviceKey</returns>
protected virtual async Task<bool> OnObservationInput(string deviceKey, string dataItemKey, string input)
{
return false;
}


private async Task ProcessStatic(HttpListenerRequest httpRequest, HttpListenerResponse httpResponse)
{
if (httpRequest != null && httpResponse != null)
Expand Down
85 changes: 85 additions & 0 deletions src/MTConnect.NET-SHDR/Http/ShdrMTConnectHttpServer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// Copyright (c) 2022 TrakHound Inc., All Rights Reserved.

// This file is subject to the terms and conditions defined in
// file 'LICENSE.txt', which is part of this source code package.

using MTConnect.Adapters.Shdr;
using MTConnect.Agents;
using MTConnect.Devices;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace MTConnect.Http
{
/// <summary>
/// An Http Web Server for processing MTConnect REST Api Requests with a processor PUT requests for SHDR data sent in the URL query string
/// </summary>
public class ShdrMTConnectHttpServer : MTConnectHttpServer
{
private readonly IMTConnectAgent _mtconnectAgent;


public ShdrMTConnectHttpServer(IMTConnectAgent mtconnectAgent, IEnumerable<string> prefixes = null) : base(mtconnectAgent, prefixes)
{
_mtconnectAgent = mtconnectAgent;
}


protected override async Task<bool> OnObservationInput(string deviceKey, string dataItemKey, string input)
{
// Get the Devices Document from the Agent
var devicesDocument = await _mtconnectAgent.GetDevicesAsync(deviceKey);
if (devicesDocument != null && !devicesDocument.Devices.IsNullOrEmpty())
{
// Get the first Device (should only be one Device)
var device = devicesDocument.Devices.FirstOrDefault();
if (device != null)
{
// Get the DataItem based on the Key
var dataItem = device.GetDataItemByKey(dataItemKey);
if (dataItem != null)
{
// Construct an SHDR Line using the DataItemId and the Input string from Http
var shdrLine = $"{dataItem.Id}|{input}";

if (dataItem.Category == DataItemCategory.CONDITION)
{
var condition = ShdrFaultState.FromString(shdrLine);
if (condition != null) await _mtconnectAgent.AddObservationAsync(device.Uuid, condition);
}
else if (dataItem.Type == Devices.DataItems.Events.MessageDataItem.TypeId)
{
var message = ShdrMessage.FromString(shdrLine);
if (message != null) await _mtconnectAgent.AddObservationAsync(device.Uuid, message);
}
else if (dataItem.Representation == DataItemRepresentation.TABLE)
{
var table = ShdrTable.FromString(shdrLine);
if (table != null) await _mtconnectAgent.AddObservationAsync(device.Uuid, table);
}
else if (dataItem.Representation == DataItemRepresentation.DATA_SET)
{
var dataSet = ShdrDataSet.FromString(shdrLine);
if (dataSet != null) await _mtconnectAgent.AddObservationAsync(device.Uuid, dataSet);
}
else if (dataItem.Representation == DataItemRepresentation.TIME_SERIES)
{
var timeSeries = ShdrTimeSeries.FromString(shdrLine);
if (timeSeries != null) await _mtconnectAgent.AddObservationAsync(device.Uuid, timeSeries);
}
else
{
var dataItems = ShdrDataItem.FromString(shdrLine);
if (!dataItems.IsNullOrEmpty()) await _mtconnectAgent.AddObservationsAsync(device.Uuid, dataItems);
}
}

return true;
}
}

return false;
}
}
}
1 change: 1 addition & 0 deletions src/MTConnect.NET-SHDR/MTConnect.NET-SHDR.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\MTConnect.NET-HTTP\MTConnect.NET-HTTP.csproj" />
<ProjectReference Include="..\MTConnect.NET-XML\MTConnect.NET-XML.csproj" />
</ItemGroup>

Expand Down

0 comments on commit 310fec4

Please sign in to comment.