/// <summary> /// 数据帧构造函数 /// </summary> /// <param name="task"></param> public Frame(TaskArge task) { this.Adress = task.IoTMac; this.ControlCode = task.ControlCode; this.DataItem = task.Data; this._protocolType = task.IotProtocolType; mkey = task.MKey; if (this.DataItem != null) { this.dataLength = this.DataItem.Length; } }
public string Initi(string mac, MeterLink link, byte control, byte[] data, IotProtocolType protocolType = IotProtocolType.RanQiBiao) { if (this._meterLink != null) { return("IsExit"); } this._meterLink = link; this._meterLink.OnConnectClosed += _meterLink_OnConnectClosed; try { //读取当前表的信息并初始化 //Stopwatch sw = new Stopwatch(); //sw.Start(); meter = tms.GetMeter(mac); this._meterLink.OnReviced += _meterLink_OnReviced; //应答并上报数据 ReportData(mac, control, data, protocolType); if (meter == null) { return(""); } //读取当前表任务 List <Task> taskList = tms.GetTaskList(mac); //Log.getInstance().Write(MsgType.Information, string.Format("处理MAC上报数据:{0} Time:{1}", mac, sw.ElapsedMilliseconds / 1000.00)); //Log.getInstance().Write(new OneMeterDataLogMsg(mac, string.Format("处理MAC上报数据:{0} Time:{1}; 时间:{2}", mac, sw.ElapsedMilliseconds / 1000.00, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")))); this._reportWatch.Start(); //创建并启动任务执行线程 this._taskThread = new Thread(new ParameterizedThreadStart(DoTask)); this._reportWatch.Restart(); this._taskThread.Start(taskList); } catch (Exception e) { Log.getInstance().Write(MsgType.Error, "创建IoTMetre对象失败,原因:" + e.Message); Log.getInstance().Write(new OneMeterDataLogMsg(this.MAC, "创建IoTMetre对象失败,原因:" + e.Message + e.ToString())); Log.getInstance().Write(e, MsgType.Error); return("创建IoTMetre对象失败,原因:" + e.Message); } return(""); }
public TaskArge(string mac, DataItem data, ControlCode controlcode, IotProtocolType protocolType, byte[] key = null) { this._data = data; this._controlcode = controlcode; this._protocolType = protocolType; this._MKey = key; if (mac.Length > 14) { this._lotMac = mac.Substring(0, 14); } else if (mac.Length < 14) { this._lotMac = mac.PadLeft(14, '0'); } else { this._lotMac = mac; } }
private bool _lastDowith = false; //上一条上报数据是否处理完成,已处理完成则丢弃 /// <summary> /// 处理主动上报数据 /// </summary> /// <param name="control"></param> /// <param name="data"></param> public void ReportData(string mac, byte control, byte[] data, IotProtocolType protocolType) { lock (this._meterLink) { this._reportWatch.Restart(); CY.IoTM.Protocol.Frame frame = null; if (protocolType == IotProtocolType.RanQiBiao) { //燃气表协议 //解密数据 byte[] desData = Encryption.Decry(data, MKey); DataItem_C001 item_C001 = new DataItem_C001(desData); if (this._lastReportData == null || this._lastReportData.ReadDate != item_C001.ReadDate) { this._lastReportData = item_C001; _lastDowith = false; } //else if (_lastDowith) //{ // //上报的数据重复,并上条记录已处理过 // return; //} //解析并应答 DataItem_C001_Answer itemAnswer = new DataItem_C001_Answer(item_C001.SER); TaskArge taskArge = new TaskArge(mac, itemAnswer, ControlCode.CTR_7, MKey); frame = new Protocol.Frame(taskArge); if (this._reportWatch.ElapsedMilliseconds < Answer_YanShi) { Thread.Sleep(Answer_YanShi - (int)this._reportWatch.ElapsedMilliseconds); } this._meterLink.Send(frame.GetBytes());//应答数据 //检查上线的表是否登记到系统中 if (this.meter == null) { Log.getInstance().Write(MsgType.Information, "表:" + mac + " 在系统中未登记。"); Log.getInstance().Write(new OneMeterDataLogMsg(mac, "表:" + mac + " 在系统中未登记。")); return; } Thread.Sleep(300); //将接收到抄表数据提交给数据中心处理 Stopwatch _watch = new Stopwatch(); _watch.Start(); ReportData(item_C001); //new Thread(new ParameterizedThreadStart(ReportData)).Start(item_C001); Console.WriteLine("处理表:{0} 上报数据总用时:{1} 毫秒", mac, _watch.ElapsedMilliseconds); //Log.getInstance().Write(MsgType.Information, "处理表:" + this.MAC + " 上报数据总用时:" + _watch.ElapsedMilliseconds + " 毫秒"); //Log.getInstance().Write(new OneMeterDataLogMsg(this.MAC, "处理表:" + this.MAC + " 上报数据总用时:" + _watch.ElapsedMilliseconds + " 毫秒" + "; 时间:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"))); _lastDowith = true; //_watch.Stop(); } else if (protocolType == IotProtocolType.LCD) { //LCD屏协议 if (data[0] == 0xc0 && data[1] == 0x02) { //下载 DataItem_C002 item_C002 = new DataItem_C002(data); Log.getInstance().Write(new OneMeterDataLogMsg(mac, $"[{this._meterLink.socketHandle}]接收到LCD下载请求,文件名:{item_C002.FileName} 文件长度:{item_C002.FileLength} 请求段号:{item_C002.CurrentSegmentsIndex}")); MemoryStream stream = new MemoryStream(); string str = ADFileCacheService.getInstance().ReadFileSeg(stream, item_C002.FileName.Substring(0, 4), item_C002.FileName, item_C002.FileLength, item_C002.TotalSegments, item_C002.CurrentSegmentsIndex, item_C002.DataLength); DataItem answerItem = null; TaskArge answerArge = null; if (str != "") { //没有读取到要下载的文件,返回异常应答信息 answerItem = new DataItem_C002_Answer_Err(item_C002.SER); answerArge = new TaskArge(mac, answerItem, ControlCode.CTR_8); //TODO:记录异常应答记录 } else { byte[] tmp = new byte[stream.Length]; stream.Position = 0; stream.Read(tmp, 0, tmp.Length); answerItem = new DataItem_C002_Answer(item_C002.SER, item_C002.FileName, item_C002.FileLength, item_C002.TotalSegments, item_C002.CurrentSegmentsIndex, tmp); answerArge = new TaskArge(mac, answerItem, ControlCode.CTR_7, IotProtocolType.LCD); } //发送应答数据 frame = new Protocol.Frame(answerArge); //if (this._reportWatch.ElapsedMilliseconds < Answer_YanShi) // Thread.Sleep(Answer_YanShi - (int)this._reportWatch.ElapsedMilliseconds); this._meterLink.Send(frame.GetBytes());//应答数据 if (this.meter == null) { Log.getInstance().Write(MsgType.Information, "表:" + mac + " 在系统中未登记。"); Log.getInstance().Write(new OneMeterDataLogMsg(mac, "表:" + mac + " 在系统中未登记。")); return; } } else { Log.getInstance().Write(new OneMeterDataLogMsg(mac, $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}接收到错误的请求指令:{data[0]} {data[1]} ")); } } } }
/// <summary> /// 接收数据的线程函数 /// </summary> void ReceiveData() { //提供用于数据解析的内存流 //System.IO.MemoryStream ms = new System.IO.MemoryStream(); //FE FE 68 30 39 61 51 23 35 51 04 21 1E C0 01 20 40 14 16 22 04 15 20 18 56 42 37 18 56 02 00 18 56 02 00 18 56 02 00 23 00 00 00 6F 16 byte[] b = new byte[1]; b[0] = 0x01; while (isRun) { if (this._socket == null) { break; } try { System.Threading.Thread.Sleep(50); if (!isRun) { break; // } if (_socket.Poll(10, SelectMode.SelectRead)) { int dLength = this._socket.Available; if (dLength <= 0) { isRun = false; this.Close(); break; } byte[] buffer = null; if (dLength > 0) { if (dLength != this._socket.Available) { System.Threading.Thread.Sleep(100); dLength = this._socket.Available; } buffer = new byte[dLength]; this._socket.Receive(buffer); int index = 0;//查找报文头 for (int i = 0; i < buffer.Length - 2; i++) { if (buffer[i] == 0XFE && buffer[i + 1] == 0X68) { index = ++i; break; } } //检查仪表类型是否为燃气表或LCD屏协议,否则抛弃 IotProtocolType pType = (IotProtocolType)buffer[index + 1]; int iOffset = 11; //定义从包头(0x68)到数据区域字节数 if (pType != IotProtocolType.LCD && pType != IotProtocolType.RanQiBiao) { continue; } int DataLength = DataLength = buffer[index + 10]; if (pType == IotProtocolType.RanQiBiao) { DataLength = buffer[index + 10]; } else if (pType == IotProtocolType.LCD) { iOffset = 12;//LCD协议中,数据长度字段修改为2个字节,所以偏移量为12 DataLength += buffer[index + 11] << 8; } byte checkSum = 0; //检查校验码 for (int i = index; i < index + DataLength + iOffset; i++) { checkSum += Convert.ToByte(buffer[i]); } if (checkSum != buffer[index + iOffset + DataLength]) { //校验和错误 continue; } //取出数据部分(该数据为加密数据)注:LCD协议不加密 byte[] DATA = new byte[DataLength]; for (int i = 0; i < DataLength; i++) { DATA[i] = buffer[i + index + iOffset]; } StringBuilder sb = new StringBuilder(); for (int i = index + 8; i > index + 1; i--) { sb.Append(string.Format("{0:X2}", buffer[i])); } this._MAC = sb.ToString(); // if (!this.isLogin) { this.isLogin = true; Log.getInstance().Write(new OneMeterDataLogMsg(this._MAC, string.Format("上线-> [{0}] ", socketHandle) + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"))); RecordRevDataToLog(this._MAC, buffer, socketHandle.ToString());//添加日志 this._ioTMeter.Initi(this._MAC, this, buffer[index + 9], DATA, pType); } else { RecordRevDataToLog(this._MAC, buffer, socketHandle.ToString());//添加日志 //在此需要判端是下位机请求 if (buffer[index + 9] == 0xA1) { //下位机请求,(包括:上报燃气表数据、请求LCD文件、请求交易等) this._ioTMeter.ReportData(this._MAC, buffer[index + 9], DATA, pType); } else if (this.OnReviced != null) { this.OnReviced(new Meter_DATA() { Control = buffer[index + 9], DataLength = DataLength, m_buffer = DATA, ProtocolType = pType }); } } //else if(result != "") //{ // //Console.WriteLine(result); // Log.getInstance().Write(MsgType.Information,result); //} } else { //检查网络连接有效性 if (((this._socket.Poll(1000, SelectMode.SelectRead) && (this._socket.Available == 0)) || !this._socket.Connected)) { isRun = false; this.Close(); } continue; } } else { //检查网络连接有效性 if (((this._socket.Poll(1000, SelectMode.SelectRead) && (this._socket.Available == 0)) || !this._socket.Connected)) { isRun = false; this.Close(); } continue; } } catch (ObjectDisposedException e) { Log.getInstance().Write(MsgType.Information, $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")} 在MeterLink.ReceiveData产生ObjectDisposedException异常,详细如下:\r\nMAC:{this._MAC}[{this.socketHandle}]\r\n {e} "); //Socket已关闭 isRun = false; this.Close(); break; } catch (SocketException e1) { Log.getInstance().Write(MsgType.Information, $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")} 在MeterLink.ReceiveData产生SocketException异常ErrorCode={e1.ErrorCode},详细如下:\r\nMAC:{this._MAC}[{this.socketHandle}]\r\n {e1} "); if (e1.ErrorCode != 10035) { //当前链接已断开或连接已关闭。 isRun = false; this.Close(); break; } //Log.getInstance().Write(e1, MsgType.Error); } catch (OutOfMemoryException e2) { //Log.getInstance().Write(e2, MsgType.Error); Log.getInstance().Write(MsgType.Information, $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")} 在MeterLink.ReceiveData产生OutOfMemoryException异常,详细如下:\r\nMAC:{this._MAC}[{this.socketHandle}]\r\n {e2} "); GC.Collect(); } catch (Exception e3) { Log.getInstance().Write(MsgType.Information, $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")} 在MeterLink.ReceiveData产生Exception异常,详细如下:\r\nMAC:{this._MAC}[{this.socketHandle}]\r\n {e3} "); //Log.getInstance().Write(e3, MsgType.Error); } } //ms.Close(); }