using Hanhe.iWCS.Business;
using Hanhe.iWCS.Common;
using Hanhe.iWCS.MData;
using Hanhe.iWCS.Model;
using MongoDB.Bson;
using MongoDB.Driver;
using MongoDB.Driver.Builders;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using static Hanhe.iWCS.IndonesiaGLMProtocol.MESHelper;
using static Hanhe.iWCS.IndonesiaGLMProtocol.PLCControl;
namespace Hanhe.iWCS.IndonesiaGLMProtocol
{
///
/// ams接口辅助类
///
public class ApiHelper
{
private static ICallTaskProcessing callTaskProcessing = new ICallTaskProcessing();
static ApiHelper()
{
}
internal static SimpleResult SendTask(AddTaskModel model)
{
SimpleResult result = new SimpleResult();
if (model.taskType == 1)
{
//PLan A.当WMS调AMS生成空托出库任务时,直接拦截存入中间表,待到线程循环读取推送电梯一段任务时,优先推送
//MongoDBSingleton.Instance.Insert(new ElevatorTask { taskNo = DateTime.Now.ToString(), wmsTaskNo = DateTime.Now.ToString(), startBit = model.startBit, endBit = PLCControl.DeviceBit8(), wmsEndBit = model.endBit, startFloor = 1, endFloor = 3, sendFlag = 0, create = DateTime.Now.ToString() });
//Plan B.当WMS调AMS生成空托出库任务时,接受并创建空托出库任务,待到任务推送时,根据任务类型进行拦截
var r = AMSHelper.CreateTask(DateTime.Now.ToString(), model.startBit, model.endBit, "空托出库", 1);
result.success = r.success;
}
else if (model.taskType == 2)
{
//1楼成品货架区到1楼出库缓存位 --此任务需要添加虚拟终点,根据1楼出库缓存位的广电信号来分配AGV一个终点(四个点位,空的则可以入)
//WMS不需要传输终点,终点由AMS根据光电PLC信号,判断哪个信号是空的,再通知AGV终点,在此之前先使用虚拟终点
var r = AMSHelper.CreateTask(DateTime.Now.ToString(), model.startBit, model.endBit, "成品出库", 1);
result.success = r.success;
}
else if (model.taskType == 3)
{
//PDA:1楼空托线边区到1楼成品空托位 ——应该有起点和终点位,直接推送——需反馈WMS任务状态
var r = AMSHelper.CreateTask(DateTime.Now.ToString(), model.startBit, model.endBit, "空托线边", 1);
result.success = r.success;
}
return result;
}
public class AddTaskModel
{
///
/// 任务起点
///
public string startBit { get; set; }
///
/// 任务终点
///
public string endBit { get; set; }
///
/// 任务类别 1.1楼成品空托区到3楼补给成品空托区
/// 2.1楼成品货架区到1楼出库缓存位
/// 3.PDA:1楼空托线边区到1楼成品空托位
///
public int taskType { get; set; }
}
public class SimpleResult
{
public bool success { get; set; }
public int errCode { get; set; }
public string errMsg { get; set; }
}
public class CheckItemInfoResult
{
public bool success { get; set; }
public int errCode { get; set; }
public string errMsg { get; set; }
///
/// 批次号
///
public string batchNo { get; set; }
///
/// 袋号
///
public string bagNo { get; set; }
}
#region NG任务设备状态
internal static SimpleResult NgTask(NgTaskModel model)
{
SimpleResult result = new SimpleResult();
if (model.fcBit == 0)
{
var setus = MongoDBSingleton.Instance.FindOne(Query.EQ("bzBit", model.bzBit), "NgTaskModel");
if (setus == null)
{
MongoDBSingleton.Instance.Insert(new NgTaskModel { fcBit = model.fcBit, fcSetus = model.fcSetus, bzBit = model.bzBit, bzSetus = model.bzSetus });
}
else
{
var updateBuider = Update.Set("fcBit", model.fcBit).Set("fcSetus", model.fcSetus).Set("bzBit", model.bzBit).Set("bzSetus", model.bzSetus);
MongoDBSingleton.Instance.Update(Query.EQ("bzBit", model.bzBit), updateBuider, UpdateFlags.None);
}
}
else
{
var setus = MongoDBSingleton.Instance.FindOne(Query.EQ("fcBit", model.fcBit), "NgTaskModel");
if (setus == null)
{
//SecondWeighState
MongoDBSingleton.Instance.Insert(new NgTaskModel { fcBit = model.fcBit, fcSetus = model.fcSetus, bzBit = model.bzBit, bzSetus = model.bzSetus });
MongoDBSingleton.Instance.Update(Query.EQ("location", GetSecondWeighBit()), Update.Set("ng", 2), UpdateFlags.None);
}
else
{
var updateBuider = Update.Set("fcBit", model.fcBit).Set("fcSetus", model.fcSetus).Set("bzBit", model.bzBit).Set("bzSetus", model.bzSetus);
MongoDBSingleton.Instance.Update(Query.EQ("fcBit", model.fcBit), updateBuider, UpdateFlags.None);
MongoDBSingleton.Instance.Update(Query.EQ("location", GetSecondWeighBit()), Update.Set("ng", model.fcSetus), UpdateFlags.None);
}
}
return result;
}
public class NgTaskModel
{
///
/// 默认情况下全都都传0
///
public ObjectId _id { get; set; }
///
/// 复称平台点位 复称平台有问题,就传值1
///
public int fcBit { get; set; }
///
/// 复称平台状态 复称平台有问题的情况下,传值2
///
public int fcSetus { get; set; }
///
/// 包装点位 包装机有问题,传包装机数字编号,例如1~9
///
public int bzBit { get; set; }
///
/// 包装状态 包装机有问题的情况下,传值2
///
public int bzSetus { get; set; }
}
#endregion
#region MES接口模拟测试
internal static MESData MESTest(MESSendData model)
{
MESData result = new MESData();
var mesRequst = MongoDBSingleton.Instance.FindOne(Query.EQ("machineNo", model.machineNo), "MESReSult");
if (mesRequst != null)
{
result.machineNo = mesRequst.machineNo;
result.lotNo = mesRequst.lotNo;
result.bagNo = mesRequst.bagNo;
result.productType = mesRequst.productType;
result.materialCode = mesRequst.materialCode;
result.overlappingLayers = mesRequst.overlappingLayers;
}
else
{
MongoDBSingleton.Instance.Insert(new MESReSult { machineNo = "T1" });
}
return result;
}
public class MESSendData
{
///
/// 包装机号
///
public string machineNo { get; set; }
}
public class MESTaskData
{
///
/// 包装补空点
///
public string emptyPoint { get; set; }
}
public class MESReSult
{
public ObjectId _id { get; set; }
///
/// mes返回的包装机号(T1,T2,......,T9)
///
public string machineNo { get; set; }
///
/// mes返回的成品批次号
///
public string lotNo { get; set; }
///
/// mes返回的袋号
///
public string bagNo { get; set; }
///
/// mes返回的产品型号
///
public string productType { get; set; }
///
/// mes返回的物料编码
///
public string materialCode { get; set; }
///
/// mes返回的叠包层数 (例1,2,3:1代表不叠包,2代表叠2层,3代表叠3层)
///
public string overlappingLayers { get; set; }
}
public class MESData
{
///
/// mes返回的包装机号(T1,T2,......,T9)
///
public string machineNo { get; set; }
///
/// mes返回的成品批次号
///
public string lotNo { get; set; }
///
/// mes返回的袋号
///
public string bagNo { get; set; }
///
/// mes返回的产品型号
///
public string productType { get; set; }
///
/// mes返回的物料编码
///
public string materialCode { get; set; }
///
/// mes返回的叠包层数 (例1,2,3:1代表不叠包,2代表叠2层,3代表叠3层)
///
public string overlappingLayers { get; set; }
}
#endregion
#region Json数据写入写出中间表测试
public static int[] machinedown = new int[16];
internal static JsonData Json(JsonData model)
{
JsonData result = new JsonData();
for (int i = 0; i <= 15; i++)
{
machinedown[i] = i;
}
var json = JsonConvert.SerializeObject(machinedown);
//Console.WriteLine("json数据" + json);
var jsonMachine = MongoDBSingleton.Instance.FindOne(Query.EQ("order", model.order), "JsonDataMod");
var arr = JsonConvert.DeserializeObject(jsonMachine.jsonOne);
//Console.WriteLine("var数据" + arr);
if (jsonMachine != null)
{
result.jsonOne = jsonMachine.jsonOne;
result.jsonTwo = jsonMachine.jsonTwo;
result.jsonThree = jsonMachine.jsonThree;
}
else
{
MongoDBSingleton.Instance.Insert(new JsonDataMod { order = model.order, jsonOne = json });
}
var arr1 = JsonConvert.DeserializeObject>(jsonMachine.jsonOne);
//Console.WriteLine("数组数据:" + arr1);
for (int i = 0; i <= 15; i++)
{
//Console.WriteLine($"循环打印数组单个数据{arr1[i]}");
}
return result;
}
public class JsonData
{
public int order { get; set; }
public string jsonOne { get; set; }
public JsonConverter jsonTwo { get; set; }
public JsonData jsonThree { get; set; }
}
public class JsonDataMod
{
public ObjectId _id { get; set; }
public int order { get; set; }
public string jsonOne { get; set; }
public JsonConverter jsonTwo { get; set; }
public JsonData jsonThree { get; set; }
}
#endregion
public class AgvStateModel
{
///
/// X坐标
///
public int XCoordinates { get; set; }
///
/// Y坐标
///
public string YCoordinates { get; set; }
///
/// 方向
///
public int direction { get; set; }
}
public class cameraModel
{
///
/// 点位
///
public string site { get; set; }
///
/// 状态
///
public int state { get; set; }
}
public class FCKTInModel
{
///
/// 终点货位
///
public string end_loc { get; set; }
}
public class ItemOutModel
{
///
/// 终点库区
///
public string S_END_AREA { get; set; }
}
#region 教称流程,人工PDA返回复称平台,包装机复称信息
internal static SimpleResult SecondResult(secondResultCache model)
{
SimpleResult result = new SimpleResult();
var weigh = MongoDBSingleton.Instance.FindOne(Query.EQ("Bit", model.Bit), "secondResult");
if (weigh != null)
{
MongoDBSingleton.Instance.Update(Query.EQ("Bit", model.Bit), Update.Set("Bit", model.Bit).Set("Status", model.Status), UpdateFlags.None);
result.success = true;
CMMLog.Info($"返回状态接口调用成功,当前点位:{model.Bit},点位状态:{model.Status}");
//Console.WriteLine($"返回状态接口调用成功,当前点位:{model.Bit},点位状态:{model.Status}");
}
else
{
MongoDBSingleton.Instance.Insert(new secondResult { Bit = model.Bit, Status = model.Status });
result.success = true;
CMMLog.Info($"返回状态接口调用成功,当前点位:{model.Bit},点位状态:{model.Status}");
//Console.WriteLine($"返回状态接口调用成功,当前点位:{model.Bit},点位状态:{model.Status}");
}
if (model.Bit == GetSecondWeighBit())
{
int i = model.Status == "OK" ? 1 : 2;
MongoDBSingleton.Instance.Update(Query.EQ("location", GetSecondWeighBit()), Update.Set("secondNg", i));
}
return result;
}
internal static SimpleResult AgvState(AgvStateModel model)
{
SimpleResult result = new SimpleResult();
return result;
}
///
/// AGV状态处理
///
///
internal static void AGVDeviceReceiveSet(AgvDeviceStatus a)
{
if (!string.IsNullOrEmpty(a.forkliftNo))
{
var agvStateInfo = MongoDBSingleton.Instance.FindOne(Query.EQ("forkliftNo", a.forkliftNo), "AGV_STATE");
if (agvStateInfo != null)
{
if (string.IsNullOrEmpty(a.xPos)) a.xPos = "0";
if (string.IsNullOrEmpty(a.yPos)) a.yPos = "0";
var query1 = Query.EQ("forkliftNo", a.forkliftNo);
UpdateBuilder updateBuider = Update.Set("forkliftNo", a.forkliftNo).
Set("errCode", a.errCode).Set("errCode2", a.errCode2).
Set("faildCode", a.faildCode).Set("xPos", a.xPos).
Set("yPos", a.yPos).Set("battery", a.battery).Set("goods_visible", a.goods_visible).
Set("Degree", a.Degree);
MongoDBSingleton.Instance.Update(query1, updateBuider, UpdateFlags.None);
}
else
{
MongoDBSingleton.Instance.Insert(new AGV_STATE { forkliftNo = a.forkliftNo, errCode = a.errCode, errCode2 = a.errCode2, faildCode = a.faildCode, xPos = a.xPos, yPos = a.yPos, battery = a.battery, goods_visible = a.goods_visible, Degree = a.Degree });
}
}
}
///
/// 成品出库
///
///
///
internal static SimpleResult ItemOut(ItemOutModel model)
{
//成品出库流程:人工pad调用ams提供的接口,ams查询库区空的货位,然后调用wms接口,将空的货位的数量传给wms
SimpleResult result = new SimpleResult { success = false, errCode = -1 };
var areaList = MongoDBSingleton.Instance.Find(Query.EQ("S_AREA_CODE", model.S_END_AREA), "CPCKArea").ToList();
if (areaList.Count > 0)
{
for (int i = areaList.Count - 1; i >= 0; i--)
{
if (areaList[i].N_CURRENT_NUM == areaList[i].N_CAPACITY)
{
areaList.Remove(areaList[i]);
}
}
}
if (areaList.Count > 0)
{
CMMLog.Info($"成品缓存架出库任务,查询到可入库的货位数量为:{areaList.Count}");
//调用wms接口生成出库任务
foreach (var a in areaList)
{
CMMLog.Info($"成品缓存架出库任务,当前货位编码:{a.S_LOC_CODE}");
bool req = WMSHelper.WMSOut(a.S_LOC_CODE, "");
if (req)
{
result.success = true;
result.errCode = 0;
CMMLog.Debug($"调用WMS获取成品缓存架出库任务成功!终点货位编码:{a.S_LOC_CODE}");//现在任务由WMS自己下发,AMS做拦截处理(查询ext1里面对应的任务类型,并更改任务类型)
}
else
{
CMMLog.Debug($"调用WMS获取成品缓存架出库任务失败!终点货位编码:{a.S_LOC_CODE}");
result.errMsg = $"调用WMS获取成品缓存架出库任务失败!终点货位编码:{a.S_LOC_CODE}";
}
}
}
else
{
result.errMsg = $"该库区未找到可用货位,库区编码:{model.S_END_AREA}";
}
return result;
}
internal static SimpleResult CameraInfo(cameraModel a)
{
SimpleResult result = new SimpleResult();
var cameraInfo = MongoDBSingleton.Instance.FindOne(Query.EQ("site", a.site), "CameraTable");
if (cameraInfo != null)
{
if (cameraInfo.site == a.site && cameraInfo.state == a.state)
{
cameraInfo.time += 1;
MongoDBSingleton.Instance.Update(Query.EQ("site", a.site), Update.Set("time", cameraInfo.time), UpdateFlags.None);
}
else
{
MongoDBSingleton.Instance.Remove(Query.EQ("site", a.site), RemoveFlags.Single);
}
}
else
{
if (a.state == 0)
{
MongoDBSingleton.Instance.Insert(new CameraTable
{
site = a.site,
state = a.state,
time = 1
}, "CameraTable");
}
}
try
{
var cameraInfoList = MongoDBSingleton.Instance.FindAll("CameraTable");
if (cameraInfoList.Count > 0)
{
cameraInfoList.ForEach(it => {
if (it.time > 0)
{
CMMLog.Info("CameraTable表大于10次的数据:" + JsonConvert.SerializeObject(cameraInfoList));
//调用wms解绑接口
result.success = WMSHelper.WMSEmptyUnbind(it.site);
if (result.success)
{
MongoDBSingleton.Instance.Remove(Query.EQ("site", it.site), RemoveFlags.Single);
result.errCode = 0;
}
CMMLog.Info($"发货货架解绑成功,货位号:{it.site}");
//并将货位空满置为0
var locInfo = MongoDBSingleton.Instance.FindOne(Query.EQ("S_LOC_CODE", it.site), "FCKTArea");
if (locInfo == null)
{
FCKTArea area = new FCKTArea
{
S_LOC_CODE = it.site,
N_CURRENT_NUM = 0,
N_CAPACITY = 1,
};
MongoDBSingleton.Instance.Insert(area);
}
else
{
if (locInfo.N_CURRENT_NUM > 0) locInfo.N_CURRENT_NUM = locInfo.N_CURRENT_NUM - 1;
MongoDBSingleton.Instance.Update(Query.EQ("S_LOC_CODE", it.site), Update.Set("N_CURRENT_NUM", locInfo.N_CURRENT_NUM), UpdateFlags.None);
}
}
});
}
}
catch (Exception ex)
{
CMMLog.Error(ex.Message, ex);
}
return result;
}
internal static SimpleResult FCKTIn(FCKTInModel models)
{
SimpleResult result = new SimpleResult { success = false, errCode = -1 };
var FCInfo = MongoDBSingleton.Instance.FindOne(Query.EQ("S_LOC_CODE", models.end_loc), "FCKTArea");
if (FCInfo != null)
{
if (FCInfo.N_CURRENT_NUM < FCInfo.N_CAPACITY)
{
var taskInfo = MongoDBSingleton.Instance.FindOne(Query.Or(Query.EQ("CN_S_END_BIT", models.end_loc), Query.EQ("CN_S_START_BIT", models.end_loc)), "TN_I_TASK_MST");
if (taskInfo == null)
{
result.success = true;
result.errCode = 0;
}
else
{
result.errMsg = $"该点位有执行中的任务,任务号:{taskInfo.CN_S_TASK_NO}";
}
}
else
{
result.errMsg = $"当前货位不可用,货位数量已满";
}
}
else
{
result.errMsg = $"当前货位未维护,货位编码:{models.end_loc}";
}
return result;
}
internal static CheckItemInfoResult CheckItemInfo(string trayCode)
{
CheckItemInfoResult result = new CheckItemInfoResult() { success = false, errCode = -1 };
var machine = MongoDBSingleton.Instance.FindOne(Query.EQ("trayCode", trayCode), "MachineInfoTwo");
if (machine != null)
{
result.bagNo = machine.bagNo;
result.batchNo = machine.lotNo;
result.success = true;
result.errCode = 0;
}
else
{
result.errMsg = $"未在表中根据托盘号查询到数据,托盘号:{trayCode}";
}
return result;
}
internal static SimpleResult CheckTrayInfo(string trayCode)
{
SimpleResult result = new SimpleResult() { success = false, errCode = -1 };
var machineInfo = MongoDBSingleton.Instance.FindOne(Query.EQ("trayCode", trayCode), "MachineInfoTwo");
if (machineInfo != null)
{
//写入数据
var plc = Settings.GetPlcInfo().Where(a => a.deviceType == "3").FirstOrDefault();
if (plc != null)
{
var arr = JsonConvert.DeserializeObject>(machineInfo.jsonData);
int[] num = new int[94];
num[0] = 1;
num[1] = 0;
num[2] = 0;
for (int i = 3; i <= 93; i++) num[i] = arr[i - 3];
CMMLog.Info($"send num:{JsonConvert.SerializeObject(num)}");
var wirteall01 = OITcpHelper.RegisterWriteOutPutMulti(new OITcpHelper.RegisterWriteOutPutModelMulti
{
addr = plc.writeAddr + 7,
host = plc.ip,
port = plc.port,
data = num
});
CMMLog.Debug($"写入设备{plc.location}通道{plc.writeAddr + 10}里面数据为:{JsonConvert.SerializeObject(num)}.");
MongoDBSingleton.Instance.Remove(Query.EQ("trayCode", trayCode), RemoveFlags.None);
var wirte = OITcpHelper.RegisterWriteOutPut(new OITcpHelper.RegisterWriteOutPutModel
{
addr = plc.writeAddr,
host = plc.ip,
port = plc.port,
data = 1
});
CMMLog.Debug($"写入设备{plc.location}通道{plc.writeAddr}里面数据为1.");
result.success = true;
result.errCode = 0;
}
else
{
result.errMsg = $"叠包机未配置";
}
}
else
{
result.errMsg = $"未在表中查询到该托盘码数据,托盘码:{trayCode}";
}
return result;
}
public class FCKTArea
{
public ObjectId _id { get; set; }
///
/// 货位编码
///
public string S_LOC_CODE { get; set; }
///
/// 当前数量
///
public int N_CURRENT_NUM { get; set; }
///
/// 容量
///
public int N_CAPACITY { get; set; }
}
public class CameraTable
{
public ObjectId _id { get; set; }
///
/// 点位
///
public string site { get; set; }
///
/// 状态
///
public int state { get; set; }
///
/// 接收到了数据次数
///
public int time { get; set; }
}
///
/// 成品出库库区
///
public class CPCKArea
{
public ObjectId _id { get; set; }
///
/// 库区编码
///
public string S_AREA_CODE{ get; set; }
///
/// 货位编码
///
public string S_LOC_CODE { get; set; }
///
/// 货位容量
///
public int N_CAPACITY { get; set; }
///
/// 当前数量
///
public int N_CURRENT_NUM { get; set; }
}
public class AGV_STATE
{
public ObjectId _id { get; set; }
public string forkliftNo { get; set; }
///
/// 停止状态码
///
public string errCode { get; set; } = "";
///
/// 停止状态码2
///
public string errCode2 { get; set; } = "";
///
/// 失败状态码
///
public string faildCode { get; set; } = "";
///
/// 车辆X坐标(CM)
///
public string xPos { get; set; } = "0";
///
/// 车辆Y坐标(Y)
///
public string yPos { get; set; } = "0";
///
/// 电池电量
///
public string battery { get; set; } = "";
public string detail { get; set; }
///
/// 是否有货状态码
///
public string goods_visible { get; set; } = "";
///
/// 方向
///
public string Degree { get; set; } = "";
}
public class secondResultCache
{
///
/// 教称点位
///
public string Bit { get; set; }
///
/// 教称点位状态
///
public string Status { get; set; }
}
public class secondResult
{
public ObjectId _id { get; set; }
///
/// 教称点位
///
public string Bit { get; set; }
///
/// 教称点位状态
///
public string Status { get; set; }
}
public class ReturnResult
{
public int ResultCode { get; set; }
public string ResultMsg { get; set; }
}
///
/// hosttoagv上报车辆状态(参数在hosttoagv服务配置,可修改)
///
public class AgvDeviceStatus
{
public string infoType { get; set; }
public string inMapRoute { get; set; }
//public string detail { get; set; }
public string CumInfo { get; set; }
public string forkliftNo { get; set; }
///
/// 停止状态码
///
public string errCode { get; set; } = "";
///
/// 停止状态码2
///
public string errCode2 { get; set; } = "";
///
/// 失败状态码
///
public string faildCode { get; set; } = "";
///
/// 车辆X坐标(CM)
///
public string xPos { get; set; } = "";
///
/// 车辆Y坐标(Y)
///
public string yPos { get; set; } = "";
///
/// 电池电量
///
public string battery { get; set; } = "";
///
/// 是否有货状态码
///
public string goods_visible { get; set; } = "";
///
/// 方向
///
public string Degree { get; set; } = "";
}
#endregion
}
}