Android Question Connect To Bluetooth Dice

bocker77

Active Member
Licensed User
Longtime User
The company that manufactures bluetooth dice were kind enough to send me a browser application to test out the dice to make sure they are working properly. The application consists of an html, css, and two javascript files. Now I am attempting to make sense of what needs to be done to incorporate this into B4X. The javascript code is a main and a class.

The code in the main, main.js, to request a connection
B4X:
// Open the Bluetooth connection dialog for choosing a GoDice to connect
function openConnectionDialog() {
    const newDice = new GoDice();
    newDice.requestDevice();
}

The code in the class, godice.js, to connect to a die
B4X:
/**
     * Open a connection dialog to connect a single GoDice, after successfull connection it will follow by corresponding "DiceConnected" event (response).
     */
    requestDevice() {
        return navigator.bluetooth.requestDevice({
            filters: [{ namePrefix: 'GoDice_' }],
            optionalServices: ['6e400001-b5a3-f393-e0a9-e50e24dcca9e']
        })
            .then(async device => {                
                this.GlobalDeviceId = device.id.toString();
                console.log("GlobalDeviceId: ", this.GlobalDeviceId);                
                this.bluetoothDevice = device;
                console.log("bluetoothDevice: ", this.bluetoothDevice);
                var _self = this
                this.bluetoothDevice.addEventListener('gattserverdisconnected', function() {
                    _self.onDiceDisconnected(_self.GlobalDeviceId, _self)
                })
                await this.connectDeviceAndCacheCharacteristics();                
            });
    }

Putting Chrome into debug mode and adding some logging I see this.

GlobalDeviceId: aOHCIYtwaFac7kbrO7ac2Q== godice.js:275
bluetoothDevice: godice.js:277
BluetoothDevice {id: 'aOHCIYtwaFac7kbrO7ac2Q==', name: 'GoDice_CE03C9_B_v04',
gatt: BluetoothRemoteGATTServer, ongattserverdisconnected: null}
gatt: BluetoothRemoteGATTServer {device: BluetoothDevice, connected: true}
id: "aOHCIYtwaFac7kbrO7ac2Q=="
name: "GoDice_CE03C9_B_v04"
ongattserverdisconnected: null
[[Prototype]]: BluetoothDevice
Dice connected: aOHCIYtwaFac7kbrO7ac2Q== main.js:24

The Bluetooth.requestDevice() method of the Bluetooth interface returns a Promise to a BluetoothDevice object with the specified options. If there is no chooser UI, this method returns the first device matching the criteria.

The BluetoothRemoteGATTServer interface of the Web Bluetooth API represents a GATT Server on a remote device. Does this mean that the die is the GATT server or that the web application needed the interface to use bluetooth functionality, or is something else going on?

Either way does B4X have the capability of doing this request. I would think probably so but I am getting nowhere testing with the various bluetooth examples that exists in this forum.

In the unfiltered B4X log I am seeing this information.

Found: GoDice_CE03C9_B_v04, D9:E9:F4:C9:03:CE, RSSI = -54, (MyMap) {1=[B@f832ea0, 9=[B@2cfca59, 7=[B@bf6761e, 0=[B@9219eff}
stopLeScan()
isLeEnabled(): ON
D9:E9:F4:C9:03:CE
connecting to GoDice_CE03C9_B_v04
connect() - device: D9:E9:F4:C9:03:CE, auto: true
registerApp()
registerApp() - UUID=cfbfad8e-4090-4113-abef-ccff536c2d2c
onClientRegistered() - status=0 clientIf=12
onClientConnectionState() - status=133 clientIf=12 device=D9:E9:F4:C9:03:CE
close()
unregisterApp() - mClientIf=12
Disconnected

I read that the status code of 133 on the OnClientConnection state is that it timed out which makes sense.
 

bocker77

Active Member
Licensed User
Longtime User
I am going to end this until I get educated on the nRF52 chip. Until then I won't be able to do much in b4x programming. Thanks to Emexes for sending me to the nRF52 chip manufacturer's website. They have a lot of educational videos and SDK for the PC. Hopefully I can succeed in getting this to work. If not I only wasted $40 on the dice.
 
Upvote 0

f0raster0

Well-Known Member
Licensed User
Longtime User
I am going to end this until I get educated on the nRF52 chip. Until then I won't be able to do much in b4x programming. Thanks to Emexes for sending me to the nRF52 chip manufacturer's website. They have a lot of educational videos and SDK for the PC. Hopefully I can succeed in getting this to work. If not I only wasted $40 on the dice.
please don't worry, I'm sure you can make it work!! if that device use a nRF microcontroller it will work using b4x

what is happening if you using this example without changes?
 
Upvote 0

f0raster0

Well-Known Member
Licensed User
Longtime User
can you please use the example and update this:
B4X:
Sub Manager_DeviceFound (Name As String, Id As String, AdvertisingData As Map, RSSI As Double)
    Log("Found: " & Name & ", " & Id & ", RSSI = " & RSSI & ", " & AdvertisingData) 'ignore
    If Name = "GoDice_52FAAF_K_v04" Or Name = "GoDice_CE03C9_B_v04" Then
        ConnectedName = Name
        manager.StopScan
        Log("connecting")
            #if B4A
        manager.Connect2(Id, False) 'disabling auto connect can make the connection quicker
        #else if B4I
        manager.Connect(Id)
        #end if
        End If
End Sub
and this:
B4X:
Sub Manager_DataAvailable (ServiceId As String, Characteristics As Map)
    pbReadData.Hide
    clv.Add(CreateServiceItem(ServiceId), "")
    For Each id As String In Characteristics.Keys
        clv.Add(CreateCharacteristicItem(id, Characteristics.Get(id)), "")
        Log("id: "& id )
        Log("ServiceId: "& ServiceId)
        Log("Characteristics: "& Characteristics)
    Next
End Sub

and this (not sure if your device needs it, we can try)
B4X:
Sub Manager_Connected (services As List)
    Log("Connected")
    connected = True
    ConnectedServices = services
    manager.SetNotify("6e400001-b5a3-f393-e0a9-e50e24dcca9e", "6e400003-b5a3-f393-e0a9-e50e24dcca9e", True)
    log("SetNotify True")
    StateChanged
End Sub

then post the logs (make sure you have: #BridgeLogger: True )
edit: make sure the hardware isn't connected somewhere else. .
 
Last edited:
Upvote 0

emexes

Expert
Licensed User
As for the three down arrows, yes I did select it and I didn't see anything change. I will retry it to see if I missed something but I hit it about three times and nothing that I saw changed.

Notifications means that data is "pushed out" from the BLE device, usually only when the data changes rather than you having to poll it.

Try enabling notifications ("hit it about" one time) and then change the orientation of that die, see if any data is emitted by the UART. If not, then maybe that "hit" turned notifications off, so repeat the entire process a couple more times, to be sure, to be sure.
 
Upvote 0

emexes

Expert
Licensed User
B4X:
Sub Manager_DeviceFound (Name As String, Id As String, AdvertisingData As Map, RSSI As Double)
    Log("Found: " & Name & ", " & Id & ", RSSI = " & RSSI & ", " & AdvertisingData) 'ignore
    If Name = "GoDice_52FAAF_K_v04" Or Name = "GoDice_CE03C9_B_v04" Then

El Slacko here often resorts to lazy expedient shortcuts like:

1/ to connect to any GoDice perhaps use something like If Name.ToLowerCase.Contains("godice") Then

2/ to connect to a particular device during development/debugging that has an identifying number, consider If Name.Contains("52FAAF") Then
 
Upvote 0

f0raster0

Well-Known Member
Licensed User
Longtime User
hey team,
or @emexes if you are around ahah :)

we did this:
B4X:
Sub Manager_DataAvailable (ServiceId As String, Characteristics As Map)
    pbReadData.Hide
    clv.Add(CreateServiceItem(ServiceId), "")
    For Each id As String In Characteristics.Keys
        clv.Add(CreateCharacteristicItem(id, Characteristics.Get(id)), "")
        Log("ServiceId: "& ServiceId)
        Log("Characteristics: "& Characteristics)
    Next
    Log("*************")
 
    Dim bc As ByteConverter
    For Each key As String In Characteristics.Keys
        Dim b() As Byte = Characteristics.Get(key)
        Log("Read data: " &key & ": " & bc.HexFromBytes(b))
    Next
 
End Sub

getting this:
B4X:
SetNotify True
ServiceId: 6e400001-b5a3-f393-e0a9-e50e24dcca9e
Characteristics: (MyMap) {6e400003-b5a3-f393-e0a9-e50e24dcca9e=[B@d1b4fc4}
*************
Read data: 6e400003-b5a3-f393-e0a9-e50e24dcca9e: 52
ServiceId: 6e400001-b5a3-f393-e0a9-e50e24dcca9e
Characteristics: (MyMap) {6e400003-b5a3-f393-e0a9-e50e24dcca9e=[B@52d35c}
*************
Read data: 6e400003-b5a3-f393-e0a9-e50e24dcca9e: 5301FDBE
ServiceId: 6e400001-b5a3-f393-e0a9-e50e24dcca9e
Characteristics: (MyMap) {6e400003-b5a3-f393-e0a9-e50e24dcca9e=[B@85431f4}
*************
Read data: 6e400003-b5a3-f393-e0a9-e50e24dcca9e: 52
ServiceId: 6e400001-b5a3-f393-e0a9-e50e24dcca9e
Characteristics: (MyMap) {6e400003-b5a3-f393-e0a9-e50e24dcca9e=[B@31fcb8c}
*************

we need some help to read/show/understand the data properly..

nRF app is showing this:
and from doc we know this: Stable, FakeStable, TiltStable, and MoveStable
then I think that S mean = Stable
Screenshot_20230214-215725.png
Screenshot_20230214-221711.png
 
Last edited:
Upvote 0

f0raster0

Well-Known Member
Licensed User
Longtime User
That documentation looks interesting 🤔 where can I find it?
@bocker77 can you help with it please..

Edit:
are those: https://getgocube.com/products/godice-full-pack/ ?
and do you have 2 dice right?

Edit: https://github.com/ParticulaCode/GoDiceJavaScriptAPI ?

Edit: you can create your own ones :p
 
Last edited:
Upvote 0

emexes

Expert
Licensed User
As per the godice Python code in github, the result is a byte array and second element is the dice value

where the second element is a 3d vector comprised of 3 signed bytes

ie the second, third and fourth bytes are x, y and z accelerometer values, which look like they are each in the range -64 to 64,

and then these are translated to a die value 1..6 by finding the closest match in:

JavaScript:
// The vectors for each die and shell type, used to check which side is facing up
    static d6Vectors = {
        1: [-64, 0, 0],
        2: [0, 0, 64],
        3: [0, 64, 0],
        4: [0, -64, 0],
        5: [0, 0, -64],
        6: [64, 0, 0],
    }
 
Upvote 0

f0raster0

Well-Known Member
Licensed User
Longtime User
hey team.. an update
B4X:
[code]
Sub Manager_DataAvailable (ServiceId As String, Characteristics As Map)
    pbReadData.Hide
    clv.Add(CreateServiceItem(ServiceId), "")
    For Each id As String In Characteristics.Keys
        clv.Add(CreateCharacteristicItem(id, Characteristics.Get(id)), "")
    Next
    Log("*************************************")
    For i = 0 To Characteristics.Size - 1.
        Log("Key: " & Characteristics.GetKeyAt(i))
        Log("Value: " & Characteristics.GetValueAt(i))
        Dim arr() As Byte = Characteristics.GetValueAt(i)
        Log(BytesToString(arr, 0, arr.Length, "UTF8"))

        For i = 0 To arr.Length - 1
            Log(i & ": " & arr(i))
        Next
    Next
End Sub
[/CODE]

getting this:
B4X:
SetNotify True
retries: 4
************************************* Battery usage
Key: 6e400003-b5a3-f393-e0a9-e50e24dcca9e
Value: [B@bf85ae1
Bat;
0: 66
1: 97
2: 116
3: 59
************************************* Start of roll
Key: 6e400003-b5a3-f393-e0a9-e50e24dcca9e
Value: [B@2888519
R
0: 82
************************************* result of roll (it was a 3)
Key: 6e400003-b5a3-f393-e0a9-e50e24dcca9e
Value: [B@a3cbe51
S�F��
0: 83
1: -1
2: 70
3: 0
 
Upvote 0

emexes

Expert
Licensed User
hey team.. an update

Looks like you've cracked it 🏆 although I'm not sure why you've dismounted your horse metres from the finish line 🤔 or is this your natural forum etiquette leaving crumbs for the rest of us so we don't feel left out? 🍻

B4X:
************************************* result of roll (it was a 3)
Key: 6e400003-b5a3-f393-e0a9-e50e24dcca9e
Value: [B@a3cbe51
S�F��
0: 83
1: -1
2: 70
3: 0

and then these are translated to a die value 1..6 by finding the closest match in:

JavaScript:
// The vectors for each die and shell type, used to check which side is facing up
    static d6Vectors = {
        1: [-64, 0, 0],
        2: [0, 0, 64],
        3: [0, 64, 0],
        4: [0, -64, 0],
        5: [0, 0, -64],
        6: [64, 0, 0],
    }
 
Upvote 0

f0raster0

Well-Known Member
Licensed User
Longtime User
@emexes the genius here is you!! your make me smile reading the B4X forum.. the word needs more people like you!! 🍻

I don't have the dice with me, I hope @bocker77 will update us with the last results :)
 
Upvote 0

bocker77

Active Member
Licensed User
Longtime User
With the help from persons on this forum I was able to understand how all this stuff BLE works especially Emexes and f0raster0 and get it to work along with the BLEExample code. Their patience in working with me is commendable. Working with f0raster0 offline with his vast knowledge of BLE got me going. With him I was able to get the die to communicate. I was then able to get its battery usage and pulse the led, although the JavaScript die call parameter list is incorrect. I am going to try and get an up-to-date list from them. Of course the most important piece of this is to get the die roll value. I decided to take a shot at this and happy to say that I am able to get a die roll. The BLEExample code provided only works with six sided dice. The die manufacturer provides die with more facings (d20, d24) and those vectors will need to be added if you want to buy and use them in your program. I am going to attach both my b4x code and a zip of what the die manufacturer sent me for those who like looking at JavaScript code. A function in the javascript class is what I used to get the die roll result. For some reason I had to add a 1 to the result where the JavaScript code doesn't. I tested my code with numerous rolls and did not receive any errors. This is not to say there isn't something that won't go south in the future. Now to create a die class and add Bluetooth die rolls to my Napoleonic military miniatures wargame.
 

Attachments

  • BLEExample.zip
    13.5 KB · Views: 62
  • GoDice.zip
    37.2 KB · Views: 58
Upvote 1
Top