| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712 |
- /* MainWindow.xaml.cs/Open GoPro, Version 2.0 (C) Copyright 2021 GoPro, Inc. (http://gopro.com/OpenGoPro). */
- /* This copyright was auto-generated on Wed, Sep 1, 2021 5:05:38 PM */
- using System;
- using System.Collections.Generic;
- using System.Collections.ObjectModel;
- using System.ComponentModel;
- using System.Globalization;
- using System.IO;
- using System.Linq;
- using System.Text;
- 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 Windows.Devices.Bluetooth;
- using Windows.Devices.Bluetooth.GenericAttributeProfile;
- using Windows.Devices.Enumeration;
- using Windows.Media.MediaProperties;
- using Windows.Storage.Streams;
- namespace GoProCSharpSample
- {
- /// <summary>
- /// Interaction logic for MainWindow.xaml
- /// </summary>
- public partial class MainWindow : Window, INotifyPropertyChanged
- {
- public class GDeviceInformation
- {
- public GDeviceInformation(DeviceInformation inDeviceInformation, bool inPresent, bool inConnected)
- {
- DeviceInfo = inDeviceInformation;
- IsPresent = inPresent;
- IsConnected = inConnected;
- }
- public DeviceInformation DeviceInfo { get; set; } = null;
- public bool IsPresent { get; set; } = false;
- public bool IsConnected { get; set; } = false;
- public bool IsVisible { get { return IsPresent || IsConnected; } }
- private GDeviceInformation() { }
- }
- #region Binded Properties
- public ObservableCollection<GDeviceInformation> Devices
- {
- get; set;
- } = new ObservableCollection<GDeviceInformation>();
- private bool mEncoding = false;
- public bool Encoding
- {
- get
- {
- return mEncoding;
- }
- set
- {
- mEncoding = value;
- if (this.PropertyChanged != null)
- {
- PropertyChanged(this, new PropertyChangedEventArgs("Encoding"));
- }
- }
- }
- private int mBatterylevel = 0;
- public int BatteryLevel
- {
- get
- {
- return mBatterylevel;
- }
- set
- {
- mBatterylevel = value;
- if (this.PropertyChanged != null)
- {
- PropertyChanged(this, new PropertyChangedEventArgs("BatteryLevel"));
- }
- }
- }
- private bool mWifiOn = false;
- public bool WifiOn
- {
- get
- {
- return mWifiOn;
- }
- set
- {
- mWifiOn = value;
- if (this.PropertyChanged != null)
- {
- PropertyChanged(this, new PropertyChangedEventArgs("WifiOn"));
- }
- }
- }
- #endregion
- #region Bluetooth Device Members
- private BluetoothLEDevice mBLED = null;
- public GattCharacteristic mNotifyCmds = null;
- public GattCharacteristic mSendCmds = null;
- public GattCharacteristic mSetSettings = null;
- public GattCharacteristic mNotifySettings = null;
- public GattCharacteristic mSendQueries = null;
- public GattCharacteristic mNotifyQueryResp = null;
- public GattCharacteristic mReadAPName = null;
- public GattCharacteristic mReadAPPass = null;
- #endregion
- public event PropertyChangedEventHandler PropertyChanged;
- DeviceWatcher mDeviceWatcher = null;
- private readonly Dictionary<string, DeviceInformation> mAllDevices = new Dictionary<string, DeviceInformation>();
- public MainWindow()
- {
- InitializeComponent();
- WindowStartupLocation = WindowStartupLocation.CenterScreen;
- }
- #region Button Click Handlers
- private void BtnScanBLE_Click(object sender, RoutedEventArgs e)
- {
- string BLESelector = "System.Devices.Aep.ProtocolId:=\"{bb7bb05e-5972-42b5-94fc-76eaa7084d49}\"";
- DeviceInformationKind deviceInformationKind = DeviceInformationKind.AssociationEndpoint;
- string[] requiredProperties = { "System.Devices.Aep.Bluetooth.Le.IsConnectable", "System.Devices.Aep.IsConnected" };
- mDeviceWatcher = DeviceInformation.CreateWatcher(BLESelector, requiredProperties, deviceInformationKind);
- mDeviceWatcher.Added += MDeviceWatcher_Added; ;
- mDeviceWatcher.Updated += MDeviceWatcher_Updated; ;
- mDeviceWatcher.Removed += MDeviceWatcher_Removed; ;
- mDeviceWatcher.EnumerationCompleted += MDeviceWatcher_EnumerationCompleted; ;
- mDeviceWatcher.Stopped += MDeviceWatcher_Stopped; ;
- this.txtStatusBar.Text = "Scanning for devices...";
- mDeviceWatcher.Start();
- }
- private async void BtnPair_Click(object sender, RoutedEventArgs e)
- {
- GDeviceInformation lDevice = (GDeviceInformation)lbDevices.SelectedItem;
- if (lDevice != null)
- {
- StatusOutput("Pairing started");
- mBLED = await BluetoothLEDevice.FromIdAsync(lDevice.DeviceInfo.Id);
- mBLED.DeviceInformation.Pairing.Custom.PairingRequested += Custom_PairingRequested;
- if (mBLED.DeviceInformation.Pairing.CanPair)
- {
- DevicePairingProtectionLevel dppl = mBLED.DeviceInformation.Pairing.ProtectionLevel;
- DevicePairingResult dpr = await mBLED.DeviceInformation.Pairing.Custom.PairAsync(DevicePairingKinds.ConfirmOnly, dppl);
- StatusOutput("Pairing result = " + dpr.Status.ToString());
- }
- else
- {
- StatusOutput("Pairing failed");
- }
- }
- else
- {
- StatusOutput("Select a device");
- }
- }
- private async void BtnConnect_Click(object sender, RoutedEventArgs e)
- {
- StatusOutput("Connecting...");
- GDeviceInformation mDI = (GDeviceInformation)lbDevices.SelectedItem;
- if (mDI == null)
- {
- StatusOutput("No device selected");
- return;
- }
- mBLED = await BluetoothLEDevice.FromIdAsync(mDI.DeviceInfo.Id);
- if(!mBLED.DeviceInformation.Pairing.IsPaired)
- {
- StatusOutput("Device not paired");
- return;
- }
- GattDeviceServicesResult result = await mBLED.GetGattServicesAsync();
- mBLED.ConnectionStatusChanged += MBLED_ConnectionStatusChanged;
- if (result.Status == GattCommunicationStatus.Success)
- {
- IReadOnlyList<GattDeviceService> services = result.Services;
- foreach (GattDeviceService gatt in services)
- {
- GattCharacteristicsResult res = await gatt.GetCharacteristicsAsync();
- if (res.Status == GattCommunicationStatus.Success)
- {
- IReadOnlyList<GattCharacteristic> characteristics = res.Characteristics;
- foreach (GattCharacteristic characteristic in characteristics)
- {
- GattCharacteristicProperties properties = characteristic.CharacteristicProperties;
- if (properties.HasFlag(GattCharacteristicProperties.Read))
- {
- // This characteristic supports reading from it.
- }
- if (properties.HasFlag(GattCharacteristicProperties.Write))
- {
- // This characteristic supports writing to it.
- }
- if (properties.HasFlag(GattCharacteristicProperties.Notify))
- {
- // This characteristic supports subscribing to notifications.
- }
- if (characteristic.Uuid.ToString() == "b5f90002-aa8d-11e3-9046-0002a5d5c51b")
- {
- mReadAPName = characteristic;
- }
- if (characteristic.Uuid.ToString() == "b5f90003-aa8d-11e3-9046-0002a5d5c51b")
- {
- mReadAPPass = characteristic;
- }
- if (characteristic.Uuid.ToString() == "b5f90072-aa8d-11e3-9046-0002a5d5c51b")
- {
- mSendCmds = characteristic;
- }
- if (characteristic.Uuid.ToString() == "b5f90073-aa8d-11e3-9046-0002a5d5c51b")
- {
- mNotifyCmds = characteristic;
- GattCommunicationStatus status = await mNotifyCmds.WriteClientCharacteristicConfigurationDescriptorAsync(GattClientCharacteristicConfigurationDescriptorValue.Notify);
- if (status == GattCommunicationStatus.Success)
- {
- mNotifyCmds.ValueChanged += MNotifyCmds_ValueChanged;
- }
- else
- {
- //failure
- StatusOutput("Failed to attach notify cmd " + status);
- }
- }
- if (characteristic.Uuid.ToString() == "b5f90074-aa8d-11e3-9046-0002a5d5c51b")
- {
- mSetSettings = characteristic;
- }
- if (characteristic.Uuid.ToString() == "b5f90075-aa8d-11e3-9046-0002a5d5c51b")
- {
- mNotifySettings = characteristic;
- GattCommunicationStatus status = await mNotifySettings.WriteClientCharacteristicConfigurationDescriptorAsync(GattClientCharacteristicConfigurationDescriptorValue.Notify);
- if (status == GattCommunicationStatus.Success)
- {
- mNotifySettings.ValueChanged += MNotifySettings_ValueChanged;
- }
- else
- {
- //failure
- StatusOutput("Failed to attach notify settings " + status);
- }
- }
- if (characteristic.Uuid.ToString() == "b5f90076-aa8d-11e3-9046-0002a5d5c51b")
- {
- mSendQueries = characteristic;
- }
- if (characteristic.Uuid.ToString() == "b5f90077-aa8d-11e3-9046-0002a5d5c51b")
- {
- mNotifyQueryResp = characteristic;
- GattCommunicationStatus status = await mNotifyQueryResp.WriteClientCharacteristicConfigurationDescriptorAsync(GattClientCharacteristicConfigurationDescriptorValue.Notify);
- if (status == GattCommunicationStatus.Success)
- {
- mNotifyQueryResp.ValueChanged += MNotifyQueryResp_ValueChanged;
- if (mSendQueries != null)
- {
- //Register for settings and status updates
- DataWriter mm = new DataWriter();
- mm.WriteBytes(new byte[] { 1, 0x52 });
- GattCommunicationStatus gat = await mSendQueries.WriteValueAsync(mm.DetachBuffer());
- mm = new DataWriter();
- mm.WriteBytes(new byte[] { 1, 0x53 });
- gat = await mSendQueries.WriteValueAsync(mm.DetachBuffer());
- }
- else
- {
- StatusOutput("send queries was null!");
- }
- }
- else
- {
- //failure
- StatusOutput("Failed to attach notify query " + status);
- }
- }
- }
- }
- }
- SetThirdPartySource();
- }
- else if (result.Status == GattCommunicationStatus.Unreachable)
- {
- //couldn't find camera
- StatusOutput("Connection failed");
- }
- }
- private async void BtnReadAPName_Click(object sender, RoutedEventArgs e)
- {
- if (mReadAPName != null)
- {
- GattReadResult res = await mReadAPName.ReadValueAsync();
- if (res.Status == GattCommunicationStatus.Success)
- {
- DataReader dataReader = Windows.Storage.Streams.DataReader.FromBuffer(res.Value);
- string output = dataReader.ReadString(res.Value.Length);
- txtAPName.Text = output;
- }
- else
- {
- StatusOutput("Failed to read ap name");
- }
- }
- else
- {
- StatusOutput("Not connected");
- }
- }
- private async void BtnReadAPPass_Click(object sender, RoutedEventArgs e)
- {
- if (mReadAPPass != null)
- {
- GattReadResult res = await mReadAPPass.ReadValueAsync();
- if (res.Status == GattCommunicationStatus.Success)
- {
- DataReader dataReader = Windows.Storage.Streams.DataReader.FromBuffer(res.Value);
- string output = dataReader.ReadString(res.Value.Length);
- txtAPPassword.Text = output;
- }
- else
- {
- StatusOutput("Failed to read password");
- }
- }
- else
- {
- StatusOutput("Not connected");
- }
- }
- private void BtnTurnWifiOn_Click(object sender, RoutedEventArgs e)
- {
- TogglefWifiAP(1);
- }
- private void BtnTurnWifiOff_Click(object sender, RoutedEventArgs e)
- {
- TogglefWifiAP(0);
- }
- private void BtnShutterOn_Click(object sender, RoutedEventArgs e)
- {
- ToggleShutter(1);
- }
- private void BtnShutterOff_Click(object sender, RoutedEventArgs e)
- {
- ToggleShutter(0);
- }
- #endregion
- #region Device Watcher Event Handlers
- private void MDeviceWatcher_Stopped(DeviceWatcher sender, object args)
- {
- Application.Current.Dispatcher.BeginInvoke(new Action(() =>
- {
- this.txtStatusBar.Text = "Scan Stopped!";
- }));
- }
- private void MDeviceWatcher_EnumerationCompleted(DeviceWatcher sender, object args)
- {
- Application.Current.Dispatcher.BeginInvoke(new Action(() =>
- {
- this.txtStatusBar.Text = "Scan Complete";
- }));
- }
- private void MDeviceWatcher_Removed(DeviceWatcher sender, DeviceInformationUpdate args)
- {
- for (int i = 0; i < Devices.Count; i++)
- {
- if (Devices[i].DeviceInfo.Id == args.Id)
- {
- Application.Current.Dispatcher.BeginInvoke(new Action(() =>
- {
- Devices.RemoveAt(i);
- }));
- break;
- }
- }
- }
- private void MDeviceWatcher_Updated(DeviceWatcher sender, DeviceInformationUpdate args)
- {
- bool isPresent = false, isConnected = false, found = false;
- if (args.Properties.ContainsKey("System.Devices.Aep.Bluetooth.Le.IsConnectable"))
- {
- isPresent = (bool)args.Properties["System.Devices.Aep.Bluetooth.Le.IsConnectable"];
- }
- if (args.Properties.ContainsKey("System.Devices.Aep.IsConnected"))
- {
- isConnected = (bool)args.Properties["System.Devices.Aep.IsConnected"];
- }
- for (int i = 0; i < Devices.Count; i++)
- {
- if (Devices[i].DeviceInfo.Id == args.Id)
- {
- found = true;
- Application.Current.Dispatcher.BeginInvoke(new Action(() =>
- {
- Devices[i].DeviceInfo.Update(args);
- Devices[i].IsPresent = isPresent;
- Devices[i].IsConnected = isConnected;
- }));
- break;
- }
- }
- if(!found && (isPresent || isConnected))
- {
- if (mAllDevices.ContainsKey(args.Id))
- {
- mAllDevices[args.Id].Update(args);
- Application.Current.Dispatcher.BeginInvoke(new Action(() =>
- {
- Devices.Add(new GDeviceInformation(mAllDevices[args.Id], isPresent, isConnected));
- }));
- }
- }
- }
- private void MDeviceWatcher_Added(DeviceWatcher sender, DeviceInformation args)
- {
- bool isPresent = false;
- bool isConnected = false;
- if (args.Properties.ContainsKey("System.Devices.Aep.Bluetooth.Le.IsConnectable"))
- {
- isPresent = (bool)args.Properties["System.Devices.Aep.Bluetooth.Le.IsConnectable"];
- }
- if (args.Properties.ContainsKey("System.Devices.Aep.IsConnected"))
- {
- isConnected = (bool)args.Properties["System.Devices.Aep.IsConnected"];
- }
- if (args.Name != "" && args.Name.Contains("GoPro"))
- {
- bool found = false;
- if (!mAllDevices.ContainsKey(args.Id))
- {
- mAllDevices.Add(args.Id, args);
- }
- for (int i = 0; i < Devices.Count; i++)
- {
- if (Devices[i].DeviceInfo.Id == args.Id)
- {
- found = true;
- Application.Current.Dispatcher.BeginInvoke(new Action(() =>
- {
- Devices[i].DeviceInfo = args;
- Devices[i].IsPresent = isPresent;
- Devices[i].IsConnected = isConnected;
- }));
- break;
- }
- }
- if (!found && (isPresent || isConnected))
- {
- Application.Current.Dispatcher.BeginInvoke(new Action(() =>
- {
- Devices.Add(new GDeviceInformation(args, isPresent, isConnected));
- }));
- }
- }
- }
- #endregion
- #region BLE Device Handlers
- private void MBLED_ConnectionStatusChanged(BluetoothLEDevice sender, object args)
- {
- if (sender.ConnectionStatus == BluetoothConnectionStatus.Connected)
- StatusOutput("CONNECTED");
- else
- StatusOutput("DISCONNECTED");
- }
- private void Custom_PairingRequested(DeviceInformationCustomPairing sender, DevicePairingRequestedEventArgs args)
- {
- StatusOutput("Pairing request...");
- args.Accept();
- }
- #endregion
- #region Gatt Characteristic Notification Handlers
- private readonly List<byte> mBufQ = new List<byte>();
- private int mExpectedLengthQ = 0;
- private void MNotifyQueryResp_ValueChanged(GattCharacteristic sender, GattValueChangedEventArgs args)
- {
- var reader = DataReader.FromBuffer(args.CharacteristicValue);
- byte[] myBytes = new byte[reader.UnconsumedBufferLength];
- reader.ReadBytes(myBytes);
- int newLength = ReadBytesIntoBuffer(myBytes, mBufQ);
- if (newLength > 0)
- mExpectedLengthQ = newLength;
- if (mExpectedLengthQ == mBufQ.Count)
- {
- if ((mBufQ[0] == 0x53 || mBufQ[0] == 0x93) && mBufQ[1] == 0)
- {
- //status messages
- for (int k = 0; k < mBufQ.Count;)
- {
- if (mBufQ[k] == 10)
- {
- Encoding = mBufQ[k + 2] > 0;
- }
- if (mBufQ[k] == 70)
- {
- BatteryLevel = mBufQ[k + 2];
- }
- if(mBufQ[k] == 69)
- {
- WifiOn = mBufQ[k + 2] == 1;
- }
- k += 2 + mBufQ[k + 1];
- }
- }
- else
- {
- //Unhandled Query Message
- }
- mBufQ.Clear();
- mExpectedLengthQ = 0;
- }
- }
- private readonly List<byte> mBufSet = new List<byte>();
- private int mExpectedLengthSet = 0;
- private void MNotifySettings_ValueChanged(GattCharacteristic sender, GattValueChangedEventArgs args)
- {
- var reader = DataReader.FromBuffer(args.CharacteristicValue);
- byte[] myBytes = new byte[reader.UnconsumedBufferLength];
- reader.ReadBytes(myBytes);
- int newLength = ReadBytesIntoBuffer(myBytes, mBufSet);
- if (newLength > 0)
- mExpectedLengthSet = newLength;
- if (mExpectedLengthSet == mBufSet.Count)
- {
- /*
- if (mBufSet[0] == 0xXX)
- {
- }
- */
- mBufSet.Clear();
- }
- }
- private readonly List<byte> mBufCmd = new List<byte>();
- private int mExpectedLengthCmd = 0;
- private void MNotifyCmds_ValueChanged(GattCharacteristic sender, GattValueChangedEventArgs args)
- {
- var reader = DataReader.FromBuffer(args.CharacteristicValue);
- byte[] myBytes = new byte[reader.UnconsumedBufferLength];
- reader.ReadBytes(myBytes);
- int newLength = ReadBytesIntoBuffer(myBytes, mBufCmd);
- if (newLength > 0)
- mExpectedLengthCmd = newLength;
- if (mExpectedLengthCmd == mBufCmd.Count)
- {
- /*
- if (mBufCmd[0] == 0xXX)
- {
- }
- */
- mBufCmd.Clear();
- }
- }
- #endregion
- #region Private Helper Functions
- private async void SetThirdPartySource()
- {
- DataWriter mm = new DataWriter();
- mm.WriteBytes(new byte[] { 0x01, 0x50 });
- GattCommunicationStatus res = GattCommunicationStatus.Unreachable;
- if (mSendCmds != null)
- {
- res = await mSendCmds.WriteValueAsync(mm.DetachBuffer());
- }
- if (res != GattCommunicationStatus.Success && mSendCmds != null)
- {
- StatusOutput("Failed to set command source: " + res.ToString());
- }
- }
- private void StatusOutput(string status)
- {
- Application.Current.Dispatcher.BeginInvoke(new Action(() =>
- {
- this.txtStatusBar.Text = status;
- }));
- }
- private int ReadBytesIntoBuffer(byte[] bytes, List<byte> mBuf)
- {
- int returnLength = -1;
- int startbyte = 1;
- int theseBytes = bytes.Length;
- if ((bytes[0] & 32) > 0)
- {
- //extended 13 bit header
- startbyte = 2;
- int len = ((bytes[0] & 0xF) << 8) | bytes[1];
- returnLength = len;
- }
- else if ((bytes[0] & 64) > 0)
- {
- //extended 16 bit header
- startbyte = 3;
- int len = (bytes[1] << 8) | bytes[2];
- returnLength = len;
- }
- else if ((bytes[0] & 128) > 0)
- {
- //its a continuation packet
- }
- else
- {
- //8 bit header
- returnLength = bytes[0];
- }
- for (int k = startbyte; k < theseBytes; k++)
- mBuf.Add(bytes[k]);
- return returnLength;
- }
- private async void TogglefWifiAP(int onOff)
- {
- DataWriter mm = new DataWriter();
- mm.WriteBytes(new byte[] { 0x03, 0x17, 0x01, (byte)onOff });
- GattCommunicationStatus res = GattCommunicationStatus.Unreachable;
- if (onOff != 1 && onOff != 0)
- {
- res = GattCommunicationStatus.AccessDenied;
- }
- else if (mSendCmds != null)
- {
- res = await mSendCmds.WriteValueAsync(mm.DetachBuffer());
- }
- if (res != GattCommunicationStatus.Success)
- {
- StatusOutput("Failed to turn on wifi: " + res.ToString());
- }
- }
- private async void ToggleShutter(int onOff)
- {
- DataWriter mm = new DataWriter();
- mm.WriteBytes(new byte[] { 3, 1, 1, (byte)onOff });
- GattCommunicationStatus res = GattCommunicationStatus.Unreachable;
- if (onOff != 1 && onOff != 0)
- {
- res = GattCommunicationStatus.AccessDenied;
- }
- else if (mSendCmds != null)
- {
- res = await mSendCmds.WriteValueAsync(mm.DetachBuffer());
- }
- if (res != GattCommunicationStatus.Success)
- {
- StatusOutput("Failed to send shutter: " + res.ToString());
- }
- }
- #endregion
- }
- public class BrushBoolColorConverter : IValueConverter
- {
- public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
- {
- if (!(bool)value)
- {
- return new SolidColorBrush(Color.FromRgb(100, 100, 100));
- }
- return new SolidColorBrush(Color.FromRgb(255, 100, 100));
- }
- public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
- {
- throw new NotImplementedException();
- }
- }
- }
|