using PTMedicalInsurance.Variables;
using RFID;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace PTMedicalInsurance.Business.MetalKeyboard.JustTideEPP
{
public class MetalKeypadPasswordReaderOld
{
private int timeouts = 200000;
public void OpenKeyboard()
{
//打开串口
if (JustTideEPPDrv.OpenCom(3, 9600) != 0)
{
Global.writeLog("打开串口失败");
}
else
{
Global.writeLog("打开串口成功");
}
//打开键盘
if (JustTideEPPDrv.EnableKeyboard() != 0)
{
Global.writeLog("打开键盘失败");
}
else
{
Global.writeLog("打开键盘成功");
}
//轮询获取字符并发送到光标处
if (GetAndSendPassword() != 0)
{
Global.writeLog("获取密码失败");
return;
}
else
{
Global.writeLog("获取密码成功");
return;
}
}
public void CloseKeyboard()
{
//关闭键盘
if (JustTideEPPDrv.DisableKeyboard() != 0)
{
Global.writeLog("关闭键盘失败");
}
else
{
Global.writeLog("关闭键盘成功");
}
//关闭串口
if (JustTideEPPDrv.CloseCom() != 0)
{
Global.writeLog("关闭串口失败");
}
else
{
Global.writeLog("关闭串口成功");
}
}
private int GetAndSendPassword()
{
char key = '\0';
// 使用 Stopwatch 实现超时
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
try
{
// 主循环:持续轮询,直到超时
while (stopwatch.ElapsedMilliseconds < timeouts) // timeouts 是您的超时毫秒数
{
short result = JustTideEPPDrv.PinReportPressed(ref key, 1); // 非阻塞调用
if (result == 0) // 成功读取到按键
{
string hexStr = ((int)key).ToString("X2");
// --- 核心:发送字符到焦点窗口 ---
if (hexStr != "0D" && hexStr != "1B") // 排除回车和ESC
{
new SendMsg().SendText(key.ToString());
}
else if (hexStr == "0D") // 回车键 '#'
{
new SendMsg().SendText(key.ToString());
return 0; // 收到确认,成功返回
}
else if (hexStr == "1B") // ESC键
{
new SendMsg().SendText(key.ToString());
return 0; // 收到取消,也返回成功(或可返回特定码)
}
}
// else: result != 0 表示无按键,继续循环等待
// 关键:同步延迟,避免CPU空转
// 这会在当前线程上阻塞 50ms
System.Threading.Thread.Sleep(50);
}
// 如果走到这里,说明超时了
// 可以选择发送超时信号或直接返回
return -1; // 表示超时
}
catch (Exception ex)
{
// 捕获任何意外异常(虽然 PinReportPressed 可能不会抛出)
// 可以记录日志
// Logger.Error($"GetAndSendPassword error: {ex.Message}");
return -99; // 表示未知错误
}
finally
{
stopwatch.Stop(); // 停止计时器
// 如果需要,可以在这里执行清理工作
}
}
}
public class MetalKeypadPasswordReader : IDisposable
{
private CancellationTokenSource _listenCts;
private Task _listenTask;
private bool _isListening = false;
private const int DEFAULT_TIMEOUT = 30000; // 30秒超时,可根据需要调整
public int timeouts = DEFAULT_TIMEOUT; // 可以让调用方设置超时
///
/// 打开串口和键盘,并启动后台监听(非阻塞)
///
public void OpenKeyboard()
{
if (_isListening)
{
// 已经在监听,避免重复打开
return;
}
// 1. 打开串口
if (JustTideEPPDrv.OpenCom(3, 9600) != 0)
{
Global.writeLog("打开串口失败");
return;
}
else
{
Global.writeLog("打开串口成功");
}
// 2. 打开键盘
if (JustTideEPPDrv.EnableKeyboard() != 0)
{
Global.writeLog("打开键盘失败");
JustTideEPPDrv.CloseCom(); // 清理
return;
}
else
{
Global.writeLog("打开键盘成功");
}
// 3. 启动后台监听任务(关键:非阻塞)
_listenCts = new CancellationTokenSource();
_listenTask = Task.Run(() => ListenLoop(_listenCts.Token), _listenCts.Token);
_isListening = true;
// OpenKeyboard 方法立即返回,不会阻塞!
}
///
/// 后台监听循环 - 替代原来的 GetAndSendPassword
///
private async Task ListenLoop(CancellationToken ct)
{
char key = '\0';
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
try
{
while (!ct.IsCancellationRequested && stopwatch.ElapsedMilliseconds < timeouts)
{
short result = JustTideEPPDrv.PinReportPressed(ref key, 1);
if (result == 0)
{
string hexStr = ((int)key).ToString("X2");
// 发送字符到焦点窗口
if (hexStr != "0D" && hexStr != "1B")
{
new SendMsg().SendText(key.ToString());
}
else if (hexStr == "0D" || hexStr == "1B") // # 或 ESC
{
new SendMsg().SendText(key.ToString());
// 收到结束键,退出监听循环
break;
}
}
// 非阻塞延迟
await Task.Delay(50, ct);
}
// 如果是因为超时退出,可以做些处理(可选)
if (!ct.IsCancellationRequested && !stopwatch.IsRunning)
{
// Global.writeLog("键盘监听超时");
}
}
catch (Exception ex)
{
// 记录日志
// Logger.Error($"ListenLoop error: {ex.Message}");
}
finally
{
stopwatch.Stop();
}
}
///
/// 停止监听并关闭硬件
///
public void CloseKeyboard()
{
if (!_isListening)
{
return;
}
// 1. 停止后台监听任务
_listenCts?.Cancel();
try
{
_listenTask?.Wait(); // 等待监听任务结束
}
catch (AggregateException) { /* 忽略取消异常 */ }
_listenCts?.Dispose();
_listenCts = null;
_listenTask = null;
_isListening = false;
// 2. 关闭键盘
if (JustTideEPPDrv.DisableKeyboard() != 0)
{
Global.writeLog("关闭键盘失败");
}
else
{
Global.writeLog("关闭键盘成功");
}
// 3. 关闭串口
if (JustTideEPPDrv.CloseCom() != 0)
{
Global.writeLog("关闭串口失败");
}
else
{
Global.writeLog("关闭串口成功");
}
}
public void Dispose()
{
CloseKeyboard();
}
}
}