123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583 |
- using DbCommon.BusinessCore.BaseCore;
- using DbCommon.Enties.DbModels;
- using Mapster;
- using ProjectManagementSystem.Common.Config;
- using ProjectManagementSystem.Common.Extenions;
- using ProjectManagementSystem.Common.Logger;
- using ProjectManagementSystem.Device.Command;
- using ProjectManagementSystem.Device.CommandCallback;
- using ProjectManagementSystem.Device.Core;
- using System;
- using System.Collections.Concurrent;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading;
- using System.Threading.Tasks;
- namespace ProjectManagementSystem.Common.Core
- {
- public class DeviceControl
- {
- private static DeviceControl m_instance;
- private CommandRoller commandRollerQuery = new CommandRoller();
- public CasunCommunication Communication { get; private set; }
- public static DeviceControl Instance
- {
- get
- {
- if (m_instance == null)
- {
- m_instance = new DeviceControl();
- if (!m_instance.Initialize())
- {
- m_instance = null;
- }
- }
- return m_instance;
- }
- }
- private DeviceControl()
- {
- }
- private bool Initialize()
- {
- string ipAddress = Function.AppSetting.TryGetValue<string>("ListenIp");
- int port = Function.AppSetting.TryGetValue<int>("ListenPort");
- string comPortName = Function.AppSetting.TryGetValue<string>("ComPortName");
- Communication = new CasunCommunication();
- Communication.OnInfoRoller += Communication_OnInfoRoller;
- Communication.OnInfoIO += Communication_OnInfoIO;
- Communication.OnInfoBox += Communication_OnInfoBox;
- Communication.OnInfoBoxRelease += Communication_OnInfoBoxRelease;
- Communication.OnInfoAgv += Communication_OnInfoAgv;
- if (!string.IsNullOrEmpty(ipAddress))
- {
- var tcp = new CommunicationTcp(ipAddress, port);
- tcp.OnLogMsg += LogMsg;
- tcp.DataReceived += (addr, data) => Communication.Handling(addr, data);
- tcp.Start();
- if (tcp.IsStart) { Communication.Communications.Add(tcp); }
- else { return false; }
- var udp = new CommunicationUdp(ipAddress, port);
- udp.OnLogMsg += LogMsg;
- udp.DataReceived += (addr, data) => Communication.Handling(addr, data);
- udp.Start();
- if (udp.IsStart) { Communication.Communications.Add(udp); }
- else { return false; }
- }
- if (!string.IsNullOrEmpty(comPortName))
- {
- var com = new CommunicationCom(comPortName, 9600);
- com.OnLogMsg += LogMsg;
- com.DataReceived += (addr, data) => Communication.Handling(addr, data);
- com.Start();
- if (com.IsStart) { Communication.Communications.Add(com); }
- else { return false; }
- }
- var vcu = CommunicationVcu.Instance;
- vcu.OnLogMsg += LogMsg;
- vcu.DataReceived += (addr, data) => Communication.Handling(addr, data);
- Communication.Communications.Add(vcu);
- CLog.Instance.SystemLog.WriteDebug($"DeviceControl已启动");
- return true;
- }
- private void Communication_OnInfoAgv(InfoAgv info)
- {
- CLog.Instance.GetAgvLog(info.AgvId).WriteDebug($"{info.AgvId}# M:{info.Mark} R:{info.Route} S:0x{info.Status:X2}({info.StatusEnum}) A:0x{info.Alarm:X2}({info.AlarmText})");
- }
- private void Communication_OnInfoBoxRelease(InfoBoxRelease info)
- {
- if (info.BoxReleaseLightOn)
- {
- CLog.Instance.SystemLog.WriteInfo($"放行盒已亮灯,地标{info.Mark} 路线{info.Route} AGV{info.AgvId}");
- }
- if (info.BoxReleaseAgv)
- {
- CLog.Instance.SystemLog.WriteInfo($"放行盒已放行,地标{info.Mark} 路线{info.Route} AGV{info.AgvId}");
- }
- }
- private void Communication_OnInfoBox(InfoBox info)
- {
- if (info.BoxCalled || info.BoxCancelCall)
- {
- CLog.Instance.SystemLog.WriteInfo($"线路{info.Route} 叫料{info.BoxCalled} 叫料取消{info.BoxCancelCall}");
- //RouteCalled.Instance.Call(info.Adapt<InfoBox>());
- }
- }
- private void Communication_OnInfoIO(InfoIO info)
- {
- }
- private void Communication_OnInfoRoller(InfoRoller info)
- {
- }
- private void LogMsg(string obj, Exception ex)
- {
- if (ex == null)
- {
- CLog.Instance.DeviceLog.WriteDebug(obj);
- }
- else
- {
- CLog.Instance.DeviceLog.WriteException("DeviceControl", obj, ex);
- }
- }
- #region IO透传功能
- private int GetIOAddressIndex(string address)
- {
- //解析地址,格式Y1-Y8(输出信号)
- var invalidValue = -1;
- if (string.IsNullOrEmpty(address)) return invalidValue;
- if (!int.TryParse(address.Substring(1), out int index))
- {
- return invalidValue;
- }
- index--;
- if (index < 0)
- {
- return invalidValue;
- }
- return index;
- }
- public bool CheckInputIO(int id, string[] addressArray, bool[] bitArray, out string msg)
- {
- msg = null;
- for (int i = 0; i < addressArray.Length; i++)
- {
- string plcAddr = addressArray[i];
- bool plcValue = bitArray[i];
- var result2 = GetInputIO(id, addressArray[i]);
- if (result2.Item1 == false
- || result2.Item2 != plcValue)
- {
- msg = $"等待信号({plcAddr}={plcValue})";
- return false;
- }
- }
- return true;
- }
- public bool CheckOutputIO(int id, string[] addressArray, bool[] bitArray, out string msg)
- {
- msg = null;
- for (int i = 0; i < addressArray.Length; i++)
- {
- string plcAddr = addressArray[i];
- bool plcValue = bitArray[i];
- var result = GetOutputIO(id, addressArray[i]);
- if (result.Item1 == false
- || result.Item2 != plcValue)
- {
- msg = $"写入失败({plcAddr}写入{plcValue})";
- return false;
- }
- }
- return true;
- }
- public Tuple<bool, bool> GetInputIO(int id, string address)
- {
- int index = GetIOAddressIndex(address);
- if (index < 0) return new Tuple<bool, bool>(false, false);
- if (!Communication.InfoIODictionary.TryGetValue(id, out var info))
- {
- return new Tuple<bool, bool>(false, false);
- }
- if (!info.DataValid) return new Tuple<bool, bool>(false, false);
- bool bitTrue = (info.Input & (0x01 << index)) > 0;
- return new Tuple<bool, bool>(true, bitTrue);
- }
- public Tuple<bool, bool> GetOutputIO(int id, string address)
- {
- int index = GetIOAddressIndex(address);
- if (index < 0) return new Tuple<bool, bool>(false, false);
- if (!Communication.InfoIODictionary.TryGetValue(id, out var info))
- {
- return new Tuple<bool, bool>(false, false);
- }
- if (!info.DataValid) return new Tuple<bool, bool>(false, false);
- bool bitTrue = (info.Output & (0x01 << index)) > 0;
- return new Tuple<bool, bool>(true, bitTrue);
- }
- public void SetOutputIO(int id, string address, bool bit)
- {
- SetOutputIO(id, new string[] { address }, new bool[] { bit });
- }
- public void SetOutputIO(int id, string[] addressArray, bool[] bitArray)
- {
- if (addressArray == null || addressArray.Length == 0) return;
- if (bitArray == null || bitArray.Length == 0) return;
- int[] indexArray = new int[addressArray.Length];
- for (int i = 0; i < addressArray.Length; i++)
- {
- string address = addressArray[i];
- indexArray[i] = GetIOAddressIndex(address);
- }
- SetOutputIO(id, indexArray, bitArray);
- }
- public bool SetOutputIO_ThenCheck(int id, string[] addressArray, bool[] bitArray, out string msg)
- {
- msg = null;
- SetOutputIO(id, addressArray, bitArray);
- for (int i = 0; i < 50; i++)
- {
- if (CheckOutputIO(id, addressArray, bitArray, out msg))
- {
- return true;
- }
- Thread.Sleep(20);
- }
- return false;
- }
- public void SetOutputIO(int id, int[] indexArray, bool[] bitArray)
- {
- if (!Communication.InfoIODictionary.TryGetValue(id, out var info))
- {
- return;
- }
- if (!info.DataValid) return;
- ushort newOutput = info.Output;
- for (int i = 0; i < indexArray.Length; i++)
- {
- int index = indexArray[i];
- if (index < 0)
- {
- return;
- }
- bool bit = bitArray[i];
- if (bit)
- {
- newOutput = (ushort)(newOutput | (0x01 << index));
- }
- else
- {
- newOutput = (ushort)(newOutput & (ushort.MaxValue - (1 << index)));
- }
- }
- SetOutputIO(id, newOutput);
- }
- public void SetOutputIO(int id, ushort output)
- {
- var data = new CommandIO();
- data.TargetID = (byte)id;
- data.Output = output;
- SendCommand(data, id, Communication.InfoIODictionary);
- }
- public void SetOutputIOClear(int id)
- {
- if (Communication.InfoIODictionary.TryGetValue(id, out var info)
- && info.Output != 0)
- {
- SetOutputIO(id, 0);
- CLog.Instance.SystemLog.WriteInfo($"对接盒ID{id},清零输出");
- Thread.Sleep(100);
- }
- }
- #endregion
- #region 滚筒台对接
- public void RollerOperate(int id, ushort code)
- {
- var data = new CommandRoller();
- data.TargetID = (byte)id;
- data.ActionCode = code;
- SendCommand(data, id, Communication.InfoRollerDictionary);
- }
- public void RollerOperateClear(int id)
- {
- var data = new CommandRoller();
- data.TargetID = (byte)id;
- data.Operate = 0;
- data.ActionCode = 0;
- SendCommand(data, id, Communication.InfoRollerDictionary);
- }
- public void RollerActionClear(int id)
- {
- var data = new CommandRoller();
- data.TargetID = (byte)id;
- data.ActionCode = 0;
- SendCommand(data, id, Communication.InfoRollerDictionary);
- }
- public void RollerQuery(int id)
- {
- commandRollerQuery.Function = 0x21;
- commandRollerQuery.TargetID = (byte)id;
- SendCommand(commandRollerQuery, id, Communication.InfoRollerDictionary);
- }
- public void RollerQuery()
- {
- var configList = ExcelConfig.Instance.RouteConfigList;
- for (int i = 0; i < configList.Count; i++)
- {
- var config = configList[i];
- if (config.RollerID > 0)
- {
- RollerQuery(config.RollerID);
- }
- }
- }
- #endregion
- #region 华星滚筒
- public void RollerHxOperate(int id, ushort code)
- {
- var data = new CommandRollerHx();
- data.TargetID = (byte)id;
- data.Function = 0x51;
- data.ActionCode = (byte)code;
- SendCommand(data, id, Communication.InfoRollerHxDictionary);
- }
- public void RollerHxQuery(int id)
- {
- var data = new CommandRollerHx();
- data.TargetID = (byte)id;
- data.Function = 0x53;
- SendCommand(data, id, Communication.InfoRollerHxDictionary);
- }
- #endregion
- #region 报警灯功能
- public void SetAlarmLight(int id, int lightType)
- {
- var data = new CommandAlarmLight();
- data.DeviceId = (byte)id;
- data.LightType = (byte)lightType;
- SendCommand(data, id, Communication.InfoAlarmLightDictionary);
- }
- #endregion
- #region 叫料盒功能
- public void CallBoxQuery(int route)
- {
- var data = new CommandBox();
- data.Route = route;
- data.Function = 0x40;
- SendCommand(data, route, Communication.InfoBoxDictionary);
- }
- public void CallBoxLightOff(int route)
- {
- var data = new CommandBox();
- data.Route = route;
- data.Function = 0x45;
- SendCommand(data, route, Communication.InfoBoxDictionary);
- }
- #endregion
- #region 放行盒功能
- public void ReleaseBoxLightOn(int mark, int route = 0, int agvId = 0)
- {
- var data = new CommandBox();
- data.Mark = mark;
- data.Route = route;
- data.AgvId = (byte)agvId;
- data.Function = 0x35;
- SendCommand(data, mark, Communication.InfoBoxReleaseDictionary);
- }
- public void ReleaseBoxLightOff(int mark, int route = 0, int agvId = 0)
- {
- var data = new CommandBox();
- data.Mark = mark;
- data.Route = route;
- data.AgvId = (byte)agvId;
- data.Function = 0x38;
- SendCommand(data, mark, Communication.InfoBoxReleaseDictionary);
- }
- #endregion
- #region 有轨AGV
- public void ReleaseAgvOnStop(int mark, int route, int agvId)
- {
- var data = new CommandBox();
- data.Mark = mark;
- data.Route = route;
- data.AgvId = (byte)agvId;
- data.Function = 0x37;
- SendCommand(data, agvId, Communication.InfoAgvDictionary);
- }
- public void ReleaseAgvOnStop(int mark, int route, int targetMark, int agvId)
- {
- var data = new CommandBoxRelease();
- data.Mark = mark;
- data.Spare = targetMark;
- data.Route = route;
- data.AgvId = (byte)agvId;
- data.Function = 0x37;
- SendCommand(data, agvId, Communication.InfoAgvDictionary);
- }
- public void ReleaseAgvOnStandby(int mark, int route, int agvId)
- {
- var data = new CommandBox();
- data.Mark = mark;
- data.Route = route;
- data.AgvId = (byte)agvId;
- data.Function = 0x31;
- SendCommand(data, agvId, Communication.InfoAgvDictionary);
- }
- public void RailAgv_Query1061(int agvId = 0)
- {
- var data = new Command1061();
- SendCommand(data, agvId, Communication.InfoAgvDictionary);
- }
- public void RailAgv_Query1063(int fps, int agvId = 0)
- {
- var data = new Command1063();
- data.FPS = fps;
- SendCommand(data, agvId, Communication.InfoAgvDictionary);
- }
- public void RailAgv_Query()
- {
- for (int i = 1; i <= 3; i++)
- {
- RailAgv_Query1063(i);
- Thread.Sleep(100);
- }
- }
- public void RailAgv_StartButton(int agvId)
- {
- RailAgv_Control1071(agvId, 0, 0);
- }
- public void RailAgv_StopButton(int agvId)
- {
- RailAgv_Control1071(agvId, 1, 0);
- }
- public void RailAgv_Control1071(int agvId, int iOperation = 0, int iSpeed = 0)
- {
- var data = new Command1071();
- data.Function = 0x71;
- data.Operation = (byte)iOperation;
- data.Speed = (byte)iSpeed;
- data.AgvId = (byte)agvId;
- SendCommand(data, agvId, Communication.InfoAgvDictionary);
- }
- /// <summary>
- /// 改变AGV速度
- /// </summary>
- /// <param name="agvId">AGV编号</param>
- /// <param name="speed">AGV速度,单位:m/min</param>
- public void RailAgv_SpeedChange(int agvId, decimal speed)
- {
- var data = new CommandBox();
- data.Spare = (int)Math.Round(speed * 100);
- data.AgvId = (byte)agvId;
- data.Function = 0x47;
- SendCommand(data, agvId, Communication.InfoAgvDictionary);
- }
- public void RailAgv_ReleaseAlarm(int agvId, int alarmSec)
- {
- var data = new CommandBox();
- data.Spare = alarmSec;
- data.AgvId = (byte)agvId;
- data.Function = 0x49;
- SendCommand(data, agvId, Communication.InfoAgvDictionary);
- }
- #endregion
- /// <summary>
- /// 根据设备ID查找设备终结点,并向指定终结点发送指令
- /// </summary>
- /// <typeparam name="TKey"></typeparam>
- /// <typeparam name="TValue"></typeparam>
- /// <param name="cmd"></param>
- /// <param name="deviceId"></param>
- /// <param name="infoDict"></param>
- public void SendCommand<TKey, TValue>(IDeviceCommand cmd, TKey deviceId, IDictionary<TKey, TValue> infoDict)
- where TKey : struct
- where TValue : BaseInfo
- {
- string ipAddress = infoDict.TryGetValue(deviceId, out var info) ? info.RemoteEndPoint : null;
- var data = cmd.Serialization();
- Communication.SendCommand(data, ipAddress);
- }
- }
- }
|