diff --git a/Windows/CS/Framework4.0/Toprie/Toprie/Camera.cs b/Windows/CS/Framework4.0/Toprie/Toprie/Camera.cs
index 4a55c21..b2df931 100644
--- a/Windows/CS/Framework4.0/Toprie/Toprie/Camera.cs
+++ b/Windows/CS/Framework4.0/Toprie/Toprie/Camera.cs
@@ -188,7 +188,7 @@ namespace JoyD.Windows.CS.Toprie
}
///
- /// 开始接收图像
+ /// 开始接收图像(使用HTTP方式)
///
private void StartReceiveImage()
{
@@ -196,7 +196,9 @@ namespace JoyD.Windows.CS.Toprie
{
if (!_isReceivingImage && _deviceManager.ConnectionStatus == ConnectionStatus.Connected)
{
- _deviceManager.StartReceiveImage();
+ Console.WriteLine("Camera开始使用HTTP方式接收图像");
+ // 直接调用HTTP方式的图像接收
+ _deviceManager.StartImageReceiving();
_isReceivingImage = true;
}
}
diff --git a/Windows/CS/Framework4.0/Toprie/Toprie/DeviceManager.cs b/Windows/CS/Framework4.0/Toprie/Toprie/DeviceManager.cs
index fce6266..c2c8f2f 100644
--- a/Windows/CS/Framework4.0/Toprie/Toprie/DeviceManager.cs
+++ b/Windows/CS/Framework4.0/Toprie/Toprie/DeviceManager.cs
@@ -1078,6 +1078,7 @@ namespace JoyD.Windows.CS.Toprie
///
public void StartImageReceiving()
{
+ Console.WriteLine("开始使用HTTP方式接收图像数据");
try
{
// 确保之前的连接已关闭
@@ -1157,11 +1158,19 @@ namespace JoyD.Windows.CS.Toprie
///
private void ReceiveImageDataWithHttpWebRequest()
{
+ Console.WriteLine($"图像接收线程启动: 使用HTTP请求获取图像数据");
try
{
- string url = string.Format("http://{0}:8080{1}", DeviceIp, _isInfraredMode ? "/img.jpg" : "/visible.jpg");
+ string url = string.Format("http://{0}:8080{1}", DeviceIp, _isInfraredMode ? "/video/infrared.jpg" : "/video/optical.jpg");
while (_isReceivingImages)
{
+ // 确保连接状态正常
+ if (_connectionStatus != ConnectionStatus.Connected)
+ {
+ Console.WriteLine("连接状态异常,暂停图像接收");
+ Thread.Sleep(500);
+ continue;
+ }
// 添加时间戳避免缓存
string timestampUrl = url + "?t=" + DateTime.Now.Ticks;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(timestampUrl);
@@ -1169,6 +1178,7 @@ namespace JoyD.Windows.CS.Toprie
request.Timeout = 3000; // 3秒超时
request.KeepAlive = true;
request.UserAgent = "Mozilla/5.0"; // 模拟浏览器
+ request.ServicePoint.Expect100Continue = false; // 优化HTTP请求性能
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
@@ -1206,8 +1216,19 @@ namespace JoyD.Windows.CS.Toprie
// 记录异常并尝试重连
if (_isReceivingImages)
{
- Console.WriteLine("ReceiveImageDataWithHttpWebRequest error: " + ex.Message);
- StartImageReconnect();
+ Console.WriteLine($"ReceiveImageDataWithHttpWebRequest error: {ex.Message}");
+ // 避免频繁重连
+ Thread.Sleep(100);
+
+ // 只有在连接状态为Connected时才尝试图像重连
+ if (_connectionStatus == ConnectionStatus.Connected)
+ {
+ StartImageReconnect();
+ }
+ else
+ {
+ Console.WriteLine("连接已断开,不启动图像重连");
+ }
}
}
}
@@ -1625,22 +1646,19 @@ namespace JoyD.Windows.CS.Toprie
}
///
- /// 开始接收图像
+ /// 开始接收图像(已弃用,使用HTTP方式替代)
///
public void StartReceiveImage()
{
+ Console.WriteLine("已弃用的StartReceiveImage方法,自动切换到HTTP方式");
+
if (_connectionStatus != ConnectionStatus.Connected)
{
throw new InvalidOperationException("设备未连接,无法开始接收图像");
}
- ResetStopFlag();
- Thread imageThread = new Thread(ReceiveImageThread)
- {
- IsBackground = true,
- Name = "ImageReceiver"
- };
- imageThread.Start();
+ // 直接调用HTTP方式的图像接收
+ StartImageReceiving();
}
///
@@ -1652,12 +1670,23 @@ namespace JoyD.Windows.CS.Toprie
}
///
- /// 图像接收线程
+ /// 图像接收线程 (已弃用,使用HTTP方式替代)
///
private void ReceiveImageThread()
{
+ Console.WriteLine("警告: 已弃用的图像接收方式,使用HTTP方式替代");
try
{
+ // 如果调用了这个方法,自动切换到HTTP方式
+ if (!_stopRequested.WaitOne(0))
+ {
+ Console.WriteLine("自动切换到HTTP方式获取图像数据");
+ if (_imageReceiveThread == null || !_imageReceiveThread.IsAlive)
+ {
+ StartImageReceiving(); // 启动HTTP方式
+ }
+ return;
+ }
// 持续获取图像数据
while (!_stopRequested.WaitOne(0))
{
@@ -1996,7 +2025,12 @@ namespace JoyD.Windows.CS.Toprie
if (_isReconnecting != 0)
{
Console.WriteLine("检测到正在重连过程中,暂停设备连接");
- UpdateConnectionStatus(ConnectionStatus.Disconnected, "正在进行自动重连,请稍后再试");
+ // 保持当前状态,不切换到Disconnected,避免状态闪烁
+ // 只输出提示信息,不更改状态
+ if (_connectionStatus != ConnectionStatus.Reconnecting)
+ {
+ UpdateConnectionStatus(_connectionStatus, "正在进行自动重连,请稍后再试");
+ }
return;
}
@@ -2046,8 +2080,9 @@ namespace JoyD.Windows.CS.Toprie
_a8Sdk = new A8SDK(_deviceIp);
Console.WriteLine("SDK实例创建完成");
- // 验证连接是否成功(通过心跳检测)
- Console.WriteLine("尝试发送心跳包进行连接验证...(尝试 1/3)");
+ // 注意:设备使用UDP协议通信,不需要建立TCP连接
+ // 通过心跳检测来验证设备可达性
+ Console.WriteLine("尝试发送UDP心跳包进行设备验证...(尝试 1/3)");
int heartbeatResult = _a8Sdk.Heartbeat();
// 尝试多次心跳检测,增加连接成功率
@@ -2055,22 +2090,22 @@ namespace JoyD.Windows.CS.Toprie
while (heartbeatResult <= 0 && retryCount < 3)
{
retryCount++;
- Console.WriteLine($"心跳检测失败,等待500ms后重试...(尝试 {retryCount}/3)");
+ Console.WriteLine($"UDP心跳检测失败,等待500ms后重试...(尝试 {retryCount}/3)");
Thread.Sleep(500);
heartbeatResult = _a8Sdk.Heartbeat();
}
if (heartbeatResult <= 0)
{
- Console.WriteLine("多次心跳检测均失败");
+ Console.WriteLine("多次UDP心跳检测均失败");
// 安全释放SDK实例
if (_a8Sdk != null)
{
_a8Sdk = null;
}
- throw new Exception("心跳检测失败,设备可能未响应或端口配置错误");
+ throw new Exception("UDP心跳检测失败,设备可能未响应或端口配置错误(应为18890)");
}
- Console.WriteLine("心跳检测成功,设备连接有效");
+ Console.WriteLine("UDP心跳检测成功,设备连接有效");
// 连接成功
result = true;
diff --git a/Windows/CS/Framework4.0/Toprie/Toprie/V8.cs b/Windows/CS/Framework4.0/Toprie/Toprie/V8.cs
index 090ddea..e45592e 100644
--- a/Windows/CS/Framework4.0/Toprie/Toprie/V8.cs
+++ b/Windows/CS/Framework4.0/Toprie/Toprie/V8.cs
@@ -143,40 +143,40 @@ namespace JoyD.Windows.CS.Toprie
{
try
{
- if (isConnected && socket != null && socket.Connected)
- return true;
-
- // 创建Socket连接
- socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
- socket.ReceiveTimeout = TIMEOUT;
- socket.SendTimeout = TIMEOUT;
- socket.Connect(deviceIp, SDK_PORT);
+ // 注意:设备使用UDP协议通信,不需要建立TCP连接
+ // 直接设置连接状态为true,表示准备好进行UDP通信
+ // 这里仍然保持isConnected标志,以兼容现有代码逻辑
isConnected = true;
+ Console.WriteLine($"UDP通信准备就绪,目标设备 {deviceIp}:18890");
return true;
}
catch (Exception ex)
{
- Console.WriteLine($"连接设备 {deviceIp} 失败: {ex.Message}");
+ Console.WriteLine($"初始化UDP通信失败: {ex.Message}");
isConnected = false;
return false;
}
}
- // 断开连接
+ // 断开连接(UDP模式下)
private void Disconnect()
{
try
{
+ // 注意:在UDP模式下,不需要关闭socket连接
+ // 只需重置连接状态标志
+ // 仍然清理socket资源以防万一
if (socket != null)
{
socket.Close();
socket = null;
}
isConnected = false;
+ Console.WriteLine("UDP通信状态已重置");
}
catch (Exception ex)
{
- Console.WriteLine($"断开连接失败: {ex.Message}");
+ Console.WriteLine($"重置UDP通信状态失败: {ex.Message}");
}
}
@@ -184,30 +184,32 @@ namespace JoyD.Windows.CS.Toprie
private bool SendCommand(byte[] command, out byte[] response, int responseLength = 0)
{
response = null;
- if (!Connect())
- return false;
try
{
- // 发送命令
- socket.Send(command);
-
- // 接收响应
- byte[] buffer = new byte[BUFFER_SIZE];
- int bytesRead = socket.Receive(buffer);
-
- if (bytesRead > 0)
+ // 修改为UDP协议,与SDK保持一致
+ // SDK中使用的是UDP协议(socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))
+ // 端口使用18890,与SDK中的CMD_SERVER_UDP_PORT保持一致
+ using (UdpClient udpClient = new UdpClient())
{
- response = new byte[bytesRead];
- Array.Copy(buffer, response, bytesRead);
+ // 设置接收超时,与SDK中的超时保持一致
+ udpClient.Client.ReceiveTimeout = 200; // SDK中普通命令超时为200ms
+
+ // 发送UDP数据报,端口使用18890与SDK保持一致
+ udpClient.Send(command, command.Length, deviceIp, 18890);
+ Console.WriteLine($"UDP命令已发送到 {deviceIp}:18890");
+
+ // 尝试接收响应
+ IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
+ response = udpClient.Receive(ref remoteEndPoint);
+
+ Console.WriteLine($"收到UDP命令响应,长度: {response.Length}");
return true;
}
- return false;
}
catch (Exception ex)
{
- Console.WriteLine($"发送命令失败: {ex.Message}");
- Disconnect();
+ Console.WriteLine($"UDP发送命令失败: {ex.Message}");
return false;
}
}
@@ -216,30 +218,36 @@ namespace JoyD.Windows.CS.Toprie
private bool SendCommand(string cmd, out string response)
{
response = null;
- if (!Connect())
- return false;
try
{
- // 发送命令
- byte[] commandBytes = Encoding.ASCII.GetBytes(cmd);
- socket.Send(commandBytes);
-
- // 接收响应
- byte[] buffer = new byte[BUFFER_SIZE];
- int bytesRead = socket.Receive(buffer);
-
- if (bytesRead > 0)
+ // 修改为UDP协议,与SDK保持一致
+ // SDK中使用的是UDP协议(socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))
+ // 端口使用18890,与SDK中的CMD_SERVER_UDP_PORT保持一致
+ using (UdpClient udpClient = new UdpClient())
{
- response = Encoding.ASCII.GetString(buffer, 0, bytesRead);
+ // 设置接收超时,与SDK中的超时保持一致
+ udpClient.Client.ReceiveTimeout = 200; // SDK中普通命令超时为200ms
+
+ // 发送UDP数据报,端口使用18890与SDK保持一致
+ byte[] commandBytes = Encoding.ASCII.GetBytes(cmd);
+ udpClient.Send(commandBytes, commandBytes.Length, deviceIp, 18890);
+ Console.WriteLine($"UDP命令已发送: {cmd}");
+ Console.WriteLine($"目标IP: {deviceIp}:18890");
+
+ // 尝试接收响应
+ IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
+ byte[] responseBytes = udpClient.Receive(ref remoteEndPoint);
+ response = Encoding.ASCII.GetString(responseBytes);
+
+ Console.WriteLine($"收到UDP命令响应: {response}");
return true;
}
- return false;
+
}
catch (Exception ex)
{
- Console.WriteLine($"发送命令失败: {ex.Message}");
- Disconnect();
+ Console.WriteLine($"UDP发送命令失败: {ex.Message}");
return false;
}
}
@@ -1679,29 +1687,55 @@ namespace JoyD.Windows.CS.Toprie
{
try
{
- // 设置接收超时,与SDK中的50毫秒保持一致
- udpClient.Client.ReceiveTimeout = 50;
+ // 注意:SDK中tv_out.tv_sec=50实际表示50秒,这是SDK的实现方式
+ // 这里我们设置一个更合理的值500毫秒,既保证能接收到响应,又不会等待太久
+ udpClient.Client.ReceiveTimeout = 500;
// 发送UDP数据报,端口使用18890与SDK保持一致
udpClient.Send(commandBytes, commandBytes.Length, deviceIp, 18890);
- Console.WriteLine("UDP心跳命令已发送");
+ Console.WriteLine("UDP心跳命令已发送,等待响应...");
// 尝试接收响应
IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
- byte[] responseBytes = udpClient.Receive(ref remoteEndPoint);
- string response = Encoding.ASCII.GetString(responseBytes);
- Console.WriteLine($"收到UDP心跳响应: {response}");
-
- // SDK要求响应中必须包含 ":ok" 字符串才算成功
- if (!string.IsNullOrEmpty(response) && response.Contains(":ok"))
+ // 使用BeginReceive和EndReceive进行非阻塞接收,更好地处理超时
+ IAsyncResult ar = udpClient.BeginReceive(null, null);
+ if (ar.AsyncWaitHandle.WaitOne(500)) // 额外的超时检查,双重保险
{
- Console.WriteLine("心跳成功: 响应包含':ok'");
- return 1; // 返回1表示成功,与DeviceManager中的判断一致
+ try
+ {
+ byte[] responseBytes = udpClient.EndReceive(ar, ref remoteEndPoint);
+ string response = Encoding.ASCII.GetString(responseBytes);
+
+ Console.WriteLine($"收到UDP心跳响应: {response}");
+ // 不使用LINQ的Select方法,避免缺少System.Linq命名空间的问题
+ string[] asciiValues = new string[response.Length];
+ for (int i = 0; i < response.Length; i++)
+ {
+ asciiValues[i] = ((int)response[i]).ToString();
+ }
+ Console.WriteLine($"响应长度: {response.Length} 字节,响应ASCII码: {string.Join(",", asciiValues)}");
+
+ // SDK要求响应中必须包含 ":ok" 字符串才算成功
+ if (!string.IsNullOrEmpty(response) && response.Contains(":ok"))
+ {
+ Console.WriteLine("心跳成功: 响应包含':ok'");
+ return 1; // 返回1表示成功,与DeviceManager中的heartbeatResult > 0判断一致
+ }
+ else
+ {
+ Console.WriteLine($"心跳响应不包含':ok',验证失败。收到的响应: '{response}'");
+ }
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"处理UDP响应时发生异常: {ex.Message}");
+ }
}
else
{
- Console.WriteLine("心跳响应不包含':ok',验证失败");
+ Console.WriteLine("UDP接收超时,取消接收操作");
+ udpClient.Close(); // 关闭以取消接收操作
}
}
catch (SocketException ex) when (ex.SocketErrorCode == SocketError.TimedOut)
@@ -1722,8 +1756,8 @@ namespace JoyD.Windows.CS.Toprie
}
}
- // 3次尝试都失败
- Console.WriteLine("三次心跳检测均失败");
+ // 所有重试都失败了
+ Console.WriteLine("三次心跳检测均失败,连接未建立");
return -1;
}
catch (Exception ex)