Send messages to the client
This commit is contained in:
parent
9ee271559f
commit
5daecdd445
|
@ -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));
|
||||
});
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
17
Ooui/Node.cs
17
Ooui/Node.cs
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
webSocket = webSocketContext.WebSocket;
|
||||
await SendMessageAsync (webSocket, m, token);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
Error ("Failed to handled element message", ex);
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// Communicate!
|
||||
//
|
||||
try {
|
||||
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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue