using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Imaging; using System.Globalization; using System.IO; using System.Linq; using System.Text; using System.Windows.Forms; using Correlator.Model; using Correlator.SensorHubTag; using HandyControl.Controls; using MathWorks.MATLAB.NET.Arrays; using Tag = Correlator.SensorHubTag.Tag; namespace Correlator.Util { public static class MethodExtensions { private const int HeaderSize = 44; private static FileStream CreateEmptyWaveHeader(this string filePath) { var fileStream = new FileStream(filePath, FileMode.OpenOrCreate); const byte emptyByte = new byte(); for (var i = 0; i < HeaderSize; i++) { fileStream.WriteByte(emptyByte); } return fileStream; } public static void SaveWavFile(this string filePath, double[] dataArray, double[] dataArray1) { try { var fileStream = filePath.CreateEmptyWaveHeader(); var bytesData = new byte[dataArray.Length * 16]; for (var i = 0; i < dataArray.Length; i++) { var byteArray16 = new byte[16]; BitConverter.GetBytes(dataArray[i]).CopyTo(byteArray16, 0); BitConverter.GetBytes(dataArray1[i]).CopyTo(byteArray16, 8); byteArray16.CopyTo(bytesData, i * 16); } fileStream.Write(bytesData, 0, bytesData.Length); fileStream.Flush(); //重写头文件 fileStream.WriteHeader(7500, 2); } catch (Exception e) { "MethodExtensions".WriteLog(e.Message); } } private static void WriteHeader(this FileStream fileStream, int hz, int channels) { //hz = 7500;//采样频率 //channels = 1;//单声道为1,双声道为2 //samples = 3750;//实际样本数 try { fileStream.Seek(0, SeekOrigin.Begin); //资源交换文件标志(RIFF) var riff = Encoding.UTF8.GetBytes("RIFF"); //### fileStream.Write(riff, 0, 4); //从下个地址开始到文件尾的总字节数 var chunkSize = BitConverter.GetBytes(fileStream.Length - 8); //### fileStream.Write(chunkSize, 0, 4); //WAV文件标志 var wave = Encoding.UTF8.GetBytes("WAVE"); //### fileStream.Write(wave, 0, 4); //波形格式标志 var fmt = Encoding.UTF8.GetBytes("fmt "); //### fileStream.Write(fmt, 0, 4); //过滤字节一般为00000010H,若为00000012H则说明数据头携带附加信息 var subChunk1 = BitConverter.GetBytes(16); //### fileStream.Write(subChunk1, 0, 4); //格式种类值为1时表示数据为线性PCM编码 var audioFormat = BitConverter.GetBytes((short)1); //### fileStream.Write(audioFormat, 0, 2); //通道数,单声道为1,双声道为2 var numChannels = BitConverter.GetBytes((short)channels); //### fileStream.Write(numChannels, 0, 2); //采样频率 # var sampleRate = BitConverter.GetBytes(hz); fileStream.Write(sampleRate, 0, 4); //波形数据传输速率 var byRate = BitConverter.GetBytes(hz * channels * 2 * 8 / 8); fileStream.Write(byRate, 0, 4); //data数据块长度,字节 var blockAlign = (ushort)(channels * 8 * 2 / 8); fileStream.Write(BitConverter.GetBytes(blockAlign), 0, 2); //PCM位宽 const ushort bps = 16; var bitsPerSample = BitConverter.GetBytes(bps); fileStream.Write(bitsPerSample, 0, 2); //数据标志符data var dataString = Encoding.UTF8.GetBytes("data"); fileStream.Write(dataString, 0, 4); var samples = ((int)fileStream.Length - 44) / 16; //Data总数据长度,字节 var subChunk2 = BitConverter.GetBytes(samples * channels * 2); fileStream.Write(subChunk2, 0, 4); fileStream.Close(); } catch (Exception ex) { "MethodExtensions".WriteLog(ex.Message); } } /// <summary> /// Log本地化,并输出在Console,便于Debug /// </summary> /// <param name="className"></param> /// <param name="log"></param> public static void WriteLog(this string className, string log) { Console.WriteLine($@"{className} => {log}"); LogHelper.Info(log); } /// <summary> /// 计算文件占用空间大小 /// </summary> /// <param name="size"></param> /// <returns></returns> public static string FormatFileSize(this long size) { string fileSize; if (size == 0) { fileSize = "0B"; } else if (size < 1024) { fileSize = $"{size:#.0}" + "B"; } else if (size < 1048576) { fileSize = $"{(double)size / 1024:#.0}" + "K"; } else if (size < 1073741824) { fileSize = $"{(double)size / 1048576:#.0}" + "M"; } else { fileSize = $"{(double)size / 1073741824:#.0}" + "G"; } return fileSize; } /// <summary> /// 字节数组转Int /// </summary> /// <param name="bytes"></param> /// <returns></returns> public static int ConvertToInt(this byte[] bytes) { return bytes.Aggregate(0, (current, b) => 16 * 16 * current + b); } /// <summary> /// 字节数组转String /// </summary> /// <param name="bytes"></param> /// <returns></returns> private static string ConvertToString(this byte[] bytes) { return bytes.Aggregate("", (current, t) => current + t.ToString("X2")); } /// <summary> /// 字符串转byte /// </summary> /// <param name="str"></param> /// <returns></returns> public static byte ConvertToByte(this string str) { return byte.Parse(str, NumberStyles.HexNumber); } /// <summary> /// 字符串转BCD码 /// </summary> /// <param name="str"></param> /// <returns></returns> public static byte ConvertToBcdCode(this string str) { return (byte)(int.Parse(str.Substring(0, 1)) * 16 + int.Parse(str.Substring(1, 1))); } /// <summary> /// 字符串转byte[] /// </summary> /// <param name="str"></param> /// <returns></returns> private static byte[] ConvertToByteArray(string str) { var ret = new byte[str.Length / 2]; for (var i = 0; i < str.Length / 2; i++) { ret[i] = byte.Parse(str.Substring(i * 2, 2), NumberStyles.HexNumber); } return ret; } public static string AppendLeftZero(this int i) { //数据固定长度2 return i.ToString("G").PadLeft(2, '0'); } /// <summary> /// 转16进制字符串 /// </summary> /// <param name="src"></param> /// <returns></returns> public static string ConvertToHexString(this string src) { if (src.Length == 4) { return src; } var temp = ""; for (var i = 0; i < 4 - src.Length; i++) { temp += "0"; } return temp + src; } /// <summary> /// 截屏 /// </summary> /// <param name="filePath"></param> public static void SnapShot(this string filePath) { var width = Screen.PrimaryScreen.Bounds.Width; var height = Screen.PrimaryScreen.Bounds.Height; var memoryImage = new Bitmap(width, height); var memoryGraphics = Graphics.FromImage(memoryImage); memoryGraphics.CopyFromScreen(0, 0, 0, 0, new Size(width, height), CopyPixelOperation.SourceCopy); var data = new MemoryStream(); memoryImage.Save(data, ImageFormat.Png); var fs = new FileStream(filePath, FileMode.OpenOrCreate); var w = new BinaryWriter(fs); w.Write(data.ToArray()); fs.Close(); data.Close(); Growl.Success("快照已保存"); } /// <summary> /// 字节数组转数据Tag集合 /// </summary> /// <param name="tagBytes"></param> /// <returns></returns> public static List<Tag> GetTags(this byte[] tagBytes) { var tags = new List<Tag>(); try { var i = 0; // var n = 0; while (i < tagBytes.Length) { // n++; var oidBytes = new byte[4]; Array.Copy(tagBytes, i, oidBytes, 0, 4); var oid = oidBytes.ConvertToString(); //value域的长度 var tagValueBytes = new byte[2]; Array.Copy(tagBytes, i + 4, tagValueBytes, 0, 2); Array.Reverse(tagValueBytes); int tagValueLength = BitConverter.ToInt16(tagValueBytes, 0); // Console.WriteLine($@"value域的长度 => {tagValueLength}"); var valueBytes = new byte[tagValueLength]; Array.Copy(tagBytes, i + 6, valueBytes, 0, tagValueLength); // Console.WriteLine($@"第{n}个Tag => {BitConverter.ToString(valueBytes)}"); i = i + 6 + tagValueLength; var tag = TagFactory.Create(oid, tagValueLength, valueBytes); tags.Add(tag); } } catch (Exception e) { "MethodExtensions".WriteLog($"设备上传协议出错:{e.Message}"); } return tags; } /// <summary> /// 通过Linq查找电量Tag /// </summary> /// <param name="tags"></param> /// <returns></returns> public static CellTag GetCellTag(this List<Tag> tags) { return tags.Where(tag => tag is CellTag).Cast<CellTag>().FirstOrDefault(); } /// <summary> /// 通过Linq查找状态Tag /// </summary> /// <param name="tags"></param> /// <returns></returns> public static SensorExceptionTag GetSensorExceptionTag(this IEnumerable<Tag> tags) { return tags.Where(tag => tag is SensorExceptionTag).Cast<SensorExceptionTag>().FirstOrDefault(); } /// <summary> /// 十六进制转double /// </summary> /// <param name="src"></param> /// <returns></returns> public static double HexToDouble(this IReadOnlyList<byte> src) { if (src.Count != 3) return 0; short result1 = src[0]; short result2 = src[1]; short result3 = src[2]; if ((result1 & 0x80) == 0x80) { result1 = Convert.ToInt16(result1 - 255); result2 = Convert.ToInt16(result2 - 255); result3 = Convert.ToInt16(result3 - 255); } var data = (result1 * 65536 + result2 * 256 + result3) * 5 / 83.88607 / 100000; return data; } /// <summary> /// 通过Linq查找噪声Tag /// </summary> /// <param name="tags"></param> /// <returns></returns> public static UploadTag GetUploadNoiseTag(this IEnumerable<Tag> tags) { return tags.Where(tag => tag is UploadTag).Cast<UploadTag>().FirstOrDefault(); } /// <summary> /// MWNumericArray转double[] /// </summary> /// <param name="inputMw"></param> /// <returns></returns> public static double[] GetArray(this MWNumericArray inputMw) { var num = inputMw.NumberOfElements; var outArray = new double[num]; for (var i = 0; i < num; i++) { outArray[i] = Convert.ToDouble(inputMw[i + 1].ToString()); } return outArray; } /// <summary> /// 二进制转byte[] /// </summary> /// <param name="ints"></param> /// <returns></returns> public static byte[] ToByteArray(this List<int> ints) { var bitIndex = new List<byte>(); for (var i = 1; i <= 64; i++) { bitIndex.Add(ints.Contains(i) ? (byte)0 : (byte)1); } //每八位为一个字节 var tempBytes = new List<byte>(); for (var i = 0; i < bitIndex.Count; i += 8) { var bytes = new List<byte> { bitIndex[i], bitIndex[i + 1], bitIndex[i + 2], bitIndex[i + 3], bitIndex[i + 4], bitIndex[i + 5], bitIndex[i + 6], bitIndex[i + 7] }; var builder = new StringBuilder(); foreach (var b in bytes) { builder.Append(b); } var binary = builder.ToString(); //二进制转十进制 var decimalValue = Convert.ToInt32(binary, 2); //十进制转byte,0~255之间的int值才可以,否则需要先转为Hex,再由Hex转为byte[] tempBytes.Add(Convert.ToByte(decimalValue)); } return tempBytes.ToArray(); } /// <summary> /// 数据类型 /// </summary> /// <param name="i"></param> /// <returns></returns> public static string ToChineseType(this int i) { //1,2,3,4分别代表流量、压力、液位、噪声 switch (i) { case 1: return "流量数据"; case 2: return "压力数据"; case 3: return "液位数据"; case 4: return "噪声数据"; default: return "未知类型数据"; } } /// <summary> /// 二维集合转为一维数组 /// </summary> /// <param name="doubleArrays">二维集合</param> /// <returns></returns> public static double[] ToOneDimensionalArray(this List<List<double>> doubleArrays) { var totalData = new List<double>(); foreach (var item in doubleArrays) { totalData.AddRange(item); } return totalData.ToArray(); } /// <summary> /// 保存传感器上传的原始数据 /// </summary> /// <param name="fileName"></param> /// <param name="response"></param> public static void SaveSensorResponse(this string fileName, List<string> response) { var builder = new StringBuilder(); for (var i = 0; i < response.Count; i++) { var str = response[i]; if (i == response.Count - 1) { builder.Append(str); } else { builder.Append(str).Append("\r\n"); } } File.AppendAllText(fileName, builder.ToString()); } /// <summary> /// 每个音频数据 /// </summary> private static string _perData; /// <summary> /// 保存听音上传的原始数据 /// </summary> /// <param name="dataArray"></param> public static void SaveSoundData(this List<byte[]> dataArray) { using (var manager = new DataBaseManager()) { var today = DateTime.Now.ToString("yyyyMMdd"); var configModel = manager .Table<CorrelatorConfigModel>() .Where(x => x.Date == today) .OrderBy(x => x.Date) .LastOrDefault() ?? new CorrelatorConfigModel { Date = today, Pipe = 1, LocateTimes = 1, ListenTimes = 1 }; //如果配置里面的日期相同,则取配置里面的Pipe作为index,如果配置里面的日期不相同,则默认index=1 var pipeIndex = configModel.Date.Equals(today) ? configModel.Pipe : 1; var listenDataDir = DirectoryManager.GetListenDir(); var listenTimes = configModel.LocateTimes; var fileName = $"{listenDataDir}\\听音数据{today}.{pipeIndex}.{listenTimes}.txt"; var builder = new StringBuilder(); for (var i = 0; i < dataArray.Count; i++) { _perData = BitConverter.ToString(dataArray[i]); if (i == dataArray.Count - 1) { builder.Append(_perData); } else { builder.Append(_perData).Append("\r\n"); } } File.AppendAllText(fileName, builder.Replace("-", "").ToString()); //插入新纪录 configModel.Pipe++; configModel.LocateTimes++; manager.Insert(configModel); //清空缓存 RuntimeCache.SoundCaches.Clear(); } } /// <summary> /// 保存定位数据 /// </summary> /// <param name="fileName">完整路径</param> /// <param name="it">CorrelatorDataModel</param> public static void SaveLocateData(this string fileName, CorrelatorDataModel it) { var builder = new StringBuilder(); builder.Append(DateTime.Now.ToString(CultureInfo.InvariantCulture)).Append("\r\n"); foreach (var d in it.LeftDeviceDataArray) { builder.Append(d).Append("\r\n"); } builder.Append("===============").Append("\r\n"); for (var i = 0; i < it.RightDeviceDataArray.Length; i++) { var d = it.RightDeviceDataArray[i]; if (i == it.RightDeviceDataArray.Length - 1) { builder.Append(d); } else { builder.Append(d).Append("\r\n"); } } File.AppendAllText(fileName, builder.ToString()); } /// <summary> /// 本地数据读取 /// </summary> /// <param name="filePath"></param> /// <returns></returns> public static List<string> ReadFromFile(this string filePath) { var list = new List<string>(); var streamReader = new StreamReader(filePath); string line; while ((line = streamReader.ReadLine()) != null) { list.Add(line); } streamReader.Close(); return list; } public static void SaveArrayToFile(this double[] array, string fileName) { var builder = new StringBuilder(); foreach (var d in array) { builder.Append(d).Append("\r\n"); } File.AppendAllText(fileName, builder.ToString()); } /// <summary> /// 根据列表返回总页码 /// </summary> /// <param name="count"></param> /// <returns></returns> public static int GetPageSize(this int count) { return (count + RuntimeCache.PerPageItemCount - 1) / RuntimeCache.PerPageItemCount; } } }