feat: 添加16个遥控通道
parent
ec5fb3f3ad
commit
4fd583d9f9
Binary file not shown.
|
@ -0,0 +1,347 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
|
||||
namespace Autolabor
|
||||
{
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct SerialDevice
|
||||
{
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
|
||||
public string port;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
|
||||
public string description;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
|
||||
public string hardware_id;
|
||||
public UInt16 vid;
|
||||
public UInt16 pid;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
|
||||
public string serial_num;
|
||||
|
||||
}
|
||||
public class SerialBaseException : Exception
|
||||
{
|
||||
public SerialBaseException(string message)
|
||||
:base(message)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public class SerialBase
|
||||
{
|
||||
public static IntPtr DllImportResolver(string libraryName, Assembly assembly, DllImportSearchPath? searchPath)
|
||||
{
|
||||
|
||||
if (libraryName == "serial_base")
|
||||
{
|
||||
|
||||
if (System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
|
||||
{
|
||||
if (System.Runtime.InteropServices.RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
|
||||
{
|
||||
|
||||
return NativeLibrary.Load("libserial_base-mac-arm64.dylib", assembly, searchPath);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
return NativeLibrary.Load("libserial_base-mac.dylib", assembly, searchPath);
|
||||
}
|
||||
|
||||
}
|
||||
else if (System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||
{
|
||||
if (System.Runtime.InteropServices.RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
|
||||
{
|
||||
return NativeLibrary.Load("libserial_base-linux-arm64.so", assembly, searchPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
return NativeLibrary.Load("libserial_base-linux.so", assembly, searchPath);
|
||||
}
|
||||
|
||||
}
|
||||
else if (System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
if (System.Runtime.InteropServices.RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
|
||||
{
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NativeLibrary.Load("serial_base-win.dll", assembly, searchPath);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
|
||||
[DllImport("serial_base", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
|
||||
private static extern bool al_serial_enumerate_ports(IntPtr excep,IntPtr[] portlist ,ref int portsize);
|
||||
|
||||
|
||||
[DllImport("serial_base",CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
|
||||
private static extern bool al_serial_create(IntPtr excep,ref IntPtr serial,string port, int baudrate, int timeout);
|
||||
|
||||
[DllImport("serial_base", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
|
||||
private static extern bool al_serial_open(IntPtr excep,IntPtr serial);
|
||||
|
||||
[DllImport("serial_base", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
|
||||
private static extern bool al_serial_close(IntPtr excep,IntPtr serial);
|
||||
|
||||
[DllImport("serial_base",CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
|
||||
private static extern bool al_serial_is_open(IntPtr excep,IntPtr serial,ref bool opened);
|
||||
|
||||
[DllImport("serial_base",CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
|
||||
private static extern bool al_serial_write(IntPtr excep,IntPtr serial, IntPtr data,int size);
|
||||
|
||||
[DllImport("serial_base",CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
|
||||
|
||||
private static extern bool al_serial_available(IntPtr excep,IntPtr serial, ref int avaiable_size);
|
||||
|
||||
[DllImport("serial_base",CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
|
||||
private static extern bool al_serial_read(IntPtr excep,IntPtr serial, int buffer_size,IntPtr data,ref int recev_size);
|
||||
|
||||
[DllImport("serial_base",CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
|
||||
private static extern bool al_serial_readline(IntPtr excep,IntPtr serial, StringBuilder data,ref int recev_size);
|
||||
|
||||
[DllImport("serial_base", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
|
||||
private static extern bool al_serial_delete(IntPtr excep,ref IntPtr serial);
|
||||
|
||||
|
||||
private IntPtr _serialPtr;
|
||||
|
||||
public string Port=string.Empty;
|
||||
|
||||
public int Baudrate = 0;
|
||||
|
||||
public int ReadTimeout = 80;
|
||||
|
||||
|
||||
private const int PortInfoBufferSize = 32;
|
||||
private const int ReadBufferSize = 1024;
|
||||
private const int WriteBufferSize = 1024;
|
||||
private const int ExceptionBufferSize = 256; //固定尺寸,不能修改
|
||||
|
||||
private IntPtr _readBuffer;
|
||||
private IntPtr _writeBuffer;
|
||||
private IntPtr _exceptionBuffer;
|
||||
|
||||
private static bool dynamicLibLoaded = false;
|
||||
|
||||
public SerialBase()
|
||||
{
|
||||
_serialPtr=IntPtr.Zero;
|
||||
_readBuffer = Marshal.AllocHGlobal(ReadBufferSize);
|
||||
_writeBuffer = Marshal.AllocHGlobal(WriteBufferSize);
|
||||
_exceptionBuffer = Marshal.AllocHGlobal(ExceptionBufferSize);
|
||||
|
||||
if (dynamicLibLoaded == false)
|
||||
{
|
||||
NativeLibrary.SetDllImportResolver(Assembly.GetExecutingAssembly(), SerialBase.DllImportResolver);
|
||||
|
||||
dynamicLibLoaded = true;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static List<SerialDevice> EnumeratePorts()
|
||||
{
|
||||
if (dynamicLibLoaded == false)
|
||||
{
|
||||
NativeLibrary.SetDllImportResolver(Assembly.GetExecutingAssembly(), SerialBase.DllImportResolver);
|
||||
|
||||
dynamicLibLoaded = true;
|
||||
}
|
||||
|
||||
|
||||
IntPtr[] portinfoPtrs = new IntPtr[PortInfoBufferSize];
|
||||
|
||||
IntPtr _tmpExceptionBuffer = Marshal.AllocHGlobal(ExceptionBufferSize);
|
||||
|
||||
List<SerialDevice> result = new List<SerialDevice>();
|
||||
|
||||
int copySize = 0;
|
||||
|
||||
for (int i = 0; i < PortInfoBufferSize; i++)
|
||||
{
|
||||
portinfoPtrs[i] = Marshal.AllocHGlobal(Marshal.SizeOf<SerialDevice>());
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool success = al_serial_enumerate_ports(_tmpExceptionBuffer, portinfoPtrs, ref copySize);
|
||||
|
||||
if (success == false)
|
||||
{
|
||||
for (int i = 0; i < PortInfoBufferSize; i++)
|
||||
{
|
||||
Marshal.FreeHGlobal(portinfoPtrs[i]);
|
||||
}
|
||||
|
||||
throw new SerialBaseException(_tmpExceptionBuffer.ToString());
|
||||
}
|
||||
|
||||
for (int i = 0; i < copySize; i++)
|
||||
{
|
||||
|
||||
result.Add(Marshal.PtrToStructure<SerialDevice>(portinfoPtrs[i]));
|
||||
|
||||
}
|
||||
|
||||
for (int i = 0; i < PortInfoBufferSize; i++)
|
||||
{
|
||||
Marshal.FreeHGlobal(portinfoPtrs[i]);
|
||||
}
|
||||
|
||||
Marshal.FreeHGlobal(_tmpExceptionBuffer);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public void Open()
|
||||
{
|
||||
|
||||
if (_serialPtr == IntPtr.Zero)
|
||||
{
|
||||
|
||||
if (al_serial_create(_exceptionBuffer, ref _serialPtr, Port, Baudrate, ReadTimeout) == false) {
|
||||
|
||||
throw new SerialBaseException(_exceptionBuffer.ToString());
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (al_serial_open(_exceptionBuffer,_serialPtr) == false)
|
||||
{
|
||||
throw new SerialBaseException(_exceptionBuffer.ToString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
|
||||
|
||||
if (_serialPtr == IntPtr.Zero)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
if (al_serial_close(_exceptionBuffer,_serialPtr) == false)
|
||||
{
|
||||
throw new SerialBaseException(_exceptionBuffer.ToString());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public bool IsOpen()
|
||||
{
|
||||
|
||||
|
||||
if (_serialPtr == IntPtr.Zero)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool opened = false;
|
||||
|
||||
|
||||
if (al_serial_is_open(_exceptionBuffer, _serialPtr,ref opened) == false)
|
||||
{
|
||||
throw new SerialBaseException(_exceptionBuffer.ToString());
|
||||
}
|
||||
|
||||
return opened;
|
||||
|
||||
}
|
||||
|
||||
public void Write(byte[] data)
|
||||
{
|
||||
|
||||
if (_serialPtr == IntPtr.Zero)
|
||||
{
|
||||
throw new SerialBaseException("Serial is not open.");
|
||||
}
|
||||
|
||||
int sendCount = 0;
|
||||
|
||||
// 分批发送数据
|
||||
while (sendCount < data.Length) {
|
||||
|
||||
int needSend = (data.Length - sendCount) >= WriteBufferSize
|
||||
? WriteBufferSize
|
||||
: (data.Length - sendCount);
|
||||
|
||||
Marshal.Copy(data,sendCount,_writeBuffer, needSend);
|
||||
|
||||
if (al_serial_write(_exceptionBuffer, _serialPtr, _writeBuffer,needSend) == false)
|
||||
{
|
||||
|
||||
throw new SerialBaseException(_exceptionBuffer.ToString());
|
||||
}
|
||||
|
||||
sendCount += needSend;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public byte[] Read()
|
||||
{
|
||||
|
||||
|
||||
if (_serialPtr == IntPtr.Zero)
|
||||
{
|
||||
throw new SerialBaseException("Serial is not open.");
|
||||
}
|
||||
|
||||
|
||||
int recvSize = 0;
|
||||
|
||||
if (al_serial_read(_exceptionBuffer, _serialPtr,ReadBufferSize, _readBuffer,ref recvSize) == false)
|
||||
{
|
||||
throw new SerialBaseException(_exceptionBuffer.ToString());
|
||||
}
|
||||
|
||||
|
||||
Byte[] recvData = new byte[recvSize];
|
||||
|
||||
Marshal.Copy(_readBuffer, recvData, 0, recvSize);
|
||||
|
||||
return recvData;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
~SerialBase() {
|
||||
al_serial_delete(_exceptionBuffer, ref _serialPtr);
|
||||
_serialPtr=IntPtr.Zero;
|
||||
Marshal.FreeHGlobal(_readBuffer);
|
||||
Marshal.FreeHGlobal(_writeBuffer);
|
||||
Marshal.FreeHGlobal(_exceptionBuffer);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,7 @@
|
|||
namespace LoraGamepad.ViewModels
|
||||
{
|
||||
|
||||
public class MainWindowViewModel : ViewModelBase
|
||||
{
|
||||
|
||||
public TProViewModel TProViewModels { get; }
|
||||
|
||||
public MainWindowViewModel()
|
||||
|
|
|
@ -2,16 +2,41 @@
|
|||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
mc:Ignorable="d" d:DesignWidth="600" d:DesignHeight="400"
|
||||
x:Class="LoraGamepad.Views.TProView">
|
||||
<DockPanel>
|
||||
<Button DockPanel.Dock="Bottom"
|
||||
HorizontalAlignment="Center">
|
||||
Add an item
|
||||
</Button>
|
||||
<StackPanel>
|
||||
<CheckBox Margin="4">Walk the dog</CheckBox>
|
||||
<CheckBox Margin="4">Buy some milk</CheckBox>
|
||||
<Grid RowDefinitions="60,*,40,2*">
|
||||
<Grid Grid.Row="0" Background="Blue" ColumnDefinitions="*,3*,*">
|
||||
<Slider Grid.Column="0"/>
|
||||
<Button Grid.Column="2" Width="100" Height="40"/>
|
||||
</Grid>
|
||||
<Grid Grid.Row="1" Background="Gray" ColumnDefinitions="2*,*,4*,*,2*">
|
||||
<Button Grid.Column="0" Width="80" Height="60"/>
|
||||
<Slider Grid.Column="1" Orientation="Vertical"/>
|
||||
<Slider Grid.Column="3" Orientation="Vertical"/>
|
||||
<Button Grid.Column="4" Width="80" Height="60"/>
|
||||
</Grid>
|
||||
<Grid Grid.Row="2" Background="Yellow">
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
|
||||
<Button Width="40" Margin="10"/>
|
||||
<Button Width="40" Margin="10"/>
|
||||
<Button Width="40" Margin="10"/>
|
||||
<Button Width="40" Margin="10"/>
|
||||
<Button Width="40" Margin="10"/>
|
||||
<Button Width="40" Margin="10"/>
|
||||
</StackPanel>
|
||||
</DockPanel>
|
||||
</Grid>
|
||||
<Grid Grid.Row="3" Background="Green" ColumnDefinitions="*,2*,*">
|
||||
<Grid Grid.Column="0">
|
||||
<Slider VerticalAlignment="Center"/>
|
||||
<Slider Orientation="Vertical" HorizontalAlignment="Center"/>
|
||||
</Grid>
|
||||
<Grid Grid.Column="1" Background="Purple">
|
||||
<TextBox Text="Hello T-Pro!"/>
|
||||
</Grid>
|
||||
<Grid Grid.Column="2">
|
||||
<Slider VerticalAlignment="Center"/>
|
||||
<Slider Orientation="Vertical" HorizontalAlignment="Center"/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
|
Loading…
Reference in New Issue