工業福利!用.NET快速開發物聯網掃碼器裝置的通用掃碼功能

WeskyNet發表於2024-05-17

不管你是用.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以及以上版本均可。

工業福利!用.NET快速開發物聯網掃碼器裝置的通用掃碼功能

如果你是在.netframework環境下面開放,或者是沒有使用依賴注入的專案中使用,使用方式可以直接new一個物件來使用,有關使用如下程式碼:

ICodeReader reader = new CodeReader();ReaderClientInfo clientInfo = new ReaderClientInfo(); // 掃碼器客戶端例項clientInfo.Ip = IPAddress.Parse("192.168.1.102"); // 掃碼器IPclientInfo.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); // 通訊連線,連線掃碼器服務端,引數返回客戶端例項 以及 標準返回值型別ReaderResultInfoif (!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>();

工業福利!用.NET快速開發物聯網掃碼器裝置的通用掃碼功能

建議新建一個全域性實體類屬性,用於儲存掃碼器的所有客戶端例項,用於保持例項長連線。

例如:

public class ReaderClients{    public static ReaderClientInfo[] Clients { get; set; }=new ReaderClientInfo[0];}

工業福利!用.NET快速開發物聯網掃碼器裝置的通用掃碼功能

掃碼器服務注入和使用.此處為了方便,我直接建立一個api控制器來演示,並對ICodeReader進行了建構函式注入。大佬們請自行根據實際情況進行操作。

工業福利!用.NET快速開發物聯網掃碼器裝置的通用掃碼功能

假設有一個方法,或者介面等,傳入一批掃碼裝置的配置資訊,例如配置檔案讀取、資料庫讀取、或者其他任意方式配置的掃碼器集合資訊,傳給連線介面或者方法等。然後根據傳入的配置資訊,進行對每個裝置通訊連線:

工業福利!用.NET快速開發物聯網掃碼器裝置的通用掃碼功能

訪問掃碼函式,進行觸發掃碼操作。以下案例僅供參考,請根據個人實際情況進行最佳化或者修改。例如修改掃碼次數、掃碼成功或失敗的其他處理等等。

工業福利!用.NET快速開發物聯網掃碼器裝置的通用掃碼功能

控制器內所有程式碼如下:

 public class ScannerController : ControllerBase {     private readonly ICodeReader _reader;     public ScannerController(ICodeReader reader)     {         _reader = reader;     }     [HttpPost]     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}");         }     }     [HttpPost]     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

工業福利!用.NET快速開發物聯網掃碼器裝置的通用掃碼功能

相關文章