CenterService.cs 15.3 KB
using HHECS.Communication;
using HHECS.Communication.Modbus;
using HHECS.Communication.Robot;
using HHECS.RobotTool.Common;
using HHECS.RobotTool.Common.Enums;
using HHECS.RobotTool.Model;
using HslCommunication.Core;
using System.Data;

namespace HHECS.RobotTool.Service
{
    public class CenterService
    {
        public List<EquipmentExtend> Equipments = new List<EquipmentExtend>();

        private readonly IFreeSql _freeSql;
        private readonly GrooveService _grooveService;
        private readonly SystemLog _logger = SystemLog.GetInstance();
        private CancellationTokenSource _cancellationTokenSource = null!;

        private List<IEquipmentCommunication> _equipmentCommunications = new List<IEquipmentCommunication>();

        public CenterService(IFreeSql freeSql, GrooveService grooveService)
        {
            _freeSql = freeSql;
            _grooveService = grooveService;
        }

        internal void Start()
        {
            try
            {
                _cancellationTokenSource = new CancellationTokenSource();
                Equipments = _freeSql.Queryable<EquipmentExtend>().ToList();
                var equipmentTypeIds = Equipments.Select(x => x.EquipmentTypeId).Distinct().ToList();
                var equipmentTypes = _freeSql.Queryable<EquipmentTypeExtend>().Where(x => equipmentTypeIds.Contains(x.Id)).ToList();
                var equipmentIds = Equipments.Select(x => x.Id).ToList();
                var equipmentProps = _freeSql.Queryable<EquipmentPropExtend>().Where(x => equipmentIds.Contains(x.EquipmentId)).ToList();
                var equipmentTypeTemps = _freeSql.Queryable<EquipmentTypePropTemplateExtend>().Where(x => equipmentTypeIds.Contains(x.EquipmentTypeId)).ToList();

                foreach (var item in Equipments)
                {
                    item.EquipmentType = equipmentTypes.FirstOrDefault(x => x.Id == item.EquipmentTypeId)!;
                    var props = equipmentProps.Where(x => x.EquipmentId == item.Id).ToList();
                    props.ForEach(prop =>
                    {
                        prop.Equipment = item;
                        prop.EquipmentTypePropTemplate = equipmentTypeTemps.FirstOrDefault(x => x.Id == prop.EquipmentTypePropTemplateId)!;
                    });
                    item.EquipmentProps = props;
                }

                var communicationConfig = _freeSql.Queryable<CommunicationConfig>().Where(x => x.IsEnable).ToList();
                if (communicationConfig.Count == 0)
                {
                    _logger.LogWarning($"设备通讯配置列表为空,请配置数据后再试!");
                    return;
                }
                _equipmentCommunications = InitialCommunication(communicationConfig);
                if (_equipmentCommunications.Count == 0)
                {
                    _logger.LogWarning($"通讯配置数量:{communicationConfig.Count},初始化成功数量:{_equipmentCommunications.Count},请检查基础数据配置是否正确!");
                }
                foreach (var communication in _equipmentCommunications)
                {
                    _ = Task.Run(async () =>
                    {
                        while (!_cancellationTokenSource.IsCancellationRequested)
                        {
                            try
                            {
                                await Task.Delay(1000);
                                var currentEquipments = Equipments.Where(x => x.IP == communication.IP).ToList();
                                var readTemps = currentEquipments.SelectMany(x => x.EquipmentProps).Select(x => new EquipmentCommunicationObj
                                {
                                    Address = x.Address,
                                    IP = communication.IP,
                                }).ToArray();
                                var readResult = communication.Reads(readTemps);
                                if (!readResult.Success)
                                {
                                    _logger.LogError($"读取设备[{communication.Name}],IP:{communication.IP}出现异常:{readResult.Msg}");
                                    continue;
                                }

                                //读取成功,数据赋值
                                foreach (var prop in currentEquipments.SelectMany(x => x.EquipmentProps))
                                {
                                    var temp = readTemps.Where(x => x.Address == prop.Address).FirstOrDefault();
                                    if (temp != null)
                                    {
                                        prop.Value = temp.Value;
                                    }
                                }

                                //数据处理
                                foreach (var equipment in currentEquipments)
                                {
                                    var codes = Enum.GetNames<RobotProp>();
                                    if (!equipment.EquipmentProps.All(x => codes.Contains(x.EquipmentTypePropTemplateCode)))
                                    {
                                        //属性数据不全,则跳过
                                        _logger.LogWarning($"设备{equipment.Name}属性数据不全,请完善基础配置数据!");
                                        continue;
                                    }

                                    //请求
                                    var dateSendValue = equipment[RobotProp.RequestMessage.ToString()].Value;
                                    //回复
                                    var ackSendValue = equipment[RobotProp.ReplyMessage.ToString()].Value;

                                    //设备请求
                                    if (dateSendValue == bool.TrueString)
                                    {
                                        //已回复
                                        if (ackSendValue == bool.TrueString)
                                        {
                                            _logger.LogWarning($"已处理设备[{equipment.Name}]请求信号,待设备清除信号!");
                                            continue;
                                        }

                                        _ = float.TryParse(equipment[RobotProp.RequestWidth.ToString()].Value, out var width);
                                        _ = float.TryParse(equipment[RobotProp.RequestDepth.ToString()].Value, out var depth);
                                        _ = int.TryParse(equipment[RobotProp.RequestLayer.ToString()].Value, out var layer);

                                        var computedResult = _grooveService.GetComputedData(equipment.IP, width, depth);
                                        if (!computedResult.Success)
                                        {
                                            _logger.LogError($"响应设备[{equipment.Name}]请求信号失败,数据计算出现异常:{computedResult.Msg}");
                                            continue;
                                        }

                                        var outputParameter = computedResult.Data;

                                        var ackObjs = new List<EquipmentCommunicationObj>
                                        {
                                            new EquipmentCommunicationObj
                                            {
                                                IP = equipment.IP,
                                                Address = equipment[RobotProp.ReplyWeldNum.ToString()].Address,
                                                Value = outputParameter.Layers.ToString(),
                                            }
                                        };

                                        //有层号的时候,需要附加其他参数
                                        if (layer > 0 && layer <= outputParameter.Layers)
                                        {
                                            //var speedValue = robotTechnologies.Where(x => x.Layer == layer).Select(x => x.WeldingSpeed).FirstOrDefault();
                                            //var freqValue = robotTechnologies.Where(x => x.Layer == layer).Select(x => x.SwingFrequency).FirstOrDefault();
                                            //var swingValue = robotTechnologies.Where(x => x.Layer == layer).Select(x => x.Amplitude).FirstOrDefault();
                                            //var stayValue = robotTechnologies.Where(x => x.Layer == layer).Select(x => x.LeftAndRightDwellTime).FirstOrDefault();
                                            var speedValue = 0;
                                            var freqValue = 0;
                                            var swingValue = 0;
                                            var stayValue = 0;

                                            ackObjs.AddRange(new List<EquipmentCommunicationObj>
                                            {
                                                new EquipmentCommunicationObj
                                                {
                                                    IP = equipment.IP,
                                                    Address = equipment[RobotProp.ReplySpeed.ToString()].Address,
                                                    Value = speedValue.ToString(),
                                                },
                                                new EquipmentCommunicationObj
                                                {
                                                    IP = equipment.IP,
                                                    Address = equipment[RobotProp.ReplyFreq.ToString()].Address,
                                                    Value = freqValue.ToString(),
                                                },
                                                new EquipmentCommunicationObj
                                                {
                                                    IP = equipment.IP,
                                                    Address = equipment[RobotProp.ReplySwing.ToString()].Address,
                                                    Value = swingValue.ToString(),
                                                },
                                                new EquipmentCommunicationObj
                                                {
                                                    IP = equipment.IP,
                                                    Address = equipment[RobotProp.ReplyStay.ToString()].Address,
                                                    Value = stayValue.ToString(),
                                                }
                                            });
                                        }

                                        //回复地址
                                        ackObjs.Add(new EquipmentCommunicationObj
                                        {
                                            IP = equipment.IP,
                                            Address = equipment[RobotProp.ReplyMessage.ToString()].Address,
                                            Value = bool.TrueString,
                                        });

                                        var ackTempsResult = communication.Writes(ackObjs.ToArray());
                                        if (!ackTempsResult.Success)
                                        {
                                            _logger.LogSuccess($"响应设备[{equipment.Name}]请求信号失败:{ackTempsResult.Msg}");
                                            continue;
                                        }

                                        //回复
                                        _logger.LogSuccess($"响应设备[{equipment.Name}]请求信号成功");
                                        continue;
                                    }

                                    //清除交互信号
                                    if (dateSendValue == bool.FalseString && ackSendValue == bool.TrueString)
                                    {
                                        var ackObj = new EquipmentCommunicationObj
                                        {
                                            Address = equipment[RobotProp.ReplyMessage.ToString()].Address,
                                            IP = equipment.IP,
                                            Value = bool.FalseString
                                        };
                                        var ackResult = communication.Write(ackObj);
                                        if (!ackResult.Success)
                                        {
                                            _logger.LogError($"清除设备[{equipment.Name}]信号失败:{ackResult.Msg}");
                                            continue;
                                        }

                                        _logger.LogSuccess($"清除设备[{equipment.Name}]信号成功");
                                    }
                                }
                            }
                            catch (Exception ex)
                            {
                                _logger.LogException($"设备[{communication.Name}],IP:{communication.IP}处理线程出现异常:{ex.Message}");
                            }
                        }
                    });
                }
            }
            catch (Exception ex)
            {
                _logger.LogError($"启动失败:{ex.Message}");
            }
        }

        internal void Stop()
        {
            _cancellationTokenSource.Cancel();
            _equipmentCommunications.ForEach(x => x.DisConnect());
            _equipmentCommunications.Clear();
            Equipments.Clear();
        }

        /// <summary>
        /// 初始化设备通讯
        /// </summary>
        /// <param name="communicationConfigs"></param>
        /// <returns></returns>
        private static List<IEquipmentCommunication> InitialCommunication(IEnumerable<CommunicationConfig> communicationConfigs)
        {
            var temps = new List<IEquipmentCommunication>();
            foreach (var item in communicationConfigs)
            {
                IEquipmentCommunication? communication = item.CommunicationType switch
                {
                    CommunicationTypeConst.Fanuc => new HslFanucImplement(new FanucBuildModel
                    {
                        Name = item.Name,
                        IP = item.IpAddress,
                        Port = item.Port,
                    }),
                    CommunicationTypeConst.ModbusTcp => new ModbusTcpClientImplement(new ModbusClientBuildModel
                    {
                        Name = item.Name,
                        IP = item.IpAddress,
                        Port = item.Port,
                        Station = 3,
                        DataFormat = DataFormat.CDAB.ToString(),
                    }),
                    _ => null
                };
                if (communication == null)
                {
                    continue;
                }
                temps.Add(communication);
            }
            return temps;
        }
    }
}