Send messages to the client

This commit is contained in:
Frank A. Krueger 2017-06-12 20:31:47 -07:00
parent 9ee271559f
commit 5daecdd445
5 changed files with 87 additions and 11 deletions

View File

@ -12,5 +12,5 @@ socket.addEventListener('open', function (event) {
// Listen for messages
socket.addEventListener('message', function (event) {
console.log('Message from server', event.data);
console.log('Message from server', JSON.parse (event.data));
});

View File

@ -1,13 +1,26 @@
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace Ooui
{
public class Message
{
[JsonProperty("t")]
[JsonConverter (typeof (MillisecondEpochConverter))]
public DateTime CreatedTime = DateTime.UtcNow;
[JsonProperty("m")]
[JsonConverter (typeof (StringEnumConverter))]
public MessageType MessageType = MessageType.Nop;
[JsonProperty("id")]
public string TargetId = "";
public string Member = "";
[JsonProperty("k")]
public string Key = "";
[JsonProperty("v")]
public string Value = "";
public void SetValue (object value)
@ -20,7 +33,7 @@ namespace Ooui
Value = EncodeString (s);
break;
default:
Value = String.Format (System.Globalization.CultureInfo.InvariantCulture, "{0}", value);
Value = JsonConvert.SerializeObject (value);
break;
}
}
@ -42,4 +55,20 @@ namespace Ooui
Set,
Call,
}
class MillisecondEpochConverter : DateTimeConverterBase
{
private static readonly DateTime epoch = new DateTime (1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
public override void WriteJson (JsonWriter writer, object value, JsonSerializer serializer)
{
writer.WriteRawValue (((DateTime)value - epoch).TotalMilliseconds.ToString (System.Globalization.CultureInfo.InvariantCulture));
}
public override object ReadJson (JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.Value == null) return null;
return epoch.AddMilliseconds ((double)reader.Value);
}
}
}

View File

@ -14,6 +14,13 @@ namespace Ooui
readonly List<Message> messages = new List<Message> ();
readonly List<Message> stateMessages = new List<Message> ();
public event Action<Message> MessageLogged;
public IEnumerable<Message> AllMessages =>
messages
.Concat (from c in children from m in c.AllMessages select m)
.OrderBy (x => x.CreatedTime);
public Node ()
{
Mapping = Mapping.Get (GetType ());
@ -66,7 +73,7 @@ namespace Ooui
{
var old = stateMessages.FirstOrDefault (
x => x.MessageType == MessageType.Set &&
x.Member == message.Member);
x.Key == message.Key);
if (old != null) {
stateMessages.Remove (old);
}
@ -74,6 +81,8 @@ namespace Ooui
}
break;
}
MessageLogged?.Invoke (message);
}
protected void LogCreate ()
@ -90,7 +99,7 @@ namespace Ooui
Log (new Message {
MessageType = MessageType.Call,
TargetId = Id,
Member = methodName,
Key = methodName,
});
}
@ -99,13 +108,13 @@ namespace Ooui
var m = new Message {
MessageType = MessageType.Set,
TargetId = Id,
Member = Mapping.GetMemberPath (propertyName),
Key = Mapping.GetMemberPath (propertyName),
};
m.SetValue (value);
Log (m);
}
protected bool SetProperty<T> (ref T backingStore, T newValue, string propertyName = "")
protected bool SetProperty<T> (ref T backingStore, T newValue, [System.Runtime.CompilerServices.CallerMemberName] string propertyName = "")
{
if (!backingStore.Equals (newValue)) {
backingStore = newValue;

View File

@ -129,6 +129,9 @@ namespace Ooui
async void ProcessWebSocketRequest (HttpListenerContext listenerContext, CancellationToken token)
{
//
// Find the element
//
var url = listenerContext.Request.Url;
var path = url.LocalPath;
@ -150,9 +153,14 @@ namespace Ooui
return;
}
//
// Connect the web socket
//
WebSocketContext webSocketContext = null;
WebSocket webSocket = null;
try {
webSocketContext = await listenerContext.AcceptWebSocketAsync(subProtocol: "ooui-1.0").ConfigureAwait (false);
webSocket = webSocketContext.WebSocket;
Console.WriteLine ("WEBSOCKET {0}", listenerContext.Request.Url.LocalPath);
}
catch (Exception ex) {
@ -162,9 +170,30 @@ namespace Ooui
return;
}
WebSocket webSocket = null;
//
// Preparse handlers for the element
//
Action<Message> onElementMessage = async m => {
if (webSocket == null) return;
try {
await SendMessageAsync (webSocket, m, token);
}
catch (Exception ex) {
Error ("Failed to handled element message", ex);
}
};
//
// Communicate!
//
try {
webSocket = webSocketContext.WebSocket;
foreach (var m in element.AllMessages) {
if (webSocket.State == WebSocketState.Open) {
await SendMessageAsync (webSocket, m, token);
}
}
element.MessageLogged += onElementMessage;
var receiveBuffer = new byte[1024];
@ -190,8 +219,8 @@ namespace Ooui
var receivedString = Encoding.UTF8.GetString (receiveBuffer, 0, size);
Console.WriteLine ("RECEIVED: {0}", receivedString);
var outputBuffer = new ArraySegment<byte> (Encoding.UTF8.GetBytes ($"You said: {receivedString}"));
await webSocket.SendAsync (outputBuffer, WebSocketMessageType.Text, true, token).ConfigureAwait (false);
// var outputBuffer = new ArraySegment<byte> (Encoding.UTF8.GetBytes ($"You said: {receivedString}"));
// await webSocket.SendAsync (outputBuffer, WebSocketMessageType.Text, true, token).ConfigureAwait (false);
}
}
}
@ -202,10 +231,18 @@ namespace Ooui
Error ("Failed to process web socket", ex);
}
finally {
element.MessageLogged -= onElementMessage;
webSocket?.Dispose ();
}
}
Task SendMessageAsync (WebSocket webSocket, Message message, CancellationToken token)
{
var json = Newtonsoft.Json.JsonConvert.SerializeObject (message);
var outputBuffer = new ArraySegment<byte> (Encoding.UTF8.GetBytes (json));
return webSocket.SendAsync (outputBuffer, WebSocketMessageType.Text, true, token);
}
void Error (string message, Exception ex)
{
Console.ForegroundColor = ConsoleColor.Red;

View File

@ -9,6 +9,7 @@ namespace Samples
{
var server = new Server ();
var button = new Button();
button.Name = "TestButton";
server.Publish ("/button", button);
server.RunAsync ("http://*:8080/").Wait ();
return 0;