<add>[important]添加部分电子标签代码

This commit is contained in:
葛林强 2024-05-28 16:53:50 +08:00
parent f1da7a4d28
commit 7023e6cefd
23 changed files with 573 additions and 38 deletions

View File

@ -131,8 +131,6 @@ public class SocketClient
reConnectSocket.Start();
//Task.Factory.StartNew(ReConnectSocket);
}
/// <summary>
/// 连接 socket
/// </summary>
@ -163,15 +161,11 @@ public class SocketClient
try
{
int bytes = socket.Receive(recvBytes, recvBytes.Length, SocketFlags.None);
if (bytes <= 0)
{
continue;
}
if (bytes <= 0) continue;
GetTcpData?.BeginInvoke(recvBytes, socketInfo.SocketIp ?? "", null, null);
if (GetTcpData != null) continue;
string? recvStr = Encod?.GetString(recvBytes, 0, bytes); //此处编码方式请根据服务端发送的编码方式修改对应,否则可能造成部分字符乱码
if (string.IsNullOrEmpty(recvStr))
{
continue;
}
if (string.IsNullOrEmpty(recvStr)) continue;
if (recvStr.Trim().Length > 0)
{
GetSocketMessage?.Invoke(recvStr, socketInfo.SocketIp ?? "");
@ -325,6 +319,13 @@ public class SocketClient
public event GetMessage? GetSocketMessage;
public delegate void GetData(byte[] data, string IPAddress);
/// <summary>
/// 字节返回事件
/// </summary>
public event GetData? GetTcpData;
public delegate void OffLine(string IPAddress);
/// <summary>
/// 当有地址掉线时触发

View File

@ -0,0 +1,20 @@
using System.Text.Json.Serialization;
namespace WcsMain.ApiServe.Controllers.Dto.WcsDto.ElTag;
public class ShowNumRequest
{
/// <summary>
/// 标签名称
/// </summary>
[JsonPropertyName("tagName")]
public int? TagName { get; set; }
/// <summary>
/// 标签显示的数字
/// </summary>
[JsonPropertyName("value")]
public int? Num { get; set; }
}

View File

@ -0,0 +1,36 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using WcsMain.ApiServe.ControllerFilter.ExceptionFilter;
using WcsMain.ApiServe.Controllers.Dto;
using WcsMain.ApiServe.Controllers.Dto.WcsDto.ElTag;
using WcsMain.ApiServe.Service.WcsService;
namespace WcsMain.ApiServe.Controllers.WcsController;
/// <summary>
/// 电子标签控制器的控制类
/// </summary>
[Route("api/wcs/elTag")]
[ApiController]
[WcsExceptionFilter]
public class ElTagController(ElTagService elTagService) : ControllerBase
{
private readonly ElTagService _elTagService = elTagService;
/// <summary>
/// 向标签发送显示数字
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
[HttpPost("showNum")]
public WcsApiResponse ShowNum([FromBody] ShowNumRequest request)
{
return _elTagService.ShowNum(request);
}
}

View File

@ -0,0 +1,20 @@
using WcsMain.ApiServe.Controllers.Dto;
using WcsMain.ApiServe.Controllers.Dto.WcsDto.ElTag;
using WcsMain.ApiServe.Factory;
using WcsMain.WcsAttribute.AutoFacAttribute;
namespace WcsMain.ApiServe.Service.WcsService;
[Service]
public class ElTagService
{
/// <summary>
/// 展示电子标签的数字
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public WcsApiResponse ShowNum(ShowNumRequest request)
{
return WcsApiResponseFactory.Fail();
}
}

View File

@ -83,6 +83,16 @@ public class AppConfigEntity
[ConfigKey("UseSocket")]
public string? UseSocket { get; set; }
/// <summary>
/// 表示是否开启 Opr 连接 电子标签
/// </summary>
/// <remarks>
/// 0 - 关闭
/// 1 - 开启
/// </remarks>
[ConfigKey("UseOpr")]
public string? UseOpr { get; set; }
/// <summary>
/// 表示过账确认的方法

View File

@ -3,6 +3,7 @@ using PlcTool.Siemens;
using SqlSugar;
using System.Diagnostics.CodeAnalysis;
using WcsMain.Business.CommonAction;
using WcsMain.ElTag.Atop;
using WcsMain.Tcp.Client;
namespace WcsMain.Common;
@ -46,6 +47,19 @@ public class CommonTool
#endregion
#region TCP
/// <summary>
/// 电子标签的 TCP 连接
/// </summary>
[NotNull]
public static OprTcpClient? OprTcpClient { get; set; }
#endregion
#region WMS
// 请查看 Plugins 文件夹 WmsWebApiPost

View File

@ -0,0 +1,58 @@
using SqlSugar;
namespace WcsMain.DataBase.TableEntity;
[SugarTable("tbl_app_eltag_base")]
public class AppElTagBase
{
/// <summary>
/// 点位
/// </summary>
[SugarColumn(ColumnName = "location", IsPrimaryKey = true)]
public string? Location { get; set; }
/// <summary>
/// 标签的名称
/// </summary>
[SugarColumn(ColumnName = "tag_name")]
public string? TagName { get; set; }
/// <summary>
/// 标签的ID
/// </summary>
[SugarColumn(ColumnName = "tag_id")]
public int? TagId { get; set; }
/// <summary>
/// 标签类型
/// </summary>
[SugarColumn(ColumnName = "tag_type")]
public int? TagType { get; set; }
/// <summary>
/// 控制器的别称
/// </summary>
[SugarColumn(ColumnName = "controller_diaplay_name")]
public string? ControllerDisplayName { get; set;}
/// <summary>
/// 所属区域
/// </summary>
[SugarColumn(ColumnName = "area")]
public string? Area { get; set; }
/// <summary>
/// LED灯的默认状态
/// </summary>
[SugarColumn(ColumnName = "led_status")]
public int? LedStatus { get; set; }
/// <summary>
/// 备注
/// </summary>
[SugarColumn(ColumnName = "remark")]
public string? Remark { get; set; }
}

View File

@ -0,0 +1,14 @@
namespace WcsMain.ElTag.Atop.AtopEnum;
/// <summary>
/// 蜂鸣器类型
/// </summary>
public enum BuzzerType
{
OFF = 0,
ON = 1,
_2sec = 2,
_1sec = 3,
_0_5_sec = 4,
_0_25_sec = 5
}

View File

@ -0,0 +1,14 @@
namespace WcsMain.ElTag.Atop.AtopEnum;
/// <summary>
/// 电子标签灯的颜色
/// </summary>
public enum LedColor
{
Red = 0,
Green = 1,
Orange = 2,
Blue = 3,
Pink = 4,
Cyan = 5,
}

View File

@ -0,0 +1,14 @@
namespace WcsMain.ElTag.Atop.AtopEnum;
/// <summary>
/// 灯的状态
/// </summary>
public enum LedStatus
{
LEDOff = 0,
LEDOn = 1,
_2secblinking = 2,
_1secblinking = 3,
_0_5secblinking = 4,
_0_25secblinking = 5
}

View File

@ -0,0 +1,11 @@
namespace WcsMain.ElTag.Atop.AtopEnum;
/// <summary>
/// 标签按钮
/// </summary>
public enum TagButtons
{
ConfirmKey = 1,
ShortageKey = 2,
AllKey = 3
}

View File

@ -0,0 +1,10 @@
namespace WcsMain.ElTag.Atop.AtopEnum;
/// <summary>
/// 标签的模式
/// </summary>
public enum TagMode
{
Picking = 0,
Stock = 1
}

View File

@ -0,0 +1,18 @@
using WcsMain.Common;
using WcsMain.Tcp.Client;
using WcsMain.Tcp.Entity;
using WcsMain.WcsAttribute.AutoFacAttribute;
using static SocketTool.SocketClient;
namespace WcsMain.ElTag.Atop;
/// <summary>
/// 电子标签收到数据的数据处理类
/// </summary>
[Component]
public class BaseOprDataHandler
{
}

View File

@ -0,0 +1,74 @@
using WcsMain.Common;
using WcsMain.DataBase.Dao;
using WcsMain.DataBase.TableEntity;
using WcsMain.Enum.General;
using WcsMain.Enum.Tcp;
using WcsMain.Tcp.Entity;
using WcsMain.WcsAttribute.AutoFacAttribute;
namespace WcsMain.ElTag.Atop;
/// <summary>
/// 连接并接收电子标签信息
/// </summary>
/// <param name="baseOprDataHandler"></param>
[Component]
public class ConnectOprServe(AppTcpDao tcpDao, BaseOprDataHandler baseOprDataHandler)
{
private readonly AppTcpDao _tcpDao = tcpDao;
private readonly BaseOprDataHandler _baseOprDataHandler = baseOprDataHandler;
/// <summary>
/// 设置基本参数
/// </summary>
public void SetBaseAction()
{
CommonTool.OprTcpClient = new OprTcpClient();
CommonTool.OprTcpClient.SetConnecting((tcpData) => ConsoleLog.Info($"电子标签:{tcpData} 正在连接"));
CommonTool.OprTcpClient.SetConnectFailAction((tcpData, ex) => ConsoleLog.Warning($"电子标签:{tcpData} 连接失败,参考信息:{ex.Message}"));
CommonTool.OprTcpClient.SetConnectSuccess((tcpData) => ConsoleLog.Success($"电子标签:{tcpData} 连接成功"));
CommonTool.OprTcpClient.SetConnectOffline((tcpData) => ConsoleLog.Warning($"电子标签:{tcpData} 失去连接"));
CommonTool.OprTcpClient.SetGetData(GetData);
}
/// <summary>
/// 连接电子标签
/// </summary>
public void Connect()
{
Task.Factory.StartNew(() =>
{
List<AppTcp>? tcps = default;
while (true)
{
tcps = _tcpDao.Query(new AppTcp { TcpStatus = (int)TrueFalseEnum.TRUE, TcpType = (int)TcpType.Opr });
if (tcps != default) break;
Thread.Sleep(5000);
continue;
}
if (tcps.Count == 0) return;
CommonTool.OprTcpClient.SetBaseTcpServe(tcps);
CommonTool.OprTcpClient.Connect();
}, TaskCreationOptions.LongRunning);
}
/// <summary>
/// 收到数据处理方法
/// </summary>
/// <param name="tcpServe"></param>
/// <param name="datas"></param>
public void GetData(TcpServeConnectionData tcpServe, byte[] datas)
{
}
}

View File

@ -0,0 +1,51 @@
namespace WcsMain.ElTag.Atop.Entity;
public class TagReturnInfo
{
/// <summary>
/// 按下的按键类型
/// </summary>
/// <remarks>
/// Data(1)= 16H “confirmatin key “ pressed
/// 43H “shotage button/down-count button” pressed
/// 25H “function button/up-count button” pressed.
/// </remarks>
public int KeyType { get; set; }
/// <summary>
/// 消息类型
/// </summary>
/// <remarks>
/// 01H:Tag busy,04H 功能键
/// </remarks>
public int MsgType { get; set; }
/// <summary>
/// 提交信息
/// </summary>
/// <remarks>
/// 13卡键
/// 10通讯超时
/// </remarks>
public int SubCommand { get; set; }
/// <summary>
/// IP 地址
/// </summary>
public string? Ip { get; set; }
public int Abbr { get; set; }
/// <summary>
/// 传回消息的端口 ---- 注意不是控制器端口
/// </summary>
public int Port { get; set; }
/// <summary>
/// 返回的数据
/// </summary>
public string? Data { get; set; }
}

View File

@ -0,0 +1,98 @@
using System.Drawing;
using WcsMain.ElTag.Atop.AtopEnum;
namespace WcsMain.ElTag.Atop.Entity;
/// <summary>
/// 发送到电子标签的信息
/// </summary>
public class TagSendInfo
{
/// <summary>
/// 展示标签的ID
/// </summary>
/// <param name="tagId"></param>
/// <returns></returns>
public static byte[] ShowTagId(byte tagId)
{
byte[] data = new byte[8];
data[0] = 8;
data[1] = 0;
data[2] = 0x60;
data[6] = 0x13;
data[7] = tagId;
return data;
}
/// <summary>
/// 标签重启
/// </summary>
/// <param name="tagId"></param>
/// <returns></returns>
public static byte[] RestartTag(byte tagId)
{
byte[] data = new byte[8];
data[0] = 8;
data[1] = 0;
data[2] = 0x60;
data[6] = 0x14;
data[7] = tagId;
return data;
}
/// <summary>
/// 关闭标签
/// </summary>
/// <param name="tagId"></param>
/// <returns></returns>
public static byte[] TurnOffTag(byte tagId)
{
byte[] data = new byte[8];
data[0] = 8;
data[1] = 0;
data[2] = 0x60;
data[6] = 1;
data[7] = tagId;
return data;
}
/// <summary>
/// 返回一个设置标签按钮灯颜色的报文
/// </summary>
/// <param name="tagId">标签的ID</param>
/// <param name="ledColor">颜色枚举值</param>
/// <returns></returns>
public static byte[] LedColor(byte tagId, LedColor ledColor = AtopEnum.LedColor.Green)
{
byte[] data = new byte[10];
data[0] = 0x0A;
data[1] = 0;
data[2] = 0x60;
data[6] = 0x1F;
data[7] = tagId;
data[8] = 0;
data[9] = (byte)ledColor;
return data;
}
/// <summary>
/// 返回一个设置按钮灯闪烁频率的报文
/// </summary>
/// <param name="tagId">标签的编号</param>
/// <param name="ledStatus">闪烁频率</param>
/// <returns></returns>
public static byte[] LedStatus(byte tagId, LedStatus ledStatus = AtopEnum.LedStatus._0_5secblinking)
{
byte[] data = new byte[10];
data[0] = 0x0A;
data[1] = 0;
data[2] = 0x60;
data[6] = 0x1F;
data[7] = tagId;
data[8] = 4;
data[9] = (byte)ledStatus;
return data;
}
}

View File

@ -0,0 +1,27 @@
using SocketTool;
using System.Text;
using WcsMain.ElTag.Atop.Entity;
using WcsMain.Tcp.Client;
using WcsMain.WcsAttribute.AutoFacAttribute;
namespace WcsMain.ElTag.Atop;
/// <summary>
/// 电子标签主控制类
/// </summary>
public class OprTcpClient : BaseTcpClient
{
/// <summary>
/// 连接电子标签客户端
/// </summary>
public void Send()
{
}
}

View File

@ -5,8 +5,8 @@
/// </summary>
public enum TcpType
{
PLC = 0,
SCAN = 1,
PLC = 0, // PLC
SCAN = 1, // 扫码器
Opr = 2, // 电子标签
}

View File

@ -9,6 +9,7 @@ using WcsMain.DataBase.Dao;
using WcsMain.DataBase.TableEntity;
using WcsMain.WcsAttribute.AppConfig;
using WcsMain.Business.Convey;
using WcsMain.ElTag.Atop;
namespace WcsMain.StartAction;
@ -17,7 +18,8 @@ namespace WcsMain.StartAction;
/// </summary>
[Component]
public class ServiceStart(WcsCirculation wcsCirculation, ConnectPLCs connectPLCs, SocketOperation socketOperation,
AppStackerDao appStackerDao, AppLocationDao appLocationDao, AppConfigDao appConfigDao, ConnectPlcServe connectPlcServe)
AppStackerDao appStackerDao, AppLocationDao appLocationDao, AppConfigDao appConfigDao, ConnectPlcServe connectPlcServe,
ConnectOprServe connectOprServe)
{
private readonly AppConfigDao _appconfigDao = appConfigDao;
private readonly AppLocationDao _applocationDao = appLocationDao;
@ -26,6 +28,7 @@ public class ServiceStart(WcsCirculation wcsCirculation, ConnectPLCs connectPLCs
private readonly ConnectPLCs _connectPlcs = connectPLCs;
private readonly WcsCirculation _wcsCirculation = wcsCirculation;
private readonly ConnectPlcServe _connectPlcServe = connectPlcServe;
private readonly ConnectOprServe _connectOprServe = connectOprServe;
private static string _errMsg = string.Empty;
@ -52,10 +55,10 @@ public class ServiceStart(WcsCirculation wcsCirculation, ConnectPLCs connectPLCs
{
/* 指定线程池规格 */
ThreadPool.SetMinThreads(30, 10);
CreatePlcClient(); // 连接 PLC 客户端
CreateSocketClient(); // Socket客户端
ConnectOprServe(); // 连接 Opr 电子标签客户端
CreateCieculateTask();// 创建并启用定时器
}
@ -71,7 +74,7 @@ public class ServiceStart(WcsCirculation wcsCirculation, ConnectPLCs connectPLCs
}
/// <summary>
/// 创建并运行 Socket 客户端
/// 创建并运行 Socket 客户端 ---- 待更新
/// </summary>
public void CreateSocketClient()
{
@ -81,6 +84,19 @@ public class ServiceStart(WcsCirculation wcsCirculation, ConnectPLCs connectPLCs
}
}
/// <summary>
/// 连接Opr电子标签客户端
/// </summary>
public void ConnectOprServe()
{
if (CommonData.AppConfig.UseOpr == "1") // 1 表示允许连接电子标签
{
_connectOprServe.SetBaseAction();
_connectOprServe.Connect();
}
}
public void CreateTcpClient()
{
@ -179,6 +195,4 @@ public class ServiceStart(WcsCirculation wcsCirculation, ConnectPLCs connectPLCs
CommonData.AppLocations = appLocations;
}
}

View File

@ -9,7 +9,6 @@ namespace WcsMain.Tcp.Client;
/// <summary>
/// Wcs 的Tcp 客户端
/// </summary>
[Component]
public class BaseTcpClient
{
/// <summary>
@ -37,12 +36,18 @@ public class BaseTcpClient
/// </summary>
private Action<TcpServeConnectionData, string>? _getMessage;
/// <summary>
/// 获取数据事件
/// </summary>
private Action<TcpServeConnectionData, byte[]>? _getData;
public void SetConnecting(Action<TcpServeConnectionData> action) => _connecting = action;
public void SetConnectFailAction(Action<TcpServeConnectionData, Exception> action) => _connectFail = action;
public void SetConnectSuccess(Action<TcpServeConnectionData> action) => _connectSuccess = action;
public void SetConnectOffline(Action<TcpServeConnectionData> action) => _connectOffline = action;
public void GetMessage(Action<TcpServeConnectionData, string> action) => _getMessage = action;
public void SetGetData(Action<TcpServeConnectionData, byte[]> action) => _getData = action;
/// <summary>
/// 当前需要连接的服务端数量
@ -104,6 +109,7 @@ public class BaseTcpClient
if (readLength > 0)
{
serveData.RecvMsgTime = DateTime.Now;
_getData?.BeginInvoke(serveData, bytes, null, null);
_getMessage?.BeginInvoke(serveData, Encoding.ASCII.GetString(bytes), null, null);
continue;
}
@ -185,6 +191,45 @@ public class BaseTcpClient
}
}
/// <summary>
/// 向指定别称的客户端发送消息
/// </summary>
/// <param name="value"></param>
/// <param name="displayNames"></param>
/// <returns></returns>
public TcpClientSendResult Send(byte[] value, params string[] displayNames)
{
TcpClientSendResult tcpClientSendResult = new() { Success = true };
// 指定发送
List<Task> sendTasks = [];
foreach (var tcpServe in tcpServeConnectionDatas)
{
if (displayNames.Length > 0 && !displayNames.Contains(tcpServe.DisplayName)) { continue; }
if (tcpServe.TcpClient == default || tcpServe.IsConnected != Enum.General.TrueFalseEnum.TRUE)
{
tcpClientSendResult = new() { Success = false, Exception = new Exception($"别称:{tcpServe.DisplayName} 的Tcp连接不可用") };
}
else
{
sendTasks.Add(Task.Factory.StartNew(() =>
{
var sendNetworkStream = tcpServe.TcpClient.GetStream();
try
{
sendNetworkStream.Write(value);
}
catch (Exception ex)
{
tcpClientSendResult = new() { Success = false, Exception = ex };
}
}));
}
}
if (sendTasks.Count == 0) return new() { Success = false, Exception = new Exception("没有要发送的客户端") };
Task.WaitAll([.. sendTasks]);
return tcpClientSendResult;
}
/// <summary>
/// 向指定别称的客户端发送消息
/// </summary>

View File

@ -9,8 +9,7 @@ namespace WcsMain.Tcp.Client;
/// <summary>
/// 专用与连接 PLC 的Tcp客户端
/// </summary>
[Component]
public partial class PlcTcpClient : BaseTcpClient
public class PlcTcpClient : BaseTcpClient
{
/// <summary>
@ -86,7 +85,7 @@ public partial class PlcTcpClient : BaseTcpClient
public MsgHeader? GetMsgHeader(string? value)
{
if (string.IsNullOrEmpty(value)) return default;
if (!RegexMsgFormat().IsMatch(value)) return default;
if (!Regex.IsMatch(value, "^<.+\\>$")) return default;
string[] msgDatas = value.Split(';');
if(msgDatas.Length < 4 ) return default;
var msgHeader = new MsgHeader()
@ -99,19 +98,4 @@ public partial class PlcTcpClient : BaseTcpClient
return msgHeader;
}
[GeneratedRegex("^<.+\\>$")]
private static partial Regex RegexMsgFormat();
}

View File

@ -2,5 +2,7 @@
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<NameOfLastUsedPublishProfile>FolderProfile</NameOfLastUsedPublishProfile>
<Controller_SelectedScaffolderID>ApiControllerEmptyScaffolder</Controller_SelectedScaffolderID>
<Controller_SelectedScaffolderCategoryPath>root/Common/Api</Controller_SelectedScaffolderCategoryPath>
</PropertyGroup>
</Project>

View File

@ -14,7 +14,7 @@
"DBMssqlLocal": "Data Source=192.168.142.131;Initial Catalog=wcs_stacker;User Id=sa;Password=Sa123;",
"ApplicationConfig": {
"ApiOnly": true,
"ApiOnly": false,
"Language": "zh-CN"
},
"UseUrls": [ "http://*:890" ]