add usb mode
This commit is contained in:
parent
0a437ecec2
commit
5ca73b8897
|
@ -0,0 +1,13 @@
|
||||||
|
[*.cs]
|
||||||
|
|
||||||
|
# CS8600: Converting null literal or possible null value to non-nullable type.
|
||||||
|
dotnet_diagnostic.CS8600.severity = none
|
||||||
|
|
||||||
|
# CS8618: Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
||||||
|
dotnet_diagnostic.CS8618.severity = none
|
||||||
|
|
||||||
|
# CS8602: Dereference of a possibly null reference.
|
||||||
|
dotnet_diagnostic.CS8602.severity = none
|
||||||
|
|
||||||
|
# CS8601: Possible null reference assignment.
|
||||||
|
dotnet_diagnostic.CS8601.severity = none
|
|
@ -2,6 +2,7 @@
|
||||||
{
|
{
|
||||||
internal class Config
|
internal class Config
|
||||||
{
|
{
|
||||||
|
public int mode = 0;
|
||||||
public string sn = "";
|
public string sn = "";
|
||||||
public string disk0 = "";
|
public string disk0 = "";
|
||||||
public string disk1 = "";
|
public string disk1 = "";
|
||||||
|
|
|
@ -6,28 +6,35 @@
|
||||||
xmlns:local="clr-namespace:Topuino_Client_Windows"
|
xmlns:local="clr-namespace:Topuino_Client_Windows"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
Closing="Window_Closing"
|
Closing="Window_Closing"
|
||||||
Title="Topuino 客户端" Height="150" Width="400">
|
Title="Topuino 客户端" Height="180" Width="400">
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="*" />
|
<RowDefinition Height="*" />
|
||||||
<RowDefinition Height="*" />
|
<RowDefinition Height="*" />
|
||||||
<RowDefinition Height="*" />
|
<RowDefinition Height="*" />
|
||||||
|
<RowDefinition Height="*" />
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<StackPanel Grid.Row="0" Orientation="Horizontal" HorizontalAlignment="Left" Margin="5">
|
<StackPanel Grid.Row="0" Orientation="Horizontal" Margin="5">
|
||||||
|
<Label Content="运行模式:" VerticalAlignment="Center" />
|
||||||
|
<RadioButton x:Name="RadioButton_UsbMode" VerticalAlignment="Center" Margin="5,0" IsChecked="True">USB 模式</RadioButton>
|
||||||
|
<RadioButton x:Name="RadioButton_OnlineMode" VerticalAlignment="Center" Margin="5,0">在线模式</RadioButton>
|
||||||
|
<RadioButton x:Name="RadioButton_LocalMode" VerticalAlignment="Center" Margin="5,0" IsEnabled="False">本地模式</RadioButton>
|
||||||
|
</StackPanel>
|
||||||
|
<StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Left" Margin="5">
|
||||||
<TextBlock Text="设备 SN:" VerticalAlignment="Center"/>
|
<TextBlock Text="设备 SN:" VerticalAlignment="Center"/>
|
||||||
<TextBox x:Name="TextBox_DeviceSn" Width="80" VerticalAlignment="Center" />
|
<TextBox x:Name="TextBox_DeviceSn" Width="80" VerticalAlignment="Center" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Left" Margin="5">
|
<StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Left" Margin="5">
|
||||||
<TextBlock Text="0 号磁盘:" VerticalAlignment="Center"/>
|
<TextBlock Text="0 号磁盘:" VerticalAlignment="Center"/>
|
||||||
<ComboBox x:Name="ComboBox_Disk0" Height="20" Width="60" VerticalAlignment="Center"/>
|
<ComboBox x:Name="ComboBox_Disk0" Height="20" Width="60" VerticalAlignment="Center"/>
|
||||||
<Separator Width="10" Background="Transparent" />
|
<Separator Width="10" Background="Transparent" />
|
||||||
<TextBlock Text="1 号磁盘:" VerticalAlignment="Center"/>
|
<TextBlock Text="1 号磁盘:" VerticalAlignment="Center"/>
|
||||||
<ComboBox x:Name="ComboBox_Disk1" Height="20" Width="60" VerticalAlignment="Center"/>
|
<ComboBox x:Name="ComboBox_Disk1" Height="20" Width="60" VerticalAlignment="Center"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Right" Margin="5">
|
<StackPanel Grid.Row="3" Orientation="Horizontal" HorizontalAlignment="Right" Margin="5">
|
||||||
<Button Content="保存" Click="Button_Save_Click" Height="20" Width="40" />
|
<Button Content="应用并保存" Click="Button_Save_Click" Height="25" Width="80" />
|
||||||
<Separator Width="10" Background="Transparent" />
|
<Separator Width="10" Background="Transparent" />
|
||||||
<Button Content="隐藏" Click="Button_Hide_Click" Height="20" Width="40" />
|
<Button Content="隐藏" Click="Button_Hide_Click" Height="25" Width="40" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Window>
|
</Window>
|
||||||
|
|
|
@ -8,6 +8,7 @@ using System.Collections.Generic;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace Topuino_Client_Windows
|
namespace Topuino_Client_Windows
|
||||||
|
@ -44,6 +45,7 @@ namespace Topuino_Client_Windows
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
RadioButton_UsbMode.IsChecked = true;
|
||||||
ComboBox_Disk0.SelectedIndex = 0;
|
ComboBox_Disk0.SelectedIndex = 0;
|
||||||
ComboBox_Disk1.SelectedIndex = 0;
|
ComboBox_Disk1.SelectedIndex = 0;
|
||||||
}
|
}
|
||||||
|
@ -56,37 +58,71 @@ namespace Topuino_Client_Windows
|
||||||
|
|
||||||
private NotifyIcon trayIon = new NotifyIcon();
|
private NotifyIcon trayIon = new NotifyIcon();
|
||||||
|
|
||||||
|
private int mode = 0;
|
||||||
private string sn = "";
|
private string sn = "";
|
||||||
private List<DriveInfo> allDrives;
|
private List<DriveInfo> allDrives;
|
||||||
private DriveInfo? drive0 = null;
|
private DriveInfo drive0;
|
||||||
private DriveInfo? drive1 = null;
|
private DriveInfo drive1;
|
||||||
|
|
||||||
private Config? initConfig = null;
|
private bool ready = false;
|
||||||
|
|
||||||
private Thread? refreshThread = null;
|
private Thread? refreshThread = null;
|
||||||
|
|
||||||
private ManualResetEvent requestStop = new ManualResetEvent(false);
|
private ManualResetEvent requestStop = new ManualResetEvent(false);
|
||||||
private ManualResetEvent stopDone = new ManualResetEvent(false);
|
private ManualResetEvent stopDone = new ManualResetEvent(false);
|
||||||
|
|
||||||
|
private OnlineConnector? onlineClient = null;
|
||||||
|
private UsbConnector? usbClient = null;
|
||||||
|
|
||||||
private void LoadConfig()
|
private void LoadConfig()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
initConfig = JsonConvert.DeserializeObject<Config>(File.ReadAllText("Config.json"));
|
Config? initConfig = JsonConvert.DeserializeObject<Config>(File.ReadAllText("Config.json"));
|
||||||
if (initConfig == null)
|
if (initConfig == null)
|
||||||
{
|
{
|
||||||
throw new Exception();
|
throw new Exception();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch (initConfig.mode)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
RadioButton_UsbMode.IsChecked = true;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
RadioButton_OnlineMode.IsChecked = true;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
RadioButton_LocalMode.IsChecked = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
RadioButton_UsbMode.IsChecked = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// check if drivers missing
|
// check if drivers missing
|
||||||
|
bool disk0Found = false;
|
||||||
|
bool disk1Fount = false;
|
||||||
foreach (DriveInfo drive in allDrives)
|
foreach (DriveInfo drive in allDrives)
|
||||||
{
|
{
|
||||||
if (drive.Name != initConfig.disk0 && drive.Name != initConfig.disk1)
|
if (drive.Name == initConfig.disk0)
|
||||||
{
|
{
|
||||||
initConfig.disk0 = drive.Name;
|
disk0Found = true;
|
||||||
initConfig.disk1 = drive.Name;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
if (drive.Name == initConfig.disk1)
|
||||||
|
{
|
||||||
|
disk1Fount = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!disk0Found)
|
||||||
|
{
|
||||||
|
ShowErrorBox("找不到磁盘0,已切换为默认磁盘");
|
||||||
|
initConfig.disk0 = allDrives[0].Name;
|
||||||
|
}
|
||||||
|
if (!disk1Fount)
|
||||||
|
{
|
||||||
|
ShowErrorBox("找不到磁盘1,已切换为默认磁盘");
|
||||||
|
initConfig.disk1 = allDrives[0].Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < allDrives.Count; i++)
|
for (int i = 0; i < allDrives.Count; i++)
|
||||||
|
@ -148,26 +184,78 @@ namespace Topuino_Client_Windows
|
||||||
netBytesReceiveAfter += ni.GetIPStatistics().BytesReceived;
|
netBytesReceiveAfter += ni.GetIPStatistics().BytesReceived;
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma warning disable CS8602 // Dereference of a possibly null reference.
|
MonitorData data = new MonitorData
|
||||||
Dictionary<string, string> statusInfo = new Dictionary<string, string>();
|
{
|
||||||
statusInfo.Add("SN", sn);
|
cpuPercent = (byte)cpuCounter.NextValue(),
|
||||||
statusInfo.Add("CPU_PERCENT", ((int)cpuCounter.NextValue()).ToString());
|
memPercent = (byte)ramPercentUsed,
|
||||||
statusInfo.Add("MEM_PERCENT", ((int)ramPercentUsed).ToString());
|
disk0Percent = (byte)((double)(drive0.TotalSize - drive0.AvailableFreeSpace) / drive0.TotalSize * 100),
|
||||||
statusInfo.Add("DISK_PERCENT", ((int)((double)(drive0.TotalSize - drive0.AvailableFreeSpace) / drive0.TotalSize * 100)).ToString());
|
disk1Percent = (byte)((double)(drive1.TotalSize - drive1.AvailableFreeSpace) / drive1.TotalSize * 100),
|
||||||
statusInfo.Add("DISK1_PERCENT", ((int)((double)(drive1.TotalSize - drive1.AvailableFreeSpace) / drive1.TotalSize * 100)).ToString());
|
diskReadRate = (uint)diskReadCounter.NextValue(),
|
||||||
statusInfo.Add("DISK_READ_RATE", ((int)diskReadCounter.NextValue()).ToString());
|
diskWriteRate = (uint)diskWriteCounter.NextValue(),
|
||||||
statusInfo.Add("DISK_WRITE_RATE", ((int)diskWriteCounter.NextValue()).ToString());
|
netSentRate = (uint)(netBytesSentAfter - netBytesSentBefore),
|
||||||
statusInfo.Add("NET_SENT_RATE", ((int)(netBytesSentAfter - netBytesSentBefore)).ToString());
|
netRecvRate = (uint)(netBytesReceiveAfter - netBytesReceiveBefore),
|
||||||
statusInfo.Add("NET_RECV_RATE", ((int)(netBytesSentAfter - netBytesSentBefore)).ToString());
|
};
|
||||||
#pragma warning restore CS8602 // Dereference of a possibly null reference.
|
|
||||||
|
|
||||||
PublicComm connection = new PublicComm();
|
switch (mode)
|
||||||
connection.Post(statusInfo);
|
{
|
||||||
|
case 0:
|
||||||
|
UsbRun(data);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
OnlineRun(data);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
OfflineRun(data);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stopDone.Set();
|
stopDone.Set();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void UsbRun(MonitorData data)
|
||||||
|
{
|
||||||
|
int size = Marshal.SizeOf(data);
|
||||||
|
byte[] bin = new byte[size];
|
||||||
|
IntPtr ptr = IntPtr.Zero;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ptr = Marshal.AllocHGlobal(size);
|
||||||
|
Marshal.StructureToPtr(data, ptr, true);
|
||||||
|
Marshal.Copy(ptr, bin, 0, size);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Marshal.FreeHGlobal(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
usbClient.Send(bin);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnlineRun(MonitorData data)
|
||||||
|
{
|
||||||
|
Dictionary<string, string> statusInfo = new Dictionary<string, string>();
|
||||||
|
statusInfo.Add("SN", sn);
|
||||||
|
statusInfo.Add("CPU_PERCENT", data.cpuPercent.ToString());
|
||||||
|
statusInfo.Add("MEM_PERCENT", data.memPercent.ToString());
|
||||||
|
statusInfo.Add("DISK_PERCENT", data.disk0Percent.ToString());
|
||||||
|
statusInfo.Add("DISK1_PERCENT", data.disk1Percent.ToString());
|
||||||
|
statusInfo.Add("DISK_READ_RATE", data.diskReadRate.ToString());
|
||||||
|
statusInfo.Add("DISK_WRITE_RATE", data.diskWriteRate.ToString());
|
||||||
|
statusInfo.Add("NET_SENT_RATE", data.netSentRate.ToString());
|
||||||
|
statusInfo.Add("NET_RECV_RATE", data.netRecvRate.ToString());
|
||||||
|
|
||||||
|
onlineClient.Post(statusInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OfflineRun(MonitorData data)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void ShowErrorBox(string msg)
|
public void ShowErrorBox(string msg)
|
||||||
{
|
{
|
||||||
System.Windows.MessageBox.Show(
|
System.Windows.MessageBox.Show(
|
||||||
|
@ -181,53 +269,93 @@ namespace Topuino_Client_Windows
|
||||||
|
|
||||||
private void ApplyConfig()
|
private void ApplyConfig()
|
||||||
{
|
{
|
||||||
sn = TextBox_DeviceSn.Text;
|
try
|
||||||
drive0 = ComboBox_Disk0.SelectedItem as DriveInfo;
|
{
|
||||||
drive1 = ComboBox_Disk1.SelectedItem as DriveInfo;
|
if (RadioButton_UsbMode.IsChecked == true)
|
||||||
|
{
|
||||||
|
mode = 0;
|
||||||
|
usbClient = new UsbConnector();
|
||||||
|
}
|
||||||
|
else if (RadioButton_OnlineMode.IsChecked == true)
|
||||||
|
{
|
||||||
|
mode = 1;
|
||||||
|
onlineClient = new OnlineConnector();
|
||||||
|
}
|
||||||
|
else if (RadioButton_LocalMode.IsChecked == true)
|
||||||
|
{
|
||||||
|
mode = 2;
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
sn = TextBox_DeviceSn.Text;
|
||||||
|
|
||||||
|
drive0 = ComboBox_Disk0.SelectedItem as DriveInfo;
|
||||||
|
drive1 = ComboBox_Disk1.SelectedItem as DriveInfo;
|
||||||
|
|
||||||
|
ready = true;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ready = false;
|
||||||
|
ShowErrorBox(e.Message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void StartRun()
|
private void StartRun()
|
||||||
{
|
{
|
||||||
Mouse.OverrideCursor = System.Windows.Input.Cursors.Wait;
|
if (!ready)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!drive0.IsReady || !drive1.IsReady)
|
||||||
|
{
|
||||||
|
ShowErrorBox("磁盘未就绪");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
refreshThread = new Thread(Run);
|
||||||
|
refreshThread.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void StopRun()
|
||||||
|
{
|
||||||
if (refreshThread != null)
|
if (refreshThread != null)
|
||||||
{
|
{
|
||||||
requestStop.Set();
|
requestStop.Set();
|
||||||
stopDone.WaitOne();
|
stopDone.WaitOne();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
refreshThread = null;
|
||||||
|
|
||||||
requestStop.Reset();
|
requestStop.Reset();
|
||||||
stopDone.Reset();
|
stopDone.Reset();
|
||||||
|
|
||||||
#pragma warning disable CS8602 // Dereference of a possibly null reference.
|
|
||||||
if (!drive0.IsReady || !drive1.IsReady)
|
|
||||||
{
|
|
||||||
ShowErrorBox("磁盘未就绪");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#pragma warning restore CS8602 // Dereference of a possibly null reference.
|
|
||||||
|
|
||||||
Mouse.OverrideCursor = null;
|
|
||||||
|
|
||||||
refreshThread = new Thread(Run);
|
|
||||||
refreshThread.Start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void SaveConfig()
|
private async void SaveConfig()
|
||||||
{
|
{
|
||||||
Config newConfig = new Config();
|
Config newConfig = new Config();
|
||||||
|
newConfig.mode = mode;
|
||||||
newConfig.sn = sn;
|
newConfig.sn = sn;
|
||||||
#pragma warning disable CS8602 // Dereference of a possibly null reference.
|
|
||||||
newConfig.disk0 = drive0.Name;
|
newConfig.disk0 = drive0.Name;
|
||||||
newConfig.disk1 = drive1.Name;
|
newConfig.disk1 = drive1.Name;
|
||||||
await File.WriteAllTextAsync("Config.json", JsonConvert.SerializeObject(newConfig, Formatting.Indented));
|
await File.WriteAllTextAsync("Config.json", JsonConvert.SerializeObject(newConfig, Formatting.Indented));
|
||||||
#pragma warning restore CS8602 // Dereference of a possibly null reference.
|
}
|
||||||
|
|
||||||
|
private void ResetConnectors()
|
||||||
|
{
|
||||||
|
usbClient?.Dispose();
|
||||||
|
onlineClient?.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Button_Save_Click(object sender, RoutedEventArgs e)
|
private void Button_Save_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
|
Mouse.OverrideCursor = System.Windows.Input.Cursors.Wait;
|
||||||
|
StopRun();
|
||||||
|
ResetConnectors();
|
||||||
ApplyConfig();
|
ApplyConfig();
|
||||||
SaveConfig();
|
SaveConfig();
|
||||||
StartRun();
|
StartRun();
|
||||||
|
Mouse.OverrideCursor = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void TrayIcon_DoubleClick(object? sender, EventArgs e)
|
private void TrayIcon_DoubleClick(object? sender, EventArgs e)
|
||||||
|
@ -242,11 +370,8 @@ namespace Topuino_Client_Windows
|
||||||
|
|
||||||
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
|
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
|
||||||
{
|
{
|
||||||
if (refreshThread != null)
|
StopRun();
|
||||||
{
|
ResetConnectors();
|
||||||
requestStop.Set();
|
|
||||||
stopDone.WaitOne();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace Topuino_Client_Windows
|
||||||
|
{
|
||||||
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||||
|
internal struct MonitorData
|
||||||
|
{
|
||||||
|
public byte cpuPercent;
|
||||||
|
public byte memPercent;
|
||||||
|
public byte disk0Percent;
|
||||||
|
public byte disk1Percent;
|
||||||
|
public uint diskReadRate;
|
||||||
|
public uint diskWriteRate;
|
||||||
|
public uint netSentRate;
|
||||||
|
public uint netRecvRate;
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,12 +6,12 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Topuino_Client_Windows
|
namespace Topuino_Client_Windows
|
||||||
{
|
{
|
||||||
internal class PublicComm
|
internal class OnlineConnector
|
||||||
{
|
{
|
||||||
private HttpClient client = new HttpClient();
|
private HttpClient client = new HttpClient();
|
||||||
private int errorCount = 0;
|
private int errorCount = 0;
|
||||||
|
|
||||||
public async void Post(Dictionary<string, string> data)
|
internal async void Post(Dictionary<string, string> data)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -19,7 +19,7 @@ namespace Topuino_Client_Windows
|
||||||
HttpResponseMessage response = await client.PostAsync("https://iot.vvzero.com/topuino/putdata", content);
|
HttpResponseMessage response = await client.PostAsync("https://iot.vvzero.com/topuino/putdata", content);
|
||||||
response.EnsureSuccessStatusCode();
|
response.EnsureSuccessStatusCode();
|
||||||
string responseBody = await response.Content.ReadAsStringAsync();
|
string responseBody = await response.Content.ReadAsStringAsync();
|
||||||
PublicCommResponse? respData = JsonConvert.DeserializeObject<PublicCommResponse>(responseBody);
|
OnlineConnectorResponse? respData = JsonConvert.DeserializeObject<OnlineConnectorResponse>(responseBody);
|
||||||
if (respData == null || respData.CODE != 0)
|
if (respData == null || respData.CODE != 0)
|
||||||
{
|
{
|
||||||
throw new Exception();
|
throw new Exception();
|
||||||
|
@ -35,10 +35,15 @@ namespace Topuino_Client_Windows
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal void Dispose()
|
||||||
|
{
|
||||||
|
client.Dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class PublicCommResponse
|
internal class OnlineConnectorResponse
|
||||||
{
|
{
|
||||||
public int CODE;
|
public int CODE = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
{
|
{
|
||||||
|
"mode": 0,
|
||||||
"sn": "V0000T0000",
|
"sn": "V0000T0000",
|
||||||
"disk0": "C:\\",
|
"disk0": "C:\\",
|
||||||
"disk1": "C:\\"
|
"disk1": "C:\\"
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
<UseWPF>true</UseWPF>
|
<UseWPF>true</UseWPF>
|
||||||
<UseWindowsForms>true</UseWindowsForms>
|
<UseWindowsForms>true</UseWindowsForms>
|
||||||
<ApplicationIcon>Topuino.ico</ApplicationIcon>
|
<ApplicationIcon>Topuino.ico</ApplicationIcon>
|
||||||
|
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -15,6 +16,7 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||||
|
<PackageReference Include="System.IO.Ports" Version="6.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
|
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
|
||||||
|
|
|
@ -3,7 +3,12 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio Version 17
|
# Visual Studio Version 17
|
||||||
VisualStudioVersion = 17.2.32526.322
|
VisualStudioVersion = 17.2.32526.322
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Topuino_Client_Windows", "Topuino_Client_Windows.csproj", "{53D6F46D-6FE0-4730-B55A-C4233BA001D3}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Topuino_Client_Windows", "Topuino_Client_Windows.csproj", "{53D6F46D-6FE0-4730-B55A-C4233BA001D3}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{0B1B2118-B48C-4CA8-800F-3F2ED24C73ED}"
|
||||||
|
ProjectSection(SolutionItems) = preProject
|
||||||
|
.editorconfig = .editorconfig
|
||||||
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.IO.Ports;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace Topuino_Client_Windows
|
||||||
|
{
|
||||||
|
internal class UsbConnector
|
||||||
|
{
|
||||||
|
internal UsbConnector()
|
||||||
|
{
|
||||||
|
string[] portNames = SerialPort.GetPortNames();
|
||||||
|
|
||||||
|
foreach (string name in portNames)
|
||||||
|
{
|
||||||
|
SerialPort port = new SerialPort(name, 115200, Parity.None, 8, StopBits.One);
|
||||||
|
if (IsTopuinoPort(port))
|
||||||
|
{
|
||||||
|
topuinoPort = port;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Exception("找不到 Topuino 设备");
|
||||||
|
}
|
||||||
|
|
||||||
|
private SerialPort? topuinoPort = null;
|
||||||
|
private ManualResetEvent portInitReceived = new ManualResetEvent(false);
|
||||||
|
private bool portValid = false;
|
||||||
|
|
||||||
|
internal void Send(byte[] data)
|
||||||
|
{
|
||||||
|
if (topuinoPort == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] buff = new byte[data.Length + 4];
|
||||||
|
Array.Copy(data, 0, buff, 4, data.Length);
|
||||||
|
buff[0] = 0x66;
|
||||||
|
buff[1] = 0x77;
|
||||||
|
buff[2] = 0xaa;
|
||||||
|
buff[3] = 0xff;
|
||||||
|
topuinoPort.Write(buff, 0, buff.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsTopuinoPort(SerialPort port)
|
||||||
|
{
|
||||||
|
port.DataReceived += PortInitDataReceiver;
|
||||||
|
port.Open();
|
||||||
|
byte[] pingBuff = new byte[4] { 0x19, 0x26, 0x08, 0x17 };
|
||||||
|
|
||||||
|
portValid = false;
|
||||||
|
port.Write(pingBuff, 0, 4);
|
||||||
|
portInitReceived.WaitOne(1000);
|
||||||
|
|
||||||
|
if (portValid)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
port.Close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PortInitDataReceiver(object sender, SerialDataReceivedEventArgs e)
|
||||||
|
{
|
||||||
|
SerialPort port = sender as SerialPort;
|
||||||
|
|
||||||
|
byte[] pongBuff = new byte[2];
|
||||||
|
int readCount = port.Read(pongBuff, 0, 2);
|
||||||
|
if (readCount == 2)
|
||||||
|
{
|
||||||
|
if (pongBuff[0] == 0x68 && pongBuff[1] == 0x61)
|
||||||
|
{
|
||||||
|
portValid = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void Dispose()
|
||||||
|
{
|
||||||
|
if (topuinoPort != null)
|
||||||
|
{
|
||||||
|
if (topuinoPort.IsOpen)
|
||||||
|
{
|
||||||
|
topuinoPort.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
topuinoPort = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue