Skip to content

Instantly share code, notes, and snippets.

@xymox12
Last active November 18, 2020 09:22
Show Gist options
  • Save xymox12/241e1e686d8a95e526af9f611c2f217d to your computer and use it in GitHub Desktop.
Save xymox12/241e1e686d8a95e526af9f611c2f217d to your computer and use it in GitHub Desktop.
/*
Based on Neil Kolban example for IDF:
https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleWrite.cpp
Ported to Arduino ESP32 by Evandro Copercini
*/
// Modificado por Juan Antonio Villalpando.
// http://kio4.com/arduino/160i_Wemos_ESP32_BLE.htm
// https://community.appinventor.mit.edu/t/ble-esp32-bluetooth-send-receive-arduino-ide/1980/3
// https://github.com/michaelruck/ESP32_phone_camera_remote_shutter
// A Frankenstein's monstor from the above that works for me :P
// Camera Shutter BLE HID code for Android.
// Apart from the HID device, an extra service + characteristic is also created to react to
// commands from a MIT Inventor 2 application (TODO)
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#include <BLE2902.h>
#include <BLEHIDDevice.h>
#include <HIDTypes.h>
#include <HIDKeyboardTypes.h>
// Bluetooth labels
#define __MANUFACTURER "CAHSS DIT"
#define __BT_NAME "Cam-Butts"
// UUIDs
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
// BLE HID Descriptor Report ID
#define MEDIA_KEYS_ID 0x01
// Hex value of the key pressed
#define KEY_PRESSED 0xe9 // Volume up key
BLEHIDDevice *hid;
BLECharacteristic *inputVolume;
BLECharacteristic *outputVolume;
// Boolean to check in loop if BLE successfully connected
bool connected = false;
// Application callback
class MyCallbacks: public BLECharacteristicCallbacks {
String valor;
void onWrite(BLECharacteristic *pCharacteristic) {
std::string value = pCharacteristic->getValue();
if (value.length() > 0) {
valor = "";
for (int i = 0; i < value.length(); i++){
// Serial.print(value[i]); // Presenta value.
valor = valor + value[i];
}
Serial.println("*********");
Serial.print("valor = ");
Serial.println(valor); // Presenta valor.
}
}
};
// Server Callback
class ServerCallbacks : public BLEServerCallbacks {
void onConnect(BLEServer* pServer) {
connected = true;
BLE2902* desc = (BLE2902*)inputVolume->getDescriptorByUUID(BLEUUID((uint16_t)0x2902));
desc->setNotifications(true);
}
void onDisconnect(BLEServer* pServer) {
connected = false;
BLE2902* desc = (BLE2902*)inputVolume->getDescriptorByUUID(BLEUUID((uint16_t)0x2902));
desc->setNotifications(false);
}
};
// BLE HID Callback
class MyOutputCallbacks: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic* me) {
uint8_t* value = (uint8_t*)(me->getValue().c_str());
ESP_LOGI(LOG_TAG, "special keys: %d", *value);
}
};
// Task can make use of second core on esp32
void taskServer(void*) {
BLEDevice::init(__BT_NAME);
BLEServer *pServer = BLEDevice::createServer();
pServer->setCallbacks(new ServerCallbacks());
// Service 1 = pService == Android App interface
BLEService *pService = pServer->createService(SERVICE_UUID);
// Characteristic 1
BLECharacteristic *pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE |
BLECharacteristic::PROPERTY_NOTIFY |
BLECharacteristic::PROPERTY_INDICATE
);
pCharacteristic->addDescriptor(new BLE2902());
pCharacteristic->setCallbacks(new MyCallbacks());
pCharacteristic->setValue("Hello World");
pService->start();
// Service 2 = HID == Camera Clicker
hid = new BLEHIDDevice(pServer);
inputVolume = hid->inputReport(1); // <-- input REPORTID from report map
outputVolume = hid->outputReport(MEDIA_KEYS_ID); // <-- output REPORTID from report map
std::string name = __MANUFACTURER;
hid->manufacturer()->setValue(name);
hid->pnp(0x02, 0xe502, 0xa111, 0x0210);
hid->hidInfo(0x00, 0x02);
// HID Descriptor report (consider https://github.com/drdnar/Arduino-HID-Remote instead?)
const uint8_t report[] = {
USAGE_PAGE(1), 0x0C, // USAGE_PAGE (Consumer)
USAGE(1), 0x01, // USAGE (Consumer Control)
COLLECTION(1), 0x01, // COLLECTION (Application)
USAGE_MINIMUM(1), 0x00, // USAGE_MINIMUM (Unassigned)
USAGE_MAXIMUM(2), 0x3c, 0x02, // USAGE_MAXIMUM (AC Format
REPORT_ID(1), MEDIA_KEYS_ID, // REPORT_ID (3)
USAGE_PAGE(1), 0x0C, // USAGE_PAGE (Consumer)
LOGICAL_MINIMUM(1), 0x00, // LOGICAL_MINIMUM (0)
LOGICAL_MAXIMUM(2), 0x3c, 0x02, // LOGICAL_MAXIMUM (1)
REPORT_SIZE(1), 0x10, // REPORT_SIZE (1)
REPORT_COUNT(1), 0x10, // REPORT_COUNT (16)
HIDINPUT(1), 0x00, // INPUT (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
END_COLLECTION(0) // END_COLLECTION
};
hid->reportMap((uint8_t*)report, sizeof(report));
hid->startServices();
BLESecurity *qSecurity = new BLESecurity();
qSecurity->setAuthenticationMode(ESP_LE_AUTH_BOND);
// Advertise Server
BLEAdvertising *pAdvertising = pServer->getAdvertising();
pAdvertising->setAppearance(HID_KEYBOARD);
pAdvertising->addServiceUUID(hid->hidService()->getUUID());
pAdvertising->start();
// Set battery level - just not 0 :P
hid->setBatteryLevel(70);
delay(portMAX_DELAY);
}
void setup() {
Serial.begin(115200);
// Create a task to make use of esp32 cores
xTaskCreate(taskServer, "server", 20000, NULL, 5, NULL);
}
void loop() {
static bool volDirUp = true;
delay(4000);
if (connected) {
Serial.println("Cheese...");
// Key press
uint8_t vol_up_key_press = KEY_PRESSED;
inputVolume->setValue((uint8_t*)&vol_up_key_press,sizeof(vol_up_key_press));
inputVolume->notify();
//Key release
uint8_t vol_up_key_release = 0x0;
inputVolume->setValue((uint8_t*)&vol_up_key_release,sizeof(vol_up_key_release));
inputVolume->notify();
delay(1000);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment