I'm writing my thesis on how to obtain data from different fitness bands.
At the moment I'm doing some research on the Mi Band 2 using bluetooth connection with my PC, unfortunately BLE is a new field for me.
By looking at projects like Gadgetbridge or miband2-python-test I try to understand the protocol. I get how the authentication works and how to extract data like battery or time information. However, I don't understand the protocol to obtain past data, like the minutely steps from two days ago until now.
I would be pleased if someone could help me by giving a tip or explaining the steps of the protocol. Thanks in advance!
That's my code for now, as far as I understood the protocol:
UUID_CHAR_ACTIVITY_DATA = "00000005-0000-3512-2118-0009af100700"
UUID_CHAR_FETCH = "00000004-0000-3512-2118-0009af100700"
CCCD_UUID = 0x2902
class MiBand2(Peripheral):
[...]
self.char_activity_data = self.getCharacteristics(uuid=UUID_CHAR_ACTIVITY_DATA)[0]
self.char_fetch = self.getCharacteristics(uuid=UUID_CHAR_FETCH)[0]
self.cccd_fetch = self.char_fetch.getDescriptors(forUUID=CCCD_UUID)[0]
def fetch_activity_data(self):
# \x01\x01 key?
# \xe2\x07 2018 year
# \x05 month
# \x03 year
# \x11 hour
# \x2f minute
# \x00\x08 timezone
value = b'\x01\x01\xe2\x07\x05\x03\x11\x2f\x00\x08'
self.cccd_fetch.write(b'\x01\x00', False)
self.char_fetch.write(value_from_wireshark, False)
for i in range(30):
self.waitForNotifications(1.0)
class AuthenticationDelegate(DefaultDelegate):
[...]
def handleNotification(self, hnd, data):
[...]
if hnd == self.device.char_fetch.getHandle():
if data[:3] == b'\x10\x01\x01':
self.device.char_activity_data.write(b'\x01\x00', False)
# After \x02 I receive \x10\x02\x01 instead of fitness data as I thought
self.device.char_fetch.write(b'\x02', False)
It is need to analyze btsnoop_hci.log
On every 30 minute the device send a notification value 0x0e from 00000010-0000-3512-2118-0009af100700. Then you must start to take your past data. Firstly you need to enable notification descriptors for UUID_CHAR_ACTIVITY_DATA and so called UUID_CHAR_FETCH. Then you need to get count of packages from your last successful getting of data. So you send a value 0x0101+datatime+tz to UUID_CHAR_FETCH. The device response to you with value of 0x100101+packages_count+1st_package_datetimetz if no gaps the 1st_package_datetimetz is that you send previously. Now you need to start transfer past data, just send one byte value 0x02 to UUID_CHAR_FETCH and device will send notifications from UUID_CHAR_ACTIVITY_DATA. Every activity data notification value has a queue number in first byte and maximum 4 packages of data in remain bytes. Every single package of past data consists of 4 bytes and has this format: activity_type,intensity,steps,heart_rate. The device stores data for every minute. So usualy on every 0x0e event you will get 30 packages in 8 notification message values by 4 packages most of time. After the last notification got the device will send notification of success 0x100201 from UUID_CHAR_FETCH. I don't know why but it need to be done the last 3-rd step: send a single byte 0x03 to UUID_CHAR_FETCH then get success response 0x100301. This actualy all what you need but Mi Fit does bouble check for a new data packages, then gets zero count and then does last 3-rd step. Now it need to set notification descriptors off with value 0x0000. After all this your success synchronize datatime will be grater for count of past data packets you got * 60 seconds.
If you have response packages count = 0 after 0x0101 command the device will obviously send to you nothing after command 0x02 and then send success 0x100201 :)
I don't know what for 0x0102+datatimetz is. It always response packages count = 0 in my btsnoop_hci.logs.
I think it is not necessary to synchronize by 0x0e event.
https://gist.github.com/Roxxor91/0d3ff17153270e447d01e7afd0c54e0f
Related
I am developing Android authenticator.I am getting {-125,0,1,4} byte array from webauthn client after pairing. When I decoding this array
-125 (0x83) - MSG
1 (0x01) - length of the data
4 (0x04) - AuthenticatorGetInfo
I am not sure about 0 in this array. Please let me know is there any meaning for this 0.
For this request, I am sending response as CBOR data.
00a60182684649444f5f325f30665532465f563202816b686d61632d73656372657403506435323965353235383533343133663304a462726bf5627570f564706c6174f469636c69656e7450696ef505190400069f01ff
I am notifying above data by using Fido Status as follows.
for (byte[] frame : response.toFrames(mMTU)) {
getFidoStatus().setValue(frame);
mGattServer.notifyCharacteristicChanged(device, getFidoStatus(), true);
}
After that I am not getting any request/response from webauthn client. I am sending KEEPALIVE(0x82) command with value PROCESSING(0x01) for every kKeepAliveMillis(500ms). Is there any issue with my implementation?
Please help me to proceed this. Thanks in advance.
This speciciation fully explains for you
https://fidoalliance.org/specs/fido-v2.0-id-20180227/fido-client-to-authenticator-protocol-v2.0-id-20180227.html#ble-framing-fragmentation
CMD is 0x83 (MSG)
Length of DATA is 2 bytes: HLEN byte and LLEN byte.
In your case, length of DATA is 0x0001 (= 1). The DATA is 0x04
I have spent much time trying to find out where is my mistakes while Im flashing the PIC16F688. The Pic has successfully flashed using PicKit2. Im using the Pic to convert analog pressure sensor to digital output and sending the data via Bluetooth, but the Bluetooth is not receiving stable numbers of data. The data is consist of 4 character decimal number that is between 0 and 1023.
The problem is that the Bluetooth can't wait at specific number and keep reading it, instead, it is reading the 4 digits in random.
I think my mistake is within the configuration of internal oscillator.
I'm attaching my code, the code is written to configure the flexiforce sensor circuit that outputs analog voltage up to 5v, and then the pic duty is to convert it to digital as I mentioned above.
it might be my wiring is not correct, please If you could help out with this one
and what configuration "at edit project" do I need to choose for Mikro PRO software?
I used "Bluetooth terminal" app to see my data asynchronous from Bluetooth.
Thank you.
char *temp = "0000";
unsigned int adc_value;
char uart_rd; int i;
void main()
{
OSCCON = 0x77;
ANSEL = 0b00000100;
CMCON0 = 0X07;
TRISA = 0b00001100;
UART1_Init(9600);
Delay_ms(100);
while (1)
{
adc_value = ADC_Read(2);
temp[0] = adc_value/1000+48;
temp[1] = (adc_value/100)%10+48;
temp[2] = (adc_value/10)%10+48;
temp[3] = adc_value%10+48;
for (i=0;i<4; i++)
UART1_Write(temp[i]);
UART1_Write(13);
Delay_ms(1000);
}
}
You can use itoa function to convert ADC integer value to characters for sending over UART. If there is error in calculation then you wont get appropriate value. Below code snippet for your reference :
while (1)
{
adc_value = ADC_Read(2);
itoa(adc_value, temp, 10);
for (i=0;i<4; i++)
UART1_Write(temp[i]);
UART1_Write(13);
Delay_ms(1000);
}
Please check Baud Rate you have configured at both ends is same or not. If baudrate mismatches then you will get Random value at Bluetooth Terminal where you are reading values.
What i would suggest, if you have a logic analyser, hook it up. If you don't recalculate your oscillator speed with the datasheet. It could just be that the internal oscillator is not accurate enough. What also works, is to write a function in assembly that waits a known time (by copy-pasting a lot of NOPs and using this to blink a led. Then start a stopwatch and count, say, 100 blinks. This is what i used to do before i had a logic analyser. (They are quite cheep on ebay).
When I try to analyse CDN download, some logs looks like below:
GET http://1234.apk?track=mmmmmmm range:bytes-sent=[500-500], content-length:1500 ...
In my understanding, range:bytes-sent represents continue download after break and it should have different number in bytes-sent, the followings are reasonable:
bytes-sent=[500-600]
bytes-sent=[500-]
bytes-sent=[-500]
but what meaning of range start = range end like [500-500]? It seems no data should be downloaded but generates http response.
Thanks first~
The bytes mentioned in the range are also sent. Hence if the server wants to only send the 500th byte, the server would send [500-500] as the bytes range. Have a look at https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-p5-range-26 which has an example of how the first and last byte are sent :
o The first and last bytes only (bytes 0 and 9999):
bytes=0-0,-1
I have a routine that uses a HttpURLConnection to upload a file via a multipart/form-data content type. The server does some processing on the uploaded file and returns a short response code. This works fine in all cases so far except with one user with an HTC Evo when on 4G. If the user switches to 3G then everything works fine. When on 4G the app will wait on the while ((line = reader.readLine()) != null) { until a socket connection timeout exception is thrown. I have the connection timeout set to 70 seconds. The server is in php here is the relevant snippet
//all ob_ related entries were added because I found some info indicating
//that some clients would not acknowledge the response without the content-length header
ob_end_clean();
header("Connection: close");
ob_start();
...
//the response is one of either
echo "BACKGROUND"; //this one works!
//or
echo $rv //$rv = "1336757671374T37171FR"
//or
echo "FailedQA";
$size = ob_get_length();
header("Content-Length: $size");
ob_end_flush();
ob_flush();
flush();
die();
?>
Note that the 'BACKGROUND' response works, and the rest cause the client to sit until the timeout exception. I have currently 2 notions on this, but I am not in a 4G area so I can only test this through the end user and I really want to limit the number of attempts. My first thought is that the 'BACKGROUND' is slightly longer than the 'FailedQA', and while the other one is longer it has a numeric start. So maybe adding white space to the response would help? The other aspect is response time. The 'BACKGROUND' message is normally sent faster than the other ones. But, I do have a counter example here so I am not sire. Example: the 'BACKGROUND' message normally goes out within 15 to 20 seconds. The other messages are normally 30-40 seconds. However, I have one example where the '1336757671374T37171FR' style response went out in 24 seconds and was not received and one where the 'BACKGROUND' message went out in 27 seconds and was received.
So to sum up: This only happens on Sprint 4G. I suspect it might either be content length or response time that is causing the issue, but in both cases I have a counter example to the contrary. Except with the length case the one that is the longer counter example has a numeric beginning, so there's that.
It seems to be the delay before a response that was causing the problem. I used this guide Easy Parallel Processing in PHP to set up a multi-tasking php configuration. This way I have a script that just counts and echos the elapsed seconds while the other one does the job processing. The problem is now resolved.
I'am working with arduino and ADK und I have problems to get Information from Arduino-Sensors. At the moment I can send Information from Phone to control LED or servos.... . But it is impossible for me to send Data via acc.write(msg,3) to smarthphone. I'am using this example Dev-O-Rama and try to extend this example to get sensor data(without success). To get sensordata I'am using code from ADK example. Everytime when I try to send data from arduino with: acc.write(msg,3) it seems everything freezing. Have someone a working "little" example or a hint what can cause this behavior?
LG Marcel
I figure it's the Android application that's freezing?
Try using the USBControl library in my project
The arduino write code is very simple:
//Batt update, 0.1 Hz loop
if (acc.isConnected() && millis()-timer_batt >= 1000/BATT_FREQ) {
timer_batt = millis();
//Serial.print("b");
msg[0] = SYNC;
msg[1] = BATTERY_LEVEL;
msg[2] = getBatt();
acc.write(msg, 3);
}
Make sure you're limiting the writing frequency, and reading quickly enough on both sides. There's a strange behaviour where the connection will appear to hang if there's too much data being buffered.
It's hard to say what to do without knowing what kind of data you are sending. Basically you have to make sure use the acc.write() method with the correct parameters. The first one is the byte array itself and the second one is the number of bytes in the array. So if your byte array is 5 bytes in size you need to call it like that: acc.write(msg, 5).
It is even better to make it more dynamic by using the sizeof Arduino function:
acc.write(msg, sizeof(msg));