工业福利!用.NET快速开发物联网扫码器设备的通用扫码功能
本文主要讲解关于工业福利!用.NET快速开发物联网扫码器设备的通用扫码功能相关内容,让我们来一起学习下吧!
不管你是用.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 'rn' for Keyence; empty if not used. 75 /// 命令的结束字符,如基恩士使用的'rn';如果不使用则为空字符串。 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;
}
[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 'rn' for Keyence; empty if not used.
/// 命令的结束字符,如基恩士使用的'rn';如果不使用则为空字符串。
/// </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快速开发物联网扫码器设备的通用扫码功能相关的全部内容,希望对你有帮助。欢迎持续关注程序员导航网,学习愉快哦!