123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332 |
- using Edge.Core.Parser.BinaryParser.Util;
- using Edge.Core.Processor;
- using Edge.Core.UniversalApi;
- using Microsoft.Extensions.Logging;
- using Microsoft.Extensions.Logging.Abstractions;
- using PetroChinaOnlineWatchPlugin.MessageEntity;
- using PetroChinaOnlineWatchPlugin.MessageEntity.Outgoing;
- using System;
- using System.Collections.Generic;
- using System.Net;
- using System.Net.Sockets;
- using System.Text;
- namespace PetroChinaOnlineWatchPlugin
- {
- internal class ConnectionController
- {
- public int TcpListenPort { get { return 6000; } }
- public TcpClient TcpClientInstance { get { return tcpClient; } }
- public static ConnectionController Default => instance;
- private static readonly ConnectionController instance = new ConnectionController();
- private ILogger logger = NullLogger.Instance;
- private IProcessor source;
- private UniversalApiHub universalApiHub;
- private TcpListener tcpListener;
- private TcpClient tcpClient = new TcpClient();
- //消息长度不应大于228字节,以减小对应用缓冲区大小的要求。
- private byte[] tcpServerReceivedBuffer = new byte[1024];
- private byte[] tcpClientReceivedBuffer = new byte[1024];
- private AppConfigV1 appConfig;
- private bool hasSentConfig = false;
- private int environmentPushingInterval = -1;
- private const string OnUploadOnlineMonitorDataStateChangeEventName = "OnUploadOnlineMonitorDataStateChange";
- public bool Start(AppConfigV1 appConfig, ILogger logger, IProcessor source, UniversalApiHub universalApiHub)
- {
- this.appConfig = appConfig;
- this.logger = logger;
- this.source = source;
- this.universalApiHub = universalApiHub;
- HeartBeatUdpProxy.Default.OnDataReceived += Udp_DataReceived;
- logger.LogInformation($"TcpListener is listening on port, {TcpListenPort}");
- tcpListener = new TcpListener(new IPEndPoint(IPAddress.Any, TcpListenPort));
- tcpListener.Start();
- tcpListener.BeginAcceptTcpClient(AcceptCallback, null);
- return true;
- }
- public void SendUnsolicitedMessage()
- {
- try
- {
- if (tcpClient.Client == null || !tcpClient.Connected)
- {
- logger.LogDebug($"在线监测所有数据上传失败:无法连接到远程服务器");
- return;
- }
- dynamic dataList = null;
- var tempDic = new Dictionary<string, object>();
- var span = DateTime.Now - DateTime.Today;
- //如果配置数据无变更,每日零时和中午12点上传该配置信息。
- if (span.TotalSeconds < 8 || (span.TotalSeconds > 43200 && span.TotalSeconds < 43208))
- {
- if (!hasSentConfig)
- {
- dataList = SqlClientHelper.ReadOnlineMonitorData(appConfig, logger, ref tempDic, DbAddressType.Configure);
- if (dataList != null)
- {
- // CF_ID 01H, CF_Message
- var configMessage = new AnswerWriteUnsolicitedMessageOut(appConfig, 0x01, dataList);
- SendOnlineMonitorData("配置数据", configMessage);
- hasSentConfig = true;
- }
- }
- }
- else if (hasSentConfig)
- {
- hasSentConfig = false;
- }
- if (environmentPushingInterval < 0)
- {
- //环境实时,数据采集时间间隔不大于 30 秒
- environmentPushingInterval = 29;
- dataList = SqlClientHelper.ReadOnlineMonitorData(appConfig, logger, ref tempDic, DbAddressType.EnvironmentData);
- if (dataList != null)
- {
- var environmentRealtime = new AnswerWriteUnsolicitedMessageOut(appConfig, 0x11, dataList);
- SendOnlineMonitorData("环境数据", environmentRealtime);
- SqlClientHelper.UpdateOnlineMonitorData(appConfig, logger);
- }
- }
- else
- {
- environmentPushingInterval -= 1;
- }
- dataList = SqlClientHelper.ReadOnlineMonitorData(appConfig, logger, ref tempDic, DbAddressType.PumpData);
- if (dataList != null)
- {
- var pumpRealtimeMessage = new AnswerWriteUnsolicitedMessageOut(appConfig, 0x21, dataList);
- SendOnlineMonitorData("加油枪数据", pumpRealtimeMessage);
- SqlClientHelper.UpdateOnlineMonitorData(appConfig, logger);
- }
- dataList = SqlClientHelper.ReadOnlineMonitorData(appConfig, logger, ref tempDic, DbAddressType.FaultData);
- if (dataList != null)
- {
- var faultMessage = new AnswerWriteUnsolicitedMessageOut(appConfig, 0x41, dataList);
- SendOnlineMonitorData("报警_故障数据", faultMessage);
- SqlClientHelper.UpdateOnlineMonitorData(appConfig, logger);
- }
- }
- catch (Exception ex)
- {
- logger.LogError($"Exception in SendUnsolicitedMessage(...):\r\n{ex}");
- }
- }
- private void SendOnlineMonitorData(string dataTypeName, MessageBase sendMessage)
- {
- try
- {
- if (tcpClient.Client == null || !tcpClient.Connected)
- {
- logger.LogError($"{dataTypeName}上传失败:无法连接到远程服务器");
- return;
- }
- byte[] sendBuffer = Parser.Default.Serialize(sendMessage);
- logger.LogDebug($"Tcp client sent data, {sendMessage.ToString()} in SendOnlineMonitorData");
- tcpClient.Client.Send(sendBuffer);
- logger.LogDebug($"Tcp client sent data, 0x{sendBuffer.ToHexLogString()} in Udp_DataReceived");
- var r = universalApiHub.FireEvent(source,
- OnUploadOnlineMonitorDataStateChangeEventName, new UploadState() { DataTypeName = dataTypeName });
- }
- catch (Exception ex)
- {
- logger.LogDebug($"Exception in SendOnlineMonitorData(...):\r\n{ex}");
- tcpClient.Close();
- }
- }
- private void Udp_DataReceived(object sender, EventArgs ar)
- {
- try
- {
- var udpar = ar as UdpDataEventArgs;
- logger.LogDebug($"TcpClient connect to {udpar.IpAddress}, port {udpar.Port}");
- tcpClient = new TcpClient();
- tcpClient.Connect(udpar.IpAddress, udpar.Port);
- tcpClient.Client.BeginReceive(tcpClientReceivedBuffer, 0, tcpClientReceivedBuffer.Length, SocketFlags.None, TcpClientDataReceived, tcpClient);
- var tempDic = new Dictionary<string, object>();
- var dataList = SqlClientHelper.ReadOnlineMonitorData(appConfig, logger, ref tempDic, DbAddressType.Configure);
- if (dataList != null)
- {
- // CF_ID 01H, CF_Message
- var configMessage = new AnswerWriteUnsolicitedMessageOut(appConfig, 0x01, dataList);
- SendOnlineMonitorData("配置数据", configMessage);
- }
- }
- catch (Exception ex)
- {
- logger.LogError($"Exception in Udp_DataReceived(...):\r\n{ex}");
- }
- }
- private void TcpClientDataReceived(IAsyncResult ar)
- {
- TcpClient client = null;
- try
- {
- client = ar.AsyncState as TcpClient;
- int number = client.Client.EndReceive(ar);
- ar.AsyncWaitHandle.Close();
- var remoteEndPoint = client.Client.RemoteEndPoint as IPEndPoint;
- int messageLengthIndex = 6;
- for (int offset = 0; offset < number;)
- {
- var temp = new byte[] { tcpClientReceivedBuffer[offset + messageLengthIndex + 1], tcpClientReceivedBuffer[offset + messageLengthIndex] };
- offset = messageLengthIndex + 2 + BitConverter.ToUInt16(temp, 0);
- byte[] messageBuffer = new byte[offset];
- for (int i = 0; i < offset; i++)
- {
- messageBuffer[i] = tcpClientReceivedBuffer[i];
- }
- logger.LogDebug($"Tcp client received data, 0x{messageBuffer.ToHexLogString()}, from IpAddress:Port, {remoteEndPoint.Address}:{remoteEndPoint.Port}");
- dynamic receivedMessage = Parser.Default.Deserialize(messageBuffer);
- if (receivedMessage.MessageType == MessageType.IFSF_MESSAGE_TYPE_ACK)
- {
- logger.LogDebug($"Tcp client Incoming--->: {receivedMessage.ToString()}");
- //ACK 0x00 肯定确认,收到数据
- if (receivedMessage.MessageAck == 0x00)
- {
- logger.LogDebug($"SqlClientHelper ");
- //SqlClientHelper.UpdateOnlineMonitorData(appConfig, logger);
- }
- }
- }
- if (number > 0)
- {
- tcpClientReceivedBuffer = new byte[tcpClientReceivedBuffer.Length];
- client.Client.BeginReceive(tcpClientReceivedBuffer, 0, tcpClientReceivedBuffer.Length, SocketFlags.None, TcpClientDataReceived, client);
- }
- else
- {
- logger.LogDebug($"Tcp client received 0 count data which indicates the connection is broken in TcpClientDataReceived!");
- client.Close();
- }
- }
- catch (Exception ex)
- {
- logger.LogError($"Exception in TcpClientDataReceived(...):\r\n{ex}");
- client.Close();
- }
- }
- private void TcpServerDataReceived(IAsyncResult ar)
- {
- TcpClient client = null;
- try
- {
- client = ar.AsyncState as TcpClient;
- int number = client.Client.EndReceive(ar);
- ar.AsyncWaitHandle.Close();
- var remoteEndPoint = client.Client.RemoteEndPoint as IPEndPoint;
- logger.LogDebug($"Tcp server received {number} bytes, from IpAddress:Port, {remoteEndPoint.Address}:{remoteEndPoint.Port}");
- int messageLengthIndex = 6;
- for (int offset = 0; offset < number;)
- {
- var temp = new byte[] { tcpServerReceivedBuffer[offset + messageLengthIndex + 1], tcpServerReceivedBuffer[offset + messageLengthIndex] };
- offset = messageLengthIndex + 2 + BitConverter.ToUInt16(temp, 0);
- byte[] messageBuffer = new byte[offset];
- for (int i = 0; i < offset; i++)
- {
- messageBuffer[i] = tcpServerReceivedBuffer[i];
- }
- logger.LogDebug($"Tcp server received data, 0x{messageBuffer.ToHexLogString()}");
- dynamic receivedMessage = Parser.Default.Deserialize(messageBuffer);
- logger.LogDebug($"Tcp server Incoming--->: {receivedMessage.ToString()}");
- if (receivedMessage.MessageType == MessageType.IFSF_MESSAGE_TYPE_READ)
- {
- //控制设备读取设备的心跳间隔
- if (receivedMessage.DatabaseAddress[0] == 0x00 && receivedMessage.DataIdentifier[0] == 0x04)
- {
- var dataList = new List<IfsfMessageDataOut>() { new Bin8Message(0x04, 11) };
- if (dataList != null)
- {
- // 心跳间隔为11秒
- var configMessage = new AnswerWriteUnsolicitedMessageOut(appConfig, receivedMessage.MessageToken, receivedMessage.DatabaseAddress, dataList);
- byte[] sendBuffer = Parser.Default.Serialize(configMessage);
- logger.LogDebug($"Tcp server sent data, {configMessage.ToString()} in TcpServerDataReceived");
- client.Client.Send(sendBuffer);
- logger.LogDebug($"Tcp server sent data, 0x{sendBuffer.ToHexLogString()} in TcpServerDataReceived");
- }
- }
- }
- }
- if (number > 0)
- {
- tcpServerReceivedBuffer = new byte[tcpServerReceivedBuffer.Length];
- client.Client.BeginReceive(tcpServerReceivedBuffer, 0, tcpServerReceivedBuffer.Length, SocketFlags.None, TcpServerDataReceived, client);
- }
- else
- {
- logger.LogDebug($"Tcp server received 0 count data which indicates the connection is broken in TcpServerDataReceived!");
- client.Close();
- }
- }
- catch (Exception ex)
- {
- logger.LogError($"Exception in TcpServerDataReceived(...):\r\n{ex}");
- client.Close();
- }
- }
- private void AcceptCallback(IAsyncResult ar)
- {
- try
- {
- var client = tcpListener.EndAcceptTcpClient(ar);
- client.Client.BeginReceive(tcpServerReceivedBuffer, 0, tcpServerReceivedBuffer.Length, SocketFlags.None, TcpServerDataReceived, client);
- var remoteEndPoint = client.Client.RemoteEndPoint as IPEndPoint;
- logger.LogDebug($"Accepted a remote tcp client from IpAddress:Port, {remoteEndPoint.Address}:{remoteEndPoint.Port}");
- tcpListener.BeginAcceptTcpClient(AcceptCallback, null);
- }
- catch (Exception ex)
- {
- logger.LogError($"Exception in AcceptCallback(...):\r\n{ex}");
- }
- }
- private decimal BytesToBcd(List<byte> data)
- {
- var strBcd = new StringBuilder();
- int pointIndex = data[0];
- for (int i = 1; i < data.Count; i++)
- {
- strBcd.Append(data[i]);
- if (i == pointIndex)
- strBcd.Append('.');
- }
- return decimal.Parse(strBcd.ToString());
- }
- }
- public class UploadState
- {
- public string DataTypeName { get; set; }
- /// <summary>
- /// each vr watching nozzle is a physical pump nozzle, here is the bind info, will be used to draw UI.
- /// </summary>
- public int SiteLevelNozzleId { get; set; }
- }
- }
|