cubing.js icon indicating copy to clipboard operation
cubing.js copied to clipboard

Battery level characteristic reports 55 for full power (instead of 100)

Open lgarron opened this issue 7 years ago • 16 comments

Cursory research suggests that it should be a value from 0 to 100, but the GiiKer cube appears to report 55 when the app shows it as 100% charged.

lgarron avatar Jun 22 '18 03:06 lgarron

Same here.... cube ALWAYS reports 55%. Any solution???

ragcsalo avatar May 10 '19 13:05 ragcsalo

Not that I know of. :-(

lgarron avatar May 10 '19 19:05 lgarron

So I have found the solution in a forum post. :-) Forget the battery service, it doesn't work, reports fixed 55%.

The service the Supercube uses for reporting battery level and turn count, is "0000aaaa-0000-1000-8000-00805f9b34fb" on Android and "AAAA" on iOS. You have to start listening (notify) to characteristic "0000aaab-0000-1000-8000-00805f9b34fb" ("AAAB" on iOS)... but it's complicated. If you do nothing else, this characteristic will report a value starting with B8, which is useless. To get battery level or turn count, first you have to WRITE a byte to to characteristic "0000aaac-0000-1000-8000-00805f9b34fb" ("AAAC" on iOS).

For battery level write "0xB5" to AAAC, then the AAAB characteristic (you are listening for) will report a value starting with B5. The next byte is the battery level (convert Hexa to Decimal).

For turn count write "0xCC" to AAAC, then the AAAB characteristic will report a value starting with CC. The next 4 bytes (converted to Decimal) will be the turn count.

I don't know why they made it so complicated, I had a hard time to figure it out..... Good luck to you!!! :-)

ragcsalo avatar May 14 '19 06:05 ragcsalo

For battery level write "0xB5" to AAAC, then the AAAB characteristic (you are listening for) will report a value starting with B5. The next byte is the battery level (convert Hexa to Decimal).

For turn count write "0xCC" to AAAC, then the AAAB characteristic will report a value starting with CC. The next 4 bytes (converted to Decimal) will be the turn count.

Looks like you might be right! From a recent Bluetooth capture:

(App to GiiKER i3S)
Write to handle 0x0019: b5
Write to handle 0x0019: ba
Write to handle 0x0019: b7
Write to handle 0x0019: cc

(GiiKER i3s to App)
Received value for handle 0x0016: b564036480a69500000000000000
Received value for handle 0x0016: bac4d4789de39500000000000000
Received value for handle 0x0016: b727d4789de39500000000000000
Received value for handle 0x0016: cc00000018e39500000000000000
[1.86s delay]
Received value for handle 0x0016: b8a0000018e39500000000000000

However, I didn't figure out how to map the handles to characteristics without triggering a cube reset, although I'm able to map it to aaa[abc] now.

How did you figure it out? :-D

lgarron avatar May 15 '19 08:05 lgarron

I think 0xb7 is firmware edition: my GiiKER app shows firmware version 39, and the first byte after 0xb7 is 0x27 == 39.

Still don't know what 0xba is.

lgarron avatar May 15 '19 08:05 lgarron

Values from an original i3:

B55A035A71A10000000000000000
BAF9CC3FDE666800000000000000
B723CC3FDE666800000000000000
CC00000008666800000000000000
B8A0000008666800000000000000

On subsequent runs, I got B55A035A71A16800000000000000, which suggests to me that the data in a frame can contain trailing junk bytes from previous ones (...6800000000000000 in this case), and that ...035A71A1... might mean something?

lgarron avatar May 15 '19 08:05 lgarron

which suggests to me that the data in a frame can contains trailing junk bytes from previous ones

Yep, requesting 0xb5 followed by 0xb7 gives:

B55A035A71A16800000000000000
B723035A71A16800000000000000

I also figured out B8. So far I've decoded the following:

Code Sample Bytes Meaning
B5 5A + 03 5A 71 A1 (i3)
64 + 03 64 80 A6 (i3S)
battery percentage + unknown
BA F9 CC 3F DE 66 68 (i3)
C4 D4 78 9D E3 95 (i3S)
unknown
B7 23 (i3)
27 (i3S)
firmware version
CC 00 00 00 08 number of moves
B8 A0 A1 if the cube is picked up,
A0 if the cube has been still for 10 seconds

Some observations:

  • B5 : 03 is followed by three bytes, the first of which seems to be a duplicate of the preceding battery byte. My first guess was that this means "the following 3 bytes are the battery level to 3 bytes of detail", but the value doesn't seem to budge too often.
  • BA: there are six bytes, like the six faces of the cube. There is a config in the app to store color scheme variant and orientation, although it doesn't seem to affect this value.

lgarron avatar May 15 '19 09:05 lgarron

Offtopic: what about resetting the cube, if it shows wrong pattern (sends wrong data)? Can I also write to the characteristic, where I get the cube state data from? 🤔

ragcsalo avatar Jul 30 '19 22:07 ragcsalo

Yes, I have code to set the state!

It's not quite shipped in this library yet, bu you can write to the same channel.

lgarron avatar Jul 31 '19 00:07 lgarron

I could get the info from "btsnoop_hci.log": for a solved state reset we have to write A1 to service AAAA, characteristic AAAC

There is another way to reset, when you define all the colors on the cube... and then you have to write it somehow to the cube. It's more complicated, so I'm not interested in this one... however, if you know which service/characteristic should we write the full state of the cube, please share! :-)

ragcsalo avatar Jul 31 '19 07:07 ragcsalo

B7 (alleged firmware version) reports these values: Giiker i3 (GiC....): 26 Giiker i3 (Gi1....): 28 Giiker i3S (GiS....): 27 So from this value we can't get the type of the cube... if you have any idea where to get the type/model from, please share! :-)

ragcsalo avatar Jul 31 '19 09:07 ragcsalo

About renaming the cube: I've found out that we can write to 1800/2A00 and the cube will store the new name!! However, when discovering and connecting, it shows the original name (Gi*). In the official Supercube app we can rename the cube, but it won't write it to the cube, it will be stored only in the app. I don't know why they didn't write the value to the cube... (???)

ragcsalo avatar Jul 31 '19 10:07 ragcsalo

I've played a bit with these values, and:

  • BA is the macAddress of my cube
  • B5's second byte is: 2 - charging, 3 - not charging, and I think the rest of the bytes related to battery level. For USB charging (5,27V) these are [100, 130, 167], for battery operation, these are [85, 110, 160]. Don't know the exact voltage of the internal battery, but it should be between 1.7V - 3.6V, my guess is 3.3V (the voltage the chip inside needs).

boogie avatar Oct 17 '19 04:10 boogie

For USB charging (5,27V) these are [100, 130, 167], for battery operation, these are [85, 110, 160].

Ok, here's some more information. I think the first byte is the battery voltage percentage, 100% and 85% in this example. The second and third bytes are a big endian word, and it can be the voltage value. So 130 * 256 + 167 is 33447. 110 * 256 + 160 is 28320. 28320/33447 is 0,8467 => 85%. I was not able to measure the actual voltages, but will check it later today.

boogie avatar Oct 21 '19 13:10 boogie

Well, the three numbers are separate bytes, and they are representing different views of the same value. I've collected these triplets:

 85 110 160
 90 113 161
 95 116 162
100 120 163
100 122 164
100 125 165
100 128 166
100 130 167
100 132 168

The first is capped, and I think the third is the original value. These are not connected to the battery level percentage value, but not clear what exactly they mean. I'm getting the highest values during charging, and slowly going down when I disconnect the charger. Actually it seems to be not a directly useful information.

And B5's second byte is (I've just spotted the value 1):

  • 1: fully charged
  • 2: charging
  • 3: not charging

And the cube is sending B5 without a request when the battery level percentage has changed. You don't have to poll it.

boogie avatar Oct 21 '19 16:10 boogie

B2 responds with time elapsed since the last reset as 4 bytes: days, hours, minutes, seconds.

boogie avatar Oct 21 '19 19:10 boogie