You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

544 lines
20 KiB
C#

2 months ago
using HslCommunication.Core;
using Mesnac.Compressor.Entity;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Newtonsoft.Json.Linq;
using SlnMesnac.Common;
using SlnMesnac.Config;
using SlnMesnac.Model.domain;
using SlnMesnac.Plc;
using SlnMesnac.Serilog;
using SqlSugar;
using System.Collections;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
namespace ConsoleApp
{
internal class MainCentralControl
{
private IHost host;
// 新增一个标志位,用于表示方法是否正在执行
private static String StationCode;
private bool isExecuting = false;
private AppConfig _appConfig;
private readonly SerilogHelper _logger;
private IServiceProvider serviceProvider;
private ISqlSugarClient SqlSugarClient;
public List<PlcAbsractFactory> plcList;
IByteTransform ByteTransform = new ReverseBytesTransform();
public bool isConnect;
public string State;
private StationInfo _stationInfo;
private object _mcValue;
//PLC心跳地址
private string _plcHeartBeatAddress;
//PLC工作请求地址
private string _workAskAddress;
//PLC工作完成放行请求地址
private string _completeAskAddress;
public MainCentralControl(IHost host)
{
this.host = host;
_appConfig = host.Services.GetService<AppConfig>();
StationCode = _appConfig.StationCode;
SqlSugarClient = host.Services.GetRequiredService<ISqlSugarClient>();
_logger = host.Services.GetRequiredService<SerilogHelper>();
plcList = host.Services.GetRequiredService<List<PlcAbsractFactory>>();
}
public void Start()
{
init();
StartCheckStatus();
ListeningPlcValue();
_logger.Info("iMES系统启动成功!");
}
2 months ago
/// <summary>
/// 初始化加载PLC地址不同工位PLC提供的地址不同
/// </summary>
2 months ago
private void init()
{
try
{
switch (StationCode)
{
case "S130-1":
_plcHeartBeatAddress = "D7777";
_completeAskAddress = "D7703";
break;
case "S130-2":
_plcHeartBeatAddress = "D7777";
_workAskAddress = "";
_completeAskAddress = "";
break;
}
}
catch (Exception ex)
{
}
}
/// <summary>
/// 监听PLC地址值
/// </summary>
private void ListeningPlcValue()
{
Task.Run(async () =>
{
while (true)
{
try
{
PlcAbsractFactory? Plc = plcList.FirstOrDefault(x => x.ConfigKey == "plc");
if (Plc == null || !Plc.IsConnected)
{
_logger.Plc(DateTime.Now + "PLC未连接,请检查网络!");
continue;
}
//读取PLC工作请求放行请求
switch (StationCode)
{
case "S130-1":
if (Plc.readInt16ByAddress(_completeAskAddress) == 1)
{
Plc.writeInt16ByAddress(_completeAskAddress, 0);
SaveStationDataTask(Plc);
}
break;
case "S130-2":
//读取PLC工作请求
if (Plc.readInt16ByAddress(_workAskAddress) == 1)
{
Plc.writeInt16ByAddress(_workAskAddress, 0);
//根据转子码查询上工位是否合格
SelectStationQuality(Plc);
}
//读取PLC放行请求
if (Plc.readInt16ByAddress(_completeAskAddress) == 1)
{
Plc.writeInt16ByAddress(_completeAskAddress, 0);
//存盘
}
break;
}
}
catch (Exception ex)
{
_logger.Error($"ListeningPlcValue方法异常:" + ex.StackTrace);
}
finally
{
Thread.Sleep(1000);
}
}
});
}
/// <summary>
/// 判断数据库表是否已存在条码数据,存在则更新,不存在则插入
/// </summary>
/// <param name="ProductBarCode"></param>
/// <returns></returns>
private Datastation IsExistData(string ProductBarCode)
{
Datastation datastation = null;
try
{
SqlSugarClient.Queryable<Datastation>().Any(x => x.Partsns.Contains(ProductBarCode));
datastation = SqlSugarClient.Queryable<Datastation>().First(it => it.Partsns.Contains(ProductBarCode));
if (datastation != null)
{
return datastation;
}
return datastation;
}
catch (Exception ex)
{
return datastation;
}
}
/// <summary>
/// S130-1工位存盘
/// </summary>
/// <param name="Plc"></param>
private async void SaveStationDataTask(PlcAbsractFactory Plc)
{
try
{ //主线码
byte[] SemBarCode = Plc.readValueByAddress("D7701", 20);
string barcode = ByteTransform.TransString(SemBarCode, 0, 20, Encoding.ASCII);
partsns partsns = new partsns();
partsns.sn.Add(barcode);
//数据
string jsonString = StringChange.ModeToJson(partsns);
D data1 = new D()
{
n = "转子压装位置1压力值",
t = 0,
ng = int.Parse(Plc.readFloatByAddress("D7708").ToString()),
v = Plc.readFloatByAddress("D7705").ToString(),
min = Plc.readFloatByAddress("D7706").ToString(),
max = Plc.readFloatByAddress("D7707").ToString(),
};
D data2 = new D()
{
n = "转子压装位置2压力值",
t = 0,
ng = int.Parse(Plc.readFloatByAddress("D7712").ToString()),
v = Plc.readFloatByAddress("D7709").ToString(),
min = Plc.readFloatByAddress("D7710").ToString(),
max = Plc.readFloatByAddress("D7711").ToString(),
};
D data3 = new D()
{
n = "转子压装位置3压力值",
t = 0,
ng = int.Parse(Plc.readFloatByAddress("D7716").ToString()),
v = Plc.readFloatByAddress("D7713").ToString(),
min = Plc.readFloatByAddress("D7714").ToString(),
max = Plc.readFloatByAddress("D7715").ToString(),
};
D data4 = new D()
{
n = "转子压装位置4位移值",
t = 0,
ng = 1,
v = Plc.readFloatByAddress("D7717").ToString(),
min = Plc.readFloatByAddress("D7718").ToString(),
max = Plc.readFloatByAddress("D7719").ToString(),
};
D data5 = new D()
{
n = "转子压装位置4压力值",
t = 0,
ng = int.Parse(Plc.readFloatByAddress("D7724").ToString()),
v = Plc.readFloatByAddress("D7721").ToString(),
min = Plc.readFloatByAddress("D7722").ToString(),
max = Plc.readFloatByAddress("D7723").ToString(),
};
Root root = new Root();
root.d.Add(data1);
root.d.Add(data2);
root.d.Add(data3);
root.d.Add(data4);
root.d.Add(data5);
string datastring = StringChange.ModeToJson(root);
//查询是否已经存在数据,存在则更新不存在则保存
Datastation datastation = IsExistData(barcode);
if (datastation != null)
{
//更新
datastation.Stime = DateTime.Now;
datastation.Stationid = StationCode;
datastation.Ng = Plc.readFloatByAddress("D7708").ToString() == "1" ? 0 : 1;
datastation.Partsns = jsonString;
datastation.Paratemp = datastring;
int LockFlag = SqlSugarClient.Updateable(datastation).ExecuteCommand();
Console.WriteLine(StringChange.ModeToJson(datastation));
_logger.Info(StringChange.ModeToJson(datastation));
}
else
{
datastation = new Datastation()
{
Stime = DateTime.Now,
Stationid = StationCode,
Productid = "",
Partid = "",
Modelid = "",
Ng = Plc.readFloatByAddress("D7708").ToString() == "1" ? 0 : 1,
Proc = 0,
Sublinenum = 0,
Sublinesnnum = 0,
Partsnnum = 1,
Sublineids = "",
Partsns = jsonString,
Sublinesns = StringChange.ModeToJson(new partsns()),
Paratemp = datastring,
Stringtemp = "",
GroupStationId = "",
Renum = "0",
};
//存盘
int id = SqlSugarClient.Insertable(datastation).ExecuteReturnIdentity();
Plc.writeInt16ByAddress("D7704", 1);
Console.WriteLine(StringChange.ModeToJson(datastation));
_logger.Info(StringChange.ModeToJson(datastation));
}
}
catch (Exception ex)
{
_logger.Error($"存盘异常{ex.Message}");
}
}
/// <summary>
/// 查询上工位是否有数据无数据或NG则下发PLC报警提示
/// </summary>
/// <param name="Plc"></param>
private async void SelectStationQuality(PlcAbsractFactory Plc)
{
try
{
byte[] SemBarCode = Plc.readValueByAddress("D7701", 20);
string ZZBarCode = ByteTransform.TransString(SemBarCode, 0, 20, Encoding.ASCII);
Datastation datastation = IsExistData(ZZBarCode);
if (datastation != null)
{
if (datastation.Ng != 0)
{
//下发PLC上工位不合格
Plc.writeInt16ByAddress("", 1);
}
}
//上工位无数据
else
{
//下发PLC上工位不合格
Plc.writeInt16ByAddress("", 1);
}
}
catch (Exception ex)
{
_logger.Error($"上工位查询异常{ex.Message}");
}
}
/// <summary>
/// PLC心跳检测重连机制
/// </summary>
private void StartCheckStatus()
{
Task.Run(async () =>
{
while (true)
{
try
{
foreach (var plc in plcList)
{
PlcConfig? plcConfig = host.Services.GetService<AppConfig>().plcConfig.FirstOrDefault(x => x.plcKey == plc.ConfigKey);
if (plc != null && plc.IsConnected)
{
plc.IsConnected = plc.readHeartByAddress(_plcHeartBeatAddress); //DB100.DBX0.0
if (!plc.IsConnected)
{
plc.IsConnected = await plc.ConnectAsync(plcConfig.plcIp, plcConfig.plcPort);
}
}
else
{
if (plcConfig != null)
{
bool result = await plc.ConnectAsync(plcConfig.plcIp, plcConfig.plcPort);
plc.IsConnected = result;
}
}
}
}
catch (Exception ex)
{
_logger.Error($"监听PLC设备状态异常:{ex.Message}");
}
await Task.Delay(1000 * 10);
}
});
}
#region 中际产线弃用逻辑
private bool TryObject(object value, out object[] arry)
{
arry = null;
try
{
arry = (object[])value;
return true;
}
catch (Exception ex)
{
return false;
}
}
public stationPara ParaFormart(object[] obj, int paraCount)
{
byte[] bytes = obj.Select(o => Convert.ToByte(o)).ToArray();
string str = Convert.ToString(Convert.ToInt32(bytes[2]), 2).PadLeft(8, '0');
string[] items = new string[8];
for (int i = 0; i < items.Length; i++)
{
items[i] = str[i].ToString();
}
Array.Reverse(items);
//byte[] bools = ByteTransform.TransByte(bytes, 2,1);
isConnect = Convert.ToInt32(items[0]) == 1;
State = Convert.ToInt32(items[1]).ToString();
stationPara sinfo = new stationPara();
int index = 0;
//是否重投
if (sinfo.Restart)
{
//ICSharpCode.Core.LoggingService.Info(StationInfo.StationCode + ",开始重投");
}
//是否有主线二维码
sinfo.BarcodeUpdate = Convert.ToInt32(items[3]) == 1;
//是否有支线二维码
sinfo.MaterialBarcodeUpdate = Convert.ToInt32(items[4]) == 1;
index++;
//自动模式
//重构,收到作业或放行请求才进行解析
//PLC工作请求信号
sinfo.AskWork = ByteTransform.TransInt16(bytes, 5) > 0;
index++;
//放行请求
sinfo.MaskID = ByteTransform.TransInt16(bytes, 7);
sinfo.NewFlag = sinfo.MaskID > 0 ? true : false;
index += 3;
//当前机种号
sinfo.machineID = ByteTransform.TransByte(bytes, 13);
string NewMachineID = sinfo.machineID.ToString();
index++;
//托盘号
int intNum = ByteTransform.TransByte(bytes, 15);
//支线条码状态
index++;
bool[] bools2 = ByteTransform.TransBool(bytes, 16, 1);
//ArrayList array2 = ConvertToList(bools2);
//数据保存区
index++;
sinfo.ProductOkNg = ByteTransform.TransByte(bytes, 19);
index++;
//线体代号ABC'
int gongxu = ByteTransform.TransByte(bytes, 21);
sinfo.RFIDNo = string.Format("{0:X}", gongxu) + intNum.ToString().PadLeft(2, '0');
index += 1;
//sinfo.productDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");//这里不用日期了
if (sinfo.BarcodeUpdate || sinfo.MaterialBarcodeUpdate)
{
GetBarcodeList(bytes, index, ref sinfo);
}
index = 180;
for (int i = 0; i < paraCount; i++)
{
dataUnite du = new dataUnite();
du.actValue = ByteTransform.TransSingle(bytes, index).ToString();
du.MaxValue = ByteTransform.TransSingle(bytes, index + 4).ToString();
du.MinValue = ByteTransform.TransSingle(bytes, index + 8).ToString();
du.result = ByteTransform.TransInt32(bytes, index + 12);
du.Remark = ByteTransform.TransInt32(bytes, index + 16).ToString();
index += 20;
sinfo.SavedataList.Add(du);
}
if (sinfo.MaskID == 1)
{
foreach (var row in sinfo.SavedataList)
{
Console.WriteLine("------------------------");
Console.WriteLine("|生产值:" + row.actValue + "|");
Console.WriteLine("------------------------");
}
}
return sinfo;
}
private void GetBarcodeList(byte[] buffer, int index, ref stationPara sinfo)
{
try
{
//获取条码支线信息
//for (int i = 1; i <= 5; i++)
//{
// subLine sl = new subLine();
// sl.lineID = buffer[index + i].ToString();
// sl.barcode = "";
// sinfo.subLineList.Add(sl);
//}
//int barcodeLegth = 10;//设置单个条码长度
//获取主条码
byte[] bytes = new byte[20];
Array.Copy(buffer, 22, bytes, 0, 20);
//ByteTransform.DataFormat = HslCommunication.Core.DataFormat.DCBA;
//ByteTransform.IsStringReverseByteWord = true;
//if (BitConverter.IsLittleEndian)
//{
// Array.Reverse(bytes, 0, 4);
// Array.Reverse(bytes, 4, 4);
// Array.Reverse(bytes, 8, 4);
// Array.Reverse(bytes, 12, 4);
// Array.Reverse(bytes, 16, 4);
//}
sinfo.ProductBarcode = ByteTransform.TransString(bytes, 0, 20, Encoding.ASCII);
}
catch (Exception ex)
{
_logger.Error("条码信息获取失败:" + ex.ToString());
}
}
public object MCValue
{
get
{
return _mcValue;
}
set
{
if (value == null)
{
return;
}
//数据没有变化,直接返回
object[] objectarray;
if (!TryObject(value, out objectarray))
{
return;
}
if (value == _mcValue)
{
return;
}
_mcValue = value;
_stationInfo.Data = ParaFormart(objectarray, 0);
if (_stationInfo.Data.AskWork)
{
//这里需要判断上工位结果是否OK
_logger.Info("工位:" + _stationInfo.StationCode + " 收到作业请求信号");
//PreWorkThread();
}
////有新数据
if (isConnect && _stationInfo.Data.NewFlag)
{
_logger.Info("工位:" + _stationInfo.StationCode + " 收到作业完成信号,开始上传数据。托盘号:" + _stationInfo.Data.RFIDNo);
//OnRerefreshData();
}
}
}
#endregion
}
}