Giter Club home page Giter Club logo

onewheel-web-bluetooth's Introduction

Onewheel Web Bluetooth

LIVE

This repository demonstrates the use of Web Bluetooth for connecting to a Onewheel, carrying out the unlock mechanism and subscribing to the main service characteristics for debugging.

This project will be extended to support visual and non-visual (vibrator, speaker) indicators of batter level, speed etc.

How It Works

  • Web Bluetooth is used to find and pair with a Onewheel over its GATT server
  • The main service is found by the reverse-engineered UUID e659f300-ea98-11e3-ac10-0800200c9a66
  • All services and their characteristics can be inspected using chrome://bluetooth-internals
  • UART serial characteristics are used to carry out an unlock procedure described in detail below
  • All Web Bluetooth characteristics are thus made available for reading/writing/subscription

What Is Missing

See TODO comments in code.

The unlock mechanism works, but the periodical "reminder" to the board that we are still unlocked fails. I have not been able to pin down why that might be.

The UWP-Onewheel project mentioned below doesn't have this issue. I need to adjust it to output some logging and then check android-ponewheel as well and adjust that to output more logging and then compare both with what's happening in my implementation. I have some garbage coming in on the serial read UART which I don't think I should be seeing and maybe there are problems with unsubscribing from it (and writing to the UART serial write which cause the remind signal to get ignored).

Related Projects

How Does The Unlock Flow Go

Kudos to the good people of this pOnewheel issue thread who figured this stuff out.

  1. Read the value of the firmware revision characteristic (e659f311-ea98-11e3-ac10-0800200c9a66)
  2. Check that the firmware revision characteristic value is known (see the code)
  3. Subscribe to the UART serial read characteristic (e659f3fe-ea98-11e3-ac10-0800200c9a66)
  4. Write the firmware revision characteristic value back to the firmware revision characteristic to initiate unlocking
  5. Collect the UART serial read characteristic value change callbacks until 20 challenge bytes are gathered
  6. Unsubscribe from the UART serial read characteristic
  7. Verify that the first three bytes of the 20 byte challenge value match the known signature 0x43 0x52 0x58
  8. Prepare a challenge response byte array and append the signature bytes 0x43 0x52 0x58 to it
  9. Prepare a password byte array prefilled with the remaining 16 challenge bytes ignoring the last check byte
  10. Append the known password 0xd9 0x25 0x5f 0x0f 0x23 0x35 0x4e 0x19 0ba 0x73 0x9c 0xcd 0xc4 0xa9 0x17 0x65 to it
  11. Compute the MD5 cycle on the password byte array and append the resulting byte array to the response byte array
  12. Append the check byte checkByte = 0; for (let i = 0; i < response.length; i++) checkByte = response[i] ^ checkByte;
  13. Write the response byte array to the UART serial write characteristic

After carrying out these steps, the Onewheel should unlock and you should be able to read/write/subscribe to any service characteristics you like. The list of know characteristics is in the code.

You need to unlock the Onewheel every 24 seconds or less otherwise if will lock you out.

This code demonstrates the correct response derivation from a given challenge:

const challengeText = '4352581f2e39be9702badaea0a0a0a0a0a708f15';
console.log('challenge', challengeText);
const challengeBytes = challengeText.match(/.{2}/g).map(b => Number.parseInt(b, 16));
const signatureBytes = challengeBytes.slice(0, 3);
const signatureText = signatureBytes.map(b => b.toString(16)).join(' ');
console.log('sig', signatureText);
const restBytes = challengeBytes.slice(3, -1); // Except last byte, should be 16
const restText = restBytes.map(b => b.toString(16)).join(' ') + ' = ' + restBytes.length;
console.log('rest', restText);
const passwordBytes = [217, 37, 95, 15, 35, 53, 78, 25, 186, 115, 156, 205, 196, 169, 23, 101];
const passwordText = passwordBytes.map(b => b.toString(16)).join(' ');
console.log('pass', passwordText);
const toMd5Bytes = [...restBytes, ...passwordBytes];
const toMd5Text = toMd5Bytes.map(b => b.toString(16)).join(' ');
console.log('to md5', toMd5Text);
const fromMd5Bytes = [...md5(toMd5Bytes)];
const fromMd5Text = fromMd5Bytes.map(b => b.toString(16)).join(' ');
console.log('from md5', fromMd5Text);
const responseBytes = [...challengeBytes.slice(0, 3), ...fromMd5Bytes];
const responseText = responseBytes.map(b => b.toString(16)).join(' ');
console.log('response', responseText);
let checkByte = 0;
for (let index = 0; index < responseBytes.length; index++) {
  checkByte = responseBytes[index] ^ checkByte;
}

console.log('check byte', checkByte.toString(16));

To-Do

Try connecting to Pint

onewheel-web-bluetooth's People

Contributors

tomashubelbauer avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

Forkers

yomed

onewheel-web-bluetooth's Issues

Still working?

Thanks for making this! I'm able to pair to my XR+ but can't read any characteristics except firmware revision (4162) and hardware revision (4213). Is it still possible to make this work?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.