//保存文件,16进制,封装开头是0xAA,结尾是0x55 public void StoreDataToFile(int intDeviceID, byte[] bytes) { string filename = DateTime.Now.ToString("yyyy-MM-dd") + "--" + DateTime.Now.Hour.ToString() + "-" + DateTime.Now.Minute.ToString() + "-" + DateTime.Now.Second.ToString() + "--" + intDeviceID.ToString();//以日期时间命名,避免文件名重复 byte[] fileStartAndEnd = new byte[2] { 0xAA, 0x55 }; //保存文件的头是AA,尾是55 string path = @"D:\\Data\\" + filename + ".dat"; FileStream F = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite); F.Write(fileStartAndEnd, 0, 1); F.Write(bytes, 0, bytes.Length); F.Write(fileStartAndEnd, 1, 1); F.Flush(); F.Close(); //StatusBox.Text = "文件保存成功"; Net_DB.addsensorad(intDeviceID, DateTime.Now.ToString(), path); }
//接收数据 private void OnReceive(IAsyncResult ar) { byte[] ID = new byte[4];//设备的ID号 int intdeviceID = 0; int[] cfg = new int[5];//存储从数据库读取的设备配置参数 try { Socket clientSocket = (Socket)ar.AsyncState;//此处获取数据大小 //获取客户端信息,包括了IP地址、端口 string strIP = (clientSocket.RemoteEndPoint as IPEndPoint).Address.ToString(); string strPort = (clientSocket.RemoteEndPoint as IPEndPoint).Port.ToString(); //test string strAddress = clientSocket.RemoteEndPoint.ToString(); DataItem dataitem = (DataItem)htClient[strAddress]; //取出address对应的dataitem //获取接收的数据长度,注意此处的停止接收,后面必须继续接收,否则不会接收数据的。 int bytesRead = clientSocket.EndReceive(ar); //接收到的数据长度 if (bytesRead > 0) //打印数据 { string str = byteToHexStr(dataitem.SingleBuffer); string strrec = str.Substring(0, bytesRead * 2); System.Diagnostics.Debug.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + "从硬件" + strAddress + "设备号--" + dataitem.intDeviceID + "接收到的数据长度是" + bytesRead.ToString() + "数据是" + strrec + "\n"); //把接收的数据打印出来 if (checkIsHeartPackage(dataitem.SingleBuffer)) { if (dataitem.intDeviceID == 0)//只判断新地址的心跳包,避免重复检测 { //设备的ID字符串 ID[0] = dataitem.SingleBuffer[3]; ID[1] = dataitem.SingleBuffer[4]; ID[2] = dataitem.SingleBuffer[5]; ID[3] = dataitem.SingleBuffer[6]; intdeviceID = byteToInt(ID); string oldAddress = checkIsHaveID(intdeviceID); //得到当前ID对应的旧地址 if (oldAddress != null) //若存在,把旧地址的属性复制到新地址上 { //!!!由于掉线,新dataitem属性要继承旧设备,只需要更新网络属性,如IP、port、socket等 DataItem olddataitem = (DataItem)htClient[oldAddress]; //取出当前数据IP对应的dataitem dataitem.byteDeviceID = ID; dataitem.intDeviceID = intdeviceID; dataitem.strIP = strIP; dataitem.strPort = strPort; dataitem.datalength = olddataitem.datalength; //继承旧属性 dataitem.socket = clientSocket; dataitem.byteAllData = olddataitem.byteAllData; //继承旧属性 dataitem.currentsendbulk = olddataitem.currentsendbulk; //继承旧属性 dataitem.uploadGroup = olddataitem.uploadGroup; //继承旧属性 dataitem.isGetADNow = olddataitem.isGetADNow; dataitem.isWaked = 1; dataitem.CmdStage = olddataitem.CmdStage; //继承旧属性 dataitem.isSendDataToServer = olddataitem.isSendDataToServer; //继承旧属性 dataitem.CmdNum = olddataitem.CmdNum; //继承旧属性 dataitem.SingleBuffer = new byte[perPackageLength]; dataitem.strAddress = strAddress; dataitem.CmdbulkHex = olddataitem.CmdbulkHex; //要发送的命令数目--16进制//继承旧属性 dataitem.CapTimeHour = olddataitem.CapTimeHour; //继承旧属性 dataitem.CapTimeMinute = olddataitem.CapTimeMinute; //继承旧属性 dataitem.OpenTime = olddataitem.OpenTime; //继承旧属性 dataitem.CloseTime = olddataitem.CloseTime; //继承旧属性 htClient.Remove(oldAddress); //删除旧地址的键值对 htClient[strAddress] = dataitem; string time = DateTime.Now.ToString(); //把信息存入数据库 Net_DB.addsensorinfo(intdeviceID, strIP, strPort, time, dataitem.isWaked); Log.Debug("ID为" + intdeviceID + "--地址" + strAddress + "已存储"); } else { //若不存在,属于全新地址,更新ID号 dataitem.intDeviceID = intdeviceID; dataitem.byteDeviceID = ID; cfg = Net_DB.readsensorcfg(intdeviceID);//从数据库读取设备的配置参数 if (cfg != null) { dataitem.CmdbulkHex = cfg[0];//要发送的命令数目--16进制 dataitem.CapTimeHour = cfg[1]; dataitem.CapTimeMinute = cfg[2]; dataitem.OpenTime = cfg[3]; dataitem.CloseTime = cfg[4]; } //开启命令发送定时器 if (cmdTimer.Enabled != true) { cmdTimer.Start(); } string time = DateTime.Now.ToString(); //把信息存入数据库 Net_DB.addsensorinfo(intdeviceID, strIP, strPort, time, dataitem.isWaked); } } //if (dataitem.intDeviceID == 0) } //end if (checkIsHeartPackage()) //设备进入低功耗模式后,断开网络,从哈希表中移除 //如果是暂时关闭,则不能从哈希表中移除 if (checkIsOffLine(dataitem.SingleBuffer)) { //更新数据库,把isWaked置0 dataitem.isWaked = 0; Net_DB.addsensorinfo(dataitem.intDeviceID, strIP, strPort, DateTime.Now.ToString(), dataitem.isWaked); clientSocket.Shutdown(SocketShutdown.Both); clientSocket.Close(); htClient.Remove(intdeviceID); System.Diagnostics.Debug.WriteLine("设备已断开连接,进入低功耗模式"); } if (checkIsGPSsetOK(dataitem.SingleBuffer)) { dataitem.CmdNum++; System.Diagnostics.Debug.WriteLine("设定GPS采样时间成功"); Log.Debug("设备号为" + dataitem.intDeviceID + "设定GPS采样时间成功"); } if (checkIsGPSReadOK(dataitem.SingleBuffer)) { dataitem.CmdNum++; System.Diagnostics.Debug.WriteLine("读取GPS当前时间成功"); Log.Debug("设备号为" + dataitem.intDeviceID + "读取GPS当前时间成功"); } if (checkIsOpenAndCloseTime(dataitem.SingleBuffer)) { dataitem.CmdNum++; System.Diagnostics.Debug.WriteLine("关闭时长设置成功"); Log.Debug("设备号为" + dataitem.intDeviceID + "关闭时长设置成功"); //该设备需要设置或者查询的命令已发完,剩下的是上传 dataitem.CmdbulkHex = 0; } if (checkIsADstart(dataitem.SingleBuffer)) { System.Diagnostics.Debug.WriteLine("AD采样开始"); } //检查AD采样是否结束 if (checkIsADfinished(dataitem.SingleBuffer)) { System.Diagnostics.Debug.WriteLine("AD采样结束,准备上传AD数据"); //!!!在此处记录该设备的一套命令已发完,把CmdbulkHex置0;若所有设备的命令发完(包括AD采样),则关闭定时器 dataitem.CmdStage = 1; Log.Debug("设备号为" + dataitem.intDeviceID + "AD采样结束,CmdStage设为1"); //如果是立即采样,则采样完成后上传AD数据 if (dataitem.isGetADNow == true) { UploadADdata(dataitem.strAddress); } } //处理AD数据(收到纯数据时保存到一个60万大小的数组中) if (checkIsPureData(dataitem.SingleBuffer)) { dataitem.currentsendbulk++; for (int i = 7; i < perPackageLength - 1; i++)//将上传的包去掉头和尾的两个字节后,暂时存储在TotalData[]中 { dataitem.byteAllData[dataitem.datalength++] = dataitem.SingleBuffer[i]; } if (dataitem.datalength == g_datafulllength)//1000*600 = 600000; { StoreDataToFile(dataitem.intDeviceID, dataitem.byteAllData); //复位变量 //dataitem.totalsendbulk = 0; dataitem.currentsendbulk = 0; dataitem.isSendDataToServer = false; System.Diagnostics.Debug.WriteLine("数据采集完毕"); //progressBar1.Value = 0; //!!!若所有设备的命令发完(包括AD采样),设置一个属性 //!!!还要加一个判断,若哈希表中的所有设备都已发完命令。就可以关闭定时器了 dataitem.CmdStage = 3; //test Log.Debug("设备号为" + dataitem.intDeviceID + "数据采集完毕,CmdStage设为3"); if (dataitem.isGetADNow == true) { //立即采样结束后恢复采样时刻 byte[] cmdCapTime = cmdItem.CmdSetCapTime; cmdCapTime[9] = (byte)dataitem.CapTimeHour; cmdCapTime[10] = (byte)dataitem.CapTimeMinute; SendCmdSingle(cmdCapTime, dataitem.byteDeviceID, dataitem.socket, 1); dataitem.isGetADNow = false;//立即采样的数据上传完成后,将属性复位为false } } } if (checkIsAllCmdStage1()) //所有设备采样完成,关闭定时器,可以进行上传了 { cmdTimer.Stop(); //add 5-12 Log.Debug("所有设备采样完成,关闭定时器,开始分组"); setTaskGroup(); if (checkIsAllCmdStage2())//所有设备的分组属性设置完,上传第0组,激活分段上传过程 { Log.Debug("分组完成,开始上传"); UploadADdataByGroup(currentUploadGroup); } } //检查是否当前组都下线且下一组都上线 if (checkCurrentOffLineAndNextOnLine(currentUploadGroup)) { //当前组已经发完并下线,可以给下一组发送上传命令了 Log.Debug("当前组已经发完并下线,可以给下一组发送上传命令了"); //将当前组(第0组不用恢复)设备恢复关闭时长 byte[] cmdSetOpenAndCloseTime = cmdItem.CmdSetOpenAndCloseTime; cmdSetOpenAndCloseTime[9] = (byte)(2 * dataitem.OpenTime >> 8); cmdSetOpenAndCloseTime[10] = (byte)(2 * dataitem.OpenTime & 0xFF); cmdSetOpenAndCloseTime[11] = (byte)(2 * dataitem.CloseTime >> 8); cmdSetOpenAndCloseTime[12] = (byte)(2 * dataitem.CloseTime & 0xFF); SendCmdSingle(cmdSetOpenAndCloseTime, dataitem.byteDeviceID, dataitem.socket, 1); currentUploadGroup += 1; UploadADdataByGroup(currentUploadGroup); } if (checkIsAllCmdStage3()) { foreach (DictionaryEntry de in htClient) { DataItem dataitem1 = (DataItem)de.Value; if (dataitem1.CmdStage == 3)//add 5-13 { dataitem.CmdStage = 0; } } Log.Debug("所有设备数据传完,CmdStage置0"); } if (checkIsAllOffLine())//add 5-11 { htClient.Clear(); Log.Debug("清空哈希表"); } //把数据上传到服务器 if (dataitem.isSendDataToServer == true) { SendCmdSingle(SetADcmd(dataitem.currentsendbulk), dataitem.byteDeviceID, dataitem.socket, 1);//发送下一包的命令 System.Diagnostics.Debug.WriteLine("第" + dataitem.currentsendbulk + "包"); Log.Debug("设备号为" + dataitem.intDeviceID + "第" + dataitem.currentsendbulk + "包"); } } else if (bytesRead == 0)//设备自己关闭socket { clientSocket.Shutdown(SocketShutdown.Both); clientSocket.Close(); Log.Debug(dataitem.strAddress + "设备自己关闭socket"); } //需要持续接收 clientSocket.BeginReceive(dataitem.SingleBuffer, 0, dataitem.SingleBuffer.Length, SocketFlags.None, new AsyncCallback(OnReceive), clientSocket); } catch (Exception ex) { string error = DateTime.Now.ToString() + "出错信息:" + "---" + ex.Message + "\n"; Log.Debug(ex); System.Diagnostics.Debug.WriteLine(error); } }