Using the DeviceOS built-in BLE service for setup

I am trying to utilize the BLE service that DeviceOS advertises in listening mode to help do the initial device provisioning. Essentially I want to create similar functionality to the mobile app for setup, but I want to use BLE for web instead of a mobile app.

Digging around, it appears that the communication is done via writing commands to a write characteristic and receiving responses from a notify characteristic. I have verified I can do both from Javascript in the browser.

My hang-up appears to be in the format of the data I am sending to the device, I am getting no responses from the device at all.

From what I can tell, the format used is protobuf to both send and receive data. I figured I would start with a very basic command to confirm my code was correct so I selected the SystemResetRequest as it takes no arguments and I would notice the device rebooting on success. Below is the js script to write the data to the device.

        const OSwriteUuid = "6fa90004-5c4e-48a8-94f4-8030546f36fc";

	protobuf.load("control/config.proto", function(err, root) {
		if (err)
			throw err;
	
		// Obtain a message type
		var AwesomeMessage = root.lookupType("SystemResetRequest");

		console.log(AwesomeMessage);
		// Exemplary payload
		var payload = {option: {"(type_id)": 40}};

		console.log(payload);
	
		// Verify the payload if necessary (i.e. when possibly incomplete or invalid)
		var errMsg = AwesomeMessage.verify(payload);
		if (errMsg)
			throw Error(errMsg);

		console.log(errMsg);
	
		// Create a new message
		var message = AwesomeMessage.create(payload); // or use .fromObject if conversion is necessary
		//var jmessage = AwesomeMessage.fromObject(payload);
		
		console.log(message);

		// Encode a message to an Uint8Array (browser) or Buffer (node)
		var buffer = AwesomeMessage.encode(message).finish();
		// ... do something with buffer
		console.log(buffer);

		const writetoOSble = await this.service.getCharacteristic(OSwriteUuid);
		writetoOSble.writeValue(buffer);
	
		// Decode an Uint8Array (browser) or Buffer (node) to a message
		//var message = AwesomeMessage.decode(buffer);
		// ... do something with message
	
		// If the application uses length-delimited buffers, there is also encodeDelimited and decodeDelimited.
	
		// Maybe convert the message back to a plain object
		//var object = AwesomeMessage.toObject(message, {
		//	longs: String,
		//	enums: String,
		//	bytes: String,
			// see ConversionOptions
		//});
	});

using protobuf.js from here:

and the proto files from here:

When I look at the log information, I think the issue is in the encode function. The Uint8Array seems to have a size of 0 no matter what I put into the payload. Any advice or help is greatly appreciated.

You are heading in the right direction, but there’s an entire protocol that sits on top of the BLE connection. It’s authenticated and encrypted using EC-J/PAKE encryption.

It’s not impossible to figure out, since both the mobile app code and the device code are open source, but it’s complicated and confusing. Also hard to debug because it’s encrypted.

If you can wait a little longer, we’ll have a BLE configuration example app in React Native, as well as some code that could help build a native mobile or browser-based version.

Awesome, and thank you for the quick response.

For now, I created my own BLE service to handle what I need to do, but ultimately we want to migrate to the built in service.

Any idea on a rough timeframe for the initial release of the examples?

1 Like

I wanted to check in again on this to see if there are any updates or a timeframe to when we might be able to expect some BLE configuration examples?

There isn’t a timeframe for the BLE setup example yet.

Is there any documentation at all available now that describes the protocol that sits on the BLE connection and the authentication/encryption. I tried looking through the source code and it wasn’t obvious to me from that alone.

There is no documentation. It’s not a secret as you can reverse engineer it from the open-source mobile apps, but it’s really tricky. Implementing the EC-J/PAKE algorithm is tricky (hint: none of the open-source Javascript libraries implement it in the same way as the devices and mobile apps and won’t work), and doing the protobufs over BLE requires a little effort.

The examples will be released publicly, but I don’t have a schedule for doing so.

@rickkas7 I am exploring using BLE for WiFi credentials setting and wondered if the documentation and examples mentioned in September 2022 have now materialised? I would be very interested in an example of the application-defined control request if this allows my application to implement a custom control request handler that accepts requests from BLE.

Also, am I right to think that chrome browser plus webUSB can act as BLE central and be used to exercise a BLE peripheral for testing without a mobile app?

The information on configuring Wi-Fi by BLE is at Wi-Fi setup options.

You could theoretically configure by BLE from a web browser that supports WebBLE (Chrome, Edge, and Opera) but not on iOS (which doesn't allow WebBLE on those browsers). There isn't an example of doing that, however. The React example would run on web with minor-ish changes, but only with the rest of React. The Android and iOS examples have native code.

There is an example on the page above for configuring from a web browser using USB, which is significantly easier.

USB is fine for production setup however not for customer use.

I have done some searching and have only found examples for ESP32 devices but not with webBLE.

The application-defined control request - anything you could point me towards please?

Another option for configuring using WebBLE is this. It also works with the P2/Photon 2.

Hi Will,
are your customers mostly on one mobile platform or the other (Android vs Iphone)?

Thanks - I had forgotten this (mainly because we skipped Gen3) but liked it when published. @Dan-Kouba any further development of this?

Github repo states...
Future functionality may include:

  • Clear, get, and set WiFi credentials on the device
  • Expose ability to turn library on and off in user code (currently it runs all the time)
  • Add callbacks for successful configuration of credentials
  • Support for P2 module

We need to support iOS and Android mobile devices. I don't get involved in the web or mobile app side - just the device hardware and software. I will need to specify and demo the setup flow though. That's why I am interested in webBLE and I have used chrome running on a Windows laptop to do this before.

Hi Will, I have not officially tested my library with the P2, but I believe it should be fully compatible as it uses standard DVOS APIs.

Also, to your point about needing compatibility across mobile platforms — please note that WebBLE is not supported by Safari mobile, and I don't believe there is an intention from Apple to implement it. Therefore if you wish to provision over BLE on iOS it will require a custom app, or downloading a 3rd party browser app that doesn't use Safari as it's backend as most do.

Dan, thanks - there was just one ripple in the library when using with P2/Photon2 - you were checking the PLATFORM_ID and if it wasn't the Argon exiting with error. Just about to try it out now.

Good catch. If you get it working, please submit a pull request and I will happily get that merged!

Actually noticed that the community library version is pre the P2 and singleton changes which is in the GitHub repo - 2 years ago.

Understand a bit more now and it did pair, scan for WAPs and allow entry and storage of credentials, just the reconnection process not happening. For tomorrow...

I used the Manual example but rather than SYSTEM_MODE(MANUAL) which I found does not connect, I used SEMI_AUTOMATIC.

It paired, scan for networks, selected SSID and entered password, device accepted the credentials and very quickly connected to the WiFi and then the Particle Cloud but then this came out on the log from [system] WARN...

0000095208 [app.BLEWiFiSetupManager] INFO: WiFi credentials set
0000095213 [app.BLEWiFiSetupManager] TRACE: State Transition: 2 -> 1
0000095219 [app] INFO: Provision State Transition: 1 -> 0
0000100784 [system] WARN: Failed to load session data from persistent storage
0000141940 [net.rltkncp] ERROR: linkOutput up=1 link_up=0
0000144249 [system] ERROR: sock_send returned -1 118
0000144356 [comm.dtls] ERROR: mbedtls_ssl_write() failed: -0x4e
0000144586 [system] ERROR: sock_send returned -1 118
0000144695 [comm.dtls] ERROR: mbedtls_ssl_read() failed: -0x4e
0000144826 [comm.protocol] ERROR: Event loop error 34
0000144969 [system] WARN: Communication loop error, closing cloud socket

I disconnected the browser from the BLE device and the device remained cloud connected. What are the WARN and ERRORs all about?

Also, this was done with the GitHub version of the library not the community library install which appears to still have an old version that does not have the singleton model implemented.

I am also seeing this on 5.7.0, but I'll have to recheck if I see it earlier versions.