using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using ICSharpCode.SharpZipLib.GZip; using ICSharpCode.SharpZipLib.Tar; using System.IO; using ApiServer.Structures; using NLog; namespace ApiServer { public static class WorkWithFiles { private static Logger log = LogManager.GetCurrentClassLogger(); public static string[] GetFile(string fileName) { var vdp = fileName.Substring(9, 2); var dir_archive = Path.Combine( Directory.GetCurrentDirectory(), "data", "data", fileName.Substring(0,4), fileName.Substring(4, 2), fileName.Substring(6, 2) ); var tmp = Path.Combine( Directory.GetCurrentDirectory(), "temp", System.Guid.NewGuid().ToString() ); if (!Directory.Exists(tmp)) Directory.CreateDirectory(tmp); var flag_exist = false; var tar_gz = false; if (File.Exists(Path.Combine(dir_archive, vdp + ".tar.gz"))) { flag_exist = true; tar_gz = true; dir_archive = Path.Combine(dir_archive, vdp + ".tar.gz"); } if (File.Exists(Path.Combine(dir_archive, vdp + ".tar"))) { flag_exist = true; dir_archive = Path.Combine(dir_archive, vdp + ".tar"); } if (!flag_exist) return Array.Empty(); if (tar_gz) ExtractTarGZ(dir_archive, tmp); else ExtractTar(dir_archive, tmp); if (!File.Exists(Path.Combine(tmp, fileName))) { Directory.Delete(tmp, true); return Array.Empty(); } var result = File.ReadAllLines(Path.Combine(tmp, fileName)); Directory.Delete(tmp, true); return result; } public static byte[] GetFileBytes(string fileName) { var vdp = fileName.Substring(9, 2); var dir_archive = Path.Combine( Directory.GetCurrentDirectory(), "data", "data", fileName.Substring(0, 4), fileName.Substring(4, 2), fileName.Substring(6, 2) ); var tmp = Path.Combine( Directory.GetCurrentDirectory(), "temp", System.Guid.NewGuid().ToString() ); log.Info("Path: " + dir_archive); if (!Directory.Exists(tmp)) Directory.CreateDirectory(tmp); var flag_exist = false; var tar_gz = false; if (File.Exists(Path.Combine(dir_archive, vdp + ".tar.gz"))) { flag_exist = true; tar_gz = true; dir_archive = Path.Combine(dir_archive, vdp + ".tar.gz"); } if (File.Exists(Path.Combine(dir_archive, vdp + ".tar"))) { flag_exist = true; dir_archive = Path.Combine(dir_archive, vdp + ".tar"); } if (!flag_exist) return Array.Empty(); if (tar_gz) ExtractTarGZ(dir_archive, tmp); else ExtractTar(dir_archive, tmp); if (!File.Exists(Path.Combine(tmp, fileName))) { Directory.Delete(tmp, true); return Array.Empty(); } var result = File.ReadAllBytes(Path.Combine(tmp, fileName)); Directory.Delete(tmp, true); return result; } private static void ExtractTarGZ(String gzArchiveName, String destFolder) { using (var a = (Stream)File.OpenRead(gzArchiveName)) using (var b = (Stream)new GZipInputStream(a)) using (var c = TarArchive.CreateInputTarArchive(b)) c.ExtractContents(destFolder); } private static void ExtractTar(String tarFileName, String destFolder) { using (var a = (Stream)File.OpenRead(tarFileName)) using (var b = TarArchive.CreateInputTarArchive(a)) b.ExtractContents(destFolder); } public static Protect[] GetProtects(DateTime date, int vdp) { var result = new List(); var byte_arr = GetFileBytes( date.Year.ToString("D4") + date.Month.ToString("D2") + date.Day.ToString("D2") + "." + vdp.ToString("D2") + "4" ); for (var i = 0; i < byte_arr.Length; i++) { if (i + 3 >= byte_arr.Length) break; var unix_date = BitConverter.ToUInt32(byte_arr, i); i += 4; var date_time = new DateTime(1970, 1, 1, 0, 0, 0, 0); date_time = date_time.AddSeconds(unix_date).ToLocalTime(); if (i + 3 >= byte_arr.Length) break; var nanosec = BitConverter.ToUInt32(byte_arr, i); i += 4; date_time.AddMilliseconds(nanosec / 1000000); while (byte_arr[i] != 0xff) { if (i >= byte_arr.Length) break; var index = byte_arr[i]; i++; if (i >= byte_arr.Length) break; var state = byte_arr[i]; i++; result.Add( new Protect() { Index = index, start = date_time, State = state } ); } } return result.ToArray(); } public static Discret[] GetDiscrets(DateTime date, int vdp) { var desc_struct = Configuration.GetDiscretParams(vdp.ToString("D2")); var result = new List(); var byte_arr = GetFileBytes( date.Year.ToString("D4") + date.Month.ToString("D2") + date.Day.ToString("D2") + "." + vdp.ToString("D2") + "1" ); var date_bytes_struct = new List<(DateTime dt, byte?[] arr)>(); var curr_date = new DateTime(date.Year, date.Month, date.Day, 0, 0, 0); var curr_byte_arr = new List(); var halfsec = 0D; var curr_byte = 0; while (curr_byte < byte_arr.Length) { switch (byte_arr[curr_byte]) { case 0xfb: curr_byte++; if (curr_byte + 3 >= byte_arr.Length) { curr_byte += 3; break; } halfsec = BitConverter.ToUInt32(byte_arr, curr_byte); curr_byte += 4; break; case 0xfc: curr_byte_arr = new List(); date_bytes_struct.Add(( curr_date.AddSeconds(halfsec / 2), curr_byte_arr.ToArray() )); curr_byte++; if (curr_byte + 3 >= byte_arr.Length) { curr_byte += 3; break; } halfsec = BitConverter.ToUInt32(byte_arr, curr_byte); curr_byte += 4; break; case 0xfe: curr_byte++; if (curr_byte + 1 >= byte_arr.Length) { curr_byte++; break; } halfsec += BitConverter.ToInt16(byte_arr, curr_byte); curr_byte += 2; break; case 0xff: date_bytes_struct.Add(( curr_date.AddSeconds(halfsec / 2), curr_byte_arr.ToArray() )); halfsec++; curr_byte++; break; default: while (curr_byte_arr.Count <= byte_arr[curr_byte]) curr_byte_arr.Add(null); curr_byte++; if (curr_byte >= byte_arr.Length) break; curr_byte_arr[byte_arr[curr_byte - 1]] = byte_arr[curr_byte]; curr_byte++; break; } } foreach (var dm in date_bytes_struct) { foreach (var dp in desc_struct) { if (dp.Skip) continue; byte? state = 0; for (var i = 0; i < dp.Bits.Length; i++) { if ( dm.arr.Length <= dp.Bits[i].ByteIndex || !dm.arr[dp.Bits[i].ByteIndex].HasValue ) { state = null; break; } var curr_bit = (dm.arr[dp.Bits[i].ByteIndex].Value >> dp.Bits[i].BitIndex) & 1; state += (byte)(curr_bit * Math.Pow(2, i)); } var last = result.FindLastIndex(x => x.Index == dp.Index); if (last != -1 && result[last].State == state) continue; result.Add(new Discret() { Index = dp.Index, start = dm.dt, State = state }); } } return result.ToArray(); } public static AnalogArr[] GetAnalogs(DateTime date, int vdp) { var analog_struct = Configuration.GetAnalogParams(vdp.ToString("D2")); var result = new List(); var byte_arr = GetFileBytes( date.Year.ToString("D4") + date.Month.ToString("D2") + date.Day.ToString("D2") + "." + vdp.ToString("D2") + "1" ); var date_bytes_struct = new List<(DateTime dt, byte?[] arr)>(); var curr_date = new DateTime(date.Year, date.Month, date.Day, 0, 0, 0); var curr_byte_arr = new List(); var halfsec = 0D; var curr_byte = 0; while (curr_byte < byte_arr.Length) { switch (byte_arr[curr_byte]) { case 0xfb: curr_byte++; if (curr_byte + 3 >= byte_arr.Length) { curr_byte += 3; break; } halfsec = BitConverter.ToUInt32(byte_arr, curr_byte); curr_byte += 4; break; case 0xfc: curr_byte_arr = new List(); date_bytes_struct.Add(( curr_date.AddSeconds(halfsec / 2), curr_byte_arr.ToArray() )); curr_byte++; if (curr_byte + 3 >= byte_arr.Length) { curr_byte += 3; break; } halfsec = BitConverter.ToUInt32(byte_arr, curr_byte); curr_byte += 4; break; case 0xfe: curr_byte++; if (curr_byte + 1 >= byte_arr.Length) { curr_byte++; break; } halfsec += BitConverter.ToInt16(byte_arr, curr_byte); curr_byte += 2; break; case 0xff: date_bytes_struct.Add(( curr_date.AddSeconds(halfsec / 2), curr_byte_arr.ToArray() )); halfsec++; curr_byte++; break; default: while (curr_byte_arr.Count <= byte_arr[curr_byte]) curr_byte_arr.Add(null); curr_byte++; if (curr_byte >= byte_arr.Length) break; curr_byte_arr[byte_arr[curr_byte - 1]] = byte_arr[curr_byte]; curr_byte++; break; } } var sub_res = new Dictionary>(); foreach (var dm in date_bytes_struct) { foreach (var dp in analog_struct) { if (dp.Skip) continue; double? value = 0; var val_arr = new List(); for (var i = 0; i < dp.Bytes.Length; i++) { if ( dm.arr.Length <= dp.Bytes[i] || !dm.arr[dp.Bytes[i]].HasValue ) { value = null; break; } val_arr.Add(dm.arr[dp.Bytes[i]].Value); } if (val_arr != null) { if (val_arr.Count == 1) value = val_arr[0]; else if (val_arr.Count == 2) value = BitConverter.ToInt16(val_arr.ToArray(), 0); else if (val_arr.Count == 4) value = BitConverter.ToInt32(val_arr.ToArray(), 0); else if (val_arr.Count == 8) value = BitConverter.ToInt64(val_arr.ToArray(), 0); else for (var i = 0; i < val_arr.Count; i++) value += (val_arr[i] * Math.Pow(256, i)); } if (value != null) { value = Math.Round(value.Value); value = value.Value * dp.Mul; } if (!sub_res.ContainsKey(dp.Index)) sub_res.Add(dp.Index, new List()); if (sub_res[dp.Index].Count != 0 && sub_res[dp.Index][sub_res[dp.Index].Count - 1].Value == value) continue; sub_res[dp.Index].Add(new Analog() { start = dm.dt, Value = value }); } } foreach (var d in sub_res) result.Add(new AnalogArr() { Index = d.Key, Analogs = d.Value.ToArray() }); return result.ToArray(); } public static DiscretMatrix[] GetDiscretsMatrix(DateTime date, int vdp) { log.Info("Load discret struct for vpd " + vdp); var desc_struct = Configuration.GetDiscretParams(vdp.ToString("D2")); var result = new List(); log.Info("Load file " + date.Year.ToString("D4") + date.Month.ToString("D2") + date.Day.ToString("D2") + "." + vdp.ToString("D2") + "1"); var byte_arr = GetFileBytes( date.Year.ToString("D4") + date.Month.ToString("D2") + date.Day.ToString("D2") + "." + vdp.ToString("D2") + "1" ); var date_bytes_struct = new List<(DateTime dt, byte?[] arr)>(); var curr_date = new DateTime(date.Year, date.Month, date.Day, 0, 0, 0); var curr_byte_arr = new List(); var halfsec = 0D; var curr_byte = 0; log.Info("Parse file to structs."); while (curr_byte < byte_arr.Length) { switch (byte_arr[curr_byte]) { case 0xfb: curr_byte++; if (curr_byte + 3 >= byte_arr.Length) { curr_byte += 3; break; } halfsec = BitConverter.ToUInt32(byte_arr, curr_byte); curr_byte += 4; break; case 0xfc: curr_byte_arr = new List(); date_bytes_struct.Add(( curr_date.AddSeconds(halfsec / 2), curr_byte_arr.ToArray() )); curr_byte++; if (curr_byte + 3 >= byte_arr.Length) { curr_byte += 3; break; } halfsec = BitConverter.ToUInt32(byte_arr, curr_byte); curr_byte += 4; break; case 0xfe: curr_byte++; if (curr_byte + 1 >= byte_arr.Length) { curr_byte++; break; } halfsec += BitConverter.ToInt16(byte_arr, curr_byte); curr_byte += 2; break; case 0xff: date_bytes_struct.Add(( curr_date.AddSeconds(halfsec / 2), curr_byte_arr.ToArray() )); halfsec++; curr_byte++; break; default: while (curr_byte_arr.Count <= byte_arr[curr_byte]) curr_byte_arr.Add(null); curr_byte++; if (curr_byte >= byte_arr.Length) break; curr_byte_arr[byte_arr[curr_byte - 1]] = byte_arr[curr_byte]; curr_byte++; break; } } var b_matrix = new List(); foreach(var d_slice in date_bytes_struct) { var sub_res = new DiscretMatrix() { start = d_slice.dt }; foreach (var d_struct in desc_struct) { while (b_matrix.Count <= d_struct.Index) b_matrix.Add(null); byte? state = 0; for (var i = 0; i < d_struct.Bits.Length; i++) { if ( d_slice.arr.Length <= d_struct.Bits[i].ByteIndex || !d_slice.arr[d_struct.Bits[i].ByteIndex].HasValue ) { state = null; break; } var curr_bit = (d_slice.arr[d_struct.Bits[i].ByteIndex].Value >> d_struct.Bits[i].BitIndex) & 1; state += (byte)(curr_bit * Math.Pow(2, i)); } b_matrix[d_struct.Index] = state; } sub_res.M = b_matrix.ToArray(); result.Add(sub_res); } return result.ToArray(); } } }