Plane.FormationCreator/Plane.FormationCreator/Formation/CopterManager.cs
xu 4dba5da8fd 1.兼容版和新飞控版用同样的软件,配置文件不同
2.飞行时间计算,每一个判断是否修改速度,有修改就按新速度计算时间
3.加入魔方基站支持
4.支持部分任务
2020-09-20 11:42:07 +08:00

834 lines
28 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using Plane.Copters;
using GalaSoft.MvvmLight;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Plane.FormationCreator.Util;
using Microsoft.Practices.ServiceLocation;
using Plane.FormationCreator.ViewModels;
using System.Threading;
using Plane.Communication;
using Plane.Util;
using System.Windows;
using Plane.Windows.Messages;
using System.Reflection;
using System.IO;
namespace Plane.FormationCreator.Formation
{
public class CopterCollection : ObservableCollection<ICopter>
{
//软件过期时间---过期将无法添加飞机,并自动退出
public static DateTime Expire_App = DateTime.Parse("2021-06-01");
//超级用户过期时间--过期将无法使用内置超级用户登录
public static DateTime Expire_SuperUser = Expire_App;
//允许飞行的飞机数量
public int EnCopterNumber = 0;
//允许模拟的飞机数量
public int EnVCopterNumber = 0;
/// <summary>
/// 实现排序插入
/// </summary>
/// <param name="baseSemObjects"></param>
public int AddCopter(ICopter entityObject, CopterManager.CopterSortType vSortType)
{
//新增飞机区域限制:内蒙
// if (entityObject.Latitude < 37.4307185218 || entityObject.Latitude > 45.6754821756
// || entityObject.Longitude < 97.3493089056 || entityObject.Longitude > 115.8006783856)
// return 0;
if (DateTime.UtcNow > Expire_App)
{
throw new NotImplementedException();
}
/*
if (this.Count >= VersionControl.CopterUpperLimit)
{
return 0;
}
//网络登录限制
// if (!VersionControl.IsFullVersion)
{
if (entityObject is FakeCopter)
{
if (this.Count >= EnVCopterNumber)
{
return 0;
}
}
else
{
if (this.Count >= EnCopterNumber)
{
return 0;
}
}
}
*/
int _index = 0;
if (this.Count == 0)
{
Add(entityObject);
_index = 0;
}
else
{
//删除重复
// if (entityObject is PLCopter)
// {
for (int i = 0; i < this.Count; i++)
{
if (vSortType == CopterManager.CopterSortType.ByID)
{
if (int.Parse(this[i].Id) == int.Parse(entityObject.Id))
{
if (this[i] is FakeCopter)
Remove(this[i]);
else
{
Message.Show($"无法加入飞机已有重复的真实飞机ID[{this[i].Id}]");
return -1;
}
}
}else
{
if ((entityObject.VirtualId!=0) &&(this[i].VirtualId == entityObject.VirtualId))
{
if (this[i] is FakeCopter)
Remove(this[i]);
else
{
Message.Show($"无法加入飞机已有重复的真实飞机ID[{this[i].VirtualId}]");
return -1;
}
}
}
}
// }
bool isInsret = false;
for (int i = 0; i < this.Count; i++)
{
//按ID排序插入
if (vSortType == CopterManager.CopterSortType.ByID)
{
if (int.Parse(this[i].Id) > int.Parse(entityObject.Id))
{
InsertItem(i, entityObject);
isInsret = true;
_index = i;
break;
}
}
else
//按VID排序插入
{
if (this[i].VirtualId > entityObject.VirtualId)
{
InsertItem(i, entityObject);
isInsret = true;
_index = i;
break;
}
}
}
if (!isInsret)
{
Add(entityObject);
_index = this.Count()-1 ;
}
}
entityObject.DisplayID = ((vSortType == CopterManager.CopterSortType.ByID) || (vSortType == CopterManager.CopterSortType.ByVIDShowAll));
entityObject.DisplayVirtualId = ((vSortType == CopterManager.CopterSortType.ByVID) || (vSortType == CopterManager.CopterSortType.ByVIDShowAll));
return _index;
}
}
public class CopterManager : ObservableObject
{
const string LoginPage = "checkforapp.php";
const string supername = "admin";
const string superpass = "admin0622";
const string TEMP_MISSIONFILE = @".\gcs.dat";
//飞控版本控制
public int FC_VER_NO = 1;//"4.1.2" 这个版本以前版本灯光比较少no=1 //"4.5"以后no=2;
//飞控版本控制
public string FC_VER_STRING = "4.1.2以前"; //
//用户级别
const int LEVEL_NORMAL = 1;
const int LEVEL_ADMIN = 0;
//飞机默认颜色
public const string CopterDefaultColor= "1E90FF";
//开始起飞颜色//解锁起飞用暗紫色
public const string CopterTakeoffColor = "FF00FF";
//飞行中颜色
public const string CopterFlyingColor = "32CD32";
private string superDispname = "超级用户";
public CopterManager()
{
AppEx.Current.AppModeChanged += (sender, e) =>
{
RaisePropertyChanged(nameof(Copters));
};
App.Current.Exit += (sender, e) =>
{
Task.WhenAll(Copters.Select(c => c.DisconnectAsync()));
};
Windows.IniHelper.IniFiles inifilse = new Windows.IniHelper.IniFiles();
string readvalue = "";
int intTemp;
readvalue = inifilse.IniReadvalue("Default", "FC_VER_NO");
if (readvalue != "" && int.TryParse(readvalue, out intTemp))
FC_VER_NO = int.Parse(readvalue);
readvalue = inifilse.IniReadvalue("Default", "FC_VER_STRING");
if (readvalue != "" )
FC_VER_STRING =readvalue;
}
public List<ICopter> ShowCopter = new List<ICopter>();
//3维视图显示比例有些大的图案显示不出来可以缩小
private float _scale3d = 1.0f;
public float scale3d
{
get { return _scale3d; }
set { Set(nameof(scale3d), ref _scale3d, value); }
}
public delegate void NetStatusChanged(bool Logined, string status);
public event NetStatusChanged netStatusChanged;
public CopterCollection Copters { get;} = new CopterCollection();
//标记某飞机是否需要跳过
public ArrayList CopterStatus = new ArrayList();
//public ObservableCollection<ICopter> Copters
//{
// get
// {
// switch (AppEx.Instance.CurrentMode)
// {
// case AppMode.ControllingCopters:
// default:
// return CoptersForControlling;
// case AppMode.PreparedForRunningTasks:
// case AppMode.ModifyingTask:
// return CoptersForModifyingTask;
// case AppMode.RunningTasks:
// throw new NotImplementedException();
// }
// }
//}
private string _Loginstate = "未登录";
public string Loginstate
{
get { return _Loginstate; }
set
{
Set(nameof(Loginstate), ref _Loginstate, value);
netStatusChanged(Logined,Loginstate);
}
}
public enum CopterSortType { ByID, ByVID, ByVIDShowAll };
//排序类型
private CopterSortType _SortType =0;
public CopterSortType SortType
{
get { return _SortType; }
set
{
Set(nameof(SortType), ref _SortType, value);
switch (value)
{
case CopterSortType.ByID:
sortbyid();
break;
case CopterSortType.ByVID:
sortbyvid();
break;
case CopterSortType.ByVIDShowAll:
sortbyvid(true);
break;
default:
sortbyid();
break;
}
}
}
public void ReSort()
{
SortType = _SortType;
}
private int _EnCopterNumber = 0;
public int EnCopterNumber
{
get { return _EnCopterNumber; }
set
{
Set(nameof(EnCopterNumber), ref _EnCopterNumber, value);
Copters.EnCopterNumber = EnCopterNumber;
}
}
private int _EnVCopterNumber = 0;
public int EnVCopterNumber
{
get { return _EnVCopterNumber; }
set
{
Set(nameof(EnVCopterNumber), ref _EnVCopterNumber, value);
Copters.EnVCopterNumber = EnVCopterNumber;
}
}
private bool _Logined = false;
public bool Logined
{
get { return _Logined; }
set
{
Set(nameof(Logined), ref _Logined, value);
netStatusChanged(Logined, Loginstate);
}
}
private string _UserName = "";
private string _UserDisplayName = "";
public string RTK_URL = "";
public void NetLogined(string UserName,string UserDisplayName,int vEnCopterNumber,int vEnVCopterNumber,int userlever=1)
{
_UserName = UserName;
EnCopterNumber = vEnCopterNumber;
EnVCopterNumber = vEnVCopterNumber;
_UserDisplayName = UserDisplayName;
string dis_EnCopterNumber ="<"+ EnCopterNumber.ToString()+">";
string dis_EnVCopterNumber = "<" + EnVCopterNumber.ToString() + ">";
if (EnCopterNumber == -1) dis_EnCopterNumber = "<无限>";
if (EnVCopterNumber == -1) dis_EnVCopterNumber = "<无限>";
Loginstate ="["+ UserDisplayName + "]已登录,模拟飞机:"+ dis_EnVCopterNumber + "架,真实飞机:"+ dis_EnCopterNumber + "架";
Logined = true;
VersionControl.SetUserLever(userlever);
if (UserName != supername)
{
Task.Run(async () =>
{
while (Logined)
{
NetActivePost();
//30秒一次保持活跃
await Task.Delay(30 * 1000).ConfigureAwait(false);
}
}).ConfigureAwait(false);
}
}
public void GetRTKURL()
{
if (_UserName == "") return;
// 发送请求
StringBuilder sbUrl = new StringBuilder(); // 请求URL内容
sbUrl.Append(VersionControl.ServerURL + LoginPage);
sbUrl.Append("?");
sbUrl.Append("username=" + _UserName);
sbUrl.Append("&clientname=" + System.Net.Dns.GetHostName());
sbUrl.Append("&type=GetRTK");
sbUrl.Append("&ver=" + Assembly.GetExecutingAssembly().GetName().Version.ToString());
String strUrl = sbUrl.ToString();
string errorstr;
new AsynDataUtils().AsynGetData(strUrl, ResultCallBack_rtk, out errorstr);
}
public void ReleaseRTKURL()
{
if (_UserName == "") return;
// 发送请求
StringBuilder sbUrl = new StringBuilder(); // 请求URL内容
sbUrl.Append(VersionControl.ServerURL + LoginPage);
sbUrl.Append("?");
sbUrl.Append("username=" + _UserName);
sbUrl.Append("&clientname=" + System.Net.Dns.GetHostName());
sbUrl.Append("&type=RelRTK");
sbUrl.Append("&ver=" + Assembly.GetExecutingAssembly().GetName().Version.ToString());
String strUrl = sbUrl.ToString();
string errorstr;
new AsynDataUtils().AsynGetData(strUrl, null, out errorstr);
}
private void NetActivePost()
{
// 发送请求
StringBuilder sbUrl = new StringBuilder(); // 请求URL内容
sbUrl.Append(VersionControl.ServerURL+ LoginPage);
sbUrl.Append("?");
sbUrl.Append("username=" + _UserName);
sbUrl.Append("&type=Active");
String strUrl = sbUrl.ToString();
string errorstr;
new AsynDataUtils().AsynGetData(strUrl, null,out errorstr);
}
private void NetLogoutPost()
{
// 发送请求
StringBuilder sbUrl = new StringBuilder(); // 请求URL内容
sbUrl.Append(VersionControl.ServerURL + LoginPage);
sbUrl.Append("?");
sbUrl.Append("username=" + _UserName);
sbUrl.Append("&" + "clientname=" + System.Net.Dns.GetHostName());
sbUrl.Append("&type=Logout");
sbUrl.Append("&ver=" + Assembly.GetExecutingAssembly().GetName().Version.ToString());
String strUrl = sbUrl.ToString();
string errorstr;
new AsynDataUtils().AsynGetData(strUrl, null, out errorstr);
}
public void NetLogout()
{
if (Logined)
NetLogoutPost();
Logined = false;
EnCopterNumber = 0;
EnVCopterNumber = 0;
_UserDisplayName = "";
_UserName = "";
VersionControl.SetUserLever(LEVEL_NORMAL);
Loginstate = "未登录";
}
//本地飞行任务日志 提交到服务器
public void Net_PostTempMission()
{
string filePath = TEMP_MISSIONFILE;
string[] Missionstrs = { };
try
{
if (File.Exists(filePath))
{
Missionstrs = File.ReadAllLines(filePath);
List<String> Mlist = new List<string>(Missionstrs);
string upstr = "";
foreach (var mstr in Mlist)
upstr = upstr + mstr + "|";
Net_PostTempMission(upstr);
Mlist.Clear();
File.WriteAllLines(TEMP_MISSIONFILE, Mlist);
}
}
catch (Exception ex)
{
}
}
//保存飞行任务日志临时到本地
public void Net_WriteTempMission(DateTime MissionTime, double OriginLng, double OriginLat)
{
string filePath = TEMP_MISSIONFILE;
string[] Missionstrs = { };
try
{
if (File.Exists(filePath))
Missionstrs = File.ReadAllLines(filePath);
List<String> Mlist = new List<string>(Missionstrs);
Mlist.Add(MissionTime.ToString() + ";" + OriginLng.ToString() + ";" + OriginLat.ToString() + ";" + Copters.Count().ToString()
+ ";" + Assembly.GetExecutingAssembly().GetName().Version.ToString());
File.WriteAllLines(TEMP_MISSIONFILE, Mlist);
}
catch (Exception ex)
{
}
}
//提交飞行记录
public void Net_LogStartMission(DateTime MissionTime,double OriginLng, double OriginLat)
{
Net_WriteTempMission(MissionTime, OriginLng, OriginLat);
Net_PostStartMission(MissionTime, OriginLng, OriginLat);
}
//提交飞行记录
public void Net_PostStartMission(DateTime MissionTime, double OriginLng, double OriginLat)
{
// 发送请求
StringBuilder sbUrl = new StringBuilder(); // 请求URL内容
sbUrl.Append(VersionControl.ServerURL + LoginPage);
sbUrl.Append("?");
sbUrl.Append("username=" + _UserName);
sbUrl.Append("&" + "clientname=" + System.Net.Dns.GetHostName());
sbUrl.Append("&type=StartMission");
sbUrl.Append("&mtime=" + MissionTime.ToString());
sbUrl.Append("&orgLng=" + OriginLng.ToString());
sbUrl.Append("&orgLat=" + OriginLat.ToString());
sbUrl.Append("&coptercount=" + Copters.Count().ToString());
sbUrl.Append("&ver=" + Assembly.GetExecutingAssembly().GetName().Version.ToString());
String strUrl = sbUrl.ToString();
string errorstr;
new AsynDataUtils().AsynGetData(strUrl, null, out errorstr);
}
//提交本地飞行记录
public void Net_PostTempMission(string missstr)
{
// 发送请求
StringBuilder sbUrl = new StringBuilder(); // 请求URL内容
sbUrl.Append(VersionControl.ServerURL + LoginPage);
sbUrl.Append("?");
sbUrl.Append("username=" + _UserName);
sbUrl.Append("&" + "clientname=" + System.Net.Dns.GetHostName());
sbUrl.Append("&type=TempMission");
sbUrl.Append("&Mission=" + missstr);
String strUrl = sbUrl.ToString();
string errorstr;
new AsynDataUtils().AsynGetData(strUrl, null, out errorstr);
}
private string tempuser;
private string tempPassword;
private bool tempSavePassword;
//在这个方法里面接收回调的返回信息
private void DataResultCallBack(string data,bool haveerror)
{
if (haveerror)
{
Loginstate = "登录失败,"+ data;
return;
}
if (data == "")
{
Loginstate = "登录失败,请检查网络连接";
return;
}
string[] arr = data.Split(';');
string loginret = arr[0];
if (loginret == "Login ok")
{
if (arr.Length!= 5)
{
Alert.Show("系统版本不正确!", "登录提示", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
string UserDisplayName = arr[1];
int vEnCopterNumber = int.Parse(arr[2]);
int vEnVCopterNumber = int.Parse(arr[3]);
int userlevel = int.Parse(arr[4]);
NetLogined(tempuser, UserDisplayName, vEnCopterNumber, vEnVCopterNumber, userlevel);
VersionControl.SaveLogininfoToIni(tempuser, tempPassword, tempSavePassword);
Net_PostTempMission();
//MessageBox.Show(UserDisplayName + " 登录成功!", "登录提示");
}
else
if (loginret == "username error")
{
NetLogout();
Alert.Show("账号错误!", "登录提示", MessageBoxButton.OK, MessageBoxImage.Warning);
}
else
if (loginret == "password error")
{
NetLogout();
Alert.Show("密码错误!", "登录提示", MessageBoxButton.OK, MessageBoxImage.Warning);
}
else
if (loginret == "replogin error")
{
NetLogout();
Alert.Show("该账号已在其他地方登录!", "登录提示", MessageBoxButton.OK, MessageBoxImage.Warning);
}else
{
NetLogout();
Alert.Show("登录失败:"+ data, "登录提示", MessageBoxButton.OK, MessageBoxImage.Warning);
}
}
public void NetLogoin(string username,string password,bool savepassword)
{
Logined = false;
//超级用户,无限制
if ((username== supername) && (password== superpass) &&(DateTime.UtcNow < CopterCollection.Expire_SuperUser) )
{
NetLogined(supername, superDispname, -1, -1, LEVEL_ADMIN);
return;
}
tempuser = username;
tempPassword = password;
tempSavePassword = savepassword;
// 发送请求
StringBuilder sbUrl = new StringBuilder(); // 请求URL内容
sbUrl.Append(VersionControl.ServerURL + LoginPage);
sbUrl.Append("?");
sbUrl.Append("username=" + username);
sbUrl.Append("&" + "password=" + password);
sbUrl.Append("&type=Login");
sbUrl.Append("&ver=" + Assembly.GetExecutingAssembly().GetName().Version.ToString());
sbUrl.Append("&" + "clientname=" + System.Net.Dns.GetHostName());
String strUrl = sbUrl.ToString();
string errorstr;
if (new AsynDataUtils().AsynGetData(strUrl, DataResultCallBack, out errorstr))
Loginstate = "登录中...";
else Loginstate = "登录失败,"+ errorstr;
}
private void ResultCallBack_rtk(string data, bool haveerror)
{
if (haveerror)
{
MessageBox.Show("获取RTK账号失败" + data, "错误");
return;
}
if (data == "")
{
MessageBox.Show("获取RTK账号失败请检查网络", "错误");
return;
}
string[] arr = data.Split(';');
string loginret = arr[0];
if (loginret == "ok")
{
RTK_URL = arr[1];
}
else
MessageBox.Show(loginret, "错误");
}
//在这个方法里面接收回调的返回信息
private void DataResultCallBack_changepassword(string data, bool haveerror)
{
if (haveerror)
{
MessageBox.Show("更改失败," + data, "提示");
return;
}
if (data == "")
{
MessageBox.Show("更改失败,请检查网络", "提示");
return;
}
string[] arr = data.Split(';');
string loginret = arr[0];
if (loginret == "chpassword ok")
{
MessageBox.Show( "密码更改成功!", "提示");
}
else
if (loginret == "username error")
{
MessageBox.Show("账号错误!", "提示");
}
else
if (loginret == "password error")
{
MessageBox.Show("原密码错误!", "提示");
}
}
public void NetChangePassword(string username, string oldpassword, string newpassword)
{
tempuser = username;
tempPassword = oldpassword;
// 发送请求
StringBuilder sbUrl = new StringBuilder(); // 请求URL内容
sbUrl.Append(VersionControl.ServerURL + LoginPage);
sbUrl.Append("?");
sbUrl.Append("username=" + username);
sbUrl.Append("&password=" + oldpassword);
sbUrl.Append("&clientname=" + System.Net.Dns.GetHostName());
sbUrl.Append("&type=Chpassword");
sbUrl.Append("&ver=" + Assembly.GetExecutingAssembly().GetName().Version.ToString());
sbUrl.Append("&newpassword=" + newpassword);
String strUrl = sbUrl.ToString();
string errorstr;
if (!new AsynDataUtils().AsynGetData(strUrl, DataResultCallBack_changepassword, out errorstr))
MessageBox.Show("更改失败," + errorstr, "提示");
}
public bool shiftkeydown;
public IEnumerable<ICopter> SelectedCopters { get { return _selectedCoptersGetter().Cast<ICopter>(); } }
/// <summary>
/// 注意:为避免多线程操作出问题,每次使用此属性时都会新建一个 List
/// </summary>
public IEnumerable<ICopter> AcceptingControlCopters { get { return SelectedCopters.ToList(); } }
private int _SeletedCopterCount;
public int SeletedCopterCount
{
get { return _SeletedCopterCount; }
set { Set(nameof(SeletedCopterCount), ref _SeletedCopterCount, value); }
}
private Func<IList> _selectedCoptersGetter;
private Action<ICopter> _selectCopterAction;
public void SetSelectionDelegates(Func<IList> selectedCoptersGetter, Action<ICopter> selectCopterAction)
{
_selectedCoptersGetter = selectedCoptersGetter;
_selectCopterAction = selectCopterAction;
}
public event EventHandler<SelectedCoptersChangedEventArgs> SelectedCoptersChanged;
public void RaiseSelectedCoptersChanged(IEnumerable<ICopter> addedCopters, IEnumerable<ICopter> removedCopters)
{
SelectedCoptersChanged?.Invoke(this, new SelectedCoptersChangedEventArgs { AddedCopters = addedCopters, RemovedCopters = removedCopters });
SeletedCopterCount = SelectedCopters.Count();
}
public async Task ClearCopters()
{
foreach (var copter in Copters)
{
await copter.DisconnectAsync();
}
await Task.Delay(100); // 如果不等待一段时间,很可能会再触发 DataStreamReceived 事件导致飞行器重新出现在地图上。
Copters.Clear();
CopterStatus.Clear();
//wifi
if (VersionControl.ConType==1)
UdpServerConnectionManager.Instance.ClearConnections();
}
public bool EnAddCopter_Real()
{
if (EnCopterNumber == -1) return true;
else
return Copters.Count < EnCopterNumber;
}
public bool EnAddCopter_Fake()
{
if (EnVCopterNumber == -1) return true;
else
return Copters.Count < EnVCopterNumber;
}
/// <summary>
/// 选择飞机
/// </summary>
/// <param name="copter">Null表示清除所有选择</param>
public void Select(ICopter copter)
{
_selectCopterAction(copter);
}
/// <summary>
/// 按VID重新排序飞机
/// </summary>
public void sortbyvid(bool displayid=false)
{
List<ICopter> tempCopters = new List<ICopter>();
tempCopters.AddRange(Copters);
Copters.Clear();
foreach (var copter in tempCopters)
Copters.AddCopter(copter,SortType);
}
/// <summary>
/// 按原始ID重新排序飞机
/// </summary>
public void sortbyid()
{
List<ICopter> tempCopters = new List<ICopter>();
tempCopters.AddRange(Copters);
Copters.Clear();
foreach (var copter in tempCopters)
Copters.AddCopter(copter,SortType);
}
}
public class SelectedCoptersChangedEventArgs : EventArgs
{
public IEnumerable<ICopter> AddedCopters { get; set; }
public IEnumerable<ICopter> RemovedCopters { get; set; }
}
}