Browse Source

重构代码并添加新功能

重构了多个类和命名空间,简化了方法实现。更新了项目依赖包版本,添加了新的包引用。新增了 `Program`、`AppSettings`、`Startup`、`Worker` 和 `WorkStart` 类,分别用于初始化程序、加载配置、配置服务、执行后台任务和初始化设备信息。
林豪 左 10 months ago
parent
commit
c89aa313e4

+ 24 - 0
DataAcquisitionSolution/AppSettings.cs

@@ -0,0 +1,24 @@
+using Microsoft.Extensions.Configuration;
+
+namespace DataAcquisitionSolution;
+
+/// <summary>
+///     程序设置
+/// </summary>
+public class AppSettings
+{
+    /// <summary>
+    ///     静态构造函数
+    /// </summary>
+    static AppSettings()
+    {
+        Config = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json")
+            .Build();
+        WorkStart.WareHouses = Config.GetConnectionString("WareHouses");
+    }
+
+    /// <summary>
+    ///     配置信息
+    /// </summary>
+    public static IConfiguration Config { get; }
+}

+ 25 - 8
DataAcquisitionSolution/DataAcquisition.cs

@@ -1,12 +1,29 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using WCS.Core;
 
-namespace DataAcquisitionSolution
+namespace DataAcquisitionSolution;
+
+public static class DataAcquisition
 {
-    public class DataAcquisition
+    public static List<ProtocolInfo> ProtocolInfos = new();
+
+    public static void Init(int position, ushort db, string ip)
     {
+        var info = new ProtocolInfo
+        {
+            Position = position,
+            DBInfo = new DBInfo
+            {
+                No = db,
+                PLCInfo = new PLCInfo
+                {
+                    IP = ip,
+                    Port = 102,
+                    Rack = 0,
+                    Slot = 1,
+                    Type = PLCType.Siemens
+                }
+            }
+        };
+        ProtocolInfos.Add(info);
     }
-}
+}

+ 3 - 1
DataAcquisitionSolution/DataAcquisitionSolution.csproj

@@ -10,7 +10,9 @@
   <ItemGroup>
     <PackageReference Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.0.2" />
     <PackageReference Include="Npgsql" Version="8.0.3" />
-    <PackageReference Include="ServiceCenter" Version="1.0.6" />
+    <PackageReference Include="ServiceCenter" Version="1.1.4" />
+    <PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.0.2" />
+    <PackageReference Include="System.Text.RegularExpressions" Version="4.3.1" />
   </ItemGroup>
 
 </Project>

+ 16 - 20
DataAcquisitionSolution/PLCAccessors/PLCAccessorsCreater.cs

@@ -1,29 +1,25 @@
 using WCS.Core;
 using PLCType = WCS.Core.PLCType;
 
-namespace WCS.Service.PLCAccessors
+namespace DataAcquisitionSolution.PLCAccessors;
+
+/// <summary>
+///     PLC访问器创建者
+/// </summary>
+public class PlcAccessorsCreater : IPLCAccessorCreater
 {
     /// <summary>
-    ///  PLC访问器创建者
+    ///     创建PLC访问器
     /// </summary>
-    public class PLCAccessorsCreater : IPLCAccessorCreater
+    /// <param name="data">PLC信息</param>
+    /// <returns></returns>
+    /// <exception cref="Exception"> </exception>
+    public IPLCAccessor Create(PLCInfo data)
     {
-        /// <summary>
-        ///  创建PLC访问器
-        /// </summary>
-        /// <param name="data">PLC信息</param>
-        /// <returns></returns>
-        /// <exception cref="Exception"> </exception>
-        public IPLCAccessor Create(PLCInfo data)
+        return data.Type switch
         {
-            switch (data.Type)
-            {
-                case PLCType.Siemens:
-                    return new SiemensS7PLC(data.IP, data.Port, data.Rack, data.Slot);
-
-                default:
-                    return new VitrualRedisPLC(data, "127.0.0.1,database=1,prefix=Sorting:");
-            }
-        }
+            PLCType.Siemens => new SiemensS7Plc(data.IP, data.Port, data.Rack, data.Slot),
+            _ => new VitrualRedisPLC(data, "127.0.0.1,database=1,prefix=Sorting:")
+        };
     }
-}
+}

+ 32 - 37
DataAcquisitionSolution/PLCAccessors/SiemensS7PLC.cs

@@ -1,52 +1,47 @@
-
-using PlcSiemens.O;
+using PlcSiemens.O;
 using PlcSiemens.Protocol.Common;
 using ServiceCenter;
 using ServiceCenter.Virtual_PLC;
 using WCS.Core;
 
-namespace WCS.Service.PLCAccessors
+namespace DataAcquisitionSolution.PLCAccessors;
+
+public class SiemensS7Plc : IPLCAccessor
 {
-    public class SiemensS7PLC : IPLCAccessor
+    private readonly SimenssPlc _plc;
+
+    public SiemensS7Plc(string ip, int port, int rack, int slot)
     {
-        private SimenssPlc plc;
+        _plc = new SimenssPlc(ip, rack, slot);
+        _plc.Connect();
+    }
 
-        public SiemensS7PLC(string ip, int port, int rack, int slot)
-        {
-            plc = new SimenssPlc(ip, rack, slot);
-            plc.Connect();
-        }
+    public byte[] ReadBytes(ushort db, ushort address, ushort length)
+    {
+        if (ServiceHub.Any(SystemMode.虚拟plc))
+            return PlcData.Read(new PLCData { IP = _plc.IP, DB = db, Length = length, DataLength = length });
 
-        public byte[] ReadBytes(ushort db, ushort address, ushort length)
-        {
-            if (ServiceHub.Any(SystemMode.虚拟plc))
-            {
-                return PlcData.Read(new PLCData { IP = plc.IP, DB = db, Length = length, DataLength = length });
-            }
+        if (!_plc.Connected)
+            _plc.Connect();
 
-            if (!plc.Connected)
-                plc.Connect();
+        var res = _plc.ReadArea(AreaType.DB, db, address, length, DataType.Byte);
+        if (res == null)
+            throw new Exception("读取DB块数据失败");
+        return res.Data;
+    }
 
-            var res = plc.ReadArea(AreaType.DB, db, address, length, DataType.Byte);
-            if (res == null)
-                throw new Exception("读取DB块数据失败");
-            return res.Data;
+    public void WriteBytes(ushort db, ushort address, byte[] data)
+    {
+        if (ServiceHub.Any(SystemMode.虚拟plc))
+        {
+            PlcData.Write(new PLCData { IP = _plc.IP, DB = db }, address, data);
         }
-
-        public void WriteBytes(ushort db, ushort address, byte[] data)
+        else
         {
-            if (ServiceHub.Any(SystemMode.虚拟plc))
-            {
-                PlcData.Write(new PLCData { IP = plc.IP, DB = db }, address, data);
-            }
-            else
-            {
-                if (!plc.Connected)
-                    plc.Connect();
-                var res = plc.WriteArea(AreaType.DB, db, address, (ushort)data.Length, DataType.Byte, data);
-                if (!res) throw new Exception("写入DB块数据失败");
-
-            }
+            if (!_plc.Connected)
+                _plc.Connect();
+            var res = _plc.WriteArea(AreaType.DB, db, address, (ushort)data.Length, DataType.Byte, data);
+            if (!res) throw new Exception("写入DB块数据失败");
         }
     }
-}
+}

+ 70 - 2
DataAcquisitionSolution/Program.cs

@@ -1,2 +1,70 @@
-// See https://aka.ms/new-console-template for more information
-Console.WriteLine("Hello, World!");
+using System.Runtime.InteropServices;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using ServiceCenter.Extensions;
+using ServiceCenter.Redis;
+
+namespace DataAcquisitionSolution;
+
+public class Program
+{
+    public static void Main(string[] args)
+    {
+        #region 接入Redis
+
+        RedisHub.CreateContext(AppSettings.Config.GetConnectionString("Redis") ?? string.Empty, "default", true);
+
+        #endregion 接入Redis
+
+        //互斥锁检测
+        var mutexName = RedisHub.Default.Check("Mutex") ?? throw new Exception("请在Redis中配置互斥量值");
+
+        using var mt = new Mutex(true, mutexName);
+        if (mt.WaitOne())
+        {
+            CreateHostBuilder(args).Build().Run();
+            mt.ReleaseMutex();
+        }
+        else
+        {
+            Console.WriteLine("请勿重复运行");
+            //InfoLog.INFO_INIT("请勿重复运行");
+            Task.Delay(2000).Wait();
+        }
+    }
+
+    /// <summary>
+    ///     创建一个主机构建器
+    /// </summary>
+    /// <param name="args"></param>
+    /// <returns></returns>
+    public static IHostBuilder CreateHostBuilder(string[] args)
+    {
+        //是否是win平台
+        var isWin = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
+        Console.WriteLine($"win:{isWin}");
+        if (!isWin)
+            return Host.CreateDefaultBuilder(args)
+                .UseSystemd() //linux
+                .ConfigureServices((_, services) => { services.AddHostedService<Worker>(); });
+        {
+            var useUrls = RedisHub.Default.Check("UseUrls") ?? throw new Exception("请在Redis中配置网络访问端口");
+            //"http://*:8080"
+            return Host.CreateDefaultBuilder(args)
+                .UseWindowsService() //win
+                .ConfigureWebHostDefaults(web => //网络访问配置
+                {
+                    web.UseUrls(useUrls); //设备访问端口
+                    web.UseStartup<Startup>(); //调用启动服务
+                })
+                .ConfigureServices((_, services) =>
+                {
+                    services.AddHostedService<Worker>();
+                    services.AddHttpClient();
+                });
+        }
+
+    }
+}

+ 53 - 0
DataAcquisitionSolution/Startup.cs

@@ -0,0 +1,53 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+
+namespace DataAcquisitionSolution;
+
+public class Startup(IConfiguration configuration)
+{
+    public string MyCors = "Cor";
+    public IConfiguration Configuration { get; } = configuration;
+
+    // This method gets called by the runtime. Use this method to add services to the container.
+    public void ConfigureServices(IServiceCollection services)
+    {
+        services.AddControllers();
+        //跨域配置
+        services.AddCors(v => v.AddPolicy(MyCors, y =>
+        {
+            //声明跨域策略:允许所有域、允许任何请求头和允许全部http方法
+            y.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod();
+        }));
+        //services.AddSwaggerGen(c =>
+        //{
+        //    //c.SwaggerDoc("v1", new OpenApiInfo { Title = "WCSAPI", Version = "v1" });
+        //    c.SwaggerDoc("v1", new OpenApiInfo
+        //    {
+        //        Version = "v1",
+        //        Title = "WCSAPI",
+        //        Description = "API描述"
+        //    });
+        //    var xmlFilename = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
+        //    c.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, xmlFilename));
+        //});
+    }
+
+    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
+    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
+    {
+        app.UseDeveloperExceptionPage();
+        //app.UseSwagger();
+        //app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "WebApplication1 v1"));
+        //http://localhost:8080/swagger/index.html
+
+        app.UseHttpsRedirection();
+
+        app.UseRouting();
+        app.UseCors(MyCors);
+        app.UseAuthorization();
+
+        app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
+    }
+}

+ 142 - 0
DataAcquisitionSolution/WorkStart.cs

@@ -0,0 +1,142 @@
+using ServiceCenter;
+using ServiceCenter.SqlSugars;
+
+namespace DataAcquisitionSolution;
+
+/// <summary>
+///     业务工程配置信息
+/// </summary>
+public static class WorkStart
+{
+    /// <summary>
+    ///     仓库
+    /// </summary>
+    public static string? WareHouses { get; set; }
+
+    /// <summary>
+    ///     初始化 设备信息
+    /// </summary>
+    public static void InitializeDeviceInfo()
+    {
+    }
+
+    /// <summary>
+    ///     初始化数据库连接
+    /// </summary>
+    /// <param name="datas"></param>
+    public static void InitDb(this List<DataBaseConnectionString>? datas)
+    {
+        //初始化数据库
+        SqlSugarHelper.Do(db =>
+        {
+            foreach (var connectionString in datas!)
+            {
+                db.Connect.GetConnectionScope(connectionString.Key);
+                switch (connectionString.Key)
+                {
+                    case "WCSDB": //WCS基本数据库
+                        SqlSugarHelper.SetDefault(connectionString.Key);
+                        //_db.CodeFirst.InitTables(typeof(WCS_PlcData));
+                        //_db.CodeFirst.InitTables(typeof(WCS_TaskInfo));
+                        //_db.CodeFirst.InitTables(typeof(WCS_TaskDtl));
+                        //_db.CodeFirst.InitTables(typeof(WCS_TaskOld));
+                        //_db.CodeFirst.InitTables(typeof(WCS_AgvTaskInfo));
+                        //_db.CodeFirst.InitTables(typeof(WCS_Palletizing));
+                        //_db.CodeFirst.InitTables(typeof(WCS_PalletizingLayer));
+                        //_db.CodeFirst.InitTables(typeof(WCS_PalletizingRow));
+                        //_db.CodeFirst.InitTables(typeof(WCS_PalletizingLoc));
+                        //_db.CodeFirst.InitTables(typeof(WCS_CacheLine));
+                        //_db.CodeFirst.InitTables(typeof(WCS_CacheLineLoc));
+
+                        break;
+
+                    case "WCSDlog": //WCS日志数据库
+
+                        break;
+
+                    case "PLC": //PLC
+
+                        SqlSugarHelper.SetPLC(connectionString.Key);
+
+                        //_db.DbMaintenance.CreateDatabase();
+                        //_db.CodeFirst.InitTables<WCS_Log>();
+                        //_db.CodeFirst.InitTables<WCS_SRM520>();
+                        //_db.CodeFirst.InitTables<WCS_SRM521>();
+                        //_db.CodeFirst.InitTables<WCS_SRM537>();
+                        //_db.CodeFirst.InitTables<WCS_RGV520>();
+                        //_db.CodeFirst.InitTables<WCS_RGV521>();
+                        //_db.CodeFirst.InitTables<WCS_BCR80>();
+                        //_db.CodeFirst.InitTables<WCS_BCR81>();
+                        //_db.CodeFirst.InitTables<WCS_BCR83>();
+                        //_db.CodeFirst.InitTables<WCS_Station520>();
+                        //_db.CodeFirst.InitTables<WCS_Station521>();
+                        //_db.CodeFirst.InitTables<WCS_Station523>();
+                        //_db.CodeFirst.InitTables<WCS_Station524>();
+                        //_db.CodeFirst.InitTables<WCS_Station525>();
+                        //_db.CodeFirst.InitTables<WCS_Station90>();
+                        //_db.CodeFirst.InitTables<WCS_Station91>();
+                        //_db.CodeFirst.InitTables<WCS_Truss520>();
+                        //_db.CodeFirst.InitTables<WCS_Truss521>();
+                        //_db.CodeFirst.InitTables<WCS_Truss523>();
+                        //_db.CodeFirst.InitTables<WCS_Truss530>();
+                        //_db.CodeFirst.InitTables<WCS_Truss531>();
+                        //_db.CodeFirst.InitTables<WCS_Robot520>();
+                        //_db.CodeFirst.InitTables<WCS_Robot521>();
+                        //_db.CodeFirst.InitTables<WCS_Robot522>();
+                        //_db.CodeFirst.InitTables<WCS_Robot530>();
+                        //_db.CodeFirst.InitTables<WCS_Robot531>();
+                        //var a = false;
+                        break;
+                }
+
+                ;
+            }
+
+            ;
+        });
+    }
+}
+
+public class DevDbConfig<T>
+{
+    public DevDbConfig()
+    {
+    }
+
+    public DevDbConfig(string? ip, T? code)
+    {
+        Ip = ip;
+        Code = code;
+    }
+
+    public DevDbConfig(string? ip, List<DevInterval<T>>? devIntervalList)
+    {
+        Ip = ip;
+        DevIntervalList = devIntervalList;
+    }
+
+    public DevDbConfig(string? ip, List<T>? devCodeList)
+    {
+        Ip = ip;
+        DevCodeList = devCodeList;
+    }
+
+    public string? Ip { get; set; }
+
+    public T? Code { get; set; }
+
+    public T? StartCode { get; set; }
+
+    public T? EndCode { get; set; }
+
+    public List<T>? DevCodeList { get; set; }
+
+    public List<DevInterval<T>>? DevIntervalList { get; set; }
+}
+
+public class DevInterval<T>(T s, T e)
+{
+    public T StartCode { get; set; } = s;
+
+    public T EndCode { get; set; } = e;
+}

+ 166 - 0
DataAcquisitionSolution/Worker.cs

@@ -0,0 +1,166 @@
+using System.Text;
+using DataAcquisitionSolution.PLCAccessors;
+using MessagePack;
+using Microsoft.Extensions.Hosting;
+using Microsoft.Extensions.Logging;
+using Newtonsoft.Json;
+using ServiceCenter;
+using ServiceCenter.Extensions;
+using ServiceCenter.Logs;
+using ServiceCenter.Redis;
+using ServiceCenter.SqlSugars;
+using SqlSugar;
+using WCS.Core;
+
+namespace DataAcquisitionSolution
+{
+    /// <summary>
+    /// 工作服务
+    /// </summary>
+    public class Worker : BackgroundService
+    {
+        /// <summary>
+        /// 记录器
+        /// </summary>
+        private readonly ILogger<Worker> _logger;
+
+        /// <summary>
+        /// 构造函数
+        /// </summary>
+        /// <param name="logger">记录器</param>
+        public Worker(ILogger<Worker> logger)
+        {
+            _logger = logger;
+        }
+
+        public static readonly string WcsDlog = "WCSDlog";
+        public static readonly string Wcsdb = "WCSDB";
+
+        /// <summary>
+        ///  执行
+        /// </summary>
+        /// <param name="stoppingToken">停止令牌</param>
+        /// <returns></returns>
+        protected override Task ExecuteAsync(CancellationToken stoppingToken)
+        {
+            if (stoppingToken.IsCancellationRequested)
+                return Task.CompletedTask;
+
+            #region 初始化Redis连接
+
+            var redisConnectionStrings = RedisHub.Default.Check("RedisConnectionStrings") ?? throw new Exception("请在Redis中配置RedisConnectionStrings");
+            var configs = JsonConvert.DeserializeObject<List<DataBaseConnectionString>>(redisConnectionStrings);
+            if (configs != null)
+            {
+                if (configs.All(v => v.Key != "Monitor")) throw new Exception("请在RedisConnectionStrings中配置监控RedisDB库连接字符串");
+            }
+
+            foreach (var redisConnection in configs!)
+            {
+                RedisHub.CreateContext(redisConnection.ConnectionString, redisConnection.Key);
+                switch (redisConnection.Key)
+                {
+                    case "Monitor":
+                        RedisHub.SetMonitorContextType(redisConnection.Key);
+                        RedisHub.Monitor.Serialize = obj =>
+                        {
+                            var bytes = MessagePackSerializer.Serialize(obj);
+                            return bytes;
+                        };
+                        RedisHub.Monitor.DeserializeRaw = (bytes, type) =>
+                        {
+                            var obj = MessagePackSerializer.Deserialize(type, bytes);
+                            return obj;
+                        };
+                        break;
+
+                    case "DebugRedisUrl":
+                        RedisHub.SetDebugContextType(redisConnection.Key);
+                        Configs.DebugRedisUrl = redisConnection.ConnectionString;
+                        break;
+
+                    case "WMS":
+                        RedisHub.SetWMSContextType(redisConnection.Key);
+                        break;
+                }
+            }
+
+            #endregion 初始化Redis连接
+
+            #region 启用日志
+
+            //var logConfigText = RedisHub.Default.Check("LogConfigText") ?? throw new Exception("请在Redis中配置log4net相关内容");
+            //var logConfig = JsonConvert.DeserializeObject<LogConfig>(logConfigText);
+            //LogHub.SetConfigInfo(logConfig!);
+
+            #endregion 启用日志
+
+            _logger.LogInformation("WCS开始启动");
+            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
+            Configs.StringEncoding = Encoding.UTF8;
+            //var warehouseName = RedisHub.Default.Check("WarehouseName") ?? throw new Exception("请在Redis中配置仓库名称");
+            //if (string.IsNullOrEmpty(warehouseName)) throw new Exception("请在Redis中配置仓库名称");
+            //ServiceHub.SetWarehouseName(warehouseName);
+
+            #region 初始化数据库连接
+
+            var dbConnectionStrings = RedisHub.Default.Check("DbConnectionStrings") ?? throw new Exception("请在Redis中配置数据库连接相关内容");
+            ServiceHub.DbConnectionStrings = JsonConvert.DeserializeObject<List<DataBaseConnectionString>>(dbConnectionStrings);
+            if (ServiceHub.DbConnectionStrings != null)
+            {
+                if (ServiceHub.DbConnectionStrings.All(v => v.Key != Wcsdb)) throw new Exception("请在DbConnectionStrings中配置WCS基础数据库连接字符串");
+                if (ServiceHub.DbConnectionStrings.All(v => v.Key == Wcsdb && !v.IsDefault)) throw new Exception("请在DbConnectionStrings中配置WCS基础数据库为默认数据库");
+                // if (ServiceHub.DbConnectionStrings.All(v => v.Key != WcsDlog)) throw new Exception("请在DbConnectionStrings中配置WCS日志数据库连接字符串");
+            }
+
+            //设置连接信息
+            var connectionConfigs = ServiceHub.DbConnectionStrings!.Select(connectionString => new ConnectionConfig()
+                {
+                    ConfigId = connectionString.Key,
+                    ConnectionString = connectionString.ConnectionString, //连接符字串
+                    DbType = connectionString.DbType, //数据库类型
+                    IsAutoCloseConnection = true, //不设成true要手动close
+                    LanguageType = LanguageType.Chinese,
+                    MoreSettings = new ConnMoreSettings() { IsNoReadXmlDescription = true }
+                })
+                .ToList();
+            ;
+            SqlSugarHelper.SetDb(new SqlSugarScope(connectionConfigs));
+
+            ServiceHub.DbConnectionStrings.InitDb();
+
+            #endregion 初始化数据库连接
+
+            #region 初始化设备信息
+
+            WorkStart.InitializeDeviceInfo();
+
+            #endregion 初始化设备信息
+
+            #region 初始化PLC访问器及PLC读取协议
+
+            //创建PLC访问器
+            Configs.PLCAccessorCreater = new PlcAccessorsCreater();
+
+            try
+            {
+                #region 唤醒所有的世界
+
+                World.StartAll();
+
+                #endregion 唤醒所有的世界
+
+                _logger.LogInformation("WCS启动成功");
+            }
+            catch (Exception ex)
+            {
+                _logger.LogError("WCS启动失败{0}", ex.Message);
+            }
+
+            #endregion 初始化PLC访问器及PLC读取协议
+
+            LogHub.init();
+            return Task.CompletedTask;
+        }
+    }
+}