不管你是用.net framework還是用.net core或者更高版本.net環境,這篇文章也許都能幫到你!因為接下來我會提供一個簡單粗暴的方式,來快速實現多款掃碼器的通用掃碼功能。目前本地測試過的包括基恩士系列、康耐視系列、以及其他支援乙太網通訊的多款小眾廠家等。
下面開始重點操作:
首先,在你的專案裡面引用Wesky.Net.OpenTools 包,1.0.7以及以上版本均可。
如果你是在.netframework環境下面開放,或者是沒有使用依賴注入的專案中使用,使用方式可以直接new一個物件來使用,有關使用如下程式碼:
ICodeReader reader = new CodeReader();
ReaderClientInfo clientInfo = new ReaderClientInfo(); // 掃碼器客戶端例項
clientInfo.Ip = IPAddress.Parse("192.168.1.102"); // 掃碼器IP
clientInfo.Port = 3000; // 掃碼器埠號
clientInfo.Count = 3; // 沒掃到碼重試次數
clientInfo.SendTimeOut = 3000; // 請求超時 毫秒
clientInfo.ReceiveTimeOut = 3000; // 接收掃碼內容超時 毫秒
clientInfo.Brand = "SR"; // 掃碼器品牌
clientInfo.Command = "CMD"; // 掃碼器觸發指令,指令可透過各個掃碼器廠家提供的配置軟體,配置為通用的
clientInfo.ReaderNo = 1; // 掃碼器編號,可自定義,例如有10個,就可以配置1-10號
clientInfo.CloseCommand = ""; // 停止觸發指令,如果沒有則預設空字串即可
ReaderResultInfo res = reader.ReaderConnection(ref clientInfo); // 通訊連線,連線掃碼器服務端,引數返回客戶端例項 以及 標準返回值型別ReaderResultInfo
if (!res.IsSucceed)
{
Console.WriteLine($"與掃碼器建立通訊連線失敗:{res.Message}");
return;
}
res = reader.ReaderRead(ref clientInfo); // 傳入掃碼器客戶端例項,進行掃碼。並引數內返回最新的掃碼器客戶端例項
if (!res.IsSucceed)
{
Console.WriteLine($"掃碼異常:{res.Message}");
return;
}
else
{
Console.WriteLine($"掃到碼:{res.Value} 掃碼耗時:{res.ElapsedMilliseconds}");
}
當然,強烈建議你們的專案使用.net core或以上環境。畢竟.net core是開源的,還可以跨平臺,不管你是在Windows執行還是在Linux,都可以執行。
下面是在.net core或以上環境下的使用。例如我新建一個.net 8的webapi專案,
對ICodeReader介面和CodeReader類進行依賴注入的註冊,建議使用瞬時生命週期,可以提高多個掃碼器同時存在時的併發掃碼效率。
例如:builder.Services.AddTransient<ICodeReader, CodeReader>();
建議新建一個全域性實體類屬性,用於儲存掃碼器的所有客戶端例項,用於保持例項長連線。
例如:
public class ReaderClients
{
public static ReaderClientInfo[] Clients { get; set; }=new ReaderClientInfo[0];
}
掃碼器服務注入和使用.此處為了方便,我直接建立一個api控制器來演示,並對ICodeReader進行了建構函式注入。大佬們請自行根據實際情況進行操作。
假設有一個方法,或者介面等,傳入一批掃碼裝置的配置資訊,例如配置檔案讀取、資料庫讀取、或者其他任意方式配置的掃碼器集合資訊,傳給連線介面或者方法等。然後根據傳入的配置資訊,進行對每個裝置通訊連線:
訪問掃碼函式,進行觸發掃碼操作。以下案例僅供參考,請根據個人實際情況進行最佳化或者修改。例如修改掃碼次數、掃碼成功或失敗的其他處理等等。
控制器內所有程式碼如下:
1 public class ScannerController : ControllerBase
2 {
3 private readonly ICodeReader _reader;
4 public ScannerController(ICodeReader reader)
5 {
6 _reader = reader;
7 }
8
9 [HttpPost]
10 public IActionResult Connection([FromBody] List<ReaderClientInfo> clientInfos)
11 {
12 // 建立一個StringBuilder物件用於儲存返回的結果資訊
13 var result = new StringBuilder();
14 try
15 {
16 if (clientInfos == null || clientInfos.Count == 0)
17 {
18 return Ok("沒有可用客戶連線資訊"); // No available client connection info.
19 }
20
21 // 為全域性靜態陣列分配空間
22 ReaderClients.Clients = new ReaderClientInfo[clientInfos.Count];
23
24 // 用於追蹤失敗的連線,以便儲存到全域性陣列中
25 for (int i = 0; i < clientInfos.Count; i++)
26 {
27 var clientInfo = clientInfos[i];
28 // 嘗試與讀卡器裝置建立連線
29 var res = _reader.ReaderConnection(ref clientInfo);
30 if (res.IsSucceed)
31 {
32 // 連線成功,記錄成功資訊
33 result.AppendLine($"{DateTime.Now:yyyy/MM/dd HH:mm:ss}>>>與掃碼器裝置通訊連線成功:{res.Message}");
34 }
35 else
36 {
37 // 連線失敗,記錄失敗資訊並將客戶端資訊儲存到全域性靜態陣列中
38 ReaderClients.Clients[i] = clientInfo;
39 result.AppendLine($"{DateTime.Now:yyyy/MM/dd HH:mm:ss}>>>通訊連線失敗");
40 }
41 }
42
43 // 返回所有連線結果
44 return Ok(result.ToString());
45 }
46 catch (Exception ex)
47 {
48 // 異常處理,返回異常資訊
49 return Ok($"{DateTime.Now:yyyy/MM/dd HH:mm:ss}>>>通訊連線失敗: {ex.Message}");
50 }
51 }
52
53 [HttpPost]
54 public IActionResult BeginScanner(int count)
55 {
56 const string timeFormat = "yyyy/MM/dd HH:mm:ss";
57 StringBuilder result = new StringBuilder();
58 if (ReaderClients.Clients == null || !ReaderClients.Clients.Any())
59 {
60 return Ok($"{DateTime.Now.ToString(timeFormat)} >>> 沒有可連線的掃碼器客戶端,無法啟動掃描功能。");
61 }
62 try
63 {
64 for (int now = 1; now <= count; now++)
65 {
66 var res = _reader.ReaderRead(ref ReaderClients.Clients[0]); // 假設第一個客戶端已連線。下標0代表第一個掃碼器,請根據實際情況修改。
67 if (res.IsSucceed)
68 {
69 result.AppendLine($"{DateTime.Now.ToString(timeFormat)} >>> 第{now}次掃碼,掃碼結果:{res.Message}");
70 }
71 else
72 {
73 result.AppendLine($"{DateTime.Now.ToString(timeFormat)} >>> 第{now}次掃碼,掃碼失敗:{res.Value} 掃碼耗時:{res.ElapsedMilliseconds}毫秒");
74 }
75 }
76 }
77 catch (Exception ex)
78 {
79 result.AppendLine($"{DateTime.Now.ToString(timeFormat)} >>> 掃碼異常:{ex.Message}");
80 }
81 return Ok(result.ToString());
82 }
83 }
其他介紹:掃碼器配置引數和通用返回值引數對應實體類說明。
掃碼器客戶端配置實體類:
1 /// <summary>
2 /// Represents the client configuration for a scanner.
3 /// 表示掃描器的客戶端配置。
4 /// </summary>
5 public class ReaderClientInfo
6 {
7 /// <summary>
8 /// The IP address of the scanner.
9 /// 掃描器的IP地址。
10 /// </summary>
11 public IPAddress Ip { get; set; }
12
13 /// <summary>
14 /// The port number for the scanner connection.
15 /// 掃描器連線的埠號。
16 /// </summary>
17 public int Port { get; set; }
18
19 /// <summary>
20 /// Number of retry attempts if no code is scanned.
21 /// 如果沒有掃描到碼的重試次數。
22 /// </summary>
23 public short Count { get; set; }
24
25 /// <summary>
26 /// The socket connection to the scanner.
27 /// 掃描器的Socket連線。
28 /// </summary>
29 public Socket Client { get; set; }
30
31 /// <summary>
32 /// The identifier number of the scanner.
33 /// 掃描器的編號。
34 /// </summary>
35 public ushort ReaderNo { get; set; }
36
37 /// <summary>
38 /// Timeout in milliseconds for sending requests.
39 /// 傳送請求的超時時間(毫秒)。
40 /// </summary>
41 public int SendTimeOut { get; set; } = 3000;
42
43 /// <summary>
44 /// Timeout in milliseconds for receiving responses.
45 /// 接收響應的超時時間(毫秒)。
46 /// </summary>
47 public int ReceiveTimeOut { get; set; } = 3000;
48
49 /// <summary>
50 /// The brand of the scanner, such as Keyence, Cognex, OPT, etc.
51 /// 掃描器的品牌,例如基恩士、康耐視、OPT等等。
52 /// </summary>
53 public string Brand { get; set; }
54
55 /// <summary>
56 /// Command to trigger the scan.
57 /// 觸發掃描的命令。
58 /// </summary>
59 public string Command { get; set; }
60
61 /// <summary>
62 /// Command to stop triggering the scanner (used by Keyence).
63 /// 停止觸發掃描器的命令(基恩士使用)。
64 /// </summary>
65 public string CloseCommand { get; set; }
66
67 /// <summary>
68 /// Start character for commands, if applicable (empty string if none).
69 /// 命令的起始字元(如果有),沒有則為空字串。
70 /// </summary>
71 public string Start { get; set; } = string.Empty;
72
73 /// <summary>
74 /// End character for commands, such as '\r\n' for Keyence; empty if not used.
75 /// 命令的結束字元,如基恩士使用的'\r\n';如果不使用則為空字串。
76 /// </summary>
77 public string End { get; set; } = string.Empty;
78 }
返回值實體類:
1 /// <summary>
2 /// Represents the result information from a scanner.
3 /// 表示掃描器的結果資訊。
4 /// </summary>
5 public class ReaderResultInfo
6 {
7 /// <summary>
8 /// Indicates whether the scan was successful.
9 /// 指示掃描是否成功。
10 /// </summary>
11 public bool IsSucceed { get; set; } = false;
12
13 /// <summary>
14 /// The error message if the scan failed.
15 /// 如果掃描失敗,錯誤資訊。
16 /// </summary>
17 public string Message { get; set; } = string.Empty;
18
19 /// <summary>
20 /// The result of the scan.
21 /// 掃描結果。
22 /// </summary>
23 public string Value { get; set; } = string.Empty;
24
25 /// <summary>
26 /// The time taken for the scan in milliseconds.
27 /// 掃描所耗費的時間(毫秒)。
28 /// </summary>
29 public long ElapsedMilliseconds { get; set; } = 0;
30
31 /// <summary>
32 /// The number identifying the scanner.
33 /// 掃描器編號。
34 /// </summary>
35 public ushort ReaderNo { get; set; } = 0;
36
37 /// <summary>
38 /// The brand of the scanner.
39 /// 掃描器品牌。
40 /// </summary>
41 public string Brand { get; set; } = string.Empty;
42 }
如果覺得有幫助,歡迎點贊、分享。
不介意也可關注個人公眾號:Dotnet Dancer
不管你是用.net framework還是用.net core或者更高版本.net環境,這篇文章也許都能幫到你!因為接下來我會提供一個簡單粗暴的方式,來快速實現多款掃碼器的通用掃碼功能。目前本地測試過的包括基恩士系列、康耐視系列、以及其他支援乙太網通訊的多款小眾廠家等。
下面開始重點操作:
首先,在你的專案裡面引用Wesky.Net.OpenTools 包,1.0.7以及以上版本均可。
如果你是在.netframework環境下面開放,或者是沒有使用依賴注入的專案中使用,使用方式可以直接new一個物件來使用,有關使用如下程式碼:
ICodeReader reader = new CodeReader();
ReaderClientInfo clientInfo = new ReaderClientInfo(); // 掃碼器客戶端例項
clientInfo.Ip = IPAddress.Parse("192.168.1.102"); // 掃碼器IP
clientInfo.Port = 3000; // 掃碼器埠號
clientInfo.Count = 3; // 沒掃到碼重試次數
clientInfo.SendTimeOut = 3000; // 請求超時 毫秒
clientInfo.ReceiveTimeOut = 3000; // 接收掃碼內容超時 毫秒
clientInfo.Brand = "SR"; // 掃碼器品牌
clientInfo.Command = "CMD"; // 掃碼器觸發指令,指令可透過各個掃碼器廠家提供的配置軟體,配置為通用的
clientInfo.ReaderNo = 1; // 掃碼器編號,可自定義,例如有10個,就可以配置1-10號
clientInfo.CloseCommand = ""; // 停止觸發指令,如果沒有則預設空字串即可
ReaderResultInfo res = reader.ReaderConnection(ref clientInfo); // 通訊連線,連線掃碼器服務端,引數返回客戶端例項 以及 標準返回值型別ReaderResultInfo
if (!res.IsSucceed)
{
Console.WriteLine($"與掃碼器建立通訊連線失敗:{res.Message}");
return;
}
res = reader.ReaderRead(ref clientInfo); // 傳入掃碼器客戶端例項,進行掃碼。並引數內返回最新的掃碼器客戶端例項
if (!res.IsSucceed)
{
Console.WriteLine($"掃碼異常:{res.Message}");
return;
}
else
{
Console.WriteLine($"掃到碼:{res.Value} 掃碼耗時:{res.ElapsedMilliseconds}");
}
當然,強烈建議你們的專案使用.net core或以上環境。畢竟.net core是開源的,還可以跨平臺,不管你是在Windows執行還是在Linux,都可以執行。
下面是在.net core或以上環境下的使用。例如我新建一個.net 8的webapi專案,
對ICodeReader介面和CodeReader類進行依賴注入的註冊,建議使用瞬時生命週期,可以提高多個掃碼器同時存在時的併發掃碼效率。
例如:builder.Services.AddTransient<ICodeReader, CodeReader>();
建議新建一個全域性實體類屬性,用於儲存掃碼器的所有客戶端例項,用於保持例項長連線。
例如:
public class ReaderClients
{
public static ReaderClientInfo[] Clients { get; set; }=new ReaderClientInfo[0];
}
掃碼器服務注入和使用.此處為了方便,我直接建立一個api控制器來演示,並對ICodeReader進行了建構函式注入。大佬們請自行根據實際情況進行操作。
假設有一個方法,或者介面等,傳入一批掃碼裝置的配置資訊,例如配置檔案讀取、資料庫讀取、或者其他任意方式配置的掃碼器集合資訊,傳給連線介面或者方法等。然後根據傳入的配置資訊,進行對每個裝置通訊連線:
訪問掃碼函式,進行觸發掃碼操作。以下案例僅供參考,請根據個人實際情況進行最佳化或者修改。例如修改掃碼次數、掃碼成功或失敗的其他處理等等。
控制器內所有程式碼如下:
public class ScannerController : ControllerBase
{
private readonly ICodeReader _reader;
public ScannerController(ICodeReader reader)
{
_reader = reader;
}
[ ]
public IActionResult Connection([FromBody] List<ReaderClientInfo> clientInfos)
{
// 建立一個StringBuilder物件用於儲存返回的結果資訊
var result = new StringBuilder();
try
{
if (clientInfos == null || clientInfos.Count == 0)
{
return Ok("沒有可用客戶連線資訊"); // No available client connection info.
}
// 為全域性靜態陣列分配空間
ReaderClients.Clients = new ReaderClientInfo[clientInfos.Count];
// 用於追蹤失敗的連線,以便儲存到全域性陣列中
for (int i = 0; i < clientInfos.Count; i++)
{
var clientInfo = clientInfos[i];
// 嘗試與讀卡器裝置建立連線
var res = _reader.ReaderConnection(ref clientInfo);
if (res.IsSucceed)
{
// 連線成功,記錄成功資訊
result.AppendLine($"{DateTime.Now:yyyy/MM/dd HH:mm:ss}>>>與掃碼器裝置通訊連線成功:{res.Message}");
}
else
{
// 連線失敗,記錄失敗資訊並將客戶端資訊儲存到全域性靜態陣列中
ReaderClients.Clients[i] = clientInfo;
result.AppendLine($"{DateTime.Now:yyyy/MM/dd HH:mm:ss}>>>通訊連線失敗");
}
}
// 返回所有連線結果
return Ok(result.ToString());
}
catch (Exception ex)
{
// 異常處理,返回異常資訊
return Ok($"{DateTime.Now:yyyy/MM/dd HH:mm:ss}>>>通訊連線失敗: {ex.Message}");
}
}
[ ]
public IActionResult BeginScanner(int count)
{
const string timeFormat = "yyyy/MM/dd HH:mm:ss";
StringBuilder result = new StringBuilder();
if (ReaderClients.Clients == null || !ReaderClients.Clients.Any())
{
return Ok($"{DateTime.Now.ToString(timeFormat)} >>> 沒有可連線的掃碼器客戶端,無法啟動掃描功能。");
}
try
{
for (int now = 1; now <= count; now++)
{
var res = _reader.ReaderRead(ref ReaderClients.Clients[0]); // 假設第一個客戶端已連線。下標0代表第一個掃碼器,請根據實際情況修改。
if (res.IsSucceed)
{
result.AppendLine($"{DateTime.Now.ToString(timeFormat)} >>> 第{now}次掃碼,掃碼結果:{res.Message}");
}
else
{
result.AppendLine($"{DateTime.Now.ToString(timeFormat)} >>> 第{now}次掃碼,掃碼失敗:{res.Value} 掃碼耗時:{res.ElapsedMilliseconds}毫秒");
}
}
}
catch (Exception ex)
{
result.AppendLine($"{DateTime.Now.ToString(timeFormat)} >>> 掃碼異常:{ex.Message}");
}
return Ok(result.ToString());
}
}
其他介紹:掃碼器配置引數和通用返回值引數對應實體類說明。
掃碼器客戶端配置實體類:
/// <summary>
/// Represents the client configuration for a scanner.
/// 表示掃描器的客戶端配置。
/// </summary>
public class ReaderClientInfo
{
/// <summary>
/// The IP address of the scanner.
/// 掃描器的IP地址。
/// </summary>
public IPAddress Ip { get; set; }
/// <summary>
/// The port number for the scanner connection.
/// 掃描器連線的埠號。
/// </summary>
public int Port { get; set; }
/// <summary>
/// Number of retry attempts if no code is scanned.
/// 如果沒有掃描到碼的重試次數。
/// </summary>
public short Count { get; set; }
/// <summary>
/// The socket connection to the scanner.
/// 掃描器的Socket連線。
/// </summary>
public Socket Client { get; set; }
/// <summary>
/// The identifier number of the scanner.
/// 掃描器的編號。
/// </summary>
public ushort ReaderNo { get; set; }
/// <summary>
/// Timeout in milliseconds for sending requests.
/// 傳送請求的超時時間(毫秒)。
/// </summary>
public int SendTimeOut { get; set; } = 3000;
/// <summary>
/// Timeout in milliseconds for receiving responses.
/// 接收響應的超時時間(毫秒)。
/// </summary>
public int ReceiveTimeOut { get; set; } = 3000;
/// <summary>
/// The brand of the scanner, such as Keyence, Cognex, OPT, etc.
/// 掃描器的品牌,例如基恩士、康耐視、OPT等等。
/// </summary>
public string Brand { get; set; }
/// <summary>
/// Command to trigger the scan.
/// 觸發掃描的命令。
/// </summary>
public string Command { get; set; }
/// <summary>
/// Command to stop triggering the scanner (used by Keyence).
/// 停止觸發掃描器的命令(基恩士使用)。
/// </summary>
public string CloseCommand { get; set; }
/// <summary>
/// Start character for commands, if applicable (empty string if none).
/// 命令的起始字元(如果有),沒有則為空字串。
/// </summary>
public string Start { get; set; } = string.Empty;
/// <summary>
/// End character for commands, such as '\r\n' for Keyence; empty if not used.
/// 命令的結束字元,如基恩士使用的'\r\n';如果不使用則為空字串。
/// </summary>
public string End { get; set; } = string.Empty;
}
返回值實體類:
/// <summary>
/// Represents the result information from a scanner.
/// 表示掃描器的結果資訊。
/// </summary>
public class ReaderResultInfo
{
/// <summary>
/// Indicates whether the scan was successful.
/// 指示掃描是否成功。
/// </summary>
public bool IsSucceed { get; set; } = false;
/// <summary>
/// The error message if the scan failed.
/// 如果掃描失敗,錯誤資訊。
/// </summary>
public string Message { get; set; } = string.Empty;
/// <summary>
/// The result of the scan.
/// 掃描結果。
/// </summary>
public string Value { get; set; } = string.Empty;
/// <summary>
/// The time taken for the scan in milliseconds.
/// 掃描所耗費的時間(毫秒)。
/// </summary>
public long ElapsedMilliseconds { get; set; } = 0;
/// <summary>
/// The number identifying the scanner.
/// 掃描器編號。
/// </summary>
public ushort ReaderNo { get; set; } = 0;
/// <summary>
/// The brand of the scanner.
/// 掃描器品牌。
/// </summary>
public string Brand { get; set; } = string.Empty;
}
如果覺得有幫助,歡迎點贊、分享。
不介意也可關注個人公眾號:Dotnet Dancer