1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- using HslCommunication.ModBus;
- using HslCommunication;
- using HslCommunication.BasicFramework;
- using System.Net;
- using System.Threading;
- using System.Collections;
- using System.Timers;
- using HslCommunication.Controls;
- using parkMonitor.entity;
- using parkMonitor.tools;
- using parkMonitor.model;
- using System.Diagnostics;
- using System.Configuration;
- using parkMonitor.server.uiLogServer;
- using parkMonitor.LOG;
- namespace parkMonitor.server
- {
- /// <summary>
- /// PLC通信类
- /// </summary>
- public class PLCLinker : IEquipments
- {
- private Boolean isConnection = false;
- private bool isRecorded = false, exceptionBreak = false, isClosing = false;
- private static string json = "";//读到的数据
- private string json2 = "";//写入的数据
- private PLCMessage plcMsg = new PLCMessage();
- System.Timers.Timer timer;
- //parameteres for plc read function
- private int startAddr = 0;
- private int addrLength = 110;
- /// <summary> plc重连标记位 </summary>
- private int linkCount = 0;
- //plc 基本配置
- private const short PLC_TIME_SCALE = 100;
- private const short LASER_TIME_SCALE = 5000;
- private string ipString;
- private int port;
- private byte station;
- //addresses for machine arm controlling
- private int fetching_startRobot_address;
- private int parking_startRobot_address;
- //addresses for laser data to be written to plc
- private int parkingSpaceID_address;
- //addresses for space info to be written to plc
- private int parkingLaserCenterX_address;
- //parameters(addresses) for Laser monitoring
- private int laser_start_address;
- private int fetch_completed_address;
- private int fetch_completed_acknowledge_address;
- private int fetch_to_address;
- private int frontWheelbase_address;
- private int rearWheelbase_address;
- private int park_completed_address;
- private int park_completed_acknowledge_address;
- private int LASER_RESCAN_COUNT;
- private int LASER_HEARTBEAT_PERIOD;
- private int PLC_refresh_interval;
- /// <summary>
- /// 激光管理list
- /// </summary>
- private List<LaserProcessUnit> laserMgmtList = new List<LaserProcessUnit>();
- private RobotProcessUnit rpu1;
- private List<string> decompressIndex;
- /// <summary>
- /// plc构造函数
- /// </summary>
- public PLCLinker()
- {
- try
- {
- LASER_RESCAN_COUNT = Int32.Parse(ConfigurationManager.AppSettings.Get("laser_rescan_count"));
- LASER_HEARTBEAT_PERIOD = Int32.Parse(ConfigurationManager.AppSettings.Get("laser_countdown"));
- PLC_refresh_interval = Int32.Parse(ConfigurationManager.AppSettings.Get("PLC_refresh_interval"));
- parking_startRobot_address = Int32.Parse(ConfigurationManager.AppSettings.Get("parking_startRobot_address"));
- parkingLaserCenterX_address = Int32.Parse(ConfigurationManager.AppSettings.Get("parkingLaserCenterX_address"));
- parkingSpaceID_address = Int32.Parse(ConfigurationManager.AppSettings.Get("parkingSpaceID_address"));
- park_completed_address = Int32.Parse(ConfigurationManager.AppSettings.Get("park_completed_address"));
- park_completed_acknowledge_address = Int32.Parse(ConfigurationManager.AppSettings.Get("park_completed_acknowledge_address"));
- fetching_startRobot_address = Int32.Parse(ConfigurationManager.AppSettings.Get("fetching_startRobot_address"));
- fetch_to_address = Int32.Parse(ConfigurationManager.AppSettings.Get("fetch_to_address"));
- fetch_completed_address = Int32.Parse(ConfigurationManager.AppSettings.Get("fetch_completed_address"));
- fetch_completed_acknowledge_address = Int32.Parse(ConfigurationManager.AppSettings.Get("fetch_completed_acknowledge_address"));
- frontWheelbase_address = Int32.Parse(ConfigurationManager.AppSettings.Get("frontWheelbase_address"));
- rearWheelbase_address = Int32.Parse(ConfigurationManager.AppSettings.Get("rearWheelbase_address"));
- laser_start_address = Int32.Parse(ConfigurationManager.AppSettings.Get("laser_start_address"));
- rpu1 = new RobotProcessUnit(1, parking_startRobot_address, parkingLaserCenterX_address, parkingSpaceID_address, park_completed_address, park_completed_acknowledge_address, fetching_startRobot_address, fetch_to_address, fetch_completed_address, fetch_completed_acknowledge_address, frontWheelbase_address, rearWheelbase_address);
- //激光管理
- for (int i = 1; i < 20; i++)
- {
- try
- {
- string laser = ConfigurationManager.AppSettings.Get("laser" + i + "_status_address");
- int laser_status_address = Int32.Parse(laser);
- LaserProcessUnit lpu = new LaserProcessUnit(i, laser_start_address, laser_status_address, LASER_RESCAN_COUNT, LASER_HEARTBEAT_PERIOD);
- laserMgmtList.Add(lpu);
- plcMsg.laserMsgList.Add(lpu.laserMsg);
- }
- catch (Exception) { }
- }
- //定义plc被压缩的地址段
- decompressIndex = new List<string>();
- //25-27
- for (int i = 0; i < 3; i++)
- {
- decompressIndex.Add((25 + i).ToString());
- }
- //48-53
- for (int i = 0; i < 6; i++)
- {
- decompressIndex.Add((48 + i).ToString());
- }
- //70-76
- for (int i = 0; i < 7; i++)
- {
- decompressIndex.Add((70 + i).ToString());
- }
- }
- catch (Exception)
- {
- Console.WriteLine("PLC相关配置文件异常");
- }
- }
- //**************************************** PLC读写相关方法 **************************************
- private ModBusTcpClient busTcpClient
- {
- get;
- set;
- }
- private void WriteMessage(string message)
- {
- isRecorded = true;
- //json2 = "[{\"Adress\":\"1\",\"Value\":\"0043\"},{\"Adress\":\"2\",\"Value\":\"0043\"}]";
- json2 = message;
- }
- ///<summary>采集数据显示转json</summary>
- private static void DisplayString_ToJson(string str)
- {
- List<PLCNode> return_Value = new List<PLCNode>();
- if (!string.IsNullOrEmpty(str))
- {
- ArrayList array = GetSeparateSubString(str, 4);
- int Read_Address = 0;//0地址
- return_Value.Clear();
- foreach (string arr in array)
- {
- PLCNode rv = new PLCNode();
- //Console.WriteLine("地址:" + Read_Address + ": " + arr);
- rv.Address = Read_Address.ToString();
- rv.Value = Int32.Parse(arr, System.Globalization.NumberStyles.HexNumber).ToString();//plc数据16进制?
- return_Value.Add(rv);
- Read_Address++;
- }
- }
- json = JsonHelper.SerializeObject(return_Value);//序列化
- //List<PLCValue> prv = JsonHelper.DeserializeJsonToList<PLCValue>(json);
- //Console.WriteLine(json);
- }
- ///<summary>截取</summary>
- private static ArrayList GetSeparateSubString(string txtString, int charNumber)
- {
- ArrayList arrList = new ArrayList();
- string tempStr = txtString;
- for (int i = 0; i < tempStr.Length; i += charNumber)
- {
- if ((tempStr.Length - i) > charNumber)
- {
- arrList.Add(tempStr.Substring(i, charNumber));
- }
- else
- {
- arrList.Add(tempStr.Substring(i));
- }
- }
- return arrList;
- }
- private void InitTimer()
- {
- try
- {
- timer = new System.Timers.Timer(PLC_refresh_interval);
- }
- catch (Exception)
- {
- timer = new System.Timers.Timer(PLC_TIME_SCALE);
- }
- timer.AutoReset = true;
- timer.Enabled = true;
- timer.Elapsed += new ElapsedEventHandler(TimerUp);
- }
- ///<summary>实时采集</summary>
- private void TimerUp(object sender, System.Timers.ElapsedEventArgs e)
- {
- try
- {
- if (isConnection)
- {
- //从哪个地址开始,读取长度
- PLC_Read((ushort)startAddr, (ushort)addrLength);
- //LaserMonitor();
- }
- else
- {
- if (linkCount-- >= 0)
- {
- Task.Factory.StartNew(() =>
- {
- while (!isClosing)
- {
- Console.WriteLine("尝试重连plc");
- UILogServer.ins.log("尝试重连plc");
- LinkStart();
- Thread.Sleep(10000);
- if (isConnection)
- {
- linkCount = 0;
- break;
- }
- }
- });
- linkCount = -1;
- }
- }
- }
- catch (Exception ex)
- {
- Console.WriteLine(ex.Message);
- }
- }
- ///<summary>读取</summary>
- private void PLC_Read(ushort address, ushort length)
- {
- try
- {
- OperateResult<byte[]> read = busTcpClient.ReadRegister(address, length);
- if (read.IsSuccess)
- {
- string returned_value = SoftBasic.ByteToHexString(read.Content);
- DisplayString_ToJson(returned_value);
- }
- else
- {
- if (!exceptionBreak)
- {
- AsyncCmdServer.ins.send(AsyncCmdType.PLCReadException);
- Console.WriteLine("读取失败");
- isConnection = false;
- exceptionBreak = true;
- }
- }
- }
- catch (Exception ex)
- {
- Console.WriteLine(ex.Message);
- }
- }
- ///<summary>写入</summary>
- private void WriteJson(string json)
- {
- try
- {
- if (!string.IsNullOrEmpty(json))
- {
- List<PLCNode> PLC_Value = JsonHelper.DeserializeJsonToList<PLCNode>(json);
- foreach (var item in PLC_Value)
- {
- //WriteResultRender(busTcpClient.WriteRegister(ushort.Parse(item.Address), ushort.Parse(item.Value)), item.Address);
- busTcpClient.WriteRegister(ushort.Parse(item.Address), ushort.Parse(item.Value));
- Thread.Sleep(20);
- }
- }
- }
- catch (Exception ex)
- {
- Console.WriteLine(ex.Message);
- }
- }
- ///<summary>写入判断</summary>
- private static void WriteResultRender(OperateResult result, string address)
- {
- if (result.IsSuccess)
- {
- Console.WriteLine("写入成功");
- }
- else
- {
- Console.WriteLine("写入失败");
- }
- }
- ///<summary>地址-值写入plc</summary>
- private void SendtoPLC(string addr, string value)
- {
- PLCNode wrv = new PLCNode();
- wrv.Address = addr;
- wrv.Value = value;
- json2 = "[" + JsonHelper.SerializeObject(wrv) + "]";
- WriteMessage(json2);
- if (isConnection && isRecorded)
- {
- WriteJson(json2);
- isRecorded = false;
- }
- }
- /// <summary>启动与plc的连接</summary>
- private void LinkStart()
- {
- if (busTcpClient != null)
- {
- busTcpClient.ConnectClose();
- }
- busTcpClient = new ModBusTcpClient(ipString, port, station);
- try
- {
- OperateResult connect = busTcpClient.ConnectServer();
- if (connect.IsSuccess)
- {
- AsyncCmdServer.ins.send(AsyncCmdType.PLCOnline);
- Console.WriteLine("连接成功");
- UILogServer.ins.log("PLC连接成功");
- isConnection = true;
- linkCount = 0;
- }
- else
- {
- AsyncCmdServer.ins.send(AsyncCmdType.PLCOffline);
- Console.WriteLine("连接失败,重试");
- UILogServer.ins.error("PLC连接失败,重试");
- isConnection = false;
- }
- }
- catch (Exception ex)
- {
- Console.WriteLine(ex.Message);
- }
- InitTimer();//启动计时器
- }
- /// <summary>将plc地址块完全解压</summary>
- private List<PLCNode> ListDecompression(List<PLCNode> plcList, List<string> decompressIndex)
- {
- List<string> temp = new List<string>();
- List<PLCNode> decomPlcList = new List<PLCNode>();
- if (plcList != null && addrLength > 100)
- {
- try
- {
- for (int i = 0; i < plcList.Count; i++)
- {
- if (!decompressIndex.Contains(plcList[i].Address))
- {
- temp.Add(plcList[i].Value);
- }
- //定位三个被压缩区域
- else
- {
- //默认LSB优先
- int value = Int32.Parse(plcList[i].Value);
- int count = 16;
- while (count-- > 0)
- {
- temp.Add((value & 0x01).ToString());
- value = value >> 1;
- }
- }
- }
- }
- catch (Exception) { }
- }
- for (int i = 0; i < temp.Count; i++)
- {
- decomPlcList.Add(new PLCNode(i.ToString(), temp[i]));
- }
- return decomPlcList;
- }
- //************************************ 雷达相关方法 **************************************
- /*
- * 激光监听PARK_STATUS, 0等待,1启动,其余异常
- * PARK_STATUS 控制:
- * 核心线程调用SetMessage将其置1,plc线程检测到PARK_COMPLETED则复位到0,(核心将plc“PARK_COMPLETED”复位),其余异常情况由监控或核心线程置2或其他值
- *
- * 读到LASER_STATUS(扫摆激光状态),监控线程显示该状态,一旦为状态5,处理完成后置0
- *
- * */
- private void LaserMonitor()
- {
- try
- {
- if (plcMsg.originalPlcList != null)
- {
- foreach (LaserProcessUnit lds in laserMgmtList)
- {
- foreach (PLCNode p in plcMsg.originalPlcList)
- {
- int addr = Int32.Parse(p.Address);
- int value = Int32.Parse(p.Value);
- lds.LaserStatusChecking(addr, value);
- }
- lds.LaserRecord(plcMsg.originalPlcList);
- }
- }
- else
- {
- AsyncCmdServer.ins.send(AsyncCmdType.PLCReadException);
- return;
- }
- Thread.Sleep(200);
- }
- catch (Exception)
- {
- AsyncCmdServer.ins.send(AsyncCmdType.PLCReadException);
- return;
- }
- }
- private void UpdateLaserStatus()
- {
- try
- {
- lock (plcMsg)
- {
- if (plcMsg.originalPlcList != null)
- {
- foreach (LaserProcessUnit lds in laserMgmtList)
- {
- foreach (PLCNode p in plcMsg.originalPlcList)
- {
- int addr = Int32.Parse(p.Address);
- int value = Int32.Parse(p.Value);
- lds.UpdateLaserStatus(addr, value);
- }
- }
- }
- else
- {
- AsyncCmdServer.ins.send(AsyncCmdType.PLCReadException);
- return;
- }
- }
- }
- catch (Exception)
- {
- AsyncCmdServer.ins.send(AsyncCmdType.PLCReadException);
- return;
- }
- }
- private void WaitForLaserReady(LaserProcessUnit lpuTemp)
- {
- bool jumpOut = false;
- MyTimer mt = new MyTimer();
- mt.StartTiming();
- lock (lpuTemp)
- {
- while (!jumpOut)
- {
- Thread.Sleep(1000);
- if (plcMsg != null && plcMsg.originalPlcList.Count > lpuTemp.laser_status_address)
- {
- foreach (PLCNode node in plcMsg.originalPlcList)
- {
- //判断激光空闲状态
- lock (lpuTemp.laserMsg)
- {
- if (node.Address.Equals(lpuTemp.laser_status_address.ToString()) && (node.Value.Equals("254") || node.Value.Equals("255")) && !lpuTemp.laserMsg.occupied)
- {
- lpuTemp.laserMsg.occupied = true;
- jumpOut = true;
- UILogServer.ins.log("获取摆扫激光空闲状态,准备启动激光");
- break;
- }
- }
- }
- }
- mt.EndTiming();
- int activationCount = 0;
- if (mt.IsLonger(15, 1, false, out activationCount))
- {
- if (activationCount == 1)
- {
- UILogServer.ins.info("启动前暂未获取摆扫激光空闲状态,继续等待");
- }
- if (MyTimer.restart && !mt.rolledBack)
- {
- mt.rolledBack = true;
- UILogServer.ins.error("启动前超时未能获取摆扫空闲状态,请检查设备");
- }
- }
- }
- }
- }
- //***************公有方法****************
- /// <summary>
- /// 获取plc数据与激光数据
- /// </summary>
- /// <returns>返回plc消息实例</returns>
- public AbstractMessage GetMessage()
- {
- try
- {
- plcMsg.originalPlcList = JsonHelper.DeserializeJsonToList<PLCNode>(json);
- if (decompressIndex != null && decompressIndex.Count != 0)
- {
- plcMsg.extendedPlcList = ListDecompression(plcMsg.originalPlcList, decompressIndex);
- }
- return (PLCMessage)plcMsg.Clone();
- }
- catch (Exception)
- {
- AsyncCmdServer.ins.send(AsyncCmdType.PLCReadException);
- return new PLCMessage();
- }
- }
- /// <summary>
- /// 传入信息写入plc
- /// </summary>
- /// <param name="message">plc消息则传入plc,控制消息则根据指令编号分别处理</param>
- public void SetMessage(AbstractMessage message)
- {
- if (message.GetType().Equals(typeof(PLCMessage)))
- {
- PLCMessage ps = (PLCMessage)message;
- for (int i = 0; i < ps.originalPlcList.Count; i++)
- {
- SendtoPLC(ps.originalPlcList[i].Address, ps.originalPlcList[i].Value);
- }
- }
- else if (message.GetType().Equals(typeof(PLCNode)))
- {
- PLCNode pv = (PLCNode)message;
- SendtoPLC(pv.Address, pv.Value);
- }
- else if (message.GetType().Equals(typeof(ControlMessage)))
- {
- ControlMessage cm = (ControlMessage)message;
- if (cm != null && cm.status != 0)
- {
- switch (cm.status)
- {
- //停车startLaser--park_command_address
- case 1:
- //start laser scanning for parking
- LaserProcessUnit lpuTemp = null;
- Task.Factory.StartNew(() =>
- {
- string laser_start_addr = "";
- foreach (LaserProcessUnit lpu in laserMgmtList)
- {
- if (cm.laserID == lpu.id)
- {
- lpuTemp = lpu;
- laser_start_addr = lpu.laser_start_address.ToString();
- break;
- }
- }
- if (laser_start_addr == "")
- return;
- lock (lpuTemp)
- {
- WaitForLaserReady(lpuTemp);
- SendtoPLC(laser_start_addr, "0");
- lpuTemp.laserMsg.licenseNum = cm.LicenseNum;
- Thread.Sleep(300);
- SendtoPLC(laser_start_addr, "1");
- Thread.Sleep(100);
- //SendtoPLC("1", "1");//停车指令置1
- Log.WriteLog("已发送激光" + lpuTemp.id + "启动指令");
- UILogServer.ins.info("已发送激光" + lpuTemp.id + "启动指令");
- }
- });
- //Console.WriteLine("扫摆激光启动");
- break;
- //停车激光的6个数据,停车机械手,车位信息4个
- case 2:
- if (cm.RobotID == 1)
- {
- //停车指令置1
- SendtoPLC("1", "1");
- //停车启动机械手
- SendtoPLC(rpu1.parking_startRobot_address.ToString(), "1");
- //自动或手动输入激光雷达数据
- SendtoPLC(rpu1.parking_laserCenterX_address.ToString(), cm.centerX);
- SendtoPLC((rpu1.parking_laserCenterX_address + 1).ToString(), cm.centerY);
- SendtoPLC((rpu1.parking_laserCenterX_address + 2).ToString(), cm.angleA);
- //车位信息
- SendtoPLC(rpu1.parkingSpaceID_address.ToString(), cm.parkingSpaceID);
- SendtoPLC((rpu1.parkingSpaceID_address + 1).ToString(), cm.parkingSpaceX);
- SendtoPLC((rpu1.parkingSpaceID_address + 2).ToString(), cm.parkingSpaceY);
- SendtoPLC((rpu1.parkingSpaceID_address + 3).ToString(), cm.parkingSpaceZ);
- }
- break;
- //停车完成归零--park_completed_address
- case 3:
- if (cm.RobotID == 1)
- {
- //SendtoPLC(rpu1.park_completed_address.ToString(), "0");//停车完成复位
- SendtoPLC(rpu1.park_completed_acknowledge_address.ToString(), "0");
- SendtoPLC("1", "0");//停车指令置0
- //Console.WriteLine("停车完成");
- }
- break;
- //取车机械手,车位信息4个
- case 4:
- if (cm.RobotID == 1 && cm.fetchPosition != 0)
- {
- //前后轮轮距
- SendtoPLC(rpu1.frontWheelbase.ToString(), cm.frontWheelbase.ToString());
- SendtoPLC(rpu1.rearWheelbase.ToString(), cm.rearWheelbase.ToString());
- //取至区域
- //SendtoPLC(rpu1.fetch_to_address.ToString(), pm.fetchPosition.ToString());
- SendtoPLC(rpu1.fetch_to_address.ToString(), cm.parkingSpaceX);
- //车位信息
- SendtoPLC(rpu1.parkingSpaceID_address.ToString(), cm.parkingSpaceID);
- SendtoPLC((rpu1.parkingSpaceID_address + 1).ToString(), cm.parkingSpaceX);
- SendtoPLC((rpu1.parkingSpaceID_address + 2).ToString(), cm.parkingSpaceY);
- SendtoPLC((rpu1.parkingSpaceID_address + 3).ToString(), cm.parkingSpaceZ);
- SendtoPLC(rpu1.fetching_startRobot_address.ToString(), "1");
- }
- break;
- case 5:
- if (cm.RobotID == 1)
- {
- //取车完成复位
- SendtoPLC(rpu1.fetch_completed_acknowledge_address.ToString(), "0");
- SendtoPLC(rpu1.fetch_to_address.ToString(), "0");
- }
- break;
- default: Console.WriteLine("输入plc数据异常"); break;
- }
- }
- }
- else
- {
- AsyncCmdServer.ins.send(AsyncCmdType.PLCWriteException);
- Debug.WriteLine("输入字符串有误");
- }
- }
- /// <summary>
- /// 开启激光线程与模拟plc自动重置子线程
- /// </summary>
- public void Start()
- {
- exceptionBreak = false; linkCount = 0;
- try
- {
- ipString = ConfigurationManager.AppSettings.Get("PLC_ip_address");
- port = Int32.Parse(ConfigurationManager.AppSettings.Get("PLC_port"));
- station = (byte)Int32.Parse(ConfigurationManager.AppSettings.Get("PLC_station"));
- startAddr = Int32.Parse(ConfigurationManager.AppSettings.Get("PLC_start_address"));
- addrLength = Int32.Parse(ConfigurationManager.AppSettings.Get("PLC_address_length"));
- }
- catch (Exception) { UILogServer.ins.error("PLC配置文件异常"); }
- LinkStart();
- Task.Factory.StartNew(() =>
- {
- while (!isClosing)
- {
- LaserMonitor();
- }
- });
- Task.Factory.StartNew(() =>
- {
- while (!isClosing)
- {
- UpdateLaserStatus();
- }
- });
- //模拟plc与激光自动操作
- Task.Factory.StartNew(() =>
- {
- laserAnim();
- });
- Task.Factory.StartNew(() =>
- {
- wheelbaseAnim();
- });
- Task.Factory.StartNew(() =>
- {
- autoCycling();
- });
- }
- /// <summary>
- /// 系统停止
- /// </summary>
- public void Stop()
- {
- exceptionBreak = false; isClosing = true;
- busTcpClient.ConnectClose();//stop释放资源
- //throw new NotImplementedException();
- }
- private void laserAnim()
- {
- bool laserWorking = false;
- while (!isClosing)
- {
- if (plcMsg.originalPlcList != null)
- {
- //模拟plc与激光操作
- foreach (PLCNode p in plcMsg.originalPlcList)
- {
- int addr = Int32.Parse(p.Address);
- int value = Int32.Parse(p.Value);
- //模拟摆扫激光
- if (laserMgmtList.Count != 0)
- {
- if (addr == laser_start_address)
- {
- //心跳
- if (value == 0)
- {
- laserWorking = false;
- SendtoPLC(laserMgmtList[0].laser_status_address.ToString(), "254");
- Thread.Sleep(200);
- SendtoPLC(laserMgmtList[0].laser_status_address.ToString(), "255");
- Thread.Sleep(200);
- }
- //模拟测量
- else
- {
- if (!laserWorking)
- {
- SendtoPLC(laserMgmtList[0].laser_status_address.ToString(), "1");
- Thread.Sleep(300);
- SendtoPLC(laserMgmtList[0].laser_status_address.ToString(), "2");
- Thread.Sleep(500);
- SendtoPLC((laserMgmtList[0].laser_status_address + 1).ToString(), (new Random(DateTime.Now.Millisecond).Next(4000, 7000)).ToString());
- Thread.Sleep(1);
- SendtoPLC((laserMgmtList[0].laser_status_address + 2).ToString(), (new Random(DateTime.Now.Millisecond).Next(4000, 7000)).ToString());
- Thread.Sleep(1);
- SendtoPLC((laserMgmtList[0].laser_status_address + 3).ToString(), (new Random(DateTime.Now.Millisecond).Next(90, 150)).ToString());
- Thread.Sleep(1);
- SendtoPLC(laserMgmtList[0].laser_status_address.ToString(), "3");
- Thread.Sleep(500);
- }
- laserWorking = true;
- }
- }
- }
- }
- }
- Thread.Sleep(100);
- }
- }
- private void wheelbaseAnim()
- {
- bool working = false;
- while (!isClosing)
- {
- if (plcMsg.originalPlcList != null)
- {
- //模拟plc与激光操作
- foreach (PLCNode p in plcMsg.originalPlcList)
- {
- int addr = Int32.Parse(p.Address);
- int value = Int32.Parse(p.Value);
- //模拟轮距激光
- if (addr == parking_startRobot_address)
- {
- if (value == 1)
- {
- if (!working)
- {
- working = true;
- Thread.Sleep(500);
- SendtoPLC(frontWheelbase_address.ToString(), (new Random(DateTime.Now.Millisecond).Next(100, 300)).ToString());
- Thread.Sleep(1);
- SendtoPLC(rearWheelbase_address.ToString(), (new Random(DateTime.Now.Millisecond).Next(100, 300)).ToString());
- SendtoPLC("81", "3");
- Thread.Sleep(500);
- }
- }
- else
- {
- working = false;
- SendtoPLC("81", "254");
- Thread.Sleep(500);
- SendtoPLC("81", "255");
- Thread.Sleep(500);
- }
- }
- }
- }
- Thread.Sleep(200);
- }
- }
- private void autoCycling()
- {
- while (!isClosing)
- {
- if (plcMsg.originalPlcList != null)
- {
- //模拟plc与激光操作
- foreach (PLCNode p in plcMsg.originalPlcList)
- {
- int addr = Int32.Parse(p.Address);
- int value = Int32.Parse(p.Value);
- //停取车复位
- if (addr == park_completed_acknowledge_address && value == 0)
- {
- Thread.Sleep(1000);
- SendtoPLC(park_completed_address.ToString(), "0");
- SendtoPLC(park_completed_acknowledge_address.ToString(), "1");
- }
- if (addr == fetch_completed_acknowledge_address && value == 0)
- {
- Thread.Sleep(1000);
- SendtoPLC(fetch_completed_address.ToString(), "0");
- SendtoPLC(fetch_completed_acknowledge_address.ToString(), "1");
- }
- //停车完成
- if (addr == parking_startRobot_address && value == 1)
- {
- Thread.Sleep(2000);
- SendtoPLC(park_completed_address.ToString(), "1");
- SendtoPLC(addr.ToString(), "0");
- }
- //取车完成
- if (addr == fetching_startRobot_address && value == 1)
- {
- Thread.Sleep(2000);
- SendtoPLC(fetch_completed_address.ToString(), "1");
- SendtoPLC(addr.ToString(), "0");
- }
- }
- }
- Thread.Sleep(200);
- }
- }
- }
- /// <summary>
- /// 激光数据记录与处理类
- /// </summary>
- class LaserProcessUnit
- {
- public int laser_start_address { get; set; }
- public int laser_status_address { get; set; }
- public int id { get; set; }
- private int LASER_RESCAN_COUNT, LASER_HEARTBEAT_PERIOD, laser_rescan_countdown, laser_heartbeat_countdown;
- private bool laser_record, laser_heartbeat_test, enable_status_check = true, disconnected = false, disordered = false;
- private HashSet<int> laser_heartbeat = new HashSet<int>();
- private IEquipments plc = null;
- public LaserMessage laserMsg = new LaserMessage();
- public LaserProcessUnit(int id, int park_command_address, int laser_status_address, int laser_rescan_count, int laser_heartbeat_period)
- {
- try
- {
- laserMsg.id = id;
- this.id = id;
- laserMsg.status = 6;
- this.laser_start_address = park_command_address;
- this.laser_status_address = laser_status_address;
- LASER_RESCAN_COUNT = laser_rescan_count;
- LASER_HEARTBEAT_PERIOD = laser_heartbeat_period;
- laser_rescan_countdown = LASER_RESCAN_COUNT;
- laser_heartbeat_countdown = LASER_HEARTBEAT_PERIOD;
- plc = EquipmentSimpleFactory.ins.FindEquipment(EquipmentName.PLC);
- }
- catch (Exception)
- {
- UILogServer.ins.error("激光设备配置文件错误");
- }
- }
- /// <summary>
- /// 更新激光状态
- /// </summary>
- /// <param name="addr"></param>
- /// <param name="value"></param>
- public void UpdateLaserStatus(int addr, int value)
- {
- int status_addr = laser_status_address;
- if (addr == status_addr)
- {
- laserMsg.status = value;
- //UILogServer.ins.log(value.ToString());
- //系统异常状态复位
- if (value != 5 && disordered)
- {
- disordered = false;
- }
- }
- }
- ///<summary>激光状态监测</summary>
- public void LaserStatusChecking(int addr, int value)
- {
- if (enable_status_check)
- {
- int status_addr = laser_status_address;
- if (addr == status_addr)
- {
- //after status 0, start to check laser heartbeat
- if (value == 0)
- {
- laserMsg.abort_rescan = false;//就绪状态设置允许重测
- laser_heartbeat_test = true;
- }
- //after status 3 or 4, start to check laser heartbeat
- if (value == 3 && !laserMsg.recorded && laserMsg.licenseNum != "")
- {
- if (plc == null)
- {
- plc = EquipmentSimpleFactory.ins.FindEquipment(EquipmentName.PLC);
- }
- if (plc != null)
- {
- PLCNode pn = new PLCNode(laser_start_address.ToString(), "0");
- plc.SetMessage(pn);
- //停车指令置0
- MyTimer mt = new MyTimer();
- mt.StartTiming();
- while (laserMsg.status != 254 && laserMsg.status != 255)
- {
- Thread.Sleep(1000);
- mt.EndTiming();
- int activationCount = 0;
- if (mt.IsLonger(15, 1, false, out activationCount))
- {
- if (activationCount == 1)
- {
- UILogServer.ins.info("记录数据前未获得心跳,继续等待");
- }
- if (MyTimer.restart && !mt.rolledBack)
- {
- mt.rolledBack = true;
- UILogServer.ins.error("记录数据前超时未获得心跳,请检查设备");
- }
- }
- }
- laser_record = true;
- laser_rescan_countdown = LASER_RESCAN_COUNT;
- laser_heartbeat_test = true;
- }
- }
- else if (value == 4)
- {
- laser_record = false;
- //启动重测指令
- if (laser_rescan_countdown > 0)
- {
- enable_status_check = false;
- Task t = Task.Factory.StartNew(() =>
- {
- Thread.Sleep(500);
- if (plc == null)
- {
- plc = EquipmentSimpleFactory.ins.FindEquipment(EquipmentName.PLC);
- }
- if (plc != null)
- {
- laser_rescan_countdown--;
- //停车指令置0
- PLCNode pn = new PLCNode(laser_start_address.ToString(), "0");
- plc.SetMessage(pn);
- //未终止重测,车未开走,停车指令归零后置1
- if (!laserMsg.abort_rescan)
- {
- UILogServer.ins.error("激光" + laserMsg.id + "计算异常,重新测量");
- //重测检测心跳
- Task rescan_wait_heartbeat = Task.Factory.StartNew(() =>
- {
- MyTimer mt = new MyTimer();
- mt.StartTiming();
- while (laserMsg.status != 254 && laserMsg.status != 255)
- {
- Thread.Sleep(1000);
- mt.EndTiming();
- int activationCount = 0;
- if (mt.IsLonger(15, 1, false, out activationCount))
- {
- if (activationCount == 1)
- {
- UILogServer.ins.info("重测前未获得心跳,继续等待");
- }
- if (MyTimer.restart && !mt.rolledBack)
- {
- mt.rolledBack = true;
- UILogServer.ins.error("发起重测前超时未能获取摆扫激光心跳,请检查设备");
- }
- }
- }
- });
- UILogServer.ins.log("获得心跳,准备发起重测");
- rescan_wait_heartbeat.Wait();
- pn = new PLCNode(laser_start_address.ToString(), "1");
- plc.SetMessage(pn);
- }
- }
- Thread.Sleep(500);
- enable_status_check = true;
- });
- }
- else if (laser_rescan_countdown == 0)
- {
- //激光1异常
- laser_rescan_countdown = -1;
- laser_heartbeat_test = false;
- UILogServer.ins.error("激光" + laserMsg.id + "计算异常超过重测次数,请检查");
- }
- }
- //status 5, system error
- if (value == 5)
- {
- lock (laserMsg)
- {
- laser_heartbeat_test = false;
- if (!disordered)
- {
- UILogServer.ins.error("激光系统异常,请检查");
- }
- disordered = true;
- }
- }
- //find the heartbeat of laser
- if (laser_heartbeat_test && laser_heartbeat_countdown-- > 0 && value != 3 && value != 4)
- {
- if (value == 254 || value == 255)
- laser_heartbeat.Add(value);
- if (laser_heartbeat.Contains(254) && laser_heartbeat.Contains(255))
- {
- disconnected = false;
- laser_heartbeat_countdown = LASER_HEARTBEAT_PERIOD;
- laser_heartbeat_test = false;
- Console.WriteLine("激光" + laserMsg.id + "已检测到心跳");
- laser_heartbeat.Clear();
- }
- //fail to check laser heartbeat
- if (laser_heartbeat_countdown <= 0)
- {
- laser_heartbeat_countdown = LASER_HEARTBEAT_PERIOD;
- lock (laserMsg)
- {
- if (laserMsg.status >= 0)
- {
- UILogServer.ins.error("激光" + laserMsg.id + "心跳检测失败");
- }
- disconnected = true;
- laserMsg.status = -1;
- }
- }
- }
- }
- }
- else { return; }
- }
- /// <summary>激光数据记录</summary>
- public void LaserRecord(List<PLCNode> plist)
- {
- lock (laserMsg)
- {
- //激光未掉线,记录数据写入plc
- if (laserMsg.status != -1)
- {
- if (laser_record)
- {
- laser_record = false;
- foreach (PLCNode p in plist)
- {
- int addr = Int32.Parse(p.Address);
- int value = Int32.Parse(p.Value);
- if (addr == laser_status_address + 1)
- laserMsg.data.centerX = value;
- else if (addr == laser_status_address + 2)
- laserMsg.data.centerY = value;
- else if (addr == laser_status_address + 3)
- laserMsg.data.angleA = value;
- else if (addr == laser_status_address + 4)
- laserMsg.data.length = value;
- else if (addr == laser_status_address + 5)
- laserMsg.data.width = value;
- else if (addr == laser_status_address + 6)
- laserMsg.data.height = value;
- }
- laserMsg.recorded = true;
- UILogServer.ins.info("摆扫激光测量数据已记录");
- }
- }
- }
- }
- }
- /// <summary>
- /// 机械手逻辑处理类
- /// </summary>
- class RobotProcessUnit
- {
- public int id { get; set; }
- public int parking_startRobot_address { get; set; }
- public int parking_laserCenterX_address { get; set; }
- public int parkingSpaceID_address { get; set; }
- public int park_completed_address { get; set; }
- public int park_completed_acknowledge_address { get; set; }
- public int fetching_startRobot_address { get; set; }
- public int fetch_completed_address { get; set; }
- public int fetch_completed_acknowledge_address { get; set; }
- public int fetch_to_address { get; set; }
- public int frontWheelbase { get; set; }
- public int rearWheelbase { get; set; }
- public RobotProcessUnit(int id, int parking_startRobot_address, int parking_laserCenterX_address, int parkingSpaceID_address, int park_completed_address, int park_completed_acknowledge_address, int fetching_startRobot_address, int fetch_to_address, int fetch_completed_address, int fetch_completed_acknowledge_address, int frontWheelbase, int rearWheelbase)
- {
- this.id = id;
- this.parking_startRobot_address = parking_startRobot_address;
- this.parking_laserCenterX_address = parking_laserCenterX_address;
- this.parkingSpaceID_address = parkingSpaceID_address;
- this.park_completed_address = park_completed_address;
- this.park_completed_acknowledge_address = park_completed_acknowledge_address;
- this.fetching_startRobot_address = fetching_startRobot_address;
- this.fetch_completed_address = fetch_completed_address;
- this.fetch_completed_acknowledge_address = fetch_completed_acknowledge_address;
- this.fetch_to_address = fetch_to_address;
- this.frontWheelbase = frontWheelbase;
- this.rearWheelbase = rearWheelbase;
- }
- }
- }
|