diff --git a/Correlator/App.xaml.cs b/Correlator/App.xaml.cs index 5c9dd37..c66d198 100644 --- a/Correlator/App.xaml.cs +++ b/Correlator/App.xaml.cs @@ -98,6 +98,7 @@ containerRegistry.RegisterSingleton(); containerRegistry.RegisterSingleton(); containerRegistry.RegisterSingleton(); + containerRegistry.RegisterSingleton(); //Dialog or Window containerRegistry.RegisterDialog(); @@ -105,6 +106,8 @@ containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); + containerRegistry.RegisterDialog(); + containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); diff --git a/Correlator/App.xaml.cs b/Correlator/App.xaml.cs index 5c9dd37..c66d198 100644 --- a/Correlator/App.xaml.cs +++ b/Correlator/App.xaml.cs @@ -98,6 +98,7 @@ containerRegistry.RegisterSingleton(); containerRegistry.RegisterSingleton(); containerRegistry.RegisterSingleton(); + containerRegistry.RegisterSingleton(); //Dialog or Window containerRegistry.RegisterDialog(); @@ -105,6 +106,8 @@ containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); + containerRegistry.RegisterDialog(); + containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); diff --git a/Correlator/Converter/SoundParamValueConverter.cs b/Correlator/Converter/SoundParamValueConverter.cs new file mode 100644 index 0000000..4101a19 --- /dev/null +++ b/Correlator/Converter/SoundParamValueConverter.cs @@ -0,0 +1,26 @@ +using System; +using System.Globalization; +using System.Windows.Data; + +namespace Correlator.Converter +{ + public class SoundParamValueConverter : IMultiValueConverter + { + public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) + { + try + { + return "声速:" + values[0] + "m/s,采样率:" + values[1] + "Hz"; + } + catch (Exception) + { + return null; + } + } + + public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) + { + return null; + } + } +} \ No newline at end of file diff --git a/Correlator/App.xaml.cs b/Correlator/App.xaml.cs index 5c9dd37..c66d198 100644 --- a/Correlator/App.xaml.cs +++ b/Correlator/App.xaml.cs @@ -98,6 +98,7 @@ containerRegistry.RegisterSingleton(); containerRegistry.RegisterSingleton(); containerRegistry.RegisterSingleton(); + containerRegistry.RegisterSingleton(); //Dialog or Window containerRegistry.RegisterDialog(); @@ -105,6 +106,8 @@ containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); + containerRegistry.RegisterDialog(); + containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); diff --git a/Correlator/Converter/SoundParamValueConverter.cs b/Correlator/Converter/SoundParamValueConverter.cs new file mode 100644 index 0000000..4101a19 --- /dev/null +++ b/Correlator/Converter/SoundParamValueConverter.cs @@ -0,0 +1,26 @@ +using System; +using System.Globalization; +using System.Windows.Data; + +namespace Correlator.Converter +{ + public class SoundParamValueConverter : IMultiValueConverter + { + public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) + { + try + { + return "声速:" + values[0] + "m/s,采样率:" + values[1] + "Hz"; + } + catch (Exception) + { + return null; + } + } + + public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) + { + return null; + } + } +} \ No newline at end of file diff --git a/Correlator/Converter/WorkModeConverter.cs b/Correlator/Converter/WorkModeConverter.cs new file mode 100644 index 0000000..19d0327 --- /dev/null +++ b/Correlator/Converter/WorkModeConverter.cs @@ -0,0 +1,21 @@ +using System; +using System.Diagnostics; +using System.Globalization; +using System.Windows.Data; + +namespace Correlator.Converter +{ + internal class WorkModeConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + Debug.Assert(value != null, nameof(value) + " != null"); + return (int)value == 1 ? "加速度计" : "水听器"; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + return null; + } + } +} \ No newline at end of file diff --git a/Correlator/App.xaml.cs b/Correlator/App.xaml.cs index 5c9dd37..c66d198 100644 --- a/Correlator/App.xaml.cs +++ b/Correlator/App.xaml.cs @@ -98,6 +98,7 @@ containerRegistry.RegisterSingleton(); containerRegistry.RegisterSingleton(); containerRegistry.RegisterSingleton(); + containerRegistry.RegisterSingleton(); //Dialog or Window containerRegistry.RegisterDialog(); @@ -105,6 +106,8 @@ containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); + containerRegistry.RegisterDialog(); + containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); diff --git a/Correlator/Converter/SoundParamValueConverter.cs b/Correlator/Converter/SoundParamValueConverter.cs new file mode 100644 index 0000000..4101a19 --- /dev/null +++ b/Correlator/Converter/SoundParamValueConverter.cs @@ -0,0 +1,26 @@ +using System; +using System.Globalization; +using System.Windows.Data; + +namespace Correlator.Converter +{ + public class SoundParamValueConverter : IMultiValueConverter + { + public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) + { + try + { + return "声速:" + values[0] + "m/s,采样率:" + values[1] + "Hz"; + } + catch (Exception) + { + return null; + } + } + + public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) + { + return null; + } + } +} \ No newline at end of file diff --git a/Correlator/Converter/WorkModeConverter.cs b/Correlator/Converter/WorkModeConverter.cs new file mode 100644 index 0000000..19d0327 --- /dev/null +++ b/Correlator/Converter/WorkModeConverter.cs @@ -0,0 +1,21 @@ +using System; +using System.Diagnostics; +using System.Globalization; +using System.Windows.Data; + +namespace Correlator.Converter +{ + internal class WorkModeConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + Debug.Assert(value != null, nameof(value) + " != null"); + return (int)value == 1 ? "加速度计" : "水听器"; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + return null; + } + } +} \ No newline at end of file diff --git a/Correlator/Correlator.csproj b/Correlator/Correlator.csproj index da299ba..c3a433a 100644 --- a/Correlator/Correlator.csproj +++ b/Correlator/Correlator.csproj @@ -216,10 +216,14 @@ + + + + @@ -240,6 +244,9 @@ DetectNoiseDialog.xaml + + EditSoundSampleRateDialog.xaml + EditSoundSpeedDialog.xaml @@ -249,7 +256,14 @@ LoadingDialog.xaml + + SoundSampleRateDialog.xaml + + + + + ApplicationLogView.xaml @@ -303,7 +317,6 @@ - @@ -343,12 +356,14 @@ MSBuild:Compile + Designer MSBuild:Compile + Designer diff --git a/Correlator/App.xaml.cs b/Correlator/App.xaml.cs index 5c9dd37..c66d198 100644 --- a/Correlator/App.xaml.cs +++ b/Correlator/App.xaml.cs @@ -98,6 +98,7 @@ containerRegistry.RegisterSingleton(); containerRegistry.RegisterSingleton(); containerRegistry.RegisterSingleton(); + containerRegistry.RegisterSingleton(); //Dialog or Window containerRegistry.RegisterDialog(); @@ -105,6 +106,8 @@ containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); + containerRegistry.RegisterDialog(); + containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); diff --git a/Correlator/Converter/SoundParamValueConverter.cs b/Correlator/Converter/SoundParamValueConverter.cs new file mode 100644 index 0000000..4101a19 --- /dev/null +++ b/Correlator/Converter/SoundParamValueConverter.cs @@ -0,0 +1,26 @@ +using System; +using System.Globalization; +using System.Windows.Data; + +namespace Correlator.Converter +{ + public class SoundParamValueConverter : IMultiValueConverter + { + public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) + { + try + { + return "声速:" + values[0] + "m/s,采样率:" + values[1] + "Hz"; + } + catch (Exception) + { + return null; + } + } + + public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) + { + return null; + } + } +} \ No newline at end of file diff --git a/Correlator/Converter/WorkModeConverter.cs b/Correlator/Converter/WorkModeConverter.cs new file mode 100644 index 0000000..19d0327 --- /dev/null +++ b/Correlator/Converter/WorkModeConverter.cs @@ -0,0 +1,21 @@ +using System; +using System.Diagnostics; +using System.Globalization; +using System.Windows.Data; + +namespace Correlator.Converter +{ + internal class WorkModeConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + Debug.Assert(value != null, nameof(value) + " != null"); + return (int)value == 1 ? "加速度计" : "水听器"; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + return null; + } + } +} \ No newline at end of file diff --git a/Correlator/Correlator.csproj b/Correlator/Correlator.csproj index da299ba..c3a433a 100644 --- a/Correlator/Correlator.csproj +++ b/Correlator/Correlator.csproj @@ -216,10 +216,14 @@ + + + + @@ -240,6 +244,9 @@ DetectNoiseDialog.xaml + + EditSoundSampleRateDialog.xaml + EditSoundSpeedDialog.xaml @@ -249,7 +256,14 @@ LoadingDialog.xaml + + SoundSampleRateDialog.xaml + + + + + ApplicationLogView.xaml @@ -303,7 +317,6 @@ - @@ -343,12 +356,14 @@ MSBuild:Compile + Designer MSBuild:Compile + Designer diff --git a/Correlator/DataService/ApplicationDataServiceImpl.cs b/Correlator/DataService/ApplicationDataServiceImpl.cs index d3f9463..d7f0b68 100644 --- a/Correlator/DataService/ApplicationDataServiceImpl.cs +++ b/Correlator/DataService/ApplicationDataServiceImpl.cs @@ -104,7 +104,7 @@ { return new AudioVisualizer(waveDataSize); } - + public Color[] GetAllHsvColors() { var result = new Color[256 * 6]; @@ -141,5 +141,50 @@ return result; } + + public ObservableCollection GetSampleRate() + { + var sampleRateCollection = new ObservableCollection(); + using (var manager = new DataBaseManager()) + { + var result = manager + .Table() + .ToList(); + foreach (var model in result) + { + sampleRateCollection.Add(model); + } + } + + return sampleRateCollection; + } + + public int GetSampleRateByWorkMode(int mode) + { + using (var manager = new DataBaseManager()) + { + var result = manager + .Table() + .First(x => x.WorkMode == mode); + return result?.SampleRate ?? 7500; + } + } + + public void UpdateSampleRate(int mode, int sampleRate) + { + using (var manager = new DataBaseManager()) + { + var result = manager + .Table() + .First(x => x.WorkMode == mode); + var rateModel = result ?? new SampleRateModel(); + + rateModel.WorkMode = mode; + rateModel.SampleRate = sampleRate; + rateModel.UpdateDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); + + manager.Update(rateModel); + } + } } } \ No newline at end of file diff --git a/Correlator/App.xaml.cs b/Correlator/App.xaml.cs index 5c9dd37..c66d198 100644 --- a/Correlator/App.xaml.cs +++ b/Correlator/App.xaml.cs @@ -98,6 +98,7 @@ containerRegistry.RegisterSingleton(); containerRegistry.RegisterSingleton(); containerRegistry.RegisterSingleton(); + containerRegistry.RegisterSingleton(); //Dialog or Window containerRegistry.RegisterDialog(); @@ -105,6 +106,8 @@ containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); + containerRegistry.RegisterDialog(); + containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); diff --git a/Correlator/Converter/SoundParamValueConverter.cs b/Correlator/Converter/SoundParamValueConverter.cs new file mode 100644 index 0000000..4101a19 --- /dev/null +++ b/Correlator/Converter/SoundParamValueConverter.cs @@ -0,0 +1,26 @@ +using System; +using System.Globalization; +using System.Windows.Data; + +namespace Correlator.Converter +{ + public class SoundParamValueConverter : IMultiValueConverter + { + public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) + { + try + { + return "声速:" + values[0] + "m/s,采样率:" + values[1] + "Hz"; + } + catch (Exception) + { + return null; + } + } + + public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) + { + return null; + } + } +} \ No newline at end of file diff --git a/Correlator/Converter/WorkModeConverter.cs b/Correlator/Converter/WorkModeConverter.cs new file mode 100644 index 0000000..19d0327 --- /dev/null +++ b/Correlator/Converter/WorkModeConverter.cs @@ -0,0 +1,21 @@ +using System; +using System.Diagnostics; +using System.Globalization; +using System.Windows.Data; + +namespace Correlator.Converter +{ + internal class WorkModeConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + Debug.Assert(value != null, nameof(value) + " != null"); + return (int)value == 1 ? "加速度计" : "水听器"; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + return null; + } + } +} \ No newline at end of file diff --git a/Correlator/Correlator.csproj b/Correlator/Correlator.csproj index da299ba..c3a433a 100644 --- a/Correlator/Correlator.csproj +++ b/Correlator/Correlator.csproj @@ -216,10 +216,14 @@ + + + + @@ -240,6 +244,9 @@ DetectNoiseDialog.xaml + + EditSoundSampleRateDialog.xaml + EditSoundSpeedDialog.xaml @@ -249,7 +256,14 @@ LoadingDialog.xaml + + SoundSampleRateDialog.xaml + + + + + ApplicationLogView.xaml @@ -303,7 +317,6 @@ - @@ -343,12 +356,14 @@ MSBuild:Compile + Designer MSBuild:Compile + Designer diff --git a/Correlator/DataService/ApplicationDataServiceImpl.cs b/Correlator/DataService/ApplicationDataServiceImpl.cs index d3f9463..d7f0b68 100644 --- a/Correlator/DataService/ApplicationDataServiceImpl.cs +++ b/Correlator/DataService/ApplicationDataServiceImpl.cs @@ -104,7 +104,7 @@ { return new AudioVisualizer(waveDataSize); } - + public Color[] GetAllHsvColors() { var result = new Color[256 * 6]; @@ -141,5 +141,50 @@ return result; } + + public ObservableCollection GetSampleRate() + { + var sampleRateCollection = new ObservableCollection(); + using (var manager = new DataBaseManager()) + { + var result = manager + .Table() + .ToList(); + foreach (var model in result) + { + sampleRateCollection.Add(model); + } + } + + return sampleRateCollection; + } + + public int GetSampleRateByWorkMode(int mode) + { + using (var manager = new DataBaseManager()) + { + var result = manager + .Table() + .First(x => x.WorkMode == mode); + return result?.SampleRate ?? 7500; + } + } + + public void UpdateSampleRate(int mode, int sampleRate) + { + using (var manager = new DataBaseManager()) + { + var result = manager + .Table() + .First(x => x.WorkMode == mode); + var rateModel = result ?? new SampleRateModel(); + + rateModel.WorkMode = mode; + rateModel.SampleRate = sampleRate; + rateModel.UpdateDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); + + manager.Update(rateModel); + } + } } } \ No newline at end of file diff --git a/Correlator/DataService/AudioServiceImpl.cs b/Correlator/DataService/AudioServiceImpl.cs index fd3375f..c9ccb46 100644 --- a/Correlator/DataService/AudioServiceImpl.cs +++ b/Correlator/DataService/AudioServiceImpl.cs @@ -9,16 +9,17 @@ public class AudioServiceImpl : IAudioService { private bool _isStopped; + private WaveFormat _waveFormat; private WaveFileWriter _waveFileWriter; private BufferedWaveProvider _waveProvider; - private readonly WaveFormat _waveFormat = new WaveFormat(7500, 24, 1); public WaveOutEvent Wave { get; set; } = new WaveOutEvent(); - public void Start(string deviceCode) + public void Start(string deviceCode, int sampleRate) { _isStopped = false; + _waveFormat = new WaveFormat(sampleRate, 24, 1); _waveProvider = new BufferedWaveProvider(_waveFormat); Wave.Init(_waveProvider); diff --git a/Correlator/App.xaml.cs b/Correlator/App.xaml.cs index 5c9dd37..c66d198 100644 --- a/Correlator/App.xaml.cs +++ b/Correlator/App.xaml.cs @@ -98,6 +98,7 @@ containerRegistry.RegisterSingleton(); containerRegistry.RegisterSingleton(); containerRegistry.RegisterSingleton(); + containerRegistry.RegisterSingleton(); //Dialog or Window containerRegistry.RegisterDialog(); @@ -105,6 +106,8 @@ containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); + containerRegistry.RegisterDialog(); + containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); diff --git a/Correlator/Converter/SoundParamValueConverter.cs b/Correlator/Converter/SoundParamValueConverter.cs new file mode 100644 index 0000000..4101a19 --- /dev/null +++ b/Correlator/Converter/SoundParamValueConverter.cs @@ -0,0 +1,26 @@ +using System; +using System.Globalization; +using System.Windows.Data; + +namespace Correlator.Converter +{ + public class SoundParamValueConverter : IMultiValueConverter + { + public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) + { + try + { + return "声速:" + values[0] + "m/s,采样率:" + values[1] + "Hz"; + } + catch (Exception) + { + return null; + } + } + + public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) + { + return null; + } + } +} \ No newline at end of file diff --git a/Correlator/Converter/WorkModeConverter.cs b/Correlator/Converter/WorkModeConverter.cs new file mode 100644 index 0000000..19d0327 --- /dev/null +++ b/Correlator/Converter/WorkModeConverter.cs @@ -0,0 +1,21 @@ +using System; +using System.Diagnostics; +using System.Globalization; +using System.Windows.Data; + +namespace Correlator.Converter +{ + internal class WorkModeConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + Debug.Assert(value != null, nameof(value) + " != null"); + return (int)value == 1 ? "加速度计" : "水听器"; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + return null; + } + } +} \ No newline at end of file diff --git a/Correlator/Correlator.csproj b/Correlator/Correlator.csproj index da299ba..c3a433a 100644 --- a/Correlator/Correlator.csproj +++ b/Correlator/Correlator.csproj @@ -216,10 +216,14 @@ + + + + @@ -240,6 +244,9 @@ DetectNoiseDialog.xaml + + EditSoundSampleRateDialog.xaml + EditSoundSpeedDialog.xaml @@ -249,7 +256,14 @@ LoadingDialog.xaml + + SoundSampleRateDialog.xaml + + + + + ApplicationLogView.xaml @@ -303,7 +317,6 @@ - @@ -343,12 +356,14 @@ MSBuild:Compile + Designer MSBuild:Compile + Designer diff --git a/Correlator/DataService/ApplicationDataServiceImpl.cs b/Correlator/DataService/ApplicationDataServiceImpl.cs index d3f9463..d7f0b68 100644 --- a/Correlator/DataService/ApplicationDataServiceImpl.cs +++ b/Correlator/DataService/ApplicationDataServiceImpl.cs @@ -104,7 +104,7 @@ { return new AudioVisualizer(waveDataSize); } - + public Color[] GetAllHsvColors() { var result = new Color[256 * 6]; @@ -141,5 +141,50 @@ return result; } + + public ObservableCollection GetSampleRate() + { + var sampleRateCollection = new ObservableCollection(); + using (var manager = new DataBaseManager()) + { + var result = manager + .Table() + .ToList(); + foreach (var model in result) + { + sampleRateCollection.Add(model); + } + } + + return sampleRateCollection; + } + + public int GetSampleRateByWorkMode(int mode) + { + using (var manager = new DataBaseManager()) + { + var result = manager + .Table() + .First(x => x.WorkMode == mode); + return result?.SampleRate ?? 7500; + } + } + + public void UpdateSampleRate(int mode, int sampleRate) + { + using (var manager = new DataBaseManager()) + { + var result = manager + .Table() + .First(x => x.WorkMode == mode); + var rateModel = result ?? new SampleRateModel(); + + rateModel.WorkMode = mode; + rateModel.SampleRate = sampleRate; + rateModel.UpdateDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); + + manager.Update(rateModel); + } + } } } \ No newline at end of file diff --git a/Correlator/DataService/AudioServiceImpl.cs b/Correlator/DataService/AudioServiceImpl.cs index fd3375f..c9ccb46 100644 --- a/Correlator/DataService/AudioServiceImpl.cs +++ b/Correlator/DataService/AudioServiceImpl.cs @@ -9,16 +9,17 @@ public class AudioServiceImpl : IAudioService { private bool _isStopped; + private WaveFormat _waveFormat; private WaveFileWriter _waveFileWriter; private BufferedWaveProvider _waveProvider; - private readonly WaveFormat _waveFormat = new WaveFormat(7500, 24, 1); public WaveOutEvent Wave { get; set; } = new WaveOutEvent(); - public void Start(string deviceCode) + public void Start(string deviceCode, int sampleRate) { _isStopped = false; + _waveFormat = new WaveFormat(sampleRate, 24, 1); _waveProvider = new BufferedWaveProvider(_waveFormat); Wave.Init(_waveProvider); diff --git a/Correlator/DataService/CommandServiceImpl.cs b/Correlator/DataService/CommandServiceImpl.cs new file mode 100644 index 0000000..28e3402 --- /dev/null +++ b/Correlator/DataService/CommandServiceImpl.cs @@ -0,0 +1,614 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO.Ports; +using Correlator.Model; +using Correlator.Util; + +namespace Correlator.DataService +{ + public class CommandServiceImpl : ICommandService + { + public void SendCorrelatorWakeUpCmd(SerialPort sp) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + byte[] btDevId = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //广播模式,设备类型不解析 + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + const short pduTypeByte = 2; + var operateType = (short)(pduTypeByte & 0x7F); + + var pdu = (short)(2688 + operateType); //0X0A80 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oid = { 0x30, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00 }; + + byte[] totalLen = { 0x00, 0x13 }; + + //wrap the whole data + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + oid.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oid.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发加速度计数据采集指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendHydrophoneWakeUpCmd(SerialPort sp) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + //后续到CRC字段前的字节总长度(不包括长度字段和CRC字段)。 + byte[] totalLen = { 0x00, 0x1F }; + + byte[] btDevId = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //广播模式,设备类型不解析 + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 2688 + operateType; //0X0A80 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oidTag = + { + 0x40, 0x00, 0x00, 0x01, + 0x00, 0x01, + 0x00 + }; + + //获取时间(年-月-日-时-分-秒),年号-2000 + RuntimeCache.HydrophoneWakeUpTimestamp = new[] + { + CalendarHub.Year, CalendarHub.Mon, CalendarHub.Day, CalendarHub.Hor, CalendarHub.Min, + CalendarHub.Sec + }; + byte[] timeTag = + { + 0x10, 0x00, 0x00, 0x51, + 0x00, 0x06, + RuntimeCache.HydrophoneWakeUpTimestamp[0], RuntimeCache.HydrophoneWakeUpTimestamp[1], + RuntimeCache.HydrophoneWakeUpTimestamp[2], RuntimeCache.HydrophoneWakeUpTimestamp[3], + RuntimeCache.HydrophoneWakeUpTimestamp[4], RuntimeCache.HydrophoneWakeUpTimestamp[5] + }; //时间oid + + //wrap the whole data + var result = new byte[35]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oidTag.CopyTo(result, 16); + timeTag.CopyTo(result, 23); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发水听器数据采集指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void StartCheckResponse(SerialPort sp, string devCode) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + //后续到CRC字段前的字节总长度(不包括长度字段和CRC字段)。 + byte[] totalLen = { 0x00, 0x1F }; + + var btDevId = new byte[6]; + btDevId[0] = byte.Parse(devCode.Substring(0, 2), NumberStyles.HexNumber); + btDevId[1] = byte.Parse(devCode.Substring(2, 2), NumberStyles.HexNumber); + btDevId[2] = byte.Parse(devCode.Substring(4, 2), NumberStyles.HexNumber); + btDevId[3] = byte.Parse(devCode.Substring(6, 2), NumberStyles.HexNumber); + btDevId[4] = byte.Parse(devCode.Substring(8, 2), NumberStyles.HexNumber); + btDevId[5] = byte.Parse(devCode.Substring(10, 2), NumberStyles.HexNumber); + + //通信方式 + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + byte[] btPdu = { 0x01, 0x82 }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oidTag = + { + 0x40, 0x00, 0x00, 0x02, + 0x00, 0x01, + 0x00 + }; + + byte[] timeTag = + { + 0x10, 0x00, 0x00, 0x51, + 0x00, 0x06, + RuntimeCache.HydrophoneWakeUpTimestamp[0], RuntimeCache.HydrophoneWakeUpTimestamp[1], + RuntimeCache.HydrophoneWakeUpTimestamp[2], RuntimeCache.HydrophoneWakeUpTimestamp[3], + RuntimeCache.HydrophoneWakeUpTimestamp[4], RuntimeCache.HydrophoneWakeUpTimestamp[5] + }; //时间oid + + //wrap the whole data + var result = new byte[35]; + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oidTag.CopyTo(result, 16); + timeTag.CopyTo(result, 23); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发水听器点名指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendDataCheckResultCmd(SerialPort sp, string devCode, List indexArray) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + //后续到CRC字段前的字节总长度(不包括长度字段和CRC字段)。 + byte[] totalLen = { 0x00, 0x26 }; + + var btDevId = new byte[6]; + btDevId[0] = byte.Parse(devCode.Substring(0, 2), NumberStyles.HexNumber); + btDevId[1] = byte.Parse(devCode.Substring(2, 2), NumberStyles.HexNumber); + btDevId[2] = byte.Parse(devCode.Substring(4, 2), NumberStyles.HexNumber); + btDevId[3] = byte.Parse(devCode.Substring(6, 2), NumberStyles.HexNumber); + btDevId[4] = byte.Parse(devCode.Substring(8, 2), NumberStyles.HexNumber); + btDevId[5] = byte.Parse(devCode.Substring(10, 2), NumberStyles.HexNumber); + + //通信方式 + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + byte[] btPdu = { 0x05, 0x82 }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + //check result tag + var byteArray = indexArray.ToByteArray(); + byte[] oidTag = + { + 0x60, 0x00, 0x03, 0x00, + 0x00, 0x08, + byteArray[0], byteArray[1], byteArray[2], byteArray[3], + byteArray[4], byteArray[5], byteArray[6], byteArray[7] + }; + + byte[] timeTag = + { + 0x10, 0x00, 0x00, 0x51, + 0x00, 0x06, + RuntimeCache.HydrophoneWakeUpTimestamp[0], RuntimeCache.HydrophoneWakeUpTimestamp[1], + RuntimeCache.HydrophoneWakeUpTimestamp[2], RuntimeCache.HydrophoneWakeUpTimestamp[3], + RuntimeCache.HydrophoneWakeUpTimestamp[4], RuntimeCache.HydrophoneWakeUpTimestamp[5] + }; //时间oid + + //wrap the whole data + var result = new byte[42]; + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oidTag.CopyTo(result, 16); + timeTag.CopyTo(result, 30); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发水听器检查指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendCellAndStatusCollectCmd(SerialPort sp, byte devId) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + byte[] btDevId = { 0x21, 0x17, 0x00, 0x08, 0x22, devId }; //广播模式,设备类型不解析 + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0x22, devId }; + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 2688 + operateType; //0X0A80 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oid = { 0x60, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00 }; + + byte[] totalLen = { 0x00, 0x13 }; + + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + oid.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oid.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "设备 " + devId + " 下发状态采集指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendSoundCollectCmd(SerialPort sp, string devCode) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + //byte[] btDevId = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //广播模式,设备类型不解析 + var btDevId = new byte[6]; + btDevId[0] = byte.Parse(devCode.Substring(0, 2), NumberStyles.HexNumber); + btDevId[1] = byte.Parse(devCode.Substring(2, 2), NumberStyles.HexNumber); + btDevId[2] = byte.Parse(devCode.Substring(4, 2), NumberStyles.HexNumber); + btDevId[3] = byte.Parse(devCode.Substring(6, 2), NumberStyles.HexNumber); + btDevId[4] = byte.Parse(devCode.Substring(8, 2), NumberStyles.HexNumber); + btDevId[5] = byte.Parse(devCode.Substring(10, 2), NumberStyles.HexNumber); + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + var dstNodeAddr = devCode.Substring(8); //2个字节 ** ****** **** + var btDstNode = new byte[2]; + btDstNode[0] = byte.Parse(dstNodeAddr.Substring(0, 2), NumberStyles.HexNumber); + btDstNode[1] = byte.Parse(dstNodeAddr.Substring(2, 2), NumberStyles.HexNumber); + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 2688 + operateType; + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + //第一个Tag的Oid为“0x30000001”,第二个Tag为时间戳,Oid为“0x10000051”,内容为“年、月、日、时、分、秒” + byte[] oid = { 0x20, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00 }; //Tag1 + + byte[] totalLen = { 0x00, 0x13 }; + + //wrap the whole data + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + oid.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oid.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发听音指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendSoundStopCmd(SerialPort sp, string devCode) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + var btDevId = new byte[6]; + btDevId[0] = byte.Parse(devCode.Substring(0, 2), NumberStyles.HexNumber); + btDevId[1] = byte.Parse(devCode.Substring(2, 2), NumberStyles.HexNumber); + btDevId[2] = byte.Parse(devCode.Substring(4, 2), NumberStyles.HexNumber); + btDevId[3] = byte.Parse(devCode.Substring(6, 2), NumberStyles.HexNumber); + btDevId[4] = byte.Parse(devCode.Substring(8, 2), NumberStyles.HexNumber); + btDevId[5] = byte.Parse(devCode.Substring(10, 2), NumberStyles.HexNumber); + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + var dstNodeAddr = devCode.Substring(8); //2个字节 ** ****** **** + var btDstNode = new byte[2]; + btDstNode[0] = byte.Parse(dstNodeAddr.Substring(0, 2), NumberStyles.HexNumber); + btDstNode[1] = byte.Parse(dstNodeAddr.Substring(2, 2), NumberStyles.HexNumber); + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 1408 + operateType; //0x0582 TrapResponse+z噪声记录仪 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] sysTag = + { + 0x10, 0x00, 0x00, 0x51, 0x00, 0x06, + CalendarHub.Year, CalendarHub.Mon, CalendarHub.Day, CalendarHub.Hor, CalendarHub.Min, + CalendarHub.Sec + }; //Tag2 + + byte[] totalLen = { 0x00, 0x18 }; + + //wrap the whole data + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + sysTag.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + sysTag.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发听音结束指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendCorrelatorRangingCmd(SerialPort sp) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + byte[] btDevId = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //广播模式,设备类型不解析 + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 2688 + operateType; //0X0A80 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oid = { 0x30, 0x00, 0x00, 0x01, 0x00, 0x01, 0x99 }; + + byte[] totalLen = { 0x00, 0x13 }; + + //wrap the whole data + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + oid.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oid.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发相关仪测距指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + private CommandModel _lastCommand; + + public CommandModel GetLastCommand() + { + return _lastCommand; + } + } +} \ No newline at end of file diff --git a/Correlator/App.xaml.cs b/Correlator/App.xaml.cs index 5c9dd37..c66d198 100644 --- a/Correlator/App.xaml.cs +++ b/Correlator/App.xaml.cs @@ -98,6 +98,7 @@ containerRegistry.RegisterSingleton(); containerRegistry.RegisterSingleton(); containerRegistry.RegisterSingleton(); + containerRegistry.RegisterSingleton(); //Dialog or Window containerRegistry.RegisterDialog(); @@ -105,6 +106,8 @@ containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); + containerRegistry.RegisterDialog(); + containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); diff --git a/Correlator/Converter/SoundParamValueConverter.cs b/Correlator/Converter/SoundParamValueConverter.cs new file mode 100644 index 0000000..4101a19 --- /dev/null +++ b/Correlator/Converter/SoundParamValueConverter.cs @@ -0,0 +1,26 @@ +using System; +using System.Globalization; +using System.Windows.Data; + +namespace Correlator.Converter +{ + public class SoundParamValueConverter : IMultiValueConverter + { + public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) + { + try + { + return "声速:" + values[0] + "m/s,采样率:" + values[1] + "Hz"; + } + catch (Exception) + { + return null; + } + } + + public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) + { + return null; + } + } +} \ No newline at end of file diff --git a/Correlator/Converter/WorkModeConverter.cs b/Correlator/Converter/WorkModeConverter.cs new file mode 100644 index 0000000..19d0327 --- /dev/null +++ b/Correlator/Converter/WorkModeConverter.cs @@ -0,0 +1,21 @@ +using System; +using System.Diagnostics; +using System.Globalization; +using System.Windows.Data; + +namespace Correlator.Converter +{ + internal class WorkModeConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + Debug.Assert(value != null, nameof(value) + " != null"); + return (int)value == 1 ? "加速度计" : "水听器"; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + return null; + } + } +} \ No newline at end of file diff --git a/Correlator/Correlator.csproj b/Correlator/Correlator.csproj index da299ba..c3a433a 100644 --- a/Correlator/Correlator.csproj +++ b/Correlator/Correlator.csproj @@ -216,10 +216,14 @@ + + + + @@ -240,6 +244,9 @@ DetectNoiseDialog.xaml + + EditSoundSampleRateDialog.xaml + EditSoundSpeedDialog.xaml @@ -249,7 +256,14 @@ LoadingDialog.xaml + + SoundSampleRateDialog.xaml + + + + + ApplicationLogView.xaml @@ -303,7 +317,6 @@ - @@ -343,12 +356,14 @@ MSBuild:Compile + Designer MSBuild:Compile + Designer diff --git a/Correlator/DataService/ApplicationDataServiceImpl.cs b/Correlator/DataService/ApplicationDataServiceImpl.cs index d3f9463..d7f0b68 100644 --- a/Correlator/DataService/ApplicationDataServiceImpl.cs +++ b/Correlator/DataService/ApplicationDataServiceImpl.cs @@ -104,7 +104,7 @@ { return new AudioVisualizer(waveDataSize); } - + public Color[] GetAllHsvColors() { var result = new Color[256 * 6]; @@ -141,5 +141,50 @@ return result; } + + public ObservableCollection GetSampleRate() + { + var sampleRateCollection = new ObservableCollection(); + using (var manager = new DataBaseManager()) + { + var result = manager + .Table() + .ToList(); + foreach (var model in result) + { + sampleRateCollection.Add(model); + } + } + + return sampleRateCollection; + } + + public int GetSampleRateByWorkMode(int mode) + { + using (var manager = new DataBaseManager()) + { + var result = manager + .Table() + .First(x => x.WorkMode == mode); + return result?.SampleRate ?? 7500; + } + } + + public void UpdateSampleRate(int mode, int sampleRate) + { + using (var manager = new DataBaseManager()) + { + var result = manager + .Table() + .First(x => x.WorkMode == mode); + var rateModel = result ?? new SampleRateModel(); + + rateModel.WorkMode = mode; + rateModel.SampleRate = sampleRate; + rateModel.UpdateDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); + + manager.Update(rateModel); + } + } } } \ No newline at end of file diff --git a/Correlator/DataService/AudioServiceImpl.cs b/Correlator/DataService/AudioServiceImpl.cs index fd3375f..c9ccb46 100644 --- a/Correlator/DataService/AudioServiceImpl.cs +++ b/Correlator/DataService/AudioServiceImpl.cs @@ -9,16 +9,17 @@ public class AudioServiceImpl : IAudioService { private bool _isStopped; + private WaveFormat _waveFormat; private WaveFileWriter _waveFileWriter; private BufferedWaveProvider _waveProvider; - private readonly WaveFormat _waveFormat = new WaveFormat(7500, 24, 1); public WaveOutEvent Wave { get; set; } = new WaveOutEvent(); - public void Start(string deviceCode) + public void Start(string deviceCode, int sampleRate) { _isStopped = false; + _waveFormat = new WaveFormat(sampleRate, 24, 1); _waveProvider = new BufferedWaveProvider(_waveFormat); Wave.Init(_waveProvider); diff --git a/Correlator/DataService/CommandServiceImpl.cs b/Correlator/DataService/CommandServiceImpl.cs new file mode 100644 index 0000000..28e3402 --- /dev/null +++ b/Correlator/DataService/CommandServiceImpl.cs @@ -0,0 +1,614 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO.Ports; +using Correlator.Model; +using Correlator.Util; + +namespace Correlator.DataService +{ + public class CommandServiceImpl : ICommandService + { + public void SendCorrelatorWakeUpCmd(SerialPort sp) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + byte[] btDevId = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //广播模式,设备类型不解析 + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + const short pduTypeByte = 2; + var operateType = (short)(pduTypeByte & 0x7F); + + var pdu = (short)(2688 + operateType); //0X0A80 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oid = { 0x30, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00 }; + + byte[] totalLen = { 0x00, 0x13 }; + + //wrap the whole data + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + oid.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oid.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发加速度计数据采集指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendHydrophoneWakeUpCmd(SerialPort sp) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + //后续到CRC字段前的字节总长度(不包括长度字段和CRC字段)。 + byte[] totalLen = { 0x00, 0x1F }; + + byte[] btDevId = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //广播模式,设备类型不解析 + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 2688 + operateType; //0X0A80 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oidTag = + { + 0x40, 0x00, 0x00, 0x01, + 0x00, 0x01, + 0x00 + }; + + //获取时间(年-月-日-时-分-秒),年号-2000 + RuntimeCache.HydrophoneWakeUpTimestamp = new[] + { + CalendarHub.Year, CalendarHub.Mon, CalendarHub.Day, CalendarHub.Hor, CalendarHub.Min, + CalendarHub.Sec + }; + byte[] timeTag = + { + 0x10, 0x00, 0x00, 0x51, + 0x00, 0x06, + RuntimeCache.HydrophoneWakeUpTimestamp[0], RuntimeCache.HydrophoneWakeUpTimestamp[1], + RuntimeCache.HydrophoneWakeUpTimestamp[2], RuntimeCache.HydrophoneWakeUpTimestamp[3], + RuntimeCache.HydrophoneWakeUpTimestamp[4], RuntimeCache.HydrophoneWakeUpTimestamp[5] + }; //时间oid + + //wrap the whole data + var result = new byte[35]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oidTag.CopyTo(result, 16); + timeTag.CopyTo(result, 23); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发水听器数据采集指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void StartCheckResponse(SerialPort sp, string devCode) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + //后续到CRC字段前的字节总长度(不包括长度字段和CRC字段)。 + byte[] totalLen = { 0x00, 0x1F }; + + var btDevId = new byte[6]; + btDevId[0] = byte.Parse(devCode.Substring(0, 2), NumberStyles.HexNumber); + btDevId[1] = byte.Parse(devCode.Substring(2, 2), NumberStyles.HexNumber); + btDevId[2] = byte.Parse(devCode.Substring(4, 2), NumberStyles.HexNumber); + btDevId[3] = byte.Parse(devCode.Substring(6, 2), NumberStyles.HexNumber); + btDevId[4] = byte.Parse(devCode.Substring(8, 2), NumberStyles.HexNumber); + btDevId[5] = byte.Parse(devCode.Substring(10, 2), NumberStyles.HexNumber); + + //通信方式 + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + byte[] btPdu = { 0x01, 0x82 }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oidTag = + { + 0x40, 0x00, 0x00, 0x02, + 0x00, 0x01, + 0x00 + }; + + byte[] timeTag = + { + 0x10, 0x00, 0x00, 0x51, + 0x00, 0x06, + RuntimeCache.HydrophoneWakeUpTimestamp[0], RuntimeCache.HydrophoneWakeUpTimestamp[1], + RuntimeCache.HydrophoneWakeUpTimestamp[2], RuntimeCache.HydrophoneWakeUpTimestamp[3], + RuntimeCache.HydrophoneWakeUpTimestamp[4], RuntimeCache.HydrophoneWakeUpTimestamp[5] + }; //时间oid + + //wrap the whole data + var result = new byte[35]; + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oidTag.CopyTo(result, 16); + timeTag.CopyTo(result, 23); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发水听器点名指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendDataCheckResultCmd(SerialPort sp, string devCode, List indexArray) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + //后续到CRC字段前的字节总长度(不包括长度字段和CRC字段)。 + byte[] totalLen = { 0x00, 0x26 }; + + var btDevId = new byte[6]; + btDevId[0] = byte.Parse(devCode.Substring(0, 2), NumberStyles.HexNumber); + btDevId[1] = byte.Parse(devCode.Substring(2, 2), NumberStyles.HexNumber); + btDevId[2] = byte.Parse(devCode.Substring(4, 2), NumberStyles.HexNumber); + btDevId[3] = byte.Parse(devCode.Substring(6, 2), NumberStyles.HexNumber); + btDevId[4] = byte.Parse(devCode.Substring(8, 2), NumberStyles.HexNumber); + btDevId[5] = byte.Parse(devCode.Substring(10, 2), NumberStyles.HexNumber); + + //通信方式 + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + byte[] btPdu = { 0x05, 0x82 }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + //check result tag + var byteArray = indexArray.ToByteArray(); + byte[] oidTag = + { + 0x60, 0x00, 0x03, 0x00, + 0x00, 0x08, + byteArray[0], byteArray[1], byteArray[2], byteArray[3], + byteArray[4], byteArray[5], byteArray[6], byteArray[7] + }; + + byte[] timeTag = + { + 0x10, 0x00, 0x00, 0x51, + 0x00, 0x06, + RuntimeCache.HydrophoneWakeUpTimestamp[0], RuntimeCache.HydrophoneWakeUpTimestamp[1], + RuntimeCache.HydrophoneWakeUpTimestamp[2], RuntimeCache.HydrophoneWakeUpTimestamp[3], + RuntimeCache.HydrophoneWakeUpTimestamp[4], RuntimeCache.HydrophoneWakeUpTimestamp[5] + }; //时间oid + + //wrap the whole data + var result = new byte[42]; + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oidTag.CopyTo(result, 16); + timeTag.CopyTo(result, 30); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发水听器检查指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendCellAndStatusCollectCmd(SerialPort sp, byte devId) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + byte[] btDevId = { 0x21, 0x17, 0x00, 0x08, 0x22, devId }; //广播模式,设备类型不解析 + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0x22, devId }; + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 2688 + operateType; //0X0A80 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oid = { 0x60, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00 }; + + byte[] totalLen = { 0x00, 0x13 }; + + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + oid.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oid.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "设备 " + devId + " 下发状态采集指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendSoundCollectCmd(SerialPort sp, string devCode) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + //byte[] btDevId = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //广播模式,设备类型不解析 + var btDevId = new byte[6]; + btDevId[0] = byte.Parse(devCode.Substring(0, 2), NumberStyles.HexNumber); + btDevId[1] = byte.Parse(devCode.Substring(2, 2), NumberStyles.HexNumber); + btDevId[2] = byte.Parse(devCode.Substring(4, 2), NumberStyles.HexNumber); + btDevId[3] = byte.Parse(devCode.Substring(6, 2), NumberStyles.HexNumber); + btDevId[4] = byte.Parse(devCode.Substring(8, 2), NumberStyles.HexNumber); + btDevId[5] = byte.Parse(devCode.Substring(10, 2), NumberStyles.HexNumber); + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + var dstNodeAddr = devCode.Substring(8); //2个字节 ** ****** **** + var btDstNode = new byte[2]; + btDstNode[0] = byte.Parse(dstNodeAddr.Substring(0, 2), NumberStyles.HexNumber); + btDstNode[1] = byte.Parse(dstNodeAddr.Substring(2, 2), NumberStyles.HexNumber); + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 2688 + operateType; + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + //第一个Tag的Oid为“0x30000001”,第二个Tag为时间戳,Oid为“0x10000051”,内容为“年、月、日、时、分、秒” + byte[] oid = { 0x20, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00 }; //Tag1 + + byte[] totalLen = { 0x00, 0x13 }; + + //wrap the whole data + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + oid.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oid.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发听音指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendSoundStopCmd(SerialPort sp, string devCode) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + var btDevId = new byte[6]; + btDevId[0] = byte.Parse(devCode.Substring(0, 2), NumberStyles.HexNumber); + btDevId[1] = byte.Parse(devCode.Substring(2, 2), NumberStyles.HexNumber); + btDevId[2] = byte.Parse(devCode.Substring(4, 2), NumberStyles.HexNumber); + btDevId[3] = byte.Parse(devCode.Substring(6, 2), NumberStyles.HexNumber); + btDevId[4] = byte.Parse(devCode.Substring(8, 2), NumberStyles.HexNumber); + btDevId[5] = byte.Parse(devCode.Substring(10, 2), NumberStyles.HexNumber); + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + var dstNodeAddr = devCode.Substring(8); //2个字节 ** ****** **** + var btDstNode = new byte[2]; + btDstNode[0] = byte.Parse(dstNodeAddr.Substring(0, 2), NumberStyles.HexNumber); + btDstNode[1] = byte.Parse(dstNodeAddr.Substring(2, 2), NumberStyles.HexNumber); + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 1408 + operateType; //0x0582 TrapResponse+z噪声记录仪 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] sysTag = + { + 0x10, 0x00, 0x00, 0x51, 0x00, 0x06, + CalendarHub.Year, CalendarHub.Mon, CalendarHub.Day, CalendarHub.Hor, CalendarHub.Min, + CalendarHub.Sec + }; //Tag2 + + byte[] totalLen = { 0x00, 0x18 }; + + //wrap the whole data + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + sysTag.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + sysTag.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发听音结束指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendCorrelatorRangingCmd(SerialPort sp) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + byte[] btDevId = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //广播模式,设备类型不解析 + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 2688 + operateType; //0X0A80 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oid = { 0x30, 0x00, 0x00, 0x01, 0x00, 0x01, 0x99 }; + + byte[] totalLen = { 0x00, 0x13 }; + + //wrap the whole data + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + oid.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oid.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发相关仪测距指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + private CommandModel _lastCommand; + + public CommandModel GetLastCommand() + { + return _lastCommand; + } + } +} \ No newline at end of file diff --git a/Correlator/DataService/IApplicationDataService.cs b/Correlator/DataService/IApplicationDataService.cs index c2c29a7..f232681 100644 --- a/Correlator/DataService/IApplicationDataService.cs +++ b/Correlator/DataService/IApplicationDataService.cs @@ -8,7 +8,7 @@ public interface IApplicationDataService { ObservableCollection GetPipeMaterial(); - + ObservableCollection GetVelocityCollection(string materialName); void DeleteVelocity(MaterialVelocity velocity); @@ -26,11 +26,31 @@ int GetSoundVelocity(string material, int pipeDiameter); AudioVisualizer GetAudioVisualizer(int waveDataSize); - + /// /// 获取 HSV 中所有的基础颜色 (饱和度和明度均为最大值) /// /// 所有的 HSV 基础颜色(共 256 * 6 个, 并且随着索引增加, 颜色也会渐变) Color[] GetAllHsvColors(); + + /// + /// 加载所有工作模式的采样率 + /// + /// + ObservableCollection GetSampleRate(); + + /// + /// 根据工作模式获取采样率 + /// + /// + /// + int GetSampleRateByWorkMode(int mode); + + /// + /// 更新采样率 + /// + /// + /// + void UpdateSampleRate(int mode, int sampleRate); } } \ No newline at end of file diff --git a/Correlator/App.xaml.cs b/Correlator/App.xaml.cs index 5c9dd37..c66d198 100644 --- a/Correlator/App.xaml.cs +++ b/Correlator/App.xaml.cs @@ -98,6 +98,7 @@ containerRegistry.RegisterSingleton(); containerRegistry.RegisterSingleton(); containerRegistry.RegisterSingleton(); + containerRegistry.RegisterSingleton(); //Dialog or Window containerRegistry.RegisterDialog(); @@ -105,6 +106,8 @@ containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); + containerRegistry.RegisterDialog(); + containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); diff --git a/Correlator/Converter/SoundParamValueConverter.cs b/Correlator/Converter/SoundParamValueConverter.cs new file mode 100644 index 0000000..4101a19 --- /dev/null +++ b/Correlator/Converter/SoundParamValueConverter.cs @@ -0,0 +1,26 @@ +using System; +using System.Globalization; +using System.Windows.Data; + +namespace Correlator.Converter +{ + public class SoundParamValueConverter : IMultiValueConverter + { + public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) + { + try + { + return "声速:" + values[0] + "m/s,采样率:" + values[1] + "Hz"; + } + catch (Exception) + { + return null; + } + } + + public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) + { + return null; + } + } +} \ No newline at end of file diff --git a/Correlator/Converter/WorkModeConverter.cs b/Correlator/Converter/WorkModeConverter.cs new file mode 100644 index 0000000..19d0327 --- /dev/null +++ b/Correlator/Converter/WorkModeConverter.cs @@ -0,0 +1,21 @@ +using System; +using System.Diagnostics; +using System.Globalization; +using System.Windows.Data; + +namespace Correlator.Converter +{ + internal class WorkModeConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + Debug.Assert(value != null, nameof(value) + " != null"); + return (int)value == 1 ? "加速度计" : "水听器"; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + return null; + } + } +} \ No newline at end of file diff --git a/Correlator/Correlator.csproj b/Correlator/Correlator.csproj index da299ba..c3a433a 100644 --- a/Correlator/Correlator.csproj +++ b/Correlator/Correlator.csproj @@ -216,10 +216,14 @@ + + + + @@ -240,6 +244,9 @@ DetectNoiseDialog.xaml + + EditSoundSampleRateDialog.xaml + EditSoundSpeedDialog.xaml @@ -249,7 +256,14 @@ LoadingDialog.xaml + + SoundSampleRateDialog.xaml + + + + + ApplicationLogView.xaml @@ -303,7 +317,6 @@ - @@ -343,12 +356,14 @@ MSBuild:Compile + Designer MSBuild:Compile + Designer diff --git a/Correlator/DataService/ApplicationDataServiceImpl.cs b/Correlator/DataService/ApplicationDataServiceImpl.cs index d3f9463..d7f0b68 100644 --- a/Correlator/DataService/ApplicationDataServiceImpl.cs +++ b/Correlator/DataService/ApplicationDataServiceImpl.cs @@ -104,7 +104,7 @@ { return new AudioVisualizer(waveDataSize); } - + public Color[] GetAllHsvColors() { var result = new Color[256 * 6]; @@ -141,5 +141,50 @@ return result; } + + public ObservableCollection GetSampleRate() + { + var sampleRateCollection = new ObservableCollection(); + using (var manager = new DataBaseManager()) + { + var result = manager + .Table() + .ToList(); + foreach (var model in result) + { + sampleRateCollection.Add(model); + } + } + + return sampleRateCollection; + } + + public int GetSampleRateByWorkMode(int mode) + { + using (var manager = new DataBaseManager()) + { + var result = manager + .Table() + .First(x => x.WorkMode == mode); + return result?.SampleRate ?? 7500; + } + } + + public void UpdateSampleRate(int mode, int sampleRate) + { + using (var manager = new DataBaseManager()) + { + var result = manager + .Table() + .First(x => x.WorkMode == mode); + var rateModel = result ?? new SampleRateModel(); + + rateModel.WorkMode = mode; + rateModel.SampleRate = sampleRate; + rateModel.UpdateDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); + + manager.Update(rateModel); + } + } } } \ No newline at end of file diff --git a/Correlator/DataService/AudioServiceImpl.cs b/Correlator/DataService/AudioServiceImpl.cs index fd3375f..c9ccb46 100644 --- a/Correlator/DataService/AudioServiceImpl.cs +++ b/Correlator/DataService/AudioServiceImpl.cs @@ -9,16 +9,17 @@ public class AudioServiceImpl : IAudioService { private bool _isStopped; + private WaveFormat _waveFormat; private WaveFileWriter _waveFileWriter; private BufferedWaveProvider _waveProvider; - private readonly WaveFormat _waveFormat = new WaveFormat(7500, 24, 1); public WaveOutEvent Wave { get; set; } = new WaveOutEvent(); - public void Start(string deviceCode) + public void Start(string deviceCode, int sampleRate) { _isStopped = false; + _waveFormat = new WaveFormat(sampleRate, 24, 1); _waveProvider = new BufferedWaveProvider(_waveFormat); Wave.Init(_waveProvider); diff --git a/Correlator/DataService/CommandServiceImpl.cs b/Correlator/DataService/CommandServiceImpl.cs new file mode 100644 index 0000000..28e3402 --- /dev/null +++ b/Correlator/DataService/CommandServiceImpl.cs @@ -0,0 +1,614 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO.Ports; +using Correlator.Model; +using Correlator.Util; + +namespace Correlator.DataService +{ + public class CommandServiceImpl : ICommandService + { + public void SendCorrelatorWakeUpCmd(SerialPort sp) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + byte[] btDevId = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //广播模式,设备类型不解析 + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + const short pduTypeByte = 2; + var operateType = (short)(pduTypeByte & 0x7F); + + var pdu = (short)(2688 + operateType); //0X0A80 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oid = { 0x30, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00 }; + + byte[] totalLen = { 0x00, 0x13 }; + + //wrap the whole data + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + oid.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oid.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发加速度计数据采集指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendHydrophoneWakeUpCmd(SerialPort sp) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + //后续到CRC字段前的字节总长度(不包括长度字段和CRC字段)。 + byte[] totalLen = { 0x00, 0x1F }; + + byte[] btDevId = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //广播模式,设备类型不解析 + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 2688 + operateType; //0X0A80 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oidTag = + { + 0x40, 0x00, 0x00, 0x01, + 0x00, 0x01, + 0x00 + }; + + //获取时间(年-月-日-时-分-秒),年号-2000 + RuntimeCache.HydrophoneWakeUpTimestamp = new[] + { + CalendarHub.Year, CalendarHub.Mon, CalendarHub.Day, CalendarHub.Hor, CalendarHub.Min, + CalendarHub.Sec + }; + byte[] timeTag = + { + 0x10, 0x00, 0x00, 0x51, + 0x00, 0x06, + RuntimeCache.HydrophoneWakeUpTimestamp[0], RuntimeCache.HydrophoneWakeUpTimestamp[1], + RuntimeCache.HydrophoneWakeUpTimestamp[2], RuntimeCache.HydrophoneWakeUpTimestamp[3], + RuntimeCache.HydrophoneWakeUpTimestamp[4], RuntimeCache.HydrophoneWakeUpTimestamp[5] + }; //时间oid + + //wrap the whole data + var result = new byte[35]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oidTag.CopyTo(result, 16); + timeTag.CopyTo(result, 23); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发水听器数据采集指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void StartCheckResponse(SerialPort sp, string devCode) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + //后续到CRC字段前的字节总长度(不包括长度字段和CRC字段)。 + byte[] totalLen = { 0x00, 0x1F }; + + var btDevId = new byte[6]; + btDevId[0] = byte.Parse(devCode.Substring(0, 2), NumberStyles.HexNumber); + btDevId[1] = byte.Parse(devCode.Substring(2, 2), NumberStyles.HexNumber); + btDevId[2] = byte.Parse(devCode.Substring(4, 2), NumberStyles.HexNumber); + btDevId[3] = byte.Parse(devCode.Substring(6, 2), NumberStyles.HexNumber); + btDevId[4] = byte.Parse(devCode.Substring(8, 2), NumberStyles.HexNumber); + btDevId[5] = byte.Parse(devCode.Substring(10, 2), NumberStyles.HexNumber); + + //通信方式 + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + byte[] btPdu = { 0x01, 0x82 }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oidTag = + { + 0x40, 0x00, 0x00, 0x02, + 0x00, 0x01, + 0x00 + }; + + byte[] timeTag = + { + 0x10, 0x00, 0x00, 0x51, + 0x00, 0x06, + RuntimeCache.HydrophoneWakeUpTimestamp[0], RuntimeCache.HydrophoneWakeUpTimestamp[1], + RuntimeCache.HydrophoneWakeUpTimestamp[2], RuntimeCache.HydrophoneWakeUpTimestamp[3], + RuntimeCache.HydrophoneWakeUpTimestamp[4], RuntimeCache.HydrophoneWakeUpTimestamp[5] + }; //时间oid + + //wrap the whole data + var result = new byte[35]; + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oidTag.CopyTo(result, 16); + timeTag.CopyTo(result, 23); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发水听器点名指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendDataCheckResultCmd(SerialPort sp, string devCode, List indexArray) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + //后续到CRC字段前的字节总长度(不包括长度字段和CRC字段)。 + byte[] totalLen = { 0x00, 0x26 }; + + var btDevId = new byte[6]; + btDevId[0] = byte.Parse(devCode.Substring(0, 2), NumberStyles.HexNumber); + btDevId[1] = byte.Parse(devCode.Substring(2, 2), NumberStyles.HexNumber); + btDevId[2] = byte.Parse(devCode.Substring(4, 2), NumberStyles.HexNumber); + btDevId[3] = byte.Parse(devCode.Substring(6, 2), NumberStyles.HexNumber); + btDevId[4] = byte.Parse(devCode.Substring(8, 2), NumberStyles.HexNumber); + btDevId[5] = byte.Parse(devCode.Substring(10, 2), NumberStyles.HexNumber); + + //通信方式 + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + byte[] btPdu = { 0x05, 0x82 }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + //check result tag + var byteArray = indexArray.ToByteArray(); + byte[] oidTag = + { + 0x60, 0x00, 0x03, 0x00, + 0x00, 0x08, + byteArray[0], byteArray[1], byteArray[2], byteArray[3], + byteArray[4], byteArray[5], byteArray[6], byteArray[7] + }; + + byte[] timeTag = + { + 0x10, 0x00, 0x00, 0x51, + 0x00, 0x06, + RuntimeCache.HydrophoneWakeUpTimestamp[0], RuntimeCache.HydrophoneWakeUpTimestamp[1], + RuntimeCache.HydrophoneWakeUpTimestamp[2], RuntimeCache.HydrophoneWakeUpTimestamp[3], + RuntimeCache.HydrophoneWakeUpTimestamp[4], RuntimeCache.HydrophoneWakeUpTimestamp[5] + }; //时间oid + + //wrap the whole data + var result = new byte[42]; + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oidTag.CopyTo(result, 16); + timeTag.CopyTo(result, 30); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发水听器检查指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendCellAndStatusCollectCmd(SerialPort sp, byte devId) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + byte[] btDevId = { 0x21, 0x17, 0x00, 0x08, 0x22, devId }; //广播模式,设备类型不解析 + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0x22, devId }; + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 2688 + operateType; //0X0A80 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oid = { 0x60, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00 }; + + byte[] totalLen = { 0x00, 0x13 }; + + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + oid.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oid.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "设备 " + devId + " 下发状态采集指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendSoundCollectCmd(SerialPort sp, string devCode) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + //byte[] btDevId = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //广播模式,设备类型不解析 + var btDevId = new byte[6]; + btDevId[0] = byte.Parse(devCode.Substring(0, 2), NumberStyles.HexNumber); + btDevId[1] = byte.Parse(devCode.Substring(2, 2), NumberStyles.HexNumber); + btDevId[2] = byte.Parse(devCode.Substring(4, 2), NumberStyles.HexNumber); + btDevId[3] = byte.Parse(devCode.Substring(6, 2), NumberStyles.HexNumber); + btDevId[4] = byte.Parse(devCode.Substring(8, 2), NumberStyles.HexNumber); + btDevId[5] = byte.Parse(devCode.Substring(10, 2), NumberStyles.HexNumber); + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + var dstNodeAddr = devCode.Substring(8); //2个字节 ** ****** **** + var btDstNode = new byte[2]; + btDstNode[0] = byte.Parse(dstNodeAddr.Substring(0, 2), NumberStyles.HexNumber); + btDstNode[1] = byte.Parse(dstNodeAddr.Substring(2, 2), NumberStyles.HexNumber); + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 2688 + operateType; + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + //第一个Tag的Oid为“0x30000001”,第二个Tag为时间戳,Oid为“0x10000051”,内容为“年、月、日、时、分、秒” + byte[] oid = { 0x20, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00 }; //Tag1 + + byte[] totalLen = { 0x00, 0x13 }; + + //wrap the whole data + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + oid.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oid.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发听音指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendSoundStopCmd(SerialPort sp, string devCode) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + var btDevId = new byte[6]; + btDevId[0] = byte.Parse(devCode.Substring(0, 2), NumberStyles.HexNumber); + btDevId[1] = byte.Parse(devCode.Substring(2, 2), NumberStyles.HexNumber); + btDevId[2] = byte.Parse(devCode.Substring(4, 2), NumberStyles.HexNumber); + btDevId[3] = byte.Parse(devCode.Substring(6, 2), NumberStyles.HexNumber); + btDevId[4] = byte.Parse(devCode.Substring(8, 2), NumberStyles.HexNumber); + btDevId[5] = byte.Parse(devCode.Substring(10, 2), NumberStyles.HexNumber); + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + var dstNodeAddr = devCode.Substring(8); //2个字节 ** ****** **** + var btDstNode = new byte[2]; + btDstNode[0] = byte.Parse(dstNodeAddr.Substring(0, 2), NumberStyles.HexNumber); + btDstNode[1] = byte.Parse(dstNodeAddr.Substring(2, 2), NumberStyles.HexNumber); + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 1408 + operateType; //0x0582 TrapResponse+z噪声记录仪 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] sysTag = + { + 0x10, 0x00, 0x00, 0x51, 0x00, 0x06, + CalendarHub.Year, CalendarHub.Mon, CalendarHub.Day, CalendarHub.Hor, CalendarHub.Min, + CalendarHub.Sec + }; //Tag2 + + byte[] totalLen = { 0x00, 0x18 }; + + //wrap the whole data + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + sysTag.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + sysTag.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发听音结束指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendCorrelatorRangingCmd(SerialPort sp) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + byte[] btDevId = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //广播模式,设备类型不解析 + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 2688 + operateType; //0X0A80 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oid = { 0x30, 0x00, 0x00, 0x01, 0x00, 0x01, 0x99 }; + + byte[] totalLen = { 0x00, 0x13 }; + + //wrap the whole data + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + oid.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oid.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发相关仪测距指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + private CommandModel _lastCommand; + + public CommandModel GetLastCommand() + { + return _lastCommand; + } + } +} \ No newline at end of file diff --git a/Correlator/DataService/IApplicationDataService.cs b/Correlator/DataService/IApplicationDataService.cs index c2c29a7..f232681 100644 --- a/Correlator/DataService/IApplicationDataService.cs +++ b/Correlator/DataService/IApplicationDataService.cs @@ -8,7 +8,7 @@ public interface IApplicationDataService { ObservableCollection GetPipeMaterial(); - + ObservableCollection GetVelocityCollection(string materialName); void DeleteVelocity(MaterialVelocity velocity); @@ -26,11 +26,31 @@ int GetSoundVelocity(string material, int pipeDiameter); AudioVisualizer GetAudioVisualizer(int waveDataSize); - + /// /// 获取 HSV 中所有的基础颜色 (饱和度和明度均为最大值) /// /// 所有的 HSV 基础颜色(共 256 * 6 个, 并且随着索引增加, 颜色也会渐变) Color[] GetAllHsvColors(); + + /// + /// 加载所有工作模式的采样率 + /// + /// + ObservableCollection GetSampleRate(); + + /// + /// 根据工作模式获取采样率 + /// + /// + /// + int GetSampleRateByWorkMode(int mode); + + /// + /// 更新采样率 + /// + /// + /// + void UpdateSampleRate(int mode, int sampleRate); } } \ No newline at end of file diff --git a/Correlator/DataService/IAudioService.cs b/Correlator/DataService/IAudioService.cs index 3295b74..9bf2316 100644 --- a/Correlator/DataService/IAudioService.cs +++ b/Correlator/DataService/IAudioService.cs @@ -11,7 +11,8 @@ /// 开始听音 /// /// - void Start(string deviceCode); + /// + void Start(string deviceCode, int sampleRate); /// /// 缓存听音数据 diff --git a/Correlator/App.xaml.cs b/Correlator/App.xaml.cs index 5c9dd37..c66d198 100644 --- a/Correlator/App.xaml.cs +++ b/Correlator/App.xaml.cs @@ -98,6 +98,7 @@ containerRegistry.RegisterSingleton(); containerRegistry.RegisterSingleton(); containerRegistry.RegisterSingleton(); + containerRegistry.RegisterSingleton(); //Dialog or Window containerRegistry.RegisterDialog(); @@ -105,6 +106,8 @@ containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); + containerRegistry.RegisterDialog(); + containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); diff --git a/Correlator/Converter/SoundParamValueConverter.cs b/Correlator/Converter/SoundParamValueConverter.cs new file mode 100644 index 0000000..4101a19 --- /dev/null +++ b/Correlator/Converter/SoundParamValueConverter.cs @@ -0,0 +1,26 @@ +using System; +using System.Globalization; +using System.Windows.Data; + +namespace Correlator.Converter +{ + public class SoundParamValueConverter : IMultiValueConverter + { + public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) + { + try + { + return "声速:" + values[0] + "m/s,采样率:" + values[1] + "Hz"; + } + catch (Exception) + { + return null; + } + } + + public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) + { + return null; + } + } +} \ No newline at end of file diff --git a/Correlator/Converter/WorkModeConverter.cs b/Correlator/Converter/WorkModeConverter.cs new file mode 100644 index 0000000..19d0327 --- /dev/null +++ b/Correlator/Converter/WorkModeConverter.cs @@ -0,0 +1,21 @@ +using System; +using System.Diagnostics; +using System.Globalization; +using System.Windows.Data; + +namespace Correlator.Converter +{ + internal class WorkModeConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + Debug.Assert(value != null, nameof(value) + " != null"); + return (int)value == 1 ? "加速度计" : "水听器"; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + return null; + } + } +} \ No newline at end of file diff --git a/Correlator/Correlator.csproj b/Correlator/Correlator.csproj index da299ba..c3a433a 100644 --- a/Correlator/Correlator.csproj +++ b/Correlator/Correlator.csproj @@ -216,10 +216,14 @@ + + + + @@ -240,6 +244,9 @@ DetectNoiseDialog.xaml + + EditSoundSampleRateDialog.xaml + EditSoundSpeedDialog.xaml @@ -249,7 +256,14 @@ LoadingDialog.xaml + + SoundSampleRateDialog.xaml + + + + + ApplicationLogView.xaml @@ -303,7 +317,6 @@ - @@ -343,12 +356,14 @@ MSBuild:Compile + Designer MSBuild:Compile + Designer diff --git a/Correlator/DataService/ApplicationDataServiceImpl.cs b/Correlator/DataService/ApplicationDataServiceImpl.cs index d3f9463..d7f0b68 100644 --- a/Correlator/DataService/ApplicationDataServiceImpl.cs +++ b/Correlator/DataService/ApplicationDataServiceImpl.cs @@ -104,7 +104,7 @@ { return new AudioVisualizer(waveDataSize); } - + public Color[] GetAllHsvColors() { var result = new Color[256 * 6]; @@ -141,5 +141,50 @@ return result; } + + public ObservableCollection GetSampleRate() + { + var sampleRateCollection = new ObservableCollection(); + using (var manager = new DataBaseManager()) + { + var result = manager + .Table() + .ToList(); + foreach (var model in result) + { + sampleRateCollection.Add(model); + } + } + + return sampleRateCollection; + } + + public int GetSampleRateByWorkMode(int mode) + { + using (var manager = new DataBaseManager()) + { + var result = manager + .Table() + .First(x => x.WorkMode == mode); + return result?.SampleRate ?? 7500; + } + } + + public void UpdateSampleRate(int mode, int sampleRate) + { + using (var manager = new DataBaseManager()) + { + var result = manager + .Table() + .First(x => x.WorkMode == mode); + var rateModel = result ?? new SampleRateModel(); + + rateModel.WorkMode = mode; + rateModel.SampleRate = sampleRate; + rateModel.UpdateDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); + + manager.Update(rateModel); + } + } } } \ No newline at end of file diff --git a/Correlator/DataService/AudioServiceImpl.cs b/Correlator/DataService/AudioServiceImpl.cs index fd3375f..c9ccb46 100644 --- a/Correlator/DataService/AudioServiceImpl.cs +++ b/Correlator/DataService/AudioServiceImpl.cs @@ -9,16 +9,17 @@ public class AudioServiceImpl : IAudioService { private bool _isStopped; + private WaveFormat _waveFormat; private WaveFileWriter _waveFileWriter; private BufferedWaveProvider _waveProvider; - private readonly WaveFormat _waveFormat = new WaveFormat(7500, 24, 1); public WaveOutEvent Wave { get; set; } = new WaveOutEvent(); - public void Start(string deviceCode) + public void Start(string deviceCode, int sampleRate) { _isStopped = false; + _waveFormat = new WaveFormat(sampleRate, 24, 1); _waveProvider = new BufferedWaveProvider(_waveFormat); Wave.Init(_waveProvider); diff --git a/Correlator/DataService/CommandServiceImpl.cs b/Correlator/DataService/CommandServiceImpl.cs new file mode 100644 index 0000000..28e3402 --- /dev/null +++ b/Correlator/DataService/CommandServiceImpl.cs @@ -0,0 +1,614 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO.Ports; +using Correlator.Model; +using Correlator.Util; + +namespace Correlator.DataService +{ + public class CommandServiceImpl : ICommandService + { + public void SendCorrelatorWakeUpCmd(SerialPort sp) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + byte[] btDevId = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //广播模式,设备类型不解析 + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + const short pduTypeByte = 2; + var operateType = (short)(pduTypeByte & 0x7F); + + var pdu = (short)(2688 + operateType); //0X0A80 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oid = { 0x30, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00 }; + + byte[] totalLen = { 0x00, 0x13 }; + + //wrap the whole data + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + oid.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oid.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发加速度计数据采集指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendHydrophoneWakeUpCmd(SerialPort sp) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + //后续到CRC字段前的字节总长度(不包括长度字段和CRC字段)。 + byte[] totalLen = { 0x00, 0x1F }; + + byte[] btDevId = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //广播模式,设备类型不解析 + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 2688 + operateType; //0X0A80 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oidTag = + { + 0x40, 0x00, 0x00, 0x01, + 0x00, 0x01, + 0x00 + }; + + //获取时间(年-月-日-时-分-秒),年号-2000 + RuntimeCache.HydrophoneWakeUpTimestamp = new[] + { + CalendarHub.Year, CalendarHub.Mon, CalendarHub.Day, CalendarHub.Hor, CalendarHub.Min, + CalendarHub.Sec + }; + byte[] timeTag = + { + 0x10, 0x00, 0x00, 0x51, + 0x00, 0x06, + RuntimeCache.HydrophoneWakeUpTimestamp[0], RuntimeCache.HydrophoneWakeUpTimestamp[1], + RuntimeCache.HydrophoneWakeUpTimestamp[2], RuntimeCache.HydrophoneWakeUpTimestamp[3], + RuntimeCache.HydrophoneWakeUpTimestamp[4], RuntimeCache.HydrophoneWakeUpTimestamp[5] + }; //时间oid + + //wrap the whole data + var result = new byte[35]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oidTag.CopyTo(result, 16); + timeTag.CopyTo(result, 23); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发水听器数据采集指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void StartCheckResponse(SerialPort sp, string devCode) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + //后续到CRC字段前的字节总长度(不包括长度字段和CRC字段)。 + byte[] totalLen = { 0x00, 0x1F }; + + var btDevId = new byte[6]; + btDevId[0] = byte.Parse(devCode.Substring(0, 2), NumberStyles.HexNumber); + btDevId[1] = byte.Parse(devCode.Substring(2, 2), NumberStyles.HexNumber); + btDevId[2] = byte.Parse(devCode.Substring(4, 2), NumberStyles.HexNumber); + btDevId[3] = byte.Parse(devCode.Substring(6, 2), NumberStyles.HexNumber); + btDevId[4] = byte.Parse(devCode.Substring(8, 2), NumberStyles.HexNumber); + btDevId[5] = byte.Parse(devCode.Substring(10, 2), NumberStyles.HexNumber); + + //通信方式 + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + byte[] btPdu = { 0x01, 0x82 }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oidTag = + { + 0x40, 0x00, 0x00, 0x02, + 0x00, 0x01, + 0x00 + }; + + byte[] timeTag = + { + 0x10, 0x00, 0x00, 0x51, + 0x00, 0x06, + RuntimeCache.HydrophoneWakeUpTimestamp[0], RuntimeCache.HydrophoneWakeUpTimestamp[1], + RuntimeCache.HydrophoneWakeUpTimestamp[2], RuntimeCache.HydrophoneWakeUpTimestamp[3], + RuntimeCache.HydrophoneWakeUpTimestamp[4], RuntimeCache.HydrophoneWakeUpTimestamp[5] + }; //时间oid + + //wrap the whole data + var result = new byte[35]; + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oidTag.CopyTo(result, 16); + timeTag.CopyTo(result, 23); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发水听器点名指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendDataCheckResultCmd(SerialPort sp, string devCode, List indexArray) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + //后续到CRC字段前的字节总长度(不包括长度字段和CRC字段)。 + byte[] totalLen = { 0x00, 0x26 }; + + var btDevId = new byte[6]; + btDevId[0] = byte.Parse(devCode.Substring(0, 2), NumberStyles.HexNumber); + btDevId[1] = byte.Parse(devCode.Substring(2, 2), NumberStyles.HexNumber); + btDevId[2] = byte.Parse(devCode.Substring(4, 2), NumberStyles.HexNumber); + btDevId[3] = byte.Parse(devCode.Substring(6, 2), NumberStyles.HexNumber); + btDevId[4] = byte.Parse(devCode.Substring(8, 2), NumberStyles.HexNumber); + btDevId[5] = byte.Parse(devCode.Substring(10, 2), NumberStyles.HexNumber); + + //通信方式 + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + byte[] btPdu = { 0x05, 0x82 }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + //check result tag + var byteArray = indexArray.ToByteArray(); + byte[] oidTag = + { + 0x60, 0x00, 0x03, 0x00, + 0x00, 0x08, + byteArray[0], byteArray[1], byteArray[2], byteArray[3], + byteArray[4], byteArray[5], byteArray[6], byteArray[7] + }; + + byte[] timeTag = + { + 0x10, 0x00, 0x00, 0x51, + 0x00, 0x06, + RuntimeCache.HydrophoneWakeUpTimestamp[0], RuntimeCache.HydrophoneWakeUpTimestamp[1], + RuntimeCache.HydrophoneWakeUpTimestamp[2], RuntimeCache.HydrophoneWakeUpTimestamp[3], + RuntimeCache.HydrophoneWakeUpTimestamp[4], RuntimeCache.HydrophoneWakeUpTimestamp[5] + }; //时间oid + + //wrap the whole data + var result = new byte[42]; + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oidTag.CopyTo(result, 16); + timeTag.CopyTo(result, 30); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发水听器检查指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendCellAndStatusCollectCmd(SerialPort sp, byte devId) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + byte[] btDevId = { 0x21, 0x17, 0x00, 0x08, 0x22, devId }; //广播模式,设备类型不解析 + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0x22, devId }; + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 2688 + operateType; //0X0A80 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oid = { 0x60, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00 }; + + byte[] totalLen = { 0x00, 0x13 }; + + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + oid.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oid.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "设备 " + devId + " 下发状态采集指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendSoundCollectCmd(SerialPort sp, string devCode) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + //byte[] btDevId = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //广播模式,设备类型不解析 + var btDevId = new byte[6]; + btDevId[0] = byte.Parse(devCode.Substring(0, 2), NumberStyles.HexNumber); + btDevId[1] = byte.Parse(devCode.Substring(2, 2), NumberStyles.HexNumber); + btDevId[2] = byte.Parse(devCode.Substring(4, 2), NumberStyles.HexNumber); + btDevId[3] = byte.Parse(devCode.Substring(6, 2), NumberStyles.HexNumber); + btDevId[4] = byte.Parse(devCode.Substring(8, 2), NumberStyles.HexNumber); + btDevId[5] = byte.Parse(devCode.Substring(10, 2), NumberStyles.HexNumber); + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + var dstNodeAddr = devCode.Substring(8); //2个字节 ** ****** **** + var btDstNode = new byte[2]; + btDstNode[0] = byte.Parse(dstNodeAddr.Substring(0, 2), NumberStyles.HexNumber); + btDstNode[1] = byte.Parse(dstNodeAddr.Substring(2, 2), NumberStyles.HexNumber); + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 2688 + operateType; + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + //第一个Tag的Oid为“0x30000001”,第二个Tag为时间戳,Oid为“0x10000051”,内容为“年、月、日、时、分、秒” + byte[] oid = { 0x20, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00 }; //Tag1 + + byte[] totalLen = { 0x00, 0x13 }; + + //wrap the whole data + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + oid.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oid.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发听音指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendSoundStopCmd(SerialPort sp, string devCode) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + var btDevId = new byte[6]; + btDevId[0] = byte.Parse(devCode.Substring(0, 2), NumberStyles.HexNumber); + btDevId[1] = byte.Parse(devCode.Substring(2, 2), NumberStyles.HexNumber); + btDevId[2] = byte.Parse(devCode.Substring(4, 2), NumberStyles.HexNumber); + btDevId[3] = byte.Parse(devCode.Substring(6, 2), NumberStyles.HexNumber); + btDevId[4] = byte.Parse(devCode.Substring(8, 2), NumberStyles.HexNumber); + btDevId[5] = byte.Parse(devCode.Substring(10, 2), NumberStyles.HexNumber); + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + var dstNodeAddr = devCode.Substring(8); //2个字节 ** ****** **** + var btDstNode = new byte[2]; + btDstNode[0] = byte.Parse(dstNodeAddr.Substring(0, 2), NumberStyles.HexNumber); + btDstNode[1] = byte.Parse(dstNodeAddr.Substring(2, 2), NumberStyles.HexNumber); + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 1408 + operateType; //0x0582 TrapResponse+z噪声记录仪 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] sysTag = + { + 0x10, 0x00, 0x00, 0x51, 0x00, 0x06, + CalendarHub.Year, CalendarHub.Mon, CalendarHub.Day, CalendarHub.Hor, CalendarHub.Min, + CalendarHub.Sec + }; //Tag2 + + byte[] totalLen = { 0x00, 0x18 }; + + //wrap the whole data + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + sysTag.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + sysTag.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发听音结束指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendCorrelatorRangingCmd(SerialPort sp) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + byte[] btDevId = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //广播模式,设备类型不解析 + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 2688 + operateType; //0X0A80 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oid = { 0x30, 0x00, 0x00, 0x01, 0x00, 0x01, 0x99 }; + + byte[] totalLen = { 0x00, 0x13 }; + + //wrap the whole data + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + oid.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oid.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发相关仪测距指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + private CommandModel _lastCommand; + + public CommandModel GetLastCommand() + { + return _lastCommand; + } + } +} \ No newline at end of file diff --git a/Correlator/DataService/IApplicationDataService.cs b/Correlator/DataService/IApplicationDataService.cs index c2c29a7..f232681 100644 --- a/Correlator/DataService/IApplicationDataService.cs +++ b/Correlator/DataService/IApplicationDataService.cs @@ -8,7 +8,7 @@ public interface IApplicationDataService { ObservableCollection GetPipeMaterial(); - + ObservableCollection GetVelocityCollection(string materialName); void DeleteVelocity(MaterialVelocity velocity); @@ -26,11 +26,31 @@ int GetSoundVelocity(string material, int pipeDiameter); AudioVisualizer GetAudioVisualizer(int waveDataSize); - + /// /// 获取 HSV 中所有的基础颜色 (饱和度和明度均为最大值) /// /// 所有的 HSV 基础颜色(共 256 * 6 个, 并且随着索引增加, 颜色也会渐变) Color[] GetAllHsvColors(); + + /// + /// 加载所有工作模式的采样率 + /// + /// + ObservableCollection GetSampleRate(); + + /// + /// 根据工作模式获取采样率 + /// + /// + /// + int GetSampleRateByWorkMode(int mode); + + /// + /// 更新采样率 + /// + /// + /// + void UpdateSampleRate(int mode, int sampleRate); } } \ No newline at end of file diff --git a/Correlator/DataService/IAudioService.cs b/Correlator/DataService/IAudioService.cs index 3295b74..9bf2316 100644 --- a/Correlator/DataService/IAudioService.cs +++ b/Correlator/DataService/IAudioService.cs @@ -11,7 +11,8 @@ /// 开始听音 /// /// - void Start(string deviceCode); + /// + void Start(string deviceCode, int sampleRate); /// /// 缓存听音数据 diff --git a/Correlator/DataService/ICommandService.cs b/Correlator/DataService/ICommandService.cs new file mode 100644 index 0000000..d3d2c53 --- /dev/null +++ b/Correlator/DataService/ICommandService.cs @@ -0,0 +1,69 @@ +using System.Collections.Generic; +using System.IO.Ports; +using Correlator.Model; + +namespace Correlator.DataService +{ + public interface ICommandService + { + /// + /// 下发唤醒指令-加速度计 + /// + /// + void SendCorrelatorWakeUpCmd(SerialPort sp); + + /// + /// 下发唤醒指令-水听器 + /// + /// + void SendHydrophoneWakeUpCmd(SerialPort sp); + + /// + /// 水听器点名指令 + /// + /// + /// + void StartCheckResponse(SerialPort sp, string devCode); + + /// + /// 发送校验结果指令给下位机 + /// + /// + /// + /// 异常数据角标集合 + void SendDataCheckResultCmd(SerialPort sp, string devCode, List indexArray); + + /// + /// 下发状态采集指令 + /// + /// + /// + void SendCellAndStatusCollectCmd(SerialPort sp, byte devId); + + /// + /// 下发听音指令 + /// + /// + /// + void SendSoundCollectCmd(SerialPort sp, string devCode); + + /// + /// 下发听音停止指令 + /// + /// + /// + void SendSoundStopCmd(SerialPort sp, string devCode); + + /// + /// 下发测距指令 + /// + /// + void SendCorrelatorRangingCmd(SerialPort sp); + + /// + /// 获取最新下发指令集合 + /// + /// + CommandModel GetLastCommand(); + } +} \ No newline at end of file diff --git a/Correlator/App.xaml.cs b/Correlator/App.xaml.cs index 5c9dd37..c66d198 100644 --- a/Correlator/App.xaml.cs +++ b/Correlator/App.xaml.cs @@ -98,6 +98,7 @@ containerRegistry.RegisterSingleton(); containerRegistry.RegisterSingleton(); containerRegistry.RegisterSingleton(); + containerRegistry.RegisterSingleton(); //Dialog or Window containerRegistry.RegisterDialog(); @@ -105,6 +106,8 @@ containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); + containerRegistry.RegisterDialog(); + containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); diff --git a/Correlator/Converter/SoundParamValueConverter.cs b/Correlator/Converter/SoundParamValueConverter.cs new file mode 100644 index 0000000..4101a19 --- /dev/null +++ b/Correlator/Converter/SoundParamValueConverter.cs @@ -0,0 +1,26 @@ +using System; +using System.Globalization; +using System.Windows.Data; + +namespace Correlator.Converter +{ + public class SoundParamValueConverter : IMultiValueConverter + { + public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) + { + try + { + return "声速:" + values[0] + "m/s,采样率:" + values[1] + "Hz"; + } + catch (Exception) + { + return null; + } + } + + public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) + { + return null; + } + } +} \ No newline at end of file diff --git a/Correlator/Converter/WorkModeConverter.cs b/Correlator/Converter/WorkModeConverter.cs new file mode 100644 index 0000000..19d0327 --- /dev/null +++ b/Correlator/Converter/WorkModeConverter.cs @@ -0,0 +1,21 @@ +using System; +using System.Diagnostics; +using System.Globalization; +using System.Windows.Data; + +namespace Correlator.Converter +{ + internal class WorkModeConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + Debug.Assert(value != null, nameof(value) + " != null"); + return (int)value == 1 ? "加速度计" : "水听器"; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + return null; + } + } +} \ No newline at end of file diff --git a/Correlator/Correlator.csproj b/Correlator/Correlator.csproj index da299ba..c3a433a 100644 --- a/Correlator/Correlator.csproj +++ b/Correlator/Correlator.csproj @@ -216,10 +216,14 @@ + + + + @@ -240,6 +244,9 @@ DetectNoiseDialog.xaml + + EditSoundSampleRateDialog.xaml + EditSoundSpeedDialog.xaml @@ -249,7 +256,14 @@ LoadingDialog.xaml + + SoundSampleRateDialog.xaml + + + + + ApplicationLogView.xaml @@ -303,7 +317,6 @@ - @@ -343,12 +356,14 @@ MSBuild:Compile + Designer MSBuild:Compile + Designer diff --git a/Correlator/DataService/ApplicationDataServiceImpl.cs b/Correlator/DataService/ApplicationDataServiceImpl.cs index d3f9463..d7f0b68 100644 --- a/Correlator/DataService/ApplicationDataServiceImpl.cs +++ b/Correlator/DataService/ApplicationDataServiceImpl.cs @@ -104,7 +104,7 @@ { return new AudioVisualizer(waveDataSize); } - + public Color[] GetAllHsvColors() { var result = new Color[256 * 6]; @@ -141,5 +141,50 @@ return result; } + + public ObservableCollection GetSampleRate() + { + var sampleRateCollection = new ObservableCollection(); + using (var manager = new DataBaseManager()) + { + var result = manager + .Table() + .ToList(); + foreach (var model in result) + { + sampleRateCollection.Add(model); + } + } + + return sampleRateCollection; + } + + public int GetSampleRateByWorkMode(int mode) + { + using (var manager = new DataBaseManager()) + { + var result = manager + .Table() + .First(x => x.WorkMode == mode); + return result?.SampleRate ?? 7500; + } + } + + public void UpdateSampleRate(int mode, int sampleRate) + { + using (var manager = new DataBaseManager()) + { + var result = manager + .Table() + .First(x => x.WorkMode == mode); + var rateModel = result ?? new SampleRateModel(); + + rateModel.WorkMode = mode; + rateModel.SampleRate = sampleRate; + rateModel.UpdateDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); + + manager.Update(rateModel); + } + } } } \ No newline at end of file diff --git a/Correlator/DataService/AudioServiceImpl.cs b/Correlator/DataService/AudioServiceImpl.cs index fd3375f..c9ccb46 100644 --- a/Correlator/DataService/AudioServiceImpl.cs +++ b/Correlator/DataService/AudioServiceImpl.cs @@ -9,16 +9,17 @@ public class AudioServiceImpl : IAudioService { private bool _isStopped; + private WaveFormat _waveFormat; private WaveFileWriter _waveFileWriter; private BufferedWaveProvider _waveProvider; - private readonly WaveFormat _waveFormat = new WaveFormat(7500, 24, 1); public WaveOutEvent Wave { get; set; } = new WaveOutEvent(); - public void Start(string deviceCode) + public void Start(string deviceCode, int sampleRate) { _isStopped = false; + _waveFormat = new WaveFormat(sampleRate, 24, 1); _waveProvider = new BufferedWaveProvider(_waveFormat); Wave.Init(_waveProvider); diff --git a/Correlator/DataService/CommandServiceImpl.cs b/Correlator/DataService/CommandServiceImpl.cs new file mode 100644 index 0000000..28e3402 --- /dev/null +++ b/Correlator/DataService/CommandServiceImpl.cs @@ -0,0 +1,614 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO.Ports; +using Correlator.Model; +using Correlator.Util; + +namespace Correlator.DataService +{ + public class CommandServiceImpl : ICommandService + { + public void SendCorrelatorWakeUpCmd(SerialPort sp) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + byte[] btDevId = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //广播模式,设备类型不解析 + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + const short pduTypeByte = 2; + var operateType = (short)(pduTypeByte & 0x7F); + + var pdu = (short)(2688 + operateType); //0X0A80 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oid = { 0x30, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00 }; + + byte[] totalLen = { 0x00, 0x13 }; + + //wrap the whole data + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + oid.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oid.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发加速度计数据采集指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendHydrophoneWakeUpCmd(SerialPort sp) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + //后续到CRC字段前的字节总长度(不包括长度字段和CRC字段)。 + byte[] totalLen = { 0x00, 0x1F }; + + byte[] btDevId = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //广播模式,设备类型不解析 + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 2688 + operateType; //0X0A80 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oidTag = + { + 0x40, 0x00, 0x00, 0x01, + 0x00, 0x01, + 0x00 + }; + + //获取时间(年-月-日-时-分-秒),年号-2000 + RuntimeCache.HydrophoneWakeUpTimestamp = new[] + { + CalendarHub.Year, CalendarHub.Mon, CalendarHub.Day, CalendarHub.Hor, CalendarHub.Min, + CalendarHub.Sec + }; + byte[] timeTag = + { + 0x10, 0x00, 0x00, 0x51, + 0x00, 0x06, + RuntimeCache.HydrophoneWakeUpTimestamp[0], RuntimeCache.HydrophoneWakeUpTimestamp[1], + RuntimeCache.HydrophoneWakeUpTimestamp[2], RuntimeCache.HydrophoneWakeUpTimestamp[3], + RuntimeCache.HydrophoneWakeUpTimestamp[4], RuntimeCache.HydrophoneWakeUpTimestamp[5] + }; //时间oid + + //wrap the whole data + var result = new byte[35]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oidTag.CopyTo(result, 16); + timeTag.CopyTo(result, 23); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发水听器数据采集指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void StartCheckResponse(SerialPort sp, string devCode) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + //后续到CRC字段前的字节总长度(不包括长度字段和CRC字段)。 + byte[] totalLen = { 0x00, 0x1F }; + + var btDevId = new byte[6]; + btDevId[0] = byte.Parse(devCode.Substring(0, 2), NumberStyles.HexNumber); + btDevId[1] = byte.Parse(devCode.Substring(2, 2), NumberStyles.HexNumber); + btDevId[2] = byte.Parse(devCode.Substring(4, 2), NumberStyles.HexNumber); + btDevId[3] = byte.Parse(devCode.Substring(6, 2), NumberStyles.HexNumber); + btDevId[4] = byte.Parse(devCode.Substring(8, 2), NumberStyles.HexNumber); + btDevId[5] = byte.Parse(devCode.Substring(10, 2), NumberStyles.HexNumber); + + //通信方式 + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + byte[] btPdu = { 0x01, 0x82 }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oidTag = + { + 0x40, 0x00, 0x00, 0x02, + 0x00, 0x01, + 0x00 + }; + + byte[] timeTag = + { + 0x10, 0x00, 0x00, 0x51, + 0x00, 0x06, + RuntimeCache.HydrophoneWakeUpTimestamp[0], RuntimeCache.HydrophoneWakeUpTimestamp[1], + RuntimeCache.HydrophoneWakeUpTimestamp[2], RuntimeCache.HydrophoneWakeUpTimestamp[3], + RuntimeCache.HydrophoneWakeUpTimestamp[4], RuntimeCache.HydrophoneWakeUpTimestamp[5] + }; //时间oid + + //wrap the whole data + var result = new byte[35]; + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oidTag.CopyTo(result, 16); + timeTag.CopyTo(result, 23); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发水听器点名指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendDataCheckResultCmd(SerialPort sp, string devCode, List indexArray) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + //后续到CRC字段前的字节总长度(不包括长度字段和CRC字段)。 + byte[] totalLen = { 0x00, 0x26 }; + + var btDevId = new byte[6]; + btDevId[0] = byte.Parse(devCode.Substring(0, 2), NumberStyles.HexNumber); + btDevId[1] = byte.Parse(devCode.Substring(2, 2), NumberStyles.HexNumber); + btDevId[2] = byte.Parse(devCode.Substring(4, 2), NumberStyles.HexNumber); + btDevId[3] = byte.Parse(devCode.Substring(6, 2), NumberStyles.HexNumber); + btDevId[4] = byte.Parse(devCode.Substring(8, 2), NumberStyles.HexNumber); + btDevId[5] = byte.Parse(devCode.Substring(10, 2), NumberStyles.HexNumber); + + //通信方式 + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + byte[] btPdu = { 0x05, 0x82 }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + //check result tag + var byteArray = indexArray.ToByteArray(); + byte[] oidTag = + { + 0x60, 0x00, 0x03, 0x00, + 0x00, 0x08, + byteArray[0], byteArray[1], byteArray[2], byteArray[3], + byteArray[4], byteArray[5], byteArray[6], byteArray[7] + }; + + byte[] timeTag = + { + 0x10, 0x00, 0x00, 0x51, + 0x00, 0x06, + RuntimeCache.HydrophoneWakeUpTimestamp[0], RuntimeCache.HydrophoneWakeUpTimestamp[1], + RuntimeCache.HydrophoneWakeUpTimestamp[2], RuntimeCache.HydrophoneWakeUpTimestamp[3], + RuntimeCache.HydrophoneWakeUpTimestamp[4], RuntimeCache.HydrophoneWakeUpTimestamp[5] + }; //时间oid + + //wrap the whole data + var result = new byte[42]; + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oidTag.CopyTo(result, 16); + timeTag.CopyTo(result, 30); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发水听器检查指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendCellAndStatusCollectCmd(SerialPort sp, byte devId) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + byte[] btDevId = { 0x21, 0x17, 0x00, 0x08, 0x22, devId }; //广播模式,设备类型不解析 + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0x22, devId }; + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 2688 + operateType; //0X0A80 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oid = { 0x60, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00 }; + + byte[] totalLen = { 0x00, 0x13 }; + + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + oid.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oid.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "设备 " + devId + " 下发状态采集指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendSoundCollectCmd(SerialPort sp, string devCode) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + //byte[] btDevId = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //广播模式,设备类型不解析 + var btDevId = new byte[6]; + btDevId[0] = byte.Parse(devCode.Substring(0, 2), NumberStyles.HexNumber); + btDevId[1] = byte.Parse(devCode.Substring(2, 2), NumberStyles.HexNumber); + btDevId[2] = byte.Parse(devCode.Substring(4, 2), NumberStyles.HexNumber); + btDevId[3] = byte.Parse(devCode.Substring(6, 2), NumberStyles.HexNumber); + btDevId[4] = byte.Parse(devCode.Substring(8, 2), NumberStyles.HexNumber); + btDevId[5] = byte.Parse(devCode.Substring(10, 2), NumberStyles.HexNumber); + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + var dstNodeAddr = devCode.Substring(8); //2个字节 ** ****** **** + var btDstNode = new byte[2]; + btDstNode[0] = byte.Parse(dstNodeAddr.Substring(0, 2), NumberStyles.HexNumber); + btDstNode[1] = byte.Parse(dstNodeAddr.Substring(2, 2), NumberStyles.HexNumber); + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 2688 + operateType; + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + //第一个Tag的Oid为“0x30000001”,第二个Tag为时间戳,Oid为“0x10000051”,内容为“年、月、日、时、分、秒” + byte[] oid = { 0x20, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00 }; //Tag1 + + byte[] totalLen = { 0x00, 0x13 }; + + //wrap the whole data + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + oid.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oid.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发听音指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendSoundStopCmd(SerialPort sp, string devCode) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + var btDevId = new byte[6]; + btDevId[0] = byte.Parse(devCode.Substring(0, 2), NumberStyles.HexNumber); + btDevId[1] = byte.Parse(devCode.Substring(2, 2), NumberStyles.HexNumber); + btDevId[2] = byte.Parse(devCode.Substring(4, 2), NumberStyles.HexNumber); + btDevId[3] = byte.Parse(devCode.Substring(6, 2), NumberStyles.HexNumber); + btDevId[4] = byte.Parse(devCode.Substring(8, 2), NumberStyles.HexNumber); + btDevId[5] = byte.Parse(devCode.Substring(10, 2), NumberStyles.HexNumber); + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + var dstNodeAddr = devCode.Substring(8); //2个字节 ** ****** **** + var btDstNode = new byte[2]; + btDstNode[0] = byte.Parse(dstNodeAddr.Substring(0, 2), NumberStyles.HexNumber); + btDstNode[1] = byte.Parse(dstNodeAddr.Substring(2, 2), NumberStyles.HexNumber); + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 1408 + operateType; //0x0582 TrapResponse+z噪声记录仪 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] sysTag = + { + 0x10, 0x00, 0x00, 0x51, 0x00, 0x06, + CalendarHub.Year, CalendarHub.Mon, CalendarHub.Day, CalendarHub.Hor, CalendarHub.Min, + CalendarHub.Sec + }; //Tag2 + + byte[] totalLen = { 0x00, 0x18 }; + + //wrap the whole data + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + sysTag.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + sysTag.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发听音结束指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendCorrelatorRangingCmd(SerialPort sp) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + byte[] btDevId = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //广播模式,设备类型不解析 + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 2688 + operateType; //0X0A80 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oid = { 0x30, 0x00, 0x00, 0x01, 0x00, 0x01, 0x99 }; + + byte[] totalLen = { 0x00, 0x13 }; + + //wrap the whole data + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + oid.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oid.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发相关仪测距指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + private CommandModel _lastCommand; + + public CommandModel GetLastCommand() + { + return _lastCommand; + } + } +} \ No newline at end of file diff --git a/Correlator/DataService/IApplicationDataService.cs b/Correlator/DataService/IApplicationDataService.cs index c2c29a7..f232681 100644 --- a/Correlator/DataService/IApplicationDataService.cs +++ b/Correlator/DataService/IApplicationDataService.cs @@ -8,7 +8,7 @@ public interface IApplicationDataService { ObservableCollection GetPipeMaterial(); - + ObservableCollection GetVelocityCollection(string materialName); void DeleteVelocity(MaterialVelocity velocity); @@ -26,11 +26,31 @@ int GetSoundVelocity(string material, int pipeDiameter); AudioVisualizer GetAudioVisualizer(int waveDataSize); - + /// /// 获取 HSV 中所有的基础颜色 (饱和度和明度均为最大值) /// /// 所有的 HSV 基础颜色(共 256 * 6 个, 并且随着索引增加, 颜色也会渐变) Color[] GetAllHsvColors(); + + /// + /// 加载所有工作模式的采样率 + /// + /// + ObservableCollection GetSampleRate(); + + /// + /// 根据工作模式获取采样率 + /// + /// + /// + int GetSampleRateByWorkMode(int mode); + + /// + /// 更新采样率 + /// + /// + /// + void UpdateSampleRate(int mode, int sampleRate); } } \ No newline at end of file diff --git a/Correlator/DataService/IAudioService.cs b/Correlator/DataService/IAudioService.cs index 3295b74..9bf2316 100644 --- a/Correlator/DataService/IAudioService.cs +++ b/Correlator/DataService/IAudioService.cs @@ -11,7 +11,8 @@ /// 开始听音 /// /// - void Start(string deviceCode); + /// + void Start(string deviceCode, int sampleRate); /// /// 缓存听音数据 diff --git a/Correlator/DataService/ICommandService.cs b/Correlator/DataService/ICommandService.cs new file mode 100644 index 0000000..d3d2c53 --- /dev/null +++ b/Correlator/DataService/ICommandService.cs @@ -0,0 +1,69 @@ +using System.Collections.Generic; +using System.IO.Ports; +using Correlator.Model; + +namespace Correlator.DataService +{ + public interface ICommandService + { + /// + /// 下发唤醒指令-加速度计 + /// + /// + void SendCorrelatorWakeUpCmd(SerialPort sp); + + /// + /// 下发唤醒指令-水听器 + /// + /// + void SendHydrophoneWakeUpCmd(SerialPort sp); + + /// + /// 水听器点名指令 + /// + /// + /// + void StartCheckResponse(SerialPort sp, string devCode); + + /// + /// 发送校验结果指令给下位机 + /// + /// + /// + /// 异常数据角标集合 + void SendDataCheckResultCmd(SerialPort sp, string devCode, List indexArray); + + /// + /// 下发状态采集指令 + /// + /// + /// + void SendCellAndStatusCollectCmd(SerialPort sp, byte devId); + + /// + /// 下发听音指令 + /// + /// + /// + void SendSoundCollectCmd(SerialPort sp, string devCode); + + /// + /// 下发听音停止指令 + /// + /// + /// + void SendSoundStopCmd(SerialPort sp, string devCode); + + /// + /// 下发测距指令 + /// + /// + void SendCorrelatorRangingCmd(SerialPort sp); + + /// + /// 获取最新下发指令集合 + /// + /// + CommandModel GetLastCommand(); + } +} \ No newline at end of file diff --git a/Correlator/DataService/SerialPortServiceImpl.cs b/Correlator/DataService/SerialPortServiceImpl.cs index e18210e..364ee77 100644 --- a/Correlator/DataService/SerialPortServiceImpl.cs +++ b/Correlator/DataService/SerialPortServiceImpl.cs @@ -15,6 +15,8 @@ { private readonly IEventAggregator _eventAggregator; private readonly IAudioService _audioService; + private readonly ICommandService _commandService; + private readonly IApplicationDataService _dataService; private readonly DevStatus _devStatus = new DevStatus(); private int _checkResponseState; @@ -23,10 +25,14 @@ //左右传感器设备数据 private CorrelatorDataModel _dataModel; - public SerialPortServiceImpl(IEventAggregator eventAggregator, IAudioService audioService) + public SerialPortServiceImpl(IEventAggregator eventAggregator, IAudioService audioService, + ICommandService commandService, IApplicationDataService dataService) { _eventAggregator = eventAggregator; _audioService = audioService; + _commandService = commandService; + _dataService = dataService; + Sp.DataReceived += delegate { while (Sp.BytesToRead < 4) @@ -264,6 +270,7 @@ private void HandleListenData(List tags) { + var sampleRate = _dataService.GetSampleRateByWorkMode(RuntimeCache.WorkMode); //处理接到的噪声数据 var noiseTag = tags.GetUploadNoiseTag(); if (noiseTag != null) @@ -283,9 +290,9 @@ } //PCM数据 - var pcm = new byte[7500 * 3]; //每个采样点2字节 + var pcm = new byte[sampleRate * 3]; //每个采样点2字节 - for (var i = 0; i < 7500; i++) + for (var i = 0; i < sampleRate; i++) { pcm[i * 3 + 2] = dataValue[i * 2 + 0]; pcm[i * 3 + 1] = dataValue[i * 2 + 1]; @@ -357,7 +364,7 @@ } var devId = !RuntimeCache.RedSensorIsEnable ? (byte)0x01 : (byte)0x02; - CommandSender.SendCellAndStatusCollectCmd(Sp, devId); + _commandService.SendCellAndStatusCollectCmd(Sp, devId); Sp.Write("ATA" + Environment.NewLine); } } diff --git a/Correlator/App.xaml.cs b/Correlator/App.xaml.cs index 5c9dd37..c66d198 100644 --- a/Correlator/App.xaml.cs +++ b/Correlator/App.xaml.cs @@ -98,6 +98,7 @@ containerRegistry.RegisterSingleton(); containerRegistry.RegisterSingleton(); containerRegistry.RegisterSingleton(); + containerRegistry.RegisterSingleton(); //Dialog or Window containerRegistry.RegisterDialog(); @@ -105,6 +106,8 @@ containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); + containerRegistry.RegisterDialog(); + containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); diff --git a/Correlator/Converter/SoundParamValueConverter.cs b/Correlator/Converter/SoundParamValueConverter.cs new file mode 100644 index 0000000..4101a19 --- /dev/null +++ b/Correlator/Converter/SoundParamValueConverter.cs @@ -0,0 +1,26 @@ +using System; +using System.Globalization; +using System.Windows.Data; + +namespace Correlator.Converter +{ + public class SoundParamValueConverter : IMultiValueConverter + { + public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) + { + try + { + return "声速:" + values[0] + "m/s,采样率:" + values[1] + "Hz"; + } + catch (Exception) + { + return null; + } + } + + public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) + { + return null; + } + } +} \ No newline at end of file diff --git a/Correlator/Converter/WorkModeConverter.cs b/Correlator/Converter/WorkModeConverter.cs new file mode 100644 index 0000000..19d0327 --- /dev/null +++ b/Correlator/Converter/WorkModeConverter.cs @@ -0,0 +1,21 @@ +using System; +using System.Diagnostics; +using System.Globalization; +using System.Windows.Data; + +namespace Correlator.Converter +{ + internal class WorkModeConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + Debug.Assert(value != null, nameof(value) + " != null"); + return (int)value == 1 ? "加速度计" : "水听器"; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + return null; + } + } +} \ No newline at end of file diff --git a/Correlator/Correlator.csproj b/Correlator/Correlator.csproj index da299ba..c3a433a 100644 --- a/Correlator/Correlator.csproj +++ b/Correlator/Correlator.csproj @@ -216,10 +216,14 @@ + + + + @@ -240,6 +244,9 @@ DetectNoiseDialog.xaml + + EditSoundSampleRateDialog.xaml + EditSoundSpeedDialog.xaml @@ -249,7 +256,14 @@ LoadingDialog.xaml + + SoundSampleRateDialog.xaml + + + + + ApplicationLogView.xaml @@ -303,7 +317,6 @@ - @@ -343,12 +356,14 @@ MSBuild:Compile + Designer MSBuild:Compile + Designer diff --git a/Correlator/DataService/ApplicationDataServiceImpl.cs b/Correlator/DataService/ApplicationDataServiceImpl.cs index d3f9463..d7f0b68 100644 --- a/Correlator/DataService/ApplicationDataServiceImpl.cs +++ b/Correlator/DataService/ApplicationDataServiceImpl.cs @@ -104,7 +104,7 @@ { return new AudioVisualizer(waveDataSize); } - + public Color[] GetAllHsvColors() { var result = new Color[256 * 6]; @@ -141,5 +141,50 @@ return result; } + + public ObservableCollection GetSampleRate() + { + var sampleRateCollection = new ObservableCollection(); + using (var manager = new DataBaseManager()) + { + var result = manager + .Table() + .ToList(); + foreach (var model in result) + { + sampleRateCollection.Add(model); + } + } + + return sampleRateCollection; + } + + public int GetSampleRateByWorkMode(int mode) + { + using (var manager = new DataBaseManager()) + { + var result = manager + .Table() + .First(x => x.WorkMode == mode); + return result?.SampleRate ?? 7500; + } + } + + public void UpdateSampleRate(int mode, int sampleRate) + { + using (var manager = new DataBaseManager()) + { + var result = manager + .Table() + .First(x => x.WorkMode == mode); + var rateModel = result ?? new SampleRateModel(); + + rateModel.WorkMode = mode; + rateModel.SampleRate = sampleRate; + rateModel.UpdateDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); + + manager.Update(rateModel); + } + } } } \ No newline at end of file diff --git a/Correlator/DataService/AudioServiceImpl.cs b/Correlator/DataService/AudioServiceImpl.cs index fd3375f..c9ccb46 100644 --- a/Correlator/DataService/AudioServiceImpl.cs +++ b/Correlator/DataService/AudioServiceImpl.cs @@ -9,16 +9,17 @@ public class AudioServiceImpl : IAudioService { private bool _isStopped; + private WaveFormat _waveFormat; private WaveFileWriter _waveFileWriter; private BufferedWaveProvider _waveProvider; - private readonly WaveFormat _waveFormat = new WaveFormat(7500, 24, 1); public WaveOutEvent Wave { get; set; } = new WaveOutEvent(); - public void Start(string deviceCode) + public void Start(string deviceCode, int sampleRate) { _isStopped = false; + _waveFormat = new WaveFormat(sampleRate, 24, 1); _waveProvider = new BufferedWaveProvider(_waveFormat); Wave.Init(_waveProvider); diff --git a/Correlator/DataService/CommandServiceImpl.cs b/Correlator/DataService/CommandServiceImpl.cs new file mode 100644 index 0000000..28e3402 --- /dev/null +++ b/Correlator/DataService/CommandServiceImpl.cs @@ -0,0 +1,614 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO.Ports; +using Correlator.Model; +using Correlator.Util; + +namespace Correlator.DataService +{ + public class CommandServiceImpl : ICommandService + { + public void SendCorrelatorWakeUpCmd(SerialPort sp) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + byte[] btDevId = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //广播模式,设备类型不解析 + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + const short pduTypeByte = 2; + var operateType = (short)(pduTypeByte & 0x7F); + + var pdu = (short)(2688 + operateType); //0X0A80 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oid = { 0x30, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00 }; + + byte[] totalLen = { 0x00, 0x13 }; + + //wrap the whole data + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + oid.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oid.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发加速度计数据采集指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendHydrophoneWakeUpCmd(SerialPort sp) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + //后续到CRC字段前的字节总长度(不包括长度字段和CRC字段)。 + byte[] totalLen = { 0x00, 0x1F }; + + byte[] btDevId = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //广播模式,设备类型不解析 + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 2688 + operateType; //0X0A80 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oidTag = + { + 0x40, 0x00, 0x00, 0x01, + 0x00, 0x01, + 0x00 + }; + + //获取时间(年-月-日-时-分-秒),年号-2000 + RuntimeCache.HydrophoneWakeUpTimestamp = new[] + { + CalendarHub.Year, CalendarHub.Mon, CalendarHub.Day, CalendarHub.Hor, CalendarHub.Min, + CalendarHub.Sec + }; + byte[] timeTag = + { + 0x10, 0x00, 0x00, 0x51, + 0x00, 0x06, + RuntimeCache.HydrophoneWakeUpTimestamp[0], RuntimeCache.HydrophoneWakeUpTimestamp[1], + RuntimeCache.HydrophoneWakeUpTimestamp[2], RuntimeCache.HydrophoneWakeUpTimestamp[3], + RuntimeCache.HydrophoneWakeUpTimestamp[4], RuntimeCache.HydrophoneWakeUpTimestamp[5] + }; //时间oid + + //wrap the whole data + var result = new byte[35]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oidTag.CopyTo(result, 16); + timeTag.CopyTo(result, 23); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发水听器数据采集指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void StartCheckResponse(SerialPort sp, string devCode) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + //后续到CRC字段前的字节总长度(不包括长度字段和CRC字段)。 + byte[] totalLen = { 0x00, 0x1F }; + + var btDevId = new byte[6]; + btDevId[0] = byte.Parse(devCode.Substring(0, 2), NumberStyles.HexNumber); + btDevId[1] = byte.Parse(devCode.Substring(2, 2), NumberStyles.HexNumber); + btDevId[2] = byte.Parse(devCode.Substring(4, 2), NumberStyles.HexNumber); + btDevId[3] = byte.Parse(devCode.Substring(6, 2), NumberStyles.HexNumber); + btDevId[4] = byte.Parse(devCode.Substring(8, 2), NumberStyles.HexNumber); + btDevId[5] = byte.Parse(devCode.Substring(10, 2), NumberStyles.HexNumber); + + //通信方式 + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + byte[] btPdu = { 0x01, 0x82 }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oidTag = + { + 0x40, 0x00, 0x00, 0x02, + 0x00, 0x01, + 0x00 + }; + + byte[] timeTag = + { + 0x10, 0x00, 0x00, 0x51, + 0x00, 0x06, + RuntimeCache.HydrophoneWakeUpTimestamp[0], RuntimeCache.HydrophoneWakeUpTimestamp[1], + RuntimeCache.HydrophoneWakeUpTimestamp[2], RuntimeCache.HydrophoneWakeUpTimestamp[3], + RuntimeCache.HydrophoneWakeUpTimestamp[4], RuntimeCache.HydrophoneWakeUpTimestamp[5] + }; //时间oid + + //wrap the whole data + var result = new byte[35]; + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oidTag.CopyTo(result, 16); + timeTag.CopyTo(result, 23); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发水听器点名指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendDataCheckResultCmd(SerialPort sp, string devCode, List indexArray) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + //后续到CRC字段前的字节总长度(不包括长度字段和CRC字段)。 + byte[] totalLen = { 0x00, 0x26 }; + + var btDevId = new byte[6]; + btDevId[0] = byte.Parse(devCode.Substring(0, 2), NumberStyles.HexNumber); + btDevId[1] = byte.Parse(devCode.Substring(2, 2), NumberStyles.HexNumber); + btDevId[2] = byte.Parse(devCode.Substring(4, 2), NumberStyles.HexNumber); + btDevId[3] = byte.Parse(devCode.Substring(6, 2), NumberStyles.HexNumber); + btDevId[4] = byte.Parse(devCode.Substring(8, 2), NumberStyles.HexNumber); + btDevId[5] = byte.Parse(devCode.Substring(10, 2), NumberStyles.HexNumber); + + //通信方式 + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + byte[] btPdu = { 0x05, 0x82 }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + //check result tag + var byteArray = indexArray.ToByteArray(); + byte[] oidTag = + { + 0x60, 0x00, 0x03, 0x00, + 0x00, 0x08, + byteArray[0], byteArray[1], byteArray[2], byteArray[3], + byteArray[4], byteArray[5], byteArray[6], byteArray[7] + }; + + byte[] timeTag = + { + 0x10, 0x00, 0x00, 0x51, + 0x00, 0x06, + RuntimeCache.HydrophoneWakeUpTimestamp[0], RuntimeCache.HydrophoneWakeUpTimestamp[1], + RuntimeCache.HydrophoneWakeUpTimestamp[2], RuntimeCache.HydrophoneWakeUpTimestamp[3], + RuntimeCache.HydrophoneWakeUpTimestamp[4], RuntimeCache.HydrophoneWakeUpTimestamp[5] + }; //时间oid + + //wrap the whole data + var result = new byte[42]; + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oidTag.CopyTo(result, 16); + timeTag.CopyTo(result, 30); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发水听器检查指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendCellAndStatusCollectCmd(SerialPort sp, byte devId) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + byte[] btDevId = { 0x21, 0x17, 0x00, 0x08, 0x22, devId }; //广播模式,设备类型不解析 + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0x22, devId }; + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 2688 + operateType; //0X0A80 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oid = { 0x60, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00 }; + + byte[] totalLen = { 0x00, 0x13 }; + + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + oid.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oid.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "设备 " + devId + " 下发状态采集指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendSoundCollectCmd(SerialPort sp, string devCode) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + //byte[] btDevId = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //广播模式,设备类型不解析 + var btDevId = new byte[6]; + btDevId[0] = byte.Parse(devCode.Substring(0, 2), NumberStyles.HexNumber); + btDevId[1] = byte.Parse(devCode.Substring(2, 2), NumberStyles.HexNumber); + btDevId[2] = byte.Parse(devCode.Substring(4, 2), NumberStyles.HexNumber); + btDevId[3] = byte.Parse(devCode.Substring(6, 2), NumberStyles.HexNumber); + btDevId[4] = byte.Parse(devCode.Substring(8, 2), NumberStyles.HexNumber); + btDevId[5] = byte.Parse(devCode.Substring(10, 2), NumberStyles.HexNumber); + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + var dstNodeAddr = devCode.Substring(8); //2个字节 ** ****** **** + var btDstNode = new byte[2]; + btDstNode[0] = byte.Parse(dstNodeAddr.Substring(0, 2), NumberStyles.HexNumber); + btDstNode[1] = byte.Parse(dstNodeAddr.Substring(2, 2), NumberStyles.HexNumber); + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 2688 + operateType; + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + //第一个Tag的Oid为“0x30000001”,第二个Tag为时间戳,Oid为“0x10000051”,内容为“年、月、日、时、分、秒” + byte[] oid = { 0x20, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00 }; //Tag1 + + byte[] totalLen = { 0x00, 0x13 }; + + //wrap the whole data + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + oid.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oid.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发听音指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendSoundStopCmd(SerialPort sp, string devCode) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + var btDevId = new byte[6]; + btDevId[0] = byte.Parse(devCode.Substring(0, 2), NumberStyles.HexNumber); + btDevId[1] = byte.Parse(devCode.Substring(2, 2), NumberStyles.HexNumber); + btDevId[2] = byte.Parse(devCode.Substring(4, 2), NumberStyles.HexNumber); + btDevId[3] = byte.Parse(devCode.Substring(6, 2), NumberStyles.HexNumber); + btDevId[4] = byte.Parse(devCode.Substring(8, 2), NumberStyles.HexNumber); + btDevId[5] = byte.Parse(devCode.Substring(10, 2), NumberStyles.HexNumber); + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + var dstNodeAddr = devCode.Substring(8); //2个字节 ** ****** **** + var btDstNode = new byte[2]; + btDstNode[0] = byte.Parse(dstNodeAddr.Substring(0, 2), NumberStyles.HexNumber); + btDstNode[1] = byte.Parse(dstNodeAddr.Substring(2, 2), NumberStyles.HexNumber); + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 1408 + operateType; //0x0582 TrapResponse+z噪声记录仪 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] sysTag = + { + 0x10, 0x00, 0x00, 0x51, 0x00, 0x06, + CalendarHub.Year, CalendarHub.Mon, CalendarHub.Day, CalendarHub.Hor, CalendarHub.Min, + CalendarHub.Sec + }; //Tag2 + + byte[] totalLen = { 0x00, 0x18 }; + + //wrap the whole data + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + sysTag.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + sysTag.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发听音结束指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendCorrelatorRangingCmd(SerialPort sp) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + byte[] btDevId = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //广播模式,设备类型不解析 + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 2688 + operateType; //0X0A80 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oid = { 0x30, 0x00, 0x00, 0x01, 0x00, 0x01, 0x99 }; + + byte[] totalLen = { 0x00, 0x13 }; + + //wrap the whole data + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + oid.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oid.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发相关仪测距指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + private CommandModel _lastCommand; + + public CommandModel GetLastCommand() + { + return _lastCommand; + } + } +} \ No newline at end of file diff --git a/Correlator/DataService/IApplicationDataService.cs b/Correlator/DataService/IApplicationDataService.cs index c2c29a7..f232681 100644 --- a/Correlator/DataService/IApplicationDataService.cs +++ b/Correlator/DataService/IApplicationDataService.cs @@ -8,7 +8,7 @@ public interface IApplicationDataService { ObservableCollection GetPipeMaterial(); - + ObservableCollection GetVelocityCollection(string materialName); void DeleteVelocity(MaterialVelocity velocity); @@ -26,11 +26,31 @@ int GetSoundVelocity(string material, int pipeDiameter); AudioVisualizer GetAudioVisualizer(int waveDataSize); - + /// /// 获取 HSV 中所有的基础颜色 (饱和度和明度均为最大值) /// /// 所有的 HSV 基础颜色(共 256 * 6 个, 并且随着索引增加, 颜色也会渐变) Color[] GetAllHsvColors(); + + /// + /// 加载所有工作模式的采样率 + /// + /// + ObservableCollection GetSampleRate(); + + /// + /// 根据工作模式获取采样率 + /// + /// + /// + int GetSampleRateByWorkMode(int mode); + + /// + /// 更新采样率 + /// + /// + /// + void UpdateSampleRate(int mode, int sampleRate); } } \ No newline at end of file diff --git a/Correlator/DataService/IAudioService.cs b/Correlator/DataService/IAudioService.cs index 3295b74..9bf2316 100644 --- a/Correlator/DataService/IAudioService.cs +++ b/Correlator/DataService/IAudioService.cs @@ -11,7 +11,8 @@ /// 开始听音 /// /// - void Start(string deviceCode); + /// + void Start(string deviceCode, int sampleRate); /// /// 缓存听音数据 diff --git a/Correlator/DataService/ICommandService.cs b/Correlator/DataService/ICommandService.cs new file mode 100644 index 0000000..d3d2c53 --- /dev/null +++ b/Correlator/DataService/ICommandService.cs @@ -0,0 +1,69 @@ +using System.Collections.Generic; +using System.IO.Ports; +using Correlator.Model; + +namespace Correlator.DataService +{ + public interface ICommandService + { + /// + /// 下发唤醒指令-加速度计 + /// + /// + void SendCorrelatorWakeUpCmd(SerialPort sp); + + /// + /// 下发唤醒指令-水听器 + /// + /// + void SendHydrophoneWakeUpCmd(SerialPort sp); + + /// + /// 水听器点名指令 + /// + /// + /// + void StartCheckResponse(SerialPort sp, string devCode); + + /// + /// 发送校验结果指令给下位机 + /// + /// + /// + /// 异常数据角标集合 + void SendDataCheckResultCmd(SerialPort sp, string devCode, List indexArray); + + /// + /// 下发状态采集指令 + /// + /// + /// + void SendCellAndStatusCollectCmd(SerialPort sp, byte devId); + + /// + /// 下发听音指令 + /// + /// + /// + void SendSoundCollectCmd(SerialPort sp, string devCode); + + /// + /// 下发听音停止指令 + /// + /// + /// + void SendSoundStopCmd(SerialPort sp, string devCode); + + /// + /// 下发测距指令 + /// + /// + void SendCorrelatorRangingCmd(SerialPort sp); + + /// + /// 获取最新下发指令集合 + /// + /// + CommandModel GetLastCommand(); + } +} \ No newline at end of file diff --git a/Correlator/DataService/SerialPortServiceImpl.cs b/Correlator/DataService/SerialPortServiceImpl.cs index e18210e..364ee77 100644 --- a/Correlator/DataService/SerialPortServiceImpl.cs +++ b/Correlator/DataService/SerialPortServiceImpl.cs @@ -15,6 +15,8 @@ { private readonly IEventAggregator _eventAggregator; private readonly IAudioService _audioService; + private readonly ICommandService _commandService; + private readonly IApplicationDataService _dataService; private readonly DevStatus _devStatus = new DevStatus(); private int _checkResponseState; @@ -23,10 +25,14 @@ //左右传感器设备数据 private CorrelatorDataModel _dataModel; - public SerialPortServiceImpl(IEventAggregator eventAggregator, IAudioService audioService) + public SerialPortServiceImpl(IEventAggregator eventAggregator, IAudioService audioService, + ICommandService commandService, IApplicationDataService dataService) { _eventAggregator = eventAggregator; _audioService = audioService; + _commandService = commandService; + _dataService = dataService; + Sp.DataReceived += delegate { while (Sp.BytesToRead < 4) @@ -264,6 +270,7 @@ private void HandleListenData(List tags) { + var sampleRate = _dataService.GetSampleRateByWorkMode(RuntimeCache.WorkMode); //处理接到的噪声数据 var noiseTag = tags.GetUploadNoiseTag(); if (noiseTag != null) @@ -283,9 +290,9 @@ } //PCM数据 - var pcm = new byte[7500 * 3]; //每个采样点2字节 + var pcm = new byte[sampleRate * 3]; //每个采样点2字节 - for (var i = 0; i < 7500; i++) + for (var i = 0; i < sampleRate; i++) { pcm[i * 3 + 2] = dataValue[i * 2 + 0]; pcm[i * 3 + 1] = dataValue[i * 2 + 1]; @@ -357,7 +364,7 @@ } var devId = !RuntimeCache.RedSensorIsEnable ? (byte)0x01 : (byte)0x02; - CommandSender.SendCellAndStatusCollectCmd(Sp, devId); + _commandService.SendCellAndStatusCollectCmd(Sp, devId); Sp.Write("ATA" + Environment.NewLine); } } diff --git a/Correlator/Dialog/CheckResponseDialog.xaml.cs b/Correlator/Dialog/CheckResponseDialog.xaml.cs index 72fd7b6..2cf2c01 100644 --- a/Correlator/Dialog/CheckResponseDialog.xaml.cs +++ b/Correlator/Dialog/CheckResponseDialog.xaml.cs @@ -45,15 +45,17 @@ private readonly IEventAggregator _eventAggregator; private readonly ISerialPortService _serialPortService; private readonly IDialogService _dialogService; + private readonly ICommandService _commandService; public CheckResponseDialog(IEventAggregator eventAggregator, ISerialPortService serialPortService, - IDialogService dialogService) + IDialogService dialogService, ICommandService commandService) { InitializeComponent(); _eventAggregator = eventAggregator; _serialPortService = serialPortService; _dialogService = dialogService; + _commandService = commandService; var today = DateTime.Now.ToString("yyyyMMdd"); var configModel = LazyDataBase.Value.Table() @@ -218,7 +220,7 @@ if (RedSensorStepBar.StepIndex == 1) { RuntimeCache.SeqCaches.Clear(); - CommandSender.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev1); + _commandService.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev1); _redResponseTimer.Start(); ReCheckButton.IsEnabled = true; @@ -226,7 +228,7 @@ else if (RedSensorStepBar.StepIndex == 2) { //下发数据全部正常指令 - CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, new List()); + _commandService.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, new List()); #region 保存原始数据 @@ -295,14 +297,14 @@ if (BlueSensorStepBar.StepIndex == 1) { RuntimeCache.SeqCaches.Clear(); - CommandSender.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev2); + _commandService.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev2); _blueResponseTimer.Start(); ReCheckButton.IsEnabled = true; } else if (BlueSensorStepBar.StepIndex == 2) { - CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, new List()); + _commandService.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, new List()); #region 保存原始数据 @@ -376,7 +378,7 @@ } } - CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, redIndexArray); + _commandService.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, redIndexArray); } else { @@ -397,7 +399,7 @@ } } - CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, blueIndexArray); + _commandService.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, blueIndexArray); } }; } diff --git a/Correlator/App.xaml.cs b/Correlator/App.xaml.cs index 5c9dd37..c66d198 100644 --- a/Correlator/App.xaml.cs +++ b/Correlator/App.xaml.cs @@ -98,6 +98,7 @@ containerRegistry.RegisterSingleton(); containerRegistry.RegisterSingleton(); containerRegistry.RegisterSingleton(); + containerRegistry.RegisterSingleton(); //Dialog or Window containerRegistry.RegisterDialog(); @@ -105,6 +106,8 @@ containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); + containerRegistry.RegisterDialog(); + containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); diff --git a/Correlator/Converter/SoundParamValueConverter.cs b/Correlator/Converter/SoundParamValueConverter.cs new file mode 100644 index 0000000..4101a19 --- /dev/null +++ b/Correlator/Converter/SoundParamValueConverter.cs @@ -0,0 +1,26 @@ +using System; +using System.Globalization; +using System.Windows.Data; + +namespace Correlator.Converter +{ + public class SoundParamValueConverter : IMultiValueConverter + { + public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) + { + try + { + return "声速:" + values[0] + "m/s,采样率:" + values[1] + "Hz"; + } + catch (Exception) + { + return null; + } + } + + public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) + { + return null; + } + } +} \ No newline at end of file diff --git a/Correlator/Converter/WorkModeConverter.cs b/Correlator/Converter/WorkModeConverter.cs new file mode 100644 index 0000000..19d0327 --- /dev/null +++ b/Correlator/Converter/WorkModeConverter.cs @@ -0,0 +1,21 @@ +using System; +using System.Diagnostics; +using System.Globalization; +using System.Windows.Data; + +namespace Correlator.Converter +{ + internal class WorkModeConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + Debug.Assert(value != null, nameof(value) + " != null"); + return (int)value == 1 ? "加速度计" : "水听器"; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + return null; + } + } +} \ No newline at end of file diff --git a/Correlator/Correlator.csproj b/Correlator/Correlator.csproj index da299ba..c3a433a 100644 --- a/Correlator/Correlator.csproj +++ b/Correlator/Correlator.csproj @@ -216,10 +216,14 @@ + + + + @@ -240,6 +244,9 @@ DetectNoiseDialog.xaml + + EditSoundSampleRateDialog.xaml + EditSoundSpeedDialog.xaml @@ -249,7 +256,14 @@ LoadingDialog.xaml + + SoundSampleRateDialog.xaml + + + + + ApplicationLogView.xaml @@ -303,7 +317,6 @@ - @@ -343,12 +356,14 @@ MSBuild:Compile + Designer MSBuild:Compile + Designer diff --git a/Correlator/DataService/ApplicationDataServiceImpl.cs b/Correlator/DataService/ApplicationDataServiceImpl.cs index d3f9463..d7f0b68 100644 --- a/Correlator/DataService/ApplicationDataServiceImpl.cs +++ b/Correlator/DataService/ApplicationDataServiceImpl.cs @@ -104,7 +104,7 @@ { return new AudioVisualizer(waveDataSize); } - + public Color[] GetAllHsvColors() { var result = new Color[256 * 6]; @@ -141,5 +141,50 @@ return result; } + + public ObservableCollection GetSampleRate() + { + var sampleRateCollection = new ObservableCollection(); + using (var manager = new DataBaseManager()) + { + var result = manager + .Table() + .ToList(); + foreach (var model in result) + { + sampleRateCollection.Add(model); + } + } + + return sampleRateCollection; + } + + public int GetSampleRateByWorkMode(int mode) + { + using (var manager = new DataBaseManager()) + { + var result = manager + .Table() + .First(x => x.WorkMode == mode); + return result?.SampleRate ?? 7500; + } + } + + public void UpdateSampleRate(int mode, int sampleRate) + { + using (var manager = new DataBaseManager()) + { + var result = manager + .Table() + .First(x => x.WorkMode == mode); + var rateModel = result ?? new SampleRateModel(); + + rateModel.WorkMode = mode; + rateModel.SampleRate = sampleRate; + rateModel.UpdateDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); + + manager.Update(rateModel); + } + } } } \ No newline at end of file diff --git a/Correlator/DataService/AudioServiceImpl.cs b/Correlator/DataService/AudioServiceImpl.cs index fd3375f..c9ccb46 100644 --- a/Correlator/DataService/AudioServiceImpl.cs +++ b/Correlator/DataService/AudioServiceImpl.cs @@ -9,16 +9,17 @@ public class AudioServiceImpl : IAudioService { private bool _isStopped; + private WaveFormat _waveFormat; private WaveFileWriter _waveFileWriter; private BufferedWaveProvider _waveProvider; - private readonly WaveFormat _waveFormat = new WaveFormat(7500, 24, 1); public WaveOutEvent Wave { get; set; } = new WaveOutEvent(); - public void Start(string deviceCode) + public void Start(string deviceCode, int sampleRate) { _isStopped = false; + _waveFormat = new WaveFormat(sampleRate, 24, 1); _waveProvider = new BufferedWaveProvider(_waveFormat); Wave.Init(_waveProvider); diff --git a/Correlator/DataService/CommandServiceImpl.cs b/Correlator/DataService/CommandServiceImpl.cs new file mode 100644 index 0000000..28e3402 --- /dev/null +++ b/Correlator/DataService/CommandServiceImpl.cs @@ -0,0 +1,614 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO.Ports; +using Correlator.Model; +using Correlator.Util; + +namespace Correlator.DataService +{ + public class CommandServiceImpl : ICommandService + { + public void SendCorrelatorWakeUpCmd(SerialPort sp) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + byte[] btDevId = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //广播模式,设备类型不解析 + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + const short pduTypeByte = 2; + var operateType = (short)(pduTypeByte & 0x7F); + + var pdu = (short)(2688 + operateType); //0X0A80 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oid = { 0x30, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00 }; + + byte[] totalLen = { 0x00, 0x13 }; + + //wrap the whole data + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + oid.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oid.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发加速度计数据采集指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendHydrophoneWakeUpCmd(SerialPort sp) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + //后续到CRC字段前的字节总长度(不包括长度字段和CRC字段)。 + byte[] totalLen = { 0x00, 0x1F }; + + byte[] btDevId = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //广播模式,设备类型不解析 + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 2688 + operateType; //0X0A80 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oidTag = + { + 0x40, 0x00, 0x00, 0x01, + 0x00, 0x01, + 0x00 + }; + + //获取时间(年-月-日-时-分-秒),年号-2000 + RuntimeCache.HydrophoneWakeUpTimestamp = new[] + { + CalendarHub.Year, CalendarHub.Mon, CalendarHub.Day, CalendarHub.Hor, CalendarHub.Min, + CalendarHub.Sec + }; + byte[] timeTag = + { + 0x10, 0x00, 0x00, 0x51, + 0x00, 0x06, + RuntimeCache.HydrophoneWakeUpTimestamp[0], RuntimeCache.HydrophoneWakeUpTimestamp[1], + RuntimeCache.HydrophoneWakeUpTimestamp[2], RuntimeCache.HydrophoneWakeUpTimestamp[3], + RuntimeCache.HydrophoneWakeUpTimestamp[4], RuntimeCache.HydrophoneWakeUpTimestamp[5] + }; //时间oid + + //wrap the whole data + var result = new byte[35]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oidTag.CopyTo(result, 16); + timeTag.CopyTo(result, 23); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发水听器数据采集指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void StartCheckResponse(SerialPort sp, string devCode) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + //后续到CRC字段前的字节总长度(不包括长度字段和CRC字段)。 + byte[] totalLen = { 0x00, 0x1F }; + + var btDevId = new byte[6]; + btDevId[0] = byte.Parse(devCode.Substring(0, 2), NumberStyles.HexNumber); + btDevId[1] = byte.Parse(devCode.Substring(2, 2), NumberStyles.HexNumber); + btDevId[2] = byte.Parse(devCode.Substring(4, 2), NumberStyles.HexNumber); + btDevId[3] = byte.Parse(devCode.Substring(6, 2), NumberStyles.HexNumber); + btDevId[4] = byte.Parse(devCode.Substring(8, 2), NumberStyles.HexNumber); + btDevId[5] = byte.Parse(devCode.Substring(10, 2), NumberStyles.HexNumber); + + //通信方式 + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + byte[] btPdu = { 0x01, 0x82 }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oidTag = + { + 0x40, 0x00, 0x00, 0x02, + 0x00, 0x01, + 0x00 + }; + + byte[] timeTag = + { + 0x10, 0x00, 0x00, 0x51, + 0x00, 0x06, + RuntimeCache.HydrophoneWakeUpTimestamp[0], RuntimeCache.HydrophoneWakeUpTimestamp[1], + RuntimeCache.HydrophoneWakeUpTimestamp[2], RuntimeCache.HydrophoneWakeUpTimestamp[3], + RuntimeCache.HydrophoneWakeUpTimestamp[4], RuntimeCache.HydrophoneWakeUpTimestamp[5] + }; //时间oid + + //wrap the whole data + var result = new byte[35]; + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oidTag.CopyTo(result, 16); + timeTag.CopyTo(result, 23); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发水听器点名指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendDataCheckResultCmd(SerialPort sp, string devCode, List indexArray) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + //后续到CRC字段前的字节总长度(不包括长度字段和CRC字段)。 + byte[] totalLen = { 0x00, 0x26 }; + + var btDevId = new byte[6]; + btDevId[0] = byte.Parse(devCode.Substring(0, 2), NumberStyles.HexNumber); + btDevId[1] = byte.Parse(devCode.Substring(2, 2), NumberStyles.HexNumber); + btDevId[2] = byte.Parse(devCode.Substring(4, 2), NumberStyles.HexNumber); + btDevId[3] = byte.Parse(devCode.Substring(6, 2), NumberStyles.HexNumber); + btDevId[4] = byte.Parse(devCode.Substring(8, 2), NumberStyles.HexNumber); + btDevId[5] = byte.Parse(devCode.Substring(10, 2), NumberStyles.HexNumber); + + //通信方式 + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + byte[] btPdu = { 0x05, 0x82 }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + //check result tag + var byteArray = indexArray.ToByteArray(); + byte[] oidTag = + { + 0x60, 0x00, 0x03, 0x00, + 0x00, 0x08, + byteArray[0], byteArray[1], byteArray[2], byteArray[3], + byteArray[4], byteArray[5], byteArray[6], byteArray[7] + }; + + byte[] timeTag = + { + 0x10, 0x00, 0x00, 0x51, + 0x00, 0x06, + RuntimeCache.HydrophoneWakeUpTimestamp[0], RuntimeCache.HydrophoneWakeUpTimestamp[1], + RuntimeCache.HydrophoneWakeUpTimestamp[2], RuntimeCache.HydrophoneWakeUpTimestamp[3], + RuntimeCache.HydrophoneWakeUpTimestamp[4], RuntimeCache.HydrophoneWakeUpTimestamp[5] + }; //时间oid + + //wrap the whole data + var result = new byte[42]; + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oidTag.CopyTo(result, 16); + timeTag.CopyTo(result, 30); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发水听器检查指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendCellAndStatusCollectCmd(SerialPort sp, byte devId) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + byte[] btDevId = { 0x21, 0x17, 0x00, 0x08, 0x22, devId }; //广播模式,设备类型不解析 + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0x22, devId }; + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 2688 + operateType; //0X0A80 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oid = { 0x60, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00 }; + + byte[] totalLen = { 0x00, 0x13 }; + + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + oid.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oid.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "设备 " + devId + " 下发状态采集指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendSoundCollectCmd(SerialPort sp, string devCode) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + //byte[] btDevId = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //广播模式,设备类型不解析 + var btDevId = new byte[6]; + btDevId[0] = byte.Parse(devCode.Substring(0, 2), NumberStyles.HexNumber); + btDevId[1] = byte.Parse(devCode.Substring(2, 2), NumberStyles.HexNumber); + btDevId[2] = byte.Parse(devCode.Substring(4, 2), NumberStyles.HexNumber); + btDevId[3] = byte.Parse(devCode.Substring(6, 2), NumberStyles.HexNumber); + btDevId[4] = byte.Parse(devCode.Substring(8, 2), NumberStyles.HexNumber); + btDevId[5] = byte.Parse(devCode.Substring(10, 2), NumberStyles.HexNumber); + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + var dstNodeAddr = devCode.Substring(8); //2个字节 ** ****** **** + var btDstNode = new byte[2]; + btDstNode[0] = byte.Parse(dstNodeAddr.Substring(0, 2), NumberStyles.HexNumber); + btDstNode[1] = byte.Parse(dstNodeAddr.Substring(2, 2), NumberStyles.HexNumber); + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 2688 + operateType; + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + //第一个Tag的Oid为“0x30000001”,第二个Tag为时间戳,Oid为“0x10000051”,内容为“年、月、日、时、分、秒” + byte[] oid = { 0x20, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00 }; //Tag1 + + byte[] totalLen = { 0x00, 0x13 }; + + //wrap the whole data + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + oid.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oid.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发听音指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendSoundStopCmd(SerialPort sp, string devCode) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + var btDevId = new byte[6]; + btDevId[0] = byte.Parse(devCode.Substring(0, 2), NumberStyles.HexNumber); + btDevId[1] = byte.Parse(devCode.Substring(2, 2), NumberStyles.HexNumber); + btDevId[2] = byte.Parse(devCode.Substring(4, 2), NumberStyles.HexNumber); + btDevId[3] = byte.Parse(devCode.Substring(6, 2), NumberStyles.HexNumber); + btDevId[4] = byte.Parse(devCode.Substring(8, 2), NumberStyles.HexNumber); + btDevId[5] = byte.Parse(devCode.Substring(10, 2), NumberStyles.HexNumber); + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + var dstNodeAddr = devCode.Substring(8); //2个字节 ** ****** **** + var btDstNode = new byte[2]; + btDstNode[0] = byte.Parse(dstNodeAddr.Substring(0, 2), NumberStyles.HexNumber); + btDstNode[1] = byte.Parse(dstNodeAddr.Substring(2, 2), NumberStyles.HexNumber); + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 1408 + operateType; //0x0582 TrapResponse+z噪声记录仪 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] sysTag = + { + 0x10, 0x00, 0x00, 0x51, 0x00, 0x06, + CalendarHub.Year, CalendarHub.Mon, CalendarHub.Day, CalendarHub.Hor, CalendarHub.Min, + CalendarHub.Sec + }; //Tag2 + + byte[] totalLen = { 0x00, 0x18 }; + + //wrap the whole data + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + sysTag.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + sysTag.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发听音结束指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendCorrelatorRangingCmd(SerialPort sp) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + byte[] btDevId = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //广播模式,设备类型不解析 + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 2688 + operateType; //0X0A80 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oid = { 0x30, 0x00, 0x00, 0x01, 0x00, 0x01, 0x99 }; + + byte[] totalLen = { 0x00, 0x13 }; + + //wrap the whole data + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + oid.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oid.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发相关仪测距指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + private CommandModel _lastCommand; + + public CommandModel GetLastCommand() + { + return _lastCommand; + } + } +} \ No newline at end of file diff --git a/Correlator/DataService/IApplicationDataService.cs b/Correlator/DataService/IApplicationDataService.cs index c2c29a7..f232681 100644 --- a/Correlator/DataService/IApplicationDataService.cs +++ b/Correlator/DataService/IApplicationDataService.cs @@ -8,7 +8,7 @@ public interface IApplicationDataService { ObservableCollection GetPipeMaterial(); - + ObservableCollection GetVelocityCollection(string materialName); void DeleteVelocity(MaterialVelocity velocity); @@ -26,11 +26,31 @@ int GetSoundVelocity(string material, int pipeDiameter); AudioVisualizer GetAudioVisualizer(int waveDataSize); - + /// /// 获取 HSV 中所有的基础颜色 (饱和度和明度均为最大值) /// /// 所有的 HSV 基础颜色(共 256 * 6 个, 并且随着索引增加, 颜色也会渐变) Color[] GetAllHsvColors(); + + /// + /// 加载所有工作模式的采样率 + /// + /// + ObservableCollection GetSampleRate(); + + /// + /// 根据工作模式获取采样率 + /// + /// + /// + int GetSampleRateByWorkMode(int mode); + + /// + /// 更新采样率 + /// + /// + /// + void UpdateSampleRate(int mode, int sampleRate); } } \ No newline at end of file diff --git a/Correlator/DataService/IAudioService.cs b/Correlator/DataService/IAudioService.cs index 3295b74..9bf2316 100644 --- a/Correlator/DataService/IAudioService.cs +++ b/Correlator/DataService/IAudioService.cs @@ -11,7 +11,8 @@ /// 开始听音 /// /// - void Start(string deviceCode); + /// + void Start(string deviceCode, int sampleRate); /// /// 缓存听音数据 diff --git a/Correlator/DataService/ICommandService.cs b/Correlator/DataService/ICommandService.cs new file mode 100644 index 0000000..d3d2c53 --- /dev/null +++ b/Correlator/DataService/ICommandService.cs @@ -0,0 +1,69 @@ +using System.Collections.Generic; +using System.IO.Ports; +using Correlator.Model; + +namespace Correlator.DataService +{ + public interface ICommandService + { + /// + /// 下发唤醒指令-加速度计 + /// + /// + void SendCorrelatorWakeUpCmd(SerialPort sp); + + /// + /// 下发唤醒指令-水听器 + /// + /// + void SendHydrophoneWakeUpCmd(SerialPort sp); + + /// + /// 水听器点名指令 + /// + /// + /// + void StartCheckResponse(SerialPort sp, string devCode); + + /// + /// 发送校验结果指令给下位机 + /// + /// + /// + /// 异常数据角标集合 + void SendDataCheckResultCmd(SerialPort sp, string devCode, List indexArray); + + /// + /// 下发状态采集指令 + /// + /// + /// + void SendCellAndStatusCollectCmd(SerialPort sp, byte devId); + + /// + /// 下发听音指令 + /// + /// + /// + void SendSoundCollectCmd(SerialPort sp, string devCode); + + /// + /// 下发听音停止指令 + /// + /// + /// + void SendSoundStopCmd(SerialPort sp, string devCode); + + /// + /// 下发测距指令 + /// + /// + void SendCorrelatorRangingCmd(SerialPort sp); + + /// + /// 获取最新下发指令集合 + /// + /// + CommandModel GetLastCommand(); + } +} \ No newline at end of file diff --git a/Correlator/DataService/SerialPortServiceImpl.cs b/Correlator/DataService/SerialPortServiceImpl.cs index e18210e..364ee77 100644 --- a/Correlator/DataService/SerialPortServiceImpl.cs +++ b/Correlator/DataService/SerialPortServiceImpl.cs @@ -15,6 +15,8 @@ { private readonly IEventAggregator _eventAggregator; private readonly IAudioService _audioService; + private readonly ICommandService _commandService; + private readonly IApplicationDataService _dataService; private readonly DevStatus _devStatus = new DevStatus(); private int _checkResponseState; @@ -23,10 +25,14 @@ //左右传感器设备数据 private CorrelatorDataModel _dataModel; - public SerialPortServiceImpl(IEventAggregator eventAggregator, IAudioService audioService) + public SerialPortServiceImpl(IEventAggregator eventAggregator, IAudioService audioService, + ICommandService commandService, IApplicationDataService dataService) { _eventAggregator = eventAggregator; _audioService = audioService; + _commandService = commandService; + _dataService = dataService; + Sp.DataReceived += delegate { while (Sp.BytesToRead < 4) @@ -264,6 +270,7 @@ private void HandleListenData(List tags) { + var sampleRate = _dataService.GetSampleRateByWorkMode(RuntimeCache.WorkMode); //处理接到的噪声数据 var noiseTag = tags.GetUploadNoiseTag(); if (noiseTag != null) @@ -283,9 +290,9 @@ } //PCM数据 - var pcm = new byte[7500 * 3]; //每个采样点2字节 + var pcm = new byte[sampleRate * 3]; //每个采样点2字节 - for (var i = 0; i < 7500; i++) + for (var i = 0; i < sampleRate; i++) { pcm[i * 3 + 2] = dataValue[i * 2 + 0]; pcm[i * 3 + 1] = dataValue[i * 2 + 1]; @@ -357,7 +364,7 @@ } var devId = !RuntimeCache.RedSensorIsEnable ? (byte)0x01 : (byte)0x02; - CommandSender.SendCellAndStatusCollectCmd(Sp, devId); + _commandService.SendCellAndStatusCollectCmd(Sp, devId); Sp.Write("ATA" + Environment.NewLine); } } diff --git a/Correlator/Dialog/CheckResponseDialog.xaml.cs b/Correlator/Dialog/CheckResponseDialog.xaml.cs index 72fd7b6..2cf2c01 100644 --- a/Correlator/Dialog/CheckResponseDialog.xaml.cs +++ b/Correlator/Dialog/CheckResponseDialog.xaml.cs @@ -45,15 +45,17 @@ private readonly IEventAggregator _eventAggregator; private readonly ISerialPortService _serialPortService; private readonly IDialogService _dialogService; + private readonly ICommandService _commandService; public CheckResponseDialog(IEventAggregator eventAggregator, ISerialPortService serialPortService, - IDialogService dialogService) + IDialogService dialogService, ICommandService commandService) { InitializeComponent(); _eventAggregator = eventAggregator; _serialPortService = serialPortService; _dialogService = dialogService; + _commandService = commandService; var today = DateTime.Now.ToString("yyyyMMdd"); var configModel = LazyDataBase.Value.Table() @@ -218,7 +220,7 @@ if (RedSensorStepBar.StepIndex == 1) { RuntimeCache.SeqCaches.Clear(); - CommandSender.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev1); + _commandService.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev1); _redResponseTimer.Start(); ReCheckButton.IsEnabled = true; @@ -226,7 +228,7 @@ else if (RedSensorStepBar.StepIndex == 2) { //下发数据全部正常指令 - CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, new List()); + _commandService.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, new List()); #region 保存原始数据 @@ -295,14 +297,14 @@ if (BlueSensorStepBar.StepIndex == 1) { RuntimeCache.SeqCaches.Clear(); - CommandSender.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev2); + _commandService.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev2); _blueResponseTimer.Start(); ReCheckButton.IsEnabled = true; } else if (BlueSensorStepBar.StepIndex == 2) { - CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, new List()); + _commandService.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, new List()); #region 保存原始数据 @@ -376,7 +378,7 @@ } } - CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, redIndexArray); + _commandService.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, redIndexArray); } else { @@ -397,7 +399,7 @@ } } - CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, blueIndexArray); + _commandService.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, blueIndexArray); } }; } diff --git a/Correlator/Dialog/EditSoundSampleRateDialog.xaml b/Correlator/Dialog/EditSoundSampleRateDialog.xaml new file mode 100644 index 0000000..d441270 --- /dev/null +++ b/Correlator/Dialog/EditSoundSampleRateDialog.xaml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + /// - void Start(string deviceCode); + /// + void Start(string deviceCode, int sampleRate); /// /// 缓存听音数据 diff --git a/Correlator/DataService/ICommandService.cs b/Correlator/DataService/ICommandService.cs new file mode 100644 index 0000000..d3d2c53 --- /dev/null +++ b/Correlator/DataService/ICommandService.cs @@ -0,0 +1,69 @@ +using System.Collections.Generic; +using System.IO.Ports; +using Correlator.Model; + +namespace Correlator.DataService +{ + public interface ICommandService + { + /// + /// 下发唤醒指令-加速度计 + /// + /// + void SendCorrelatorWakeUpCmd(SerialPort sp); + + /// + /// 下发唤醒指令-水听器 + /// + /// + void SendHydrophoneWakeUpCmd(SerialPort sp); + + /// + /// 水听器点名指令 + /// + /// + /// + void StartCheckResponse(SerialPort sp, string devCode); + + /// + /// 发送校验结果指令给下位机 + /// + /// + /// + /// 异常数据角标集合 + void SendDataCheckResultCmd(SerialPort sp, string devCode, List indexArray); + + /// + /// 下发状态采集指令 + /// + /// + /// + void SendCellAndStatusCollectCmd(SerialPort sp, byte devId); + + /// + /// 下发听音指令 + /// + /// + /// + void SendSoundCollectCmd(SerialPort sp, string devCode); + + /// + /// 下发听音停止指令 + /// + /// + /// + void SendSoundStopCmd(SerialPort sp, string devCode); + + /// + /// 下发测距指令 + /// + /// + void SendCorrelatorRangingCmd(SerialPort sp); + + /// + /// 获取最新下发指令集合 + /// + /// + CommandModel GetLastCommand(); + } +} \ No newline at end of file diff --git a/Correlator/DataService/SerialPortServiceImpl.cs b/Correlator/DataService/SerialPortServiceImpl.cs index e18210e..364ee77 100644 --- a/Correlator/DataService/SerialPortServiceImpl.cs +++ b/Correlator/DataService/SerialPortServiceImpl.cs @@ -15,6 +15,8 @@ { private readonly IEventAggregator _eventAggregator; private readonly IAudioService _audioService; + private readonly ICommandService _commandService; + private readonly IApplicationDataService _dataService; private readonly DevStatus _devStatus = new DevStatus(); private int _checkResponseState; @@ -23,10 +25,14 @@ //左右传感器设备数据 private CorrelatorDataModel _dataModel; - public SerialPortServiceImpl(IEventAggregator eventAggregator, IAudioService audioService) + public SerialPortServiceImpl(IEventAggregator eventAggregator, IAudioService audioService, + ICommandService commandService, IApplicationDataService dataService) { _eventAggregator = eventAggregator; _audioService = audioService; + _commandService = commandService; + _dataService = dataService; + Sp.DataReceived += delegate { while (Sp.BytesToRead < 4) @@ -264,6 +270,7 @@ private void HandleListenData(List tags) { + var sampleRate = _dataService.GetSampleRateByWorkMode(RuntimeCache.WorkMode); //处理接到的噪声数据 var noiseTag = tags.GetUploadNoiseTag(); if (noiseTag != null) @@ -283,9 +290,9 @@ } //PCM数据 - var pcm = new byte[7500 * 3]; //每个采样点2字节 + var pcm = new byte[sampleRate * 3]; //每个采样点2字节 - for (var i = 0; i < 7500; i++) + for (var i = 0; i < sampleRate; i++) { pcm[i * 3 + 2] = dataValue[i * 2 + 0]; pcm[i * 3 + 1] = dataValue[i * 2 + 1]; @@ -357,7 +364,7 @@ } var devId = !RuntimeCache.RedSensorIsEnable ? (byte)0x01 : (byte)0x02; - CommandSender.SendCellAndStatusCollectCmd(Sp, devId); + _commandService.SendCellAndStatusCollectCmd(Sp, devId); Sp.Write("ATA" + Environment.NewLine); } } diff --git a/Correlator/Dialog/CheckResponseDialog.xaml.cs b/Correlator/Dialog/CheckResponseDialog.xaml.cs index 72fd7b6..2cf2c01 100644 --- a/Correlator/Dialog/CheckResponseDialog.xaml.cs +++ b/Correlator/Dialog/CheckResponseDialog.xaml.cs @@ -45,15 +45,17 @@ private readonly IEventAggregator _eventAggregator; private readonly ISerialPortService _serialPortService; private readonly IDialogService _dialogService; + private readonly ICommandService _commandService; public CheckResponseDialog(IEventAggregator eventAggregator, ISerialPortService serialPortService, - IDialogService dialogService) + IDialogService dialogService, ICommandService commandService) { InitializeComponent(); _eventAggregator = eventAggregator; _serialPortService = serialPortService; _dialogService = dialogService; + _commandService = commandService; var today = DateTime.Now.ToString("yyyyMMdd"); var configModel = LazyDataBase.Value.Table() @@ -218,7 +220,7 @@ if (RedSensorStepBar.StepIndex == 1) { RuntimeCache.SeqCaches.Clear(); - CommandSender.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev1); + _commandService.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev1); _redResponseTimer.Start(); ReCheckButton.IsEnabled = true; @@ -226,7 +228,7 @@ else if (RedSensorStepBar.StepIndex == 2) { //下发数据全部正常指令 - CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, new List()); + _commandService.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, new List()); #region 保存原始数据 @@ -295,14 +297,14 @@ if (BlueSensorStepBar.StepIndex == 1) { RuntimeCache.SeqCaches.Clear(); - CommandSender.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev2); + _commandService.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev2); _blueResponseTimer.Start(); ReCheckButton.IsEnabled = true; } else if (BlueSensorStepBar.StepIndex == 2) { - CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, new List()); + _commandService.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, new List()); #region 保存原始数据 @@ -376,7 +378,7 @@ } } - CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, redIndexArray); + _commandService.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, redIndexArray); } else { @@ -397,7 +399,7 @@ } } - CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, blueIndexArray); + _commandService.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, blueIndexArray); } }; } diff --git a/Correlator/Dialog/EditSoundSampleRateDialog.xaml b/Correlator/Dialog/EditSoundSampleRateDialog.xaml new file mode 100644 index 0000000..d441270 --- /dev/null +++ b/Correlator/Dialog/EditSoundSampleRateDialog.xaml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + /// - void Start(string deviceCode); + /// + void Start(string deviceCode, int sampleRate); /// /// 缓存听音数据 diff --git a/Correlator/DataService/ICommandService.cs b/Correlator/DataService/ICommandService.cs new file mode 100644 index 0000000..d3d2c53 --- /dev/null +++ b/Correlator/DataService/ICommandService.cs @@ -0,0 +1,69 @@ +using System.Collections.Generic; +using System.IO.Ports; +using Correlator.Model; + +namespace Correlator.DataService +{ + public interface ICommandService + { + /// + /// 下发唤醒指令-加速度计 + /// + /// + void SendCorrelatorWakeUpCmd(SerialPort sp); + + /// + /// 下发唤醒指令-水听器 + /// + /// + void SendHydrophoneWakeUpCmd(SerialPort sp); + + /// + /// 水听器点名指令 + /// + /// + /// + void StartCheckResponse(SerialPort sp, string devCode); + + /// + /// 发送校验结果指令给下位机 + /// + /// + /// + /// 异常数据角标集合 + void SendDataCheckResultCmd(SerialPort sp, string devCode, List indexArray); + + /// + /// 下发状态采集指令 + /// + /// + /// + void SendCellAndStatusCollectCmd(SerialPort sp, byte devId); + + /// + /// 下发听音指令 + /// + /// + /// + void SendSoundCollectCmd(SerialPort sp, string devCode); + + /// + /// 下发听音停止指令 + /// + /// + /// + void SendSoundStopCmd(SerialPort sp, string devCode); + + /// + /// 下发测距指令 + /// + /// + void SendCorrelatorRangingCmd(SerialPort sp); + + /// + /// 获取最新下发指令集合 + /// + /// + CommandModel GetLastCommand(); + } +} \ No newline at end of file diff --git a/Correlator/DataService/SerialPortServiceImpl.cs b/Correlator/DataService/SerialPortServiceImpl.cs index e18210e..364ee77 100644 --- a/Correlator/DataService/SerialPortServiceImpl.cs +++ b/Correlator/DataService/SerialPortServiceImpl.cs @@ -15,6 +15,8 @@ { private readonly IEventAggregator _eventAggregator; private readonly IAudioService _audioService; + private readonly ICommandService _commandService; + private readonly IApplicationDataService _dataService; private readonly DevStatus _devStatus = new DevStatus(); private int _checkResponseState; @@ -23,10 +25,14 @@ //左右传感器设备数据 private CorrelatorDataModel _dataModel; - public SerialPortServiceImpl(IEventAggregator eventAggregator, IAudioService audioService) + public SerialPortServiceImpl(IEventAggregator eventAggregator, IAudioService audioService, + ICommandService commandService, IApplicationDataService dataService) { _eventAggregator = eventAggregator; _audioService = audioService; + _commandService = commandService; + _dataService = dataService; + Sp.DataReceived += delegate { while (Sp.BytesToRead < 4) @@ -264,6 +270,7 @@ private void HandleListenData(List tags) { + var sampleRate = _dataService.GetSampleRateByWorkMode(RuntimeCache.WorkMode); //处理接到的噪声数据 var noiseTag = tags.GetUploadNoiseTag(); if (noiseTag != null) @@ -283,9 +290,9 @@ } //PCM数据 - var pcm = new byte[7500 * 3]; //每个采样点2字节 + var pcm = new byte[sampleRate * 3]; //每个采样点2字节 - for (var i = 0; i < 7500; i++) + for (var i = 0; i < sampleRate; i++) { pcm[i * 3 + 2] = dataValue[i * 2 + 0]; pcm[i * 3 + 1] = dataValue[i * 2 + 1]; @@ -357,7 +364,7 @@ } var devId = !RuntimeCache.RedSensorIsEnable ? (byte)0x01 : (byte)0x02; - CommandSender.SendCellAndStatusCollectCmd(Sp, devId); + _commandService.SendCellAndStatusCollectCmd(Sp, devId); Sp.Write("ATA" + Environment.NewLine); } } diff --git a/Correlator/Dialog/CheckResponseDialog.xaml.cs b/Correlator/Dialog/CheckResponseDialog.xaml.cs index 72fd7b6..2cf2c01 100644 --- a/Correlator/Dialog/CheckResponseDialog.xaml.cs +++ b/Correlator/Dialog/CheckResponseDialog.xaml.cs @@ -45,15 +45,17 @@ private readonly IEventAggregator _eventAggregator; private readonly ISerialPortService _serialPortService; private readonly IDialogService _dialogService; + private readonly ICommandService _commandService; public CheckResponseDialog(IEventAggregator eventAggregator, ISerialPortService serialPortService, - IDialogService dialogService) + IDialogService dialogService, ICommandService commandService) { InitializeComponent(); _eventAggregator = eventAggregator; _serialPortService = serialPortService; _dialogService = dialogService; + _commandService = commandService; var today = DateTime.Now.ToString("yyyyMMdd"); var configModel = LazyDataBase.Value.Table() @@ -218,7 +220,7 @@ if (RedSensorStepBar.StepIndex == 1) { RuntimeCache.SeqCaches.Clear(); - CommandSender.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev1); + _commandService.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev1); _redResponseTimer.Start(); ReCheckButton.IsEnabled = true; @@ -226,7 +228,7 @@ else if (RedSensorStepBar.StepIndex == 2) { //下发数据全部正常指令 - CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, new List()); + _commandService.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, new List()); #region 保存原始数据 @@ -295,14 +297,14 @@ if (BlueSensorStepBar.StepIndex == 1) { RuntimeCache.SeqCaches.Clear(); - CommandSender.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev2); + _commandService.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev2); _blueResponseTimer.Start(); ReCheckButton.IsEnabled = true; } else if (BlueSensorStepBar.StepIndex == 2) { - CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, new List()); + _commandService.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, new List()); #region 保存原始数据 @@ -376,7 +378,7 @@ } } - CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, redIndexArray); + _commandService.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, redIndexArray); } else { @@ -397,7 +399,7 @@ } } - CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, blueIndexArray); + _commandService.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, blueIndexArray); } }; } diff --git a/Correlator/Dialog/EditSoundSampleRateDialog.xaml b/Correlator/Dialog/EditSoundSampleRateDialog.xaml new file mode 100644 index 0000000..d441270 --- /dev/null +++ b/Correlator/Dialog/EditSoundSampleRateDialog.xaml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + /// - void Start(string deviceCode); + /// + void Start(string deviceCode, int sampleRate); /// /// 缓存听音数据 diff --git a/Correlator/DataService/ICommandService.cs b/Correlator/DataService/ICommandService.cs new file mode 100644 index 0000000..d3d2c53 --- /dev/null +++ b/Correlator/DataService/ICommandService.cs @@ -0,0 +1,69 @@ +using System.Collections.Generic; +using System.IO.Ports; +using Correlator.Model; + +namespace Correlator.DataService +{ + public interface ICommandService + { + /// + /// 下发唤醒指令-加速度计 + /// + /// + void SendCorrelatorWakeUpCmd(SerialPort sp); + + /// + /// 下发唤醒指令-水听器 + /// + /// + void SendHydrophoneWakeUpCmd(SerialPort sp); + + /// + /// 水听器点名指令 + /// + /// + /// + void StartCheckResponse(SerialPort sp, string devCode); + + /// + /// 发送校验结果指令给下位机 + /// + /// + /// + /// 异常数据角标集合 + void SendDataCheckResultCmd(SerialPort sp, string devCode, List indexArray); + + /// + /// 下发状态采集指令 + /// + /// + /// + void SendCellAndStatusCollectCmd(SerialPort sp, byte devId); + + /// + /// 下发听音指令 + /// + /// + /// + void SendSoundCollectCmd(SerialPort sp, string devCode); + + /// + /// 下发听音停止指令 + /// + /// + /// + void SendSoundStopCmd(SerialPort sp, string devCode); + + /// + /// 下发测距指令 + /// + /// + void SendCorrelatorRangingCmd(SerialPort sp); + + /// + /// 获取最新下发指令集合 + /// + /// + CommandModel GetLastCommand(); + } +} \ No newline at end of file diff --git a/Correlator/DataService/SerialPortServiceImpl.cs b/Correlator/DataService/SerialPortServiceImpl.cs index e18210e..364ee77 100644 --- a/Correlator/DataService/SerialPortServiceImpl.cs +++ b/Correlator/DataService/SerialPortServiceImpl.cs @@ -15,6 +15,8 @@ { private readonly IEventAggregator _eventAggregator; private readonly IAudioService _audioService; + private readonly ICommandService _commandService; + private readonly IApplicationDataService _dataService; private readonly DevStatus _devStatus = new DevStatus(); private int _checkResponseState; @@ -23,10 +25,14 @@ //左右传感器设备数据 private CorrelatorDataModel _dataModel; - public SerialPortServiceImpl(IEventAggregator eventAggregator, IAudioService audioService) + public SerialPortServiceImpl(IEventAggregator eventAggregator, IAudioService audioService, + ICommandService commandService, IApplicationDataService dataService) { _eventAggregator = eventAggregator; _audioService = audioService; + _commandService = commandService; + _dataService = dataService; + Sp.DataReceived += delegate { while (Sp.BytesToRead < 4) @@ -264,6 +270,7 @@ private void HandleListenData(List tags) { + var sampleRate = _dataService.GetSampleRateByWorkMode(RuntimeCache.WorkMode); //处理接到的噪声数据 var noiseTag = tags.GetUploadNoiseTag(); if (noiseTag != null) @@ -283,9 +290,9 @@ } //PCM数据 - var pcm = new byte[7500 * 3]; //每个采样点2字节 + var pcm = new byte[sampleRate * 3]; //每个采样点2字节 - for (var i = 0; i < 7500; i++) + for (var i = 0; i < sampleRate; i++) { pcm[i * 3 + 2] = dataValue[i * 2 + 0]; pcm[i * 3 + 1] = dataValue[i * 2 + 1]; @@ -357,7 +364,7 @@ } var devId = !RuntimeCache.RedSensorIsEnable ? (byte)0x01 : (byte)0x02; - CommandSender.SendCellAndStatusCollectCmd(Sp, devId); + _commandService.SendCellAndStatusCollectCmd(Sp, devId); Sp.Write("ATA" + Environment.NewLine); } } diff --git a/Correlator/Dialog/CheckResponseDialog.xaml.cs b/Correlator/Dialog/CheckResponseDialog.xaml.cs index 72fd7b6..2cf2c01 100644 --- a/Correlator/Dialog/CheckResponseDialog.xaml.cs +++ b/Correlator/Dialog/CheckResponseDialog.xaml.cs @@ -45,15 +45,17 @@ private readonly IEventAggregator _eventAggregator; private readonly ISerialPortService _serialPortService; private readonly IDialogService _dialogService; + private readonly ICommandService _commandService; public CheckResponseDialog(IEventAggregator eventAggregator, ISerialPortService serialPortService, - IDialogService dialogService) + IDialogService dialogService, ICommandService commandService) { InitializeComponent(); _eventAggregator = eventAggregator; _serialPortService = serialPortService; _dialogService = dialogService; + _commandService = commandService; var today = DateTime.Now.ToString("yyyyMMdd"); var configModel = LazyDataBase.Value.Table() @@ -218,7 +220,7 @@ if (RedSensorStepBar.StepIndex == 1) { RuntimeCache.SeqCaches.Clear(); - CommandSender.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev1); + _commandService.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev1); _redResponseTimer.Start(); ReCheckButton.IsEnabled = true; @@ -226,7 +228,7 @@ else if (RedSensorStepBar.StepIndex == 2) { //下发数据全部正常指令 - CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, new List()); + _commandService.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, new List()); #region 保存原始数据 @@ -295,14 +297,14 @@ if (BlueSensorStepBar.StepIndex == 1) { RuntimeCache.SeqCaches.Clear(); - CommandSender.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev2); + _commandService.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev2); _blueResponseTimer.Start(); ReCheckButton.IsEnabled = true; } else if (BlueSensorStepBar.StepIndex == 2) { - CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, new List()); + _commandService.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, new List()); #region 保存原始数据 @@ -376,7 +378,7 @@ } } - CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, redIndexArray); + _commandService.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, redIndexArray); } else { @@ -397,7 +399,7 @@ } } - CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, blueIndexArray); + _commandService.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, blueIndexArray); } }; } diff --git a/Correlator/Dialog/EditSoundSampleRateDialog.xaml b/Correlator/Dialog/EditSoundSampleRateDialog.xaml new file mode 100644 index 0000000..d441270 --- /dev/null +++ b/Correlator/Dialog/EditSoundSampleRateDialog.xaml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Correlator/App.xaml.cs b/Correlator/App.xaml.cs index 5c9dd37..c66d198 100644 --- a/Correlator/App.xaml.cs +++ b/Correlator/App.xaml.cs @@ -98,6 +98,7 @@ containerRegistry.RegisterSingleton(); containerRegistry.RegisterSingleton(); containerRegistry.RegisterSingleton(); + containerRegistry.RegisterSingleton(); //Dialog or Window containerRegistry.RegisterDialog(); @@ -105,6 +106,8 @@ containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); + containerRegistry.RegisterDialog(); + containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); diff --git a/Correlator/Converter/SoundParamValueConverter.cs b/Correlator/Converter/SoundParamValueConverter.cs new file mode 100644 index 0000000..4101a19 --- /dev/null +++ b/Correlator/Converter/SoundParamValueConverter.cs @@ -0,0 +1,26 @@ +using System; +using System.Globalization; +using System.Windows.Data; + +namespace Correlator.Converter +{ + public class SoundParamValueConverter : IMultiValueConverter + { + public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) + { + try + { + return "声速:" + values[0] + "m/s,采样率:" + values[1] + "Hz"; + } + catch (Exception) + { + return null; + } + } + + public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) + { + return null; + } + } +} \ No newline at end of file diff --git a/Correlator/Converter/WorkModeConverter.cs b/Correlator/Converter/WorkModeConverter.cs new file mode 100644 index 0000000..19d0327 --- /dev/null +++ b/Correlator/Converter/WorkModeConverter.cs @@ -0,0 +1,21 @@ +using System; +using System.Diagnostics; +using System.Globalization; +using System.Windows.Data; + +namespace Correlator.Converter +{ + internal class WorkModeConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + Debug.Assert(value != null, nameof(value) + " != null"); + return (int)value == 1 ? "加速度计" : "水听器"; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + return null; + } + } +} \ No newline at end of file diff --git a/Correlator/Correlator.csproj b/Correlator/Correlator.csproj index da299ba..c3a433a 100644 --- a/Correlator/Correlator.csproj +++ b/Correlator/Correlator.csproj @@ -216,10 +216,14 @@ + + + + @@ -240,6 +244,9 @@ DetectNoiseDialog.xaml + + EditSoundSampleRateDialog.xaml + EditSoundSpeedDialog.xaml @@ -249,7 +256,14 @@ LoadingDialog.xaml + + SoundSampleRateDialog.xaml + + + + + ApplicationLogView.xaml @@ -303,7 +317,6 @@ - @@ -343,12 +356,14 @@ MSBuild:Compile + Designer MSBuild:Compile + Designer diff --git a/Correlator/DataService/ApplicationDataServiceImpl.cs b/Correlator/DataService/ApplicationDataServiceImpl.cs index d3f9463..d7f0b68 100644 --- a/Correlator/DataService/ApplicationDataServiceImpl.cs +++ b/Correlator/DataService/ApplicationDataServiceImpl.cs @@ -104,7 +104,7 @@ { return new AudioVisualizer(waveDataSize); } - + public Color[] GetAllHsvColors() { var result = new Color[256 * 6]; @@ -141,5 +141,50 @@ return result; } + + public ObservableCollection GetSampleRate() + { + var sampleRateCollection = new ObservableCollection(); + using (var manager = new DataBaseManager()) + { + var result = manager + .Table() + .ToList(); + foreach (var model in result) + { + sampleRateCollection.Add(model); + } + } + + return sampleRateCollection; + } + + public int GetSampleRateByWorkMode(int mode) + { + using (var manager = new DataBaseManager()) + { + var result = manager + .Table() + .First(x => x.WorkMode == mode); + return result?.SampleRate ?? 7500; + } + } + + public void UpdateSampleRate(int mode, int sampleRate) + { + using (var manager = new DataBaseManager()) + { + var result = manager + .Table() + .First(x => x.WorkMode == mode); + var rateModel = result ?? new SampleRateModel(); + + rateModel.WorkMode = mode; + rateModel.SampleRate = sampleRate; + rateModel.UpdateDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); + + manager.Update(rateModel); + } + } } } \ No newline at end of file diff --git a/Correlator/DataService/AudioServiceImpl.cs b/Correlator/DataService/AudioServiceImpl.cs index fd3375f..c9ccb46 100644 --- a/Correlator/DataService/AudioServiceImpl.cs +++ b/Correlator/DataService/AudioServiceImpl.cs @@ -9,16 +9,17 @@ public class AudioServiceImpl : IAudioService { private bool _isStopped; + private WaveFormat _waveFormat; private WaveFileWriter _waveFileWriter; private BufferedWaveProvider _waveProvider; - private readonly WaveFormat _waveFormat = new WaveFormat(7500, 24, 1); public WaveOutEvent Wave { get; set; } = new WaveOutEvent(); - public void Start(string deviceCode) + public void Start(string deviceCode, int sampleRate) { _isStopped = false; + _waveFormat = new WaveFormat(sampleRate, 24, 1); _waveProvider = new BufferedWaveProvider(_waveFormat); Wave.Init(_waveProvider); diff --git a/Correlator/DataService/CommandServiceImpl.cs b/Correlator/DataService/CommandServiceImpl.cs new file mode 100644 index 0000000..28e3402 --- /dev/null +++ b/Correlator/DataService/CommandServiceImpl.cs @@ -0,0 +1,614 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO.Ports; +using Correlator.Model; +using Correlator.Util; + +namespace Correlator.DataService +{ + public class CommandServiceImpl : ICommandService + { + public void SendCorrelatorWakeUpCmd(SerialPort sp) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + byte[] btDevId = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //广播模式,设备类型不解析 + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + const short pduTypeByte = 2; + var operateType = (short)(pduTypeByte & 0x7F); + + var pdu = (short)(2688 + operateType); //0X0A80 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oid = { 0x30, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00 }; + + byte[] totalLen = { 0x00, 0x13 }; + + //wrap the whole data + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + oid.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oid.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发加速度计数据采集指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendHydrophoneWakeUpCmd(SerialPort sp) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + //后续到CRC字段前的字节总长度(不包括长度字段和CRC字段)。 + byte[] totalLen = { 0x00, 0x1F }; + + byte[] btDevId = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //广播模式,设备类型不解析 + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 2688 + operateType; //0X0A80 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oidTag = + { + 0x40, 0x00, 0x00, 0x01, + 0x00, 0x01, + 0x00 + }; + + //获取时间(年-月-日-时-分-秒),年号-2000 + RuntimeCache.HydrophoneWakeUpTimestamp = new[] + { + CalendarHub.Year, CalendarHub.Mon, CalendarHub.Day, CalendarHub.Hor, CalendarHub.Min, + CalendarHub.Sec + }; + byte[] timeTag = + { + 0x10, 0x00, 0x00, 0x51, + 0x00, 0x06, + RuntimeCache.HydrophoneWakeUpTimestamp[0], RuntimeCache.HydrophoneWakeUpTimestamp[1], + RuntimeCache.HydrophoneWakeUpTimestamp[2], RuntimeCache.HydrophoneWakeUpTimestamp[3], + RuntimeCache.HydrophoneWakeUpTimestamp[4], RuntimeCache.HydrophoneWakeUpTimestamp[5] + }; //时间oid + + //wrap the whole data + var result = new byte[35]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oidTag.CopyTo(result, 16); + timeTag.CopyTo(result, 23); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发水听器数据采集指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void StartCheckResponse(SerialPort sp, string devCode) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + //后续到CRC字段前的字节总长度(不包括长度字段和CRC字段)。 + byte[] totalLen = { 0x00, 0x1F }; + + var btDevId = new byte[6]; + btDevId[0] = byte.Parse(devCode.Substring(0, 2), NumberStyles.HexNumber); + btDevId[1] = byte.Parse(devCode.Substring(2, 2), NumberStyles.HexNumber); + btDevId[2] = byte.Parse(devCode.Substring(4, 2), NumberStyles.HexNumber); + btDevId[3] = byte.Parse(devCode.Substring(6, 2), NumberStyles.HexNumber); + btDevId[4] = byte.Parse(devCode.Substring(8, 2), NumberStyles.HexNumber); + btDevId[5] = byte.Parse(devCode.Substring(10, 2), NumberStyles.HexNumber); + + //通信方式 + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + byte[] btPdu = { 0x01, 0x82 }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oidTag = + { + 0x40, 0x00, 0x00, 0x02, + 0x00, 0x01, + 0x00 + }; + + byte[] timeTag = + { + 0x10, 0x00, 0x00, 0x51, + 0x00, 0x06, + RuntimeCache.HydrophoneWakeUpTimestamp[0], RuntimeCache.HydrophoneWakeUpTimestamp[1], + RuntimeCache.HydrophoneWakeUpTimestamp[2], RuntimeCache.HydrophoneWakeUpTimestamp[3], + RuntimeCache.HydrophoneWakeUpTimestamp[4], RuntimeCache.HydrophoneWakeUpTimestamp[5] + }; //时间oid + + //wrap the whole data + var result = new byte[35]; + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oidTag.CopyTo(result, 16); + timeTag.CopyTo(result, 23); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发水听器点名指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendDataCheckResultCmd(SerialPort sp, string devCode, List indexArray) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + //后续到CRC字段前的字节总长度(不包括长度字段和CRC字段)。 + byte[] totalLen = { 0x00, 0x26 }; + + var btDevId = new byte[6]; + btDevId[0] = byte.Parse(devCode.Substring(0, 2), NumberStyles.HexNumber); + btDevId[1] = byte.Parse(devCode.Substring(2, 2), NumberStyles.HexNumber); + btDevId[2] = byte.Parse(devCode.Substring(4, 2), NumberStyles.HexNumber); + btDevId[3] = byte.Parse(devCode.Substring(6, 2), NumberStyles.HexNumber); + btDevId[4] = byte.Parse(devCode.Substring(8, 2), NumberStyles.HexNumber); + btDevId[5] = byte.Parse(devCode.Substring(10, 2), NumberStyles.HexNumber); + + //通信方式 + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + byte[] btPdu = { 0x05, 0x82 }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + //check result tag + var byteArray = indexArray.ToByteArray(); + byte[] oidTag = + { + 0x60, 0x00, 0x03, 0x00, + 0x00, 0x08, + byteArray[0], byteArray[1], byteArray[2], byteArray[3], + byteArray[4], byteArray[5], byteArray[6], byteArray[7] + }; + + byte[] timeTag = + { + 0x10, 0x00, 0x00, 0x51, + 0x00, 0x06, + RuntimeCache.HydrophoneWakeUpTimestamp[0], RuntimeCache.HydrophoneWakeUpTimestamp[1], + RuntimeCache.HydrophoneWakeUpTimestamp[2], RuntimeCache.HydrophoneWakeUpTimestamp[3], + RuntimeCache.HydrophoneWakeUpTimestamp[4], RuntimeCache.HydrophoneWakeUpTimestamp[5] + }; //时间oid + + //wrap the whole data + var result = new byte[42]; + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oidTag.CopyTo(result, 16); + timeTag.CopyTo(result, 30); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发水听器检查指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendCellAndStatusCollectCmd(SerialPort sp, byte devId) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + byte[] btDevId = { 0x21, 0x17, 0x00, 0x08, 0x22, devId }; //广播模式,设备类型不解析 + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0x22, devId }; + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 2688 + operateType; //0X0A80 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oid = { 0x60, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00 }; + + byte[] totalLen = { 0x00, 0x13 }; + + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + oid.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oid.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "设备 " + devId + " 下发状态采集指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendSoundCollectCmd(SerialPort sp, string devCode) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + //byte[] btDevId = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //广播模式,设备类型不解析 + var btDevId = new byte[6]; + btDevId[0] = byte.Parse(devCode.Substring(0, 2), NumberStyles.HexNumber); + btDevId[1] = byte.Parse(devCode.Substring(2, 2), NumberStyles.HexNumber); + btDevId[2] = byte.Parse(devCode.Substring(4, 2), NumberStyles.HexNumber); + btDevId[3] = byte.Parse(devCode.Substring(6, 2), NumberStyles.HexNumber); + btDevId[4] = byte.Parse(devCode.Substring(8, 2), NumberStyles.HexNumber); + btDevId[5] = byte.Parse(devCode.Substring(10, 2), NumberStyles.HexNumber); + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + var dstNodeAddr = devCode.Substring(8); //2个字节 ** ****** **** + var btDstNode = new byte[2]; + btDstNode[0] = byte.Parse(dstNodeAddr.Substring(0, 2), NumberStyles.HexNumber); + btDstNode[1] = byte.Parse(dstNodeAddr.Substring(2, 2), NumberStyles.HexNumber); + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 2688 + operateType; + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + //第一个Tag的Oid为“0x30000001”,第二个Tag为时间戳,Oid为“0x10000051”,内容为“年、月、日、时、分、秒” + byte[] oid = { 0x20, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00 }; //Tag1 + + byte[] totalLen = { 0x00, 0x13 }; + + //wrap the whole data + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + oid.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oid.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发听音指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendSoundStopCmd(SerialPort sp, string devCode) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + var btDevId = new byte[6]; + btDevId[0] = byte.Parse(devCode.Substring(0, 2), NumberStyles.HexNumber); + btDevId[1] = byte.Parse(devCode.Substring(2, 2), NumberStyles.HexNumber); + btDevId[2] = byte.Parse(devCode.Substring(4, 2), NumberStyles.HexNumber); + btDevId[3] = byte.Parse(devCode.Substring(6, 2), NumberStyles.HexNumber); + btDevId[4] = byte.Parse(devCode.Substring(8, 2), NumberStyles.HexNumber); + btDevId[5] = byte.Parse(devCode.Substring(10, 2), NumberStyles.HexNumber); + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + var dstNodeAddr = devCode.Substring(8); //2个字节 ** ****** **** + var btDstNode = new byte[2]; + btDstNode[0] = byte.Parse(dstNodeAddr.Substring(0, 2), NumberStyles.HexNumber); + btDstNode[1] = byte.Parse(dstNodeAddr.Substring(2, 2), NumberStyles.HexNumber); + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 1408 + operateType; //0x0582 TrapResponse+z噪声记录仪 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] sysTag = + { + 0x10, 0x00, 0x00, 0x51, 0x00, 0x06, + CalendarHub.Year, CalendarHub.Mon, CalendarHub.Day, CalendarHub.Hor, CalendarHub.Min, + CalendarHub.Sec + }; //Tag2 + + byte[] totalLen = { 0x00, 0x18 }; + + //wrap the whole data + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + sysTag.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + sysTag.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发听音结束指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendCorrelatorRangingCmd(SerialPort sp) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + byte[] btDevId = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //广播模式,设备类型不解析 + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 2688 + operateType; //0X0A80 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oid = { 0x30, 0x00, 0x00, 0x01, 0x00, 0x01, 0x99 }; + + byte[] totalLen = { 0x00, 0x13 }; + + //wrap the whole data + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + oid.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oid.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发相关仪测距指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + private CommandModel _lastCommand; + + public CommandModel GetLastCommand() + { + return _lastCommand; + } + } +} \ No newline at end of file diff --git a/Correlator/DataService/IApplicationDataService.cs b/Correlator/DataService/IApplicationDataService.cs index c2c29a7..f232681 100644 --- a/Correlator/DataService/IApplicationDataService.cs +++ b/Correlator/DataService/IApplicationDataService.cs @@ -8,7 +8,7 @@ public interface IApplicationDataService { ObservableCollection GetPipeMaterial(); - + ObservableCollection GetVelocityCollection(string materialName); void DeleteVelocity(MaterialVelocity velocity); @@ -26,11 +26,31 @@ int GetSoundVelocity(string material, int pipeDiameter); AudioVisualizer GetAudioVisualizer(int waveDataSize); - + /// /// 获取 HSV 中所有的基础颜色 (饱和度和明度均为最大值) /// /// 所有的 HSV 基础颜色(共 256 * 6 个, 并且随着索引增加, 颜色也会渐变) Color[] GetAllHsvColors(); + + /// + /// 加载所有工作模式的采样率 + /// + /// + ObservableCollection GetSampleRate(); + + /// + /// 根据工作模式获取采样率 + /// + /// + /// + int GetSampleRateByWorkMode(int mode); + + /// + /// 更新采样率 + /// + /// + /// + void UpdateSampleRate(int mode, int sampleRate); } } \ No newline at end of file diff --git a/Correlator/DataService/IAudioService.cs b/Correlator/DataService/IAudioService.cs index 3295b74..9bf2316 100644 --- a/Correlator/DataService/IAudioService.cs +++ b/Correlator/DataService/IAudioService.cs @@ -11,7 +11,8 @@ /// 开始听音 /// /// - void Start(string deviceCode); + /// + void Start(string deviceCode, int sampleRate); /// /// 缓存听音数据 diff --git a/Correlator/DataService/ICommandService.cs b/Correlator/DataService/ICommandService.cs new file mode 100644 index 0000000..d3d2c53 --- /dev/null +++ b/Correlator/DataService/ICommandService.cs @@ -0,0 +1,69 @@ +using System.Collections.Generic; +using System.IO.Ports; +using Correlator.Model; + +namespace Correlator.DataService +{ + public interface ICommandService + { + /// + /// 下发唤醒指令-加速度计 + /// + /// + void SendCorrelatorWakeUpCmd(SerialPort sp); + + /// + /// 下发唤醒指令-水听器 + /// + /// + void SendHydrophoneWakeUpCmd(SerialPort sp); + + /// + /// 水听器点名指令 + /// + /// + /// + void StartCheckResponse(SerialPort sp, string devCode); + + /// + /// 发送校验结果指令给下位机 + /// + /// + /// + /// 异常数据角标集合 + void SendDataCheckResultCmd(SerialPort sp, string devCode, List indexArray); + + /// + /// 下发状态采集指令 + /// + /// + /// + void SendCellAndStatusCollectCmd(SerialPort sp, byte devId); + + /// + /// 下发听音指令 + /// + /// + /// + void SendSoundCollectCmd(SerialPort sp, string devCode); + + /// + /// 下发听音停止指令 + /// + /// + /// + void SendSoundStopCmd(SerialPort sp, string devCode); + + /// + /// 下发测距指令 + /// + /// + void SendCorrelatorRangingCmd(SerialPort sp); + + /// + /// 获取最新下发指令集合 + /// + /// + CommandModel GetLastCommand(); + } +} \ No newline at end of file diff --git a/Correlator/DataService/SerialPortServiceImpl.cs b/Correlator/DataService/SerialPortServiceImpl.cs index e18210e..364ee77 100644 --- a/Correlator/DataService/SerialPortServiceImpl.cs +++ b/Correlator/DataService/SerialPortServiceImpl.cs @@ -15,6 +15,8 @@ { private readonly IEventAggregator _eventAggregator; private readonly IAudioService _audioService; + private readonly ICommandService _commandService; + private readonly IApplicationDataService _dataService; private readonly DevStatus _devStatus = new DevStatus(); private int _checkResponseState; @@ -23,10 +25,14 @@ //左右传感器设备数据 private CorrelatorDataModel _dataModel; - public SerialPortServiceImpl(IEventAggregator eventAggregator, IAudioService audioService) + public SerialPortServiceImpl(IEventAggregator eventAggregator, IAudioService audioService, + ICommandService commandService, IApplicationDataService dataService) { _eventAggregator = eventAggregator; _audioService = audioService; + _commandService = commandService; + _dataService = dataService; + Sp.DataReceived += delegate { while (Sp.BytesToRead < 4) @@ -264,6 +270,7 @@ private void HandleListenData(List tags) { + var sampleRate = _dataService.GetSampleRateByWorkMode(RuntimeCache.WorkMode); //处理接到的噪声数据 var noiseTag = tags.GetUploadNoiseTag(); if (noiseTag != null) @@ -283,9 +290,9 @@ } //PCM数据 - var pcm = new byte[7500 * 3]; //每个采样点2字节 + var pcm = new byte[sampleRate * 3]; //每个采样点2字节 - for (var i = 0; i < 7500; i++) + for (var i = 0; i < sampleRate; i++) { pcm[i * 3 + 2] = dataValue[i * 2 + 0]; pcm[i * 3 + 1] = dataValue[i * 2 + 1]; @@ -357,7 +364,7 @@ } var devId = !RuntimeCache.RedSensorIsEnable ? (byte)0x01 : (byte)0x02; - CommandSender.SendCellAndStatusCollectCmd(Sp, devId); + _commandService.SendCellAndStatusCollectCmd(Sp, devId); Sp.Write("ATA" + Environment.NewLine); } } diff --git a/Correlator/Dialog/CheckResponseDialog.xaml.cs b/Correlator/Dialog/CheckResponseDialog.xaml.cs index 72fd7b6..2cf2c01 100644 --- a/Correlator/Dialog/CheckResponseDialog.xaml.cs +++ b/Correlator/Dialog/CheckResponseDialog.xaml.cs @@ -45,15 +45,17 @@ private readonly IEventAggregator _eventAggregator; private readonly ISerialPortService _serialPortService; private readonly IDialogService _dialogService; + private readonly ICommandService _commandService; public CheckResponseDialog(IEventAggregator eventAggregator, ISerialPortService serialPortService, - IDialogService dialogService) + IDialogService dialogService, ICommandService commandService) { InitializeComponent(); _eventAggregator = eventAggregator; _serialPortService = serialPortService; _dialogService = dialogService; + _commandService = commandService; var today = DateTime.Now.ToString("yyyyMMdd"); var configModel = LazyDataBase.Value.Table() @@ -218,7 +220,7 @@ if (RedSensorStepBar.StepIndex == 1) { RuntimeCache.SeqCaches.Clear(); - CommandSender.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev1); + _commandService.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev1); _redResponseTimer.Start(); ReCheckButton.IsEnabled = true; @@ -226,7 +228,7 @@ else if (RedSensorStepBar.StepIndex == 2) { //下发数据全部正常指令 - CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, new List()); + _commandService.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, new List()); #region 保存原始数据 @@ -295,14 +297,14 @@ if (BlueSensorStepBar.StepIndex == 1) { RuntimeCache.SeqCaches.Clear(); - CommandSender.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev2); + _commandService.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev2); _blueResponseTimer.Start(); ReCheckButton.IsEnabled = true; } else if (BlueSensorStepBar.StepIndex == 2) { - CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, new List()); + _commandService.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, new List()); #region 保存原始数据 @@ -376,7 +378,7 @@ } } - CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, redIndexArray); + _commandService.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, redIndexArray); } else { @@ -397,7 +399,7 @@ } } - CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, blueIndexArray); + _commandService.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, blueIndexArray); } }; } diff --git a/Correlator/Dialog/EditSoundSampleRateDialog.xaml b/Correlator/Dialog/EditSoundSampleRateDialog.xaml new file mode 100644 index 0000000..d441270 --- /dev/null +++ b/Correlator/Dialog/EditSoundSampleRateDialog.xaml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Correlator/Dialog/SoundSampleRateDialog.xaml.cs b/Correlator/Dialog/SoundSampleRateDialog.xaml.cs new file mode 100644 index 0000000..00c933d --- /dev/null +++ b/Correlator/Dialog/SoundSampleRateDialog.xaml.cs @@ -0,0 +1,12 @@ +using System.Windows.Controls; + +namespace Correlator.Dialog +{ + public partial class SoundSampleRateDialog : UserControl + { + public SoundSampleRateDialog() + { + InitializeComponent(); + } + } +} \ No newline at end of file diff --git a/Correlator/App.xaml.cs b/Correlator/App.xaml.cs index 5c9dd37..c66d198 100644 --- a/Correlator/App.xaml.cs +++ b/Correlator/App.xaml.cs @@ -98,6 +98,7 @@ containerRegistry.RegisterSingleton(); containerRegistry.RegisterSingleton(); containerRegistry.RegisterSingleton(); + containerRegistry.RegisterSingleton(); //Dialog or Window containerRegistry.RegisterDialog(); @@ -105,6 +106,8 @@ containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); + containerRegistry.RegisterDialog(); + containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); diff --git a/Correlator/Converter/SoundParamValueConverter.cs b/Correlator/Converter/SoundParamValueConverter.cs new file mode 100644 index 0000000..4101a19 --- /dev/null +++ b/Correlator/Converter/SoundParamValueConverter.cs @@ -0,0 +1,26 @@ +using System; +using System.Globalization; +using System.Windows.Data; + +namespace Correlator.Converter +{ + public class SoundParamValueConverter : IMultiValueConverter + { + public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) + { + try + { + return "声速:" + values[0] + "m/s,采样率:" + values[1] + "Hz"; + } + catch (Exception) + { + return null; + } + } + + public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) + { + return null; + } + } +} \ No newline at end of file diff --git a/Correlator/Converter/WorkModeConverter.cs b/Correlator/Converter/WorkModeConverter.cs new file mode 100644 index 0000000..19d0327 --- /dev/null +++ b/Correlator/Converter/WorkModeConverter.cs @@ -0,0 +1,21 @@ +using System; +using System.Diagnostics; +using System.Globalization; +using System.Windows.Data; + +namespace Correlator.Converter +{ + internal class WorkModeConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + Debug.Assert(value != null, nameof(value) + " != null"); + return (int)value == 1 ? "加速度计" : "水听器"; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + return null; + } + } +} \ No newline at end of file diff --git a/Correlator/Correlator.csproj b/Correlator/Correlator.csproj index da299ba..c3a433a 100644 --- a/Correlator/Correlator.csproj +++ b/Correlator/Correlator.csproj @@ -216,10 +216,14 @@ + + + + @@ -240,6 +244,9 @@ DetectNoiseDialog.xaml + + EditSoundSampleRateDialog.xaml + EditSoundSpeedDialog.xaml @@ -249,7 +256,14 @@ LoadingDialog.xaml + + SoundSampleRateDialog.xaml + + + + + ApplicationLogView.xaml @@ -303,7 +317,6 @@ - @@ -343,12 +356,14 @@ MSBuild:Compile + Designer MSBuild:Compile + Designer diff --git a/Correlator/DataService/ApplicationDataServiceImpl.cs b/Correlator/DataService/ApplicationDataServiceImpl.cs index d3f9463..d7f0b68 100644 --- a/Correlator/DataService/ApplicationDataServiceImpl.cs +++ b/Correlator/DataService/ApplicationDataServiceImpl.cs @@ -104,7 +104,7 @@ { return new AudioVisualizer(waveDataSize); } - + public Color[] GetAllHsvColors() { var result = new Color[256 * 6]; @@ -141,5 +141,50 @@ return result; } + + public ObservableCollection GetSampleRate() + { + var sampleRateCollection = new ObservableCollection(); + using (var manager = new DataBaseManager()) + { + var result = manager + .Table() + .ToList(); + foreach (var model in result) + { + sampleRateCollection.Add(model); + } + } + + return sampleRateCollection; + } + + public int GetSampleRateByWorkMode(int mode) + { + using (var manager = new DataBaseManager()) + { + var result = manager + .Table() + .First(x => x.WorkMode == mode); + return result?.SampleRate ?? 7500; + } + } + + public void UpdateSampleRate(int mode, int sampleRate) + { + using (var manager = new DataBaseManager()) + { + var result = manager + .Table() + .First(x => x.WorkMode == mode); + var rateModel = result ?? new SampleRateModel(); + + rateModel.WorkMode = mode; + rateModel.SampleRate = sampleRate; + rateModel.UpdateDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); + + manager.Update(rateModel); + } + } } } \ No newline at end of file diff --git a/Correlator/DataService/AudioServiceImpl.cs b/Correlator/DataService/AudioServiceImpl.cs index fd3375f..c9ccb46 100644 --- a/Correlator/DataService/AudioServiceImpl.cs +++ b/Correlator/DataService/AudioServiceImpl.cs @@ -9,16 +9,17 @@ public class AudioServiceImpl : IAudioService { private bool _isStopped; + private WaveFormat _waveFormat; private WaveFileWriter _waveFileWriter; private BufferedWaveProvider _waveProvider; - private readonly WaveFormat _waveFormat = new WaveFormat(7500, 24, 1); public WaveOutEvent Wave { get; set; } = new WaveOutEvent(); - public void Start(string deviceCode) + public void Start(string deviceCode, int sampleRate) { _isStopped = false; + _waveFormat = new WaveFormat(sampleRate, 24, 1); _waveProvider = new BufferedWaveProvider(_waveFormat); Wave.Init(_waveProvider); diff --git a/Correlator/DataService/CommandServiceImpl.cs b/Correlator/DataService/CommandServiceImpl.cs new file mode 100644 index 0000000..28e3402 --- /dev/null +++ b/Correlator/DataService/CommandServiceImpl.cs @@ -0,0 +1,614 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO.Ports; +using Correlator.Model; +using Correlator.Util; + +namespace Correlator.DataService +{ + public class CommandServiceImpl : ICommandService + { + public void SendCorrelatorWakeUpCmd(SerialPort sp) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + byte[] btDevId = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //广播模式,设备类型不解析 + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + const short pduTypeByte = 2; + var operateType = (short)(pduTypeByte & 0x7F); + + var pdu = (short)(2688 + operateType); //0X0A80 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oid = { 0x30, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00 }; + + byte[] totalLen = { 0x00, 0x13 }; + + //wrap the whole data + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + oid.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oid.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发加速度计数据采集指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendHydrophoneWakeUpCmd(SerialPort sp) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + //后续到CRC字段前的字节总长度(不包括长度字段和CRC字段)。 + byte[] totalLen = { 0x00, 0x1F }; + + byte[] btDevId = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //广播模式,设备类型不解析 + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 2688 + operateType; //0X0A80 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oidTag = + { + 0x40, 0x00, 0x00, 0x01, + 0x00, 0x01, + 0x00 + }; + + //获取时间(年-月-日-时-分-秒),年号-2000 + RuntimeCache.HydrophoneWakeUpTimestamp = new[] + { + CalendarHub.Year, CalendarHub.Mon, CalendarHub.Day, CalendarHub.Hor, CalendarHub.Min, + CalendarHub.Sec + }; + byte[] timeTag = + { + 0x10, 0x00, 0x00, 0x51, + 0x00, 0x06, + RuntimeCache.HydrophoneWakeUpTimestamp[0], RuntimeCache.HydrophoneWakeUpTimestamp[1], + RuntimeCache.HydrophoneWakeUpTimestamp[2], RuntimeCache.HydrophoneWakeUpTimestamp[3], + RuntimeCache.HydrophoneWakeUpTimestamp[4], RuntimeCache.HydrophoneWakeUpTimestamp[5] + }; //时间oid + + //wrap the whole data + var result = new byte[35]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oidTag.CopyTo(result, 16); + timeTag.CopyTo(result, 23); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发水听器数据采集指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void StartCheckResponse(SerialPort sp, string devCode) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + //后续到CRC字段前的字节总长度(不包括长度字段和CRC字段)。 + byte[] totalLen = { 0x00, 0x1F }; + + var btDevId = new byte[6]; + btDevId[0] = byte.Parse(devCode.Substring(0, 2), NumberStyles.HexNumber); + btDevId[1] = byte.Parse(devCode.Substring(2, 2), NumberStyles.HexNumber); + btDevId[2] = byte.Parse(devCode.Substring(4, 2), NumberStyles.HexNumber); + btDevId[3] = byte.Parse(devCode.Substring(6, 2), NumberStyles.HexNumber); + btDevId[4] = byte.Parse(devCode.Substring(8, 2), NumberStyles.HexNumber); + btDevId[5] = byte.Parse(devCode.Substring(10, 2), NumberStyles.HexNumber); + + //通信方式 + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + byte[] btPdu = { 0x01, 0x82 }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oidTag = + { + 0x40, 0x00, 0x00, 0x02, + 0x00, 0x01, + 0x00 + }; + + byte[] timeTag = + { + 0x10, 0x00, 0x00, 0x51, + 0x00, 0x06, + RuntimeCache.HydrophoneWakeUpTimestamp[0], RuntimeCache.HydrophoneWakeUpTimestamp[1], + RuntimeCache.HydrophoneWakeUpTimestamp[2], RuntimeCache.HydrophoneWakeUpTimestamp[3], + RuntimeCache.HydrophoneWakeUpTimestamp[4], RuntimeCache.HydrophoneWakeUpTimestamp[5] + }; //时间oid + + //wrap the whole data + var result = new byte[35]; + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oidTag.CopyTo(result, 16); + timeTag.CopyTo(result, 23); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发水听器点名指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendDataCheckResultCmd(SerialPort sp, string devCode, List indexArray) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + //后续到CRC字段前的字节总长度(不包括长度字段和CRC字段)。 + byte[] totalLen = { 0x00, 0x26 }; + + var btDevId = new byte[6]; + btDevId[0] = byte.Parse(devCode.Substring(0, 2), NumberStyles.HexNumber); + btDevId[1] = byte.Parse(devCode.Substring(2, 2), NumberStyles.HexNumber); + btDevId[2] = byte.Parse(devCode.Substring(4, 2), NumberStyles.HexNumber); + btDevId[3] = byte.Parse(devCode.Substring(6, 2), NumberStyles.HexNumber); + btDevId[4] = byte.Parse(devCode.Substring(8, 2), NumberStyles.HexNumber); + btDevId[5] = byte.Parse(devCode.Substring(10, 2), NumberStyles.HexNumber); + + //通信方式 + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + byte[] btPdu = { 0x05, 0x82 }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + //check result tag + var byteArray = indexArray.ToByteArray(); + byte[] oidTag = + { + 0x60, 0x00, 0x03, 0x00, + 0x00, 0x08, + byteArray[0], byteArray[1], byteArray[2], byteArray[3], + byteArray[4], byteArray[5], byteArray[6], byteArray[7] + }; + + byte[] timeTag = + { + 0x10, 0x00, 0x00, 0x51, + 0x00, 0x06, + RuntimeCache.HydrophoneWakeUpTimestamp[0], RuntimeCache.HydrophoneWakeUpTimestamp[1], + RuntimeCache.HydrophoneWakeUpTimestamp[2], RuntimeCache.HydrophoneWakeUpTimestamp[3], + RuntimeCache.HydrophoneWakeUpTimestamp[4], RuntimeCache.HydrophoneWakeUpTimestamp[5] + }; //时间oid + + //wrap the whole data + var result = new byte[42]; + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oidTag.CopyTo(result, 16); + timeTag.CopyTo(result, 30); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发水听器检查指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendCellAndStatusCollectCmd(SerialPort sp, byte devId) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + byte[] btDevId = { 0x21, 0x17, 0x00, 0x08, 0x22, devId }; //广播模式,设备类型不解析 + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0x22, devId }; + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 2688 + operateType; //0X0A80 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oid = { 0x60, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00 }; + + byte[] totalLen = { 0x00, 0x13 }; + + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + oid.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oid.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "设备 " + devId + " 下发状态采集指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendSoundCollectCmd(SerialPort sp, string devCode) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + //byte[] btDevId = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //广播模式,设备类型不解析 + var btDevId = new byte[6]; + btDevId[0] = byte.Parse(devCode.Substring(0, 2), NumberStyles.HexNumber); + btDevId[1] = byte.Parse(devCode.Substring(2, 2), NumberStyles.HexNumber); + btDevId[2] = byte.Parse(devCode.Substring(4, 2), NumberStyles.HexNumber); + btDevId[3] = byte.Parse(devCode.Substring(6, 2), NumberStyles.HexNumber); + btDevId[4] = byte.Parse(devCode.Substring(8, 2), NumberStyles.HexNumber); + btDevId[5] = byte.Parse(devCode.Substring(10, 2), NumberStyles.HexNumber); + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + var dstNodeAddr = devCode.Substring(8); //2个字节 ** ****** **** + var btDstNode = new byte[2]; + btDstNode[0] = byte.Parse(dstNodeAddr.Substring(0, 2), NumberStyles.HexNumber); + btDstNode[1] = byte.Parse(dstNodeAddr.Substring(2, 2), NumberStyles.HexNumber); + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 2688 + operateType; + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + //第一个Tag的Oid为“0x30000001”,第二个Tag为时间戳,Oid为“0x10000051”,内容为“年、月、日、时、分、秒” + byte[] oid = { 0x20, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00 }; //Tag1 + + byte[] totalLen = { 0x00, 0x13 }; + + //wrap the whole data + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + oid.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oid.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发听音指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendSoundStopCmd(SerialPort sp, string devCode) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + var btDevId = new byte[6]; + btDevId[0] = byte.Parse(devCode.Substring(0, 2), NumberStyles.HexNumber); + btDevId[1] = byte.Parse(devCode.Substring(2, 2), NumberStyles.HexNumber); + btDevId[2] = byte.Parse(devCode.Substring(4, 2), NumberStyles.HexNumber); + btDevId[3] = byte.Parse(devCode.Substring(6, 2), NumberStyles.HexNumber); + btDevId[4] = byte.Parse(devCode.Substring(8, 2), NumberStyles.HexNumber); + btDevId[5] = byte.Parse(devCode.Substring(10, 2), NumberStyles.HexNumber); + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + var dstNodeAddr = devCode.Substring(8); //2个字节 ** ****** **** + var btDstNode = new byte[2]; + btDstNode[0] = byte.Parse(dstNodeAddr.Substring(0, 2), NumberStyles.HexNumber); + btDstNode[1] = byte.Parse(dstNodeAddr.Substring(2, 2), NumberStyles.HexNumber); + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 1408 + operateType; //0x0582 TrapResponse+z噪声记录仪 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] sysTag = + { + 0x10, 0x00, 0x00, 0x51, 0x00, 0x06, + CalendarHub.Year, CalendarHub.Mon, CalendarHub.Day, CalendarHub.Hor, CalendarHub.Min, + CalendarHub.Sec + }; //Tag2 + + byte[] totalLen = { 0x00, 0x18 }; + + //wrap the whole data + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + sysTag.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + sysTag.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发听音结束指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendCorrelatorRangingCmd(SerialPort sp) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + byte[] btDevId = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //广播模式,设备类型不解析 + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 2688 + operateType; //0X0A80 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oid = { 0x30, 0x00, 0x00, 0x01, 0x00, 0x01, 0x99 }; + + byte[] totalLen = { 0x00, 0x13 }; + + //wrap the whole data + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + oid.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oid.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发相关仪测距指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + private CommandModel _lastCommand; + + public CommandModel GetLastCommand() + { + return _lastCommand; + } + } +} \ No newline at end of file diff --git a/Correlator/DataService/IApplicationDataService.cs b/Correlator/DataService/IApplicationDataService.cs index c2c29a7..f232681 100644 --- a/Correlator/DataService/IApplicationDataService.cs +++ b/Correlator/DataService/IApplicationDataService.cs @@ -8,7 +8,7 @@ public interface IApplicationDataService { ObservableCollection GetPipeMaterial(); - + ObservableCollection GetVelocityCollection(string materialName); void DeleteVelocity(MaterialVelocity velocity); @@ -26,11 +26,31 @@ int GetSoundVelocity(string material, int pipeDiameter); AudioVisualizer GetAudioVisualizer(int waveDataSize); - + /// /// 获取 HSV 中所有的基础颜色 (饱和度和明度均为最大值) /// /// 所有的 HSV 基础颜色(共 256 * 6 个, 并且随着索引增加, 颜色也会渐变) Color[] GetAllHsvColors(); + + /// + /// 加载所有工作模式的采样率 + /// + /// + ObservableCollection GetSampleRate(); + + /// + /// 根据工作模式获取采样率 + /// + /// + /// + int GetSampleRateByWorkMode(int mode); + + /// + /// 更新采样率 + /// + /// + /// + void UpdateSampleRate(int mode, int sampleRate); } } \ No newline at end of file diff --git a/Correlator/DataService/IAudioService.cs b/Correlator/DataService/IAudioService.cs index 3295b74..9bf2316 100644 --- a/Correlator/DataService/IAudioService.cs +++ b/Correlator/DataService/IAudioService.cs @@ -11,7 +11,8 @@ /// 开始听音 /// /// - void Start(string deviceCode); + /// + void Start(string deviceCode, int sampleRate); /// /// 缓存听音数据 diff --git a/Correlator/DataService/ICommandService.cs b/Correlator/DataService/ICommandService.cs new file mode 100644 index 0000000..d3d2c53 --- /dev/null +++ b/Correlator/DataService/ICommandService.cs @@ -0,0 +1,69 @@ +using System.Collections.Generic; +using System.IO.Ports; +using Correlator.Model; + +namespace Correlator.DataService +{ + public interface ICommandService + { + /// + /// 下发唤醒指令-加速度计 + /// + /// + void SendCorrelatorWakeUpCmd(SerialPort sp); + + /// + /// 下发唤醒指令-水听器 + /// + /// + void SendHydrophoneWakeUpCmd(SerialPort sp); + + /// + /// 水听器点名指令 + /// + /// + /// + void StartCheckResponse(SerialPort sp, string devCode); + + /// + /// 发送校验结果指令给下位机 + /// + /// + /// + /// 异常数据角标集合 + void SendDataCheckResultCmd(SerialPort sp, string devCode, List indexArray); + + /// + /// 下发状态采集指令 + /// + /// + /// + void SendCellAndStatusCollectCmd(SerialPort sp, byte devId); + + /// + /// 下发听音指令 + /// + /// + /// + void SendSoundCollectCmd(SerialPort sp, string devCode); + + /// + /// 下发听音停止指令 + /// + /// + /// + void SendSoundStopCmd(SerialPort sp, string devCode); + + /// + /// 下发测距指令 + /// + /// + void SendCorrelatorRangingCmd(SerialPort sp); + + /// + /// 获取最新下发指令集合 + /// + /// + CommandModel GetLastCommand(); + } +} \ No newline at end of file diff --git a/Correlator/DataService/SerialPortServiceImpl.cs b/Correlator/DataService/SerialPortServiceImpl.cs index e18210e..364ee77 100644 --- a/Correlator/DataService/SerialPortServiceImpl.cs +++ b/Correlator/DataService/SerialPortServiceImpl.cs @@ -15,6 +15,8 @@ { private readonly IEventAggregator _eventAggregator; private readonly IAudioService _audioService; + private readonly ICommandService _commandService; + private readonly IApplicationDataService _dataService; private readonly DevStatus _devStatus = new DevStatus(); private int _checkResponseState; @@ -23,10 +25,14 @@ //左右传感器设备数据 private CorrelatorDataModel _dataModel; - public SerialPortServiceImpl(IEventAggregator eventAggregator, IAudioService audioService) + public SerialPortServiceImpl(IEventAggregator eventAggregator, IAudioService audioService, + ICommandService commandService, IApplicationDataService dataService) { _eventAggregator = eventAggregator; _audioService = audioService; + _commandService = commandService; + _dataService = dataService; + Sp.DataReceived += delegate { while (Sp.BytesToRead < 4) @@ -264,6 +270,7 @@ private void HandleListenData(List tags) { + var sampleRate = _dataService.GetSampleRateByWorkMode(RuntimeCache.WorkMode); //处理接到的噪声数据 var noiseTag = tags.GetUploadNoiseTag(); if (noiseTag != null) @@ -283,9 +290,9 @@ } //PCM数据 - var pcm = new byte[7500 * 3]; //每个采样点2字节 + var pcm = new byte[sampleRate * 3]; //每个采样点2字节 - for (var i = 0; i < 7500; i++) + for (var i = 0; i < sampleRate; i++) { pcm[i * 3 + 2] = dataValue[i * 2 + 0]; pcm[i * 3 + 1] = dataValue[i * 2 + 1]; @@ -357,7 +364,7 @@ } var devId = !RuntimeCache.RedSensorIsEnable ? (byte)0x01 : (byte)0x02; - CommandSender.SendCellAndStatusCollectCmd(Sp, devId); + _commandService.SendCellAndStatusCollectCmd(Sp, devId); Sp.Write("ATA" + Environment.NewLine); } } diff --git a/Correlator/Dialog/CheckResponseDialog.xaml.cs b/Correlator/Dialog/CheckResponseDialog.xaml.cs index 72fd7b6..2cf2c01 100644 --- a/Correlator/Dialog/CheckResponseDialog.xaml.cs +++ b/Correlator/Dialog/CheckResponseDialog.xaml.cs @@ -45,15 +45,17 @@ private readonly IEventAggregator _eventAggregator; private readonly ISerialPortService _serialPortService; private readonly IDialogService _dialogService; + private readonly ICommandService _commandService; public CheckResponseDialog(IEventAggregator eventAggregator, ISerialPortService serialPortService, - IDialogService dialogService) + IDialogService dialogService, ICommandService commandService) { InitializeComponent(); _eventAggregator = eventAggregator; _serialPortService = serialPortService; _dialogService = dialogService; + _commandService = commandService; var today = DateTime.Now.ToString("yyyyMMdd"); var configModel = LazyDataBase.Value.Table() @@ -218,7 +220,7 @@ if (RedSensorStepBar.StepIndex == 1) { RuntimeCache.SeqCaches.Clear(); - CommandSender.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev1); + _commandService.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev1); _redResponseTimer.Start(); ReCheckButton.IsEnabled = true; @@ -226,7 +228,7 @@ else if (RedSensorStepBar.StepIndex == 2) { //下发数据全部正常指令 - CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, new List()); + _commandService.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, new List()); #region 保存原始数据 @@ -295,14 +297,14 @@ if (BlueSensorStepBar.StepIndex == 1) { RuntimeCache.SeqCaches.Clear(); - CommandSender.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev2); + _commandService.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev2); _blueResponseTimer.Start(); ReCheckButton.IsEnabled = true; } else if (BlueSensorStepBar.StepIndex == 2) { - CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, new List()); + _commandService.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, new List()); #region 保存原始数据 @@ -376,7 +378,7 @@ } } - CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, redIndexArray); + _commandService.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, redIndexArray); } else { @@ -397,7 +399,7 @@ } } - CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, blueIndexArray); + _commandService.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, blueIndexArray); } }; } diff --git a/Correlator/Dialog/EditSoundSampleRateDialog.xaml b/Correlator/Dialog/EditSoundSampleRateDialog.xaml new file mode 100644 index 0000000..d441270 --- /dev/null +++ b/Correlator/Dialog/EditSoundSampleRateDialog.xaml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Correlator/Dialog/SoundSampleRateDialog.xaml.cs b/Correlator/Dialog/SoundSampleRateDialog.xaml.cs new file mode 100644 index 0000000..00c933d --- /dev/null +++ b/Correlator/Dialog/SoundSampleRateDialog.xaml.cs @@ -0,0 +1,12 @@ +using System.Windows.Controls; + +namespace Correlator.Dialog +{ + public partial class SoundSampleRateDialog : UserControl + { + public SoundSampleRateDialog() + { + InitializeComponent(); + } + } +} \ No newline at end of file diff --git a/Correlator/Model/CommandModel.cs b/Correlator/Model/CommandModel.cs new file mode 100644 index 0000000..72243b7 --- /dev/null +++ b/Correlator/Model/CommandModel.cs @@ -0,0 +1,8 @@ +namespace Correlator.Model +{ + public class CommandModel + { + public string Value { get; set; } + public string Time { get; set; } + } +} \ No newline at end of file diff --git a/Correlator/App.xaml.cs b/Correlator/App.xaml.cs index 5c9dd37..c66d198 100644 --- a/Correlator/App.xaml.cs +++ b/Correlator/App.xaml.cs @@ -98,6 +98,7 @@ containerRegistry.RegisterSingleton(); containerRegistry.RegisterSingleton(); containerRegistry.RegisterSingleton(); + containerRegistry.RegisterSingleton(); //Dialog or Window containerRegistry.RegisterDialog(); @@ -105,6 +106,8 @@ containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); + containerRegistry.RegisterDialog(); + containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); diff --git a/Correlator/Converter/SoundParamValueConverter.cs b/Correlator/Converter/SoundParamValueConverter.cs new file mode 100644 index 0000000..4101a19 --- /dev/null +++ b/Correlator/Converter/SoundParamValueConverter.cs @@ -0,0 +1,26 @@ +using System; +using System.Globalization; +using System.Windows.Data; + +namespace Correlator.Converter +{ + public class SoundParamValueConverter : IMultiValueConverter + { + public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) + { + try + { + return "声速:" + values[0] + "m/s,采样率:" + values[1] + "Hz"; + } + catch (Exception) + { + return null; + } + } + + public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) + { + return null; + } + } +} \ No newline at end of file diff --git a/Correlator/Converter/WorkModeConverter.cs b/Correlator/Converter/WorkModeConverter.cs new file mode 100644 index 0000000..19d0327 --- /dev/null +++ b/Correlator/Converter/WorkModeConverter.cs @@ -0,0 +1,21 @@ +using System; +using System.Diagnostics; +using System.Globalization; +using System.Windows.Data; + +namespace Correlator.Converter +{ + internal class WorkModeConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + Debug.Assert(value != null, nameof(value) + " != null"); + return (int)value == 1 ? "加速度计" : "水听器"; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + return null; + } + } +} \ No newline at end of file diff --git a/Correlator/Correlator.csproj b/Correlator/Correlator.csproj index da299ba..c3a433a 100644 --- a/Correlator/Correlator.csproj +++ b/Correlator/Correlator.csproj @@ -216,10 +216,14 @@ + + + + @@ -240,6 +244,9 @@ DetectNoiseDialog.xaml + + EditSoundSampleRateDialog.xaml + EditSoundSpeedDialog.xaml @@ -249,7 +256,14 @@ LoadingDialog.xaml + + SoundSampleRateDialog.xaml + + + + + ApplicationLogView.xaml @@ -303,7 +317,6 @@ - @@ -343,12 +356,14 @@ MSBuild:Compile + Designer MSBuild:Compile + Designer diff --git a/Correlator/DataService/ApplicationDataServiceImpl.cs b/Correlator/DataService/ApplicationDataServiceImpl.cs index d3f9463..d7f0b68 100644 --- a/Correlator/DataService/ApplicationDataServiceImpl.cs +++ b/Correlator/DataService/ApplicationDataServiceImpl.cs @@ -104,7 +104,7 @@ { return new AudioVisualizer(waveDataSize); } - + public Color[] GetAllHsvColors() { var result = new Color[256 * 6]; @@ -141,5 +141,50 @@ return result; } + + public ObservableCollection GetSampleRate() + { + var sampleRateCollection = new ObservableCollection(); + using (var manager = new DataBaseManager()) + { + var result = manager + .Table() + .ToList(); + foreach (var model in result) + { + sampleRateCollection.Add(model); + } + } + + return sampleRateCollection; + } + + public int GetSampleRateByWorkMode(int mode) + { + using (var manager = new DataBaseManager()) + { + var result = manager + .Table() + .First(x => x.WorkMode == mode); + return result?.SampleRate ?? 7500; + } + } + + public void UpdateSampleRate(int mode, int sampleRate) + { + using (var manager = new DataBaseManager()) + { + var result = manager + .Table() + .First(x => x.WorkMode == mode); + var rateModel = result ?? new SampleRateModel(); + + rateModel.WorkMode = mode; + rateModel.SampleRate = sampleRate; + rateModel.UpdateDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); + + manager.Update(rateModel); + } + } } } \ No newline at end of file diff --git a/Correlator/DataService/AudioServiceImpl.cs b/Correlator/DataService/AudioServiceImpl.cs index fd3375f..c9ccb46 100644 --- a/Correlator/DataService/AudioServiceImpl.cs +++ b/Correlator/DataService/AudioServiceImpl.cs @@ -9,16 +9,17 @@ public class AudioServiceImpl : IAudioService { private bool _isStopped; + private WaveFormat _waveFormat; private WaveFileWriter _waveFileWriter; private BufferedWaveProvider _waveProvider; - private readonly WaveFormat _waveFormat = new WaveFormat(7500, 24, 1); public WaveOutEvent Wave { get; set; } = new WaveOutEvent(); - public void Start(string deviceCode) + public void Start(string deviceCode, int sampleRate) { _isStopped = false; + _waveFormat = new WaveFormat(sampleRate, 24, 1); _waveProvider = new BufferedWaveProvider(_waveFormat); Wave.Init(_waveProvider); diff --git a/Correlator/DataService/CommandServiceImpl.cs b/Correlator/DataService/CommandServiceImpl.cs new file mode 100644 index 0000000..28e3402 --- /dev/null +++ b/Correlator/DataService/CommandServiceImpl.cs @@ -0,0 +1,614 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO.Ports; +using Correlator.Model; +using Correlator.Util; + +namespace Correlator.DataService +{ + public class CommandServiceImpl : ICommandService + { + public void SendCorrelatorWakeUpCmd(SerialPort sp) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + byte[] btDevId = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //广播模式,设备类型不解析 + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + const short pduTypeByte = 2; + var operateType = (short)(pduTypeByte & 0x7F); + + var pdu = (short)(2688 + operateType); //0X0A80 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oid = { 0x30, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00 }; + + byte[] totalLen = { 0x00, 0x13 }; + + //wrap the whole data + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + oid.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oid.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发加速度计数据采集指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendHydrophoneWakeUpCmd(SerialPort sp) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + //后续到CRC字段前的字节总长度(不包括长度字段和CRC字段)。 + byte[] totalLen = { 0x00, 0x1F }; + + byte[] btDevId = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //广播模式,设备类型不解析 + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 2688 + operateType; //0X0A80 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oidTag = + { + 0x40, 0x00, 0x00, 0x01, + 0x00, 0x01, + 0x00 + }; + + //获取时间(年-月-日-时-分-秒),年号-2000 + RuntimeCache.HydrophoneWakeUpTimestamp = new[] + { + CalendarHub.Year, CalendarHub.Mon, CalendarHub.Day, CalendarHub.Hor, CalendarHub.Min, + CalendarHub.Sec + }; + byte[] timeTag = + { + 0x10, 0x00, 0x00, 0x51, + 0x00, 0x06, + RuntimeCache.HydrophoneWakeUpTimestamp[0], RuntimeCache.HydrophoneWakeUpTimestamp[1], + RuntimeCache.HydrophoneWakeUpTimestamp[2], RuntimeCache.HydrophoneWakeUpTimestamp[3], + RuntimeCache.HydrophoneWakeUpTimestamp[4], RuntimeCache.HydrophoneWakeUpTimestamp[5] + }; //时间oid + + //wrap the whole data + var result = new byte[35]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oidTag.CopyTo(result, 16); + timeTag.CopyTo(result, 23); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发水听器数据采集指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void StartCheckResponse(SerialPort sp, string devCode) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + //后续到CRC字段前的字节总长度(不包括长度字段和CRC字段)。 + byte[] totalLen = { 0x00, 0x1F }; + + var btDevId = new byte[6]; + btDevId[0] = byte.Parse(devCode.Substring(0, 2), NumberStyles.HexNumber); + btDevId[1] = byte.Parse(devCode.Substring(2, 2), NumberStyles.HexNumber); + btDevId[2] = byte.Parse(devCode.Substring(4, 2), NumberStyles.HexNumber); + btDevId[3] = byte.Parse(devCode.Substring(6, 2), NumberStyles.HexNumber); + btDevId[4] = byte.Parse(devCode.Substring(8, 2), NumberStyles.HexNumber); + btDevId[5] = byte.Parse(devCode.Substring(10, 2), NumberStyles.HexNumber); + + //通信方式 + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + byte[] btPdu = { 0x01, 0x82 }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oidTag = + { + 0x40, 0x00, 0x00, 0x02, + 0x00, 0x01, + 0x00 + }; + + byte[] timeTag = + { + 0x10, 0x00, 0x00, 0x51, + 0x00, 0x06, + RuntimeCache.HydrophoneWakeUpTimestamp[0], RuntimeCache.HydrophoneWakeUpTimestamp[1], + RuntimeCache.HydrophoneWakeUpTimestamp[2], RuntimeCache.HydrophoneWakeUpTimestamp[3], + RuntimeCache.HydrophoneWakeUpTimestamp[4], RuntimeCache.HydrophoneWakeUpTimestamp[5] + }; //时间oid + + //wrap the whole data + var result = new byte[35]; + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oidTag.CopyTo(result, 16); + timeTag.CopyTo(result, 23); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发水听器点名指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendDataCheckResultCmd(SerialPort sp, string devCode, List indexArray) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + //后续到CRC字段前的字节总长度(不包括长度字段和CRC字段)。 + byte[] totalLen = { 0x00, 0x26 }; + + var btDevId = new byte[6]; + btDevId[0] = byte.Parse(devCode.Substring(0, 2), NumberStyles.HexNumber); + btDevId[1] = byte.Parse(devCode.Substring(2, 2), NumberStyles.HexNumber); + btDevId[2] = byte.Parse(devCode.Substring(4, 2), NumberStyles.HexNumber); + btDevId[3] = byte.Parse(devCode.Substring(6, 2), NumberStyles.HexNumber); + btDevId[4] = byte.Parse(devCode.Substring(8, 2), NumberStyles.HexNumber); + btDevId[5] = byte.Parse(devCode.Substring(10, 2), NumberStyles.HexNumber); + + //通信方式 + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + byte[] btPdu = { 0x05, 0x82 }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + //check result tag + var byteArray = indexArray.ToByteArray(); + byte[] oidTag = + { + 0x60, 0x00, 0x03, 0x00, + 0x00, 0x08, + byteArray[0], byteArray[1], byteArray[2], byteArray[3], + byteArray[4], byteArray[5], byteArray[6], byteArray[7] + }; + + byte[] timeTag = + { + 0x10, 0x00, 0x00, 0x51, + 0x00, 0x06, + RuntimeCache.HydrophoneWakeUpTimestamp[0], RuntimeCache.HydrophoneWakeUpTimestamp[1], + RuntimeCache.HydrophoneWakeUpTimestamp[2], RuntimeCache.HydrophoneWakeUpTimestamp[3], + RuntimeCache.HydrophoneWakeUpTimestamp[4], RuntimeCache.HydrophoneWakeUpTimestamp[5] + }; //时间oid + + //wrap the whole data + var result = new byte[42]; + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oidTag.CopyTo(result, 16); + timeTag.CopyTo(result, 30); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发水听器检查指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendCellAndStatusCollectCmd(SerialPort sp, byte devId) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + byte[] btDevId = { 0x21, 0x17, 0x00, 0x08, 0x22, devId }; //广播模式,设备类型不解析 + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0x22, devId }; + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 2688 + operateType; //0X0A80 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oid = { 0x60, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00 }; + + byte[] totalLen = { 0x00, 0x13 }; + + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + oid.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oid.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "设备 " + devId + " 下发状态采集指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendSoundCollectCmd(SerialPort sp, string devCode) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + //byte[] btDevId = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //广播模式,设备类型不解析 + var btDevId = new byte[6]; + btDevId[0] = byte.Parse(devCode.Substring(0, 2), NumberStyles.HexNumber); + btDevId[1] = byte.Parse(devCode.Substring(2, 2), NumberStyles.HexNumber); + btDevId[2] = byte.Parse(devCode.Substring(4, 2), NumberStyles.HexNumber); + btDevId[3] = byte.Parse(devCode.Substring(6, 2), NumberStyles.HexNumber); + btDevId[4] = byte.Parse(devCode.Substring(8, 2), NumberStyles.HexNumber); + btDevId[5] = byte.Parse(devCode.Substring(10, 2), NumberStyles.HexNumber); + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + var dstNodeAddr = devCode.Substring(8); //2个字节 ** ****** **** + var btDstNode = new byte[2]; + btDstNode[0] = byte.Parse(dstNodeAddr.Substring(0, 2), NumberStyles.HexNumber); + btDstNode[1] = byte.Parse(dstNodeAddr.Substring(2, 2), NumberStyles.HexNumber); + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 2688 + operateType; + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + //第一个Tag的Oid为“0x30000001”,第二个Tag为时间戳,Oid为“0x10000051”,内容为“年、月、日、时、分、秒” + byte[] oid = { 0x20, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00 }; //Tag1 + + byte[] totalLen = { 0x00, 0x13 }; + + //wrap the whole data + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + oid.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oid.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发听音指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendSoundStopCmd(SerialPort sp, string devCode) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + var btDevId = new byte[6]; + btDevId[0] = byte.Parse(devCode.Substring(0, 2), NumberStyles.HexNumber); + btDevId[1] = byte.Parse(devCode.Substring(2, 2), NumberStyles.HexNumber); + btDevId[2] = byte.Parse(devCode.Substring(4, 2), NumberStyles.HexNumber); + btDevId[3] = byte.Parse(devCode.Substring(6, 2), NumberStyles.HexNumber); + btDevId[4] = byte.Parse(devCode.Substring(8, 2), NumberStyles.HexNumber); + btDevId[5] = byte.Parse(devCode.Substring(10, 2), NumberStyles.HexNumber); + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + var dstNodeAddr = devCode.Substring(8); //2个字节 ** ****** **** + var btDstNode = new byte[2]; + btDstNode[0] = byte.Parse(dstNodeAddr.Substring(0, 2), NumberStyles.HexNumber); + btDstNode[1] = byte.Parse(dstNodeAddr.Substring(2, 2), NumberStyles.HexNumber); + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 1408 + operateType; //0x0582 TrapResponse+z噪声记录仪 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] sysTag = + { + 0x10, 0x00, 0x00, 0x51, 0x00, 0x06, + CalendarHub.Year, CalendarHub.Mon, CalendarHub.Day, CalendarHub.Hor, CalendarHub.Min, + CalendarHub.Sec + }; //Tag2 + + byte[] totalLen = { 0x00, 0x18 }; + + //wrap the whole data + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + sysTag.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + sysTag.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发听音结束指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendCorrelatorRangingCmd(SerialPort sp) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + byte[] btDevId = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //广播模式,设备类型不解析 + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 2688 + operateType; //0X0A80 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oid = { 0x30, 0x00, 0x00, 0x01, 0x00, 0x01, 0x99 }; + + byte[] totalLen = { 0x00, 0x13 }; + + //wrap the whole data + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + oid.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oid.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发相关仪测距指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + private CommandModel _lastCommand; + + public CommandModel GetLastCommand() + { + return _lastCommand; + } + } +} \ No newline at end of file diff --git a/Correlator/DataService/IApplicationDataService.cs b/Correlator/DataService/IApplicationDataService.cs index c2c29a7..f232681 100644 --- a/Correlator/DataService/IApplicationDataService.cs +++ b/Correlator/DataService/IApplicationDataService.cs @@ -8,7 +8,7 @@ public interface IApplicationDataService { ObservableCollection GetPipeMaterial(); - + ObservableCollection GetVelocityCollection(string materialName); void DeleteVelocity(MaterialVelocity velocity); @@ -26,11 +26,31 @@ int GetSoundVelocity(string material, int pipeDiameter); AudioVisualizer GetAudioVisualizer(int waveDataSize); - + /// /// 获取 HSV 中所有的基础颜色 (饱和度和明度均为最大值) /// /// 所有的 HSV 基础颜色(共 256 * 6 个, 并且随着索引增加, 颜色也会渐变) Color[] GetAllHsvColors(); + + /// + /// 加载所有工作模式的采样率 + /// + /// + ObservableCollection GetSampleRate(); + + /// + /// 根据工作模式获取采样率 + /// + /// + /// + int GetSampleRateByWorkMode(int mode); + + /// + /// 更新采样率 + /// + /// + /// + void UpdateSampleRate(int mode, int sampleRate); } } \ No newline at end of file diff --git a/Correlator/DataService/IAudioService.cs b/Correlator/DataService/IAudioService.cs index 3295b74..9bf2316 100644 --- a/Correlator/DataService/IAudioService.cs +++ b/Correlator/DataService/IAudioService.cs @@ -11,7 +11,8 @@ /// 开始听音 /// /// - void Start(string deviceCode); + /// + void Start(string deviceCode, int sampleRate); /// /// 缓存听音数据 diff --git a/Correlator/DataService/ICommandService.cs b/Correlator/DataService/ICommandService.cs new file mode 100644 index 0000000..d3d2c53 --- /dev/null +++ b/Correlator/DataService/ICommandService.cs @@ -0,0 +1,69 @@ +using System.Collections.Generic; +using System.IO.Ports; +using Correlator.Model; + +namespace Correlator.DataService +{ + public interface ICommandService + { + /// + /// 下发唤醒指令-加速度计 + /// + /// + void SendCorrelatorWakeUpCmd(SerialPort sp); + + /// + /// 下发唤醒指令-水听器 + /// + /// + void SendHydrophoneWakeUpCmd(SerialPort sp); + + /// + /// 水听器点名指令 + /// + /// + /// + void StartCheckResponse(SerialPort sp, string devCode); + + /// + /// 发送校验结果指令给下位机 + /// + /// + /// + /// 异常数据角标集合 + void SendDataCheckResultCmd(SerialPort sp, string devCode, List indexArray); + + /// + /// 下发状态采集指令 + /// + /// + /// + void SendCellAndStatusCollectCmd(SerialPort sp, byte devId); + + /// + /// 下发听音指令 + /// + /// + /// + void SendSoundCollectCmd(SerialPort sp, string devCode); + + /// + /// 下发听音停止指令 + /// + /// + /// + void SendSoundStopCmd(SerialPort sp, string devCode); + + /// + /// 下发测距指令 + /// + /// + void SendCorrelatorRangingCmd(SerialPort sp); + + /// + /// 获取最新下发指令集合 + /// + /// + CommandModel GetLastCommand(); + } +} \ No newline at end of file diff --git a/Correlator/DataService/SerialPortServiceImpl.cs b/Correlator/DataService/SerialPortServiceImpl.cs index e18210e..364ee77 100644 --- a/Correlator/DataService/SerialPortServiceImpl.cs +++ b/Correlator/DataService/SerialPortServiceImpl.cs @@ -15,6 +15,8 @@ { private readonly IEventAggregator _eventAggregator; private readonly IAudioService _audioService; + private readonly ICommandService _commandService; + private readonly IApplicationDataService _dataService; private readonly DevStatus _devStatus = new DevStatus(); private int _checkResponseState; @@ -23,10 +25,14 @@ //左右传感器设备数据 private CorrelatorDataModel _dataModel; - public SerialPortServiceImpl(IEventAggregator eventAggregator, IAudioService audioService) + public SerialPortServiceImpl(IEventAggregator eventAggregator, IAudioService audioService, + ICommandService commandService, IApplicationDataService dataService) { _eventAggregator = eventAggregator; _audioService = audioService; + _commandService = commandService; + _dataService = dataService; + Sp.DataReceived += delegate { while (Sp.BytesToRead < 4) @@ -264,6 +270,7 @@ private void HandleListenData(List tags) { + var sampleRate = _dataService.GetSampleRateByWorkMode(RuntimeCache.WorkMode); //处理接到的噪声数据 var noiseTag = tags.GetUploadNoiseTag(); if (noiseTag != null) @@ -283,9 +290,9 @@ } //PCM数据 - var pcm = new byte[7500 * 3]; //每个采样点2字节 + var pcm = new byte[sampleRate * 3]; //每个采样点2字节 - for (var i = 0; i < 7500; i++) + for (var i = 0; i < sampleRate; i++) { pcm[i * 3 + 2] = dataValue[i * 2 + 0]; pcm[i * 3 + 1] = dataValue[i * 2 + 1]; @@ -357,7 +364,7 @@ } var devId = !RuntimeCache.RedSensorIsEnable ? (byte)0x01 : (byte)0x02; - CommandSender.SendCellAndStatusCollectCmd(Sp, devId); + _commandService.SendCellAndStatusCollectCmd(Sp, devId); Sp.Write("ATA" + Environment.NewLine); } } diff --git a/Correlator/Dialog/CheckResponseDialog.xaml.cs b/Correlator/Dialog/CheckResponseDialog.xaml.cs index 72fd7b6..2cf2c01 100644 --- a/Correlator/Dialog/CheckResponseDialog.xaml.cs +++ b/Correlator/Dialog/CheckResponseDialog.xaml.cs @@ -45,15 +45,17 @@ private readonly IEventAggregator _eventAggregator; private readonly ISerialPortService _serialPortService; private readonly IDialogService _dialogService; + private readonly ICommandService _commandService; public CheckResponseDialog(IEventAggregator eventAggregator, ISerialPortService serialPortService, - IDialogService dialogService) + IDialogService dialogService, ICommandService commandService) { InitializeComponent(); _eventAggregator = eventAggregator; _serialPortService = serialPortService; _dialogService = dialogService; + _commandService = commandService; var today = DateTime.Now.ToString("yyyyMMdd"); var configModel = LazyDataBase.Value.Table() @@ -218,7 +220,7 @@ if (RedSensorStepBar.StepIndex == 1) { RuntimeCache.SeqCaches.Clear(); - CommandSender.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev1); + _commandService.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev1); _redResponseTimer.Start(); ReCheckButton.IsEnabled = true; @@ -226,7 +228,7 @@ else if (RedSensorStepBar.StepIndex == 2) { //下发数据全部正常指令 - CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, new List()); + _commandService.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, new List()); #region 保存原始数据 @@ -295,14 +297,14 @@ if (BlueSensorStepBar.StepIndex == 1) { RuntimeCache.SeqCaches.Clear(); - CommandSender.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev2); + _commandService.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev2); _blueResponseTimer.Start(); ReCheckButton.IsEnabled = true; } else if (BlueSensorStepBar.StepIndex == 2) { - CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, new List()); + _commandService.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, new List()); #region 保存原始数据 @@ -376,7 +378,7 @@ } } - CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, redIndexArray); + _commandService.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, redIndexArray); } else { @@ -397,7 +399,7 @@ } } - CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, blueIndexArray); + _commandService.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, blueIndexArray); } }; } diff --git a/Correlator/Dialog/EditSoundSampleRateDialog.xaml b/Correlator/Dialog/EditSoundSampleRateDialog.xaml new file mode 100644 index 0000000..d441270 --- /dev/null +++ b/Correlator/Dialog/EditSoundSampleRateDialog.xaml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Correlator/Dialog/SoundSampleRateDialog.xaml.cs b/Correlator/Dialog/SoundSampleRateDialog.xaml.cs new file mode 100644 index 0000000..00c933d --- /dev/null +++ b/Correlator/Dialog/SoundSampleRateDialog.xaml.cs @@ -0,0 +1,12 @@ +using System.Windows.Controls; + +namespace Correlator.Dialog +{ + public partial class SoundSampleRateDialog : UserControl + { + public SoundSampleRateDialog() + { + InitializeComponent(); + } + } +} \ No newline at end of file diff --git a/Correlator/Model/CommandModel.cs b/Correlator/Model/CommandModel.cs new file mode 100644 index 0000000..72243b7 --- /dev/null +++ b/Correlator/Model/CommandModel.cs @@ -0,0 +1,8 @@ +namespace Correlator.Model +{ + public class CommandModel + { + public string Value { get; set; } + public string Time { get; set; } + } +} \ No newline at end of file diff --git a/Correlator/Model/SampleRateModel.cs b/Correlator/Model/SampleRateModel.cs new file mode 100644 index 0000000..8ff5239 --- /dev/null +++ b/Correlator/Model/SampleRateModel.cs @@ -0,0 +1,23 @@ +using SQLite; + +namespace Correlator.Model +{ + /// + /// 采样率数据模型 + /// + [Table("SampleRateTable")] + public class SampleRateModel + { + [PrimaryKey, Unique, NotNull, AutoIncrement] + public int Id { get; set; } + + //工作模式 + public int WorkMode { get; set; } + + //采样率 + public int SampleRate { get; set; } + + //采样率更新时间 + public string UpdateDate { get; set; } + } +} \ No newline at end of file diff --git a/Correlator/App.xaml.cs b/Correlator/App.xaml.cs index 5c9dd37..c66d198 100644 --- a/Correlator/App.xaml.cs +++ b/Correlator/App.xaml.cs @@ -98,6 +98,7 @@ containerRegistry.RegisterSingleton(); containerRegistry.RegisterSingleton(); containerRegistry.RegisterSingleton(); + containerRegistry.RegisterSingleton(); //Dialog or Window containerRegistry.RegisterDialog(); @@ -105,6 +106,8 @@ containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); + containerRegistry.RegisterDialog(); + containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); diff --git a/Correlator/Converter/SoundParamValueConverter.cs b/Correlator/Converter/SoundParamValueConverter.cs new file mode 100644 index 0000000..4101a19 --- /dev/null +++ b/Correlator/Converter/SoundParamValueConverter.cs @@ -0,0 +1,26 @@ +using System; +using System.Globalization; +using System.Windows.Data; + +namespace Correlator.Converter +{ + public class SoundParamValueConverter : IMultiValueConverter + { + public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) + { + try + { + return "声速:" + values[0] + "m/s,采样率:" + values[1] + "Hz"; + } + catch (Exception) + { + return null; + } + } + + public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) + { + return null; + } + } +} \ No newline at end of file diff --git a/Correlator/Converter/WorkModeConverter.cs b/Correlator/Converter/WorkModeConverter.cs new file mode 100644 index 0000000..19d0327 --- /dev/null +++ b/Correlator/Converter/WorkModeConverter.cs @@ -0,0 +1,21 @@ +using System; +using System.Diagnostics; +using System.Globalization; +using System.Windows.Data; + +namespace Correlator.Converter +{ + internal class WorkModeConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + Debug.Assert(value != null, nameof(value) + " != null"); + return (int)value == 1 ? "加速度计" : "水听器"; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + return null; + } + } +} \ No newline at end of file diff --git a/Correlator/Correlator.csproj b/Correlator/Correlator.csproj index da299ba..c3a433a 100644 --- a/Correlator/Correlator.csproj +++ b/Correlator/Correlator.csproj @@ -216,10 +216,14 @@ + + + + @@ -240,6 +244,9 @@ DetectNoiseDialog.xaml + + EditSoundSampleRateDialog.xaml + EditSoundSpeedDialog.xaml @@ -249,7 +256,14 @@ LoadingDialog.xaml + + SoundSampleRateDialog.xaml + + + + + ApplicationLogView.xaml @@ -303,7 +317,6 @@ - @@ -343,12 +356,14 @@ MSBuild:Compile + Designer MSBuild:Compile + Designer diff --git a/Correlator/DataService/ApplicationDataServiceImpl.cs b/Correlator/DataService/ApplicationDataServiceImpl.cs index d3f9463..d7f0b68 100644 --- a/Correlator/DataService/ApplicationDataServiceImpl.cs +++ b/Correlator/DataService/ApplicationDataServiceImpl.cs @@ -104,7 +104,7 @@ { return new AudioVisualizer(waveDataSize); } - + public Color[] GetAllHsvColors() { var result = new Color[256 * 6]; @@ -141,5 +141,50 @@ return result; } + + public ObservableCollection GetSampleRate() + { + var sampleRateCollection = new ObservableCollection(); + using (var manager = new DataBaseManager()) + { + var result = manager + .Table() + .ToList(); + foreach (var model in result) + { + sampleRateCollection.Add(model); + } + } + + return sampleRateCollection; + } + + public int GetSampleRateByWorkMode(int mode) + { + using (var manager = new DataBaseManager()) + { + var result = manager + .Table() + .First(x => x.WorkMode == mode); + return result?.SampleRate ?? 7500; + } + } + + public void UpdateSampleRate(int mode, int sampleRate) + { + using (var manager = new DataBaseManager()) + { + var result = manager + .Table() + .First(x => x.WorkMode == mode); + var rateModel = result ?? new SampleRateModel(); + + rateModel.WorkMode = mode; + rateModel.SampleRate = sampleRate; + rateModel.UpdateDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); + + manager.Update(rateModel); + } + } } } \ No newline at end of file diff --git a/Correlator/DataService/AudioServiceImpl.cs b/Correlator/DataService/AudioServiceImpl.cs index fd3375f..c9ccb46 100644 --- a/Correlator/DataService/AudioServiceImpl.cs +++ b/Correlator/DataService/AudioServiceImpl.cs @@ -9,16 +9,17 @@ public class AudioServiceImpl : IAudioService { private bool _isStopped; + private WaveFormat _waveFormat; private WaveFileWriter _waveFileWriter; private BufferedWaveProvider _waveProvider; - private readonly WaveFormat _waveFormat = new WaveFormat(7500, 24, 1); public WaveOutEvent Wave { get; set; } = new WaveOutEvent(); - public void Start(string deviceCode) + public void Start(string deviceCode, int sampleRate) { _isStopped = false; + _waveFormat = new WaveFormat(sampleRate, 24, 1); _waveProvider = new BufferedWaveProvider(_waveFormat); Wave.Init(_waveProvider); diff --git a/Correlator/DataService/CommandServiceImpl.cs b/Correlator/DataService/CommandServiceImpl.cs new file mode 100644 index 0000000..28e3402 --- /dev/null +++ b/Correlator/DataService/CommandServiceImpl.cs @@ -0,0 +1,614 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO.Ports; +using Correlator.Model; +using Correlator.Util; + +namespace Correlator.DataService +{ + public class CommandServiceImpl : ICommandService + { + public void SendCorrelatorWakeUpCmd(SerialPort sp) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + byte[] btDevId = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //广播模式,设备类型不解析 + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + const short pduTypeByte = 2; + var operateType = (short)(pduTypeByte & 0x7F); + + var pdu = (short)(2688 + operateType); //0X0A80 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oid = { 0x30, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00 }; + + byte[] totalLen = { 0x00, 0x13 }; + + //wrap the whole data + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + oid.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oid.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发加速度计数据采集指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendHydrophoneWakeUpCmd(SerialPort sp) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + //后续到CRC字段前的字节总长度(不包括长度字段和CRC字段)。 + byte[] totalLen = { 0x00, 0x1F }; + + byte[] btDevId = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //广播模式,设备类型不解析 + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 2688 + operateType; //0X0A80 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oidTag = + { + 0x40, 0x00, 0x00, 0x01, + 0x00, 0x01, + 0x00 + }; + + //获取时间(年-月-日-时-分-秒),年号-2000 + RuntimeCache.HydrophoneWakeUpTimestamp = new[] + { + CalendarHub.Year, CalendarHub.Mon, CalendarHub.Day, CalendarHub.Hor, CalendarHub.Min, + CalendarHub.Sec + }; + byte[] timeTag = + { + 0x10, 0x00, 0x00, 0x51, + 0x00, 0x06, + RuntimeCache.HydrophoneWakeUpTimestamp[0], RuntimeCache.HydrophoneWakeUpTimestamp[1], + RuntimeCache.HydrophoneWakeUpTimestamp[2], RuntimeCache.HydrophoneWakeUpTimestamp[3], + RuntimeCache.HydrophoneWakeUpTimestamp[4], RuntimeCache.HydrophoneWakeUpTimestamp[5] + }; //时间oid + + //wrap the whole data + var result = new byte[35]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oidTag.CopyTo(result, 16); + timeTag.CopyTo(result, 23); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发水听器数据采集指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void StartCheckResponse(SerialPort sp, string devCode) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + //后续到CRC字段前的字节总长度(不包括长度字段和CRC字段)。 + byte[] totalLen = { 0x00, 0x1F }; + + var btDevId = new byte[6]; + btDevId[0] = byte.Parse(devCode.Substring(0, 2), NumberStyles.HexNumber); + btDevId[1] = byte.Parse(devCode.Substring(2, 2), NumberStyles.HexNumber); + btDevId[2] = byte.Parse(devCode.Substring(4, 2), NumberStyles.HexNumber); + btDevId[3] = byte.Parse(devCode.Substring(6, 2), NumberStyles.HexNumber); + btDevId[4] = byte.Parse(devCode.Substring(8, 2), NumberStyles.HexNumber); + btDevId[5] = byte.Parse(devCode.Substring(10, 2), NumberStyles.HexNumber); + + //通信方式 + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + byte[] btPdu = { 0x01, 0x82 }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oidTag = + { + 0x40, 0x00, 0x00, 0x02, + 0x00, 0x01, + 0x00 + }; + + byte[] timeTag = + { + 0x10, 0x00, 0x00, 0x51, + 0x00, 0x06, + RuntimeCache.HydrophoneWakeUpTimestamp[0], RuntimeCache.HydrophoneWakeUpTimestamp[1], + RuntimeCache.HydrophoneWakeUpTimestamp[2], RuntimeCache.HydrophoneWakeUpTimestamp[3], + RuntimeCache.HydrophoneWakeUpTimestamp[4], RuntimeCache.HydrophoneWakeUpTimestamp[5] + }; //时间oid + + //wrap the whole data + var result = new byte[35]; + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oidTag.CopyTo(result, 16); + timeTag.CopyTo(result, 23); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发水听器点名指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendDataCheckResultCmd(SerialPort sp, string devCode, List indexArray) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + //后续到CRC字段前的字节总长度(不包括长度字段和CRC字段)。 + byte[] totalLen = { 0x00, 0x26 }; + + var btDevId = new byte[6]; + btDevId[0] = byte.Parse(devCode.Substring(0, 2), NumberStyles.HexNumber); + btDevId[1] = byte.Parse(devCode.Substring(2, 2), NumberStyles.HexNumber); + btDevId[2] = byte.Parse(devCode.Substring(4, 2), NumberStyles.HexNumber); + btDevId[3] = byte.Parse(devCode.Substring(6, 2), NumberStyles.HexNumber); + btDevId[4] = byte.Parse(devCode.Substring(8, 2), NumberStyles.HexNumber); + btDevId[5] = byte.Parse(devCode.Substring(10, 2), NumberStyles.HexNumber); + + //通信方式 + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + byte[] btPdu = { 0x05, 0x82 }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + //check result tag + var byteArray = indexArray.ToByteArray(); + byte[] oidTag = + { + 0x60, 0x00, 0x03, 0x00, + 0x00, 0x08, + byteArray[0], byteArray[1], byteArray[2], byteArray[3], + byteArray[4], byteArray[5], byteArray[6], byteArray[7] + }; + + byte[] timeTag = + { + 0x10, 0x00, 0x00, 0x51, + 0x00, 0x06, + RuntimeCache.HydrophoneWakeUpTimestamp[0], RuntimeCache.HydrophoneWakeUpTimestamp[1], + RuntimeCache.HydrophoneWakeUpTimestamp[2], RuntimeCache.HydrophoneWakeUpTimestamp[3], + RuntimeCache.HydrophoneWakeUpTimestamp[4], RuntimeCache.HydrophoneWakeUpTimestamp[5] + }; //时间oid + + //wrap the whole data + var result = new byte[42]; + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oidTag.CopyTo(result, 16); + timeTag.CopyTo(result, 30); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发水听器检查指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendCellAndStatusCollectCmd(SerialPort sp, byte devId) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + byte[] btDevId = { 0x21, 0x17, 0x00, 0x08, 0x22, devId }; //广播模式,设备类型不解析 + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0x22, devId }; + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 2688 + operateType; //0X0A80 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oid = { 0x60, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00 }; + + byte[] totalLen = { 0x00, 0x13 }; + + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + oid.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oid.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "设备 " + devId + " 下发状态采集指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendSoundCollectCmd(SerialPort sp, string devCode) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + //byte[] btDevId = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //广播模式,设备类型不解析 + var btDevId = new byte[6]; + btDevId[0] = byte.Parse(devCode.Substring(0, 2), NumberStyles.HexNumber); + btDevId[1] = byte.Parse(devCode.Substring(2, 2), NumberStyles.HexNumber); + btDevId[2] = byte.Parse(devCode.Substring(4, 2), NumberStyles.HexNumber); + btDevId[3] = byte.Parse(devCode.Substring(6, 2), NumberStyles.HexNumber); + btDevId[4] = byte.Parse(devCode.Substring(8, 2), NumberStyles.HexNumber); + btDevId[5] = byte.Parse(devCode.Substring(10, 2), NumberStyles.HexNumber); + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + var dstNodeAddr = devCode.Substring(8); //2个字节 ** ****** **** + var btDstNode = new byte[2]; + btDstNode[0] = byte.Parse(dstNodeAddr.Substring(0, 2), NumberStyles.HexNumber); + btDstNode[1] = byte.Parse(dstNodeAddr.Substring(2, 2), NumberStyles.HexNumber); + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 2688 + operateType; + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + //第一个Tag的Oid为“0x30000001”,第二个Tag为时间戳,Oid为“0x10000051”,内容为“年、月、日、时、分、秒” + byte[] oid = { 0x20, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00 }; //Tag1 + + byte[] totalLen = { 0x00, 0x13 }; + + //wrap the whole data + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + oid.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oid.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发听音指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendSoundStopCmd(SerialPort sp, string devCode) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + var btDevId = new byte[6]; + btDevId[0] = byte.Parse(devCode.Substring(0, 2), NumberStyles.HexNumber); + btDevId[1] = byte.Parse(devCode.Substring(2, 2), NumberStyles.HexNumber); + btDevId[2] = byte.Parse(devCode.Substring(4, 2), NumberStyles.HexNumber); + btDevId[3] = byte.Parse(devCode.Substring(6, 2), NumberStyles.HexNumber); + btDevId[4] = byte.Parse(devCode.Substring(8, 2), NumberStyles.HexNumber); + btDevId[5] = byte.Parse(devCode.Substring(10, 2), NumberStyles.HexNumber); + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + var dstNodeAddr = devCode.Substring(8); //2个字节 ** ****** **** + var btDstNode = new byte[2]; + btDstNode[0] = byte.Parse(dstNodeAddr.Substring(0, 2), NumberStyles.HexNumber); + btDstNode[1] = byte.Parse(dstNodeAddr.Substring(2, 2), NumberStyles.HexNumber); + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 1408 + operateType; //0x0582 TrapResponse+z噪声记录仪 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] sysTag = + { + 0x10, 0x00, 0x00, 0x51, 0x00, 0x06, + CalendarHub.Year, CalendarHub.Mon, CalendarHub.Day, CalendarHub.Hor, CalendarHub.Min, + CalendarHub.Sec + }; //Tag2 + + byte[] totalLen = { 0x00, 0x18 }; + + //wrap the whole data + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + sysTag.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + sysTag.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发听音结束指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + public void SendCorrelatorRangingCmd(SerialPort sp) + { + const string preamble = "A3"; + var preambleByte = byte.Parse(preamble, NumberStyles.HexNumber); + + const string version = "20"; + var btVersion = byte.Parse(version, NumberStyles.HexNumber); + + byte[] btDevId = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //广播模式,设备类型不解析 + + const string routeFlag = "1"; + var btRouteFlag = byte.Parse(routeFlag, NumberStyles.HexNumber); + + byte[] btDstNode = { 0xFF, 0xFF }; + + const short pduTypeByte = 2; + const short operateType = pduTypeByte & 0x7F; + + const short pdu = 2688 + operateType; //0X0A80 + var btPdu0 = BitConverter.GetBytes(pdu); + byte[] btPdu = { btPdu0[1], btPdu0[0] }; + + const string seq = "1"; + var btSeq = byte.Parse(seq, NumberStyles.HexNumber); + + byte[] oid = { 0x30, 0x00, 0x00, 0x01, 0x00, 0x01, 0x99 }; + + byte[] totalLen = { 0x00, 0x13 }; + + //wrap the whole data + var result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + oid.Length]; + + result[0] = preambleByte; + result[1] = btVersion; + totalLen.CopyTo(result, 2); + btDevId.CopyTo(result, 4); + result[10] = btRouteFlag; + btDstNode.CopyTo(result, 11); + btPdu.CopyTo(result, 13); + result[15] = btSeq; + oid.CopyTo(result, 16); + + //增加CRC校验 + var strCrc = $"{(int)CrcCodeHub.GenerateCrc16Code(result):X}".ConvertToHexString(); + byte[] crcByte = + { + strCrc.Substring(0, 2).ConvertToByte(), + strCrc.Substring(2, 2).ConvertToByte() + }; + + var afCrc = new byte[result.Length + 2]; + result.CopyTo(afCrc, 0); + crcByte.CopyTo(afCrc, result.Length); + sp.Write(afCrc, 0, afCrc.Length); + + var command = "下发相关仪测距指令:" + BitConverter.ToString(afCrc); + _lastCommand = new CommandModel + { + Value = command, + Time = DateTime.Now.ToString("HH:mm:ss") + }; + "CommandServiceImpl".WriteLog(command); + } + + private CommandModel _lastCommand; + + public CommandModel GetLastCommand() + { + return _lastCommand; + } + } +} \ No newline at end of file diff --git a/Correlator/DataService/IApplicationDataService.cs b/Correlator/DataService/IApplicationDataService.cs index c2c29a7..f232681 100644 --- a/Correlator/DataService/IApplicationDataService.cs +++ b/Correlator/DataService/IApplicationDataService.cs @@ -8,7 +8,7 @@ public interface IApplicationDataService { ObservableCollection GetPipeMaterial(); - + ObservableCollection GetVelocityCollection(string materialName); void DeleteVelocity(MaterialVelocity velocity); @@ -26,11 +26,31 @@ int GetSoundVelocity(string material, int pipeDiameter); AudioVisualizer GetAudioVisualizer(int waveDataSize); - + /// /// 获取 HSV 中所有的基础颜色 (饱和度和明度均为最大值) /// /// 所有的 HSV 基础颜色(共 256 * 6 个, 并且随着索引增加, 颜色也会渐变) Color[] GetAllHsvColors(); + + /// + /// 加载所有工作模式的采样率 + /// + /// + ObservableCollection GetSampleRate(); + + /// + /// 根据工作模式获取采样率 + /// + /// + /// + int GetSampleRateByWorkMode(int mode); + + /// + /// 更新采样率 + /// + /// + /// + void UpdateSampleRate(int mode, int sampleRate); } } \ No newline at end of file diff --git a/Correlator/DataService/IAudioService.cs b/Correlator/DataService/IAudioService.cs index 3295b74..9bf2316 100644 --- a/Correlator/DataService/IAudioService.cs +++ b/Correlator/DataService/IAudioService.cs @@ -11,7 +11,8 @@ /// 开始听音 /// /// - void Start(string deviceCode); + /// + void Start(string deviceCode, int sampleRate); /// /// 缓存听音数据 diff --git a/Correlator/DataService/ICommandService.cs b/Correlator/DataService/ICommandService.cs new file mode 100644 index 0000000..d3d2c53 --- /dev/null +++ b/Correlator/DataService/ICommandService.cs @@ -0,0 +1,69 @@ +using System.Collections.Generic; +using System.IO.Ports; +using Correlator.Model; + +namespace Correlator.DataService +{ + public interface ICommandService + { + /// + /// 下发唤醒指令-加速度计 + /// + /// + void SendCorrelatorWakeUpCmd(SerialPort sp); + + /// + /// 下发唤醒指令-水听器 + /// + /// + void SendHydrophoneWakeUpCmd(SerialPort sp); + + /// + /// 水听器点名指令 + /// + /// + /// + void StartCheckResponse(SerialPort sp, string devCode); + + /// + /// 发送校验结果指令给下位机 + /// + /// + /// + /// 异常数据角标集合 + void SendDataCheckResultCmd(SerialPort sp, string devCode, List indexArray); + + /// + /// 下发状态采集指令 + /// + /// + /// + void SendCellAndStatusCollectCmd(SerialPort sp, byte devId); + + /// + /// 下发听音指令 + /// + /// + /// + void SendSoundCollectCmd(SerialPort sp, string devCode); + + /// + /// 下发听音停止指令 + /// + /// + /// + void SendSoundStopCmd(SerialPort sp, string devCode); + + /// + /// 下发测距指令 + /// + /// + void SendCorrelatorRangingCmd(SerialPort sp); + + /// + /// 获取最新下发指令集合 + /// + /// + CommandModel GetLastCommand(); + } +} \ No newline at end of file diff --git a/Correlator/DataService/SerialPortServiceImpl.cs b/Correlator/DataService/SerialPortServiceImpl.cs index e18210e..364ee77 100644 --- a/Correlator/DataService/SerialPortServiceImpl.cs +++ b/Correlator/DataService/SerialPortServiceImpl.cs @@ -15,6 +15,8 @@ { private readonly IEventAggregator _eventAggregator; private readonly IAudioService _audioService; + private readonly ICommandService _commandService; + private readonly IApplicationDataService _dataService; private readonly DevStatus _devStatus = new DevStatus(); private int _checkResponseState; @@ -23,10 +25,14 @@ //左右传感器设备数据 private CorrelatorDataModel _dataModel; - public SerialPortServiceImpl(IEventAggregator eventAggregator, IAudioService audioService) + public SerialPortServiceImpl(IEventAggregator eventAggregator, IAudioService audioService, + ICommandService commandService, IApplicationDataService dataService) { _eventAggregator = eventAggregator; _audioService = audioService; + _commandService = commandService; + _dataService = dataService; + Sp.DataReceived += delegate { while (Sp.BytesToRead < 4) @@ -264,6 +270,7 @@ private void HandleListenData(List tags) { + var sampleRate = _dataService.GetSampleRateByWorkMode(RuntimeCache.WorkMode); //处理接到的噪声数据 var noiseTag = tags.GetUploadNoiseTag(); if (noiseTag != null) @@ -283,9 +290,9 @@ } //PCM数据 - var pcm = new byte[7500 * 3]; //每个采样点2字节 + var pcm = new byte[sampleRate * 3]; //每个采样点2字节 - for (var i = 0; i < 7500; i++) + for (var i = 0; i < sampleRate; i++) { pcm[i * 3 + 2] = dataValue[i * 2 + 0]; pcm[i * 3 + 1] = dataValue[i * 2 + 1]; @@ -357,7 +364,7 @@ } var devId = !RuntimeCache.RedSensorIsEnable ? (byte)0x01 : (byte)0x02; - CommandSender.SendCellAndStatusCollectCmd(Sp, devId); + _commandService.SendCellAndStatusCollectCmd(Sp, devId); Sp.Write("ATA" + Environment.NewLine); } } diff --git a/Correlator/Dialog/CheckResponseDialog.xaml.cs b/Correlator/Dialog/CheckResponseDialog.xaml.cs index 72fd7b6..2cf2c01 100644 --- a/Correlator/Dialog/CheckResponseDialog.xaml.cs +++ b/Correlator/Dialog/CheckResponseDialog.xaml.cs @@ -45,15 +45,17 @@ private readonly IEventAggregator _eventAggregator; private readonly ISerialPortService _serialPortService; private readonly IDialogService _dialogService; + private readonly ICommandService _commandService; public CheckResponseDialog(IEventAggregator eventAggregator, ISerialPortService serialPortService, - IDialogService dialogService) + IDialogService dialogService, ICommandService commandService) { InitializeComponent(); _eventAggregator = eventAggregator; _serialPortService = serialPortService; _dialogService = dialogService; + _commandService = commandService; var today = DateTime.Now.ToString("yyyyMMdd"); var configModel = LazyDataBase.Value.Table() @@ -218,7 +220,7 @@ if (RedSensorStepBar.StepIndex == 1) { RuntimeCache.SeqCaches.Clear(); - CommandSender.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev1); + _commandService.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev1); _redResponseTimer.Start(); ReCheckButton.IsEnabled = true; @@ -226,7 +228,7 @@ else if (RedSensorStepBar.StepIndex == 2) { //下发数据全部正常指令 - CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, new List()); + _commandService.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, new List()); #region 保存原始数据 @@ -295,14 +297,14 @@ if (BlueSensorStepBar.StepIndex == 1) { RuntimeCache.SeqCaches.Clear(); - CommandSender.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev2); + _commandService.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev2); _blueResponseTimer.Start(); ReCheckButton.IsEnabled = true; } else if (BlueSensorStepBar.StepIndex == 2) { - CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, new List()); + _commandService.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, new List()); #region 保存原始数据 @@ -376,7 +378,7 @@ } } - CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, redIndexArray); + _commandService.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, redIndexArray); } else { @@ -397,7 +399,7 @@ } } - CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, blueIndexArray); + _commandService.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, blueIndexArray); } }; } diff --git a/Correlator/Dialog/EditSoundSampleRateDialog.xaml b/Correlator/Dialog/EditSoundSampleRateDialog.xaml new file mode 100644 index 0000000..d441270 --- /dev/null +++ b/Correlator/Dialog/EditSoundSampleRateDialog.xaml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Correlator/Dialog/SoundSampleRateDialog.xaml.cs b/Correlator/Dialog/SoundSampleRateDialog.xaml.cs new file mode 100644 index 0000000..00c933d --- /dev/null +++ b/Correlator/Dialog/SoundSampleRateDialog.xaml.cs @@ -0,0 +1,12 @@ +using System.Windows.Controls; + +namespace Correlator.Dialog +{ + public partial class SoundSampleRateDialog : UserControl + { + public SoundSampleRateDialog() + { + InitializeComponent(); + } + } +} \ No newline at end of file diff --git a/Correlator/Model/CommandModel.cs b/Correlator/Model/CommandModel.cs new file mode 100644 index 0000000..72243b7 --- /dev/null +++ b/Correlator/Model/CommandModel.cs @@ -0,0 +1,8 @@ +namespace Correlator.Model +{ + public class CommandModel + { + public string Value { get; set; } + public string Time { get; set; } + } +} \ No newline at end of file diff --git a/Correlator/Model/SampleRateModel.cs b/Correlator/Model/SampleRateModel.cs new file mode 100644 index 0000000..8ff5239 --- /dev/null +++ b/Correlator/Model/SampleRateModel.cs @@ -0,0 +1,23 @@ +using SQLite; + +namespace Correlator.Model +{ + /// + /// 采样率数据模型 + /// + [Table("SampleRateTable")] + public class SampleRateModel + { + [PrimaryKey, Unique, NotNull, AutoIncrement] + public int Id { get; set; } + + //工作模式 + public int WorkMode { get; set; } + + //采样率 + public int SampleRate { get; set; } + + //采样率更新时间 + public string UpdateDate { get; set; } + } +} \ No newline at end of file diff --git a/Correlator/Style/MainMenuButtonStyle.xaml b/Correlator/Style/MainMenuButtonStyle.xaml index b8a71b3..dab3481 100644 --- a/Correlator/Style/MainMenuButtonStyle.xaml +++ b/Correlator/Style/MainMenuButtonStyle.xaml @@ -1,5 +1,6 @@  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Correlator/Dialog/SoundSampleRateDialog.xaml.cs b/Correlator/Dialog/SoundSampleRateDialog.xaml.cs new file mode 100644 index 0000000..00c933d --- /dev/null +++ b/Correlator/Dialog/SoundSampleRateDialog.xaml.cs @@ -0,0 +1,12 @@ +using System.Windows.Controls; + +namespace Correlator.Dialog +{ + public partial class SoundSampleRateDialog : UserControl + { + public SoundSampleRateDialog() + { + InitializeComponent(); + } + } +} \ No newline at end of file diff --git a/Correlator/Model/CommandModel.cs b/Correlator/Model/CommandModel.cs new file mode 100644 index 0000000..72243b7 --- /dev/null +++ b/Correlator/Model/CommandModel.cs @@ -0,0 +1,8 @@ +namespace Correlator.Model +{ + public class CommandModel + { + public string Value { get; set; } + public string Time { get; set; } + } +} \ No newline at end of file diff --git a/Correlator/Model/SampleRateModel.cs b/Correlator/Model/SampleRateModel.cs new file mode 100644 index 0000000..8ff5239 --- /dev/null +++ b/Correlator/Model/SampleRateModel.cs @@ -0,0 +1,23 @@ +using SQLite; + +namespace Correlator.Model +{ + /// + /// 采样率数据模型 + /// + [Table("SampleRateTable")] + public class SampleRateModel + { + [PrimaryKey, Unique, NotNull, AutoIncrement] + public int Id { get; set; } + + //工作模式 + public int WorkMode { get; set; } + + //采样率 + public int SampleRate { get; set; } + + //采样率更新时间 + public string UpdateDate { get; set; } + } +} \ No newline at end of file diff --git a/Correlator/Style/MainMenuButtonStyle.xaml b/Correlator/Style/MainMenuButtonStyle.xaml index b8a71b3..dab3481 100644 --- a/Correlator/Style/MainMenuButtonStyle.xaml +++ b/Correlator/Style/MainMenuButtonStyle.xaml @@ -1,5 +1,6 @@  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Correlator/Dialog/SoundSampleRateDialog.xaml.cs b/Correlator/Dialog/SoundSampleRateDialog.xaml.cs new file mode 100644 index 0000000..00c933d --- /dev/null +++ b/Correlator/Dialog/SoundSampleRateDialog.xaml.cs @@ -0,0 +1,12 @@ +using System.Windows.Controls; + +namespace Correlator.Dialog +{ + public partial class SoundSampleRateDialog : UserControl + { + public SoundSampleRateDialog() + { + InitializeComponent(); + } + } +} \ No newline at end of file diff --git a/Correlator/Model/CommandModel.cs b/Correlator/Model/CommandModel.cs new file mode 100644 index 0000000..72243b7 --- /dev/null +++ b/Correlator/Model/CommandModel.cs @@ -0,0 +1,8 @@ +namespace Correlator.Model +{ + public class CommandModel + { + public string Value { get; set; } + public string Time { get; set; } + } +} \ No newline at end of file diff --git a/Correlator/Model/SampleRateModel.cs b/Correlator/Model/SampleRateModel.cs new file mode 100644 index 0000000..8ff5239 --- /dev/null +++ b/Correlator/Model/SampleRateModel.cs @@ -0,0 +1,23 @@ +using SQLite; + +namespace Correlator.Model +{ + /// + /// 采样率数据模型 + /// + [Table("SampleRateTable")] + public class SampleRateModel + { + [PrimaryKey, Unique, NotNull, AutoIncrement] + public int Id { get; set; } + + //工作模式 + public int WorkMode { get; set; } + + //采样率 + public int SampleRate { get; set; } + + //采样率更新时间 + public string UpdateDate { get; set; } + } +} \ No newline at end of file diff --git a/Correlator/Style/MainMenuButtonStyle.xaml b/Correlator/Style/MainMenuButtonStyle.xaml index b8a71b3..dab3481 100644 --- a/Correlator/Style/MainMenuButtonStyle.xaml +++ b/Correlator/Style/MainMenuButtonStyle.xaml @@ -1,5 +1,6 @@  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Correlator/Dialog/SoundSampleRateDialog.xaml.cs b/Correlator/Dialog/SoundSampleRateDialog.xaml.cs new file mode 100644 index 0000000..00c933d --- /dev/null +++ b/Correlator/Dialog/SoundSampleRateDialog.xaml.cs @@ -0,0 +1,12 @@ +using System.Windows.Controls; + +namespace Correlator.Dialog +{ + public partial class SoundSampleRateDialog : UserControl + { + public SoundSampleRateDialog() + { + InitializeComponent(); + } + } +} \ No newline at end of file diff --git a/Correlator/Model/CommandModel.cs b/Correlator/Model/CommandModel.cs new file mode 100644 index 0000000..72243b7 --- /dev/null +++ b/Correlator/Model/CommandModel.cs @@ -0,0 +1,8 @@ +namespace Correlator.Model +{ + public class CommandModel + { + public string Value { get; set; } + public string Time { get; set; } + } +} \ No newline at end of file diff --git a/Correlator/Model/SampleRateModel.cs b/Correlator/Model/SampleRateModel.cs new file mode 100644 index 0000000..8ff5239 --- /dev/null +++ b/Correlator/Model/SampleRateModel.cs @@ -0,0 +1,23 @@ +using SQLite; + +namespace Correlator.Model +{ + /// + /// 采样率数据模型 + /// + [Table("SampleRateTable")] + public class SampleRateModel + { + [PrimaryKey, Unique, NotNull, AutoIncrement] + public int Id { get; set; } + + //工作模式 + public int WorkMode { get; set; } + + //采样率 + public int SampleRate { get; set; } + + //采样率更新时间 + public string UpdateDate { get; set; } + } +} \ No newline at end of file diff --git a/Correlator/Style/MainMenuButtonStyle.xaml b/Correlator/Style/MainMenuButtonStyle.xaml index b8a71b3..dab3481 100644 --- a/Correlator/Style/MainMenuButtonStyle.xaml +++ b/Correlator/Style/MainMenuButtonStyle.xaml @@ -1,5 +1,6 @@  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Correlator/Dialog/SoundSampleRateDialog.xaml.cs b/Correlator/Dialog/SoundSampleRateDialog.xaml.cs new file mode 100644 index 0000000..00c933d --- /dev/null +++ b/Correlator/Dialog/SoundSampleRateDialog.xaml.cs @@ -0,0 +1,12 @@ +using System.Windows.Controls; + +namespace Correlator.Dialog +{ + public partial class SoundSampleRateDialog : UserControl + { + public SoundSampleRateDialog() + { + InitializeComponent(); + } + } +} \ No newline at end of file diff --git a/Correlator/Model/CommandModel.cs b/Correlator/Model/CommandModel.cs new file mode 100644 index 0000000..72243b7 --- /dev/null +++ b/Correlator/Model/CommandModel.cs @@ -0,0 +1,8 @@ +namespace Correlator.Model +{ + public class CommandModel + { + public string Value { get; set; } + public string Time { get; set; } + } +} \ No newline at end of file diff --git a/Correlator/Model/SampleRateModel.cs b/Correlator/Model/SampleRateModel.cs new file mode 100644 index 0000000..8ff5239 --- /dev/null +++ b/Correlator/Model/SampleRateModel.cs @@ -0,0 +1,23 @@ +using SQLite; + +namespace Correlator.Model +{ + /// + /// 采样率数据模型 + /// + [Table("SampleRateTable")] + public class SampleRateModel + { + [PrimaryKey, Unique, NotNull, AutoIncrement] + public int Id { get; set; } + + //工作模式 + public int WorkMode { get; set; } + + //采样率 + public int SampleRate { get; set; } + + //采样率更新时间 + public string UpdateDate { get; set; } + } +} \ No newline at end of file diff --git a/Correlator/Style/MainMenuButtonStyle.xaml b/Correlator/Style/MainMenuButtonStyle.xaml index b8a71b3..dab3481 100644 --- a/Correlator/Style/MainMenuButtonStyle.xaml +++ b/Correlator/Style/MainMenuButtonStyle.xaml @@ -1,5 +1,6 @@  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Correlator/Dialog/SoundSampleRateDialog.xaml.cs b/Correlator/Dialog/SoundSampleRateDialog.xaml.cs new file mode 100644 index 0000000..00c933d --- /dev/null +++ b/Correlator/Dialog/SoundSampleRateDialog.xaml.cs @@ -0,0 +1,12 @@ +using System.Windows.Controls; + +namespace Correlator.Dialog +{ + public partial class SoundSampleRateDialog : UserControl + { + public SoundSampleRateDialog() + { + InitializeComponent(); + } + } +} \ No newline at end of file diff --git a/Correlator/Model/CommandModel.cs b/Correlator/Model/CommandModel.cs new file mode 100644 index 0000000..72243b7 --- /dev/null +++ b/Correlator/Model/CommandModel.cs @@ -0,0 +1,8 @@ +namespace Correlator.Model +{ + public class CommandModel + { + public string Value { get; set; } + public string Time { get; set; } + } +} \ No newline at end of file diff --git a/Correlator/Model/SampleRateModel.cs b/Correlator/Model/SampleRateModel.cs new file mode 100644 index 0000000..8ff5239 --- /dev/null +++ b/Correlator/Model/SampleRateModel.cs @@ -0,0 +1,23 @@ +using SQLite; + +namespace Correlator.Model +{ + /// + /// 采样率数据模型 + /// + [Table("SampleRateTable")] + public class SampleRateModel + { + [PrimaryKey, Unique, NotNull, AutoIncrement] + public int Id { get; set; } + + //工作模式 + public int WorkMode { get; set; } + + //采样率 + public int SampleRate { get; set; } + + //采样率更新时间 + public string UpdateDate { get; set; } + } +} \ No newline at end of file diff --git a/Correlator/Style/MainMenuButtonStyle.xaml b/Correlator/Style/MainMenuButtonStyle.xaml index b8a71b3..dab3481 100644 --- a/Correlator/Style/MainMenuButtonStyle.xaml +++ b/Correlator/Style/MainMenuButtonStyle.xaml @@ -1,5 +1,6 @@  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Correlator/Dialog/SoundSampleRateDialog.xaml.cs b/Correlator/Dialog/SoundSampleRateDialog.xaml.cs new file mode 100644 index 0000000..00c933d --- /dev/null +++ b/Correlator/Dialog/SoundSampleRateDialog.xaml.cs @@ -0,0 +1,12 @@ +using System.Windows.Controls; + +namespace Correlator.Dialog +{ + public partial class SoundSampleRateDialog : UserControl + { + public SoundSampleRateDialog() + { + InitializeComponent(); + } + } +} \ No newline at end of file diff --git a/Correlator/Model/CommandModel.cs b/Correlator/Model/CommandModel.cs new file mode 100644 index 0000000..72243b7 --- /dev/null +++ b/Correlator/Model/CommandModel.cs @@ -0,0 +1,8 @@ +namespace Correlator.Model +{ + public class CommandModel + { + public string Value { get; set; } + public string Time { get; set; } + } +} \ No newline at end of file diff --git a/Correlator/Model/SampleRateModel.cs b/Correlator/Model/SampleRateModel.cs new file mode 100644 index 0000000..8ff5239 --- /dev/null +++ b/Correlator/Model/SampleRateModel.cs @@ -0,0 +1,23 @@ +using SQLite; + +namespace Correlator.Model +{ + /// + /// 采样率数据模型 + /// + [Table("SampleRateTable")] + public class SampleRateModel + { + [PrimaryKey, Unique, NotNull, AutoIncrement] + public int Id { get; set; } + + //工作模式 + public int WorkMode { get; set; } + + //采样率 + public int SampleRate { get; set; } + + //采样率更新时间 + public string UpdateDate { get; set; } + } +} \ No newline at end of file diff --git a/Correlator/Style/MainMenuButtonStyle.xaml b/Correlator/Style/MainMenuButtonStyle.xaml index b8a71b3..dab3481 100644 --- a/Correlator/Style/MainMenuButtonStyle.xaml +++ b/Correlator/Style/MainMenuButtonStyle.xaml @@ -1,5 +1,6 @@  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Correlator/Dialog/SoundSampleRateDialog.xaml.cs b/Correlator/Dialog/SoundSampleRateDialog.xaml.cs new file mode 100644 index 0000000..00c933d --- /dev/null +++ b/Correlator/Dialog/SoundSampleRateDialog.xaml.cs @@ -0,0 +1,12 @@ +using System.Windows.Controls; + +namespace Correlator.Dialog +{ + public partial class SoundSampleRateDialog : UserControl + { + public SoundSampleRateDialog() + { + InitializeComponent(); + } + } +} \ No newline at end of file diff --git a/Correlator/Model/CommandModel.cs b/Correlator/Model/CommandModel.cs new file mode 100644 index 0000000..72243b7 --- /dev/null +++ b/Correlator/Model/CommandModel.cs @@ -0,0 +1,8 @@ +namespace Correlator.Model +{ + public class CommandModel + { + public string Value { get; set; } + public string Time { get; set; } + } +} \ No newline at end of file diff --git a/Correlator/Model/SampleRateModel.cs b/Correlator/Model/SampleRateModel.cs new file mode 100644 index 0000000..8ff5239 --- /dev/null +++ b/Correlator/Model/SampleRateModel.cs @@ -0,0 +1,23 @@ +using SQLite; + +namespace Correlator.Model +{ + /// + /// 采样率数据模型 + /// + [Table("SampleRateTable")] + public class SampleRateModel + { + [PrimaryKey, Unique, NotNull, AutoIncrement] + public int Id { get; set; } + + //工作模式 + public int WorkMode { get; set; } + + //采样率 + public int SampleRate { get; set; } + + //采样率更新时间 + public string UpdateDate { get; set; } + } +} \ No newline at end of file diff --git a/Correlator/Style/MainMenuButtonStyle.xaml b/Correlator/Style/MainMenuButtonStyle.xaml index b8a71b3..dab3481 100644 --- a/Correlator/Style/MainMenuButtonStyle.xaml +++ b/Correlator/Style/MainMenuButtonStyle.xaml @@ -1,5 +1,6 @@  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Correlator/Dialog/SoundSampleRateDialog.xaml.cs b/Correlator/Dialog/SoundSampleRateDialog.xaml.cs new file mode 100644 index 0000000..00c933d --- /dev/null +++ b/Correlator/Dialog/SoundSampleRateDialog.xaml.cs @@ -0,0 +1,12 @@ +using System.Windows.Controls; + +namespace Correlator.Dialog +{ + public partial class SoundSampleRateDialog : UserControl + { + public SoundSampleRateDialog() + { + InitializeComponent(); + } + } +} \ No newline at end of file diff --git a/Correlator/Model/CommandModel.cs b/Correlator/Model/CommandModel.cs new file mode 100644 index 0000000..72243b7 --- /dev/null +++ b/Correlator/Model/CommandModel.cs @@ -0,0 +1,8 @@ +namespace Correlator.Model +{ + public class CommandModel + { + public string Value { get; set; } + public string Time { get; set; } + } +} \ No newline at end of file diff --git a/Correlator/Model/SampleRateModel.cs b/Correlator/Model/SampleRateModel.cs new file mode 100644 index 0000000..8ff5239 --- /dev/null +++ b/Correlator/Model/SampleRateModel.cs @@ -0,0 +1,23 @@ +using SQLite; + +namespace Correlator.Model +{ + /// + /// 采样率数据模型 + /// + [Table("SampleRateTable")] + public class SampleRateModel + { + [PrimaryKey, Unique, NotNull, AutoIncrement] + public int Id { get; set; } + + //工作模式 + public int WorkMode { get; set; } + + //采样率 + public int SampleRate { get; set; } + + //采样率更新时间 + public string UpdateDate { get; set; } + } +} \ No newline at end of file diff --git a/Correlator/Style/MainMenuButtonStyle.xaml b/Correlator/Style/MainMenuButtonStyle.xaml index b8a71b3..dab3481 100644 --- a/Correlator/Style/MainMenuButtonStyle.xaml +++ b/Correlator/Style/MainMenuButtonStyle.xaml @@ -1,5 +1,6 @@  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Correlator/Dialog/SoundSampleRateDialog.xaml.cs b/Correlator/Dialog/SoundSampleRateDialog.xaml.cs new file mode 100644 index 0000000..00c933d --- /dev/null +++ b/Correlator/Dialog/SoundSampleRateDialog.xaml.cs @@ -0,0 +1,12 @@ +using System.Windows.Controls; + +namespace Correlator.Dialog +{ + public partial class SoundSampleRateDialog : UserControl + { + public SoundSampleRateDialog() + { + InitializeComponent(); + } + } +} \ No newline at end of file diff --git a/Correlator/Model/CommandModel.cs b/Correlator/Model/CommandModel.cs new file mode 100644 index 0000000..72243b7 --- /dev/null +++ b/Correlator/Model/CommandModel.cs @@ -0,0 +1,8 @@ +namespace Correlator.Model +{ + public class CommandModel + { + public string Value { get; set; } + public string Time { get; set; } + } +} \ No newline at end of file diff --git a/Correlator/Model/SampleRateModel.cs b/Correlator/Model/SampleRateModel.cs new file mode 100644 index 0000000..8ff5239 --- /dev/null +++ b/Correlator/Model/SampleRateModel.cs @@ -0,0 +1,23 @@ +using SQLite; + +namespace Correlator.Model +{ + /// + /// 采样率数据模型 + /// + [Table("SampleRateTable")] + public class SampleRateModel + { + [PrimaryKey, Unique, NotNull, AutoIncrement] + public int Id { get; set; } + + //工作模式 + public int WorkMode { get; set; } + + //采样率 + public int SampleRate { get; set; } + + //采样率更新时间 + public string UpdateDate { get; set; } + } +} \ No newline at end of file diff --git a/Correlator/Style/MainMenuButtonStyle.xaml b/Correlator/Style/MainMenuButtonStyle.xaml index b8a71b3..dab3481 100644 --- a/Correlator/Style/MainMenuButtonStyle.xaml +++ b/Correlator/Style/MainMenuButtonStyle.xaml @@ -1,5 +1,6 @@  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Correlator/Dialog/SoundSampleRateDialog.xaml.cs b/Correlator/Dialog/SoundSampleRateDialog.xaml.cs new file mode 100644 index 0000000..00c933d --- /dev/null +++ b/Correlator/Dialog/SoundSampleRateDialog.xaml.cs @@ -0,0 +1,12 @@ +using System.Windows.Controls; + +namespace Correlator.Dialog +{ + public partial class SoundSampleRateDialog : UserControl + { + public SoundSampleRateDialog() + { + InitializeComponent(); + } + } +} \ No newline at end of file diff --git a/Correlator/Model/CommandModel.cs b/Correlator/Model/CommandModel.cs new file mode 100644 index 0000000..72243b7 --- /dev/null +++ b/Correlator/Model/CommandModel.cs @@ -0,0 +1,8 @@ +namespace Correlator.Model +{ + public class CommandModel + { + public string Value { get; set; } + public string Time { get; set; } + } +} \ No newline at end of file diff --git a/Correlator/Model/SampleRateModel.cs b/Correlator/Model/SampleRateModel.cs new file mode 100644 index 0000000..8ff5239 --- /dev/null +++ b/Correlator/Model/SampleRateModel.cs @@ -0,0 +1,23 @@ +using SQLite; + +namespace Correlator.Model +{ + /// + /// 采样率数据模型 + /// + [Table("SampleRateTable")] + public class SampleRateModel + { + [PrimaryKey, Unique, NotNull, AutoIncrement] + public int Id { get; set; } + + //工作模式 + public int WorkMode { get; set; } + + //采样率 + public int SampleRate { get; set; } + + //采样率更新时间 + public string UpdateDate { get; set; } + } +} \ No newline at end of file diff --git a/Correlator/Style/MainMenuButtonStyle.xaml b/Correlator/Style/MainMenuButtonStyle.xaml index b8a71b3..dab3481 100644 --- a/Correlator/Style/MainMenuButtonStyle.xaml +++ b/Correlator/Style/MainMenuButtonStyle.xaml @@ -1,5 +1,6 @@