using HandyControl.Controls; using JiangsuEarthquake.Common; using JiangsuEarthquake.DataAccess; using JiangsuEarthquake.ViewModels; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace JiangsuEarthquake.Models { public class SeismographModel { private byte[] syncSend { get; set; } = new byte[4] { 0xBF, 0x13, 0x97, 0x74 }; //同步字,为0xbf139774 private byte[] cmdSend { get; set; } = new byte[2]; //帧标志 private byte[] cmdRecv { get; set; } = new byte[2]; //帧标志 private byte[] lengthSend { get; set; } = new byte[2]; //从DATA开始的帧长度,单位:字节 private byte[] lengthRecv { get; set; } = new byte[2]; //从DATA开始的帧长度,单位:字节 private List dataSend { get; set; } = new List(); //数据部分 private List dataRecv { get; set; } = new List(); //数据部分 private byte[] checkCode { get; set; } = new byte[2]; //从CMD到DATA结束的CRC16校验和 private List checkByte { get; set; } = new List(); //校验码Byte public void ParsingData(List byteList, int id) { if (byteList.Count == 0) return; //原始数据存储 string sql = $"insert into earthquakeoriginaldata(StationID,RecordTime,OriginalData) values('{id}','{DateTime.Now}','{BitConverter.ToString(byteList.ToArray())}');"; DBHelper.ExecuteNonQuery(sql, 1); //同步字校验 if (byteList[0] != 0xBF || byteList[1] != 0x13 || byteList[2] != 0x97 || byteList[3] != 0x74) return; checkByte.Clear(); //CRC16校验和校验 for (int i = 4; i < byteList.Count - 2; i++) checkByte.Add(byteList[i]); if (!Tools.CompareByte(new byte[] { byteList[^2], byteList[^1] }, Tools.CRCCalc(checkCode.ToArray()))) return; //长度校验 int length = BitConverter.ToInt16(new byte[] { byteList[7], byteList[6] }, 0); if (length != byteList.Count - 8) return; cmdRecv = new byte[] { byteList[4], byteList[5] }; dataRecv.Clear(); for (int i = 8; i < byteList.Count - 2; i++) dataRecv.Add(byteList[i]); if (Tools.CompareByte(cmdRecv, new byte[] { 0x77, 0x00 })) //用于客户端与状态流服务器建立链接过程中消息交换 { if (dataRecv.Count != 2) return; int response = BitConverter.ToInt16(new byte[2] { dataRecv[1], dataRecv[0] }, 0); if (response == 100) { //有空闲连接时应答 //发送用户认证帧 cmdSend = new byte[] { 0x77, 0x00 }; lengthSend = new byte[] { 0x00, 0x04 }; string User = "Admin"; byte[] userByte = System.Text.Encoding.ASCII.GetBytes(User); byte[] userByteArray = new byte[16]; if (userByte.Length != 16) { for (int i = 0; i < 16; i++) { userByteArray[i] = 0; } Array.Copy(userByte, 0, userByteArray, 16, userByte.Length); } else { userByteArray = userByte; } string Password = "Admin"; byte[] passwordByte = System.Text.Encoding.ASCII.GetBytes(Password); byte[] passwordByteArray = new byte[40]; if (passwordByte.Length != 40) { for (int i = 0; i < 40; i++) { passwordByteArray[i] = 0; } Array.Copy(passwordByte, 0, passwordByteArray, 40, passwordByte.Length); } else { passwordByteArray = passwordByte; } dataSend.Clear(); dataSend.AddRange(userByteArray); dataSend.AddRange(passwordByteArray); checkByte.Clear(); checkByte.AddRange(cmdSend); checkByte.AddRange(lengthSend); checkByte.AddRange(userByteArray); checkByte.AddRange(passwordByteArray); checkCode = Tools.CRCCalc(checkByte.ToArray()); dataSend.AddRange(checkCode); if (id == 1) { MainWindow.mainViewModel.clientModelDZY1.SendMessage(dataSend.ToArray()); } else { MainWindow.mainViewModel.clientModelDZY2.SendMessage(dataSend.ToArray()); } } else if (response == 405) { //没有空闲连接 //重新尝试连接 } else if (response == 200) { //认证成功 //连接成功 } else if (response == 400) { //认证失败 //重新尝试连接 } } else { if (Tools.CompareByte(cmdRecv, new byte[] { 0xC0, 0x00 })) //台站参数 { if (dataRecv.Count != 128) return; //台号 int stationNum = BitConverter.ToInt32(new byte[] { dataRecv[3], dataRecv[2], dataRecv[1], dataRecv[0] }, 0); //台站名称 List stationNameData = new List(); for (int i = 4; i < 36; i++) stationNameData.Add(dataRecv[i]); string stationName = Encoding.UTF8.GetString(stationNameData.ToArray()); //台名缩写 List stationNameAbbData = new List(); for (int i = 36; i < 44; i++) stationNameAbbData.Add(dataRecv[i]); string stationNameAbb = Encoding.UTF8.GetString(stationNameAbbData.ToArray()); //地震计总数 short seisNum = BitConverter.ToInt16(new byte[] { dataRecv[45], dataRecv[44] }, 0); //总通道数 short passNum = BitConverter.ToInt16(new byte[] { dataRecv[47], dataRecv[46] }, 0); //纬度 int latitude = BitConverter.ToInt16(new byte[] { dataRecv[51], dataRecv[50], dataRecv[49], dataRecv[48] }, 0); //经度 int longitude = BitConverter.ToInt16(new byte[] { dataRecv[55], dataRecv[54], dataRecv[53], dataRecv[52] }, 0); //高程 int elevation = BitConverter.ToInt16(new byte[] { dataRecv[59], dataRecv[58], dataRecv[57], dataRecv[56] }, 0); //起用日期 List enablingDateList = new List(); for (int i = 60; i < 92; i++) enablingDateList.Add(dataRecv[i]); string enablingDate = Encoding.UTF8.GetString(enablingDateList.ToArray()); //台网标志 string tetworkLogo = Encoding.UTF8.GetString(new byte[] { dataRecv[95], dataRecv[94], dataRecv[93], dataRecv[92] }); //软件编本 List softVersionList = new List(); for (int i = 96; i < 128; i++) softVersionList.Add(dataRecv[i]); string softVersion = Encoding.UTF8.GetString(softVersionList.ToArray()); //数据存储 sql = $"insert into earthquakeoriginaldata(StationID,RecordTime,StationNo,StationName," + $"StationShortName,EarthQuakeCount,ChannelsNo,WD,JD,GaoCheng,StartTime,Station_Id," + $"Software_Version) values('{id}','{DateTime.Now}','{stationNum}','{stationName}','{stationNameAbb}','{seisNum}','{passNum}','{latitude}','{longitude}','{elevation}','{enablingDate}','{tetworkLogo}','{softVersion}');"; DBHelper.ExecuteNonQuery(sql, 1); //通知到前端 if (id == 1) { MainViewModel.earthQuakeParaSetModel1.StationID = stationNum; MainViewModel.earthQuakeParaSetModel1.StationName = stationName; MainViewModel.earthQuakeParaSetModel1.StationShortName = stationNameAbb; MainViewModel.earthQuakeParaSetModel1.EarthQuakeCount = seisNum; MainViewModel.earthQuakeParaSetModel1.ChannelsNo = passNum; MainViewModel.earthQuakeParaSetModel1.WD = latitude; MainViewModel.earthQuakeParaSetModel1.JD = longitude; MainViewModel.earthQuakeParaSetModel1.GaoCheng = elevation; MainViewModel.earthQuakeParaSetModel1.StartTime = enablingDate; MainViewModel.earthQuakeParaSetModel1.Station_Id = tetworkLogo; MainViewModel.earthQuakeParaSetModel1.Software_Version = softVersion; } else { MainViewModel.earthQuakeParaSetModel2.StationID = stationNum; MainViewModel.earthQuakeParaSetModel2.StationName = stationName; MainViewModel.earthQuakeParaSetModel2.StationShortName = stationNameAbb; MainViewModel.earthQuakeParaSetModel2.EarthQuakeCount = seisNum; MainViewModel.earthQuakeParaSetModel2.ChannelsNo = passNum; MainViewModel.earthQuakeParaSetModel2.WD = latitude; MainViewModel.earthQuakeParaSetModel2.JD = longitude; MainViewModel.earthQuakeParaSetModel2.GaoCheng = elevation; MainViewModel.earthQuakeParaSetModel2.StartTime = enablingDate; MainViewModel.earthQuakeParaSetModel2.Station_Id = tetworkLogo; MainViewModel.earthQuakeParaSetModel2.Software_Version = softVersion; } } else if (Tools.CompareByte(cmdRecv, new byte[] { 0xC0, 0x50 })) //启动地震计调零 { if (dataRecv.Count != 2) return; int seisNum = BitConverter.ToInt16(new byte[] { dataRecv[1], dataRecv[0] }, 0); } else if (Tools.CompareByte(cmdRecv, new byte[] { 0xC0, 0x51 })) //停止地震计调零 { if (dataRecv.Count != 2) return; int seisNum = BitConverter.ToInt16(new byte[] { dataRecv[1], dataRecv[0] }, 0); } else if (Tools.CompareByte(cmdRecv, new byte[] { 0xC0, 0x66 })) //运行状态信息 { if (dataRecv.Count != 56) return; //外部供电电压 float supplyVoltage = BitConverter.ToInt16(new byte[] { dataRecv[1], dataRecv[0] }, 0) * 0.1f; //后备电池电压 float batteryVoltage = BitConverter.ToInt16(new byte[] { dataRecv[3], dataRecv[2] }, 0) * 0.1f; //压力 int pressure = BitConverter.ToInt16(new byte[] { dataRecv[5], dataRecv[4] }, 0); //温度 float temperature = BitConverter.ToInt16(new byte[] { dataRecv[7], dataRecv[6] }, 0) * 0.1f; //地震计倾斜角度 float tiltAngleSeis = BitConverter.ToInt16(new byte[] { dataRecv[9], dataRecv[8] }, 0) * 0.1f; //OBS 倾斜角度 float tiltAngleOBS = BitConverter.ToInt16(new byte[] { dataRecv[11], dataRecv[10] }, 0) * 0.1f; //钟差 int clockDeviation = BitConverter.ToInt16(new byte[] { dataRecv[13], dataRecv[12] }, 0); //频差 float freDifference = BitConverter.ToInt16(new byte[] { dataRecv[15], dataRecv[14] }, 0) * 0.01f; //CF 卡总空间 int totalSpaceCF = BitConverter.ToInt16(new byte[] { dataRecv[19], dataRecv[18], dataRecv[17], dataRecv[16] }, 0); //CF 卡可用空间 int canUseSpaceCF = BitConverter.ToInt16(new byte[] { dataRecv[23], dataRecv[22], dataRecv[21], dataRecv[20] }, 0); //SD1 卡总空间 int totalSpaceSD1 = BitConverter.ToInt16(new byte[] { dataRecv[27], dataRecv[26], dataRecv[25], dataRecv[24] }, 0); //SD1 卡可用空间 int canUseSpaceSD1 = BitConverter.ToInt16(new byte[] { dataRecv[31], dataRecv[30], dataRecv[29], dataRecv[28] }, 0); //SD2 卡总空间 int totalSpaceSD2 = BitConverter.ToInt16(new byte[] { dataRecv[35], dataRecv[34], dataRecv[33], dataRecv[32] }, 0); //SD2 卡可用空间 int canUseSpaceSD2 = BitConverter.ToInt16(new byte[] { dataRecv[39], dataRecv[38], dataRecv[37], dataRecv[36] }, 0); //地震计 U 零点 float zeroPointU = BitConverter.ToInt16(new byte[] { dataRecv[43], dataRecv[42], dataRecv[41], dataRecv[40] }, 0) * 0.1f; //地震计 V 零点 float zeroPointV = BitConverter.ToInt16(new byte[] { dataRecv[47], dataRecv[46], dataRecv[45], dataRecv[44] }, 0) * 0.1f; //地震计 W 零点 float zeroPointW = BitConverter.ToInt16(new byte[] { dataRecv[51], dataRecv[50], dataRecv[49], dataRecv[48] }, 0) * 0.1f; //寻北角度 float northSeekingAngle = BitConverter.ToInt16(new byte[] { dataRecv[55], dataRecv[54], dataRecv[53], dataRecv[52] }, 0) * 0.1f; //数据存储 sql = $"insert into earthquakestate(StationID,RecordTime,Out_Vol,Backup_Vol,Pre,Tem," + $"Sei_Tilt_Angle,OBS_Tilt_Angle,Species_Dif,Frequency_Dif,CF_Total_Cap," + $"CF_Usable_Cap,SD_Total_Cap1,SD_Usable_Cap1,SD_Total_Cap2,SD_Usable_Cap2," + $"Sei_U_Point,Sei_V_Point,Sei_W_Point,North_Angle) values('{id}','{DateTime.Now}','{supplyVoltage}','{batteryVoltage}','{pressure}'," + $"'{temperature}','{tiltAngleSeis}','{tiltAngleOBS}','{clockDeviation}'," + $"'{freDifference}','{totalSpaceCF}','{canUseSpaceCF}','{totalSpaceSD1}'," + $"'{canUseSpaceSD1}','{totalSpaceSD2}','{canUseSpaceSD2}','{zeroPointU}'," + $"'{zeroPointV}','{zeroPointW}','{northSeekingAngle}');"; DBHelper.ExecuteNonQuery(sql, 1); //通知到前端 if (id == 1) { MainViewModel.earthquakeSensorModel1.Out_Vol = supplyVoltage; MainViewModel.earthquakeSensorModel1.Backup_Vol = batteryVoltage; MainViewModel.earthquakeSensorModel1.Pre = pressure; MainViewModel.earthquakeSensorModel1.Tem = temperature; MainViewModel.earthquakeSensorModel1.Sei_Tilt_Angle = tiltAngleSeis; MainViewModel.earthquakeSensorModel1.OBS_Tilt_Angle = tiltAngleOBS; MainViewModel.earthquakeSensorModel1.Species_Dif = clockDeviation; MainViewModel.earthquakeSensorModel1.Frequency_Dif = freDifference; MainViewModel.earthquakeSensorModel1.CF_Total_Cap = totalSpaceCF; MainViewModel.earthquakeSensorModel1.CF_Usable_Cap = canUseSpaceCF; MainViewModel.earthquakeSensorModel1.SD_Total_Cap1 = totalSpaceSD1; MainViewModel.earthquakeSensorModel1.SD_Usable_Cap1 = canUseSpaceSD1; MainViewModel.earthquakeSensorModel1.SD_Total_Cap2 = totalSpaceSD2; MainViewModel.earthquakeSensorModel1.SD_Usable_Cap2 = canUseSpaceSD2; MainViewModel.earthquakeSensorModel1.Sei_U_Point = zeroPointU; MainViewModel.earthquakeSensorModel1.Sei_V_Point = zeroPointV; MainViewModel.earthquakeSensorModel1.Sei_W_Point = zeroPointW; MainViewModel.earthquakeSensorModel1.North_Angle = northSeekingAngle; } else { MainViewModel.earthquakeSensorModel2.Out_Vol = supplyVoltage; MainViewModel.earthquakeSensorModel2.Backup_Vol = batteryVoltage; MainViewModel.earthquakeSensorModel2.Pre = pressure; MainViewModel.earthquakeSensorModel2.Tem = temperature; MainViewModel.earthquakeSensorModel2.Sei_Tilt_Angle = tiltAngleSeis; MainViewModel.earthquakeSensorModel2.OBS_Tilt_Angle = tiltAngleOBS; MainViewModel.earthquakeSensorModel2.Species_Dif = clockDeviation; MainViewModel.earthquakeSensorModel2.Frequency_Dif = freDifference; MainViewModel.earthquakeSensorModel2.CF_Total_Cap = totalSpaceCF; MainViewModel.earthquakeSensorModel2.CF_Usable_Cap = canUseSpaceCF; MainViewModel.earthquakeSensorModel2.SD_Total_Cap1 = totalSpaceSD1; MainViewModel.earthquakeSensorModel2.SD_Usable_Cap1 = canUseSpaceSD1; MainViewModel.earthquakeSensorModel2.SD_Total_Cap2 = totalSpaceSD2; MainViewModel.earthquakeSensorModel2.SD_Usable_Cap2 = canUseSpaceSD2; MainViewModel.earthquakeSensorModel2.Sei_U_Point = zeroPointU; MainViewModel.earthquakeSensorModel2.Sei_V_Point = zeroPointV; MainViewModel.earthquakeSensorModel2.Sei_W_Point = zeroPointW; MainViewModel.earthquakeSensorModel2.North_Angle = northSeekingAngle; } } else if (Tools.CompareByte(cmdRecv, new byte[] { 0xC0, 0x90 })) //启动地震计调平 { if (dataRecv.Count != 2) return; int seisNum = BitConverter.ToInt16(new byte[] { dataRecv[1], dataRecv[0] }, 0); } else if (Tools.CompareByte(cmdRecv, new byte[] { 0xC0, 0x91 })) //停止地震计调平 { if (dataRecv.Count != 2) return; int seisNum = BitConverter.ToInt16(new byte[] { dataRecv[1], dataRecv[0] }, 0); } } } } }