Commit f9e08c84 by liulongfei

引入HTTP辅助类

添加包装程序集
parent e117582f
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using log4net;
using Newtonsoft.Json;
namespace VIZ.Framework.Core
{
/// <summary>
/// HTTP辅助类
/// </summary>
public static class HttpHelper
{
/// <summary>
/// 日志
/// </summary>
private static readonly ILog log = LogManager.GetLogger(typeof(HttpHelper));
/// <summary>
/// 缓存字节大小
/// </summary>
private static readonly int BUFFER_SIZE = 10 * 1024;
/// <summary>
/// 超时时间
/// </summary>
private static readonly int TIME_OUT = 10 * 1000;
/// <summary>
/// Get请求
/// </summary>
/// <typeparam name="T">返回类型</typeparam>
/// <param name="url">请求url</param>
/// <returns>返回数据</returns>
public static string Get(string url, CookieContainer cookie)
{
try
{
using (HttpClientHandler handler = new HttpClientHandler())
{
using (HttpClient client = new HttpClient(handler))
{
if (cookie != null)
{
handler.UseCookies = true;
handler.CookieContainer = cookie;
}
client.Timeout = TimeSpan.FromMilliseconds(TIME_OUT);
using (HttpResponseMessage response = client.GetAsync(url).Result)
using (Stream stream = response.Content.ReadAsStreamAsync().Result)
using (StreamReader sr = new StreamReader(stream, Encoding.UTF8))
{
string json = sr.ReadToEnd();
return json;
}
}
}
}
catch (Exception ex)
{
log.Error(ex);
return null;
}
}
/// <summary>
/// Get请求
/// </summary>
/// <typeparam name="T">返回类型</typeparam>
/// <param name="url">请求url</param>
/// <returns>返回json对象</returns>
public static T Get<T>(string url, CookieContainer cookie) where T : class
{
try
{
string json = Get(url, cookie);
if (string.IsNullOrWhiteSpace(json))
return null;
return JsonConvert.DeserializeObject<T>(json);
}
catch (Exception ex)
{
log.Error(ex);
return null;
}
}
/// <summary>
/// Post请求
/// </summary>
/// <typeparam name="T">返回类型</typeparam>
/// <param name="url">请求url</param>
/// <param name="content">请求内容</param>
/// <param name="args">参数集合</param>
/// <returns>返回json对象</returns>
public static string Post(string url, object data, CookieContainer cookie)
{
try
{
string postJson = data == null ? string.Empty : JsonConvert.SerializeObject(data);
using (HttpClientHandler handler = new HttpClientHandler())
{
if (cookie != null)
{
handler.UseCookies = true;
handler.CookieContainer = cookie;
}
using (HttpClient client = new HttpClient(handler))
{
client.Timeout = TimeSpan.FromMilliseconds(TIME_OUT);
StringContent content = new StringContent(postJson, Encoding.UTF8);
using (HttpResponseMessage response = client.PostAsync(url, content).Result)
using (Stream stream = response.Content.ReadAsStreamAsync().Result)
using (StreamReader sr = new StreamReader(stream, Encoding.UTF8))
{
string json = sr.ReadToEnd();
return json;
}
}
}
}
catch (Exception ex)
{
log.Error(ex);
return null;
}
}
/// <summary>
/// Post请求
/// </summary>
/// <typeparam name="T">返回类型</typeparam>
/// <param name="url">请求url</param>
/// <param name="content">请求内容</param>
/// <param name="args">参数集合</param>
/// <returns>返回json对象</returns>
public static T Post<T>(string url, object data, CookieContainer cookie) where T : class
{
try
{
string json = Post(url, data, cookie);
return JsonConvert.DeserializeObject<T>(json);
}
catch (Exception ex)
{
log.Error(ex);
return null;
}
}
}
}
\ No newline at end of file
...@@ -53,6 +53,9 @@ ...@@ -53,6 +53,9 @@
<HintPath>..\packages\log4net.2.0.14\lib\net45\log4net.dll</HintPath> <HintPath>..\packages\log4net.2.0.14\lib\net45\log4net.dll</HintPath>
</Reference> </Reference>
<Reference Include="Microsoft.VisualBasic" /> <Reference Include="Microsoft.VisualBasic" />
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\..\VIZ.TimeSlice\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="NvAPIWrapper, Version=0.8.1.100, Culture=neutral, PublicKeyToken=310fd07b25df79b3, processorArchitecture=MSIL"> <Reference Include="NvAPIWrapper, Version=0.8.1.100, Culture=neutral, PublicKeyToken=310fd07b25df79b3, processorArchitecture=MSIL">
<HintPath>..\..\VIZ.H2V\packages\NvAPIWrapper.Net.0.8.1.101\lib\net45\NvAPIWrapper.dll</HintPath> <HintPath>..\..\VIZ.H2V\packages\NvAPIWrapper.Net.0.8.1.101\lib\net45\NvAPIWrapper.dll</HintPath>
</Reference> </Reference>
...@@ -96,6 +99,7 @@ ...@@ -96,6 +99,7 @@
<Compile Include="Core\Enum\EnumModel.cs" /> <Compile Include="Core\Enum\EnumModel.cs" />
<Compile Include="Core\Helper\ByteHelper.cs" /> <Compile Include="Core\Helper\ByteHelper.cs" />
<Compile Include="Core\Helper\CmdHelper.cs" /> <Compile Include="Core\Helper\CmdHelper.cs" />
<Compile Include="Core\Helper\HttpHelper.cs" />
<Compile Include="Core\Helper\KeepSymbolHelper.cs" /> <Compile Include="Core\Helper\KeepSymbolHelper.cs" />
<Compile Include="Core\Helper\ProcessHelper.cs" /> <Compile Include="Core\Helper\ProcessHelper.cs" />
<Compile Include="Core\Helper\FPSHelper.cs" /> <Compile Include="Core\Helper\FPSHelper.cs" />
......
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="log4net" version="2.0.14" targetFramework="net48" /> <package id="log4net" version="2.0.14" targetFramework="net48" />
<package id="Newtonsoft.Json" version="13.0.1" targetFramework="net48" />
<package id="NvAPIWrapper.Net" version="0.8.1.101" targetFramework="net48" /> <package id="NvAPIWrapper.Net" version="0.8.1.101" targetFramework="net48" />
<package id="SharpDX" version="4.2.0" targetFramework="net48" /> <package id="SharpDX" version="4.2.0" targetFramework="net48" />
<package id="SharpDX.Mathematics" version="4.2.0" targetFramework="net48" /> <package id="SharpDX.Mathematics" version="4.2.0" targetFramework="net48" />
......
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
using VIZ.Framework.Core;
namespace VIZ.Framework.TVP.Golf
{
/// <summary>
/// 高尔夫 包装 设备模型
/// </summary>
public class GolfDeviceModel : ModelBase
{
// ===============================================================================
// Property
// ===============================================================================
#region ConnectionFailures -- 连接失败次数
private int connectionFailures;
/// <summary>
/// 连接失败次数
/// </summary>
public int ConnectionFailures
{
get { return connectionFailures; }
set { connectionFailures = value; this.RaisePropertyChanged(nameof(ConnectionFailures)); }
}
#endregion
#region SerialNumber -- 设备序列号
private string serialNumber;
/// <summary>
/// 设备序列号
/// </summary>
public string SerialNumber
{
get { return serialNumber; }
set { serialNumber = value; this.RaisePropertyChanged(nameof(SerialNumber)); }
}
#endregion
#region DisplayWidth -- 显示宽度
private int displayWidth;
/// <summary>
/// 显示宽度
/// </summary>
public int DisplayWidth
{
get { return displayWidth; }
set { displayWidth = value; this.RaisePropertyChanged(nameof(DisplayWidth)); }
}
#endregion
#region DisplayHeight -- 显示高度
private int displayHeight;
/// <summary>
/// 显示高度
/// </summary>
public int DisplayHeight
{
get { return displayHeight; }
set { displayHeight = value; this.RaisePropertyChanged(nameof(DisplayHeight)); }
}
#endregion
#region IsConnected -- 是否已经连接
private bool isConnected;
/// <summary>
/// 是否已经连接
/// </summary>
public bool IsConnected
{
get { return isConnected; }
set { isConnected = value; this.RaisePropertyChanged(nameof(IsConnected)); }
}
#endregion
#region LeftTeeAreaPoints -- 左手球座区域
private PointCollection leftTeeAreaPoints;
/// <summary>
/// 左手球座区域
/// </summary>
public PointCollection LeftTeeAreaPoints
{
get { return leftTeeAreaPoints; }
set { leftTeeAreaPoints = value; this.RaisePropertyChanged(nameof(LeftTeeAreaPoints)); }
}
#endregion
#region RightTeeAreaPoints -- 右手球座区域
private PointCollection rightTeeAreaPoints;
/// <summary>
/// 右手球座区域
/// </summary>
public PointCollection RightTeeAreaPoints
{
get { return rightTeeAreaPoints; }
set { rightTeeAreaPoints = value; this.RaisePropertyChanged(nameof(RightTeeAreaPoints)); }
}
#endregion
// ===============================================================================
// Public Function
// ===============================================================================
/// <summary>
/// 连接设备
/// </summary>
public void Connect()
{
if (!LaunchMonitor.Connect())
{
// 清除连接失败次数
this.ConnectionFailures = 0;
// 设备序列号
this.SerialNumber = LaunchMonitor.GetSerialNumber();
// 设置已经连接
this.IsConnected = true;
}
}
private PointCollection MapPointCollectionToForm(PointCollection points)
{
PointCollection result = new PointCollection();
foreach (Point p in points)
result.Add(MapPointToForm(p));
return result;
}
private Point MapPointToForm(Point p)
{
return new Point(mCenterX + p.X * mScaleFactor, mCenterY + p.Y * mScaleFactor);
}
}
}
// -----------------------------------------------------------------------
// Class BallFindDLLProxy
//
// Copyright (c) 2021 iTrack LLC
// All rights reserved
//
// This class wraps the itrackAccessDLL data structures and methods,
// alleviating the rest of the App from having to deal with Interop, etc.
//
// -----------------------------------------------------------------------
namespace VIZ.Framework.TVP.Golf
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
public class BallFindDLLProxy
{
// ==================================================
// ===== itrackAccessDLL Import Declarations =====
// ==================================================
// ----- Interop Data Structures -----
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct LaunchMonitorStatus
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
public String FirmwareVers;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 30)]
public String SerialNum;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
public String HardwareVers;
public uint StatusFlags;
public int LMIndex;
};
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct Point2D
{
public int x;
public int y;
};
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct Trapezoid
{
public Point2D topLeft;
public Point2D topRight;
public Point2D bottomLeft;
public Point2D bottomRight;
};
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct BallPlacementParameters
{
public int lcd_width;
public int lcd_height;
public Trapezoid left;
public Trapezoid right;
};
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct BallData
{
public Point2D location;
public int diameter;
};
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct BallPlacementState
{
public int flags;
public int num_balls;
public BallData ball_data0;
public BallData ball_data1;
public BallData ball_data2;
public BallData ball_data3;
public BallData ball_data4;
};
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct HittingMode
{
public int mode; // We could directly pass an int but we'll define this struct for consistency with the DLL declaration
};
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct FlashStatistics
{
public UInt32 total_Sequences;
public UInt32 total_Flashes;
public UInt32 total_EnergyUsed;
public UInt32 total_MisFires; // AKA Invalid Shots
public UInt32 last_shot_Average; // The Average Flash "Feedback" for the most recent valid shot
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct SleepFlags
{
public UInt32 flags; // We could directly pass an int but we'll define this struct for consistency with the DLL declaration
};
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct InstallationFlags
{
public UInt32 flags; // We could directly pass an int but we'll define this struct for consistency with the DLL declaration
};
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct ShotCountData
{
public UInt32 count;
};
// ----- Interop Callback Prototypes -----
public delegate int FsEventCallback(IntPtr pEventInfo, IntPtr pContext);
// ----- Interop Calls -----
private const String DLL_IDENTIFIER = "itrackAccessDLL.dll";
[DllImport(DLL_IDENTIFIER, SetLastError = false, CharSet = CharSet.Unicode)]
public static extern int ITRACK_Initialize(StringBuilder configDirPath, uint flags);
[DllImport(DLL_IDENTIFIER, SetLastError = false)]
public static extern int ITRACK_Shutdown(uint reserved);
[DllImport(DLL_IDENTIFIER, SetLastError = false)]
public static extern int ITRACK_GetLaunchMonitorStatus(int launchMonitorIndex, ref LaunchMonitorStatus launchMonitorStatus);
[DllImport(DLL_IDENTIFIER, SetLastError = false)]
public static extern int ITRACK_SetEventCallback(FsEventCallback eventCallback, IntPtr pContext);
[DllImport(DLL_IDENTIFIER, SetLastError = false)]
public static extern int ITRACK_GetBallPlacementData(ref BallPlacementParameters parameters);
[DllImport(DLL_IDENTIFIER, SetLastError = false)]
public static extern int ITRACK_GetBallPlacementState(ref BallPlacementState state);
[DllImport(DLL_IDENTIFIER, SetLastError = false)]
public static extern int ITRACK_GetHittingMode(ref HittingMode mode);
[DllImport(DLL_IDENTIFIER, SetLastError = false)]
public static extern int ITRACK_SetHittingMode(ref HittingMode mode);
[DllImport(DLL_IDENTIFIER, SetLastError = false)]
public static extern int ITRACK_GetFlashStatistics(ref FlashStatistics stats);
[DllImport(DLL_IDENTIFIER, SetLastError = false)]
public static extern int ITRACK_ResetFlashStatistics();
[DllImport(DLL_IDENTIFIER, SetLastError = false)]
public static extern int ITRACK_GetSleepFlags(ref SleepFlags flags);
[DllImport(DLL_IDENTIFIER, SetLastError = false)]
public static extern int ITRACK_SetSleepFlags(ref SleepFlags flags);
[DllImport(DLL_IDENTIFIER, SetLastError = false)]
public static extern int ITRACK_GetInstallationFlags(ref InstallationFlags flags);
[DllImport(DLL_IDENTIFIER, SetLastError = false)]
public static extern int ITRACK_SetInstallationFlags(ref InstallationFlags flags);
[DllImport(DLL_IDENTIFIER, SetLastError = false)]
public static extern int ITRACK_GetTotalShots(ref ShotCountData data);
[DllImport(DLL_IDENTIFIER, SetLastError = false)]
public static extern int ITRACK_ResetLaunchMonitor();
// ===========================
// ===== Private Members =====
// ===========================
// The following members must have values that match the equivalent values declared in itrackAccess.h
public const int ITRACK_SUCCESS = 0;
public const int ITRACK_LM_SHOTDATA = 1;
public const int ITRACK_BALL_PLACEMENT_STATE_CHANGE = 6;
public const UInt32 ITRACK_DEV_TRACKER_LOCKED = 0x2;
public const UInt32 ITRACK_DEV_RIGHT_BALL_LOCKED = 0x4;
public const UInt32 ITRACK_DEV_HMT_CONNECTED = 0x8;
public const UInt32 ITRACK_SLEEP_FLAG_TRACKER = 0x1;
public const UInt32 ITRACK_SLEEP_FLAG_BLUETOOTH = 0x2;
public const UInt32 ITRACK_INSTALLATION_FLAG_INDOOR_ONLY = 0x1;
} // End of BallFindDLLProxy
}
// -----------------------------------------------------------------------
// Class LaunchMonitor
//
// Copyright (c) 2021 iTrack LLC
// All rights reserved
//
// This class represents the Launch Monitor (connected to the PC via a USB cable) as
// an "object." It provides the ability to connect, disconnect, query and establish
// a callback for Ball-Lock State Change interrupts.
//
// Note: This class assumes only one Launch monitor is physically connected to the PC
// via USB. If more than one is connected, the one that was first connected will
// be used. There is no provision for detecting multiple Launch Monitors or
// selecting a specific Launch Monitor from those connected.
//
// Tip: To add support for multiple Launch Monitors, utilize ITRACK_GetLaunchMonitors and
// present the user with the list of connected Launch Monitors to select from.
//
// -----------------------------------------------------------------------
namespace VIZ.Framework.TVP.Golf
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Runtime.InteropServices;
using System.Windows.Media;
public class LaunchMonitor
{
// ==============================
// ===== Life Cycle Methods =====
// ==============================
public static Boolean Connect()
{
if (mConnected) return true;
mErrorCode = 0;
mConnected = (BallFindDLLProxy.ITRACK_Initialize(null, 0) == BallFindDLLProxy.ITRACK_SUCCESS) && Startup();
return mConnected;
}
public static int GetErrorCode() { return mErrorCode; }
public static void SetBallLockCallback(BallPlacementStateChangeCallback callback)
{
mUserBallPlacementStateChangeCallback = callback;
}
public static void SetNewShotEventCallback(NewShotEventCallback callback)
{
mUserNewShotEventCallback = callback;
}
public static void Disconnect()
{
if (!mConnected) return;
BallFindDLLProxy.ITRACK_Shutdown(0); // An alert should really be generated if this call fails but we're just an example App
mUserBallPlacementStateChangeCallback = null;
mConnected = false;
}
// =================================
// ===== Callback Declarations =====
// =================================
public struct BallData
{
public Point Location;
public double Diameter;
}
public struct BallPlacementState
{
public Boolean mLocked;
public Boolean mLockedRight;
public Boolean mHMTConnected;
public Int32 mBallCount; // The maximum is 5
public BallData[] mBallPositions; // The Array's Size will be mBallCount
}
public delegate void BallPlacementStateChangeCallback(BallPlacementState new_state);
// Note: A Ball Placement State Change occurs when the Lock/Unlock, Left/Right, Ball Count or any Ball Position changes
public delegate void NewShotEventCallback( /* Shot Data Structure */ ); // This example doesn't use Shot Data
// =========================
// ===== Query Methods =====
// =========================
public static Boolean IsConnected()
{
return mConnected;
}
public static string GetSerialNumber()
{
if (!mConnected) return "";
return mStatus.SerialNum;
}
// ----- Metrics -----
public static int GetDisplayWidth()
{
if (!mConnected) return 0;
return mBallPlacementParameters.lcd_width;
}
public static int GetDisplayHeight()
{
if (!mConnected) return 0;
return mBallPlacementParameters.lcd_height;
}
// ----- Installation Flags -----
public static Boolean GetInstallationFlags()
{
return (BallFindDLLProxy.ITRACK_GetInstallationFlags(ref mInstallationFlags) == BallFindDLLProxy.ITRACK_SUCCESS);
}
public static Boolean IndoorOnly() { return (mInstallationFlags.flags & BallFindDLLProxy.ITRACK_INSTALLATION_FLAG_INDOOR_ONLY) == 0; }
public static Boolean SetInstallationFlags(Boolean indoor_only)
{
mInstallationFlags.flags = 0;
if (indoor_only) mInstallationFlags.flags |= BallFindDLLProxy.ITRACK_INSTALLATION_FLAG_INDOOR_ONLY;
return (BallFindDLLProxy.ITRACK_SetInstallationFlags(ref mInstallationFlags) == BallFindDLLProxy.ITRACK_SUCCESS);
}
// ----- Sleep Flags -----
public static Boolean GetSleepFlags()
{
return (BallFindDLLProxy.ITRACK_GetSleepFlags(ref mSleepFlags) == BallFindDLLProxy.ITRACK_SUCCESS);
}
public static Boolean TrackerDisabled() { return (mSleepFlags.flags & BallFindDLLProxy.ITRACK_SLEEP_FLAG_TRACKER) != 0; }
public static Boolean BluetoothDisabled() { return (mSleepFlags.flags & BallFindDLLProxy.ITRACK_SLEEP_FLAG_BLUETOOTH) != 0; }
public static Boolean SetSleepFlags(Boolean tracker, Boolean bluetooth)
{
mSleepFlags.flags = 0;
if (tracker) mSleepFlags.flags |= BallFindDLLProxy.ITRACK_SLEEP_FLAG_TRACKER;
if (bluetooth) mSleepFlags.flags |= BallFindDLLProxy.ITRACK_SLEEP_FLAG_BLUETOOTH;
return (BallFindDLLProxy.ITRACK_SetSleepFlags(ref mSleepFlags) == BallFindDLLProxy.ITRACK_SUCCESS);
}
// ----- Ball Placement -----
public static PointCollection GetTrapezoidPoints(Boolean left) // if left is false then the values of the right trapezoid are returned
{
if (!mConnected) return new PointCollection();
if (left)
return mLeftTeeArea;
// else "right"
return mRightTeeArea;
}
public static BallPlacementState GetBallPlacementState()
{
BallPlacementState result = new BallPlacementState();
BallFindDLLProxy.BallPlacementState state = new BallFindDLLProxy.BallPlacementState();
if (BallFindDLLProxy.ITRACK_GetBallPlacementState(ref state) == BallFindDLLProxy.ITRACK_SUCCESS)
{
result.mLocked = (state.flags & BallFindDLLProxy.ITRACK_DEV_TRACKER_LOCKED) != 0;
result.mLockedRight = (state.flags & BallFindDLLProxy.ITRACK_DEV_RIGHT_BALL_LOCKED) != 0;
result.mHMTConnected = (state.flags & BallFindDLLProxy.ITRACK_DEV_HMT_CONNECTED) != 0;
result.mBallCount = state.num_balls;
result.mBallPositions = new BallData[result.mBallCount];
CopyBallData(ref result, 0, state.ball_data0);
CopyBallData(ref result, 1, state.ball_data1);
CopyBallData(ref result, 2, state.ball_data2);
CopyBallData(ref result, 3, state.ball_data3);
CopyBallData(ref result, 4, state.ball_data4);
}
return result;
}
// ----- Hitting Mode -----
public enum HittingMode { NORMAL, RIGHT_ONLY, LEFT_ONLY, UNDEFINED };
public static HittingMode GetHittingMode()
{
mHittingMode.mode = -1;
if (BallFindDLLProxy.ITRACK_GetHittingMode(ref mHittingMode) == BallFindDLLProxy.ITRACK_SUCCESS)
switch (mHittingMode.mode)
{
case 0: return HittingMode.NORMAL;
case 1: return HittingMode.RIGHT_ONLY;
case 2: return HittingMode.LEFT_ONLY;
}
return HittingMode.UNDEFINED;
}
public static Boolean SetHittingMode(HittingMode mode)
{
mHittingMode.mode = (int)mode;
return (BallFindDLLProxy.ITRACK_SetHittingMode(ref mHittingMode) == BallFindDLLProxy.ITRACK_SUCCESS);
}
// ----- Flash Statistics -----
public static Boolean GetFlashStatistics()
{
return (BallFindDLLProxy.ITRACK_GetFlashStatistics(ref mFlashStatistics) == BallFindDLLProxy.ITRACK_SUCCESS);
}
public static UInt32 GetFlashSequences() { return mFlashStatistics.total_Sequences; }
public static UInt32 GetTotalFlashCount() { return mFlashStatistics.total_Flashes; }
public static UInt32 GetTotalEnergyUse() { return mFlashStatistics.total_EnergyUsed; }
public static UInt32 GetTotalMisfires() { return mFlashStatistics.total_MisFires; }
public static UInt32 GetLastShotAverageEnergy() { return mFlashStatistics.last_shot_Average; }
public static Boolean ResetFlashStatistics()
{
return (BallFindDLLProxy.ITRACK_ResetFlashStatistics() == BallFindDLLProxy.ITRACK_SUCCESS);
}
// ----- Shot Count -----
public static UInt32 GetShotCount()
{
if (BallFindDLLProxy.ITRACK_GetTotalShots(ref mShotCountData) == BallFindDLLProxy.ITRACK_SUCCESS)
return mShotCountData.count;
return 0;
}
// ----- Reset -----
public static Boolean Reset()
{
return (BallFindDLLProxy.ITRACK_ResetLaunchMonitor() == BallFindDLLProxy.ITRACK_SUCCESS);
}
// ===========================
// ===== Private Methods =====
// ===========================
private static Boolean Startup()
{
Wait(1000); // ITRACK_Initialize returns before it's actually ready (and needs our thread to sleep a little so it can finish)
// note: itrack NET link heart beat timeout is 100ms
if (BallFindDLLProxy.ITRACK_GetLaunchMonitorStatus(0, ref mStatus) != BallFindDLLProxy.ITRACK_SUCCESS)
{
mErrorCode = 1;
BallFindDLLProxy.ITRACK_Shutdown(0);
return false;
}
if (BallFindDLLProxy.ITRACK_SetEventCallback(mDLLEventCallback, (IntPtr)null) != BallFindDLLProxy.ITRACK_SUCCESS)
{
mErrorCode = 2;
BallFindDLLProxy.ITRACK_Shutdown(0);
return false;
}
if (BallFindDLLProxy.ITRACK_GetBallPlacementData(ref mBallPlacementParameters) != BallFindDLLProxy.ITRACK_SUCCESS)
{
mErrorCode = 3;
BallFindDLLProxy.ITRACK_Shutdown(0);
return false;
}
GenerateNormalizedTrapezoids();
return true;
}
private static void GenerateNormalizedTrapezoids()
{
// Copy all of the vertices (Point2D integers) from both trapezoids into a single array of Point doubles
Point[] vertices = new Point[8]; // 2 trapezoids x 4 vertices per trapezoid
vertices[0].X = mBallPlacementParameters.left.topLeft.x; vertices[0].Y = mBallPlacementParameters.left.topLeft.y;
vertices[1].X = mBallPlacementParameters.left.topRight.x; vertices[1].Y = mBallPlacementParameters.left.topRight.y;
vertices[2].X = mBallPlacementParameters.left.bottomRight.x; vertices[2].Y = mBallPlacementParameters.left.bottomRight.y;
vertices[3].X = mBallPlacementParameters.left.bottomLeft.x; vertices[3].Y = mBallPlacementParameters.left.bottomLeft.y;
vertices[4].X = mBallPlacementParameters.right.topLeft.x; vertices[4].Y = mBallPlacementParameters.right.topLeft.y;
vertices[5].X = mBallPlacementParameters.right.topRight.x; vertices[5].Y = mBallPlacementParameters.right.topRight.y;
vertices[6].X = mBallPlacementParameters.right.bottomRight.x; vertices[6].Y = mBallPlacementParameters.right.bottomRight.y;
vertices[7].X = mBallPlacementParameters.right.bottomLeft.x; vertices[7].Y = mBallPlacementParameters.right.bottomLeft.y;
// Get the extent of the vertices
double min_x, max_x, min_y, max_y;
min_x = min_y = Int32.MaxValue;
max_x = max_y = Int32.MinValue;
for (int i = 0; i < 8; i++)
{
if (vertices[i].X < min_x) min_x = vertices[i].X;
if (vertices[i].X > max_x) max_x = vertices[i].X;
if (vertices[i].Y < min_y) min_y = vertices[i].Y;
if (vertices[i].Y > max_y) max_y = vertices[i].Y;
}
// Calculate the geometeric center of the vertices
double width = max_x - min_x;
double height = max_y - min_y;
mNormalizedCenterX = 0.5 * (min_x + max_x);
mNormalizedCenterY = 0.5 * (min_y + max_y);
// Calculate the factor which can be used to map the "DEV LCD space" to our "normalized space"
if (width > height)
mNormalizingFactor = 1.0 / width;
else
mNormalizingFactor = 1.0 / height;
// Convert the verticies of the trapezoids into normalized vertices (range = -0.5 to +0.5 with 0.0 at their geometeric center)
for (int i = 0; i < 8; i++)
{
vertices[i].X = (vertices[i].X - mNormalizedCenterX) * mNormalizingFactor;
vertices[i].Y = (vertices[i].Y - mNormalizedCenterY) * mNormalizingFactor;
}
// Set the "Tee Areas" from the normalized vertices
mLeftTeeArea = new PointCollection(new[] { vertices[0], vertices[1], vertices[2], vertices[3] });
mRightTeeArea = new PointCollection(new[] { vertices[4], vertices[5], vertices[6], vertices[7] });
}
private static void NormalizePoint(ref Point p)
{
p.X = (p.X - mNormalizedCenterX) * mNormalizingFactor;
p.Y = (p.Y - mNormalizedCenterY) * mNormalizingFactor;
}
private static void NormalizeDouble(ref double d)
{
d *= mNormalizingFactor;
}
private static void CopyBallData(ref BallPlacementState result, int index, BallFindDLLProxy.BallData ball_data)
{
if (result.mBallCount > index)
{
result.mBallPositions[index].Location.X = ball_data.location.x;
result.mBallPositions[index].Location.Y = ball_data.location.y;
result.mBallPositions[index].Diameter = ball_data.diameter;
NormalizePoint(ref result.mBallPositions[index].Location);
NormalizeDouble(ref result.mBallPositions[index].Diameter);
}
}
private static void Wait(int ms)
{
System.Threading.Thread.Sleep(ms);
}
// ----- Event Handling -----
private static int DEVEventCallback(IntPtr pEventInfo, IntPtr pContext)
{
Int32 event_id = Marshal.ReadInt32(pEventInfo); pEventInfo += 4;
switch (event_id)
{
case BallFindDLLProxy.ITRACK_BALL_PLACEMENT_STATE_CHANGE: return HandleBallPlacementStateEvent(pEventInfo);
case BallFindDLLProxy.ITRACK_LM_SHOTDATA: return HandleNewShotEvent(pEventInfo);
}
return 0; // not our event
}
private static int HandleBallPlacementStateEvent(IntPtr pEventInfo)
{
if (mUserBallPlacementStateChangeCallback == null) return 0; // no need to handle the event
BallPlacementState state = new BallPlacementState();
UInt32 flags = (UInt32)Marshal.ReadInt32(pEventInfo); pEventInfo += 4;
state.mLocked = (flags & BallFindDLLProxy.ITRACK_DEV_TRACKER_LOCKED) != 0;
state.mLockedRight = (flags & BallFindDLLProxy.ITRACK_DEV_RIGHT_BALL_LOCKED) != 0;
state.mHMTConnected = (flags & BallFindDLLProxy.ITRACK_DEV_HMT_CONNECTED) != 0;
state.mBallCount = Marshal.ReadInt32(pEventInfo); pEventInfo += 4;
state.mBallPositions = new BallData[state.mBallCount];
for (int i = 0; i < state.mBallCount; i++)
{
state.mBallPositions[i].Location.X = Marshal.ReadInt32(pEventInfo); pEventInfo += 4;
state.mBallPositions[i].Location.Y = Marshal.ReadInt32(pEventInfo); pEventInfo += 4;
state.mBallPositions[i].Diameter = Marshal.ReadInt32(pEventInfo); pEventInfo += 4;
NormalizePoint(ref state.mBallPositions[i].Location);
NormalizeDouble(ref state.mBallPositions[i].Diameter);
}
mUserBallPlacementStateChangeCallback(state);
return 1;
}
private static int HandleNewShotEvent(IntPtr pEventInfo)
{
if (mUserNewShotEventCallback == null) return 0; // no need to handle the event
mUserNewShotEventCallback( /* Shot Data Structure */ ); // This example doesn't use Shot Data
return 1;
}
// ===========================
// ===== Private Members =====
// ===========================
private static Boolean mConnected = false;
private static BallFindDLLProxy.LaunchMonitorStatus mStatus = new BallFindDLLProxy.LaunchMonitorStatus();
private static BallFindDLLProxy.BallPlacementParameters mBallPlacementParameters = new BallFindDLLProxy.BallPlacementParameters();
private static BallFindDLLProxy.FsEventCallback mDLLEventCallback = new BallFindDLLProxy.FsEventCallback(DEVEventCallback);
private static BallPlacementStateChangeCallback mUserBallPlacementStateChangeCallback = null;
private static NewShotEventCallback mUserNewShotEventCallback = null;
static BallFindDLLProxy.HittingMode mHittingMode = new BallFindDLLProxy.HittingMode();
private static double mNormalizedCenterX = 0.0;
private static double mNormalizedCenterY = 0.0;
private static double mNormalizingFactor = 0.0;
private static PointCollection mLeftTeeArea;
private static PointCollection mRightTeeArea;
private static BallFindDLLProxy.FlashStatistics mFlashStatistics = new BallFindDLLProxy.FlashStatistics();
private static BallFindDLLProxy.SleepFlags mSleepFlags = new BallFindDLLProxy.SleepFlags();
private static BallFindDLLProxy.InstallationFlags mInstallationFlags = new BallFindDLLProxy.InstallationFlags();
private static int mErrorCode = 0;
private static BallFindDLLProxy.ShotCountData mShotCountData = new BallFindDLLProxy.ShotCountData();
} // End of BallLockDLLProxy Class
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VIZ.Framework.TVP.Golf
{
/// <summary>
/// 监视错误码
/// </summary>
public enum LaunchMonitorErrorCode
{
}
}
...@@ -85,6 +85,10 @@ ...@@ -85,6 +85,10 @@
<DependentUpon>Settings.settings</DependentUpon> <DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput> <DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile> </Compile>
<Compile Include="SDK\BallFindDLLProxy.cs" />
<Compile Include="SDK\LaunchMonitor.cs" />
<Compile Include="Model\GolfDeviceModel.cs" />
<Compile Include="SDK\LaunchMonitorErrorCode.cs" />
<EmbeddedResource Include="Properties\Resources.resx"> <EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator> <Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput> <LastGenOutput>Resources.Designer.cs</LastGenOutput>
...@@ -115,5 +119,11 @@ ...@@ -115,5 +119,11 @@
<None Include="Lib\itrackSDK_usb\ReadMe_usb.txt" /> <None Include="Lib\itrackSDK_usb\ReadMe_usb.txt" />
<None Include="Lib\itrackSDK_usb\SDKSampleApp.exe" /> <None Include="Lib\itrackSDK_usb\SDKSampleApp.exe" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<ProjectReference Include="..\VIZ.Framework.Core\VIZ.Framework.Core.csproj">
<Project>{75b39591-4bc3-4b09-bd7d-ec9f67efa96e}</Project>
<Name>VIZ.Framework.Core</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project> </Project>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment