天津康师傅调度系统
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

1692 lines
67 KiB

using CommonLib;
using DBFactory;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Net.NetworkInformation;
using System.Text;
using System.Threading.Tasks;
namespace FINSTCPIP
{
public class ClientCommunication
{
public static event CWriteDarkCasketEventHandler WriteDarkCasket;
public static event RefreshMonitorEventHandler RefreshMonitor;
public static void OnRefreshMonitor(RefreshMonitorEventArgs e)
{
if (RefreshMonitor != null)
{
RefreshMonitor(e);
}
}
static string _finsError;
public static string FINSError
{
get { return _finsError; }
set
{
_finsError = value;
RefreshMonitorEventArgs rea = new RefreshMonitorEventArgs("tsStatus", string.Format("FINSTCPIP.ClientCommunication:{0}", _finsError));
OnRefreshMonitor(rea);
}
}
public const int MODBUS = 1; //Modbus协议
public const int FINS = 2; //FINS协议
//和plc通讯的socket,包含了接包、发包、
public static Dictionary<string, TcpSocket> socketFinss = new Dictionary<string, TcpSocket>();
//每个PLC通信时需要的 FINS 信息,用来从FINS包中提取数据,发送数据时添加FINS包装
public static Dictionary<string, FINSParse> clientFinss = new Dictionary<string, FINSParse>();
public static Dictionary<string, int> connectTimes = new Dictionary<string, int>();//socket的连接次数,连接成功时置0
public static Dictionary<string, List<byte>> buffer = new Dictionary<string, List<byte>>();//每个socket的buffer
public static Dictionary<string, byte[]> SC_RGV_READ_DATA = new Dictionary<string, byte[]>(); //世仓穿梭板读取车状态:发送包(FINS连接成功时添加)
static StringBuilder sql = new StringBuilder();
public static Dictionary<string, SHICANGReadData> lastReadMessage = new Dictionary<string, SHICANGReadData>();//上一次发生变化后,收到的信息
public static DBOperator dbo = CClientTCPIP.dbo;
public static DBOperator dboM = CClientTCPIP.dboM;
static Model.MDevice devinfo;
public static void InitAllClientTCPIP()
{
DataView dv = new DataView(); DataView dvs = new DataView();
string ip = string.Empty;
int port = 9600;
try
{
#region 从数据库中读取需要充电的电量
dv = dbo.ExceSQL("SELECT F_bettey_low FROM T_base_rgvInfo ").Tables[0].DefaultView;
if (dv.Count > 0)
{
SHICANGProtocol.NeedToBettey = Convert.ToInt32(dv[0]["F_bettey_low"]);
}
#endregion
//V_RGVInfo不包含禁用的穿梭车
dvs = dbo.ExceSQL("SELECT F_DeviceIndex, F_RemoteIP,F_RemotePort FROM V_RGVINFO ").Tables[0].DefaultView;
for (int i = 0; i < dvs.Count; i++)
{
ip = dvs[i]["F_RemoteIP"].ToString();
port = Convert.ToInt32(dvs[i]["F_RemotePort"]);
//前10次连接间隔10秒(timer),之后60秒连接一次
if (connectTimes.ContainsKey(ip) == true)
{
if (connectTimes[ip] > 10)
{
int rgv = Convert.ToInt32(dvs[i]["F_DeviceIndex"]);
#region 和数据库中记录的时间小于一分钟
sql.Clear();
sql.Append("select F_Time from V_RGVINFO where F_DeviceIndex =").Append(rgv);
dv = dbo.ExceSQL(sql.ToString()).Tables[0].DefaultView;
if (dv.Count > 0)
{
DateTime appdt = DateTime.Now.AddSeconds(-10); ;
DateTime.TryParse(dv[0]["F_Time"].ToString(), out appdt);
if ((appdt.AddSeconds(60) > DateTime.Now))
{
//数据库中记录的时间小于当前一分钟
//UpdateTime(rgv);
continue;
}
}
#endregion
UpdateTime(rgv);
//continue;
}
}
if (FINSTCPIP.SHICANGProtocol.ShuttleConnected(ip) == false)
{
Task.Run(async () =>
{
await ClientCommunication.Open(ip, port, FINS);
});
System.Threading.Thread.Sleep(200);
}
//if (clientFinss.ContainsKey(ip) == false)
//{
// Task.Run(async () =>
// {
// await ClientCommunication.Open(ip, port, FINS);
// });
// System.Threading.Thread.Sleep(50);
//}
//else if (clientFinss[ip]._ifIniting == false)
//{
// Task.Run(async () =>
// {
// await ClientCommunication.Open(ip, port, FINS);
// });
// System.Threading.Thread.Sleep(50);
//}
}
}
catch (Exception e)
{
FINSError = e.StackTrace + e.Message;
}
}
public static void CloseAllClient()
{
foreach(var ip in socketFinss.Keys)
{
if (clientFinss[ip]._socketConnected == true)
{
clientFinss[ip]._socketConnected = false;
clientFinss[ip]._finsConnected = false;
clientFinss[ip]._ifIniting = false;
socketFinss[ip].Close(); //只要关闭socket连接即可,无需再关闭fins连接
}
}
}
private const int DelayTime = 500;
public static readonly Object thisLock = new Object();
public static async Task Open(string ip, int port, int protocol = MODBUS)
{
await Task.Run(() =>
{
if (clientFinss.ContainsKey(ip) == true)
{
if (clientFinss[ip]._ifIniting == true)
{
//有其他线程正在进行初始化连接
return;
}
else
{
//没有其他线程正在初始化,本线程准备进入初始化
}
if (clientFinss[ip]._socketConnected == true)
{
return;
}
//新添加的
if (clientFinss[ip]._finsConnected == true)
{
return;
}
}
else
{
FINSParse fp = new FINSParse();
//本线程进入初始化工作
fp._ifIniting = true;
clientFinss.Add(ip, fp);
List<byte> te = new List<byte>();
buffer.Add(ip, te );
}
clientFinss[ip]._ifIniting = true;
if (connectTimes.ContainsKey(ip) == false)
{
connectTimes.Add(ip, 0);
}
//else
//{
// connectTimes[ip] += 1;
//}
int shuttle = CClientTCPIP.GetAGVServer(ip);
int[] chatnew;
chatnew = new int[1];
#region 判断网络是否正常
ClientCommunication.connectTimes[ip] += 1;
Ping ping = new Ping();
try
{
if (ping.Send(ip).Status != 0)
{
ClientCommunication.clientFinss[ip]._ifIniting = false;
FINSError = shuttle + ":" + ip + " 网络故障或未开机。";
return;
}
}catch
{
ClientCommunication.clientFinss[ip]._ifIniting = false;
FINSError = shuttle + ":" + ip +" 网络故障或未开机。";
}
#endregion
TcpSocket tcpsocket = new TcpSocket(ip, port, shuttle);
AddTCPSocketEvent(tcpsocket, clientFinss[ip], protocol);
if (socketFinss.ContainsKey(ip) == false)
{
socketFinss.Add(ip, tcpsocket);
}
else
{
try
{
socketFinss[ip].Close();
}
catch
{
FINSError = shuttle + ":" + ip + " 断开连接失败。";
}
socketFinss[ip] = null;
socketFinss[ip] = tcpsocket;
}
CWriteDarkCasketEventArgs ee = new CWriteDarkCasketEventArgs("FINSTCPIP.CConnectTCPIP", "Open", ip, "建立socket连接", chatnew);
OnWriteDarkCasket(ee);
if (TcpSocket.thisLock.ContainsKey(ip) == false)
{
TcpSocket.thisLock.Add(ip, new object());
}
tcpsocket.Open();
Task.Run(async () =>
{
byte[] header = new byte[4];
byte[] length = new byte[4];
List<byte> bufftemp = new List<byte>();
//解析报文
while (true)
{
bufftemp.Clear();
lock (TcpSocket.thisLock[ip])
{
if (buffer[ip].Count >= 4)
{
bufftemp.AddRange(buffer[ip]);
buffer[ip].Clear();
}
}
if (bufftemp.Count == 0)
{
await Task.Delay(DelayTime);
continue;
}
bufftemp.CopyTo(0, header, 0, 4);
if (clientFinss[ip].IsHeader(header) == true)
{
//获得Length的值
bufftemp.CopyTo(4, length, 0, 4);
if (BitConverter.IsLittleEndian)
Array.Reverse(length);
int len = BitConverter.ToInt16(length, 0);
if (len == FINSParse.SHAKEHAND_RECV_LENGTH)
{//握手回复
//string err = string.Empty;
#region 握手失败
if (clientFinss[ip].IsConnectRight(bufftemp) == false)
{
CWriteDarkCasketEventArgs eee = new CWriteDarkCasketEventArgs("FINSTCPIP.CConnectTCPIP", "Open", shuttle.ToString(), "FINS连接失败,断开Socket", chatnew);
OnWriteDarkCasket(eee);
bufftemp.Clear();
clientFinss[ip]._socketConnected = false;
clientFinss[ip]._finsConnected = false;
socketFinss[ip].Close();
#region FINS 连接错误
FINSError = ip + " " + clientFinss[ip].CommLayerError;
#endregion
return;
}
#endregion
//握手成功
CWriteDarkCasketEventArgs e = new CWriteDarkCasketEventArgs("FINSTCPIP.CConnectTCPIP", "Open", shuttle.ToString(), "FINS连接成功", chatnew);
OnWriteDarkCasket(e);
bufftemp.Clear();
clientFinss[ip]._finsConnected = true;
SC_RGV_READ_DATA[ip] = ClientCommunication.clientFinss[ip].GetInfo_DMRead(2100, 30);
#region LYJL 读D2025的值
//socketFinss[ip].Send(clientFinss[ip].GetInfo_DMRead(2025, 1), null);
#endregion
}
else if (len >= FINSParse.FRAM_NODATA_RECV_LENGTH)
{//读写回复
if (clientFinss[ip].IsRecvRight(bufftemp) == false)
{
CWriteDarkCasketEventArgs e = new CWriteDarkCasketEventArgs("FINSTCPIP.CConnectTCPIP", "Open", shuttle.ToString(), "接收数据错误", chatnew);
OnWriteDarkCasket(e);
bufftemp.Clear();
FINSError = ip + " " + clientFinss[ip].CommLayerError;
await Task.Delay(DelayTime);
continue;
}
if (len > FINSParse.FRAM_NODATA_RECV_LENGTH)
{//得到数据
byte[] data = new byte[len-22]; //保存原始数据
bufftemp.CopyTo(30, data, 0, data.Length);
ushort [] newData = CClientTCPIP.ConvertByteToUInt16(data, true); //处理后的数据
if (newData.Length == 30)
{
SHICANGReadData temp = new SHICANGReadData();
temp.D2100 = newData[0];
temp.D2101 = newData[1];
temp.D2102 = newData[2];
temp.D2121 = newData[21];
temp.D2122 = newData[22];
temp.D2123 = newData[23];
temp.D2129 = newData[29];
lock (thisLock)
{
DisposeReceivedReadMessage(shuttle, temp);
}
}
else if (newData.Length == 1)
{
devinfo = Model.CGetInfo.GetDeviceInfo(shuttle);
devinfo.XCoor = newData[0];
}
}
else
{
DisposeReceivedWriteMessage(shuttle);
}
bufftemp.Clear();
}
else
{
bufftemp.Clear();
}
}
else
{
bufftemp.Clear();
FINSError = ip + " " + clientFinss[ip].CommLayerError;
}
await Task.Delay(DelayTime);
}
});
});
}
private static void AddTCPSocketEvent(TcpSocket tcpsocket, FINSParse fp,int protocol)
{
int[] chatnew;
chatnew = new int[1];
string ip = tcpsocket.IP;
tcpsocket.OpenSuccess += () =>
{
//Logging.Invoke("连接成功\n", 0);
CWriteDarkCasketEventArgs e = new CWriteDarkCasketEventArgs("FINSTCPIP.CConnectTCPIP", "OpenSuccess", ip, "Socket连接成功", chatnew);
OnWriteDarkCasket(e);
tcpsocket.Receive();
connectTimes[ip] = 0;
fp._ifIniting = false;
fp._socketConnected = true;
//此处只是socket连接成功,fins连接状态不知道
#region FINS协议, socket 连接成功,先发送 FINS 的连接请求
byte[] conndata = clientFinss[ip].GetConnectInfo();
if (protocol == FINS && fp._finsConnected == false)
{
tcpsocket.Send(conndata, null);
CWriteDarkCasketEventArgs eee = new CWriteDarkCasketEventArgs("FINSTCPIP.CConnectTCPIP", "OpenSuccess", ip, "建立FINS连接", chatnew);
OnWriteDarkCasket(eee);
}
else
{
CWriteDarkCasketEventArgs eee = new CWriteDarkCasketEventArgs("FINSTCPIP.CConnectTCPIP", "OpenSuccess", ip, "FINS连接状态已存在", chatnew);
OnWriteDarkCasket(eee);
FINSError = ip + "FINS连接状态已存在";
}
#endregion
};
tcpsocket.OpenFail += async (ex) =>
{
connectTimes[ip] += 1;
fp._ifIniting = false;
fp._socketConnected = false;
fp._finsConnected = false;
CWriteDarkCasketEventArgs e = new CWriteDarkCasketEventArgs("FINSTCPIP.CConnectTCPIP", "OpenFail", ip, "连接失败", chatnew);
OnWriteDarkCasket(e);
await Task.Delay(100);
//连接失败,通过timer重新连接
//return;
};
tcpsocket.Disconnect += async (ex) =>
{
CWriteDarkCasketEventArgs e = new CWriteDarkCasketEventArgs("FINSTCPIP.CConnectTCPIP", "Disconnect", ip, "连接断开", chatnew);
OnWriteDarkCasket(e);
connectTimes[ip] += 1;
if (connectTimes[ip] >= 3)
{
fp._ifIniting = false;
fp._socketConnected = false;
fp._finsConnected = false;
tcpsocket.Close();
await Task.Delay(100);
}
};
tcpsocket.ReceiveSuccess += (bytes) =>
{
//if (ip == "192.168.0.232")
{
lock (TcpSocket.thisLock[ip])
{
buffer[ip].AddRange(bytes);
}
}
};
tcpsocket.ReceiveFail += (ex) =>
{
CWriteDarkCasketEventArgs e = new CWriteDarkCasketEventArgs("FINSTCPIP.CConnectTCPIP", "ReceiveFail", ip, "接收失败", chatnew);
OnWriteDarkCasket(e);
connectTimes[ip] += 1;
//SocketConnected[ip] = false;
};
tcpsocket.SendFail += async (ex) =>
{
CWriteDarkCasketEventArgs e = new CWriteDarkCasketEventArgs("FINSTCPIP.CConnectTCPIP", "SendFail", ip, "发送失败", chatnew);
OnWriteDarkCasket(e);
connectTimes[ip] += 1;
await Task.Delay(100);
//if (connectTimes[ip] >= 3)
//{
// SocketConnected[ip] = false;
// FINSConnected[ip] = false;
// await Task.Delay(100);
// //socket.Open();
// //await Open(ip, port, protocol);
//}
};
tcpsocket.CloseSuccess += async () =>
{
CWriteDarkCasketEventArgs e = new CWriteDarkCasketEventArgs("FINSTCPIP.CConnectTCPIP", "CloseSuccess", ip, "断开连接成功", chatnew);
OnWriteDarkCasket(e);
tcpsocket = null;
await Task.Delay(100);
};
tcpsocket.CloseFail += async (ex) =>
{
CWriteDarkCasketEventArgs e = new CWriteDarkCasketEventArgs("FINSTCPIP.CConnectTCPIP", "CloseFail", ip, "断开连接失败", chatnew);
OnWriteDarkCasket(e);
await Task.Delay(100);
//if (connectTimes[ip] >= 3)
//{
// SocketConnected[ip] = false;
// FINSConnected[ip] = false;
// await Task.Delay(100);
// //socket.Open();
// //await Open(ip, port, protocol);
//}
};
CClientTCPIP.SQLString(dbo, sql);
}
private static StringBuilder log = new StringBuilder();
//public static readonly Object thisLock = new Object();
/// <summary>
///处理收到的消息——读PLC数据的应答处理
/// </summary>
/// <param name="message">消息数组</param>
private static void DisposeReceivedReadMessage(int shuttle, SHICANGReadData message)
{
DataView dv = new DataView();
try
{
devinfo = Model.CGetInfo.GetDeviceInfo(shuttle);
bool change = false; //车状态发生了变化
bool complete = false; //车的当前任务完成了
bool runing = false; //车的当前任务开始执行了
#region 状态未发生变化,只更新一下数据库的时间
if (lastReadMessage.ContainsKey(devinfo.RemoteIP) == true)
{
if (lastReadMessage[devinfo.RemoteIP].Equal(message) == false)
{
change = true;
//只有发生了变化时,才写入黑匣子
int[] ddd = new int[7] {message.D2100, message.D2101, message.D2102, message.D2121, message.D2122, message.D2123, message.D2129};
CWriteDarkCasketEventArgs e = new CWriteDarkCasketEventArgs("FINSTCPIP.CConnectTCPIP", "Read", shuttle.ToString(), "读数据成功", ddd);
OnWriteDarkCasket(e);
//只有发生了变化时,才更新记录
lastReadMessage[devinfo.RemoteIP].Update(message);
}
}
else
{
int[] ddd = new int[7] { message.D2100, message.D2101, message.D2102, message.D2121, message.D2122, message.D2123, message.D2129 };
CWriteDarkCasketEventArgs e = new CWriteDarkCasketEventArgs("FINSTCPIP.CConnectTCPIP", "Read", shuttle.ToString(), "读数据成功", ddd);
OnWriteDarkCasket(e);
//第一次,添加数据
lastReadMessage.Add(devinfo.RemoteIP, message);
}
#endregion
//发生变化则进行后续处理
byte[] err = new byte[32];
#region 根据车号,获取当前任务,当前位置
int fstatus = -1; int forder = -1; int fmonitorID = -1; string begintime = string.Empty;
//sql.Clear();
//sql.Append("select * from t_monitor_task where f_status <> 0 and f_deviceIndex =").Append(shuttle);
dv = dbo.ExceSQL(string.Format("select * from t_monitor_task where f_status <> 0 and f_deviceIndex ={0}", shuttle)).Tables[0].DefaultView;
if (dv.Count == 1)
{
fstatus = Convert.ToInt32(dv[0]["f_status"]);
forder = Convert.ToInt32(dv[0]["F_DeviceCommandIndex"]);
fmonitorID = Convert.ToInt32(dv[0]["F_MonitorIndex"]);
begintime = dv[0]["F_startTime"].ToString();
}
#endregion
#region 更新内存中的车状态信息
{
#region D2100
//RunState,0-空闲,-1 非空闲
devinfo.RunState = (message.D2100 & 1) == 1 ? 0 : -1;
//AB面相叉车位, SplitByte_0 0-B面, 1-A面
devinfo.SplitByte_5 = (message.D2100 & 2) == 2 ? 1 : 0;
//有托盘位 HaveGoods 1-有货,0-无货
devinfo.SplitByte_0 = (message.D2100 & 4) == 4 ? 1 : 0;
//上/下/前/后/起升位 RunState 1-运行
if (((message.D2100 & 8) == 8) || ((message.D2100 & 16) == 16) ||
((message.D2100 & 32) == 32) || ((message.D2100 & 64) == 256))
{
devinfo.RunState = 1;
}
//存货位 , SplitByte_1 ,1-存货(时间很短,不一定能抓到)
devinfo.SplitByte_1 = (message.D2100 & 256) == 256 ? 1 : 0;
//取货位, SplitByte_2 , 1-取货(时间很短,不一定能抓到)
devinfo.SplitByte_2 = (message.D2100 & 512) == 512 ? 1 : 0;
//盘点位 ------
//模式位 , ControlMode, 0-叉车模式, 1-堆垛模式
devinfo.ControlMode = (message.D2100 & 16384) == 16384 ? 1 : 0;
//充电位 , SplitByte_3, 1-充电中
devinfo.SplitByte_3 = (message.D2100 & 32768) == 32768 ? 1 : 0;
if (devinfo.SplitByte_3 == 1)
devinfo.RunState = 0; //充电时,车状态标记为空闲,可以工作
#endregion
#region D2101
//A面障碍位,SplitByte_4 , 1-A面障碍, 0-A/B面均无障碍
if ((message.D2101 & 2) == 2)
{
devinfo.SplitByte_4 = 1;
}
else if (devinfo.SplitByte_4 == 1)
{
devinfo.SplitByte_4 = 0;
}
//B面障碍位 , SplitByte_4, 2-B面障碍, 0-A/B面均无障碍
if ((message.D2101 & 4) == 4)
{
devinfo.SplitByte_4 = 2;
}
else if (devinfo.SplitByte_4 == 2)
{
devinfo.SplitByte_4 = 0;
}
//在充电架上位 (无此状态)
//上电状态位 变化 RunState = 3 未上电状态
devinfo.RunState = (message.D2101 & 64) == 64 ? devinfo.RunState : 3;
//掉头结束位 变化 SplitByte_7
devinfo.SplitByte_7 = (message.D2101 & 128) == 128 ? 1 : 0;
//AA状态位(无此状态)
#endregion
}
//D2102 电池电量
devinfo.SplitByte = message.D2102;
//D2121,D2122 穿梭板 报警信息
err = GetError(message.D2121, message.D2122);
//D2123 禁止动作
devinfo.SplitByte_6 = message.D2123;
//D2129 执行完成的任务号
devinfo.TaskNo = message.D2129;
#endregion
#region 数据库中有已发送或执行中的任务,更新任务状态
//根据车的状态,找到了当前的唯一任务
if (fmonitorID != -1 && fmonitorID != 0 && devinfo.RunState < 2)
{
switch (forder)
{
case 1://存货/入
//任务完成的判断条件,车上报任务号,上报指令,且任务号和从数据库中获取的正在执行的任务号相同,且车空闲
if ((fstatus == 1 || fstatus == 2) && devinfo.TaskNo == fmonitorID && devinfo.RunState == 0)
complete = true; //完成任务
else if (devinfo.RunState == 1 && fstatus == 1)
runing = true; //开始执务
break;
case 2://取货/出
if ((fstatus == 1 || fstatus == 2) && devinfo.TaskNo == fmonitorID && devinfo.RunState == 0)
complete = true; //完成任务
else if (devinfo.RunState == 1 && fstatus == 1)
runing = true; //开始执行
break;
case 3://上堆垛机/切换成叉车模式
if ((fstatus == 1 || fstatus == 2) && devinfo.ControlMode == 0 && devinfo.RunState == 0)
complete = true; //完成任务
else if (devinfo.RunState == 1 && fstatus == 1)
runing = true; //开始执行
break;
case 4://下堆垛机/切换成堆垛模式
if ((fstatus == 1 || fstatus == 2) && devinfo.ControlMode == 1 && devinfo.RunState == 0)
complete = true; //完成任务
else if (devinfo.RunState == 1 && fstatus == 1)
runing = true; //开始执务
break;
case 5://回原点模式
if ((fstatus == 1 || fstatus == 2) && devinfo.RunState == 0)
complete = true; //完成任务
else if (devinfo.RunState == 1 && fstatus == 1)
runing = true; //开始执务
break;
case 7://去B边
if ((fstatus == 1 || fstatus == 2) && devinfo.SplitByte_7 == 1 && devinfo.RunState == 0)
complete = true; //完成任务
else if ((fstatus == 1 || fstatus == 2) && devinfo.SplitByte_5 == 0 && devinfo.SplitByte_7 == 0 && devinfo.RunState == 0)
complete = true; //完成任务
else if (fstatus == 1 && devinfo.RunState == 1)
runing = true; //开始执务
break;
case 12://去A边
if ((fstatus == 1 || fstatus == 2) && devinfo.SplitByte_7 == 1 && devinfo.RunState == 0)
complete = true; //完成任务
else if ((fstatus == 1 || fstatus == 2) && devinfo.SplitByte_5 == 1 && devinfo.SplitByte_7 == 0 && devinfo.RunState == 0)
complete = true; //完成任务
else if (fstatus == 1 && devinfo.RunState == 1)
runing = true; //开始执务
break;
case 11://禁止穿梭板动作
if ((fstatus == 1 || fstatus == 2) && devinfo.SplitByte_6 == 1)
complete = true;
break;
case 13://允许穿梭板动作
if ((fstatus == 1 || fstatus == 2) && devinfo.SplitByte_6 == 0)
complete = true; //完成任务
break;
case 30://开始充电
if ((fstatus == 1 || fstatus == 2) && devinfo.SplitByte_3 == 1)
complete = true; //完成任务
break;
case 50://停止充电
if ((fstatus == 1 || fstatus == 2) && devinfo.SplitByte_3 == 0)
complete = true; //完成任务
break;
default:
break;
}
}
#endregion
#region 本线程处理的任务
//充满电了则停止充电(电池厂家优化了,不发停止充电)
if (devinfo.SplitByte == 100 && devinfo.SplitByte_3 == 1)
{
//SHICANGProtocol.Order_EndCharge(devinfo.RemoteIP);
}
//如果车的状态和数据库中记录的不一致,则更新数据库
//sql.Clear();
//sql.Append("select * from t_base_rgvInfo where f_rgvIndex = ").Append(shuttle);
dv = dbo.ExceSQL(string.Format("select * from t_base_rgvInfo where f_rgvIndex = {0}", shuttle)).Tables[0].DefaultView;
if (dv.Count > 0)
{
sql.Clear();
sql.Append("update t_base_rgvInfo set f_forkamount =0");
if (dv[0]["F_ControlMode"].ToString() != devinfo.ControlMode.ToString())
sql.Append(", F_ControlMode = ").Append(devinfo.ControlMode);
if (dv[0]["f_currentAB"].ToString() != devinfo.SplitByte_5.ToString())
sql.Append(", f_currentAB = ").Append(devinfo.SplitByte_5);
if (dv[0]["f_ForbidRGVMove"].ToString() != devinfo.SplitByte_6.ToString())
sql.Append(", f_ForbidRGVMove = ").Append(devinfo.SplitByte_6);
if (dv[0]["f_betteying"].ToString() != devinfo.SplitByte_3.ToString())
sql.Append(", f_betteying = ").Append(devinfo.SplitByte_3);
if (dv[0]["f_havegood"].ToString() != devinfo.SplitByte_0.ToString())
sql.Append(", f_havegood = ").Append(devinfo.SplitByte_0);
if (dv[0]["f_bettey_cur"].ToString() != devinfo.SplitByte.ToString())
sql.Append(", f_bettey_cur = ").Append(devinfo.SplitByte);
if (dv[0]["f_runstate"].ToString() != devinfo.RunState.ToString())
sql.Append(", f_runstate = ").Append(devinfo.RunState);
sql.Append(" where f_rgvindex= ").Append(shuttle);
sql.Append(" ");
sql.Append("update t_base_device set f_havegoods = ").Append(devinfo.SplitByte_0).Append(" where f_deviceIndex=").Append(shuttle);
dbo.ExceSQL(sql.ToString());
}
//更新车辆的时间
UpdateTime(shuttle, true);
if (message.D2121 + message.D2122 == 0)
{
//更新车状态
sql.Clear();
sql.Append("update t_base_device set F_ErrorCode = 0 where F_ErrorCode >= 30 and f_deviceindex = ").Append(shuttle);
sql.Append(" ");
sql.Append("update t_base_rgvInfo set f_error = 0 where f_RGVIndex = ").Append(shuttle);
dbo.ExceSQL(sql.ToString());
}
#endregion
#region 主线程要处理的任务
#region 电量不足
if (/*devinfo.SplitByte < 70 ||*/ devinfo.SplitByte < SHICANGProtocol.NeedToBettey)
{
//正在充电中不生成充电任务
if (devinfo.SplitByte_3 == 0 && devinfo.RunState == 0)
{
CClientTCPIP.ActionError(shuttle, null, err);
}
}
#endregion
#region 发生故障
if (message.D2121 + message.D2122 != 0)
{
devinfo.RunState = 2;
CClientTCPIP.ActionError(shuttle, null, err);
}
else
{
//将上一次的故障停止
StringBuilder dtime = new StringBuilder(DateTime.Now.ToString("u"));
dtime.Remove(dtime.Length - 1, 1);
string ddtime = dtime.ToString();
sql.Clear();
sql.Append("SELECT TOP 1 * FROM T_Base_Device_Error_Log where f_deviceindex = ").Append(shuttle).Append(" order by F_DateTime desc");
dv = dbo.ExceSQL(sql.ToString()).Tables[0].DefaultView;
if (dv.Count > 0)
{
if (string.IsNullOrEmpty(dv[0]["F_FixDateTime"].ToString()) == true)
{
sql.Clear();
sql.Append("UPDATE T_Base_Device_Error_Log SET F_FixDateTime ='").Append(dtime).Append("',F_End_DateTime='").Append(dtime).Append("' Where ID=").Append(dv[0]["ID"]);
dbo.ExceSQL(sql.ToString());
}
}
}
if (begintime != "-" && begintime != string.Empty && fmonitorID != -1)
{
if (Convert.ToDateTime(begintime.Substring(0, 19), System.Globalization.CultureInfo.CurrentCulture).AddMinutes(15) <= DateTime.Now)
{
//任务超过了10分钟,且还处于运行状态,发送回起点,把指令改为超时
if (devinfo.RunState ==1)
{
if (((message.D2100 & 8) == 8) || ((message.D2100 & 16) == 16))
{
sql.Clear();
sql.Append("update t_monitor_Task set f_status =999, f_errorCode='运行超时' where f_monitorIndex =").Append(fmonitorID);
sql.Append(" ");
sql.Append("update t_base_rgvInfo set f_error =51 where f_rgvIndex = ").Append(shuttle);
dbo.ExceSQL(sql.ToString());
//发现超时了,且不在充电位,发送回原点
if (FINSTCPIP.SHICANGProtocol.ShuttleInBetteyLane(shuttle) == false)
{
SHICANGProtocol.Order_ToOrigin(devinfo.RemoteIP);
}
}
}
}
}
#endregion
#region 通知主线程中,穿梭车状态发生了变化
if (complete)
{
//任务完成
CClientTCPIP.ActionChange(shuttle, fmonitorID, 2);
CClientTCPIP.DataSourceChange();
}
if (runing)
{
//开始执行
//sql.Remove(0, sql.Length);
//sql.Append("UPDATE T_Monitor_Task SET F_ErrorCode='', F_Status=2 WHERE F_MonitorIndex = ").Append(fmonitorID);
dbo.ExceSQL(string.Format("UPDATE T_Monitor_Task SET F_ErrorCode='', F_Status=2 WHERE F_MonitorIndex = {0}", fmonitorID));
}
#endregion
#endregion
}
catch (Exception ex)
{
int[] tem = new int[1];
CWriteDarkCasketEventArgs e = new CWriteDarkCasketEventArgs("FINSTCPIP:DisposeReceivedReadMessage", "Error", shuttle.ToString(), ex.StackTrace + ex.Message, tem);
OnWriteDarkCasket(e);
FINSError = shuttle + "读信息处理错误。" + ex.StackTrace + ex.Message;
//throw ex;
}
finally
{
dv.Dispose();
}
}
//checkTime,检查时间间隔。checkTime = true时,且时间小于10秒,则不更新时间
private static void UpdateTime(int shuttle, bool checkTime = false)
{
DateTime dt = DateTime.Now;
try
{
if (checkTime)
{
if (SHICANGProtocol.GetTime(shuttle).AddSeconds(5) > dt)
{
return;
}
}
sql.Clear();
sql.Append("update t_base_rgvInfo set f_time = '").Append(dt).Append("' where f_rgvIndex = ").Append(shuttle);
dbo.ExceSQL(sql.ToString());
}
catch(Exception ex)
{
int[] tem = new int[1];
CWriteDarkCasketEventArgs e = new CWriteDarkCasketEventArgs("FINSTCPIP:UpdateTime", "Error", shuttle.ToString(), ex.StackTrace + ex.Message, tem);
OnWriteDarkCasket(e);
FINSError = shuttle + "更新时间错误。" + ex.StackTrace + ex.Message;
}
}
private static bool IsEquals(Array array1, Array array2, int arraylength)
{//20090902新增加arraylength
//比较类型是否一样
if ((array1 == null) || (array2 == null)) return false;
if (!Object.ReferenceEquals(array1.GetType(), array2.GetType()))
{
return false;
}
//比较长度是否一样
if (array1.GetLength(0) != array2.GetLength(0))
{
return false;
}
//比较成员是否对应相等
ValueType v1, v2;
for (int i = 0; i < arraylength; i++)
{
v1 = (ValueType)array1.GetValue(i);
v2 = (ValueType)array2.GetValue(i);
if (!v1.Equals(v2))
{
return false;
}
}
return true;
}
private static byte[] GetError(UInt16 D2121, UInt16 D2122)
{
byte[] t21 = UInt16ToBit(D2121, true);
byte[] t22 = UInt16ToBit(D2122, true);
//StringBuilder err = new StringBuilder();
byte[] err = new byte[32];
for (int j = 0; j < err.Length; j++)
{
if (j < 16)
{
//报警信息已在数据库中保存,
err[j] = t21[j];
}
else
{
err[j] = t22[j - 16];
}
}
return err;
}
private static int GetOrderFromMonitorIndex(int monitorIndex)
{
DataView dv = new DataView();
int order = 0;
try
{
//sql.Clear();
//sql.Append("select F_DeviceCommandIndex from t_monitor_task where F_monitorIndex = ").Append(monitorIndex);
dv = dbo.ExceSQL(string.Format("select F_DeviceCommandIndex from t_monitor_task where F_monitorIndex = {0}", monitorIndex)).Tables[0].DefaultView;
if (dv.Count > 0)
{
order = Convert.ToInt32(dv[0]["F_DeviceCommandIndex"]);
}
return order;
}
catch (Exception ex)
{
throw ex;
}
finally
{
dv.Dispose();
}
}
//从数据库中,返回车辆正在执行或已发送的指令
private static int GetMonitorTaskIndex(int shuttle)
{
DataView dv = new DataView();
int monitorindex = 0;
try
{
//sql.Clear();
//sql.Append("select F_ManTaskReserve,F_LockedState from t_base_device where f_deviceIndex = ").Append(shuttle);
dv = dbo.ExceSQL(string.Format("select F_ManTaskReserve, F_LockedState from t_base_device where f_deviceIndex = {0}", shuttle)).Tables[0].DefaultView;
if (dv.Count > 0)
{
//string manReserve = dv[0]["F_ManTaskReserve"].ToString();
//int fid = Convert.ToInt32(manReserve.Substring(1));
monitorindex = Convert.ToInt32(dv[0]["F_LockedState"]);
}
else
{
//sql.Clear();
//sql.Append("select f_monitorIndex from t_monitor_task where f_status > 0 and f_deviceIndex = ").Append(shuttle);
dv = dbo.ExceSQL(string.Format("select f_monitorIndex from t_monitor_task where f_status > 0 and f_deviceIndex = ", shuttle)).Tables[0].DefaultView;
if (dv.Count > 0)
{
//string manReserve = dv[0]["F_ManTaskReserve"].ToString();
//int fid = Convert.ToInt32(manReserve.Substring(1));
monitorindex = Convert.ToInt32(dv[0]["f_monitorIndex"]);
}
}
return monitorindex;
}
catch (Exception ex)
{
throw ex;
}
finally
{
dv.Dispose();
}
}
private static int GetManageTaskIndex(int rgvdev)
{
DataView dv = new DataView();
int fid = 0;
try
{
sql.Clear();
sql.Append("select F_ManTaskReserve,F_LockedState from t_base_device where f_deviceIndex = ").Append(rgvdev);
dv = dbo.ExceSQL(sql.ToString()).Tables[0].DefaultView;
if (dv.Count > 0)
{
string manReserve = dv[0]["F_ManTaskReserve"].ToString();
if (manReserve != "0")
{
fid = Convert.ToInt32(manReserve.Substring(1));
}
//monitorindex = Convert.ToInt32(dv[0]["F_LockedState"]);
}
return fid;
}
catch (Exception ex)
{
throw ex;
}
finally
{
dv.Dispose();
}
}
/// <summary>
///处理收到的消息——写PLC数据的应答处理
/// </summary>
/// <param name="message">消息数组</param>
private static void DisposeReceivedWriteMessage(int rgvdev)
{
DataView dv = new DataView();
try
{
int monitorindex = GetMonitorTaskIndex(rgvdev);
int order = GetOrderFromMonitorIndex(monitorindex);
if (monitorindex != 0)
{
//sql.Clear();
////RGV已接收任务 f_status = 2
//sql.Append("update t_monitor_Task set f_status = 2 where F_MonitorIndex = ").Append(monitorindex)
// .Append(" and f_deviceindex = ").Append(rgvdev);
dbo.ExceSQL(string.Format("update t_monitor_Task set f_status = 2 where F_MonitorIndex = {0} and f_deviceindex = {1}", monitorindex, rgvdev));
}
int[] tem = new int[1];
CWriteDarkCasketEventArgs e = new CWriteDarkCasketEventArgs("FINSTCPIP", "指令发送成功", "车号:" + rgvdev.ToString(), "任务号:" + monitorindex.ToString() + "命令字:" + order.ToString(), tem);
OnWriteDarkCasket(e);
}
catch (Exception ex)
{
int[] tem = new int[1];
CWriteDarkCasketEventArgs e = new CWriteDarkCasketEventArgs("FINSTCPIP:DisposeReceivedWriteMessage", "Error", rgvdev.ToString(), ex.StackTrace, tem);
OnWriteDarkCasket(e);
FINSError = rgvdev + "接收写指令处理错误。" + ex.StackTrace + ex.Message;
//throw ex;
}
finally
{
dv.Dispose();
}
}
private static byte[] UInt16ToBit(UInt16 src, bool bigEndian =false)
{
byte[] t = new byte[2];
if (bigEndian == true)
{
t[1] = (byte)((src >> 8) & 0xFF);
t[0] = (byte)(src & 0xFF);
}
else
{
t[0] = (byte)((src >> 8) & 0xFF);
t[1] = (byte)(src & 0xFF);
}
BitArray BA = new BitArray(t);
byte[] result = new byte[BA.Length];
for (int i = 0 ; i < BA.Count; i++)
{
bool b = BA.Get(i);
if (b == true)
{
result[i] = 1;
}
else
{
result[i] = 0;
}
}
return result;
}
public static void OnWriteDarkCasket(CWriteDarkCasketEventArgs e)
{
if (WriteDarkCasket != null)
{
WriteDarkCasket(null, e);
}
}
}
/// <summary>
/// 20210405 世仓穿梭板协议类(可理解为 DB2)
/// 创建者:zcy
/// </summary>
public class SHICANGReadData
{
public ushort D2100;
public ushort D2101;
public ushort D2102;
public ushort D2121;
public ushort D2122;
public ushort D2123;
public ushort D2129;
//车的电量是模拟量,会有波动,此处忽略波动
public bool Equal(SHICANGReadData rd )
{
if (this.D2100 == rd.D2100 && this.D2101 == rd.D2101 &&
(this.D2102 == rd.D2102 || this.D2102 == (rd.D2102 + 1) || this.D2102 == (rd.D2102 - 1)) &&
this.D2121 == rd.D2121 && this.D2122 == rd.D2122 && this.D2123 == rd.D2123 && this.D2129 == rd.D2129)
{
return true;
}
else
{
return false;
}
}
public void Update(SHICANGReadData rd)
{
this.D2100 = rd.D2100;
this.D2101 = rd.D2101;
this.D2102 = rd.D2102;
this.D2121 = rd.D2121;
this.D2122 = rd.D2122;
this.D2123 = rd.D2123;
this.D2129 = rd.D2129;
}
}
//世仓穿梭板的通用方法类,烟台万华项目整理,zcy
public static class SHICANGProtocol
{
public static StringBuilder sql = new StringBuilder();
public static DBOperator dbo = CClientTCPIP.dbo;
static Model.MDevice devinfo;
public static int NeedToBettey = 50;
private static void SendFINS(string ip, ushort startAddress , ushort length, byte[] _Sdata)
{
byte[] data = ClientCommunication.clientFinss[ip].GetInfo_DMWrite(startAddress, length, _Sdata);
ClientCommunication.socketFinss[ip].Send(data, null);
}
//穿梭板存货(入库) 不指定位置时location为0
public static void Order_SetGood(string ip, int taskindex ,int location = 0)
{
byte[] _Sdata = new byte[12];
_Sdata[0] = 0;
_Sdata[1] = 1; //自动作业码(入货/存货)
_Sdata[4] = 0;
_Sdata[5] = 0; //手动作业码
_Sdata[8] = Convert.ToByte((taskindex >> 8) & 255);
_Sdata[9] = Convert.ToByte(taskindex & 255); //调度任务号
_Sdata[10] = Convert.ToByte((location >> 8) & 255);
_Sdata[11] = Convert.ToByte(location & 255); //堆垛模式下存货区分
SendFINS(ip, 2001, 6, _Sdata);
return;
}
//穿梭板取货(出库),注:取货无法指定位置
public static void Order_GetGood(string ip, int taskindex)
{
byte[] _Sdata = new byte[10];
_Sdata[0] = 0;
_Sdata[1] = 2; //自动作业码(出货/取货)
_Sdata[4] = 0;
_Sdata[5] = 0; //手动作业码
_Sdata[8] = Convert.ToByte((taskindex >> 8) & 255);
_Sdata[9] = Convert.ToByte(taskindex & 255); //调度任务号
SendFINS(ip, 2001, 5, _Sdata);
return;
}
//开始充电,需要先将穿梭板送到充电位置,只有D2010=30
public static void Order_BeginCharge(string ip)
{
byte[] _Sdata = new byte[2];
_Sdata[0] = 0;
_Sdata[1] = 30; //充电控制(30:开始充电, 50:停止充电)
SendFINS(ip, 2010, 1, _Sdata);
return;
}
//停止充电,只有D2010=50
public static void Order_EndCharge(string ip )
{
byte[] _Sdata = new byte[2];
_Sdata[0] = 0;
_Sdata[1] = 50; //充电控制(30:开始充电, 50:停止充电)
SendFINS(ip, 2010, 1, _Sdata);
return;
}
//复位,只有D2003=6
public static void Order_ResetShuttle(string ip)
{
byte[] _Sdata = new byte[2];
_Sdata[0] = 0;
_Sdata[1] = 6; //6:清故障码
SendFINS(ip, 2003, 1, _Sdata);
return;
}
//回起点位,只有D2003=5
public static void Order_ToOrigin(string ip)
{
byte[] _Sdata = new byte[2];
_Sdata[0] = 0;
_Sdata[1] = 5; //5:回起点
SendFINS(ip, 2003, 1, _Sdata);
return;
}
//禁止Shuttle动作,在换成叉车模式后,发送
public static void Order_ForbidShuttleMove(string ip)
{
byte[] _Sdata = new byte[2];
_Sdata[0] = 0;
_Sdata[1] = 1; //1:禁止动作
SendFINS(ip, 2023, 1, _Sdata);
return;
}
//允许Shuttle动作,在发送Shuttle指令时
public static void Order_AllowShuttleMove(string ip)
{
byte[] _Sdata = new byte[2];
_Sdata[0] = 0;
_Sdata[1] = 0; //0:允许动作
SendFINS(ip, 2023, 1, _Sdata);
return;
}
//LYJL 提示穿梭板在充电巷道中 (项目不同会有变化)
public static void Order_InBetteyLocatLane(int shuttle)
{
devinfo = Model.CGetInfo.GetDeviceInfo(shuttle);
int z = GetZ(shuttle); int order = 0;
if (z == 1) { order = 97; } //一巷道的两个充电位
if (z == 2) { order = 98; } //二巷道的两个充电位
if (z == 3) { order = 99; } //三巷道的两个充电位
byte[] _Sdata = new byte[2];
_Sdata[0] = 0;
_Sdata[1] = (byte)order; //90+:在充电位的货架中,不同的充电架不一样
SendFINS(devinfo.RemoteIP, 2025, 1, _Sdata);
return;
}
// 提示穿梭板不在充电巷道中
public static void Order_NotInBetteyLocatLane(string ip)
{
byte[] _Sdata = new byte[2];
_Sdata[0] = 0;
_Sdata[1] = 0; //1:不在充电位的货架中
SendFINS(ip, 2025, 1, _Sdata);
return;
}
public const int TOASIDE = 12;//(掉头到A边)
public const int TOBSIDE = 7;//(掉头到B边)
public const int CHACHEMODE = 0; //叉车模式
public const int DUIDUOMODE = 1; //堆垛模式
//AB面变换,在堆垛机搬运后排坐标变化后调用,在一个通道中变换方向时调用
//只写D2001=7(掉头到B边),D2001=12(掉头到A边)
public static void Order_ChangeAB(string ip, int abside)
{
byte[] _Sdata = new byte[2];
_Sdata[0] = 0;
_Sdata[1] = (byte)abside;
SendFINS(ip, 2001, 1, _Sdata);
return;
}
//改变穿梭板模式,叉车模式/堆垛模式
public static void Order_ChangeMode(string ip, int mode)
{
byte[] _Sdata = new byte[2];
_Sdata[0] = 0;
_Sdata[1] = (byte)mode;
SendFINS(ip, 2000, 1, _Sdata);
return;
}
//返回数据库中穿梭板的位置,和货位相同格式
public static string GetShuttleLocation(int device)
{
DataView dv = new DataView();
try
{
//sql.Clear();
//sql.Append("select * from V_RGVINFO where F_DeviceIndex = ").Append(device);
dv = dbo.ExceSQL(string.Format("select * from V_RGVINFO where F_DeviceIndex = {0}", device)).Tables[0].DefaultView;
if (dv.Count > 0)
{
int z = Convert.ToInt32(dv[0]["F_rgvz"]);
int x = Convert.ToInt32(dv[0]["F_rgvx"]);
int y = Convert.ToInt32(dv[0]["F_rgvy"]);
int w = Convert.ToInt32(dv[0]["F_rgvw"]);
return ToLaneCoorZXYW(z, x, y, w);
}
return string.Empty;
}
catch (Exception ex)
{
throw ex;
}
finally
{
dv.Dispose();
}
}
#region 坐标转换
public static int GetZ(int shuttle)
{
DataView dv = new DataView();
try
{
//sql.Clear();
//sql.Append("select F_rgvz from V_RGVINFO where F_DeviceIndex = ").Append(shuttle);
dv = dbo.ExceSQL(string.Format("select F_rgvz from V_RGVINFO where F_DeviceIndex = {0}", shuttle)).Tables[0].DefaultView;
if (dv.Count > 0)
{
int z = Convert.ToInt32(dv[0]["F_rgvz"]);
return z;
}
return 0;
}
catch (Exception ex)
{
throw ex;
}
finally
{
dv.Dispose();
}
}
private static string ToLaneCoorZXYW(int z, int x, int y, int w = 0)
{
string coor = string.Format("{0:D2}-{1:D2}-{2:D2}-{3:D2}", z, x, y, w);
return coor;
//return string.Empty;
}
public static string ToLaneCoorZXY(int z, int x, int y)
{
string coor = string.Format("{0:D2}-{1:D2}-{2:D2}", z, x, y);
return coor;
//return string.Empty;
}
//将三维或四维的货架坐标转换为三维的
public static string ToLaneCoorZXY(string coorzxyw)
{
char[] cc = new char[1] { '-' };
string[] sp = coorzxyw.Split(cc);
if (sp.Length < 3)
{
return string.Empty; //转换为货位坐标,如果小于三维,则肯定不是货位
}
string coorzxy = sp[0] + "-" + sp[1] + "-" + sp[2];
return coorzxy;
}
#endregion
#region 车的位置
//获取所有穿梭板的四维坐标(包括不在线的穿梭板)
public static Dictionary<int, string> GetAllShuttleLocation()
{
DataView dv = new DataView();
Dictionary<int, string> coors = new Dictionary<int, string>();
try
{
//sql.Clear();
//sql.Append("select * from T_Base_RGVInfo "); //此处应考虑下线的车,不能从视图V_RGVINFO中获取
dv = dbo.ExceSQL(string.Format("select * from T_Base_RGVInfo ")).Tables[0].DefaultView;
for (int i = 0; i < dv.Count; i++)
{
int rgv = Convert.ToInt32(dv[i]["F_rgvIndex"]);
int z = Convert.ToInt32(dv[i]["F_rgvz"]);
int x = Convert.ToInt32(dv[i]["F_rgvx"]);
int y = Convert.ToInt32(dv[i]["F_rgvy"]);
int w = Convert.ToInt32(dv[i]["F_rgvw"]);
coors.Add(rgv, ToLaneCoorZXYW(z, x, y, w));
}
return coors;
}
catch (Exception ex)
{
throw ex;
}
finally
{
dv.Dispose();
}
}
//给一个货位坐标,返回在货位组内的穿梭板号,无穿梭板返回-1 (20211220 更新为四位的坐标)
public static int LaneCoorAlreadyHaveRGV(string coor)
{
if (IsCorrectCellCoor(coor) == false)
{
return -1;
}
bool checkzxy = false; //在充电位或换巷道的货位中,只检查三位坐标(当成了站台处理,站台只有三位坐标)
if (IsBetteyCoor(coor) == true || IsChangeLaneCell(coor) == true || coor.Length == 8)
{
checkzxy = true;
coor = ToLaneCoorZXY(coor);
}
string shuttleCell = string.Empty;
//所有车的三维坐标
Dictionary<int, string > coors = GetAllShuttleLocation();
foreach (int shuttle in coors.Keys)
{
if (checkzxy == true)
{
shuttleCell = ToLaneCoorZXY(coors[shuttle]);
}
else
{
shuttleCell = coors[shuttle];
}
if (shuttleCell == coor)
{
return shuttle;
}
}
return -1;
}
//穿梭板在充电位
public static bool ShuttleInBetteyLane(int device)
{
string rgvzxy = GetShuttleLocation(device);
return IsBetteyCoor(rgvzxy);
}
//穿梭板在换巷道的货位组内
public static bool ShuttleInChangeLane(int device)
{
string rgvzxy = GetShuttleLocation(device);
return IsChangeLaneCell(rgvzxy);
}
public static bool IsBetteyCoor(string coor)
{
DataView dv = new DataView();
try
{
string coorzxy = ToLaneCoorZXY(coor); //充电位只有三位坐标,只比较zxy即可
if (coorzxy == string.Empty)
{
return false;
}
//sql.Clear();
//sql.Append("select * from T_Base_Device where F_DeviceKindIndex = 9 and F_BindingDevice like '").Append(coorzxy).Append("%'");
dv = dbo.ExceSQL(string.Format("select * from T_Base_Device where F_DeviceKindIndex = 9 and F_BindingDevice like '{0}%'", coorzxy)).Tables[0].DefaultView;
if (dv.Count > 0)
{
return true;
}
return false;
}
catch (Exception ex)
{
throw ex;
}
finally
{
dv.Dispose();
}
}
//是换巷道货位
public static bool IsChangeLaneCell(string coor)
{
DataView dv = new DataView();
try
{
string coorzxy = ToLaneCoorZXY(coor); //只比较zxy即可
if (coorzxy == string.Empty)
{
return false;
}
//sql.Clear();
//sql.Append("select * from T_Base_Device where F_DeviceKindIndex = 13 and F_BindingDevice like '").Append(coorzxy).Append("%'");
dv = dbo.ExceSQL(string.Format("select * from T_Base_Device where F_DeviceKindIndex = 13 and F_BindingDevice like '{0}%'", coor)).Tables[0].DefaultView;
if (dv.Count > 0)
{
return true;
}
return false;
}
catch (Exception ex)
{
throw ex;
}
finally
{
dv.Dispose();
}
}
//穿梭板在正确的货位坐标中,在堆垛机上、或坐标是 0-0-0-0 表示不正确的货位坐标
private static bool IsCorrectCellCoor(string coor)
{
if (coor == string.Empty)
{
return false; //不是货位坐标
}
char[] cc = new char[1] { '-' };
string[] sp = coor.Split(cc);
if (sp.Length < 3)
{
return false;
}
if (Convert.ToInt32(sp[0]) == 0 || Convert.ToInt32(sp[0]) > 100)
{
return false; //排坐标不能是0,不能是堆垛机(堆垛机11001大于100)
}
if (Convert.ToInt32(sp[1]) == 0 || Convert.ToInt32(sp[2]) == 0)
{
return false; //列坐标不能是0,层坐标不能是0
}
return true;
}
#endregion
//穿梭板是否已连接
public static bool ShuttleConnected(string ip)
{
if (FINSTCPIP.ClientCommunication.clientFinss.ContainsKey(ip) == true)
{
if (FINSTCPIP.ClientCommunication.clientFinss[ip]._finsConnected == false)
{
// FINS 连接失败,
return false;
}
}
else
{
//无 FINS 连接,
return false;
}
return true;
}
//所有车的时间
public static DateTime GetTime(int shuttle)
{
DateTime dt = DateTime.MinValue;
DataView dv = new DataView();
try
{
//sql.Clear();
//sql.Append("select F_Time from T_Base_RGVInfo where F_RgvIndex =").Append(shuttle); //这行一直在报错,没有发现问题
dv = dbo.ExceSQL(string.Format("select F_Time from T_Base_RGVInfo where F_RgvIndex ={0}", shuttle)).Tables[0].DefaultView;
if (dv.Count > 0)
{
DateTime.TryParse(dv[0]["F_Time"].ToString(), out dt);
}
return dt;
}
catch(Exception ex)
{
throw ex;
}
finally
{
dv.Dispose();
}
}
}
}