Trying to understand how to move from using bridge data to the http API data
I use bridge data to authorize NFC cards at various doors in my lock project
/*
this will copy data to the device with the id sent as param[1]
param[0] determines if we copy all data or just 1 card
*/
BLYNK_WRITE(bridgewrite)
{
String stoken = param[1].asStr(); // get the lock token string
char token[BLYNKSIZE];
byte tokenbytes[BLYNKSIZE];
stoken.getBytes(tokenbytes, BLYNKSIZE); // copy the token string to a char array
for ( int i = 0; i < BLYNKSIZE; i++) {
token[i] = tokenbytes[i];
}
bridge_lock.setAuthToken(token); // set the bridge token to the lock
bridge_lock.virtualWrite(bridgedata, cardHolder[0], cardId[0], accessFlags[0]); //copy current card from reader
}
/*
this will copy data to the device with the id sent as param[1]
param[0] determines if we copy all data or just 1 card
*/
BLYNK_WRITE(bridgewriteall)
{
String stoken = param[1].asStr(); // get the lock token string
char token[BLYNKSIZE];
byte tokenbytes[BLYNKSIZE];
stoken.getBytes(tokenbytes, BLYNKSIZE); // copy the token string to a char array
for ( int i = 0; i < BLYNKSIZE; i++) {
token[i] = tokenbytes[i];
}
bridge_lock.setAuthToken(token); // set the bridge token to the lock
for (int i = 1; i <= rowIndex; i++) {
bridge_lock.virtualWrite(bridgedata, cardHolder[i], cardId[i], accessFlags[i]); //copy all cards from reader
yield();
}
}
BLYNK_WRITE(copybutton)
{
if (param.asInt()) {
bridge_master.virtualWrite(bridgewrite, 1, lock_token); //tell masterlock to copy current card to current lock
}
}
You can use the automation as switch only ( on/off ) based on certain trigger, you can’t send data like sensors data between devices using automation.
If you would like to send data between devices then you can check the topic suggested by pete, or you can try Node-red.
Okay I got past that I noticed that I had corrupted the server_name declaration.
Now I am getting an error telling me that I used an obsolete API
In function 'void api_bridge(String, int, String)':
httpapi:19:13: error: call to 'HTTPClient::begin' declared with attribute error: obsolete API, use ::begin(WiFiClient, url)
19 | http.begin(server_path.c_str());
| ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~
exit status 1
call to 'HTTPClient::begin' declared with attribute error: obsolete API, use ::begin(WiFiClient, url)
It looks like something has been updated in the API.
I added
HTTPClient http;
to the api_bridge
and changed the HTTP.begin to look like this
http.begin(client, server_name, 8080, path);
No errors but not getting the data to send
error code is -1
WiFiClient client;
void push_some_data()
{
api_bridge_write(String(configStore.cloudToken),9,"this is a test"); // Token for receiving device, virtual pin number, value to send
}
void api_bridge_write(String token, int virtual_pin, String data_to_send)
{
String server_name = "http://ny3.blynk.cloud/";
String path = "update?token=" + token + "&pin=v" + String(virtual_pin) + "&string=" + data_to_send;
// Your Domain name with URL path or IP address with path
// http.begin(server_name, path);
http.begin(client, server_name, 443, path);
// Send HTTP GET request
Serial.print("Sending ");
Serial.print(data_to_send);
Serial.print(" Token of device ");
Serial.print(token);
Serial.print(" to pin V");
Serial.println(virtual_pin);
long request_time = millis();
int httpResponseCode = http.GET();
if (httpResponseCode>0)
{
Serial.print("HTTP Response code: ");
Serial.println(httpResponseCode);
String payload = http.getString();
}
else
{
Serial.print("Error code: ");
Serial.print(httpResponseCode);
Serial.print(" <-----------------------------------");
}
Serial.print("Response time = ");
Serial.print(millis() - request_time);
Serial.println(" milliseconds");
Serial.println();
// Free resources
http.end();
}
This is the latest code. I don’t get any errors in the compile but I still don’t see the data.
My new question is can I use this to write to the device that is also sending the data? Not sure why I would want that but that is how my test is setup.
I tried ports 8080, 443 and 80. These all had the same result.
Okay, looks like you didn’t read my 14th January update on the change to the syntax for the http.begin command that resulted from using version 3.xx of the Arduino core…
When it refers to API in the error message, it means the syntax for the http.begin command, and as I explained in my 14th January update, this syntax has changed with the release of the 3.x.x ESP core, which is installed/updated via Boards Manager in the IDE.
I updated the code and gave it a try. Here is the serial output.
21:14:01.837 -> Sending this is a test To device ????????? pin V9
21:14:02.467 -> HTTP Response code: 301
21:14:02.467 -> Response time = 626 milliseconds
21:14:02.467 ->
21:14:26.786 -> Sending this is a test To device ????????? pin V9
21:14:26.985 -> HTTP Response code: 301
21:14:26.985 -> Response time = 204 milliseconds
21:14:26.985 ->
21:18:13.637 -> Sending this is a test To device ????????? pin V9
21:18:13.835 -> HTTP Response code: 301
21:18:13.835 -> Response time = 184 milliseconds
21:18:13.835 ->
So you would think that it worked but no data was actually received.
Current code looks like this
WiFiClient My_wifi_client;
void push_some_data()
{
api_bridge_write(String(configStore.cloudToken),9,"this is a test"); // Token for receiving device, virtual pin number, value to send
}
void api_bridge_write(String token, int virtual_pin, String data_to_send)
{
String server_name = "http://ny3.blynk.cloud/";
String path = server_name + "update?token=" + token + "&pin=v" + String(virtual_pin) + "&string=" + data_to_send;
// Your Domain name with URL path or IP address with path
// http.begin(server_name, path);
http.begin(My_wifi_client, path.c_str());
// Send HTTP GET request
Serial.print("Sending ");
Serial.print(data_to_send);
Serial.print(" To device ");
Serial.print(token);
Serial.print(" pin V");
Serial.println(virtual_pin);
long request_time = millis();
int httpResponseCode = http.GET();
if (httpResponseCode>0)
{
Serial.print("HTTP Response code: ");
Serial.println(httpResponseCode);
String payload = http.getString();
}
else
{
Serial.print("Error code: ");
Serial.print(httpResponseCode);
Serial.print(" <-----------------------------------");
}
Serial.print("Response time = ");
Serial.print(millis() - request_time);
Serial.println(" milliseconds");
Serial.println();
// Free resources
http.end();
}
Why are you adding the &string= towards the end of the AP:I call?
Also, you’ve changed my original code, so that instead of specifying the auth token of the device that the data is to be sent to via the bridge command, you are extracting the auth token of the sending device from the config store and using that. This means that you are getting the device to send the data to itself - which is really simulating a Blynk.virtualWrite() command.
Yes I know that I am sending it to itself and that that is not very useful. At this point I am trying to get it working. The fewer devices involved the better, Getting the token from the device store is also needed for my final implementation as it will need to send the token to the reader to begin the communication.
I thought that the string “&string=” was the indication that the following data would be a string. Is that incorrect?
+ "&string=" + data_to_send
Also if I cant send strings then there is no purpose for me in continuing this experiment.
That’s one way to look at it, but you don’t need a physical device as the receiver - just create a new device in the web console and send the data there. You can view the incoming data in the web dashboard.
I’m not sure about the logic of that, it seems like a bit of a “chicken and egg” situation to me. Are you sure you’ve thought that through?
That syntax is news to me, and I can’t see it in the documentation, which is why I asked where it came from.
It’s certainly possible to send strings via the API, but it’s not necessary to specify the variable type in the API call.
If the string contains spaces then they need to be replaced with %20