using InTheHand.Net.Bluetooth; using InTheHand.Net.Sockets; using InTheHand.Net; using System; using System.Collections.Generic; using System.Linq; using System.Net.Sockets; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using InTheHand.Windows.Forms; using System.Windows.Forms; using MonitoringTechnology.Models; using Windows.Devices.Bluetooth.GenericAttributeProfile; using Org.BouncyCastle.Utilities; using System.Runtime.InteropServices; using System.Collections.ObjectModel; using UserControl = System.Windows.Controls.UserControl; using MonitoringTechnology.ViewModels; using MaterialDesignThemes.Wpf; using System.Windows.Markup; using MonitoringTechnology.Ble; using MonitoringTechnology.Common; using System.IO; using System.Security.Cryptography; using MonitoringTechnology.Base; using MD5 = MonitoringTechnology.Common.MD5; using System.Runtime.CompilerServices; using System.Windows.Threading; namespace MonitoringTechnology.Views { /// /// SystemOperationView.xaml 的交互逻辑 /// public partial class SystemOperationView : UserControl { private readonly BleManager BleManager = BleManager.Instance; private readonly LYScanPageViewModels ViewModel = new LYScanPageViewModels(); private readonly ObservableCollection Logs = new ObservableCollection(); public static SystemOperationViewModel systemOperationViewModel = new SystemOperationViewModel(); public static FileModel FileModel { get; set; } = new FileModel(); private int LogCount; BluetoothRadio Radio = null; //蓝牙适配器 static bool isSelect = false;//是否已选择蓝牙设备 static bool isSending = false;//数据是否定时发送 public static bool isConnection = false;//是否蓝牙设备出于连接状态 public SystemOperationView() { InitializeComponent(); this.DataContext = systemOperationViewModel; systemOperationViewModel._connectDevice = "连接设备"; listBoxLog.ItemsSource = Logs; } #region 蓝牙设备搜索与连接 /// /// 搜索设备 /// /// /// private void SearchDevice_Click(object sender, RoutedEventArgs e) { Radio = BluetoothRadio.PrimaryRadio;//获取当前PC的蓝牙适配器 if (Radio == null) { System.Windows.MessageBox.Show("电脑蓝牙未打开或者未发现!", "提示", MessageBoxButton.OK, MessageBoxImage.Information); AddLog("电脑蓝牙未打开或者未发现!"); } else { LYScanPage lYScanPage = new LYScanPage(); lYScanPage.ShowDialog(); return; } } /// /// 连接设备 /// /// /// private void buttonConnect_Click(object sender, RoutedEventArgs e) { if (isSelect) { if (systemOperationViewModel.BleDevice.IsConnected) { if (isSending == true) { AddLog("请先关闭数据发送功能后,重新尝试!"); System.Windows.MessageBox.Show("请先关闭数据发送功能后,重新尝试!", "提示", MessageBoxButton.OK, MessageBoxImage.Information); } else { systemOperationViewModel.BleDevice.Disconnect(); } } else { systemOperationViewModel.BleDevice.Connect(); } } else { AddLog("请搜索附近蓝牙设备后重试!!!"); } } /// /// 读取设备名称 /// /// /// private async void buttonRead_Click(object sender, RoutedEventArgs e) { if (isConnection) { byte[] data = await systemOperationViewModel.BleDevice.Read(Uuids.GenericAccess, Uuids.DeviceName); if (data != null) { AddLog($"读取的设备名称: {Encoding.UTF8.GetString(data)}"); } } else { AddLog("请搜索附近蓝牙设备并连接后重试!!!"); } } /// /// 系统校时 /// /// /// private void TimeCheck_Click(object sender, RoutedEventArgs e) { TimeSpan ts = DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0); send_port_time(Convert.ToInt64(ts.TotalSeconds).ToString("X2")); } /// /// 收数据 /// /// /// private void BleDevice_CharacteristicValueChanged(GattCharacteristic sender, byte[] args) { AddLog($"收到数据 <<< {args.ToHex()}"); } /// /// 自定义数据显示功能 --数据解析 /// /// /// private void BleDevice_ReceiveValueChanged(GattCharacteristic sender, string data) { AddLog($"{data}"); } /// /// 连接按钮 /// /// /// private void BleDevice_ConnectionStateChanged(BleDevice sender, bool args) { if (args) { isConnection = true; AddLog("连接成功!"); } else { isConnection = false; AddLog("连接已断开!"); } UpdateConnectButton(args); } /// /// 更新连接按钮信息 /// /// private void UpdateConnectButton(bool connected) { buttonConnect.Dispatcher.Invoke(delegate { if (connected) { systemOperationViewModel.connectDevice = "断开连接"; MainWindow.mainViewModel.IsConnection = "已连接"; MainWindow.mainViewModel.Brush = new SolidColorBrush(Color.FromRgb(0, 255, 127));//设置连接状态颜色-绿色 MainWindow.mainViewModel.LYDevice = LYScanPage._bleDevice.Name; } else { systemOperationViewModel.connectDevice = "连接设备"; MainWindow.mainViewModel.IsConnection = "未连接"; MainWindow.mainViewModel.Brush = new SolidColorBrush(Color.FromRgb(255, 0, 0));//设置连接状态颜色-红色 } }); } /// /// 单次发送数据 /// /// /// private async void buttonSendOne_Click(object sender, RoutedEventArgs e) { if (isConnection) { if (buttonSendOne.Content.ToString() == "单询") { List list = new List() { 0xFE, 0xEF, 0x00, 0x38, 0x00, 0x02, 0x33, 0x00, 0x4F, 0x63, 0x2C, 0x43, 0x04, 0xD2, 0x0D, 0x31, 0x27, 0xD4, 0x09, 0xAE, 0x09, 0xAE, 0x09, 0xAE, 0x09, 0xAE, 0x09, 0xAE, 0x09, 0xAE, 0x09, 0xAE, 0x09, 0xAE, 0x09, 0xAE, 0x09, 0xAE, 0x00, 0x7D, 0x00, 0x7D, 0x00, 0x7D, 0x00, 0x7D, 0x00, 0x7D, 0x00, 0x7D, 0x00, 0x7D, 0x00, 0x7D, 0x00, 0x7D, 0x00, 0x7D }; int a = 0; for (int i = 0; i < list.Count; i++) { a += list[i]; } a = a & 0xFF; list.Add((byte)a); list.Add(0x16); byte[] sendmessage = list.ToArray(); //byte[] data = systemOperationViewModel.TxDataHex.ToData();//待发送的数据 bool success = await systemOperationViewModel.BleDevice.Write(sendmessage); if (success) { //AddLog("发送成功 >>> " + sendmessage.ToHex()); AddLog("已查询当前状态数据,请稍等!"); PreservationData(sendmessage.ToList(), "单次发送数据"); } } else if (buttonSendOne.Content.ToString() == "停止") { buttonSendOne.Content = "单询"; } } else { AddLog("请搜索附近蓝牙设备并连接后重试!!!"); } } int[] result = GetRandom(50); /// /// 循环发送数据 /// /// /// private void buttonSend_Click(object sender, RoutedEventArgs e) { if (isConnection) { if (buttonSend.Content.ToString() == "轮询") { List list = new List() { 0xFE, 0xEF, 0x00, 0x38, 0x00, 0x02, 0x33, 0x00, 0x4F, 0x63, 0x2C, 0x43, 0x04, 0xD2, 0x0D, 0x31, 0x27, 0xD4, 0x09, 0xAE, 0x09, 0xAE, 0x09, 0xAE, 0x09, 0xAE, 0x09, 0xAE, 0x09, 0xAE, 0x09, 0xAE, 0x09, 0xAE, 0x09, 0xAE, 0x09, 0xAE, 0x00, 0x7D, 0x00, 0x7D, 0x00, 0x7D, 0x00, 0x7D, 0x00, 0x7D, 0x00, 0x7D, 0x00, 0x7D, 0x00, 0x7D, 0x00, 0x7D, 0x00, 0x7D }; int a = 0; for (int i = 0; i < list.Count; i++) { a += list[i]; } a = a & 0xFF; list.Add((byte)a); list.Add(0x16); byte[] sendmessage = list.ToArray(); int time = 3;//间隔 isSending = true; Time_Send(time, sendmessage); buttonSend.Content = "停止"; } else if (buttonSend.Content.ToString() == "停止") { isSending = false; buttonSend.Content = "轮询"; } } else { AddLog("请搜索附近蓝牙设备并连接后重试!!!"); } } /// /// 定时发送数据 /// /// /// private async void Time_Send(int time, byte[] message) { while (isSending) { //调用发送的那个方法 bool success = await systemOperationViewModel.BleDevice.Write(message); if (success) { //AddLog("发送成功 >>> " + message.ToHex()); AddLog("定时查询数据中...."); PreservationData(message.ToList(), "定时发送数据"); } //间隔 await Task.Delay(1000 * time); } } /// /// 版本查询 /// /// /// private async void VersionQueryButton_Click(object sender, RoutedEventArgs e) { if (isConnection) { byte[] _send = new byte[] { 0xFE, 0xEF, 0x00, 0x05, 0x00, 0x6F, 0x00, 0x00, 0x16 }; int a = 0; for (int i = 0; i < _send.Length - 2; i++) { a += _send[i]; } a = a & 0xFF; _send[7] = (byte)a; //调用发送的那个方法 bool success = await systemOperationViewModel.BleDevice.Write(_send); if (success) { AddLog("已发送版本查询指令,请稍等!"); PreservationData(_send.ToList(), "版本查询指令"); } } else { AddLog("请搜索附近蓝牙设备并连接后重试!!!"); } } /// /// 文件选择 /// /// /// private void FileSelectionButton_Click(object sender, RoutedEventArgs e) { OpenFileDialog dialog = new OpenFileDialog(); dialog.Multiselect = false;//不允许多选 dialog.Title = "请选择升级程序";//窗口title dialog.Filter = "文本文件(*.bin)|*.bin*";//可选择的文件类型 if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) { systemOperationViewModel.FileSelectionData = dialog.FileName; //获取文件路径 } } /// /// 老版本号 /// public static byte[] old_bbh { get; set; } = new byte[4]; public static void Setbbh(byte[] bbh) { for (int i = 0; i < old_bbh.Length; i++) { old_bbh[i] = bbh[i]; } } static byte[] binchar = new byte[] { }; /// /// 文件发送 /// /// public async void FileSendingButton_Click(object sender, RoutedEventArgs e) { if (isConnection) { if (FileSelectionData.Text == null || FileSelectionData.Text == "") { AddLog("请选择升级文件!!!"); return; } //读取文件 int file_len;//bin文件长度 FileStream MyFile = new FileStream(FileSelectionData.Text, FileMode.Open, FileAccess.Read); BinaryReader Reader = new BinaryReader(MyFile); file_len = (int)MyFile.Length; StringBuilder str = new StringBuilder(); binchar = Reader.ReadBytes(file_len); Reader.Close(); string md5 = MD5.Encrypt(binchar); Console.WriteLine(md5); byte[] _md5 = new byte[md5.Length / 2]; for (int i = 0; i < md5.Length; i += 2) { _md5[i / 2] = Convert.ToByte(md5.Substring(i, 2), 16); } byte[] _send = new byte[] { 0xFE, 0xEF, 0x00, 0x1D, 0x00, 0x6E, 0x00, old_bbh[0], old_bbh[1], old_bbh[2], old_bbh[3], 0x00, 0x00, 0x00, 0x00, _md5[0], _md5[1], _md5[2], _md5[3], _md5[4], _md5[5], _md5[6], _md5[7], _md5[8], _md5[9], _md5[10], _md5[11], _md5[12], _md5[13], _md5[14], _md5[15], 0x00, 0x16 }; int a = 0; for (int i = 0; i < _send.Length - 2; i++) { a += _send[i]; } a = a & 0xFF; _send[31] = (byte)a; //调用发送的那个方法 bool success = await systemOperationViewModel.BleDevice.Write(_send); if (success) { AddLog("已发送版本升级指令,请稍等!"); PreservationData(_send.ToList(), "版本升级指令"); } } else { AddLog("请搜索附近蓝牙设备并连接后重试!!!"); } } #endregion #region 工具类 public SystemOperationView(BleDevice device) : this() { systemOperationViewModel.BleDevice = device; systemOperationViewModel.BleDevice.CharacteristicValueChanged += BleDevice_CharacteristicValueChanged;//收数据 systemOperationViewModel.BleDevice.ConnectionStateChanged += BleDevice_ConnectionStateChanged;//连接变化 systemOperationViewModel.BleDevice.ReceiveValueChanged += BleDevice_ReceiveValueChanged;//自定义数据显示功能 DataContext = systemOperationViewModel; isSelect = true;//已选择蓝牙设备 if (device.IsConnected == true) { systemOperationViewModel.connectDevice = "断开连接"; MainWindow.mainViewModel.IsConnection = "已连接"; MainWindow.mainViewModel.Brush = new SolidColorBrush(Color.FromRgb(0, 255, 127));//设置连接状态颜色-绿色 MainWindow.mainViewModel.LYDevice = device.Name; if (isSending == true)//如果处于循环发送状态 { buttonSend.Content = "停止"; } } else { device.Connect(); } } /// /// 输出日志 /// /// public void AddLog(string msg) { listBoxLog.Dispatcher.Invoke(delegate { if (LogCount > 500) { Logs.RemoveAt(0); } Logs.Add($"{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff} - {msg}"); LogCount++; }); } /// /// 时间同步 /// /// public async void send_port_time(string time) { if (isConnection) { byte[] time_byte = tools.ConvertHexStringToBytes(time); int a = 0xFE + 0xEF + 0x00 + 0x08 + 0x00 + 0x06; for (int i = 0; i < time_byte.Length; i++) { a += time_byte[i]; } //取十六进制最低两位 a = a & 0xFF; string send_mes = "FEEF00080006" + time + a.ToString("X2") + "16"; byte[] bytea = tools.ConvertHexStringToBytes(send_mes); //调用发送的那个方法 bool success = await systemOperationViewModel.BleDevice.Write(bytea); if (success) { AddLog("时间正在同步中,请稍等!"); } } else { AddLog("请搜索附近蓝牙设备并连接后重试!!!"); } } /// /// int数组转化为byte数组 /// /// /// public static byte[] IntArrToByteArr(int[] intArr) { int intSize = sizeof(int) * intArr.Length; byte[] bytArr = new byte[intSize]; //申请一块非托管内存 IntPtr ptr = Marshal.AllocHGlobal(intSize); //复制int数组到该内存块 Marshal.Copy(intArr, 0, ptr, intArr.Length); //复制回byte数组 Marshal.Copy(ptr, bytArr, 0, bytArr.Length); //释放申请的非托管内存 Marshal.FreeHGlobal(ptr); return bytArr; } /// /// 获得无重复随机数组 /// /// 上限n /// 返回随机数组 static int[] GetRandom(int n) { //容器A和B int[] arryA = new int[n]; int[] arryB = new int[n]; //填充容器a for (int i = 0; i < arryA.Length; i++) { arryA[i] = i + 1; } //随机对象 Random r = new Random(); //最后一个元素的索引 如n=100,end=99 int end = n - 1; for (int i = 0; i < n; i++) { //生成随机数 因为随机的是索引 所以从0到100取,end=100 //一个大于等于 minValue 且小于 maxValue 的 32 位带符号整数,即:返回的值范围包括 minValue 但不包括 maxValue。 //如果 minValue 等于 maxValue,则返回 minValue int minValue = 0; int maxValue = end + 1; int ranIndex = r.Next(minValue, maxValue); //把随机数放在容器B中 arryB[i] = arryA[ranIndex]; //用最后一个元素覆盖取出的元素 arryA[ranIndex] = arryA[end]; //缩减随机数生成的范围 end--; } //返回生成的随机数组 return arryB; } /// /// 设备回复文件数据指令 /// /// 文件起始地址 /// 读取长度,0-读取结束 public async void _send(int _start, int _Length) { List _send = new List(); //读取文件的实际长度 int _read_length = (binchar.Length - _start) >= _Length ? _Length : binchar.Length - _start; byte[] _read = new byte[2]; if (_read_length > 255) { _read[0] = BitConverter.GetBytes(_read_length)[1]; _read[1] = BitConverter.GetBytes(_read_length)[0]; } else { _read[0] = 0x00; _read[1] = (byte)_read_length; } byte bb = (byte)((_start + _Length) >= binchar.Length ? 0xFF : 0x00); _send.AddRange(new List() { 0xEF, 0xFE, BitConverter.GetBytes(_read_length + 12)[1], BitConverter.GetBytes(_read_length + 12)[0], 0x01, 0x66, 0x00, BitConverter.GetBytes(binchar.Length)[3], BitConverter.GetBytes(binchar.Length)[2], BitConverter.GetBytes(binchar.Length)[1], BitConverter.GetBytes(binchar.Length)[0], (byte)((_start + _Length) >= binchar.Length ? 0xFF : 0x00), _read[0], _read[1] }); for (int i = _start; i < _start + _read_length; i++) { _send.Add(binchar[i]); } int a = 0; for (int i = 0; i < _send.Count; i++) { a += _send[i]; } _send.AddRange(new List() { (byte)(a & 0xFF), 0x16 }); byte[] sendmessage = _send.ToArray(); bool success = await systemOperationViewModel.BleDevice.Write(sendmessage); if (success) { PreservationData(sendmessage.ToList(), "版本升级发送"); if (binchar.Length != 0) { systemOperationViewModel.ProgressValue = (int)((double)(_start + _read_length) * 100 / (double)binchar.Length); AddLog("当前已上传" + (int)((double)(_start + _read_length) * 100 / (double)binchar.Length) + "%"); if (systemOperationViewModel.ProgressValue == 100) { AddLog("文件已发送"); } } } } /// /// 记录发送数据日志 /// private static string _localtime => $"{DateTime.Now: yyyy-MM-dd HH:mm:ss.fff}"; private void PreservationData(List byteList, string type) { string rec_16 = null; for (int i = 0; i < byteList.Count; i++) { rec_16 += byteList[i].ToString("X2"); //16进制显示 } //以txt文档的形式存储接收到的数据 tools.AddLgoToTXT(FileModel.File_Name + FileModel.File_Time.ToString("yyyy-MM-dd") + "日志" + ".txt", FileModel.File_Path + FileModel.File_Time.ToString("yyyy-MM-dd") + @"\", _localtime + " " + type + ": " + rec_16 + "\r\n"); } #endregion } }