/// <summary> /// 根据指令创建指定数据项对象(代码未完成) /// </summary> /// <returns></returns> public DataItem getDataItem(byte ser) { byte[] cmdData = strToToHexByte(_cmd.DataCommand); //重新编写指令序列号 cmdData[2] = ser; if (_cmd.Identification == "A013" && _cmd.ControlCode == 0x04) { cmdData[3] = ser; } DataItem item = null; switch ((ControlCode)_cmd.ControlCode) { case ControlCode.ReadData: //读数据指令 item = new DataItem_ReadData_ASK(cmdData); break; case ControlCode.WriteData: //写数据 item = getWriteDataAskItem(cmdData); break; case ControlCode.ReadKeyVersion: //读Key版本号 break; case ControlCode.ReadMeterAdress: //读地址 break; case ControlCode.WriteMeterAdress: //写地址 break; case ControlCode.WriteMeterNum: //写表底 break; case ControlCode.CYReadData: //读参数 item = getCYReadDataAskItem(cmdData); break; case ControlCode.CYWriteData: //创源内部写指令(参数设置) item = getCYWriteDataAskItem(cmdData); break; case ControlCode.CTR_6: //主动上报数据中 item = new DataItem_C001(cmdData); break; default: break; } return(item); }
private bool ReportToZhuZhan(Stopwatch watch, Socket socket) { watch.Start(); DataItem_C001 item_C001 = new DataItem_C001(ser++, DateTime.Now, this.TotalAmount, this.TotalTopUp - this.CurrentBalance, this.CurrentBalance, this.LastTotal, this._st1, this._st2); TaskArge taskArge = new TaskArge(this.Mac, item_C001, ControlCode.CTR_6, MKey); Frame frame = new Frame(taskArge); int iTime = 1; byte[] buffer = frame.GetBytes(); while (socket.Poll(100, SelectMode.SelectWrite)) { socket.Send(buffer); break; } Notice(string.Format("{1:yyyy-MM-dd HH:mm:ss} 第{0}次发送上报数据请求帧\r", iTime, DateTime.Now)); string message; //等待应答 while (true) { Thread.Sleep(100); if (socket.Poll(10, SelectMode.SelectRead)) { int dLength = socket.Available; Thread.Sleep(100); if (dLength != socket.Available) { dLength = socket.Available; } buffer = new byte[dLength]; socket.Receive(buffer); Notice(string.Format("{1:yyyy-MM-dd HH:mm:ss}接收到主站应答数据:{0}\r", MyDataConvert.BytesToHexStr(buffer), DateTime.Now)); taskArge = JieXi(buffer, out message); if (taskArge != null && taskArge.ControlCode == ControlCode.CTR_7) { Notice(string.Format("第{0}次发送上报数据请求完成。\r", iTime)); } Notice(string.Format("本次上报数据总用时:{0}毫秒\r", watch.ElapsedMilliseconds)); this._reportWatch.Restart(); break; } else if (socket.Poll(100, SelectMode.SelectError)) { } if (watch.ElapsedMilliseconds >= 1000 * 10) { if (iTime >= 3) { //接收不到主站应答,本次上报结束 this.tcpClient.Close(); this.tcpClient = null; return(false); } iTime++; buffer = frame.GetBytes(); socket.Send(buffer); Notice(string.Format("{1:yyyy-MM-dd HH:mm:ss}接收到主站应答数据:{0}\r", MyDataConvert.BytesToHexStr(buffer), DateTime.Now)); watch.Restart(); } } return(true); }
//Semaphore _semaphore = new Semaphore(10, 10); /// <summary> /// 上报数据并接收主站指令 /// </summary> private void ReportData() { //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 DataItem_C001 item_C001 = new DataItem_C001(ser++, DateTime.Now, this.TotalAmount, LJMoney, CurrentBalance, this.LastTotal, _st1, _st2); TaskArge taskArge = new TaskArge(this.Mac, item_C001, ControlCode.CTR_6, MKey); //连接服务器 Stopwatch watch = new Stopwatch(); watch.Start(); byte[] buffer = null; try { this.tcpClient = new System.Net.Sockets.TcpClient(); this.tcpClient.Connect(this.hostname, this.port); Socket socket = tcpClient.Client; Notice(string.Format("{0} 表连接服务器完成.\r", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"))); if (!ReportToZhuZhan(watch, socket)) { return; } Frame frame = new Frame(taskArge); string message; //等待主站指令 Notice(string.Format("================================\r")); watch.Restart(); while (true) { if (watch.ElapsedMilliseconds >= 1000 * 20) { //20秒内没有收到任何主站指令,关闭连接并结束本次通信 this.tcpClient.Close(); Notice(string.Format("{0} 关闭表连接\r\n--------------------------------\r", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"))); this._reportWatch.Restart(); break; } //if (this._reportWatch.ElapsedMilliseconds >= this.周期 * 60 * 1000) //{ // //上报数据周期到 // watch.Restart(); // if (!ReportToZhuZhan(watch,socket)) // { // return; // } //} //检查数据 if (socket.Poll(10, SelectMode.SelectRead)) { int dLength = socket.Available; Thread.Sleep(100); if (dLength != socket.Available) { dLength = socket.Available; } buffer = new byte[dLength]; socket.Receive(buffer); Notice(string.Format("{1:yyyy-MM-dd HH:mm:ss} 接收到主站数据:{0}\r", MyDataConvert.BytesToHexStr(buffer), DateTime.Now)); Thread.Sleep(10); // _semaphore.WaitOne(); //解析接收到的数据 try { taskArge = JieXi(buffer, out message); // _semaphore.Release(); Notice(string.Format("控制码:{0} 指令:{1}\r", taskArge.ControlCode, taskArge.Data.IdentityCode)); } catch (Exception ex) { // _semaphore.Release(); throw ex; } if (taskArge != null && (((byte)taskArge.ControlCode) & 0x80) == 0x00) { //接收到主站请求数据 taskArge = CreateAnswerData(taskArge); frame = new Frame(taskArge); buffer = frame.GetBytes(); socket.Send(buffer); Notice(string.Format("{0:yyyy-MM-dd HH:mm:ss}从站应答完成。\r", DateTime.Now)); watch.Restart(); } } } } catch (Exception e) { Notice(string.Format("{1:yyyy-MM-dd HH:mm:ss} 程序异常:{0}\r", e.Message, DateTime.Now)); Debug.Print(e.Message); } }
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> private void ReportData(object ParObject) { //*********该函数要求2秒内必须返回*****************// DataItem_C001 item_C001 = ParObject as DataItem_C001; if (item_C001 == null || this.meter == null) { return; } //编写调用上报数据中心抄表数据处理程序 //Console.WriteLine(string.Format("于:{1} 接收到表{0}上报的数据:累计气量={2},累计金额={3},剩余金额={4},上次结算累计量={5}", this.meter.Mac,DateTime .Now, // item_C001.LJGas,item_C001.LJMoney,item_C001.SYMoney,item_C001.LastLJGas)); Log.getInstance().Write(string.Format("于:{1} 接收到表{0}上报的数据:累计气量={2},累计金额={3},剩余金额={4},上次结算累计量={5}", this.meter.Mac, DateTime.Now, item_C001.LJGas, item_C001.LJMoney, item_C001.SYMoney, item_C001.LastLJGas), MsgType.Information); //Log.getInstance().Write(new OneMeterDataLogMsg(this.meter.Mac, string.Format("接收到表{0}上报的数据:累计气量={2},累计金额={3},剩余金额={4},上次结算累计量={5}; 时间:{1} ", this.meter.Mac, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"), // item_C001.LJGas, item_C001.LJMoney, item_C001.SYMoney, item_C001.LastLJGas))); //WCFServiceProxy<IReportData> _iReportDataProxy = new WCFServiceProxy<IReportData>(); this.meter = this.tms.GetMeter(meter.Mac); this.meter.TotalAmount = item_C001.LJGas; if (!meter.IsDianHuo && meter.LastGasPoint > item_C001.LJGas && meter.TotalTopUp == 0) { //this.meter.LastGasPoint = item_C001.LJGas; } CY.IoTM.DataService.Business.ReportDataService rds = new DataService.Business.ReportDataService(); //SubmitResult result = _iReportDataProxy.getChannel SubmitResult result = rds.Submit(this.meter, new SubmitData() { JSDay = item_C001.JSDay, LastLJGas = item_C001.LastLJGas, LJGas = item_C001.LJGas, LJMoney = item_C001.LJMoney, ReadDate = item_C001.ReadDate, ST1 = item_C001.ST1, ST2 = item_C001.ST2, SYMoney = item_C001.SYMoney }); // _iReportDataProxy.CloseChannel(); //判断是否需要重新加载Meter对象 if (result.IsReLoadMeter)//上报数据后,后台已更新Meter对象数据,当前meter对象已过失,需要重新加载。 { //WCFServiceProxy<ITaskManage> _iTaskManageProxy = new WCFServiceProxy<ITaskManage>(); try { //Meter _m = _iTaskManageProxy.getChannel.GetMeter(meter.Mac); Meter _m = this.tms.GetMeter(meter.Mac); //_iTaskManageProxy.CloseChannel(); this.meter = _m; } catch (Exception er) { Log.getInstance().Write(MsgType.Error, "重新加载表:" + meter.Mac + " 信息失败,原因:" + er.Message); Log.getInstance().Write(new OneMeterDataLogMsg(meter.Mac, "重新加载表:" + meter.Mac + " 信息失败,原因:" + er.Message)); } } if (result.IsCalibration && result.Calibrations != null) { //执行校准 // this._xZTaskList = result.Calibrations; } }