I have set an ESP32 up to behave as a keyboard - this demo works perfectly:
/**
* This example turns the ESP32 into a Bluetooth LE keyboard that writes the words, presses Enter, presses a media key and then Ctrl+Alt+Delete
*/
#include <BleKeyboard.h>
BleKeyboard bleKeyboard;
void setup() {
Serial.begin(115200);
Serial.println("Starting BLE work!");
bleKeyboard.begin();
}
void loop() {
if(bleKeyboard.isConnected()) {
Serial.println("Sending 'Hello world'...");
bleKeyboard.print("Hello world");
delay(1000);
Serial.println("Sending Enter key...");
bleKeyboard.write(KEY_RETURN);
delay(1000);
Serial.println("Sending Play/Pause media key...");
bleKeyboard.write(KEY_MEDIA_PLAY_PAUSE);
delay(1000);
Serial.println("Sending Ctrl+Alt+Delete...");
bleKeyboard.press(KEY_LEFT_CTRL);
bleKeyboard.press(KEY_LEFT_ALT);
bleKeyboard.press(KEY_DELETE);
delay(100);
bleKeyboard.releaseAll();
}
Serial.println("Waiting 5 seconds...");
delay(5000);
}
I have tried to modify the bleKeyboard.print("Hello world"); to have my long command line curl.exe . . . . . in place of the Hello world. Then I get the following error:
C:\Users\Gerald\Dropbox\A. PROJECTS\GoPro\ESP32 WROOM\GDAttempt00\GDAttempt01.ino\GDAttempt01.ino.ino:17:38: error: stray '\' in program
bleKeyboard.print("curl.exe -d "{\"command\": \"sendCameraCommand\",\"cameras\": [\"GoPro 2281\"],\"cameraCommand\": \"startRecording\"}" "http://192.168.0.108:809"");
^
C:\Users\Gerald\Dropbox\A. PROJECTS\GoPro\ESP32 WROOM\GDAttempt00\GDAttempt01.ino\GDAttempt01.ino.ino:17:169: error: missing terminating " character
bleKeyboard.print("curl.exe -d "{\"command\": \"sendCameraCommand\",\"cameras\": [\"GoPro 2281\"],\"cameraCommand\": \"startRecording\"}" "http://192.168.0.108:809"");
^~~
C:\Users\Gerald\Dropbox\A. PROJECTS\GoPro\ESP32 WROOM\GDAttempt00\GDAttempt01.ino\GDAttempt01.ino.ino: In function 'void loop()':
C:\Users\Gerald\Dropbox\A. PROJECTS\GoPro\ESP32 WROOM\GDAttempt00\GDAttempt01.ino\GDAttempt01.ino.ino:17:37: error: expected ')' before '{' token
bleKeyboard.print("curl.exe -d "{\"command\": \"sendCameraCommand\",\"cameras\": [\"GoPro 2281\"],\"cameraCommand\": \"startRecording\"}" "http://192.168.0.108:809"");
~ ^
)
C:\Users\Gerald\Dropbox\A. PROJECTS\GoPro\ESP32 WROOM\GDAttempt00\GDAttempt01.ino\GDAttempt01.ino.ino:41:1: error: expected '}' at end of input
}
^
C:\Users\Gerald\Dropbox\A. PROJECTS\GoPro\ESP32 WROOM\GDAttempt00\GDAttempt01.ino\GDAttempt01.ino.ino:14:13: note: to match this '{'
void loop() {
^
exit status 1
Compilation error: stray '\' in program
Sorry , I am a beginner. How can I insert my long command line into the program so that the "keyboard" writes it. (I want to to swap between 2 commands every 5 seconds - the words start and stop being the only difference)
From the error messages, it just looks like you have failed to escape every quote mark and maybe a few others.
Post the entire command line in a <CODE/> block, as you would have typed it.
Post the entire attempt to get this as one quoted string (character array or constant). In a <CODE/> block
bleKeyboard.print("curl.exe -d "{\"command...
The first backslash is without the quotation. Essentially all quotes but the first and last have to be escaped.
bleKeyboard.print ( "curl.exe -d " {\"command...
That first "part" is complete, the backslash makes no sense outside a quote.
Not to add mud to the water, but when or if you start wanting that string to be adjustable by code, keep sprintf() in mind. Still need to escape quote marks.
I am trying to start and stop 3 GoPro cameras. Therefore there will only be 6 variations/permutations of that command line. I derived the line from here. Json converted to single line.
This is what caused the errors:
/**
* This example turns the ESP32 into a Bluetooth LE keyboard that writes the words, presses Enter, presses a media key and then Ctrl+Alt+Delete
*/
#include <BleKeyboard.h>
BleKeyboard bleKeyboard;
void setup() {
Serial.begin(115200);
Serial.println("Starting BLE work!");
bleKeyboard.begin();
}
void loop() {
if(bleKeyboard.isConnected()) {
Serial.println("Sending 'Hello world'...");
bleKeyboard.print("curl.exe -d "{\"command\": \"sendCameraCommand\",\"cameras\": [\"GoPro 2281\"],\"cameraCommand\": \"startRecording\"}" "http://192.168.0.108:809"");
delay(1000);
Serial.println("Sending Enter key...");
bleKeyboard.write(KEY_RETURN);
delay(1000);
Serial.println("Sending Play/Pause media key...");
bleKeyboard.write(KEY_MEDIA_PLAY_PAUSE);
delay(1000);
Serial.println("Sending Ctrl+Alt+Delete...");
bleKeyboard.press(KEY_LEFT_CTRL);
bleKeyboard.press(KEY_LEFT_ALT);
bleKeyboard.press(KEY_DELETE);
delay(100);
bleKeyboard.releaseAll();
}
Serial.println("Waiting 5 seconds...");
delay(5000);
}
for Stefan; I am testing at a windows computer, but eventually it will be on Raspberry Pi3.
(I am trying to automate the making of videos like this https://www.youtube.com/watch?v=c5ApZpFzdh0 )
Please post the command line as you would type it. In a code block.
Simply put, any quote marks within the quoted string have to be escaped. You only did some of them, I think, but until you post what you are trying to say, it's hard to,tell,what you have, and have not, seen or overlooked.
I just implemented what @alto777 already posted; escape every " that is a part of the string by a backslash ... Only the first and the last one are used to frame the string (if my assumption is correct).
char command[] = // Should contain all(!) data that are identical for each camera to save memory space
const char camNo[noOfCams] // Holds the different numbers of the cameras
const char camIP[noOfCams][8] // Holds the differences of the camera IPs (may be even less e.g. the last 3 entries?)
char buffer[160]; // Must be large enough to hold the final command, otherwise the controller may crash
sprintf(buffer,command,camNo[i],camIP[i]); // Copies camNo and camIP to those places in the command string where you find a string placeholder %s
Now its your turn ...
ec2021
See the yellow marked characters in the Wokwi screenshot to identify the differences:
which line of code would come after the array declaration.
Also, parallel arrays like these can be reformed into one array of struct variables, I don't usually bother until it starts to get out of hand. It's a tradeoff of a kind. For this kinda thing, I like the parallel arrays, for me it is easier to read in the declartions and use.
Thanks for an amazing response. Unfortunately a lot is Greek to me. I am away from my desk for a while and will consider it all carefully when I get back.
3 gopros in car, front and sides. The each need start and stop commands.
Suggest you maybe read my 2 posts above carefully again.
There are a few things that are important to consider
If you want to use mutliple parameters with double-quotationmarks like in your case
you have to put a single-quotation mark at the most left and the most right to make AHK accept the whole thing
#Requires AutoHotkey v2+
;script for AHK v2 does NOT work with AHK v1
#SingleInstance Force
SetTimer(MyTimedAction, 5000)
MyTimedAction()
{
Run 'C:\Windows\SysWOW64\curl.exe -d "{"command": "sendCameraCommand","cameras": ["GoPro 2281"],"cameraCommand": "startRecording"}" "http://192.168.0.108:809" '
Run 'C:\Windows\SysWOW64\curl.exe -d "{"command": "sendCameraCommand","cameras": ["GoPro 2282"],"cameraCommand": "startRecording"}" "http://192.168.0.208:809" '
Run 'C:\Windows\SysWOW64\curl.exe -d "{"command": "sendCameraCommand","cameras": ["GoPro 2283"],"cameraCommand": "startRecording"}" "http://192.168.0.308:809" '
Run 'C:\Windows\SysWOW64\curl.exe -d "{"command": "sendCameraCommand","cameras": ["GoPro 2284"],"cameraCommand": "startRecording"}" "http://192.168.0.408:809" '
Run 'C:\Windows\SysWOW64\curl.exe -d "{"command": "sendCameraCommand","cameras": ["GoPro 2285"],"cameraCommand": "startRecording"}" "http://192.168.0.508:809" '
Run 'C:\Windows\SysWOW64\curl.exe -d "{"command": "sendCameraCommand","cameras": ["GoPro 2286"],"cameraCommand": "startRecording"}" "http://192.168.0.608:809" '
}
What's missing from your side is just the information which parts of the command line change from camera to camera.
For the example I assumed that it is the camera number and the last two bytes of the IP, e.g. for the first camera {"2281","108:809"}.
I inserted two placeholders in the command line that are filled with the changing data by the sprintf function. The rest of the command line stays as it has been defined.
%s is a placeholder for a string. This placeholder is replaced here by the appropriate cam name:
[\"GoPro %s\"],
So for cam name "1234" the resulting string would be
[\"GoPro 1234\"],
Here %s is replaced by the partial IP
"http://192.168.0.%s\"";
For e.g. PartialIP = "111:222" the result is
"http://192.168.0.111:222\"";
If you have less to change then modify the command line to hold everything that is common to all cams and insert %s exactly and only where different data are required. Then modify the data in the array to provide exactly these data.
The function sprintf expects variables in the same order (left to right) as the placeholders are inserted in the format string (which is called "command" in the examples).