Skip to content

Commit 62e8597

Browse files
authored
Support setting Battery Power State 0x2A1A values
Use nRF Connect on Android to test
1 parent 53d573a commit 62e8597

File tree

8 files changed

+185
-15
lines changed

8 files changed

+185
-15
lines changed

BleGamepad.cpp

Lines changed: 87 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,26 @@
2020
static const char *LOG_TAG = "BLEGamepad";
2121
#endif
2222

23-
#define SERVICE_UUID_DEVICE_INFORMATION "180A" // Service - Device information
23+
#define SERVICE_UUID_DEVICE_INFORMATION "180A" // Service - Device information
24+
25+
#define CHARACTERISTIC_UUID_MODEL_NUMBER "2A24" // Characteristic - Model Number String - 0x2A24
26+
#define CHARACTERISTIC_UUID_SOFTWARE_REVISION "2A28" // Characteristic - Software Revision String - 0x2A28
27+
#define CHARACTERISTIC_UUID_SERIAL_NUMBER "2A25" // Characteristic - Serial Number String - 0x2A25
28+
#define CHARACTERISTIC_UUID_FIRMWARE_REVISION "2A26" // Characteristic - Firmware Revision String - 0x2A26
29+
#define CHARACTERISTIC_UUID_HARDWARE_REVISION "2A27" // Characteristic - Hardware Revision String - 0x2A27
30+
#define CHARACTERISTIC_UUID_BATTERY_POWER_STATE "2A1A" // Characteristic - Battery Power State - 0x2A1A
31+
32+
#define POWER_STATE_UNKNOWN 0 // B00
33+
#define POWER_STATE_NOT_SUPPORTED 1 // B01
34+
#define POWER_STATE_NOT_PRESENT 2 // B10
35+
#define POWER_STATE_NOT_DISCHARGING 2 // B10
36+
#define POWER_STATE_NOT_CHARGING 2 // B10
37+
#define POWER_STATE_GOOD 2 // B10
38+
#define POWER_STATE_PRESENT 3 // B11
39+
#define POWER_STATE_DISCHARGING 3 // B11
40+
#define POWER_STATE_CHARGING 3 // B11
41+
#define POWER_STATE_CRITICAL 3 // B11
2442

25-
#define CHARACTERISTIC_UUID_MODEL_NUMBER "2A24" // Characteristic - Model Number String - 0x2A24
26-
#define CHARACTERISTIC_UUID_SOFTWARE_REVISION "2A28" // Characteristic - Software Revision String - 0x2A28
27-
#define CHARACTERISTIC_UUID_SERIAL_NUMBER "2A25" // Characteristic - Serial Number String - 0x2A25
28-
#define CHARACTERISTIC_UUID_FIRMWARE_REVISION "2A26" // Characteristic - Firmware Revision String - 0x2A26
29-
#define CHARACTERISTIC_UUID_HARDWARE_REVISION "2A27" // Characteristic - Hardware Revision String - 0x2A27
3043

3144

3245
uint8_t tempHidReportDescriptor[150];
@@ -77,7 +90,12 @@ BleGamepad::BleGamepad(std::string deviceName, std::string deviceManufacturer, u
7790
_aX(0),
7891
_aY(0),
7992
_aZ(0),
80-
hid(0)
93+
_batteryPowerInformation(0),
94+
_dischargingState(0),
95+
_chargingState(0),
96+
_powerLevel(0),
97+
hid(0),
98+
pCharacteristic_Power_State(0)
8199
{
82100
this->resetButtons();
83101
this->deviceName = deviceName;
@@ -1906,14 +1924,65 @@ void BleGamepad::setMotionControls(int16_t gX, int16_t gY, int16_t gZ, int16_t a
19061924
sendReport();
19071925
}
19081926
}
1927+
1928+
void BleGamepad::setPowerStateAll(uint8_t batteryPowerInformation, uint8_t dischargingState, uint8_t chargingState, uint8_t powerLevel)
1929+
{
1930+
uint8_t powerStateBits = B00000000;
1931+
1932+
_batteryPowerInformation = batteryPowerInformation;
1933+
_dischargingState = dischargingState;
1934+
_chargingState = chargingState;
1935+
_powerLevel = powerLevel;
1936+
1937+
// HID Battery Power State Bits:
1938+
// Bits 0 and 1: Battery Power Information : 0(B00) = Unknown, 1(B01) = Not Supported, 2(B10) = Not Present, 3(B11) = Present
1939+
// Bits 2 and 3: Discharging State : 0(B00) = Unknown, 1(B01) = Not Supported, 2(B10) = Not Discharging, 3(B11) = Discharging
1940+
// Bits 4 and 5: Charging State : 0(B00) = Unknown, 1(B01) = Not Chargeable, 2(B10) = Not Charging (Chargeable), 3(B11) = Charging (Chargeable)
1941+
// Bits 6 and 7: Power Level : 0(B00) = Unknown, 1(B01) = Not Supported, 2(B10) = Good Level, 3(B11) = Critically Low Level
1942+
1943+
powerStateBits |= (_batteryPowerInformation << 0); // Populate first 2 bits with data
1944+
powerStateBits |= (_dischargingState << 2); // Populate second 2 bits with data
1945+
powerStateBits |= (_chargingState << 4); // Populate third 2 bits with data
1946+
powerStateBits |= (_powerLevel << 6); // Populate last 2 bits with data
1947+
1948+
if (this->pCharacteristic_Power_State)
1949+
{
1950+
this->pCharacteristic_Power_State->setValue(&powerStateBits, 1);
1951+
this->pCharacteristic_Power_State->notify();
1952+
}
1953+
}
1954+
1955+
1956+
void BleGamepad::setBatteryPowerInformation(uint8_t batteryPowerInformation)
1957+
{
1958+
_batteryPowerInformation = batteryPowerInformation;
1959+
setPowerStateAll(_batteryPowerInformation, _dischargingState, _chargingState, _powerLevel);
1960+
}
1961+
1962+
void BleGamepad::setDischargingState(uint8_t dischargingState)
1963+
{
1964+
_dischargingState = dischargingState;
1965+
setPowerStateAll(_batteryPowerInformation, _dischargingState, _chargingState, _powerLevel);
1966+
}
19091967

1968+
void BleGamepad::setChargingState(uint8_t chargingState)
1969+
{
1970+
_chargingState = chargingState;
1971+
setPowerStateAll(_batteryPowerInformation, _dischargingState, _chargingState, _powerLevel);
1972+
}
1973+
1974+
void BleGamepad::setPowerLevel(uint8_t powerLevel)
1975+
{
1976+
_powerLevel = powerLevel;
1977+
setPowerStateAll(_batteryPowerInformation, _dischargingState, _chargingState, _powerLevel);
1978+
}
19101979

19111980
void BleGamepad::taskServer(void *pvParameter)
19121981
{
19131982
BleGamepad *BleGamepadInstance = (BleGamepad *)pvParameter; // static_cast<BleGamepad *>(pvParameter);
19141983

19151984
NimBLEDevice::init(BleGamepadInstance->deviceName);
1916-
NimBLEDevice::setPower(powerLevel); // Set transmit power for advertising (Range: -127 to +9 dBm)
1985+
NimBLEDevice::setPower(powerLevel); // Set transmit power for advertising (Range: -12 to +9 dBm)
19171986
NimBLEServer *pServer = NimBLEDevice::createServer();
19181987
pServer->setCallbacks(BleGamepadInstance->connectionStatus);
19191988
pServer->advertiseOnDisconnect(true);
@@ -1964,6 +2033,13 @@ void BleGamepad::taskServer(void *pvParameter)
19642033
NIMBLE_PROPERTY::READ
19652034
);
19662035
pCharacteristic_Hardware_Revision->setValue(hardwareRevision);
2036+
2037+
NimBLECharacteristic* pCharacteristic_Power_State = BleGamepadInstance->hid->getBatteryService()->createCharacteristic(
2038+
CHARACTERISTIC_UUID_BATTERY_POWER_STATE,
2039+
NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::NOTIFY
2040+
);
2041+
BleGamepadInstance->pCharacteristic_Power_State = pCharacteristic_Power_State; // Assign the created characteristic
2042+
BleGamepadInstance->pCharacteristic_Power_State->setValue(B00000000); // Now it's safe to call setValue <- Set all to unknown by default
19672043

19682044
BleGamepadInstance->hid->setPnp(0x01, vid, pid, guidVersion);
19692045
BleGamepadInstance->hid->setHidInfo(0x00, 0x01);
@@ -1975,12 +2051,14 @@ void BleGamepad::taskServer(void *pvParameter)
19752051
uint8_t *customHidReportDescriptor = new uint8_t[hidReportDescriptorSize];
19762052
memcpy(customHidReportDescriptor, tempHidReportDescriptor, hidReportDescriptorSize);
19772053

1978-
// Testing
2054+
// Testing - Ask ChatGPT to convert it into a commented HID descriptor
2055+
//Serial.println("------- HID DESCRIPTOR START -------");
19792056
//for (int i = 0; i < hidReportDescriptorSize; i++)
19802057
//{
19812058
// Serial.printf("%02x", customHidReportDescriptor[i]);
19822059
// Serial.println();
19832060
//}
2061+
//Serial.println("------- HID DESCRIPTOR END -------");
19842062

19852063
BleGamepadInstance->hid->setReportMap((uint8_t *)customHidReportDescriptor, hidReportDescriptorSize);
19862064
BleGamepadInstance->hid->startServices();

BleGamepad.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ class BleGamepad
4040
int16_t _aX;
4141
int16_t _aY;
4242
int16_t _aZ;
43+
uint8_t _batteryPowerInformation;
44+
uint8_t _dischargingState;
45+
uint8_t _chargingState;
46+
uint8_t _powerLevel;
4347

4448
//BleGamepadConfiguration configuration;
4549

@@ -50,6 +54,7 @@ class BleGamepad
5054
NimBLEHIDDevice *hid;
5155
NimBLECharacteristic *inputGamepad;
5256
NimBLECharacteristic *outputGamepad;
57+
NimBLECharacteristic *pCharacteristic_Power_State;
5358

5459
uint8_t *outputBackupBuffer;
5560

@@ -117,7 +122,12 @@ class BleGamepad
117122
bool isConnected(void);
118123
void resetButtons();
119124
void setBatteryLevel(uint8_t level);
120-
void setTXPowerLevel(int8_t level = 9);
125+
void setPowerStateAll(uint8_t batteryPowerInformation, uint8_t dischargingState, uint8_t chargingState, uint8_t powerLevel);
126+
void setBatteryPowerInformation(uint8_t batteryPowerInformation);
127+
void setDischargingState(uint8_t dischargingState);
128+
void setChargingState(uint8_t chargingState);
129+
void setPowerLevel(uint8_t powerLevel);
130+
void setTXPowerLevel(int8_t level = 9);
121131
int8_t getTXPowerLevel();
122132
uint8_t batteryLevel;
123133
std::string deviceManufacturer;

BleGamepadConfiguration.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ BleGamepadConfiguration::BleGamepadConfiguration() : _controllerType(CONTROLLER_
2222
_modelNumber("1.0.0"),
2323
_softwareRevision("1.0.0"),
2424
_serialNumber("0123456789"),
25-
_firmwareRevision("0.7.2"),
25+
_firmwareRevision("0.7.3"),
2626
_hardwareRevision("1.0.0"),
2727
_enableOutputReport(false),
2828
_outputReportLength(64),

BleGamepadConfiguration.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,17 @@
199199
#define VOLUME_DEC_BUTTON 6
200200
#define VOLUME_MUTE_BUTTON 7
201201

202+
#define POWER_STATE_UNKNOWN 0 // B00
203+
#define POWER_STATE_NOT_SUPPORTED 1 // B01
204+
#define POWER_STATE_NOT_PRESENT 2 // B10
205+
#define POWER_STATE_NOT_DISCHARGING 2 // B10
206+
#define POWER_STATE_NOT_CHARGING 2 // B10
207+
#define POWER_STATE_GOOD 2 // B10
208+
#define POWER_STATE_PRESENT 3 // B11
209+
#define POWER_STATE_DISCHARGING 3 // B11
210+
#define POWER_STATE_CHARGING 3 // B11
211+
#define POWER_STATE_CRITICAL 3 // B11
212+
202213
class BleGamepadConfiguration
203214
{
204215
private:

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ It would be great however if any improvements are fed back into this version.
1111
- [x] Button release (128 buttons)
1212
- [x] Axes movement (6 axes (configurable resolution up to 16 bit) (x, y, z, rX, rY, rZ) --> In Windows usually (Left Thumb X, Left Thumb Y, Right Thumb X, Left Trigger, Right Trigger, Right Thumb Y))
1313
- [x] Gyroscope and Accelerometer
14+
- [x] Set battery percentage
15+
- [x] Set battery power state information using UUID 0x2A1A. Use nRF Connect on Android for example to see this information
1416
- [x] 2 Sliders (configurable resolution up to 16 bit) (Slider 1 and Slider 2)
1517
- [x] 4 point of view hats (ie. d-pad plus 3 other hat switches)
1618
- [x] Simulation controls (rudder, throttle, accelerator, brake, steering)
@@ -44,7 +46,7 @@ This was due to the fact that non-Windows operating systems and some online web-
4446

4547
This version endeavors to be compatible with the latest released version of NimBLE-Arduino through the Arduino Library Manager; currently version 2.2.1 at the time of this writing; --> https://github.com/h2zero/NimBLE-Arduino/releases/tag/2.2.1
4648

47-
setAxes accepts them in the order (x, y, z, rx, ry, rz)
49+
setAxes accepts axes in the order (x, y, z, rx, ry, rz)
4850
setHIDAxes accepts them in the order (x, y, z, rz, rx, ry)
4951

5052
Please see updated examples
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
This example builds on the SetBatteryLevel example by also showing how to set the battery power state information to be reported to the host OS
3+
Use nRF Connect on Android for example to see the set information
4+
5+
You can set:
6+
7+
- Whether there is a battery installed or not
8+
- Whether the device is discharging or not
9+
- Whether the device is charging or not
10+
- Whether the power level is good or critically low
11+
12+
Each of the above also supports unknown or not supported states
13+
14+
You can use the definitions as shown below, or direct values
15+
16+
#define POWER_STATE_UNKNOWN 0 // B00
17+
#define POWER_STATE_NOT_SUPPORTED 1 // B01
18+
#define POWER_STATE_NOT_PRESENT 2 // B10
19+
#define POWER_STATE_NOT_DISCHARGING 2 // B10
20+
#define POWER_STATE_NOT_CHARGING 2 // B10
21+
#define POWER_STATE_GOOD 2 // B10
22+
#define POWER_STATE_PRESENT 3 // B11
23+
#define POWER_STATE_DISCHARGING 3 // B11
24+
#define POWER_STATE_CHARGING 3 // B11
25+
#define POWER_STATE_CRITICAL 3 // B11
26+
27+
*/
28+
29+
#include <Arduino.h>
30+
#include <BleGamepad.h>
31+
32+
BleGamepad bleGamepad;
33+
34+
int batteryLevel = 100;
35+
36+
void setup()
37+
{
38+
Serial.begin(115200);
39+
Serial.println("Starting BLE work!");
40+
bleGamepad.begin();
41+
}
42+
43+
void loop()
44+
{
45+
if (bleGamepad.isConnected())
46+
{
47+
// bleGamepad.setPowerStateAll(POWER_STATE_PRESENT, POWER_STATE_NOT_DISCHARGING, POWER_STATE_CHARGING, POWER_STATE_GOOD); // Can set all values together or separate as below
48+
bleGamepad.setBatteryPowerInformation(POWER_STATE_PRESENT); // POWER_STATE_UNKNOWN or POWER_STATE_NOT_SUPPORTED or POWER_STATE_NOT_PRESENT or POWER_STATE_PRESENT
49+
bleGamepad.setDischargingState(POWER_STATE_NOT_DISCHARGING); // POWER_STATE_UNKNOWN or POWER_STATE_NOT_SUPPORTED or POWER_STATE_NOT_DISCHARGING or POWER_STATE_DISCHARGING
50+
bleGamepad.setChargingState(POWER_STATE_CHARGING); // POWER_STATE_UNKNOWN or POWER_STATE_NOT_SUPPORTED or POWER_STATE_NOT_CHARGING or POWER_STATE_CHARGING
51+
bleGamepad.setPowerLevel(POWER_STATE_GOOD); // POWER_STATE_UNKNOWN or POWER_STATE_NOT_SUPPORTED or POWER_STATE_GOOD or POWER_STATE_CRITICAL
52+
53+
if (batteryLevel > 0)
54+
{
55+
batteryLevel -= 1;
56+
}
57+
58+
Serial.print("Battery Level Set To: ");
59+
Serial.println(batteryLevel);
60+
bleGamepad.setBatteryLevel(batteryLevel);
61+
62+
delay(10000);
63+
}
64+
}

keywords.txt

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,13 @@ setIncludeGyroscope KEYWORD2
7979
setIncludeAccelerometer KEYWORD2
8080
setWhichSimulationControls KEYWORD2
8181
resetButtons KEYWORD2
82-
setBatteryLevel KEYWORD2
83-
pressSpecialButton KEYWORD2
82+
setBatteryLevel KEYWORD2
83+
setPowerStateAll KEYWORD2
84+
setBatteryPowerInformation KEYWORD2
85+
setDischargingState KEYWORD2
86+
setChargingState KEYWORD2
87+
setPowerLevel KEYWORD2
88+
pressSpecialButton KEYWORD2
8489
releaseSpecialButton KEYWORD2
8590
pressStart KEYWORD2
8691
releaseStart KEYWORD2

library.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name=ESP32-BLE-Gamepad
2-
version=0.7.2
2+
version=0.7.3
33
author=lemmingDev
44
maintainer=lemmingDev
55
sentence=Bluetooth LE Gamepad library for the ESP32.

0 commit comments

Comments
 (0)