|
|
@@ -0,0 +1,712 @@
|
|
|
+/* 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();
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|