diff --git a/BPA.Model/Enums/BatchStep.cs b/BPA.Model/Enums/BatchStep.cs new file mode 100644 index 0000000..2eaf36d --- /dev/null +++ b/BPA.Model/Enums/BatchStep.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BPA.Model.Enums +{ + public enum BatchStep:int + { + /// + /// 等待配料 + /// + WaitBatch=0, + /// + /// 写入配料参数。 + /// + WriteBatchParam=100, + /// + /// 开始配料。 + /// + StartBatch=200, + /// + /// 等待配料完成。 + /// + WaitBatchComplete=300, + /// + /// 配料完成。 + /// + BatchCompleted=400 + } +} diff --git a/BPA.Model/Enums/MoveConveyer.cs b/BPA.Model/Enums/MoveConveyer.cs new file mode 100644 index 0000000..66fa5c9 --- /dev/null +++ b/BPA.Model/Enums/MoveConveyer.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BPA.Model.Enums +{ + public enum MoveConveyer:int + { + WaitMove=0, + Moveing=100, + MoveComplete=200, + } +} diff --git a/BPA.Model/GlobalData.cs b/BPA.Model/GlobalData.cs index bab1d60..5dc6c5d 100644 --- a/BPA.Model/GlobalData.cs +++ b/BPA.Model/GlobalData.cs @@ -4,11 +4,25 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using System.Collections.Concurrent; +using BPA.Model.Recipe; +using BPA.Model.Enums; namespace BPA.Model { - public class GlobalData + public class GlobalData { - public static ConcurrentQueue GoodsModels { get; set; } = new ConcurrentQueue(); + public ConcurrentQueue GoodsModels { get; set; } = new ConcurrentQueue(); + /// + /// 需要执行的配方队列。 + /// + public ConcurrentQueue RecipeQueue { get; set; } = new(); + + #region 配料机 + + #endregion + + #region 传送带 + public MoveConveyer MoveConveyerStep { get; set; } + #endregion } } diff --git a/BPA.Model/Recipe/RecipeData.cs b/BPA.Model/Recipe/RecipeData.cs new file mode 100644 index 0000000..706e454 --- /dev/null +++ b/BPA.Model/Recipe/RecipeData.cs @@ -0,0 +1,47 @@ +using BPA.Model.Enums; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BPA.Model.Recipe +{ + /// + /// 根据设备生成的配方数据。 + /// + public class RecipeData + { + public string ID { get; set; } + public string Name { get; set; } + /// + /// 该配方当前所在的工位。 + /// + public int CurrentStation { get; set; } + /// + /// 配方对应的各设备的下料数据,键为设备编号,值为设备下各个料仓的下料重量。 + /// + public Dictionary MaterialData { get; set; } + /// + /// 各个设备是否下料完成。 + /// + public bool[] IsMakeComplete { get; set; } + + public Dictionary BatchStatus { get; set; } + public RecipeData(string id,string name, Dictionary materialData,int stationCount=5) + { + ID = id; + Name = name; + MaterialData = materialData; + //取决于工位数量,本案例中,有五个工位,但是第三个工位没有设备。 + IsMakeComplete = new bool[stationCount]; + + BatchStatus = new(); + for (int i = 1; i <= stationCount; i++) + { + BatchStatus.Add(i, BatchStep.WaitBatch); + } + } + + } +} diff --git a/BPA.Model/TaskServer.cs b/BPA.Model/TaskServer.cs new file mode 100644 index 0000000..1f86f3a --- /dev/null +++ b/BPA.Model/TaskServer.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace BPA.Model +{ + /// + /// 配料线程服务类。 + /// + public class TaskServer + { + public int ID { get; set; } + /// + /// 任务名称 + /// + public string TaskName { get; set; } + /// + /// 是否结束。 + /// + public bool IsCompleted { get; set; } + public Task RunTask { get; set; } + /// + /// 任务取消标识 + /// + public CancellationTokenSource Cts { get; set; } = new CancellationTokenSource(); + } +} diff --git a/BPA.SingleDevice/App.xaml.cs b/BPA.SingleDevice/App.xaml.cs index f6731d4..339dd29 100644 --- a/BPA.SingleDevice/App.xaml.cs +++ b/BPA.SingleDevice/App.xaml.cs @@ -43,7 +43,17 @@ namespace BPA.SingleDevice base.OnStartup(e); SqlHelper.GetInstance.Init(); - MainControl.GetInstance.Start(); + //MainControl.GetInstance.Start(); + + #region 注册调试日志。 + ILogService logService = App.Current.Services.GetService(); + MessageLog.GetInstance.NotifyShow = (string str) => + { + logService.LogDebugInfo(str); + }; + #endregion + + Current.Services.GetService().Inital(); MainView mv = new MainView(); mv.Show(); } @@ -51,7 +61,7 @@ namespace BPA.SingleDevice protected override void OnExit(ExitEventArgs e) { base.OnExit(e); - MainControl.GetInstance.Stop(); + //MainControl.GetInstance.Stop(); } private static IServiceProvider ConfigurServices() @@ -61,15 +71,20 @@ namespace BPA.SingleDevice //services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); - - + services.AddSingleton(); + services.AddSingleton(); return services.BuildServiceProvider(); } diff --git a/BPA.SingleDevice/Business/Batcher.cs b/BPA.SingleDevice/Business/Batcher.cs new file mode 100644 index 0000000..c572117 --- /dev/null +++ b/BPA.SingleDevice/Business/Batcher.cs @@ -0,0 +1,75 @@ +using BPA.SingleDevice.Interface; +using BPA.SingleDevice.Services; +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BPA.SingleDevice.Business +{ + /// + /// 配料机,在这个程序中,指的是味魔方。 + /// + public class Batcher : IBatchcer + { + public int ID { get; set; } + public bool BatchComplete { get; set; } + public bool AllowBatching { get; set; } + public bool IsConnected { get => modbus.IsConnected(); } + + string iP="192.168.6.100"; + int port=502; + ModbusTcp modbus = new(); + public async Task Initial() + { + await Task.Run(() => + { + modbus.WithModbusTcp(iP, port).UseConnected(() => + { + TaskManage.GetInstance.StartLong(() => + { + BatchComplete = modbus.Read("LB1000".ToModbusAdd()).Content; + }, $"Batcher【{ID}】:ReadData", true); + }); + }); + + } + + + public bool StartBatching() + { + try + { + var result = modbus.Write("LB1001".ToModbusAdd(), true); + return result.IsSuccess; + } + catch (Exception ex) + { + return false; + } + } + + public bool WriteBatchData(ushort[] value) + { + try + { + var result = modbus.Write("LW1000".ToModbusAdd(), value); + return result.IsSuccess; + } + catch(Exception ex) + { + return false; + } + } + + + public void SetCommParam(int id,string ip, int port = 502) + { + this.iP = ip; + this.port = port; + this.ID = id; + } + } +} diff --git a/BPA.SingleDevice/Business/Conveyer.cs b/BPA.SingleDevice/Business/Conveyer.cs new file mode 100644 index 0000000..d52fb97 --- /dev/null +++ b/BPA.SingleDevice/Business/Conveyer.cs @@ -0,0 +1,138 @@ +using BPA.SingleDevice.Interface; +using BPA.SingleDevice.Services; +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BPA.SingleDevice.Business +{ + public class Conveyer : IConveyer + { + public int ID { get; set; } + + public bool[] HaveVessel { get; set; } + public int IsReverse { get; set ; } + public float InchSpeed { get; set; } + public float MoveSpeed { get; set; } + public int AccTime { get; set; } + public int MoveLength { get; set; } + public bool MoveComplete { get;set; } + + public bool AllowMove { get; set; } + + public bool IsConnected => modbus.IsConnected(); + + string iP = "192.168.6.104"; + int port = 502; + ModbusTcp modbus = new(); + public async Task Initial() + { + //因为设备中间有个空位。虽然是4台设备,但是需要设置5个位置。 + HaveVessel = new bool[5]; + + //这里还需写入默认参数,从文件读取,如移动速度等。 + await Task.Run(() => + { + modbus.WithModbusTcp(iP, port).UseConnected(() => + { + TaskManage.GetInstance.StartLong(() => + { + modbus.Read("VW300".ToModbusAdd()).OnSuccess((haveVessel) => + { + HaveVessel[0] = haveVessel.GetBitValue(1); + HaveVessel[1] = haveVessel.GetBitValue(2); + //HaveVessel[2] = false; + HaveVessel[3] = haveVessel.GetBitValue(4); + HaveVessel[4] = haveVessel.GetBitValue(5); + }); + + modbus.Read("M0.2".ToModbusAdd()).OnSuccess((moveComplete) => + { + MoveComplete = moveComplete; + }); + }, $"Conveyer【{ID}】:ReadData", true); + }); + }); + + } + + public void SetCommParam(int id, string ip, int port = 502) + { + this.iP = ip; + this.port = port; + this.ID = id; + } + + public void InchMove() + { + if (IsConnected) + { + try + { + modbus.Write("VW0".ToModbusAdd(), 1); + } + catch (Exception ex) + { + + + } + } + } + + public bool MoveOnce() + { + if (IsConnected) + { + try + { + return modbus.Write("VW0".ToModbusAdd(), 2).IsSuccess; + } + catch (Exception ex) + { + + } + } + return false; + } + + public bool SetInchParam(int isReverse, float inchSpeed) + { + if (IsConnected) + { + try + { + var result1= modbus.Write("VD100".ToModbusAdd(), inchSpeed); + var result2= modbus.Write("VW200".ToModbusAdd(), isReverse); + return result1.IsSuccess && result2.IsSuccess; + } + catch (Exception ex) + { + + } + } + return false; + } + + public bool SetMoveParam(float moveSpeed, int accTime, int moveLength) + { + if (IsConnected) + { + try + { + var result1 = modbus.Write("VD104".ToModbusAdd(), moveSpeed); + var result2 = modbus.Write("VW122".ToModbusAdd(), accTime); + var result3 = modbus.Write("VD108".ToModbusAdd(), moveLength); + return result1.IsSuccess && result2.IsSuccess && result3.IsSuccess; + } + catch (Exception ex) + { + + } + } + return false; + } + } +} diff --git a/BPA.SingleDevice/Business/MainControl.cs b/BPA.SingleDevice/Business/MainControl.cs index 5238e9e..4e9f1a2 100644 --- a/BPA.SingleDevice/Business/MainControl.cs +++ b/BPA.SingleDevice/Business/MainControl.cs @@ -27,11 +27,11 @@ namespace BPA.SingleDevice.Business private void CommInit() { Enum.GetNames(typeof(EDeviceType)).ToList().ForEach(x => { Comm.TryAdd(x.ToEnum(), new DeviceControl()); }); - Comm[EDeviceType.WeimoCube1].SetPar("192.168.1.100", EDeviceType.WeimoCube1); - Comm[EDeviceType.WeimoCube2].SetPar("192.168.1.100", EDeviceType.WeimoCube2); - Comm[EDeviceType.WeimoCube3].SetPar("192.168.1.100", EDeviceType.WeimoCube3); - Comm[EDeviceType.WeimoCube4].SetPar("192.168.1.100", EDeviceType.WeimoCube4); - Comm[EDeviceType.Conveyor].SetPar("192.168.1.100", EDeviceType.Conveyor); + Comm[EDeviceType.WeimoCube1].SetPar("192.168.6.100", EDeviceType.WeimoCube1); + Comm[EDeviceType.WeimoCube2].SetPar("192.168.6.101", EDeviceType.WeimoCube2); + Comm[EDeviceType.WeimoCube3].SetPar("192.168.6.102", EDeviceType.WeimoCube3); + Comm[EDeviceType.WeimoCube4].SetPar("192.168.6.103", EDeviceType.WeimoCube4); + Comm[EDeviceType.Conveyor].SetPar("192.168.6.104", EDeviceType.Conveyor); Task.Run(() => { Parallel.ForEach(Comm, (s) => { s.Value.Stop(); }); @@ -40,43 +40,43 @@ namespace BPA.SingleDevice.Business public void Start() { - CommInit(); - TaskManage.GetInstance.StartLong(() => - { - while (GlobalData.GoodsModels.Count > 0 && !Comm[EDeviceType.Conveyor].AllowBatching) - { - Task.Run(() => - { - if (GlobalData.GoodsModels.TryDequeue(out GoodsModel gm)) - { - //对设备进行分组,筛选出对应设备所需要的料仓中的原料信息 - var res = gm.RawMaters.GroupBy(p => p.DeviceNum).ToDictionary(p => p.Key, p => p.ToList()); - res.ToList().ForEach(item => - { - int index = item.Key - 1; - if (index >= 0 && index < Comm[EDeviceType.Conveyor].DeviceStationDetection.Length) - { - if (Comm[EDeviceType.Conveyor].DeviceStationDetection[index]) - { - Comm[EDeviceType.Conveyor].ConveyorControl(false); - ushort[] weights = new ushort[14]; - item.Value.ForEach(s => - { - int tempIndex = s.WarehouseNum - 1; - if (tempIndex >= 0 && tempIndex < weights.Length) - { - weights[tempIndex] = s.Weight; - } - }); - Comm[(EDeviceType)item.Key].WriteControl(weights); - } - } - }); - } - }); - } - Thread.Sleep(10); - }, "配料任务", true); + //CommInit(); + //TaskManage.GetInstance.StartLong(() => + //{ + // while (GlobalData.GoodsModels.Count > 0 && !Comm[EDeviceType.Conveyor].AllowBatching) + // { + // Task.Run(() => + // { + // if (GlobalData.GoodsModels.TryDequeue(out GoodsModel gm)) + // { + // //对设备进行分组,筛选出对应设备所需要的料仓中的原料信息 + // var res = gm.RawMaters.GroupBy(p => p.DeviceNum).ToDictionary(p => p.Key, p => p.ToList()); + // res.ToList().ForEach(item => + // { + // int index = item.Key - 1; + // if (index >= 0 && index < Comm[EDeviceType.Conveyor].DeviceStationDetection.Length) + // { + // if (Comm[EDeviceType.Conveyor].DeviceStationDetection[index]) + // { + // Comm[EDeviceType.Conveyor].ConveyorControl(false); + // ushort[] weights = new ushort[14]; + // item.Value.ForEach(s => + // { + // int tempIndex = s.WarehouseNum - 1; + // if (tempIndex >= 0 && tempIndex < weights.Length) + // { + // weights[tempIndex] = s.Weight; + // } + // }); + // Comm[(EDeviceType)item.Key].WriteControl(weights); + // } + // } + // }); + // } + // }); + // } + // Thread.Sleep(10); + //}, "配料任务", true); } public void Stop() diff --git a/BPA.SingleDevice/Business/ProcessControl.cs b/BPA.SingleDevice/Business/ProcessControl.cs new file mode 100644 index 0000000..7321133 --- /dev/null +++ b/BPA.SingleDevice/Business/ProcessControl.cs @@ -0,0 +1,311 @@ +using BPA.Model.Enums; +using BPA.Model.Recipe; +using BPA.SingleDevice.Interface; +using BPA.SingleDevice.Services; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace BPA.SingleDevice.Business +{ + /// + /// 配料流程控制 + /// + public class ProcessControl : IProcessControl + { + public ProcessControl(ILogService logService,GlobalData global) + { + this.logService = logService; + this.global = global; + } + /// + /// 键就是配料设备对应的ID。这里分别为1,2,4,5。 + /// + ConcurrentDictionary batchers = new(); + + //List currentTask = new(); + //ConcurrentDictionary test = new(); + IConveyer conveyer = new Conveyer(); + private readonly ILogService logService; + private GlobalData global; + RecipeData currentRecipe; + + CancellationTokenSource cts; + + Task runTask; + public async void Inital() + { + #region 实例初始化配料机 + batchers.TryAdd(1, new Batcher()); + batchers.TryAdd(2, new Batcher()); + batchers.TryAdd(4, new Batcher()); + batchers.TryAdd(5, new Batcher()); + + //SetBatcherComm(1, "192.168.6.100"); + //SetBatcherComm(2, "192.168.6.101"); + //SetBatcherComm(4, "192.168.6.102"); + //SetBatcherComm(5, "192.168.6.103"); + + SetBatcherComm(1, "127.0.0.1", 503); + SetBatcherComm(2, "127.0.0.1", 504); + SetBatcherComm(4, "127.0.0.1", 505); + SetBatcherComm(5, "127.0.0.1", 506); + foreach (var batcher in batchers.Values) + { + await batcher.Initial(); + } + #endregion + + //conveyer.SetCommParam(1, "192.168.6.104"); + conveyer.SetCommParam(1, "127.0.0.1",510); + await conveyer.Initial(); + + //currentTask.Clear(); + ActionRegister(); + + + + TaskManage.GetInstance.StartLong(() => + { + if (global.RecipeQueue.Count>0 && currentRecipe is null ) + { + //多配方情况下,必须在工位1没有碗位置,才能进行下发,否则会与之前的配方冲突。 + if (/*!conveyer.HaveVessel[0] &&*/ global.RecipeQueue.ElementAt(0) is not null && global.RecipeQueue.ElementAt(0) is RecipeData) + { + global.RecipeQueue.TryDequeue(out currentRecipe); + + //currentTask.Add(new TaskServer() {RunTask=Task.Run(() => { Batching(recipe); }) ,TaskName=$"{recipe.Name}"}); + + cts = new(); + Task.Run(() => { Batching(currentRecipe); }, cts.Token); + logService.LogRunInfo($"配方【{currentRecipe.Name}】-- 开始执行配料。"); + } + } + }, "MonitorRecipeIssue", true); + } + /// + /// 配料。 + /// + /// 需要配料的配方 + private async void Batching(RecipeData recipe) + { + if (recipe is null) + { + logService.LogRunInfo($"参数值为null,配料流程结束。"); + return; + } + while (recipe.IsMakeComplete[0] == false) + { + await StationBatching(recipe, 1); + } + + + + for (int stationNum = 2; stationNum <= 5; stationNum++) + { + await MoveOnceAndBatach(recipe, stationNum); + } + //ToDo:如果最后需要移动一次才能出餐,在这里添加一次移动传送带。 + logService.LogRunInfo($"配方【{recipe.Name}】配料完成。"); + logService.LogRecipeCompleteInfo($"【{recipe.Name}】"); + currentRecipe = null; + } + + /// + /// 单工位配料 + /// + /// 配方 + /// 工位数。 + private async Task StationBatching(RecipeData recipe,int stationNum) + { + + #region 数据验证 + if (recipe is null) + { + logService.LogRunInfo($"参数值为null,配料流程结束。"); + return; + } + //如果配料机里没连接该工位的配料机,则直接完成。 + if (!batchers.ContainsKey(stationNum)) + { + recipe.BatchStatus[stationNum] = BatchStep.BatchCompleted; + recipe.IsMakeComplete[stationNum - 1] = true; + logService.LogRunInfo($"参数值为[{stationNum}],目前该工位无配料机或连接配料机失败。"); + //工位3无到位检测。 + recipe.CurrentStation = stationNum; + return; + } + #endregion + + //数组起始索引是0,工位起始ID是1。 + if (conveyer.HaveVessel[stationNum-1]) + { + recipe.CurrentStation = stationNum; + ushort[] materialList=new ushort[14]; + //获取工位需要的配料数据。 + if (recipe.MaterialData.ContainsKey(stationNum)) + { + materialList = recipe.MaterialData[stationNum]; + } + //如果该工位不需要配料,直接完成就行。 + else + { + recipe.BatchStatus[stationNum] = BatchStep.BatchCompleted; + recipe.IsMakeComplete[stationNum - 1] = true; + logService.LogRunInfo($"参数值为[{stationNum}],该配方无该工位配料需求。"); + return; + } + //配料完成的上升沿检测。 + var completeTrig =RTrig.GetInstance($"Batchers[{stationNum}].BatchComplete").Start(batchers[stationNum].BatchComplete); + + //配料流程。 + switch (recipe.BatchStatus[stationNum]) + { + case BatchStep.WaitBatch: + recipe.BatchStatus[stationNum] = BatchStep.WriteBatchParam; + break; + case BatchStep.WriteBatchParam: + if (materialList is not null && materialList.Length == 14) + { + if (batchers[stationNum].WriteBatchData(materialList)) + { + recipe.BatchStatus[stationNum] = BatchStep.StartBatch; + logService.LogRunInfo($"配方【{recipe.Name}】写入工位【{stationNum}】的下料参数【{String.Join(',',materialList)}】成功。"); + } + else + { + logService.LogRunInfo($"配方【{recipe.Name}】写入工位【{stationNum}】的下料参数失败,稍后重试。"); + await Task.Delay(3000); + } + } + else + { + logService.LogRunInfo($"配方【{recipe.Name}】写入工位【{stationNum}】的下料参数失败,参数长度错误或为Null。"); + return; + } + break; + case BatchStep.StartBatch: + if (batchers[stationNum].StartBatching()) + { + recipe.BatchStatus[stationNum] = BatchStep.WaitBatchComplete; + logService.LogRunInfo($"配方【{recipe.Name}】工位【{stationNum}】的开始配料,等待配料完成信号上升沿。"); + } + else + { + logService.LogRunInfo($"配方【{recipe.Name}】写入工位【{stationNum}】的开始配料失败,3S后重试。"); + await Task.Delay(3000); + } + break; + case BatchStep.WaitBatchComplete: + //先延时,以免味魔方还没开始工作,未把配料完成写为false。 + //await Task.Delay(500); + //if (batchers[stationNum].BatchComplete) + if (completeTrig) + { + logService.LogRunInfo($"配方【{recipe.Name}】工位【{stationNum}】的配料完成。"); + recipe.BatchStatus[stationNum] = BatchStep.BatchCompleted; + } + break; + case BatchStep.BatchCompleted: + recipe.IsMakeComplete[stationNum - 1] = true; + break; + } + } + else + { + logService.LogRunInfo($"配方【{recipe.Name}】工位【{stationNum}】未检测到容器到位,请检查,3秒后重新检测。"); + await Task.Delay(3000); + } + } + + private async Task MoveOnceAndBatach(RecipeData recipe,int stationNum) + { + global.MoveConveyerStep = MoveConveyer.WaitMove; + while (global.MoveConveyerStep != MoveConveyer.MoveComplete) + { + var moveCompleteTrig = RTrig.GetInstance("MoveCompleted").Start(conveyer.MoveComplete); + switch (global.MoveConveyerStep) + { + case MoveConveyer.WaitMove: + if (conveyer.MoveOnce()) + { + logService.LogRunInfo($"配方【{recipe.Name}】控制传送带去下个工位,等待动作完成信号上升沿。"); + global.MoveConveyerStep = MoveConveyer.Moveing; + } + else + { + logService.LogRunInfo($"配方【{recipe.Name}】控制传送带去下个工位失败,3S后重试。"); + await Task.Delay(3000); + } + break; + case MoveConveyer.Moveing: + if (moveCompleteTrig) + { + logService.LogRunInfo($"配方【{recipe.Name}】控制传送带移动结束。"); + while (recipe.IsMakeComplete[stationNum - 1] == false) + { + await StationBatching(recipe, stationNum); + } + global.MoveConveyerStep = MoveConveyer.MoveComplete; + } + break; + case MoveConveyer.MoveComplete: + //logService.LogRunInfo($"配方【{recipe.Name}】控制传送带移动结束。"); + //await StationBatching(recipe, stationNum); + break; + } + } + + } + /// + /// 设置相应设备ID的配料机的通讯参数。 + /// + /// 该设备对应的工位ID。 + /// IP地址 + /// 端口号,默认为502。 + private void SetBatcherComm(int id,string ip,int port=502) + { + if (batchers.ContainsKey(id)) + { + batchers[id].SetCommParam(id, ip, port); + } + else + { + logService.LogDebugInfo($"设置配料机设备【{id}】的通讯参数失败,未在集合中找到此ID对应的设备。"); + } + } + + private void ActionRegister() + { + ActionManage.GetInstance.Register(new Func(() => + { + //目前如果工位1 没有碗或者当前没配方就可以下配方。 + bool result =! (conveyer.HaveVessel[0]) || (currentRecipe==null); + return result; + }), "CanIssueRecipe", true); + } + /// + /// 传送带和配料机之间的信号交互。 + /// + private void InterActive() + { + #region 配料机 + + #endregion + + #region 传送带 + conveyer.AllowMove = conveyer.MoveComplete; + #endregion + } + + private void SingleDetect() + { + //TODO:上升沿信号检测。 + } + } + +} diff --git a/BPA.SingleDevice/Interface/IBatchcer.cs b/BPA.SingleDevice/Interface/IBatchcer.cs new file mode 100644 index 0000000..6914795 --- /dev/null +++ b/BPA.SingleDevice/Interface/IBatchcer.cs @@ -0,0 +1,48 @@ +using MongoDB.Driver; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BPA.SingleDevice.Interface +{ + public interface IBatchcer + { + /// + /// 设备ID + /// + public int ID { get; set; } + /// + /// 配料完成 + /// + public bool BatchComplete { get; set; } + /// + /// 允许下料。 + /// + public bool AllowBatching { get; set; } + /// + /// 是否连接。 + /// + bool IsConnected { get; } + /// + /// 设置通讯参数 + /// + void SetCommParam(int id,string ip, int port = 502); + /// + /// 写入下料数据。 + /// + /// + /// + bool WriteBatchData(ushort[] value); + /// + /// 开始配料 + /// + /// + bool StartBatching(); + /// + /// 设备初始化 + /// + Task Initial(); + } +} diff --git a/BPA.SingleDevice/Interface/IConveyer.cs b/BPA.SingleDevice/Interface/IConveyer.cs new file mode 100644 index 0000000..6c44f1f --- /dev/null +++ b/BPA.SingleDevice/Interface/IConveyer.cs @@ -0,0 +1,84 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BPA.SingleDevice.Interface +{ + + public interface IConveyer + { + /// + /// 设备ID + /// + public int ID { get; set; } + /// + /// 位置有容器,这个程序里容器是碗。 + /// + bool[] HaveVessel { get; set; } + /// + /// 寸动是否反转,值为1时是反转,为0时则为正转。 + /// + int IsReverse { get;set; } + /// + /// 寸动速度。 + /// + float InchSpeed { get; set; } + /// + /// 传动带移动速度。 + /// + float MoveSpeed { get; set; } + /// + /// 加速时间,一般不改动。 + /// + int AccTime { get; set; } + /// + /// 传动带移动一次的长度,单位:脉冲。 + /// + int MoveLength { get; set; } + /// + /// 移动结束。 + /// + bool MoveComplete { get; set; } + /// + /// 是否连接。 + /// + bool IsConnected { get;} + /// + /// 允许移动。 + /// + bool AllowMove { get; set; } + /// + /// 设备初始化 + /// + Task Initial(); + /// + /// 设置通讯参数 + /// + void SetCommParam(int id, string ip, int port = 502); + /// + /// 寸动【调试状态】 + /// + void InchMove(); + /// + /// 设置寸动参数 + /// + /// 是否反转 + /// 寸动速度 + /// 设置是否成功 + bool SetInchParam(int isReverse,float inchSpeed); + /// + /// 设置移动参数 + /// + /// 移动速度 + /// 移动加速时间 + /// 移动长度 + /// 设置是否成功 + bool SetMoveParam(float moveSpeed, int accTime, int moveLength); + /// + /// 移动一次。 + /// + bool MoveOnce(); + } +} diff --git a/BPA.SingleDevice/Interface/IProcessControl.cs b/BPA.SingleDevice/Interface/IProcessControl.cs new file mode 100644 index 0000000..68b5e58 --- /dev/null +++ b/BPA.SingleDevice/Interface/IProcessControl.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BPA.SingleDevice.Interface +{ + public interface IProcessControl + { + /// + /// 初始化即开始。 + /// + void Inital(); + } +} diff --git a/BPA.SingleDevice/Json/ConnectConfig.cs b/BPA.SingleDevice/Json/ConnectConfig.cs new file mode 100644 index 0000000..48f4fba --- /dev/null +++ b/BPA.SingleDevice/Json/ConnectConfig.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BPA.SingleDevice.Json +{ + public class ConnectConfig + { + + } + + public class BatcherConfig + { + /// + /// 对应工位ID + /// + public int StationID { get; set; } + /// + /// IP地址 + /// + public string IP { get; set; } + /// + /// 端口号 + /// + public int Port { get; set; } + + } +} diff --git a/BPA.SingleDevice/Services/ILogService.cs b/BPA.SingleDevice/Services/ILogService.cs index 0cef42e..fcd7023 100644 --- a/BPA.SingleDevice/Services/ILogService.cs +++ b/BPA.SingleDevice/Services/ILogService.cs @@ -21,6 +21,6 @@ namespace BPA.SingleDevice.Services void LogRecipeCompleteInfo(string info); void LogDebugInfo(string info); - Task> GetAllLog(); + Task> GetAllLog() where T:LogBase; } } diff --git a/BPA.SingleDevice/Services/LogService.cs b/BPA.SingleDevice/Services/LogService.cs index b1f6c12..61f6b90 100644 --- a/BPA.SingleDevice/Services/LogService.cs +++ b/BPA.SingleDevice/Services/LogService.cs @@ -132,7 +132,7 @@ namespace BPA.SingleDevice.Services } } - public async Task> GetAllLog() + public async Task> GetAllLog() where T:LogBase { var logs= await sqlHelper.GetListAsync(); if (logs.IsSuccess) diff --git a/BPA.SingleDevice/View/AddRawMaterialDialogView.xaml b/BPA.SingleDevice/View/AddRawMaterialDialogView.xaml index 51a1028..cb57591 100644 --- a/BPA.SingleDevice/View/AddRawMaterialDialogView.xaml +++ b/BPA.SingleDevice/View/AddRawMaterialDialogView.xaml @@ -48,7 +48,7 @@ HorizontalAlignment="Right" FontSize="16" Foreground="#ddd" - Text="设备编号:" /> + Text="设备对应工位:" /> + + + + + + + +