Skip to content

Commit

Permalink
Merge pull request #20 from lillo42/master
Browse files Browse the repository at this point in the history
Merge with master
  • Loading branch information
lillo42 authored Feb 14, 2020
2 parents eef8d97 + 89a052a commit e1dc8c9
Show file tree
Hide file tree
Showing 58 changed files with 1,266 additions and 160 deletions.
9 changes: 7 additions & 2 deletions sample/MultiThing/Startup.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
Expand All @@ -7,6 +7,7 @@
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.WebSockets;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
Expand All @@ -30,6 +31,8 @@ public void ConfigureServices(IServiceCollection services)
services.AddThings()
.AddThing<ExampleDimmableLight>()
.AddThing<FakeGpioHumiditySensor>();

services.AddWebSockets(opt => { });
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
Expand All @@ -41,7 +44,9 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
}

app.UseRouting();


app.UseWebSockets();

app.UseEndpoints(endpoints =>
{
endpoints.MapThings();
Expand Down
6 changes: 3 additions & 3 deletions sample/MultiThing/Things/ExampleDimmableLight.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ public class ExampleDimmableLight : Thing
{
public override string Name => "my-lamp-1234";

public override string? Title => "My Lamp";
public override string Title => "My Lamp";

public override string[]? Type { get; } = new[] {"OnOffSwitch", "Light"};
public override string[] Type { get; } = new[] {"OnOffSwitch", "Light"};

public override string? Description => "A web connected lamp";
public override string Description => "A web connected lamp";

private bool _on = true;

Expand Down
6 changes: 3 additions & 3 deletions sample/MultiThing/Things/FakeGpioHumiditySensor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ public FakeGpioHumiditySensor()
}
public override string Name => "my-humidity-sensor-1234";

public override string? Title => "My Humidity Sensor";
public override string Title => "My Humidity Sensor";

public override string[]? Type { get; } = new[] {"MultiLevelSensor"};
public override string[] Type { get; } = new[] {"MultiLevelSensor"};

public override string? Description => "A web connected humidity sensor";
public override string Description => "A web connected humidity sensor";


[ThingProperty(Type = new []{"LevelProperty"}, Title = "Humidity", Description = "The current humidity in %",
Expand Down
8 changes: 7 additions & 1 deletion sample/SampleThing/Startup.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.WebSockets;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using SampleThing.Things;
Expand All @@ -15,6 +16,9 @@ public void ConfigureServices(IServiceCollection services)
{
services.AddThings()
.AddThing<LampThing>();


services.AddWebSockets(opt => { });
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
Expand All @@ -27,6 +31,8 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)

app.UseRouting();

app.UseWebSockets();

app.UseEndpoints(endpoints =>
{
endpoints.MapThings();
Expand Down
2 changes: 1 addition & 1 deletion sample/SampleThing/Things/LampThing.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public class LampThing : Thing
[ThingEvent(Title = "Overheated", Unit = "degree celsius",
Type = new [] {"OverheatedEvent"},
Description = "The lamp has exceeded its safe operating temperature")]
public event EventHandler<double> Overheated;
public event EventHandler<double>? Overheated;


[ThingAction(Name = "fade", Title = "Fade", Type = new []{"FadeAction"},
Expand Down
56 changes: 56 additions & 0 deletions src/Mozilla.IoT.WebThing/ActionCollection.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using Mozilla.IoT.WebThing.Actions;

namespace Mozilla.IoT.WebThing
{
public class ActionCollection : IEnumerable<ActionInfo>
{
private readonly ConcurrentDictionary<Guid, ActionInfo> _actions;

public event EventHandler<ActionInfo>? Change;

public ActionCollection()
{
_actions = new ConcurrentDictionary<Guid, ActionInfo>();
}

public void Add(Guid id, ActionInfo actionInfo)
{
_actions.TryAdd(id, actionInfo);

actionInfo.StatusChanged += OnStatusChange;

var change = Change;
change?.Invoke(this, actionInfo);
}

public bool TryGetValue(Guid id, out ActionInfo? action)
=> _actions.TryGetValue(id, out action);

public bool TryRemove(Guid id, out ActionInfo action)
{
var result =_actions.TryRemove(id, out action);
if (result && action != null)
{

action.StatusChanged -= OnStatusChange;
}

return result;
}

private void OnStatusChange(object? sender, EventArgs args)
{
var change = Change;
change?.Invoke(this, (ActionInfo)sender);
}

public IEnumerator<ActionInfo> GetEnumerator()
=> _actions.Values.GetEnumerator();

IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
}
4 changes: 1 addition & 3 deletions src/Mozilla.IoT.WebThing/ActionContext.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using System;
using System.Collections.Concurrent;
using Mozilla.IoT.WebThing.Actions;

namespace Mozilla.IoT.WebThing
{
Expand All @@ -12,6 +10,6 @@ public ActionContext(Type actionType)
}

public Type ActionType { get; }
public ConcurrentDictionary<Guid, ActionInfo> Actions { get; } = new ConcurrentDictionary<Guid, ActionInfo>();
public ActionCollection Actions { get; } = new ActionCollection();
}
}
14 changes: 12 additions & 2 deletions src/Mozilla.IoT.WebThing/Actions/ActionInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ public abstract class ActionInfo
internal Thing Thing { get; set; } = default!;
protected abstract string ActionName { get; }

public string Href => $"/things/{Thing.Name}/actions/{ActionName}/{Id}";
public string Href { get; internal set; }

public DateTime TimeRequested { get; } = DateTime.UtcNow;
public DateTime? TimeCompleted { get; private set; } = null;
public string Status { get; private set; } = "pending";
Expand All @@ -27,8 +27,13 @@ public async Task ExecuteAsync(Thing thing, IServiceProvider provider)
{
var logger = provider.GetRequiredService<ILogger<ActionInfo>>();
logger.LogInformation("Going to execute {actionName}", ActionName);

var status = StatusChanged;

Status = "executing";

status?.Invoke(this, EventArgs.Empty);

try
{
await InternalExecuteAsync(thing, provider)
Expand All @@ -42,13 +47,18 @@ await InternalExecuteAsync(thing, provider)
}

TimeCompleted = DateTime.UtcNow;

Status = "completed";

status?.Invoke(this, EventArgs.Empty);

}

internal string GetActionName() => ActionName;

public void Cancel()
=> Source.Cancel();

public event EventHandler? StatusChanged;
}
}
4 changes: 3 additions & 1 deletion src/Mozilla.IoT.WebThing/Context.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Net.WebSockets;
using Mozilla.IoT.WebThing.Converts;

namespace Mozilla.IoT.WebThing
Expand All @@ -20,8 +22,8 @@ public Context(IThingConverter converter,
public IThingConverter Converter { get; }

public IProperties Properties { get; }

public Dictionary<string, EventCollection> Events { get; }
public Dictionary<string, ActionContext> Actions { get; }
public ConcurrentDictionary<Guid, WebSocket> Sockets { get; } = new ConcurrentDictionary<Guid, WebSocket>();
}
}
9 changes: 4 additions & 5 deletions src/Mozilla.IoT.WebThing/Converts/ThingConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,29 +44,28 @@ public override void Write(Utf8JsonWriter writer, Thing value, JsonSerializerOpt

writer.WriteStartObject();
writer.WriteString("@context", value.Context);
var builder = new UriBuilder(value.Context) {Path = $"/things/{value.Name}"};
var builder = new UriBuilder(value.Prefix) {Path = $"/things/{options.GetPropertyName(value.Name)}"};
WriteProperty(writer, "Id", builder.Uri.ToString(), options);
value.ThingContext.Converter.Write(writer, value, options);

StartArray(writer, "Links", options);

writer.WriteStartObject();
WriteProperty(writer, "rel", "properties", options);
WriteProperty(writer, "href", $"/things/{value.Name}/properties", options);
WriteProperty(writer, "href", $"/things/{options.GetPropertyName(value.Name)}/properties", options);
writer.WriteEndObject();

writer.WriteStartObject();
WriteProperty(writer, "rel", "actions", options);
WriteProperty(writer, "href", $"/things/{value.Name}/actions", options);
WriteProperty(writer, "href", $"/things/{options.GetPropertyName(value.Name)}/actions", options);
writer.WriteEndObject();

writer.WriteStartObject();
WriteProperty(writer, "rel", "events", options);
WriteProperty(writer, "href", $"/things/{value.Name}/events", options);
WriteProperty(writer, "href", $"/things/{options.GetPropertyName(value.Name)}/events", options);
writer.WriteEndObject();

builder.Scheme = value.Prefix.Scheme == "http" ? "ws" : "wss";
builder.Path = $"/things/{value.Name}";
writer.WriteStartObject();
WriteProperty(writer, "rel", "alternate", options);
WriteProperty(writer, "href", builder.Uri.ToString(), options);
Expand Down
1 change: 0 additions & 1 deletion src/Mozilla.IoT.WebThing/Endpoints/GetAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
Expand Down
1 change: 0 additions & 1 deletion src/Mozilla.IoT.WebThing/Endpoints/GetActionById.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
Expand Down
1 change: 0 additions & 1 deletion src/Mozilla.IoT.WebThing/Endpoints/GetActions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
Expand Down
3 changes: 1 addition & 2 deletions src/Mozilla.IoT.WebThing/Endpoints/GetEvent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Mozilla.IoT.WebThing.Converts;
Expand Down Expand Up @@ -52,7 +51,7 @@ public static Task InvokeAsync(HttpContext context)
context.Response.StatusCode = (int)HttpStatusCode.OK;
context.Response.ContentType = Const.ContentType;

return JsonSerializer.SerializeAsync(context.Response.Body, result, ThingConverter.Options);
return JsonSerializer.SerializeAsync(context.Response.Body, result, service.GetRequiredService<JsonSerializerOptions>());
}
}
}
2 changes: 1 addition & 1 deletion src/Mozilla.IoT.WebThing/Endpoints/GetEvents.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public static Task InvokeAsync(HttpContext context)
context.Response.StatusCode = (int)HttpStatusCode.OK;
context.Response.ContentType = Const.ContentType;

return JsonSerializer.SerializeAsync(context.Response.Body, result, ThingConverter.Options);
return JsonSerializer.SerializeAsync(context.Response.Body, result, service.GetRequiredService<JsonSerializerOptions>());
}
}
}
2 changes: 1 addition & 1 deletion src/Mozilla.IoT.WebThing/Endpoints/GetProperties.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public static Task InvokeAsync(HttpContext context)
context.Response.StatusCode = (int)HttpStatusCode.OK;
context.Response.ContentType = Const.ContentType;

return JsonSerializer.SerializeAsync(context.Response.Body, properties, ThingConverter.Options);
return JsonSerializer.SerializeAsync(context.Response.Body, properties, service.GetRequiredService<JsonSerializerOptions>());
}
}
}
3 changes: 1 addition & 2 deletions src/Mozilla.IoT.WebThing/Endpoints/GetProperty.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Mozilla.IoT.WebThing.Converts;
using Mozilla.IoT.WebThing.Extensions;

namespace Mozilla.IoT.WebThing.Endpoints
{
Expand Down Expand Up @@ -47,7 +46,7 @@ public static Task InvokeAsync(HttpContext context)
context.Response.StatusCode = (int)HttpStatusCode.OK;
context.Response.ContentType = Const.ContentType;

return JsonSerializer.SerializeAsync(context.Response.Body, properties, ThingConverter.Options);
return JsonSerializer.SerializeAsync(context.Response.Body, properties, service.GetRequiredService<JsonSerializerOptions>());
}
}
}
Loading

0 comments on commit e1dc8c9

Please sign in to comment.