forked from powerfun/udpservice
一些功能调整
增加tcp协议支持; 增加模拟多用户的功能;
This commit is contained in:
parent
e8b6418aa6
commit
0e931a3ac9
@ -1,14 +1,12 @@
|
|||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
using OnlineUserPool.Unility;
|
||||||
using OnlineUserPool.Model;
|
using System;
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace OnlineUserPool.Unility
|
namespace OnlineUserPool.Api
|
||||||
{
|
{
|
||||||
public class BaseApi
|
public class BaseApi
|
||||||
{
|
{
|
||||||
@ -19,7 +17,7 @@ namespace OnlineUserPool.Unility
|
|||||||
httpClient.DefaultRequestHeaders.UserAgent.Add(new System.Net.Http.Headers.ProductInfoHeaderValue("OnlineUserPool", "1.0.0"));
|
httpClient.DefaultRequestHeaders.UserAgent.Add(new System.Net.Http.Headers.ProductInfoHeaderValue("OnlineUserPool", "1.0.0"));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static async Task<T> PostAsync<T>(string url, object data)
|
public static async Task<T> PostAsync<T>(string url, object data)
|
||||||
{
|
{
|
||||||
StringContent stringContent;
|
StringContent stringContent;
|
||||||
if (data != null)
|
if (data != null)
|
||||||
@ -35,36 +33,11 @@ namespace OnlineUserPool.Unility
|
|||||||
return JsonConvert.DeserializeObject<T>(result);
|
return JsonConvert.DeserializeObject<T>(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static async Task<T> GetAsync<T>(string url)
|
public static async Task<T> GetAsync<T>(string url)
|
||||||
{
|
{
|
||||||
var response = await httpClient.GetAsync(ConfigHelp.Host + url, HttpCompletionOption.ResponseContentRead).ConfigureAwait(false);
|
var response = await httpClient.GetAsync(ConfigHelp.Host + url, HttpCompletionOption.ResponseContentRead).ConfigureAwait(false);
|
||||||
var result = await response.Content.ReadAsStringAsync();
|
var result = await response.Content.ReadAsStringAsync();
|
||||||
return JsonConvert.DeserializeObject<T>(result);
|
return JsonConvert.DeserializeObject<T>(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public class WebService : BaseApi
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 从服务端获取记录信息
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static List<MapRecordRanking> GetRecordFileFromServer(List<long> id)
|
|
||||||
{
|
|
||||||
if (!id.Any())
|
|
||||||
{
|
|
||||||
return new List<MapRecordRanking>();
|
|
||||||
}
|
|
||||||
return PostAsync<JsonResult<List<MapRecordRanking>>>("MapRecord/GetRandomList", id).ConfigureAwait(false).GetAwaiter().GetResult().data;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<MapRouteAndUserQueryVM> GetMapRouteRandomRecord(int top, IEnumerable<int> routeIds)
|
|
||||||
{
|
|
||||||
var routeIdsStr = "";
|
|
||||||
if(routeIds != null)
|
|
||||||
{
|
|
||||||
routeIdsStr = string.Join(",", routeIds);
|
|
||||||
}
|
|
||||||
return GetAsync<JsonResult<List<MapRouteAndUserQueryVM>>>($"MapRecord/GetRandomRankingUserRecord?top={ top }&routeIds={ routeIdsStr }").ConfigureAwait(false).GetAwaiter().GetResult().data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
41
Api/Model/MultiUserModel.cs
Normal file
41
Api/Model/MultiUserModel.cs
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
using OnlineUserPool.Model;
|
||||||
|
using OnlineUserPool.Unility;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace OnlineUserPool.Api.Model
|
||||||
|
{
|
||||||
|
public class MultiUserModel
|
||||||
|
{
|
||||||
|
public List<User> users { get; set; }
|
||||||
|
|
||||||
|
public MapDataModel route { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public class User
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
public string NickName { get; set; }
|
||||||
|
|
||||||
|
public string WxHeadImg { get; set; }
|
||||||
|
|
||||||
|
public double Weight { get; set; }
|
||||||
|
|
||||||
|
public User()
|
||||||
|
{
|
||||||
|
Speed = CommonHelper.GenerateRandomInteger(0, 30);
|
||||||
|
|
||||||
|
//Distance = CommonHelper.GenerateRandomInteger(0, 30)/1000D;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public double Speed {
|
||||||
|
get;set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double Distance { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
38
Api/WebService.cs
Normal file
38
Api/WebService.cs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
using OnlineUserPool.Model;
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace OnlineUserPool.Api
|
||||||
|
{
|
||||||
|
public class WebService : BaseApi
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 从服务端获取记录信息
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static List<MapRecordRanking> GetRecordFileFromServer(List<long> id)
|
||||||
|
{
|
||||||
|
if (!id.Any())
|
||||||
|
{
|
||||||
|
return new List<MapRecordRanking>();
|
||||||
|
}
|
||||||
|
return PostAsync<JsonResult<List<MapRecordRanking>>>("MapRecord/GetRandomList", id).ConfigureAwait(false).GetAwaiter().GetResult().data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<MapRouteAndUserQueryVM> GetMapRouteRandomRecord(int top, IEnumerable<int> routeIds)
|
||||||
|
{
|
||||||
|
var routeIdsStr = "";
|
||||||
|
if(routeIds != null)
|
||||||
|
{
|
||||||
|
routeIdsStr = string.Join(",", routeIds);
|
||||||
|
}
|
||||||
|
return GetAsync<JsonResult<List<MapRouteAndUserQueryVM>>>($"MapRecord/GetRandomRankingUserRecord?top={ top }&routeIds={ routeIdsStr }").ConfigureAwait(false).GetAwaiter().GetResult().data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,9 +2,8 @@
|
|||||||
<configuration>
|
<configuration>
|
||||||
<appSettings>
|
<appSettings>
|
||||||
<add key="Host" value="http://192.168.0.97:5082/"/>
|
<add key="Host" value="http://192.168.0.97:5082/"/>
|
||||||
<add key="Top" value="10"/>
|
<add key="Top" value="0"/>
|
||||||
<add key="ShowVirtualUser" value="true"/>
|
<add key="ShowVirtualUser" value="true"/>
|
||||||
<add key="Ip" value="192.168.0.97"/>
|
|
||||||
<add key="Port" value="11000"/>
|
<add key="Port" value="11000"/>
|
||||||
</appSettings>
|
</appSettings>
|
||||||
</configuration>
|
</configuration>
|
||||||
14
Hander/IHandle.cs
Normal file
14
Hander/IHandle.cs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
using OnlineUserPool.Model;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace OnlineUserPool.Hander
|
||||||
|
{
|
||||||
|
interface IHandle
|
||||||
|
{
|
||||||
|
List<MsgModel> GetVirtualUserData();
|
||||||
|
|
||||||
|
void RemoveEndAndAddNewVirtualUser(int customerCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,4 +1,5 @@
|
|||||||
using OnlineUserPool.Model;
|
using OnlineUserPool.Api;
|
||||||
|
using OnlineUserPool.Model;
|
||||||
using OnlineUserPool.Unility;
|
using OnlineUserPool.Unility;
|
||||||
|
|
||||||
using Serilog;
|
using Serilog;
|
||||||
@ -10,11 +11,11 @@ using System.Text;
|
|||||||
|
|
||||||
namespace OnlineUserPool.Hander
|
namespace OnlineUserPool.Hander
|
||||||
{
|
{
|
||||||
public class MapRecordRankingHander
|
public class MapRecordRankingHander : IHandle
|
||||||
{
|
{
|
||||||
private static List<MapRecordRanking> mapRecordRankings;
|
private static List<MapRecordRanking> mapRecordRankings = new List<MapRecordRanking>();
|
||||||
private static object locker = new object();//防止服务端响应慢,多次加载
|
private static object locker = new object();//防止服务端响应慢,多次加载
|
||||||
private int top = ConfigHelp.Top;
|
//private int top = ConfigHelp.Top;
|
||||||
|
|
||||||
public MapRecordRankingHander()
|
public MapRecordRankingHander()
|
||||||
{
|
{
|
||||||
@ -23,13 +24,15 @@ namespace OnlineUserPool.Hander
|
|||||||
|
|
||||||
private void Init()
|
private void Init()
|
||||||
{
|
{
|
||||||
var records = WebService.GetMapRouteRandomRecord(top, null);
|
if (ConfigHelp.Top > 0)
|
||||||
var pageSize = 10;
|
|
||||||
var pageCount = (int)Math.Ceiling(records.Count / (double)pageSize);
|
|
||||||
mapRecordRankings = new List<MapRecordRanking>();
|
|
||||||
for (int i = 0; i < pageCount; i++)
|
|
||||||
{
|
{
|
||||||
mapRecordRankings.AddRange(WebService.GetRecordFileFromServer(records.Skip(i* pageSize).Take(pageSize).Select(n => n.Id).ToList()));
|
var records = WebService.GetMapRouteRandomRecord(ConfigHelp.Top, null);
|
||||||
|
var pageSize = 10;
|
||||||
|
var pageCount = (int)Math.Ceiling(records.Count / (double)pageSize);
|
||||||
|
for (int i = 0; i < pageCount; i++)
|
||||||
|
{
|
||||||
|
mapRecordRankings.AddRange(WebService.GetRecordFileFromServer(records.Skip(i * pageSize).Take(pageSize).Select(n => n.Id).ToList()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,9 +76,9 @@ namespace OnlineUserPool.Hander
|
|||||||
//Prop = string.Join(',', prop),
|
//Prop = string.Join(',', prop),
|
||||||
RouteId = item.RouteId,
|
RouteId = item.RouteId,
|
||||||
EndDistance = Math.Round(targetData._Distance, 6),
|
EndDistance = Math.Round(targetData._Distance, 6),
|
||||||
ShowVirtual = true,
|
//ShowVirtual = true,
|
||||||
CommandType = 1,
|
CommandType = 1,
|
||||||
IsVirtual = true,
|
//IsVirtual = true,
|
||||||
Speed = targetData._Speed,
|
Speed = targetData._Speed,
|
||||||
WeightKg = weightKg,
|
WeightKg = weightKg,
|
||||||
PreDistance = item.GetPreDistance()
|
PreDistance = item.GetPreDistance()
|
||||||
@ -94,31 +97,31 @@ namespace OnlineUserPool.Hander
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 删除已经骑行完的人,添加新的人物进去
|
/// 删除已经骑行完的人,添加新的人物进去
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void RemoveEndAndAddNewVirtualUser()
|
public void RemoveEndAndAddNewVirtualUser(int customerCount)
|
||||||
{
|
{
|
||||||
lock (locker)
|
lock (locker)
|
||||||
{
|
{
|
||||||
var end = mapRecordRankings.FindAll(n => n.End);
|
mapRecordRankings.RemoveAll(n => n.End);
|
||||||
//if (end.Count == mapRecordRankings.Count)
|
//var virutalEndCount = mapRecordRankings.Count(d => d.UserId < 0 && d.End);
|
||||||
//{
|
var routeIds = mapRecordRankings.Select(n => n.RouteId).Distinct().ToList();
|
||||||
// Init();
|
|
||||||
//}
|
|
||||||
if (end.Count > 0)
|
|
||||||
{
|
|
||||||
var virutalEndCount = mapRecordRankings.Count(d => d.UserId < 0 && d.End);
|
|
||||||
var routeIds = mapRecordRankings.Select(n => n.RouteId).Distinct().ToList();
|
|
||||||
mapRecordRankings.RemoveAll(n => n.End);
|
|
||||||
if (virutalEndCount > 0)
|
|
||||||
{
|
|
||||||
var randomUser = WebService.GetMapRouteRandomRecord(virutalEndCount, routeIds);
|
|
||||||
|
|
||||||
//var str = "参数:" + (ConfigHelp.Top - virutalEndCount) + "," + string.Join(",",routeIds) + "\r\n";
|
var top = ConfigHelp.Top;
|
||||||
//str += "服务端返回:" + Newtonsoft.Json.JsonConvert.SerializeObject(randomUser) +"\r\n";
|
if(customerCount > 9)
|
||||||
//Log.Information(str);
|
{
|
||||||
var addRankings = WebService.GetRecordFileFromServer(randomUser.Select(n => n.Id).ToList());
|
top = 0;
|
||||||
mapRecordRankings.AddRange(addRankings);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if(top - mapRecordRankings.Count(d=>d.UserId<0) > 0)
|
||||||
|
{
|
||||||
|
var count = top - mapRecordRankings.Count(d => d.UserId < 0);
|
||||||
|
var randomUser = WebService.GetMapRouteRandomRecord(count, routeIds);
|
||||||
|
|
||||||
|
//var str = "参数:" + (ConfigHelp.Top - virutalEndCount) + "," + string.Join(",",routeIds) + "\r\n";
|
||||||
|
//str += "服务端返回:" + Newtonsoft.Json.JsonConvert.SerializeObject(randomUser) +"\r\n";
|
||||||
|
//Log.Information(str);
|
||||||
|
var addRankings = WebService.GetRecordFileFromServer(randomUser.Select(n => n.Id).ToList());
|
||||||
|
mapRecordRankings.AddRange(addRankings);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
84
Hander/MultiUserHandle.cs
Normal file
84
Hander/MultiUserHandle.cs
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
using OnlineUserPool.Api;
|
||||||
|
using OnlineUserPool.Api.Model;
|
||||||
|
using OnlineUserPool.Model;
|
||||||
|
using OnlineUserPool.Unility;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace OnlineUserPool.Hander
|
||||||
|
{
|
||||||
|
public class MultiUserHandle : IHandle
|
||||||
|
{
|
||||||
|
private int _index = -1;
|
||||||
|
private MultiUserModel model;
|
||||||
|
private TurfHelper _turfHelper;
|
||||||
|
private int _routeId = 4297; //1660;
|
||||||
|
private int _size = 200;
|
||||||
|
public MultiUserHandle()
|
||||||
|
{
|
||||||
|
Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async void Init()
|
||||||
|
{
|
||||||
|
model = await BaseApi.GetAsync<MultiUserModel>($"/Map/sss?routeId={ _routeId }&size={ _size }");
|
||||||
|
double i = 0;
|
||||||
|
foreach (var item in model.users)
|
||||||
|
{
|
||||||
|
i += 0.0005;
|
||||||
|
item.Distance = i;
|
||||||
|
}
|
||||||
|
_turfHelper = new TurfHelper(model.route.List.Select(d => d.Point));
|
||||||
|
//Debug.WriteLine(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<MsgModel> GetVirtualUserData()
|
||||||
|
{
|
||||||
|
_index++;
|
||||||
|
|
||||||
|
var msgModels = new List<MsgModel>();
|
||||||
|
if(model == null)
|
||||||
|
{
|
||||||
|
return msgModels;
|
||||||
|
}
|
||||||
|
foreach (var item in model.users)
|
||||||
|
{
|
||||||
|
var preDistance = 0D;
|
||||||
|
//item.Distance = CommonHelper.GenerateRandomInteger(0, 30) / 1000D;
|
||||||
|
if (_index > 0)
|
||||||
|
{
|
||||||
|
preDistance = item.Distance * (_index -1);
|
||||||
|
}
|
||||||
|
var point = _turfHelper.Along(item.Distance * _index);
|
||||||
|
var info = new MsgModel()
|
||||||
|
{
|
||||||
|
exit = false,
|
||||||
|
IsCompleted = false,
|
||||||
|
MemberId = item.Id,//虚拟的人Id变为负数
|
||||||
|
Point = new double[] { Math.Round(point.Latitude, 6), Math.Round(point.Longitude, 6) },
|
||||||
|
//Prop = string.Join(',', prop),
|
||||||
|
RouteId = _routeId,
|
||||||
|
EndDistance = item.Distance * _index,
|
||||||
|
//ShowVirtual = true,
|
||||||
|
CommandType = 1,
|
||||||
|
//IsVirtual = true,
|
||||||
|
Speed = item.Speed,
|
||||||
|
WeightKg = 0,
|
||||||
|
PreDistance = preDistance,
|
||||||
|
Competitionid = 30
|
||||||
|
};
|
||||||
|
msgModels.Add(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
return msgModels;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveEndAndAddNewVirtualUser(int customerCount)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,4 +1,5 @@
|
|||||||
using Prism.Mvvm;
|
using OnlineUserPool.Services;
|
||||||
|
using Prism.Mvvm;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
@ -50,9 +51,26 @@ namespace OnlineUserPool.Model
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public List<int> ShowRouteId { get; set; }
|
public List<int> ShowRouteId { get; set; }
|
||||||
|
|
||||||
|
///// <summary>
|
||||||
|
///// 是否展示在线的人
|
||||||
|
///// </summary>
|
||||||
|
//public bool ShowVirtual { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 是否展示在线的人
|
/// 客户端支持的消息格式的版本号
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool ShowVirtual { get; set; }
|
public int V { get; set; }
|
||||||
|
|
||||||
|
[Newtonsoft.Json.JsonIgnore]
|
||||||
|
public IService Service { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public String ServiceName
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Service.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
103
Model/MapDataModel.cs
Normal file
103
Model/MapDataModel.cs
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using OnlineUserPool.Unility;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace OnlineUserPool.Model
|
||||||
|
{
|
||||||
|
public class MapDataModel
|
||||||
|
{
|
||||||
|
public string Type => "LineString";
|
||||||
|
/// <summary>
|
||||||
|
/// 总距离(km)
|
||||||
|
/// </summary>
|
||||||
|
public double TotalDistance { get; set; }
|
||||||
|
|
||||||
|
private List<Item> _List;
|
||||||
|
public List<Item> List
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _List;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_List = value;
|
||||||
|
if (_List == null) return;
|
||||||
|
this.CalcDistance();
|
||||||
|
this.CalcGrade();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void CalcDistance()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < _List.Count - 1; i++)
|
||||||
|
{
|
||||||
|
var value = CommonHelper.GetDistances(_List[i].Point[1], _List[i].Point[0], _List[i + 1].Point[1], _List[i + 1].Point[0]);
|
||||||
|
//var value = Turf.Distance(pt1, pt2, "kilometers") * 1000;
|
||||||
|
_List[i].Distance = Math.Round(value, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 计算坡度数据
|
||||||
|
/// </summary>
|
||||||
|
private void CalcGrade()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < this._List.Count - 1; i++)
|
||||||
|
{
|
||||||
|
var a = _List[i + 1].Elevation - _List[i].Elevation;
|
||||||
|
if (a == 0)
|
||||||
|
{
|
||||||
|
//grade.Add(0);
|
||||||
|
_List[i].Grade = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
//勾股定理
|
||||||
|
var c = _List[i].Distance;//如果车停了下来,c为0
|
||||||
|
if (c == 0 && i > 0)
|
||||||
|
{
|
||||||
|
_List[i].Grade = _List[i - 1].Grade;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var b = Math.Sqrt(c * c - a * a);
|
||||||
|
if (b == 0)//如果b等于,这就是垂直的墙壁
|
||||||
|
{
|
||||||
|
_List[i].Grade = _List[i - 1].Grade;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_List[i].Grade = Math.Round(a / b * 100, 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public MapDataModel()
|
||||||
|
{
|
||||||
|
//_List = new List<Item>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Item
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 坐标(lat,lon)
|
||||||
|
/// </summary>
|
||||||
|
public double[] Point { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 距离(单位米)
|
||||||
|
/// </summary>
|
||||||
|
[JsonIgnore]
|
||||||
|
public double Distance { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 海拔m
|
||||||
|
/// </summary>
|
||||||
|
public double Elevation { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
|
public double Grade { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -25,13 +25,13 @@ namespace OnlineUserPool.Model
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 是否展示在线的人
|
/// 是否展示在线的人
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool ShowVirtual { get; set; }
|
//public bool ShowVirtual { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 命令类型,0命令,1消息
|
/// 命令类型,0命令,1消息
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public byte CommandType { get; set; }
|
public byte CommandType { get; set; }
|
||||||
|
|
||||||
public bool IsVirtual { get; set; }
|
//public bool IsVirtual { get; set; }
|
||||||
|
|
||||||
//public double Power { get; set; }
|
//public double Power { get; set; }
|
||||||
//public double Weight { get; set; }
|
//public double Weight { get; set; }
|
||||||
@ -43,5 +43,15 @@ namespace OnlineUserPool.Model
|
|||||||
public int Competitionid { get; set; }
|
public int Competitionid { get; set; }
|
||||||
|
|
||||||
public bool Saved { get; set; }
|
public bool Saved { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 能处理的消息格式的版本号
|
||||||
|
/// </summary>
|
||||||
|
public int V { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public string ToString(int v)
|
||||||
|
{
|
||||||
|
return $"{ RouteId },{ MemberId },{ string.Join(":", Point) },{ Convert.ToInt32(IsCompleted) },{ Speed },{ PreDistance },{ EndDistance },{ WeightKg },{ Competitionid },{ Convert.ToInt32(Saved) }";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -46,7 +46,11 @@ namespace OnlineUserPool.Model
|
|||||||
target._Speed = double.Parse(split[2]);
|
target._Speed = double.Parse(split[2]);
|
||||||
target._Distance = double.Parse(split[3]);
|
target._Distance = double.Parse(split[3]);
|
||||||
target._Cadence = double.Parse(split[4]);
|
target._Cadence = double.Parse(split[4]);
|
||||||
target._HeartRate = int.Parse(split[5]);
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(split[5]) && split[5] != "null")
|
||||||
|
{
|
||||||
|
target._HeartRate = int.Parse(split[5]);
|
||||||
|
}
|
||||||
if (split.Length > 6)
|
if (split.Length > 6)
|
||||||
{
|
{
|
||||||
target._Lat = double.Parse(split[6]);
|
target._Lat = double.Parse(split[6]);
|
||||||
|
|||||||
@ -5,7 +5,13 @@
|
|||||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
<UseWPF>true</UseWPF>
|
<UseWPF>true</UseWPF>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Remove="Services\TcpService.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="GeoJSON.Net" Version="0.1.51" />
|
||||||
|
<PackageReference Include="NetCoreServer" Version="3.0.22" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||||
<PackageReference Include="Prism.Unity" Version="7.2.0.1422" />
|
<PackageReference Include="Prism.Unity" Version="7.2.0.1422" />
|
||||||
<PackageReference Include="Prism.Wpf" Version="7.2.0.1422" />
|
<PackageReference Include="Prism.Wpf" Version="7.2.0.1422" />
|
||||||
@ -14,5 +20,10 @@
|
|||||||
<PackageReference Include="Serilog.Sinks.File" Version="4.1.0" />
|
<PackageReference Include="Serilog.Sinks.File" Version="4.1.0" />
|
||||||
<PackageReference Include="System.Configuration.ConfigurationManager" Version="4.7.0" />
|
<PackageReference Include="System.Configuration.ConfigurationManager" Version="4.7.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="TurfCS">
|
||||||
|
<HintPath>..\PowerFun Server\PowerFun Server\lib\TurfCS.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
17
Services/IService.cs
Normal file
17
Services/IService.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
using OnlineUserPool.Model;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Net;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace OnlineUserPool.Services
|
||||||
|
{
|
||||||
|
public interface IService
|
||||||
|
{
|
||||||
|
public void RunServer(Action<IPEndPoint, MsgModel, IService> action);
|
||||||
|
|
||||||
|
public void Send(byte[] dgram, int bytes, IPEndPoint endPoint);
|
||||||
|
|
||||||
|
public void Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
93
Services/TcpService.cs
Normal file
93
Services/TcpService.cs
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
using OnlineUserPool.Model;
|
||||||
|
using OnlineUserPool.Unility;
|
||||||
|
using Serilog;
|
||||||
|
using SimpleTcp;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace OnlineUserPool.Services
|
||||||
|
{
|
||||||
|
public class TcpService : IService
|
||||||
|
{
|
||||||
|
private bool _stop = false;
|
||||||
|
SimpleTcpServer socket;
|
||||||
|
Action<IPEndPoint, MsgModel, IService> _action;
|
||||||
|
|
||||||
|
public void RunServer(Action<IPEndPoint, MsgModel, IService> action)
|
||||||
|
{
|
||||||
|
//throw new NotImplementedException();
|
||||||
|
|
||||||
|
_action = action;
|
||||||
|
//var ip = IPAddress.Parse("192.168.0.97");
|
||||||
|
var b = IPAddress.Any;
|
||||||
|
socket = new SimpleTcpServer($"{ IPAddress.Any }:11001");
|
||||||
|
socket.Events.ClientConnected += Events_ClientConnected;
|
||||||
|
socket.Events.ClientDisconnected += Events_ClientDisconnected;
|
||||||
|
socket.Events.DataReceived += Events_DataReceived;
|
||||||
|
|
||||||
|
Task.Run(() =>
|
||||||
|
{
|
||||||
|
socket.Start();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Events_DataReceived(object sender, SimpleTcp.DataReceivedEventArgs e)
|
||||||
|
{
|
||||||
|
var returnData = Encoding.UTF8.GetString(e.Data);
|
||||||
|
Debug.WriteLine(returnData);
|
||||||
|
|
||||||
|
foreach (var item in returnData.Split(new string[] { "}" }, StringSplitOptions.RemoveEmptyEntries))
|
||||||
|
{
|
||||||
|
var msg = Newtonsoft.Json.JsonConvert.DeserializeObject<MsgModel>(item +"}");
|
||||||
|
var ipEndPoint = IPEndPoint.Parse(e.IpPort);
|
||||||
|
_action(ipEndPoint, msg, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Events_ClientDisconnected(object sender, ClientDisconnectedEventArgs e)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Events_ClientConnected(object sender, ClientConnectedEventArgs e)
|
||||||
|
{
|
||||||
|
Debug.WriteLine("有新客户端连接" + e.IpPort);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Send(byte[] dgram, int bytes, IPEndPoint endPoint)
|
||||||
|
{
|
||||||
|
if(dgram == null || !dgram.Any())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var item in socket.GetClients())
|
||||||
|
{
|
||||||
|
//try
|
||||||
|
//{
|
||||||
|
if(socket.IsConnected(item) == false)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
socket.Send(item, dgram);
|
||||||
|
//}
|
||||||
|
//catch(Exception e)
|
||||||
|
//{
|
||||||
|
// Log.Error($"{ item.ToString() }:{ e.Message }\r\n{ e.StackTrace }");
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
_stop = true;
|
||||||
|
socket.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
118
Services/TcpService1.cs
Normal file
118
Services/TcpService1.cs
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
using NetCoreServer;
|
||||||
|
using OnlineUserPool.Model;
|
||||||
|
using Serilog;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace OnlineUserPool.Services
|
||||||
|
{
|
||||||
|
public class TcpService1 : IService
|
||||||
|
{
|
||||||
|
private PfTcpServer _server;
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
//throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RunServer(Action<IPEndPoint, MsgModel, IService> action)
|
||||||
|
{
|
||||||
|
//throw new NotImplementedException();
|
||||||
|
//_action = action;
|
||||||
|
_server = new PfTcpServer(IPAddress.Any, 11001, (ip, model)=> {
|
||||||
|
action(ip, model, this);
|
||||||
|
});
|
||||||
|
//_server.OptionNoDelay = true;
|
||||||
|
_server.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public void Send(byte[] dgram, int bytes, IPEndPoint endPoint)
|
||||||
|
{
|
||||||
|
if (dgram == null || !dgram.Any())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_server.Multicast(dgram);
|
||||||
|
}
|
||||||
|
|
||||||
|
class PfTcpServer : TcpServer
|
||||||
|
{
|
||||||
|
Action<IPEndPoint, MsgModel> _action;
|
||||||
|
public PfTcpServer(IPAddress address, int port, Action<IPEndPoint, MsgModel> action) :base(address, port)
|
||||||
|
{
|
||||||
|
_action = action;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override TcpSession CreateSession()
|
||||||
|
{
|
||||||
|
//return base.CreateSession()
|
||||||
|
return new PfTcpSession(this, _action);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnError(SocketError error)
|
||||||
|
{
|
||||||
|
//base.OnError(error);
|
||||||
|
Debug.WriteLine(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PfTcpSession : TcpSession
|
||||||
|
{
|
||||||
|
Action<IPEndPoint, MsgModel> _action;
|
||||||
|
public PfTcpSession(TcpServer server, Action<IPEndPoint, MsgModel> action) : base(server) {
|
||||||
|
_action = action;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnConnected()
|
||||||
|
{
|
||||||
|
//base.OnConnected();
|
||||||
|
Debug.WriteLine("有新的Tcp连接");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnDisconnected()
|
||||||
|
{
|
||||||
|
//base.OnDisconnected();
|
||||||
|
Debug.WriteLine("Tcp断开连接");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnReceived(byte[] buffer, long offset, long size)
|
||||||
|
{
|
||||||
|
//base.OnReceived(buffer, offset, size);
|
||||||
|
var returnData = Encoding.UTF8.GetString(buffer, (int)offset, (int)size);
|
||||||
|
//Debug.WriteLine(returnData);
|
||||||
|
//Log.Information(returnData + "\r\n");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//var msg = Newtonsoft.Json.JsonConvert.DeserializeObject<MsgModel>(returnData);
|
||||||
|
//var ipEndPoint = IPEndPoint.Parse(this.Socket.RemoteEndPoint.ToString());
|
||||||
|
//_action(ipEndPoint, msg);
|
||||||
|
|
||||||
|
foreach (var item in returnData.Split(new string[] { "}" }, StringSplitOptions.RemoveEmptyEntries))
|
||||||
|
{
|
||||||
|
//if (string.IsNullOrWhiteSpace(item)) continue;
|
||||||
|
var msg = Newtonsoft.Json.JsonConvert.DeserializeObject<MsgModel>(item + "}");
|
||||||
|
var ipEndPoint = IPEndPoint.Parse(this.Socket.RemoteEndPoint.ToString());
|
||||||
|
_action(ipEndPoint, msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Error($"接受到的数据处理时出错:{ returnData }\r\n{ ex.Message }\r\n{ ex.StackTrace }");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnError(SocketError error)
|
||||||
|
{
|
||||||
|
//base.OnError(error);
|
||||||
|
Debug.WriteLine(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
80
Services/UdpService.cs
Normal file
80
Services/UdpService.cs
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
using OnlineUserPool.Model;
|
||||||
|
using OnlineUserPool.Unility;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace OnlineUserPool.Services
|
||||||
|
{
|
||||||
|
public class UdpService : IService
|
||||||
|
{
|
||||||
|
private bool _stop = false;
|
||||||
|
//private static IPEndPoint serverIpEndPoint;
|
||||||
|
private static UdpClient udpServer;
|
||||||
|
|
||||||
|
public UdpService()
|
||||||
|
{
|
||||||
|
//serverIpEndPoint = new IPEndPoint(IPAddress.Parse(ConfigHelp.Ip), ConfigHelp.Port);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RunServer(Action<IPEndPoint, MsgModel, IService> action)
|
||||||
|
{
|
||||||
|
udpServer = new UdpClient(ConfigHelp.Port);
|
||||||
|
uint IOC_IN = 0x80000000;
|
||||||
|
uint IOC_VENDOR = 0x18000000;
|
||||||
|
uint SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12;
|
||||||
|
udpServer.Client.IOControl((int)SIO_UDP_CONNRESET, new byte[] { Convert.ToByte(false) }, null);
|
||||||
|
var remoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);
|
||||||
|
Task.Run(() =>
|
||||||
|
{
|
||||||
|
while (_stop == false)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
byte[] receiveBytes = udpServer.Receive(ref remoteIpEndPoint);
|
||||||
|
var returnData = Encoding.ASCII.GetString(receiveBytes);
|
||||||
|
var msg = Newtonsoft.Json.JsonConvert.DeserializeObject<MsgModel>(returnData);
|
||||||
|
|
||||||
|
//lock (locker)
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
WriteLine($"本次接收:{ remoteIpEndPoint.Address.ToString() }:{ remoteIpEndPoint.Port }收到消息:{ returnData }");
|
||||||
|
#endif
|
||||||
|
action(remoteIpEndPoint, msg, this);
|
||||||
|
|
||||||
|
//if (timer.AutoReset == false)
|
||||||
|
//{
|
||||||
|
// timer.AutoReset = true;
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Serilog.Log.Error("RunServer:" + e.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void Send(byte[] dgram, int bytes, IPEndPoint endPoint)
|
||||||
|
{
|
||||||
|
udpServer.Send(dgram, bytes, endPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
_stop = true;
|
||||||
|
udpServer.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteLine(string str)
|
||||||
|
{
|
||||||
|
//Debug.WriteLine(str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
27
Unility/CommonHelper.cs
Normal file
27
Unility/CommonHelper.cs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Text;
|
||||||
|
using TurfCS;
|
||||||
|
|
||||||
|
namespace OnlineUserPool.Unility
|
||||||
|
{
|
||||||
|
public class CommonHelper
|
||||||
|
{
|
||||||
|
public static double GetDistances(double lon, double lat, double lon1, double lat1)
|
||||||
|
{
|
||||||
|
var pt1 = Turf.Point(new double[] { lon, lat });
|
||||||
|
var pt2 = Turf.Point(new double[] { lon1, lat1 });
|
||||||
|
|
||||||
|
var value = Turf.Distance(pt1, pt2, "kilometers") * 1000;
|
||||||
|
return Math.Round(value, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int GenerateRandomInteger(int min = 0, int max = int.MaxValue)
|
||||||
|
{
|
||||||
|
var randomNumberBuffer = new byte[10];
|
||||||
|
new RNGCryptoServiceProvider().GetBytes(randomNumberBuffer);
|
||||||
|
return new Random(BitConverter.ToInt32(randomNumberBuffer, 0)).Next(min, max);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -7,20 +7,26 @@ namespace OnlineUserPool.Unility
|
|||||||
class ConfigHelp
|
class ConfigHelp
|
||||||
{
|
{
|
||||||
public static string Host { get; set; }
|
public static string Host { get; set; }
|
||||||
public static int Top { get; private set; }
|
public static int Top
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["Top"]);
|
||||||
|
}
|
||||||
|
}
|
||||||
public static bool ShowVirtualUser { get; set; }
|
public static bool ShowVirtualUser { get; set; }
|
||||||
|
|
||||||
public static string Ip { get; set; }
|
//public static string Ip { get; private set; }
|
||||||
|
|
||||||
public static int Port { get; set; }
|
public static int Port { get; private set; }
|
||||||
|
|
||||||
|
|
||||||
static ConfigHelp()
|
static ConfigHelp()
|
||||||
{
|
{
|
||||||
Host = System.Configuration.ConfigurationManager.AppSettings["Host"];
|
Host = System.Configuration.ConfigurationManager.AppSettings["Host"];
|
||||||
Top = Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["Top"]);
|
//Top = Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["Top"]);
|
||||||
ShowVirtualUser = bool.Parse(System.Configuration.ConfigurationManager.AppSettings["ShowVirtualUser"]);
|
ShowVirtualUser = bool.Parse(System.Configuration.ConfigurationManager.AppSettings["ShowVirtualUser"]);
|
||||||
Ip = System.Configuration.ConfigurationManager.AppSettings["Ip"];
|
//Ip = System.Configuration.ConfigurationManager.AppSettings["Ip"];
|
||||||
Port = int.Parse(System.Configuration.ConfigurationManager.AppSettings["Port"]);
|
Port = int.Parse(System.Configuration.ConfigurationManager.AppSettings["Port"]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
38
Unility/TurfHelper.cs
Normal file
38
Unility/TurfHelper.cs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
using GeoJSON.Net.Geometry;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using TurfCS;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace OnlineUserPool.Unility
|
||||||
|
{
|
||||||
|
public class TurfHelper
|
||||||
|
{
|
||||||
|
private LineString _line;
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="points">坐标(lat,lon)</param>
|
||||||
|
public TurfHelper(IEnumerable<double[]> points)
|
||||||
|
{
|
||||||
|
//var list = new GeoJSON.Net.Geometry.GeographicPosition();
|
||||||
|
var list = points.Select(p => new GeoJSON.Net.Geometry.GeographicPosition(p[0], p[1]));
|
||||||
|
|
||||||
|
_line = new LineString(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="distance">km</param>
|
||||||
|
public GeographicPosition Along(double distance)
|
||||||
|
{
|
||||||
|
var pt1 = Turf.Along(_line, distance);
|
||||||
|
return ((GeographicPosition)((GeoJSON.Net.Geometry.Point)pt1.Geometry).Coordinates);
|
||||||
|
//new LineString()
|
||||||
|
//new GeoJSON.Net.Geometry.Point(new GeoJSON.Net.Geometry.GeographicPosition())
|
||||||
|
//pt1.BoundingBoxes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -13,18 +13,19 @@ using System.Net.Sockets;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows.Threading;
|
using System.Windows.Threading;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using OnlineUserPool.Services;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
|
||||||
namespace OnlineUserPool.ViewModels
|
namespace OnlineUserPool.ViewModels
|
||||||
{
|
{
|
||||||
public class MainWindowViewModel : BindableBase
|
public class MainWindowViewModel : BindableBase
|
||||||
{
|
{
|
||||||
private static IPEndPoint serverIpEndPoint;
|
|
||||||
private static UdpClient udpServer;
|
|
||||||
public ObservableCollection<HostModel> Clients { get; private set; } = new ObservableCollection<HostModel>();
|
public ObservableCollection<HostModel> Clients { get; private set; } = new ObservableCollection<HostModel>();
|
||||||
private static List<MsgModel> receiveMes = new List<MsgModel>();
|
private static ConcurrentBag<MsgModel> receiveMes = new ConcurrentBag<MsgModel>();
|
||||||
private static object locker = new object();
|
private static object locker = new object();
|
||||||
public static System.Timers.Timer timer;
|
public static System.Timers.Timer timer;
|
||||||
private static MapRecordRankingHander mapRecordRankingHander;
|
private static IHandle mapRecordRankingHander;
|
||||||
|
|
||||||
private Dispatcher dispatcher;
|
private Dispatcher dispatcher;
|
||||||
public ObservableCollection<MsgModel> Customers { get; private set; } =
|
public ObservableCollection<MsgModel> Customers { get; private set; } =
|
||||||
@ -40,23 +41,36 @@ namespace OnlineUserPool.ViewModels
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string _SendDataSize = "";
|
||||||
|
public string SendDataSize
|
||||||
|
{
|
||||||
|
get { return _SendDataSize; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
SetProperty(ref _SendDataSize, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//private IService _udpService;
|
||||||
public MainWindowViewModel()
|
public MainWindowViewModel()
|
||||||
{
|
{
|
||||||
Title = $"{ ConfigHelp.Ip }:{ ConfigHelp.Port }";
|
Title = $"{ IPAddress.Any }:{ ConfigHelp.Port }";
|
||||||
|
|
||||||
dispatcher = Dispatcher.CurrentDispatcher;
|
dispatcher = Dispatcher.CurrentDispatcher;
|
||||||
|
|
||||||
//Customers.Add("suntao");
|
//Customers.Add("suntao");
|
||||||
WriteLine(DateTime.Now.ToShortDateString());
|
WriteLine(DateTime.Now.ToShortDateString());
|
||||||
WriteLine("加载日志组件");
|
|
||||||
LogHelper.Init();
|
LogHelper.Init();
|
||||||
Log.Information("日志组件加载完成");
|
|
||||||
Log.Information("加载虚拟人物");
|
|
||||||
mapRecordRankingHander = new MapRecordRankingHander();
|
mapRecordRankingHander = new MapRecordRankingHander();
|
||||||
Log.Information("虚拟人物加载完成");
|
Log.Information($"初始化连接,当前地址:{ IPAddress.Any }:{ConfigHelp.Port}");
|
||||||
Log.Information($"初始化连接,当前地址:{ConfigHelp.Ip}:{ConfigHelp.Port}");
|
|
||||||
serverIpEndPoint = new IPEndPoint(IPAddress.Parse(ConfigHelp.Ip), ConfigHelp.Port);
|
new TcpService1().RunServer(ReceivedData);
|
||||||
RunServer();
|
//var tet = new System.Collections.Concurrent.ConcurrentBag<object>();
|
||||||
|
|
||||||
|
var _udpService = new UdpService();
|
||||||
|
_udpService.RunServer(ReceivedData);
|
||||||
|
|
||||||
|
|
||||||
Log.Information("服务启动成功");
|
Log.Information("服务启动成功");
|
||||||
timer = new System.Timers.Timer(1000);
|
timer = new System.Timers.Timer(1000);
|
||||||
timer.Elapsed += Timer_Elapsed;
|
timer.Elapsed += Timer_Elapsed;
|
||||||
@ -66,96 +80,67 @@ namespace OnlineUserPool.ViewModels
|
|||||||
//Console.ReadKey();
|
//Console.ReadKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ReceivedData(IPEndPoint remoteIpEndPoint, MsgModel msg, IService service)
|
||||||
|
{
|
||||||
|
dispatcher.Invoke(() =>
|
||||||
|
{
|
||||||
|
if (!Clients.Any(c => c.Equals(remoteIpEndPoint)))
|
||||||
|
{
|
||||||
|
Clients.Add(new HostModel
|
||||||
|
{
|
||||||
|
IPEndPoint = remoteIpEndPoint,
|
||||||
|
LastActiveTime = DateTime.Now,
|
||||||
|
RouteId = msg.RouteId,
|
||||||
|
MemberId = msg.MemberId,
|
||||||
|
//ShowVirtual = msg.ShowVirtual
|
||||||
|
V = msg.V,
|
||||||
|
Service = service
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msg.CommandType == 0)
|
||||||
|
{
|
||||||
|
var client = Clients.FirstOrDefault(n => n.Equals(remoteIpEndPoint));
|
||||||
|
client.LastActiveTime = DateTime.Now;
|
||||||
|
//client.ShowVirtual = msg.ShowVirtual;
|
||||||
|
}
|
||||||
|
else if (msg.CommandType == 1)
|
||||||
|
{
|
||||||
|
receiveMes.Add(msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
|
private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
|
||||||
{
|
{
|
||||||
NotifyClient();
|
NotifyClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RunServer()
|
|
||||||
{
|
|
||||||
udpServer = new UdpClient(serverIpEndPoint.Port);
|
|
||||||
uint IOC_IN = 0x80000000;
|
|
||||||
uint IOC_VENDOR = 0x18000000;
|
|
||||||
uint SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12;
|
|
||||||
udpServer.Client.IOControl((int)SIO_UDP_CONNRESET, new byte[] { Convert.ToByte(false) }, null);
|
|
||||||
var remoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);
|
|
||||||
Task.Run(() =>
|
|
||||||
{
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
byte[] receiveBytes = udpServer.Receive(ref remoteIpEndPoint);
|
|
||||||
var returnData = Encoding.ASCII.GetString(receiveBytes);
|
|
||||||
var msg = Newtonsoft.Json.JsonConvert.DeserializeObject<MsgModel>(returnData);
|
|
||||||
lock (locker)
|
|
||||||
{
|
|
||||||
#if DEBUG
|
|
||||||
WriteLine($"本次接收:{ remoteIpEndPoint.Address.ToString() }:{ remoteIpEndPoint.Port }收到消息:{ returnData }");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
dispatcher.Invoke(() =>
|
|
||||||
{
|
|
||||||
if (!Clients.Any(c => c.Equals(remoteIpEndPoint)))
|
|
||||||
{
|
|
||||||
Clients.Add(new HostModel
|
|
||||||
{
|
|
||||||
IPEndPoint = remoteIpEndPoint,
|
|
||||||
LastActiveTime = DateTime.Now,
|
|
||||||
RouteId = msg.RouteId,
|
|
||||||
MemberId = msg.MemberId,
|
|
||||||
ShowVirtual = msg.ShowVirtual
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (msg.CommandType == 0)
|
|
||||||
{
|
|
||||||
var client = Clients.FirstOrDefault(n => n.Equals(remoteIpEndPoint));
|
|
||||||
client.LastActiveTime = DateTime.Now;
|
|
||||||
client.ShowVirtual = msg.ShowVirtual;
|
|
||||||
}
|
|
||||||
else if(msg.CommandType == 1)
|
|
||||||
{
|
|
||||||
receiveMes.Add(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
//if (timer.AutoReset == false)
|
|
||||||
//{
|
|
||||||
// timer.AutoReset = true;
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Log.Error("RunServer:" + e.Message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void NotifyClient()
|
private void NotifyClient()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
lock (locker)
|
lock (locker)
|
||||||
{
|
{
|
||||||
|
var list = CloneJson(receiveMes).ToList();
|
||||||
|
receiveMes.Clear();
|
||||||
|
|
||||||
//加入虚拟人物消息
|
//加入虚拟人物消息
|
||||||
var virtualData = mapRecordRankingHander.GetVirtualUserData();
|
var virtualData = mapRecordRankingHander.GetVirtualUserData();
|
||||||
WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "-当前在线人数:" + Clients.Count + "-当前虚拟人数:" + virtualData.Count);
|
WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "-当前在线人数:" + Clients.Count + "-当前虚拟人数:" + virtualData.Count);
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
WriteLine($"在线人:{Newtonsoft.Json.JsonConvert.SerializeObject(receiveMes)}");
|
WriteLine($"在线人:{Newtonsoft.Json.JsonConvert.SerializeObject(list)}");
|
||||||
//\r\n虚拟人:{Newtonsoft.Json.JsonConvert.SerializeObject(virtualData)}
|
//\r\n虚拟人:{Newtonsoft.Json.JsonConvert.SerializeObject(virtualData)}
|
||||||
#endif
|
#endif
|
||||||
receiveMes.AddRange(virtualData);
|
list.AddRange(virtualData);
|
||||||
|
|
||||||
SendMessage(Clients, receiveMes);
|
SendMessage(Clients, list);
|
||||||
|
|
||||||
dispatcher.Invoke(() =>
|
dispatcher.Invoke(() =>
|
||||||
{
|
{
|
||||||
Customers.Clear();
|
Customers.Clear();
|
||||||
foreach (var item in receiveMes)
|
foreach (var item in list)
|
||||||
{
|
{
|
||||||
if (Customers.Any(c => c.MemberId == item.MemberId))
|
if (Customers.Any(c => c.MemberId == item.MemberId))
|
||||||
{
|
{
|
||||||
@ -165,20 +150,21 @@ namespace OnlineUserPool.ViewModels
|
|||||||
}
|
}
|
||||||
|
|
||||||
//移除下线的客户端
|
//移除下线的客户端
|
||||||
for (int i = 0; i < receiveMes.Count; i++)
|
for (int i = 0; i < list.Count; i++)
|
||||||
{
|
{
|
||||||
if (receiveMes[i].exit && !receiveMes[i].IsVirtual)//客户端退出,并且不是虚拟的人物
|
if (list[i].exit && list[i].MemberId >0)//客户端退出,并且不是虚拟的人物
|
||||||
{
|
{
|
||||||
//这个地方有严重的逻辑错误(虚拟的人物不能和真实的人用同一个名字)
|
//这个地方有严重的逻辑错误(虚拟的人物不能和真实的人用同一个名字)
|
||||||
var info = Clients.FirstOrDefault(n => n.MemberId == receiveMes[i].MemberId);
|
var info = Clients.FirstOrDefault(n => n.MemberId == list[i].MemberId);
|
||||||
if (info != null)
|
if (info != null)
|
||||||
{
|
{
|
||||||
Clients.Remove(info);
|
Clients.Remove(info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
receiveMes.Clear();//删除已经发送的数据
|
//删除已经发送的数据
|
||||||
//clients.RemoveAll(i => i.Expire);//移除5钟内连接不上的客户端
|
//receiveMes.Clear();
|
||||||
|
//移除5钟内连接不上的客户端
|
||||||
Clients.ToList().ForEach(item =>
|
Clients.ToList().ForEach(item =>
|
||||||
{
|
{
|
||||||
if (item.Expire)
|
if (item.Expire)
|
||||||
@ -189,7 +175,7 @@ namespace OnlineUserPool.ViewModels
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
//更新虚拟人物信息
|
//更新虚拟人物信息
|
||||||
mapRecordRankingHander.RemoveEndAndAddNewVirtualUser();
|
mapRecordRankingHander.RemoveEndAndAddNewVirtualUser(Customers.Count);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@ -197,9 +183,17 @@ namespace OnlineUserPool.ViewModels
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void SendMessage(Collection<HostModel> clients, List<MsgModel> msgModels)
|
private void SendMessage(Collection<HostModel> clients, List<MsgModel> msgModels)
|
||||||
{
|
{
|
||||||
string jsonString = Newtonsoft.Json.JsonConvert.SerializeObject(msgModels.Select(m=> new {
|
var clients1 = clients.ToList();
|
||||||
|
var list = CloneJson<List<MsgModel>>(msgModels);
|
||||||
|
foreach (var item in list)
|
||||||
|
{
|
||||||
|
item.PreDistance = Math.Round(item.PreDistance, 5);
|
||||||
|
item.EndDistance = Math.Round(item.EndDistance, 5);
|
||||||
|
item.WeightKg = Math.Round(item.WeightKg, 2);
|
||||||
|
}
|
||||||
|
string jsonString = Newtonsoft.Json.JsonConvert.SerializeObject(list.Select(m=> new {
|
||||||
m.RouteId,
|
m.RouteId,
|
||||||
m.MemberId,
|
m.MemberId,
|
||||||
m.Point,
|
m.Point,
|
||||||
@ -208,21 +202,42 @@ namespace OnlineUserPool.ViewModels
|
|||||||
m.Speed,
|
m.Speed,
|
||||||
m.PreDistance,
|
m.PreDistance,
|
||||||
m.EndDistance,
|
m.EndDistance,
|
||||||
m.IsVirtual,//后面要把这个字段过滤掉
|
//m.IsVirtual,//后面要把这个字段过滤掉
|
||||||
m.WeightKg,
|
m.WeightKg,
|
||||||
m.Competitionid,
|
m.Competitionid,
|
||||||
m.Saved
|
m.Saved,
|
||||||
}));
|
}));
|
||||||
var data = Encoding.ASCII.GetBytes(jsonString);
|
var data = Encoding.ASCII.GetBytes(jsonString);
|
||||||
foreach (var item in clients)
|
SendDataSize = (data.Length/1000D).ToString() +"KB";
|
||||||
|
|
||||||
|
var strV1 = string.Join("|", list.Select(m => m.ToString(1)));
|
||||||
|
WriteLine(strV1);
|
||||||
|
WriteLine(strV1.Length.ToString());
|
||||||
|
var dataV1 = Encoding.ASCII.GetBytes(strV1);
|
||||||
|
|
||||||
|
SendDataSize += $"\tV1:{ (strV1.Length/1000D) }KB";
|
||||||
|
|
||||||
|
foreach (var item in clients1)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
udpServer.Send(data, data.Length, item.IPEndPoint);
|
if(item == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (item.V == 1)
|
||||||
|
{
|
||||||
|
item.Service.Send(dataV1, dataV1.Length, item.IPEndPoint);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
item.Service.Send(data, data.Length, item.IPEndPoint);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Log.Error($"{ item.IPEndPoint.ToString() }:{ e.Message }\r\n{ e.StackTrace }");
|
Debug.WriteLine(e.Message);
|
||||||
|
Log.Error($"{ item.IPEndPoint.ToString() }:{ e.Message }\r\n{ e.StackTrace }");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -230,7 +245,24 @@ namespace OnlineUserPool.ViewModels
|
|||||||
|
|
||||||
void WriteLine(string str)
|
void WriteLine(string str)
|
||||||
{
|
{
|
||||||
Debug.WriteLine(str);
|
//Debug.WriteLine(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
T CloneJson<T>(T source)
|
||||||
|
{
|
||||||
|
// Don't serialize a null object, simply return the default for that object
|
||||||
|
if (Object.ReferenceEquals(source, null))
|
||||||
|
{
|
||||||
|
return default(T);
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialize inner objects individually
|
||||||
|
// for example in default constructor some list property initialized with some values,
|
||||||
|
// but in 'source' these items are cleaned -
|
||||||
|
// without ObjectCreationHandling.Replace default constructor values will be added to result
|
||||||
|
var deserializeSettings = new JsonSerializerSettings { ObjectCreationHandling = ObjectCreationHandling.Replace };
|
||||||
|
|
||||||
|
return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(source), deserializeSettings);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,6 +8,7 @@
|
|||||||
Title="{ Binding Title }" Height="450" Width="800">
|
Title="{ Binding Title }" Height="450" Width="800">
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="20"></RowDefinition>
|
||||||
<RowDefinition></RowDefinition>
|
<RowDefinition></RowDefinition>
|
||||||
<RowDefinition></RowDefinition>
|
<RowDefinition></RowDefinition>
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
@ -28,7 +29,13 @@
|
|||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</ListView.ItemTemplate>
|
</ListView.ItemTemplate>
|
||||||
</ListView>-->
|
</ListView>-->
|
||||||
<DataGrid ItemsSource="{ Binding Clients }" IsReadOnly="True"></DataGrid>
|
<TextBlock>
|
||||||
<DataGrid ItemsSource="{ Binding Customers }" Grid.Row="1" IsReadOnly="True"></DataGrid>
|
<Run Text="在线客户端:"></Run>
|
||||||
|
<Run Text="{ Binding Clients.Count, Mode=OneWay}"></Run>
|
||||||
|
<Run Text="发送单个客户端数据包大小:"></Run>
|
||||||
|
<Run Text="{Binding SendDataSize,Mode=OneWay}"></Run>
|
||||||
|
</TextBlock>
|
||||||
|
<DataGrid ItemsSource="{ Binding Clients }" Grid.Row="1" IsReadOnly="True"></DataGrid>
|
||||||
|
<DataGrid ItemsSource="{ Binding Customers }" Grid.Row="2" IsReadOnly="True"></DataGrid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Window>
|
</Window>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user