添加项目文件。

This commit is contained in:
Administrator 2025-11-04 11:15:44 +08:00
parent 9561817cc2
commit 6b83962ae1
16 changed files with 756 additions and 0 deletions

View File

@ -0,0 +1,5 @@
{
"version": 1,
"isRoot": true,
"tools": {}
}

View File

@ -0,0 +1,71 @@
using LolaiService.Devices.Tunnel;
using LolaiService.Global;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace LolaiService.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class TunnelApiController : ControllerBase
{
/// <summary>
/// 隧道机关门
/// </summary>
/// <returns></returns>
[HttpPost("TunnelClose")]
public string TunnelCloseApi()
{
string result = GlobalDeviceInfo.CloseDoorTunnel();
if (result.Equals("已关门"))
{
return "关门成功";
}
else
{
return "关门失败";
}
}
/// <summary>
/// 隧道机开门
/// </summary>
/// <returns></returns>
[HttpPost("TunnelOpen")]
public string TunnelOpenDoorApi()
{
string result = GlobalDeviceInfo.OpenDoorTunnel();
if (result.Equals("已开门"))
{
return "开门成功";
}
else
{
return "开门失败";
}
}
[HttpGet("today")]
public IActionResult GetTodayWeather()
{
var data = new { Temp = 22, Condition = "Sunny" };
return Ok(data);
}
// GET api/weather/week
[HttpGet("week")]
public IActionResult GetWeekForecast()
{
var data = new[]
{
new { Day = "Mon", Temp = 21, Condition = "Cloudy" },
new { Day = "Tue", Temp = 23, Condition = "Sunny" },
new { Day = "Wed", Temp = 19, Condition = "Rain" },
};
return Ok(data);
}
}
}

View File

@ -0,0 +1,63 @@
using Rovinj.Device;
using Rovinj.Reader.Silion;
using Rovinj.Tunnel;
namespace LolaiService.Devices.Tunnel
{
/// <summary>
/// 隧道机接口
/// </summary>
public interface IRfidTunnel
{
/// <summary>
/// 连接通道机
/// </summary>
bool ConnectTunnel(SilionReaderConfig readerConfig, ConnectionConfig plcConnectionConfig, TunnelConfig tunnelConfig);
/// <summary>
/// 关闭通道机
/// </summary>
/// <returns></returns>
void CloseTunnel();
/// <summary>
/// 标签报告事件
/// </summary>
/// <param name="tunnel"></param>
/// <param name="e"></param>
void Tunnel_TagsReported(ITunnel tunnel, TunnelTagsReportedEventArgs e);
/// <summary>
/// 通道机读写器状态变化事件
/// </summary>
/// <param name="tunnel"></param>
/// <param name="e"></param>
void Tunnel_ReaderStateChanged(ITunnel tunnel, TunnelReaderStateChangedEventArgs e);
/// <summary>
/// 通道机PLC状态变化事件
/// </summary>
/// <param name="tunnel"></param>
/// <param name="e"></param>
void Tunnel_PlcStateChanged(ITunnel tunnel, TunnelPlcStateChangedEventArgs e);
/// <summary>
/// 通道机错误事件
/// </summary>
/// <param name="tunnel"></param>
/// <param name="e"></param>
void Tunnel_ErrorReceived(ITunnel tunnel, TunnelErrorReceivedEventArgs e);
/// <summary>
/// 隧道关门
/// </summary>
/// <returns></returns>
string CloseDoor();
/// <summary>
/// 隧道开门
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
string OpenDoor();
}
}

View File

@ -0,0 +1,285 @@
using LolaiService.Global;
using Rovinj.Device;
using Rovinj.Log;
using Rovinj.Reader;
using Rovinj.Reader.Silion;
using Rovinj.Tunnel;
using Rovinj.Tunnel.Plc;
namespace LolaiService.Devices.Tunnel
{
/// <summary>
/// 隧道机实现类
/// </summary>
public class RfidTunnel : IRfidTunnel
{
/// <summary>
/// 是否开始校验数量
/// </summary>
private volatile bool isStartCheckTags;
/// <summary>
/// 扫描ID的标签
/// </summary>
private string tagsScanId;
/// <summary>
/// 标签ID列表可以是EPC或TID
/// </summary>
private List<string> tagIdList = new List<string>();
/// <summary>
/// 当前PLC的状态
/// </summary>
private PlcStatus currentPlcStatus;
/// <summary>
/// 隧道是否已连接
/// </summary>
//private bool isTunnelConnected;
/// <summary>
///通道机接口
/// </summary>
//private ITunnel tunnel;
/// <summary>
/// 线程退出标识
/// </summary>
private CancellationTokenSource cancellationTokenSource;
/// <summary>
/// 检查标签线程
/// </summary>
private Thread checkTagsThread;
/// <summary>
/// Silion读写器支持R2000/E310/E710芯片支持1、2、3、4、8、16口天线
/// </summary>
private SilionReader silionReader;
/// <summary>
/// 通道机读写器状态变化事件
/// </summary>
/// <param name="tunnel"></param>
/// <param name="e"></param>
public void Tunnel_ReaderStateChanged(ITunnel tunnel, TunnelReaderStateChangedEventArgs e)
{
LogHelper.Error("e.RunningState:" + e.RunningState);
if (e.RunningState == 0)
{
//停止业务
LogHelper.Info("停止业务");
}
else if (e.RunningState == 1)
{
//启动业务
tagsScanId = e.ScanId;
LogHelper.Info("启动业务");
}
else
{
LogHelper.Info("其他状态");
//其他状态
}
}
/// <summary>
/// 标签报告事件
/// </summary>
/// <param name="tunnel"></param>
/// <param name="e"></param>
public void Tunnel_TagsReported(ITunnel tunnel, TunnelTagsReportedEventArgs e)
{
LogHelper.Error("e.Tags.Count:" + e.Tags.Count);
for (int i = 0; i < e.Tags.Count; i++)
{
Tag tag = e.Tags[i];
//过滤掉不符合扫描ID的标签
if (tag.ScanId != tagsScanId)
continue;
//如果配置为"TID"且TID不为空则使用TID否则使用EPC。检查标签ID是否已存在于 tagIdList 中,避免重复添加。
if (tunnel.TunnelConfig.TagIdFieldName == "TID" && !string.IsNullOrEmpty(tag.TID))
{
if (tagIdList.Contains(tag.TID))
continue;
tagIdList.Add(tag.TID);
LogHelper.Info("tag.TID" + tag.TID);
}
else
{
if (tagIdList.Contains(tag.EPC))
continue;
tagIdList.Add(tag.EPC);
LogHelper.Info("tag.TID" + tag.TID);
}
}
}
/// <summary>
/// 通道机PLC状态变化事件
/// </summary>
/// <param name="tunnel"></param>
/// <param name="e"></param>
public void Tunnel_PlcStateChanged(ITunnel tunnel, TunnelPlcStateChangedEventArgs e)
{
currentPlcStatus = e.PlcStatus;//记录当前PLC状态
LogHelper.Info("通道机PLC状态变化事件" + e.PlcStatus);
}
/// <summary>
/// 通道机错误接收事件
/// </summary>
/// <param name="tunnel"></param>
/// <param name="e"></param>
/// <exception cref="NotImplementedException"></exception>
public void Tunnel_ErrorReceived(ITunnel tunnel, TunnelErrorReceivedEventArgs e)
{
// 在控制台输出错误信息,包括错误消息和异常详情
Console.WriteLine($"错误信息:{e.ErrorMessage},异常:{e.Exception}");
LogHelper.Error("通道机错误接收事件:" + $"错误信息:{e.ErrorMessage},异常:{e.Exception}");
}
/// <summary>
/// 关闭通道机连接
/// </summary>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public void CloseTunnel()
{
if (GlobalData.tunnel == null)
return;
if (GlobalData.tunnel.Reader.IsStarted)
{
GlobalData.tunnel.StopReader();
}
StopTunnel();
GlobalData.tunnel.Close();
GlobalData.tunnel = null;
GlobalData.isTunnelConnected = false;
}
/// <summary>
/// 停止隧道
/// </summary>
private void StopTunnel()
{
if (GlobalData.tunnel.IsStarted)
GlobalData.tunnel.Stop();
isStartCheckTags = false;
if (cancellationTokenSource != null)
cancellationTokenSource.Cancel();
if (checkTagsThread != null)
checkTagsThread.Join();
}
/// <summary>
/// 连接隧道
/// </summary>
/// <param name="readerConfig">配置RFID读写器参数</param>
/// <param name="plcConnectionConfig">配置PLC连接方式</param>
/// <param name="tunnelConfig">配置读写器连接方式</param>
public bool ConnectTunnel(SilionReaderConfig readerConfig, ConnectionConfig plcConnectionConfig, TunnelConfig tunnelConfig)
{
if (!GlobalData.isTunnelConnected)
{
//创建并打开隧道
GlobalData.tunnel = TunnelFactory.CreateTunnel(TunnelType.SC201, tunnelConfig);//根据实际的设备选择对应的类型这里假设是SC201
GlobalData.tunnel.TagsReported += Tunnel_TagsReported; //读到标签时触发;
GlobalData.tunnel.ReaderStateChanged += Tunnel_ReaderStateChanged; //读写器状态变化
GlobalData.tunnel.PlcStateChanged += Tunnel_PlcStateChanged; //PLC 状态变化
GlobalData.tunnel.ErrorReceived += Tunnel_ErrorReceived; //收到错误时触发
if (GlobalData.tunnel.Open())
{
LogHelper.Info("连接成功");
GlobalData.isTunnelConnected = true;
//获取读写器能力(支持的发射功率列表)
silionReader = GlobalData.tunnel.Reader as SilionReader;
if (silionReader.ReaderCapability != null)
{
//发射率列表
List<double> doubles = new List<double>();
for (int i = 0; i < silionReader.ReaderCapability.TxPowers.Count; i++)
{
doubles.Add(silionReader.ReaderCapability.TxPowers[i]);
LogHelper.Info("发射率列表:" + silionReader.ReaderCapability.TxPowers[i]);
}
}
if (GlobalData.tunnel.Initialize())//复位
{
LogHelper.Info("复位成功");
//语音提示
//SoundPlayer player = new SoundPlayer();
//player.Play();
}
return true;
}
else
{
LogHelper.Error("连接失败");
GlobalData.tunnel.Close();
GlobalData.isTunnelConnected = false;
return false;
}
}
else
{
CloseTunnel();
return false;
}
}
/// <summary>
/// 隧道关门
/// </summary>
/// <returns></returns>
public string CloseDoor()
{
if (GlobalData.tunnel == null)
{
return "隧道机未连接";
}
if (GlobalData.tunnel.CloseDoor())
{
return "已关门";
}
else
{
return "关门失败";
}
//MessageBox.Show(string.Format(crm.GetString("ExecuteCommandFailed"), btn_CloseDoor.Text));
}
/// <summary>
/// 隧道开门
/// </summary>
/// <returns></returns>
public string OpenDoor()
{
if (GlobalData.tunnel == null)
{
return "隧道机未连接";
}
if (GlobalData.tunnel.OpenDoor())
{
return "已开门";
}
else
{
return "开门失败";
}
}
}
}

View File

@ -0,0 +1,16 @@
using Rovinj.Tunnel;
namespace LolaiService.Global
{
public static class GlobalData
{
/// <summary>
/// 隧道机是否已连接
/// </summary>
public static bool isTunnelConnected = false;
/// <summary>
/// 隧道机接口
/// </summary>
public static ITunnel tunnel;
}
}

View File

@ -0,0 +1,124 @@
using LolaiService.Devices.Tunnel;
using Rovinj.Device;
using Rovinj.Reader.Silion;
using Rovinj.Tunnel;
using Rovinj.Tunnel.Plc;
namespace LolaiService.Global
{
/// <summary>
/// 隧道机设备
/// </summary>
public class GlobalDeviceInfo
{
/// <summary>
/// 连接设备
/// </summary>
public static bool ConnectDevice()
{
//创建日志目录
if (!Directory.Exists("log"))
Directory.CreateDirectory("log");
//初始化日志组件(仅供测试使用)
Rovinj.Log.LogHelper.InitLogger(new Rovinj.Log.TextLog($"log\\{DateTime.Now:yyyy-MM-dd}.log"));
//隧道机业务层
RfidTunnel rfidTunnel = new RfidTunnel();
////配置RFID读写器参数
#region RFID读写器参数
SilionReaderConfig readerConfig = new SilionReaderConfig()
{
Qvalue = 5,
Session = 1,
ReadTID = false,
Target = 0,
RfMode = 1,
IsFastRead = true,
QuickModeType = 3,
Antennas = new List<SilionAntennaConfig>(),
};
double power = 30; //功率
int antCount = 4; //4个天线
//根据用户输入的天线数量(默认 4 个),给每个天线端口配置功率和启用状态。
for (int i = 0; i < antCount; i++)
{
readerConfig.Antennas.Add(new SilionAntennaConfig()
{
IsEnabled = true,
PortNumber = (ushort)(i + 1),
TxPowerInDbm = power
});
}
#endregion
#region PLC连接方式
ConnectionConfig plcConnectionConfig = new ConnectionConfig();
plcConnectionConfig.ConnectionMode = ConnectionMode.Network; //网口连接模式
plcConnectionConfig.NetworkAddress = "192.168.1.250"; //PLC IP地址
plcConnectionConfig.NetworkPort = 502; //PLC 端口号
#endregion
#region
ConnectionConfig readerConnectionConfig = new ConnectionConfig();
readerConnectionConfig.Args = new object[] { antCount }; //天线数量默认是4个天线支持1,2,4,8,16
readerConnectionConfig.ConnectionMode = ConnectionMode.Network; //网口连接模式
readerConnectionConfig.NetworkAddress = "192.168.1.100";
#endregion
//封装成隧道配置 根据用户选择,判断是三菱还是西门子 PLC。
TunnelConfig tunnelConfig = new TunnelConfig()
{
PlcType = PlcType.Mitsubishi_FX5U, //PLC类型
PlcConnectionConfig = plcConnectionConfig, //PLC连接配置
ReaderConnectionConfig = readerConnectionConfig, //读写器连接配置
ReaderConfig = readerConfig, //读写器配置
ReaderType = Rovinj.Tunnel.Reader.ReaderType.Silion //读写器类型
};
////西门子PLC暂时不支持使用串口的通讯方式
//if ((tunnelConfig.PlcType == PlcType.Mitsubishi_FX5U || tunnelConfig.PlcType == PlcType.Siemens)
// && tunnelConfig.PlcConnectionConfig.ConnectionMode != ConnectionMode.Network)
//{
// return false;
//}
//是否连接成功
bool result = rfidTunnel.ConnectTunnel(readerConfig, plcConnectionConfig, tunnelConfig);
return result;
}
/// <summary>
/// 隧道关门
/// </summary>
/// <returns></returns>
public static string CloseDoorTunnel()
{
RfidTunnel rfidTunnel = new RfidTunnel();
return rfidTunnel.CloseDoor();
}
/// <summary>
/// 隧道开门
/// </summary>
/// <returns></returns>
public static string OpenDoorTunnel()
{
RfidTunnel rfidTunnel = new RfidTunnel();
return rfidTunnel.OpenDoor();
}
}
}

View File

@ -0,0 +1,16 @@
namespace LolaiService.Global
{
public class GlobalVar
{
/// <summary>
/// 初始化设备
/// </summary>
public static void InitData()
{
GlobalDeviceInfo.ConnectDevice();
}
}
}

View File

@ -0,0 +1,35 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.IdentityModel.Logging" Version="8.14.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2" />
</ItemGroup>
<ItemGroup>
<Reference Include="Rovinj.Device">
<HintPath>..\..\demo1.9\Rovinj.Device.dll</HintPath>
</Reference>
<Reference Include="Rovinj.Log">
<HintPath>..\..\demo1.9\Rovinj.Log.dll</HintPath>
</Reference>
<Reference Include="Rovinj.Reader">
<HintPath>..\..\demo1.9\Rovinj.Reader.dll</HintPath>
</Reference>
<Reference Include="Rovinj.Reader.Silion">
<HintPath>..\..\demo1.9\Rovinj.Reader.Silion.dll</HintPath>
</Reference>
<Reference Include="Rovinj.Tunnel">
<HintPath>..\..\demo1.9\Rovinj.Tunnel.dll</HintPath>
</Reference>
</ItemGroup>
<ProjectExtensions><VisualStudio><UserProperties properties_4launchsettings_1json__JsonSchema="" /></VisualStudio></ProjectExtensions>
</Project>

View File

@ -0,0 +1,6 @@
@LolaiService_HostAddress = http://localhost:5049
GET {{LolaiService_HostAddress}}/weatherforecast/
Accept: application/json
###

39
LolaiService/Program.cs Normal file
View File

@ -0,0 +1,39 @@
namespace LolaiService
{
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
Global.GlobalDeviceInfo.ConnectDevice();
app.Run();
}
}
}

View File

@ -0,0 +1,41 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:50686",
"sslPort": 44389
}
},
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "http://localhost:5049",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "https://localhost:8999;http://localhost:5049",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

View File

@ -0,0 +1,13 @@
namespace LolaiService
{
public class WeatherForecast
{
public DateOnly Date { get; set; }
public int TemperatureC { get; set; }
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
public string? Summary { get; set; }
}
}

View File

@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

View File

@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}

BIN
LolaiService/tunnelPlc.dll Normal file

Binary file not shown.

25
LolaiSysService.sln Normal file
View File

@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.14.36623.8 d17.14
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LolaiService", "LolaiService\LolaiService.csproj", "{9EF3747E-AF77-46F0-9F5B-624765C748E1}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{9EF3747E-AF77-46F0-9F5B-624765C748E1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9EF3747E-AF77-46F0-9F5B-624765C748E1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9EF3747E-AF77-46F0-9F5B-624765C748E1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9EF3747E-AF77-46F0-9F5B-624765C748E1}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {4273D124-83C5-4283-AD67-CDC24E9BE380}
EndGlobalSection
EndGlobal