private void WriteLighMode(uint lightMode) { Task.Run(async() => { OnewheelBoard onewheel = OnewheelConnectionHelper.INSTANCE.GetOnewheel(); if (onewheel is null) { await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => ShowInfo("Updating light mode failed - not connected!", 5000)); } else { GattWriteResult result = await onewheel.WriteShortAsync(OnewheelCharacteristicsCache.CHARACTERISTIC_LIGHTING_MODE, (short)lightMode); await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => { if (result != null && result.Status == GattCommunicationStatus.Success) { ShowInfo("💡 Light mode updated!", 5000); } else { ShowInfo("Failed to update light mode: " + (result == null ? "characteristic not found" : result.Status.ToString()), 5000); } }); } }); }
//--------------------------------------------------------Set-, Get- Methods:---------------------------------------------------------\\ #region --Set-, Get- Methods-- public void SetBoard(OnewheelBoard onewheel) { UnSubscribeFromEvents(); this.onewheel = onewheel; SubscribeToEvents(); ShowBattery(); ShowBoard(); }
//--------------------------------------------------------Set-, Get- Methods:---------------------------------------------------------\\ #region --Set-, Get- Methods-- public void SetOnewheel(OnewheelBoard onewheel) { UnsubscribeFromEvents(); this.onewheel = onewheel; SubscribeToEvents(); Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => { ShowOnewheel(); SetVisability(); }).AsTask(); }
private string GetOwTypeName(OnewheelBoard onewheel) { switch (onewheel.owType) { case OnewheelType.ONEWHEEL_PLUS_XR: return("xr"); case OnewheelType.ONEWHEEL_PINT: return("pint"); default: return(""); } }
/// <summary> /// Calculates the response for the given challenge. /// Based on: https://github.com/OnewheelCommunityEdition/OWCE_App/blob/4fc1923323543db849deccbf2998646cdf1bae31/OWCE/OWCE/OWBoard.cs#L899-L914 /// </summary> /// <param name="challenge">The challenge send by the Onewheel.</param> /// <returns>The response for the given challenge.</returns> private async Task <byte[]> CalcResponseAsync(byte[] challenge, OnewheelBoard onewheel) { List <byte> response = new List <byte>(20); response.AddRange(CHALLENGE_FIRST_BYTES); // Get bytes 3 through to 19 (start 3, length 16) byte[] apiKeyArray = new byte[16]; Buffer.BlockCopy(challenge, 3, apiKeyArray, 0, 16); // Convert to hex string. string apiKey = Utils.ByteArrayToHexString(apiKeyArray); // Fetch the Token from the server: return(await FetchTokenAsync(apiKey, onewheel)); }
private async Task UpdateLightLevelAsync() { OnewheelBoard board = OnewheelConnectionHelper.INSTANCE.GetOnewheel(); if (board is null) { return; } try { byte[] data = { WhiteValue, RedValue }; await board.WriteBytesAsync(Uuid, data); Logger.Info("Updated " + Description + " to " + WhiteValue + " and " + RedValue); } catch (Exception e) { Logger.Error("Failed to update light level!", e); } }
private async void printAll_btn_Click(object sender, RoutedEventArgs e) { OnewheelBoard onewheel = OnewheelConnectionHelper.INSTANCE.GetOnewheel(); await onewheel?.PrintAllCharacteristicsAsync(); }
//--------------------------------------------------------Constructor:----------------------------------------------------------------\\ #region --Constructors-- /// <summary> /// Basic Constructor /// </summary> /// <history> /// 17/11/2018 Created [Fabian Sauter] /// </history> public OnewheelChangedEventArgs(OnewheelBoard onewheel) { this.ONEWHEEL = onewheel; }
//--------------------------------------------------------Constructor:----------------------------------------------------------------\\ #region --Constructors-- #endregion //--------------------------------------------------------Set-, Get- Methods:---------------------------------------------------------\\ #region --Set-, Get- Methods-- #endregion //--------------------------------------------------------Misc Methods:---------------------------------------------------------------\\ #region --Misc Methods (Public)-- public abstract Task CalcAndSendResponseAsync(List <byte> serialReadCache, OnewheelBoard onewheel);
//--------------------------------------------------------Constructor:----------------------------------------------------------------\\ #region --Constructors-- public OnewheelUnlockHelper(OnewheelBoard onewheel) { this.ONEWHEEL = onewheel; OnewheelConnectionHelper.INSTANCE.CACHE.CharacteristicChanged += CACHE_CharacteristicChanged; }
//--------------------------------------------------------Constructor:----------------------------------------------------------------\\ #region --Constructors-- #endregion //--------------------------------------------------------Set-, Get- Methods:---------------------------------------------------------\\ #region --Set-, Get- Methods-- #endregion //--------------------------------------------------------Misc Methods:---------------------------------------------------------------\\ #region --Misc Methods (Public)-- public override async Task CalcAndSendResponseAsync(List <byte> serialReadCache, OnewheelBoard onewheel) { byte[] challenge = serialReadCache.ToArray(); byte[] response = CalcResponse(challenge); await onewheel.WriteBytesAsync(OnewheelCharacteristicsCache.CHARACTERISTIC_UART_SERIAL_WRITE, response); Logger.Info("Sent Gemini unlock response to Onewheel challenge."); }
/// <summary> /// Based on: https://github.com/OnewheelCommunityEdition/OWCE_App/blob/4fc1923323543db849deccbf2998646cdf1bae31/OWCE/OWCE/OWBoard.cs#L981 /// </summary> /// <param name="apiKey"></param> /// <param name="onewheel"></param> /// <returns></returns> private async Task <byte[]> FetchTokenAsync(string apiKey, OnewheelBoard onewheel) { string owType = GetOwTypeName(onewheel); string deviceName = GetDeviceName(onewheel); OnewheelApiCredentials apiCredentials = new OnewheelApiCredentials(deviceName); // Check if we have already an API token cached for this device: if (Vault.LoadCredentials(apiCredentials) && string.Equals(apiKey, apiCredentials.apiKey)) { return(Utils.HexStringToByteArray(apiCredentials.apiToken)); } // Else continue with requesting a new API token: apiCredentials.apiKey = apiKey; using (HttpClientHandler handler = new HttpClientHandler()) { handler.AutomaticDecompression = DecompressionMethods.GZip; using (HttpClient client = new HttpClient()) { // Match headers as best as possible: client.DefaultRequestHeaders.Clear(); client.DefaultRequestHeaders.TryAddWithoutValidation("Accept", "application/json"); client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json"); client.DefaultRequestHeaders.TryAddWithoutValidation("Connection", "keep-alive"); client.DefaultRequestHeaders.TryAddWithoutValidation("Accept-Language", "en-us"); client.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", "Basic Og=="); client.DefaultRequestHeaders.TryAddWithoutValidation("Accept-Encoding", "gzip"); // Use the IOS user agent: client.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", "Onewheel/0 CFNetwork/1121.2.2 Darwin/19.2.0"); client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json"); client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json"); // Request unlock key based on board name, board type, and token: Uri uri = BuildUri(deviceName, owType, apiKey); try { HttpResponseMessage response = await client.GetAsync(uri); if (response.IsSuccessStatusCode) { string responseBody = await response.Content.ReadAsStringAsync(); PintGeminiUnlockResponse result = JsonConvert.DeserializeObject <PintGeminiUnlockResponse>(responseBody); if (result is null || string.IsNullOrEmpty(result.key)) { throw new Exception($"Unexpected response code ({response.StatusCode})"); } apiCredentials.apiKey = result.key; Vault.StoreCredentials(apiCredentials); return(Utils.HexStringToByteArray(apiCredentials.apiToken)); } else { throw new Exception($"Unexpected response code ({response.StatusCode})"); } } catch (Exception e) { Logger.Error("Failed to perform Pint Gemini unlock.", e); return(null); } } } }
private string GetDeviceName(OnewheelBoard onewheel) { // TODO use concrete name: return("".ToLowerInvariant().Replace("ow", "")); }