using System;
using System.Threading;
using EmbedIO.WebSockets;
using System.Threading.Tasks;
using KevDrawServer.Drawer;
using EmbedIO.Sessions;
using System.Collections.Generic;
using GeoSigma.SigmaDrawerUtil;
using System.IO;
using GeoSigmaDrawLib;
using System.Drawing;
using System.Drawing.Imaging;
using System.Net.WebSockets;
using System.Diagnostics;
namespace KevDrawServer
{
class EventSocketModule : WebSocketModule
{
public string MapFile { get; set; } = string.Empty;
private static readonly Object locker = new Object();
private WebDrawer drawer = null;
//IWebSocketContext socketContex;
public EventSocketModule() :
base("/event", true)
{
AddProtocol("json");
}
///
protected override async Task OnClientConnectedAsync(IWebSocketContext context)
{
Logger.Info("client connected");
await SendTargetedEvent(context, new JsEvent("connected")).ConfigureAwait(false);
}
//CancellationTokenSource _cts;
//private char[] message;
///
/// Sends the targeted event.
///
/// The context.
/// The js event.
/// A Task.
private Task SendTargetedEvent(IWebSocketContext context, JsEvent jsEvent)
{
if (context.WebSocket.State != WebSocketState.Open)
{
return Task.CompletedTask;
}
// 取消之前的发送任务
//_cts.Cancel();
//_cts = new CancellationTokenSource();
return SendAsync(context, JsonUtils.SerializeToJson(jsEvent));
}
///
protected override Task OnClientDisconnectedAsync(IWebSocketContext context)
{
Logger.Info("client disconnected");
return Task.CompletedTask;
}
public async Task BroadcastEvent(JsEvent jsEvent)
{
var json = JsonUtils.SerializeToJson(jsEvent);
await BroadcastAsync(json).ConfigureAwait(false);
}
///
protected override async Task OnMessageReceivedAsync(IWebSocketContext context, byte[] rxBuffer,
IWebSocketReceiveResult rxResult)
{
// 回应客户端
//socketContex = context;
string text = Encoding.GetString(rxBuffer);
//Trace.WriteLine($"Message {text}");
JsEvent evt = new JsEvent("Nothing");
Dictionary dictionary = new Dictionary();
try
{
evt = JsonUtils.DeserializeFromJson(text);
try
{
dictionary = JsonUtils.DeserializeFromJson>($"{evt.Data}");
}
catch
{
Logger.Info("Got message is block:{0}", text);
}
}
catch (Exception ex)
{
Logger.Info("Got message error:{0}\r\n{1}", text, ex.Message);
return;
}
string strEventType = evt.Type;
Logger.Info("Got message of type {0}", strEventType);
if (strEventType.Equals("Ping", StringComparison.CurrentCultureIgnoreCase))
{
await SendTargetedEvent(context, new JsEvent("Pong")).ConfigureAwait(false);
return;
}
string strToken = evt.Token;
if (strEventType == "OpenFile")
{
if (!dictionary.ContainsKey("token"))
{
return;
}
strToken = $"{dictionary["token"]}";
this.clearError(context, strToken);
string strFile = $"{dictionary["file"]}";
double dWidth = Convert.ToDouble(dictionary["width"]);
double dHeight = Convert.ToDouble(dictionary["height"]);
string strResult = await EventResponse.CreateDrawerAsync(strFile, (int)dWidth, (int)dHeight, context, strToken).ConfigureAwait(true);
if (!string.IsNullOrEmpty(strResult))
{
if (this.findError(context, strToken) != null)
{
return;
}
// 发送Token
var jsEvent = new JsEvent("NewToken");
jsEvent.Token = strToken;
jsEvent.UserID = strFile;
await SendTargetedEvent(context, jsEvent).ConfigureAwait(false);
}
else
{
// 发送打开错误信息
var jsEvent = new JsEvent("OpenError");
jsEvent.Token = strToken;
jsEvent.UserID = strFile;
// 记录错误
GlobalSession.StoreData($"Error_{strToken}", strToken);
await SendTargetedEvent(context, jsEvent).ConfigureAwait(false);
return;
}
}
else if (strEventType == "CloseDrawer")
{
await EventResponse.CloseDrawerAsync(strToken, context);
return;
}
//Logger.Info("OnMessageReceivedAsync:" + strToken);
SemaphoreSlim drawerLock = GetCurrentLocker(strToken, context);
if (drawerLock != null)
{
await drawerLock.WaitAsync(); // 异步获取锁
try
{
WebDrawer drawerCur = GetCurrentDrawer(strToken, context);
EventResponse response = new EventResponse(drawerCur, context);
// FIXME: 下面的获取有利区需要知道原始文件名,所以需要知道 token,在这里扩充了一下
dictionary["token"] = strToken;
JsEvent responseEvent = await Task.Run(() => response.ExcuteOperator(evt.Type, dictionary));
if (responseEvent != null)
{
responseEvent.Token = strToken;
responseEvent.CmdID = evt.CmdID;
await SendTargetedEvent(context, responseEvent).ConfigureAwait(false);
// 执行后续事件
if(evt.Type== "SelectMouseUp")
{
string strEventAfterType = "GetElementProperty";
await ExcuteAfter(strEventAfterType, context, strToken, evt.CmdID, response);
}
}
}
finally
{
drawerLock.Release();
}
}
}
///
/// 后续事件.
///
/// The event name.
/// The context.
/// The str token.
/// The cmd i d.
/// The response.
/// A Task.
private async Task ExcuteAfter(string eventName, IWebSocketContext context, string strToken, string cmdID, EventResponse response)
{
JsEvent responseAfter = await Task.Run(() => response.ExcuteOperator(eventName, null));
if (responseAfter != null)
{
responseAfter.Token = strToken;
responseAfter.CmdID = cmdID;
await SendTargetedEvent(context, responseAfter).ConfigureAwait(false);
}
}
///
/// 查找错误信息.
///
/// The context.
///
/// An object.
private object findError(IWebSocketContext context, string token)
{
string strError = $"Error_{token}";
foreach (KeyValuePair kv in context.Session.TakeSnapshot())
{
if(kv.Key.StartsWith(strError))
{
return kv.Value;
}
}
return null;
}
///
/// 清除错误信息.
///
/// The context.
///
private void clearError(IWebSocketContext context,string token)
{
string strError = $"Error_{token}";
IReadOnlyList> kvs = context.Session.TakeSnapshot();
for (int i=kvs.Count-1;i>=0;i--)
{
KeyValuePair kv = kvs[i];
if (kv.Key.StartsWith(strError))
{
object objFind = null;
GlobalSession.TryRemove(kv.Key, out objFind);
}
}
}
///
/// Gets the current locker.
///
/// The token.
/// The context.
/// An object.
private SemaphoreSlim GetCurrentLocker(string token, IWebSocketContext context)
{
object obj = GlobalSession.GetData($"Lock_{token}");
return (SemaphoreSlim)obj;
}
///
/// 获得当前Session中的Drawer.
///
/// A WebDrawer.
private WebDrawer GetCurrentDrawer(string token, IWebSocketContext context)
{
drawer = (WebDrawer)GlobalSession.GetData(token);
return drawer;
}
/////
///// Creates the drawer.
/////
///// The file.
///// The w.
///// The h.
//public async Task CreateDrawerAsync(string file, int w, int h)
//{
// DrawerConfig.StartupPath = WebConfig.StartupPath;
// string strServerPath = WebConfig.MapDirectory;
// drawer = new WebDrawer(w, h);
// MapFile = Path.Combine(strServerPath, file);
// //ImageFile = Path.Combine(strServerPath, "K1.png");
// GeoSigmaXY geo = drawer.OpenFile(MapFile);
// string strToken = geo.GetDrawerXy().ToInt64().ToString();
// GlobalSession.StoreData(strToken, drawer);
// GlobalSession.StoreData("DrawerFile", file);
// GlobalSession.StoreData($"Lock_{strToken}", new SemaphoreSlim(1, 1));
// // 发送Token
// var responseEvent = new JsEvent("NewToken");
// responseEvent.Data = strToken;
// await SendTargetedEvent(context, responseEvent).ConfigureAwait(false);
// return strToken;
//}
////// GET: Drawer
//////public ActionResult Index()
//////{
////// ViewBag.Title = "Kep图形平台";
////// return View();
//////}
//////public FileResult Image()
//////{
////// ImageFile = Server.MapPath("..") + "\\Maps\\K1.png";
////// byte[] image = GetBytesFromImage(ImageFile);
////// return new FileContentResult(image, "image/jpeg");
//////}
//public async System.Threading.Tasks.Task OpenAsync(string file, int w = 0, int h = 0)
//{
// object oDrawer = null;
// //drawer = (WebDrawer)context.Session["KevDrawer"];
// if (GlobalSession.ContainsKey("KevDrawer"))
// {
// if (GlobalSession.TryGetValue("KevDrawer", out oDrawer))
// {
// GlobalSession.TryRemove("KevDrawer", out oDrawer);
// this.drawer = oDrawer as WebDrawer;
// if (drawer != null)
// {
// drawer.Dispose();
// drawer = null;
// }
// }
// }
// await this.ShowImgAsync(file, w, h);
//}
////[Route(HttpVerbs.Get, "/Redraw")]
//public async Task Redraw(int w = 0, int h = 0)
//{
// //this.drawer = GetCurrentDrawer();
// if (drawer == null)
// {
// return;
// }
// await this.ShowImgAsync("", w, h);
//}
//private string imageFile = "temp/K1.png";
//private async Task ShowImgAsync(string file = "", int w = 0, int h = 0, bool sendContent = false)
//{
// Bitmap bmp = null;
// await Task.Run(() =>
// {
// lock (locker)
// {
// if (drawer == null)
// {
// DrawerConfig.StartupPath = WebConfig.StartupPath;
// string strServerPath = WebConfig.MapDirectory;
// drawer = new WebDrawer(w, h);
// MapFile = Path.Combine(strServerPath, file);
// //ImageFile = Path.Combine(strServerPath, "K1.png");
// GeoSigmaXY geo = drawer.OpenFile(MapFile);
// string strToken = geo.GetDrawerXy().ToInt64().ToString();
// GlobalSession.StoreData(strToken,drawer);
// GlobalSession.StoreData("DrawerFile", file);
// // 发送Token
// var responseEvent = new JsEvent("NewToken");
// responseEvent.Data = strToken;
// SendTargetedEvent(socketContex, responseEvent).ConfigureAwait(false);
// }
// if (w != 0 && h != 0)
// {
// drawer.DrawerSize = new Size(w, h);
// }
// bmp = new Bitmap(drawer.DrawerSize.Width, drawer.DrawerSize.Height);
// // bmp.SetResolution(bmp.HorizontalResolution, bmp.VerticalResolution);
// using (Graphics g = Graphics.FromImage(bmp))
// {
// drawer.OnPaint(g);
// }
// }
// });
// await SendImg(bmp, "", sendContent);
//}
/////
///// 发送图片.
/////
///// The bmp.
///// 事件名称
///// If true, send content.
///// A Task.
//private async Task SendImg(Bitmap bmp, string eventName = "", bool sendContent = false)
//{
// byte[] image = null;
// string strFile = string.Empty;
// try
// {
// if (sendContent == false)
// {
// strFile = Path.Combine(WebConfig.HtmlRoot, imageFile);
// bmp.Save(strFile);
// }
// else
// {
// image = ConvertBitmapToByteArray(bmp);
// }
// }
// catch(Exception ex)
// {
// //Console.WriteLine($"SendImg: {ex.Message}");
// return;
// }
// string strEventName = eventName;
// if (string.IsNullOrEmpty(eventName))
// {
// strEventName = "Redraw";
// }
// var responseEvent = new JsEvent(strEventName);
// if (sendContent)
// {
// string base64Header = $"data:image/png;base64,";
// responseEvent.Data = (base64Header + Convert.ToBase64String(image));
// }
// else
// {
// responseEvent.Data = imageFile;
// }
// await SendTargetedEvent(socketContex, responseEvent).ConfigureAwait(false);
//}
//public async Task SaveFileAsync()
//{
// if (drawer == null)
// {
// return;
// }
// bool bSuccess = drawer.SaveFile();
// var responseEvent = new JsEvent("Save");
// responseEvent.Data = bSuccess;
// await SendTargetedEvent(socketContex, responseEvent).ConfigureAwait(false);
//}
//[Route(HttpVerbs.Get, "/ZoomIn")]
//public async Task ZoomIn(Dictionary keyValues)
//{
// //this.drawer = GetCurrentDrawer();
// if (drawer == null)
// {
// return;
// }
// double dWidth = Convert.ToDouble(keyValues["width"]);
// double dHeight = Convert.ToDouble(keyValues["height"]);
// drawer.DrawerSize = new Size((int)dWidth, (int)dHeight);
// drawer.ZoomIn();
// await ShowImgAsync();
//}
//[Route(HttpVerbs.Get, "/ZoomOut")]
//public async Task ZoomOut(Dictionary keyValues)
//{
// //this.drawer = GetCurrentDrawer();
// if (drawer == null)
// {
// return;
// }
// double dWidth = Convert.ToDouble(keyValues["width"]);
// double dHeight = Convert.ToDouble(keyValues["height"]);
// drawer.DrawerSize = new Size((int)dWidth, (int)dHeight);
// drawer.ZoomOut();
// await this.ShowImgAsync();
//}
//public async Task ViewAll(Dictionary keyValues)
//{
// if (drawer == null)
// {
// return;
// }
// double dWidth = Convert.ToDouble(keyValues["width"]);
// double dHeight = Convert.ToDouble(keyValues["height"]);
// drawer.DrawerSize = new Size((int)dWidth, (int)dHeight);
// drawer.ViewAll();
// await this.ShowImgAsync();
//}
//[Route(HttpVerbs.Get, "/SelectAll")]
//public async System.Threading.Tasks.Task SelectAll([QueryField]int arg)
//{
// this.drawer = GetCurrentDrawer();
// if (drawer == null)
// {
// return;
// }
// WebDrawToolSelect drawToolSelect = new WebDrawToolSelect(drawer.Geo);
// drawToolSelect.Start();
// drawToolSelect.SelectAll();
// await this.ShowImgAsync();
//}
public static byte[] ConvertBitmapToByteArray(Bitmap bitmap)
{
if(bitmap == null)
{
return null;
}
using (MemoryStream memoryStream = new MemoryStream())
{
// 选择图像格式,可以是Png、Jpeg等
bitmap.Save(memoryStream, ImageFormat.Png);
return memoryStream.ToArray();
}
}
//public async Task SelectLButtonDown(double x, double y)
//{
// if (drawer == null)
// {
// return;
// }
// Bitmap bmp = null;
// await Task.Run(() =>
// {
// lock (locker)
// {
// bmp = drawer.OnLButtonDown(x, y);
// }
// });
// if (bmp != null)
// {
// bmp.MakeTransparent(Color.White);
// Point pt = drawer.CacheImgLocation;
// string strFile = string.Empty;
// try
// {
// strFile = Path.Combine(WebConfig.HtmlRoot, imageFile);
// bmp.Save(strFile);
// }
// catch (Exception ex)
// {
// //Console.WriteLine($"SendImg: {ex.Message}");
// return;
// }
// string strEventName = "DragElement";
// var responseEvent = new JsEvent(strEventName);
// Dictionary keyValues = new Dictionary();
// keyValues.Add("Data", imageFile);
// keyValues.Add("ImgLeft", pt.X);
// keyValues.Add("ImgTop", pt.Y);
// responseEvent.Data = keyValues;
// await SendTargetedEvent(socketContex, responseEvent).ConfigureAwait(false);
// }
//}
///
/// 选中对象
///
///
//[Route(HttpVerbs.Get, "/ClickImage")]
//public async Task SelectMouseUp(double endX, double endY)
//{
// if (drawer == null)
// {
// return;
// }
// Bitmap bmp = null;
// await Task.Run(() =>
// {
// lock (locker)
// {
// bmp = drawer.LButtonUp(endX, endY);
// }
// });
// if (bmp != null)
// {
// // bmp.MakeTransparent(Color.White);
// await SendImg(bmp, string.Empty, false);
// }
//}
////[Route(HttpVerbs.Get, "/LButtonUp")]
//public async Task LButtonUp( double x, double y)
//{
// if (drawer == null)
// {
// return;
// }
// Bitmap bmp = null;
// await Task.Run(() =>
// {
// lock (locker)
// {
// bmp = drawer.LButtonUp(x, y);
// }
// });
// if (bmp != null)
// {
// await SendImg(bmp,string.Empty, false);
// }
//}
//public async Task MouseMove(double x, double y)
//{
// if (drawer == null)
// {
// return ;
// }
// int result = 0;
// //await Task.Run(() =>
// //{
// // lock (locker)
// // {
// result = this.drawer.MouseMove(x, y);
// // }
// //});
// //Console.WriteLine($"MouseMove hanle:{result}");
// var responseEvent = new JsEvent("SelectHandle")
// {
// Data = result,
// };
// await SendTargetedEvent(socketContex, responseEvent).ConfigureAwait(true);
// //return result;
//}
///
/// 移动浏览
///
/// 起始坐标X
/// 起始坐标Y
/// 终止坐标X
/// 终止坐标Y
///
//public async Task ViewPan(Dictionary keyValues)
//{
// if (this.drawer == null)
// {
// return;
// }
// double dStartX = Convert.ToDouble(keyValues["startX"]);
// double dStartY = Convert.ToDouble(keyValues["startY"]);
// double dEndX = Convert.ToDouble(keyValues["endX"]);
// double dEndY = Convert.ToDouble(keyValues["endY"]);
// double dWidth = Convert.ToDouble(keyValues["width"]);
// double dHeight = Convert.ToDouble(keyValues["height"]);
// drawer.DrawerSize = new Size((int)dWidth, (int)dHeight);
// Bitmap bmp = null;
// await Task.Run(() =>
// {
// lock (locker)
// {
// bmp = drawer.ViewOperatorPan(dStartX, dStartY, dEndX, dEndY);
// }
// });
// if (bmp != null)
// {
// await SendImg(bmp);
// }
//}
///
/// 移动浏览
///
/// 起始坐标X
/// 起始坐标Y
/// 终止坐标X
/// 终止坐标Y
///
//public async Task ViewWindow(Dictionary keyValues)
//{
// if (this.drawer == null)
// {
// return;
// }
// double dStartX = Convert.ToDouble(keyValues["startX"]);
// double dStartY = Convert.ToDouble(keyValues["startY"]);
// double dEndX = Convert.ToDouble(keyValues["endX"]);
// double dEndY = Convert.ToDouble(keyValues["endY"]);
// double dWidth = Convert.ToDouble(keyValues["width"]);
// double dHeight = Convert.ToDouble(keyValues["height"]);
// drawer.DrawerSize = new Size((int)dWidth, (int)dHeight);
// Bitmap bmp = drawer.ViewOperatorWindow(dStartX, dStartY, dEndX, dEndY);
// if (bmp != null)
// {
// await SendImg(bmp);
// }
//}
//public async Task TranslateElements( double x, double y)
//{
// if (drawer == null)
// {
// return;
// }
// try
// {
// if (socketContex.WebSocket.State == WebSocketState.Open)
// {
// Bitmap bmp = drawer.TranslateElements(x, y);
// if (bmp != null)
// {
// await SendImg(bmp);
// }
// }
// else
// {
// //Console.WriteLine("WebSocket connection is not open.");
// }
// }
// catch (EmbedIO.WebSockets.WebSocketException ex)
// {
// //Console.WriteLine($"WebSocketException: {ex.Message}");
// }
// catch (Exception ex)
// {
// //Console.WriteLine($"Exception: {ex.Message}");
// }
//}
//[Route(HttpVerbs.Get, "/MouseMove")]
//public async Task MouseMove([QueryField] double x, [QueryField] double y)
//{
// this.drawer = GetCurrentDrawer();
// if (drawer == null)
// {
// return -2;
// }
// return this.drawer.MouseMove(x, y);
//}
//public byte[] GetBytesFromImage(string filename)
//{
// try
// {
// FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read);
// int length = (int)fs.Length;
// byte[] image = new byte[length];
// fs.Read(image, 0, length);
// fs.Close();
// return image;
// }
// catch (Exception ex)
// {
// return null;
// }
//}
#region 图层管理
///
/// 获得图层数据.
///
/// A Task.
//public async Task GetLayers()
//{
// if (this.drawer == null)
// {
// return;
// }
// var responseEvent = new JsEvent("ReloadLayer");
// responseEvent.Data = drawer.LayerTree.Layers;
// await SendTargetedEvent(socketContex, responseEvent).ConfigureAwait(false);
//}
///
/// Sets the layers status.
///
/// The layers status.
/// VIEW_EDIT = 10,
/// VIEW_NOT_EDIT = 11,
/// NOT_VIEW_NOT_EDIT = 12
/// A Task.
//public async Task SetLayersStatus(string layersStatus)
//{
// if (this.drawer == null)
// {
// return;
// }
// GeoLayerTree layerTree = drawer?.LayerTree;
// if (layerTree.SetLayersStatus(layersStatus))
// {
// await this.ShowImgAsync();
// }
//}
///
/// 删除图层
///
///
///
///
//public async Task DeleteLayers(string layers, bool withSubLayer)
//{
// if (drawer == null)
// {
// return;
// }
// var layerArray = layers.Split(new string[] { Environment.NewLine, ","}, StringSplitOptions.RemoveEmptyEntries);
// int nCount = layerArray.Length;
// if(nCount == 0)
// {
// return;
// }
// for(int i=0;i< nCount; i++)
// {
// int nIndexFind = layerArray[i].IndexOf("Layer:\\", 0, StringComparison.CurrentCultureIgnoreCase);
// if (nIndexFind >= 0)
// {
// layerArray[i] = layerArray[i].Remove(0, 7);
// }
// }
// await Task.Run(() =>
// {
// lock (locker)
// {
// drawer.DeleteLayers(layerArray, withSubLayer);
// }
// });
// var responseEvent = new JsEvent("DeleteLayers")
// {
// Data = string.Empty,
// };
// await SendTargetedEvent(socketContex, responseEvent).ConfigureAwait(true);
// await this.ShowImgAsync();
//}
#endregion
#region 数据操作
///
/// 添加数据.
///
/// The data.
/// A Task.
//public async Task AddBufferData(string data)
//{
// if (drawer == null)
// {
// return;
// }
// int nResult = -1;
// await Task.Run(() =>
// {
// lock (locker)
// {
// nResult = drawer.AddBufferData(data);
// }
// });
// var responseEvent = new JsEvent("AddBufferData")
// {
// Data = nResult,
// };
// await SendTargetedEvent(socketContex, responseEvent).ConfigureAwait(true);
//}
#endregion
#region 坐标工具
///
/// Queries the range screen2 real x.
///
/// The start x.
///
/// The start y.
///
/// A Task.
//public async Task QueryRangeScreen2RealX(double startX,double endX, double startY, double endY)
//{
// if (drawer == null)
// {
// return;
// }
// double dRectLeft = 0, dRectRight = 0, dRectTop = 0, dRectBottom = 0;
// await Task.Run(() =>
// {
// lock (locker)
// {
// drawer.Geo.GetScreenReal((int)startX, (int)startY, (int)endX, (int)endY
// , ref dRectLeft, ref dRectTop, ref dRectRight, ref dRectBottom);
// }
// });
// Dictionary keyValues = new Dictionary();
// keyValues.Add("left", dRectLeft);
// keyValues.Add("bottom", dRectBottom);
// keyValues.Add("right", dRectRight);
// keyValues.Add("top", dRectTop);
// var responseEvent = new JsEvent("MapRangeReal")
// {
// Data = keyValues,
// };
// await SendTargetedEvent(socketContex, responseEvent).ConfigureAwait(true);
//}
#endregion
}
public class ActionResult
{
public ActionResult(int resultType, string data, int imgLeft, int imgTop, int imgWidth, int imgHeight)
{
ResultType = resultType;
Data = data;
ImgLeft = imgLeft;
ImgTop = imgTop;
ImgWidth = imgWidth;
ImgHeight = imgHeight;
}
public int ResultType { get; set; } = 0;
public string Data { get; set; } = string.Empty;
public int ImgLeft { get; set; }
public int ImgTop { get; set; }
public int ImgWidth { get; set; }
public int ImgHeight { get; set; }
}
}