Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FR] Add batterylevel for PM and HR #443

Open
Flo100 opened this issue Jan 25, 2023 · 9 comments
Open

[FR] Add batterylevel for PM and HR #443

Flo100 opened this issue Jan 25, 2023 · 9 comments

Comments

@Flo100
Copy link
Contributor

Flo100 commented Jan 25, 2023

Is your feature request related to a problem? Please describe.
No problem, I would like to know the batterylevel from my Power Pedals and Heartrate sensor.

I don't really understand the way SmartSpin2k works with the sensordata to subscribe to different clients and services and could use some help.
I would like both the PMclient and HRclient to subscribe to service UUID 0x180F with characteristic UUID 0x2A19. Then after a notify callback store the batterylevel somewhere in the sensordata where I can 'get' it and show it for example on the status.html page. (And eventually on a custom display I use)

@doudar
Copy link
Owner

doudar commented Jan 25, 2023

That's not a bad idea at all.
I would create a function/class for this and then add it into the post connect callback. Just make sure that you test every characteristic for nullptr before you attempt to read/connect to it.

void SpinBLEClient::postConnect() {

Any new BLE characteristics/constants you read should be placed in:
https://github.com/doudar/SmartSpin2k/blob/develop/lib/SS2K/include/Constants.h
Since battery updates aren't time critical, I'd consider just reading that characteristic on a long timer of some sort. You could add that into the BLE communications loop on a long (like 1 minute or more) timer:
void BLECommunications(void *pvParameters) {

@Flo100
Copy link
Contributor Author

Flo100 commented Jan 28, 2023

I added a new BatteryData Class and also added a bool hasBatteryLevel() and int getBatteryLevel() to every sensors .h & .cpp file. I also added the subscribtion to the postConnect(), but it seems that this void is only called when a BLEclient is connected. Is this done on purpose?
Anyway, I moved the postConnect() out of the if statement and it looks like I can connect to the HRclient & PMclient batteryservice.
The only thing left is to get this batteryleveldata for both devices...
Do I have to make changes to rtConfig as well? Like something with rtConfig.hr_batt.getValue(); and rtConfig.pm_batt.getValue(); Any Ideas?

@doudar
Copy link
Owner

doudar commented Jan 28, 2023

In order to expose them to the http server, it would be easiest to add them to rtConfig.

The post connection only needs to be run once on connection. The reason it's not in a direct callback is that some of the functions (specifically setting the connection parameters and the echelon setup) need to be done some ms after the initial connection is made. Also the regular NimBLE callbacks need to be as short as possible because they are isr and will cause a crash if they take very long.

Can't wait to see your results!

@Flo100
Copy link
Contributor Author

Flo100 commented Jan 28, 2023

I made some progress.
I removed the new battery class and deleted all the changes to the sensors files. Also the postconnect is restored as it was.
Now I added 2 new measurements in rtconfig
Measurement pm_batt;
Measurement hr_batt;

And before the } else if

} else if (!pClient->isConnected()) { // This shouldn't ever be

I added:
if(millis() - last_battery_update >= BATTERY_UPDATE_INTERVAL_MILLIS){
last_battery_update = millis();
if(spinBLEClient.myBLEDevices[x].charUUID == HEARTCHARACTERISTIC_UUID){
BLERemoteCharacteristic *battCharacteristic = pClient->getService(BATTERYSERVICE_UUID)->getCharacteristic(BATTERYCHARACTERISTIC_UUID);
if (battCharacteristic != nullptr) {
SS2K_LOG(BLE_COMMON_LOG_TAG, "Updating HRM battery");
std::string value = battCharacteristic->readValue();
String batt_characteristic = value.c_str();
char buf[2];
batt_characteristic.toCharArray(buf, 2);
rtConfig.hr_batt.setValue(int(buf[0]));
}
} else if(spinBLEClient.myBLEDevices[x].charUUID == CYCLINGPOWERMEASUREMENT_UUID ) {
BLERemoteCharacteristic *battCharacteristic = pClient->getService(BATTERYSERVICE_UUID)->getCharacteristic(BATTERYCHARACTERISTIC_UUID);
if (battCharacteristic != nullptr) {
SS2K_LOG(BLE_COMMON_LOG_TAG, "Updating PM battery");
std::string value = battCharacteristic->readValue();
String batt_characteristic = value.c_str();
char buf[2];
batt_characteristic.toCharArray(buf, 2);
rtConfig.pm_batt.setValue(int(buf[0]));
}
}
}

This way the batterylevels are stored in rtconfig and I can easily get them with rtConfig.hr_batt.getValue().
Offcourse an include to constants.h is needed and BATTERY_UPDATE_INTERVAL_MILLIS is set to 300000.

This approach seems to work, although I have not tested it with a long workout, but ble communications seems to be ok.
Thank you for your help.

@doudar
Copy link
Owner

doudar commented Jan 28, 2023

Awesome! Is there any chance I can talk you into making a pull request for this?

@Flo100
Copy link
Contributor Author

Flo100 commented Jan 28, 2023

Awesome! Is there any chance I can talk you into making a pull request for this?

I could try? Which branches do I need to choose to create one?

@doudar
Copy link
Owner

doudar commented Jan 28, 2023 via email

@doudar
Copy link
Owner

doudar commented Feb 25, 2023

Merged into develop. Still need some .html monitoring at some point

@doudar
Copy link
Owner

doudar commented Mar 23, 2024

This would be a good addition to the Config App

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants