KonradIT / goprowifihack

Unofficial GoPro WiFi API Documentation - HTTP GET requests for commands, status, livestreaming and media query.
Apache License 2.0
2.12k stars 335 forks source link

Gopro MAX Power ON command: rather bluetooth and not WOL? #191

Open paicolman opened 4 years ago

paicolman commented 4 years ago

I am trying to use the commands on a Gopro MAX, when the cam is on, all works fine, also to turn it off is OK. But it seems that when the camera is OFF, the WiFi gets turned OFF, so a WOL command will not get to the camera.

I am tinkering with an ESP32 to try to turn it back on via Bluetooth, no success so far, but when you install the Gopro App, and connect to the bluetooth of the cam directly (the app does the trust and pairing before, so it´s in the bluetooth list), it turns on promptly.

Details:

KonradIT commented 4 years ago

Yes, MAX powers on when you connect to it via BLE.

paicolman commented 4 years ago

thanks! Do you have any idea on how to pair to a Gopro? I can connect with the ESP32 when the Gopro is in pairing mode, but I have no idea on what to do to initiate the pairing. Sorry, this is not an "issue" rather a request for help...

KonradIT commented 4 years ago

Mind sharing your code? I actually got stuck when trying to send BLE commands to the GoPro using the ESP32 board.

paicolman commented 4 years ago

I'll have to cleanup a bit, at the moment it's just a complete "construction site" with snippets outcommented and stuff (yes, a total mess at the moment).

But I'll share it sure, although I'm stuck pretty much there, too. I tried with a mac BLE tool to write BLE commands to the camera and it works fine, but not (yet) with the ESP32. I can connect, find the service and characteristics, but still stuck there... I'll post the code here when I've cleaned up a bit.

paicolman commented 4 years ago

Ok, cleaned it up a bit, so its readable... Tried now to write the characteristic with all available methods from Neil Kolban, but no luck. This is based on the BLE Client example. I tried to send BLE codes directly from my Mac with a really cool app called BlueSee and the camera reacted happily.

#include "BLEDevice.h"
#include "BLEScan.h"
#include <string>

/******************************************************************************************************************************
Advertised Device found: Name: GoPro Cam, Address: db:b0:2f:8f:b1:46, serviceUUID: 0000fe2c-0000-1000-8000-00805f9b34fb, txPower: -22 
Advertised Device found: Name: GoPro 1608, Address: eb:bb:11:42:32:2f, manufacturer data: f2020205333f002f324211bbeb0f, serviceUUID: 0000fea6-0000-1000-8000-00805f9b34fb

Command("b5f90072-aa8d-11e3-9046-0002a5d5c51b"), CAN WRITE
CommandResponse("b5f90073-aa8d-11e3-9046-0002a5d5c51b"), CAN NORIFY
SetSetting("b5f90074-aa8d-11e3-9046-0002a5d5c51b"), CAN WRITE
SetSettingResponse("b5f90075-aa8d-11e3-9046-0002a5d5c51b"),
QueryRequest("b5f90076-aa8d-11e3-9046-0002a5d5c51b"),
QueryResponse("b5f90077-aa8d-11e3-9046-0002a5d5c51b"),
SensorData("b5f90078-aa8d-11e3-9046-0002a5d5c51b"),
SensorDataResponse("b5f90079-aa8d-11e3-9046-0002a5d5c51b");

CHAR : b5f90072-aa8d-11e3-9046-0002a5d5c51b
The characteristic can be written
------------------------------------------------------
CHAR : b5f90073-aa8d-11e3-9046-0002a5d5c51b
The characteristic can notify
------------------------------------------------------
CHAR : b5f90074-aa8d-11e3-9046-0002a5d5c51b
The characteristic can be written
------------------------------------------------------
CHAR : b5f90075-aa8d-11e3-9046-0002a5d5c51b
The characteristic can notify
------------------------------------------------------
CHAR : b5f90076-aa8d-11e3-9046-0002a5d5c51b
The characteristic can be written
------------------------------------------------------
CHAR : b5f90077-aa8d-11e3-9046-0002a5d5c51b
The characteristic can notify
------------------------------------------------------
CHAR : b5f90078-aa8d-11e3-9046-0002a5d5c51b
The characteristic can be written
------------------------------------------------------
CHAR : b5f90079-aa8d-11e3-9046-0002a5d5c51b
The characteristic can notify

******************************************************************************************************************************/
const int buttonPin = T0;     // the number of the pushbutton pin
const int ledPin =  2;      // the number of the LED pin

// variables will change:
int buttonState = 0;         // variable for reading the pushbutton status

static BLEUUID serviceUUID("0000fea6-0000-1000-8000-00805f9b34fb");
// The characteristic of the remote service we are interested in.
static BLEUUID    writeUUID("b5f90072-aa8d-11e3-9046-0002a5d5c51b");
static BLEUUID   notifyUUID("b5f90073-aa8d-11e3-9046-0002a5d5c51b");

static boolean doConnect = false;
static boolean connected = false;
static boolean doScan = false;
static BLERemoteCharacteristic* pRemoteCharacteristic;
static BLERemoteCharacteristic* pNotifyCharacteristic;
static BLEAdvertisedDevice* myDevice;

static void notifyCallback(
  BLERemoteCharacteristic* pBLERemoteCharacteristic,
  uint8_t* pData,
  size_t length,
  bool isNotify) {
    Serial.print("Notify callback for characteristic ");
    Serial.print(pBLERemoteCharacteristic->getUUID().toString().c_str());
    Serial.print(" of data length ");
    Serial.println(length);
    Serial.print("data: ");
    Serial.println((char*)pData);
}

class MyClientCallback : public BLEClientCallbacks {
  void onConnect(BLEClient* pclient) {
    Serial.println("onConnect has been called");
  }

  void onDisconnect(BLEClient* pclient) {
    connected = false;
    Serial.println("onDisconnect has been called");
  }
};

bool connectToServer() {
    Serial.println("Forming a connection to eb:bb:11:42:32:2f");

    BLEAddress fixedAddress = *new BLEAddress("eb:bb:11:42:32:2f");

    BLEClient*  pClient  = new BLEClient();
    Serial.printf(" - Created client\n");
    pClient->setClientCallbacks(new MyClientCallback());

    bool isConnected = pClient->connect(fixedAddress, BLE_ADDR_TYPE_RANDOM);       

    if (isConnected) {
      Serial.println("YAY! connected!");
    } else {
      Serial.println("F**K! no connection");
    }

    BLERemoteService* pRemoteService = pClient->getService(serviceUUID);

    if (pRemoteService == nullptr) {
      Serial.print("Failed to find our service UUID: ");
      Serial.println(serviceUUID.toString().c_str());
      pClient->disconnect();
      return false;
    } else {
      Serial.println(" - Found our service");
    }

    // Obtain a reference to the characteristic in the service of the remote BLE server.

    pRemoteCharacteristic = pRemoteService->getCharacteristic(writeUUID);
    pNotifyCharacteristic = pRemoteService->getCharacteristic(notifyUUID);
    pNotifyCharacteristic->registerForNotify(notifyCallback);

    if(pRemoteCharacteristic->canWrite()) {
      Serial.println("Characteristic is writeable!");
    }
    connected = true;
    return true;
}

class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
 /**
   * Called for each advertising BLE server.
   */
  void onResult(BLEAdvertisedDevice advertisedDevice) {
    Serial.print("BLE Advertised Device found: ");
    Serial.println(advertisedDevice.toString().c_str());

    // We have found a device, let us now see if it contains the service we are looking for.
    if (advertisedDevice.haveServiceUUID() && advertisedDevice.isAdvertisingService(serviceUUID)) {

      BLEDevice::getScan()->stop();
      myDevice = new BLEAdvertisedDevice(advertisedDevice);
      doConnect = true;
      doScan = true;
      Serial.println("Will connect to it...");

    } // Found our server
  } // onResult
}; // MyAdvertisedDeviceCallbacks

void setup() {
  Serial.begin(115200);
  Serial.println("Starting Arduino GOPRO BLE Client application...");

  //Scan just to see if Gopro is there somewhere...
  BLEDevice::init("");

  BLEScan* pBLEScan = BLEDevice::getScan();
  pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
  pBLEScan->setInterval(1349);
  pBLEScan->setWindow(449);
  pBLEScan->setActiveScan(true);
  pBLEScan->start(5, false);

  pinMode(buttonPin, INPUT);
  pinMode(ledPin, OUTPUT);
  Serial.println("************************* WE START CONNECTING HERE *************************");
  connectToServer();
  Serial.println("*************** CONNECTION OK - 10 sec running  *******************");
  delay(10000);
  Serial.println("***************** LETS TRY TO TURN OFF ********************");

  Serial.println("Trying with a byte array...");
  uint8_t *myData = new uint8_t[2];  //Lets try to turn it off at least {0x01, 0x04};
  myData[0] = 0x01;
  myData[1] = 0x04;
  size_t myLength = sizeof(myData);
  pRemoteCharacteristic->writeValue(myData, myLength);

  delay(2000);
  Serial.println("Trying with a plain hex number...");
  pRemoteCharacteristic->writeValue(0x0104);

  delay(2000);
  Serial.println("Trying with a char code...");
  char ch1 = 0x01;
  char ch2 = 0x04;
  std::string myStr = "AB";
  myStr[0] = ch1;
  myStr[1] = ch2;
  pRemoteCharacteristic->writeValue(myStr);

  Serial.println("************************** WORKED?  *****************************");

} // End of setup.

// This is the Arduino main loop function.
void loop() {

  // Just do nothing...
  digitalWrite(ledPin, !digitalRead(buttonPin));
  delay(100);

} // End of loop

Edit from @KonradIT: formatting code.

paicolman commented 4 years ago

Shoot it got completely reformatted, sry. BTW, this is the log of the script. All seems ok, but writing just won´t work...

Starting Arduino GOPRO BLE Client application...
BLE Advertised Device found: Name: 846B21C4AAC630A8E9, Address: f3:33:8a:54:d5:de, appearance: 0, manufacturer data: a7050310019944deadbeef000a00ca, serviceUUID: 0000fe07-0000-1000-8000-00805f9b34fb, txPower: 0
BLE Advertised Device found: Name: vívosport, Address: e0:d7:10:34:3e:8e, manufacturer data: 87000a3f, serviceUUID: 6a4e3e10-667b-11e3-949a-0800200c9a66
BLE Advertised Device found: Name: , Address: 71:62:1f:ff:33:a3, manufacturer data: 4c001006131e8f72310c, txPower: 12
BLE Advertised Device found: Name: 846B21C596A630A8E9, Address: f3:33:90:64:56:f4, appearance: 0, manufacturer data: a7050311536f6e6f735f4f584c4559, serviceUUID: 0000fe07-0000-1000-8000-00805f9b34fb, txPower: 0
BLE Advertised Device found: Name: GoPro Cam, Address: db:b0:2f:8f:b1:46, serviceUUID: 0000fe2c-0000-1000-8000-00805f9b34fb, txPower: -22
BLE Advertised Device found: Name: , Address: 45:9b:ee:47:c1:d1, manufacturer data: 4c0010054b1c6c8ba7
BLE Advertised Device found: Name: , Address: 61:ee:fa:3c:79:ec, manufacturer data: 4c0010054b1c6c8ba7
BLE Advertised Device found: Name: , Address: 53:09:19:8b:d4:0e, manufacturer data: 4c001006231aaa2f7d2f, txPower: 8
BLE Advertised Device found: Name: , Address: 76:ba:b9:a7:6a:65, manufacturer data: 4c001006131e18f4c227, txPower: 12
BLE Advertised Device found: Name: , Address: 6b:28:9b:25:89:73, manufacturer data: 4c001006511e344adde4, txPower: 12
************************* WE START CONNECTING HERE *************************
Forming a connection to eb:bb:11:42:32:2f
 - Created client
onConnect has been called
YAY! connected!
 - Found our service
Characteristic is writeable!
*************** CONNECTION OK - 10 sec running  *******************
***************** LETS TRY TO TURN OFF ********************
Trying with a byte array...
Trying with a plain hex number...
Trying with a char code...
************************** WORKED?  *****************************
onDisconnect has been called
paicolman commented 4 years ago

Last comment: Somehow it only works when I scan first. The scan is not used, I connect directly to the gopro adress hardcoded (another one of many trials). So, sorry for the spam ;)