545 lines
16 KiB
C#
545 lines
16 KiB
C#
|
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<string>();
|
|||
|
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<string>();
|
|||
|
}
|
|||
|
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<byte>();
|
|||
|
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<byte>();
|
|||
|
}
|
|||
|
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<Protect>();
|
|||
|
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<Discret>();
|
|||
|
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<byte?>();
|
|||
|
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<byte?>();
|
|||
|
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<AnalogArr>();
|
|||
|
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<byte?>();
|
|||
|
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<byte?>();
|
|||
|
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<int, List<Analog>>();
|
|||
|
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<byte>();
|
|||
|
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<Analog>());
|
|||
|
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<DiscretMatrix>();
|
|||
|
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<byte?>();
|
|||
|
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<byte?>();
|
|||
|
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<byte?>();
|
|||
|
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();
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
}
|