From 35e1c5d6f82382ba6514c24bbb5d09ca6cde9a8e Mon Sep 17 00:00:00 2001 From: aster94 Date: Tue, 26 Mar 2019 01:45:13 +0100 Subject: [PATCH] ready for version 1.0.0 --- README.md | 16 +- examples/ESP32_FreeRTOS/ESP32_FreeRTOS.ino | 207 +++++++++++---------- examples/GoProControl/GoProControl.ino | 39 ++-- examples/MultiCam/MultiCam.ino | 21 +-- keywords.txt | 179 +++++++++--------- library.properties | 4 +- src/GoProControl.cpp | 168 +++++++++++------ src/GoProControl.h | 21 +-- src/Settings.h | 8 +- 9 files changed, 356 insertions(+), 307 deletions(-) diff --git a/README.md b/README.md index 3b7da4b..34f85c1 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ Have you ever thought about the possibility to control your action camera with y - HERO5 - HERO6 - HERO7 -- Fusion +- FUSION I made the library with a style which would be quite easy to add other cameras (not only GoPro). I would be very happy to accept pull requests 😃 @@ -153,9 +153,21 @@ I made the library with a style which would be quite easy to add other cameras ( | 3 | ✔ | | | 0 | ✔ | | +**NOTE:** Not all the options are available for all the cameras (for example on a HERO3 you can't set 1080p at 240 frame per second 😲). You can see the possibilities on the manual of your camera of here for [HERO3](https://github.com/KonradIT/goprowifihack/blob/master/HERO3/Framerates-Resolutions.md) and here for [HERO4 and newer](https://github.com/KonradIT/goprowifihack/blob/master/HERO4/Framerates-Resolutions.md) + +## To Do list and known issues + +- Missing get status which gives info like mode (photo, video), fow and so on: [see here](https://github.com/KonradIT/goprowifihack/blob/master/HERO5/HERO5-Commands.md#gopro-hero5-commands-status-and-notes) +- Wait for the ESP32 core to make a stable BLE core, right now it has many issues, especially, if used together with wifi: [see here](https://github.com/espressif/arduino-esp32/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+ble) +- No confirm pairing for HERO4: [see here](https://github.com/KonradIT/goprowifihack/blob/master/HERO4/WifiCommands.md#code-pairing) +- Missing some modes for HERO4 and newer camera: [see here](https://github.com/KonradIT/goprowifihack/blob/master/HERO4/WifiCommands.md#secondary-modes) +- The arduino class String() could cause memory leaks (I never had problem yet), move to char array? 🤔 +- `BSSID()` and `macAddress()` not perfectly compatible with arduino API: [see here](https://github.com/espressif/arduino-esp32/issues/2613) +- make gopro_mac_address field optional + ## Reference All the commands came from: https://github.com/KonradIT/goprowifihack -The idea cames from another gopro library: https://github.com/agdl/GoPRO which works only on arduino WiFi boards and only with gopro HERO3. +The idea of making a GoPro library for arduino comes from another library https://github.com/agdl/GoPRO which works only on arduino WiFi boards and only with GoPro HERO3. \ No newline at end of file diff --git a/examples/ESP32_FreeRTOS/ESP32_FreeRTOS.ino b/examples/ESP32_FreeRTOS/ESP32_FreeRTOS.ino index 6563f80..de44993 100644 --- a/examples/ESP32_FreeRTOS/ESP32_FreeRTOS.ino +++ b/examples/ESP32_FreeRTOS/ESP32_FreeRTOS.ino @@ -1,12 +1,14 @@ #include #include "Constants.h" +/* + Control your GoPro with the Serial Monitor: to start edit the file Constants.h and choose your camera +*/ + // Choose your camera //GoProControl gp(GOPRO_SSID, GOPRO_PASS, CAMERA); // use this if you have a HERO3 or older //GoProControl gp(GOPRO_SSID, GOPRO_PASS, CAMERA, gopro_mac_address, BOARD_NAME); -char in = 0; - void setup() { gp.enableDebug(&Serial); @@ -15,116 +17,119 @@ void setup() void loop() { + char in = 0; if (Serial.available() > 0) { in = Serial.read(); - //Serial.write(in); } switch (in) { - default: - break; - - // connect - case 'C': - gp.begin(); - break; - - // turn on/off - case 'T': - gp.turnOn(); - break; - - case 't': - gp.turnOff(); - break; - - // take a picture of start a video - case 'A': - gp.shoot(); - break; - - // stop the video - case 'S': - gp.stopShoot(); - break; - - //set modes - case 'V': - gp.setMode(VIDEO_MODE); - break; - - case 'P': - gp.setMode(PHOTO_MODE); - break; - - case 'M': - gp.setMode(MULTISHOT_MODE); - break; - - // set orientation - case 'u': - gp.setOrientation(ORIENTATION_UP); - break; - - case 'd': - gp.setOrientation(ORIENTATION_DOWN); - break; - - case 'W': - gp.setVideoFov(MEDIUM_FOV); - break; - - case 'E': - gp.setFrameRate(FR_120); - break; - - case 'f': - gp.setPhotoResolution(PR_11MP_WIDE); - break; - - case 'F': - gp.setVideoResolution(VR_1080p); - break; - - case 'L': - gp.setTimeLapseInterval(60); - break; - - case 'O': - gp.localizationOn(); - break; - - case 'I': - gp.localizationOff(); - break; - - case 'l': - gp.deleteLast(); - break; - - case 'D': - gp.deleteAll(); - break; - - case 'X': - gp.end(); - break; - - case 'p': - gp.printStatus(); - break; + default: + break; + + // Connect + case 'C': + gp.begin(); + break; + + // Turn on and off + case 'T': + gp.turnOn(); + break; + + case 't': + gp.turnOff(); + break; + + // Take a picture of start a video + case 'A': + gp.shoot(); + break; + + // Stop the video + case 'S': + gp.stopShoot(); + break; + + // Set modes + case 'V': + gp.setMode(VIDEO_MODE); + break; + + case 'P': + gp.setMode(PHOTO_MODE); + break; + + case 'M': + gp.setMode(MULTISHOT_MODE); + break; + + // Change the orientation + case 'u': + gp.setOrientation(ORIENTATION_UP); + break; + + case 'd': + gp.setOrientation(ORIENTATION_DOWN); + break; + + // Change other parameters + case 'W': + gp.setVideoFov(MEDIUM_FOV); + break; + + case 'E': + gp.setFrameRate(FR_120); + break; + + case 'f': + gp.setPhotoResolution(PR_11MP_WIDE); + break; + + case 'F': + gp.setVideoResolution(VR_1080p); + break; + + case 'L': + gp.setTimeLapseInterval(60); + break; + + // Localize the camera + case 'O': + gp.localizationOn(); + break; + + case 'I': + gp.localizationOff(); + break; + + // Delete some files, be carefull! + case 'l': + gp.deleteLast(); + break; + + case 'D': + gp.deleteAll(); + break; + + // Print useful data + case 'p': + gp.printStatus(); + break; + + // Close the connection + case 'X': + gp.end(); + break; } - - in = 0; } void keep_alive(void *parameter) { - while (gp.checkConnection(true)) { + while (1) + { gp.keepAlive(); - Serial.println("KeepAlive sent"); } - vTaskDelete( NULL ); -} + vTaskDelete(NULL); +} \ No newline at end of file diff --git a/examples/GoProControl/GoProControl.ino b/examples/GoProControl/GoProControl.ino index e8d890a..f442c26 100644 --- a/examples/GoProControl/GoProControl.ino +++ b/examples/GoProControl/GoProControl.ino @@ -1,12 +1,14 @@ #include #include "Constants.h" +/* + Control your GoPro with the Serial Monitor: to start edit the file Constants.h and choose your camera +*/ + // Choose your camera //GoProControl gp(GOPRO_SSID, GOPRO_PASS, CAMERA); // use this if you have a HERO3 or older //GoProControl gp(GOPRO_SSID, GOPRO_PASS, CAMERA, gopro_mac_address, BOARD_NAME); -char in = 0; - void setup() { gp.enableDebug(&Serial); @@ -14,10 +16,10 @@ void setup() void loop() { + char in = 0; if (Serial.available() > 0) { in = Serial.read(); - //Serial.write(in); } switch (in) @@ -25,12 +27,12 @@ void loop() default: break; - // connect + // Connect case 'C': gp.begin(); break; - // turn on/off + // Turn on and off case 'T': gp.turnOn(); break; @@ -39,17 +41,17 @@ void loop() gp.turnOff(); break; - // take a picture of start a video + // Take a picture of start a video case 'A': gp.shoot(); break; - // stop the video + // Stop the video case 'S': gp.stopShoot(); break; - //set modes + // Set modes case 'V': gp.setMode(VIDEO_MODE); break; @@ -62,7 +64,7 @@ void loop() gp.setMode(MULTISHOT_MODE); break; - // set orientation + // Change the orientation case 'u': gp.setOrientation(ORIENTATION_UP); break; @@ -71,6 +73,7 @@ void loop() gp.setOrientation(ORIENTATION_DOWN); break; + // Change other parameters case 'W': gp.setVideoFov(MEDIUM_FOV); break; @@ -91,6 +94,7 @@ void loop() gp.setTimeLapseInterval(60); break; + // Localize the camera case 'O': gp.localizationOn(); break; @@ -99,6 +103,7 @@ void loop() gp.localizationOff(); break; + // Delete some files, be carefull! case 'l': gp.deleteLast(); break; @@ -107,19 +112,15 @@ void loop() gp.deleteAll(); break; - case 'X': - gp.end(); - break; - + // Print useful data case 'p': gp.printStatus(); break; - case 'K': - gp.keepAlive(); + // Close the connection + case 'X': + gp.end(); break; } - - in = 0; - gp.keepAlive(); -} + gp.keepAlive(); // not needed on HERO3 +} \ No newline at end of file diff --git a/examples/MultiCam/MultiCam.ino b/examples/MultiCam/MultiCam.ino index 26ba860..5b6fd98 100644 --- a/examples/MultiCam/MultiCam.ino +++ b/examples/MultiCam/MultiCam.ino @@ -1,6 +1,10 @@ #include #include "Constants.h" +/* + Control two or more GoPro: to start edit the file Constants.h +*/ + GoProControl Hero_Seven(GOPRO_SSID, GOPRO_PASS, CAMERA, gopro_mac_address, BOARD_NAME); GoProControl Hero_Four(GOPRO_2_SSID, GOPRO_2_PASS, CAMERA_2, gopro_2_mac_address, BOARD_NAME); @@ -8,20 +12,15 @@ void setup() { Hero_Seven.enableDebug(&Serial); Hero_Four.enableDebug(&Serial); + + Hero_Four.begin(); + Hero_Seven.begin(); } void loop() { - Hero_Seven.begin(); - delay(1000); - if (!Hero_Seven.shoot()) - { - Hero_Seven.begin(); - } - delay(1000); - Hero_Four.begin(); - delay(1000); Hero_Four.shoot(); - - delay(2000); + delay(1000); + Hero_Seven.shoot(); + delay(500); } \ No newline at end of file diff --git a/keywords.txt b/keywords.txt index c4362ae..195a13b 100644 --- a/keywords.txt +++ b/keywords.txt @@ -8,122 +8,111 @@ GoProControl KEYWORD1 # Methods and Functions (KEYWORD2) ####################################### -begin KEYWORD2 -enableDebug KEYWORD2 -GoProStatus KEYWORD2 - -turnOn KEYWORD2 -turnOff KEYWORD2 - -startCapture KEYWORD2 -stopCapture KEYWORD2 - -localizationOn KEYWORD2 -localizationOff KEYWORD2 - -setTimeLapseInterval KEYWORD2 -setContinuousShot KEYWORD2 -setCameraMode KEYWORD2 -setCameraOrientation KEYWORD2 -setVideoMode KEYWORD2 -setVideoResolution KEYWORD2 -setPhotoResolution KEYWORD2 -setFrameRate KEYWORD2 -setFov KEYWORD2 -confirmPairing KEYWORD2 -sendWoL KEYWORD2 -deleteLast KEYWORD2 -deleteAll KEYWORD2 +begin KEYWORD2 +end KEYWORD2 +keepAlive KEYWORD2 +enableBLE KEYWORD2 +disableBLE KEYWORD2 +wifiOff KEYWORD2 +wifiOn KEYWORD2 + +turnOn KEYWORD2 +turnOff KEYWORD2 +isOn KEYWORD2 +checkConnection KEYWORD2 + +shoot KEYWORD2 +stopShoot KEYWORD2 + +setMode KEYWORD2 +setOrientation KEYWORD2 + +setVideoResolution KEYWORD2 +setVideoFov KEYWORD2 +setFrameRate KEYWORD2 +setVideoEncoding KEYWORD2 + +setPhotoResolution KEYWORD2 +setTimeLapseInterval KEYWORD2 +setContinuousShot KEYWORD2 + +localizationOn KEYWORD2 +localizationOff KEYWORD2 +deleteLast KEYWORD2 +deleteAll KEYWORD2 + +enableDebug KEYWORD2 +disableDebug KEYWORD2 +printStatus KEYWORD2 ####################################### # Constants (LITERAL1) +####################################### HERO LITERAL1 HERO2 LITERAL1 HERO3 LITERAL1 -HERO3P LITERAL1 -HERO3B LITERAL1 -HERO3BP LITERAL1 HERO4 LITERAL1 HERO5 LITERAL1 HERO6 LITERAL1 HERO7 LITERAL1 +FUSION LITERAL1 -VIDEO_MODE LITERAL1 -PHOTO_MODE LITERAL1 -BURST_MODE LITERAL1 +VIDEO_MODE LITERAL1 +PHOTO_MODE LITERAL1 +BURST_MODE LITERAL1 TIMELAPSE_MODE LITERAL1 -TIMER_MODE LITERAL1 -PLAY_HDMI LITERAL1 -MULTISHOT_MODE LITERAL1 +TIMER_MODE LITERAL1 +PLAY_HDMI_MODE LITERAL1 +MULTISHOT_MODE LITERAL1 -ORIENTATION_UP LITERAL1 +ORIENTATION_UP LITERAL1 ORIENTATION_DOWN LITERAL1 -ORIENTATION_AUTO LITERAL1 - -VR_WVGA60 LITERAL1 -VR_WVGA120 LITERAL1 -VR_720_30 LITERAL1 -VR_720_60 LITERAL1 -VR_960_30 LITERAL1 -VR_960_48 LITERAL1 -VR_1080_30 LITERAL1 - -VR_4K LITERAL -VR_2K LITERAL -VR_2K_SuperView LITERAL -VR_1440p LITERAL -VR_1080p_SuperView LITERAL -VR_1080p LITERAL -VR_960p LITERAL -VR_720p_SuperView LITERAL -VR_720p LITERAL -VR_WVGA LITERAL - -FPS12 LITERAL1 -FPS15 LITERAL1 -FPS12p5 LITERAL1 -FPS24 LITERAL1 -FPS25 LITERAL1 -FPS30 LITERAL1 -FPS48 LITERAL1 -FPS50 LITERAL1 -FPS60 LITERAL1 -FPS100 LITERAL1 -FPS120 LITERAL1 -FPS240 LITERAL1 - -FR_240 LITERAL -FR_120 LITERAL -FR_100 LITERAL -FR_90 LITERAL -FR_80 LITERAL -FR_60 LITERAL -FR_50 LITERAL -FR_48 LITERAL -FR_30 LITERAL -FR_25 LITERAL +ORIENTATION_AUTO LITERAL1 + +VR_4K LITERAL1 +VR_2K LITERAL1 +VR_2K_SuperView LITERAL1 +VR_1440p LITERAL1 +VR_1080p_SuperView LITERAL1 +VR_1080p LITERAL1 +VR_960p LITERAL1 +VR_720p_SuperView LITERAL1 +VR_720p LITERAL1 +VR_WVGA LITERAL1 WIDE_FOV LITERAL1 MEDIUM_FOV LITERAL1 NARROW_FOV LITERAL1 LINEAR_FOV LITERAL1 -PR_11mpW LITERAL1 -PR_8mpW LITERAL1 -PR_5mpW LITERAL1 -PR_7mpW LITERAL1 -PR_12mpW LITERAL1 - -PR_12MP_Wide LITERAL -PR_12MP_Linear 1LITERAL -PR_12MP_Medium LITERAL -PR_12MP_Narrow LITERAL -PR_7MP_Wide LITERAL -PR_7MP_Medium LITERAL -PR_5MP_Wide LITERAL +FR_240 LITERAL1 +FR_120 LITERAL1 +FR_100 LITERAL1 +FR_90 LITERAL1 +FR_80 LITERAL1 +FR_60 LITERAL1 +FR_50 LITERAL1 +FR_48 LITERAL1 +FR_30 LITERAL1 +FR_25 LITERAL1 +FR_24 LITERAL1 +FR_15 LITERAL1 +FR_12p5 LITERAL1 +FR_12 LITERAL1 NTSC LITERAL1 -PAL LITERAL1 -####################################### +PAL LITERAL1 + +PR_12MP_WIDE LITERAL1 +PR_12MP_MEDIUM LITERAL1 +PR_12MP_NARROW LITERAL1 +PR_12MP_LINEAR LITERAL1 +PR_11MP_WIDE LITERAL1 +PR_8MP_WIDE LITERAL1 +PR_8MP_MEDIUM LITERAL1 +PR_7MP_WIDE LITERAL1 +PR_7MP_MEDIUM LITERAL1 +PR_5MP_WIDE LITERAL1 +PR_5MP_MEDIUM LITERAL1 \ No newline at end of file diff --git a/library.properties b/library.properties index 78cb9dc..147bb4f 100644 --- a/library.properties +++ b/library.properties @@ -1,9 +1,9 @@ name=GoProControl -version=0.9.3 +version=1.0.0 author=Vincenzo G. / KonradIT maintainer=Vincenzo G. / KonradIT sentence=A library that makes using GoPro a breeze. paragraph=Control your GoPro HERO3, HERO4, HERO5, HERO6 and HERO7 from Arduino category=Device Control url=https://github.com/aster94/GoProControl/ -architectures=* +architectures=* \ No newline at end of file diff --git a/src/GoProControl.cpp b/src/GoProControl.cpp index 80c43a2..7d64062 100644 --- a/src/GoProControl.cpp +++ b/src/GoProControl.cpp @@ -70,24 +70,32 @@ uint8_t GoProControl::begin() WiFi.begin(_ssid.c_str(), _pwd.c_str()); - while (WiFi.status() != WL_CONNECTED) { - delay(1000); - Serial.println("Connecting to WiFi.."); - } + uint32_t start_time = millis(); + while (WiFi.status() != WL_CONNECTED && start_time + MAX_WAIT_TIME > millis()) + { + if (_debug) + { + delay(100); + _debug_port->print("."); + } + } if (WiFi.status() == WL_CONNECTED) { if (_debug) { - _debug_port->println("Connected to GoPro"); + _debug_port->println("\nConnected to GoPro"); } _connected = true; return true; } else { - _debug_port->print("Connection failed with status: "); - _debug_port->println(WiFi.status()); + if (_debug) + { + _debug_port->print("\nConnection failed with status: "); + _debug_port->println(WiFi.status()); + } _connected = false; } @@ -126,7 +134,7 @@ uint8_t GoProControl::keepAlive() { if (_camera == HERO3) { - // not needed since the connection won't be closed by the camera (tested 6 minutes) + // not needed since the connection won't be closed by the camera (tested for more then 6 minutes) return true; } else if (_camera >= HERO4) @@ -136,7 +144,6 @@ uint8_t GoProControl::keepAlive() _debug_port->println("Keeping connection alive"); } sendRequest("_GPHD_:0:0:2:0.000000\n"); - // should it answer? } } } @@ -146,7 +153,7 @@ uint8_t GoProControl::keepAlive() //////////////////////////////////////////////////////////// #if defined(ARDUINO_ARCH_ESP32) -// none of these function will work, I am adding these for a future release +// none of these function will work, I am adding these for a future release, see the readME // https://github.com/KonradIT/goprowifihack/blob/master/HERO5/HERO5-Commands.md#bluetooth-pairing uint8_t GoProControl::enableBLE() { @@ -377,7 +384,7 @@ uint8_t GoProControl::shoot() #else if (_debug) { - _debug_port->println("This shoudln't be run"); + _debug_port->println("This shouldn't be run"); } return -1; #endif @@ -425,7 +432,7 @@ uint8_t GoProControl::stopShoot() #else if (_debug) { - _debug_port->println("This shoudln't be run"); + _debug_port->println("This shouldn't be run"); } return -1; #endif @@ -490,7 +497,6 @@ uint8_t GoProControl::setMode(const uint8_t option) } else if (_camera >= HERO4) { - // todo: add sub-modes switch (option) { case VIDEO_MODE: @@ -533,7 +539,7 @@ uint8_t GoProControl::setMode(const uint8_t option) #else if (_debug) { - _debug_port->println("This shoudln't be run"); + _debug_port->println("This shouldn't be run"); } return -1; #endif @@ -1165,7 +1171,10 @@ uint8_t GoProControl::setContinuousShot(const uint8_t option) } else if (_camera >= HERO4) { - // Not supported in Hero4/5/6/7 + if (_debug) + { + _debug_port->println("Not supported by HERO4 and newer"); + } return false; } return sendHTTPRequest(_request); @@ -1217,7 +1226,6 @@ uint8_t GoProControl::localizationOff() } return false; } - // todo test to turn it on and off with the camera off if (!isOn()) // camera is off { @@ -1337,41 +1345,43 @@ void GoProControl::printStatus() _debug_port->print(WiFi.RSSI()); _debug_port->println(" dBm"); - uint8_t mac[6]; - WiFi.macAddress(mac); + uint8_t my_mac[6]; + WiFi.macAddress(my_mac); _debug_port->print("My MAC:\t\t"); - _debug_port->print(mac[5], HEX); + _debug_port->print(my_mac[5], HEX); _debug_port->print(":"); - _debug_port->print(mac[4], HEX); + _debug_port->print(my_mac[4], HEX); _debug_port->print(":"); - _debug_port->print(mac[3], HEX); + _debug_port->print(my_mac[3], HEX); _debug_port->print(":"); - _debug_port->print(mac[2], HEX); + _debug_port->print(my_mac[2], HEX); _debug_port->print(":"); - _debug_port->print(mac[1], HEX); + _debug_port->print(my_mac[1], HEX); _debug_port->print(":"); - _debug_port->println(mac[0], HEX); + _debug_port->println(my_mac[0], HEX); + /* + uint8_t *gp_mac = WiFi.BSSID(); + _debug_port->print("GoPro MAC:\t"); + _debug_port->print(gp_mac[5], HEX); + _debug_port->print(":"); + _debug_port->print(gp_mac[4], HEX); + _debug_port->print(":"); + _debug_port->print(gp_mac[3], HEX); + _debug_port->print(":"); + _debug_port->print(gp_mac[2], HEX); + _debug_port->print(":"); + _debug_port->print(gp_mac[1], HEX); + _debug_port->print(":"); + _debug_port->println(gp_mac[0], HEX); + */ + if (_camera >= HERO4) { - _debug_port->print("GoPro MAC:\t"); - uint8_t* gpMac = WiFi.BSSID(); - _debug_port->print(gpMac[5],HEX); - _debug_port->print(":"); - _debug_port->print(gpMac[4],HEX); - _debug_port->print(":"); - _debug_port->print(gpMac[3],HEX); - _debug_port->print(":"); - _debug_port->print(gpMac[2],HEX); - _debug_port->print(":"); - _debug_port->print(gpMac[1],HEX); - _debug_port->print(":"); - _debug_port->println(gpMac[0],HEX); _debug_port->print("Board Name:\t"); _debug_port->println(_board_name); } - // todo add more info like mode (photo, video), fow and so on - // convert this output in a human readable https://github.com/KonradIT/goprowifihack/blob/master/HERO5/HERO5-Commands.md#gopro-hero5-commands-status-and-notes + _debug_port->println(); } } @@ -1528,18 +1538,17 @@ uint8_t GoProControl::confirmPairing() { if (_debug) { - _debug_port->println("Not supported"); + _debug_port->println("Not supported by HERO3"); } return false; } else if (_camera == HERO4) { - // https://github.com/KonradIT/goprowifihack/blob/master/HERO4/WifiCommands.md#code-pairing - // todo if (_debug) { - _debug_port->println("not implemented yet"); + _debug_port->println("Not implemented yet, see readME"); } + return false; } else if (_camera >= HERO5) { @@ -1549,52 +1558,87 @@ uint8_t GoProControl::confirmPairing() return sendHTTPRequest(_request); } -uint16_t GoProControl::listenResponse(const bool only_first_line) +uint16_t GoProControl::listenResponse() { - memset(_response, 0, LEN(_response)); // empty _response - if (_wifi_client.available() == 0) + char incoming; + char first_line[20]; + bool first_line_completed = false; + uint8_t index = 0; + + if (_debug) + { + _debug_port->print("Waiting response"); + } + + uint32_t start_time = millis(); + while (_wifi_client.available() == 0 && start_time + MAX_WAIT_TIME > millis()) { delay(5); + if (_debug) + { + _debug_port->print("."); + } } - _wifi_client.readBytesUntil('\n', _response, 18); + if (_debug) { - _debug_port->println("Response body start"); - _debug_port->println(_response); + _debug_port->println("\nStart response body"); } - char incoming; - while (_wifi_client.available()) // empty the incoming buffer + while (_wifi_client.available() > 0) { incoming = _wifi_client.read(); - if (only_first_line == false && _debug) + if (first_line_completed == false) + { + first_line[index++] = incoming; + if (incoming == '\n') + { + first_line_completed = true; + } + } + if (_debug) { _debug_port->print(incoming); } } + if (_debug) { - _debug_port->println("Response body end"); + _debug_port->println("\nEnd response body"); } - if (_response[0] == 0) + if (first_line[0] == NULL) // empty response { if (_debug) { - _debug_port->println("empty response"); + _debug_port->println("No response"); } - return -1; + return false; } - // typical response: "HTTP/1.1 200 OK" we need to split it - char *token = strtok(_response, " "); // waste first part (HTTP/1.1) of the response - token = strtok(NULL, " "); // this is the response code - uint16_t code = atoi(token); // convert to integer + + uint16_t response_code = atoi(splitString(first_line, 1)); if (_debug) { _debug_port->print("Response code: "); - _debug_port->println(code); + _debug_port->println(response_code); } - return code; + return response_code; } + +char *GoProControl::splitString(char str[], uint8_t index) +{ + uint8_t counter = 0; + char *token = strtok(str, " "); + while (token != NULL) + { + if (counter == index) + { + return token; + } + token = strtok(NULL, " "); + counter++; + } + return NULL; +} \ No newline at end of file diff --git a/src/GoProControl.h b/src/GoProControl.h index cec2008..a63211b 100644 --- a/src/GoProControl.h +++ b/src/GoProControl.h @@ -28,28 +28,25 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SO #include #elif defined(ARDUINO_ARCH_ESP32) // ESP32 #include -// todo include BLE libraries #elif defined(ARDUINO_SAMD_MKR1000) // MKR1000 #include -#elif defined(ARDUINO_SAMD_MKRWIFI1010) // MKR WiFi 1010 +#elif defined(ARDUINO_SAMD_MKRWIFI1010) || defined(ARDUINO_AVR_UNO_WIFI_REV2) // MKR WiFi 1010 and UNO WiFi Rev.2 #include #elif defined(ARDUINO_SAMD_MKRVIDOR4000) // MKR VIDOR 4000 #include #include -#elif defined(ARDUINO_AVR_UNO_WIFI_REV2) // UNO WiFi Rev.2 -#include #else // any board (like arduino UNO) without wifi + ESP01 with AT commands #include +#include +#define WiFiClient WiFiEspClient +#define WiFiUDP WiFiEspUDP #define AT_COMMAND -#warning "Are you using an ESP01 + AT commands? if not open an issue on github: https://github.com/aster94/GoProControl" +#warning "Are you using an ESP01 + AT commands? if not open an issue on github: https://github.com/aster94/GoProControl/issues" #endif // include the UDP library to turn on and off HERO4 and newer camera #if not defined(AT_COMMAND) #include -#else -#include -#define WiFiClient WiFiEspClient #endif // include the correct Serial class @@ -73,7 +70,7 @@ class GoProControl // BLE functions are availables only on ESP32 #if defined(ARDUINO_ARCH_ESP32) - // none of these function will work, I am adding these for a proof of concept + // none of these function will work, I am adding these for a proof of concept, see the readME // https://github.com/KonradIT/goprowifihack/blob/master/HERO5/HERO5-Commands.md#bluetooth-pairing uint8_t enableBLE(); uint8_t disableBLE(); @@ -130,7 +127,6 @@ class GoProControl String _request; String _parameter; - char _response[20]; uint8_t _mac_address[6]; String _board_name; @@ -152,7 +148,8 @@ class GoProControl #endif uint8_t connectClient(); uint8_t confirmPairing(); - uint16_t listenResponse(const bool only_first_line = true); + uint16_t listenResponse(); + char *splitString(char str[], uint8_t index); }; -#endif //GOPRO_CONTROL_H +#endif //GOPRO_CONTROL_H \ No newline at end of file diff --git a/src/Settings.h b/src/Settings.h index d1bbb5f..a0e83f9 100644 --- a/src/Settings.h +++ b/src/Settings.h @@ -17,7 +17,8 @@ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#define KEEP_ALIVE 3000 +#define KEEP_ALIVE 1500 +#define MAX_WAIT_TIME 2000 enum camera { @@ -27,7 +28,8 @@ enum camera HERO4, HERO5, HERO6, - HERO7 + HERO7, + FUSION }; //The above settings must be between a *_first and *_last member @@ -132,4 +134,4 @@ const uint8_t BLE_RecordStop[] = {01, 01, 00}; const uint8_t BLE_ModeVideo[] = {02, 01, 00}; const uint8_t BLE_ModePhoto[] = {02, 01, 01}; const uint8_t BLE_ModeMultiShot[] = {02, 01, 02}; -#endif +#endif \ No newline at end of file