Converting from bridge to HTTP API data

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
  }
}

I think that you can now use Automations (although I’ve not tried it myself).
If you want to use the API then you should probably read this…

Pete.

1 Like

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.

1 Like

I made a copy of this code and tried to compile. It gives an error

httpapi:15:36: error: invalid operands of types 'const char [25]' and 'const char [14]' to binary 'operator+'
   15 |   String server_path = server_name + "update?token=" + token + "&pin=v" + String(virtual_pin) + "&string=" + data_to_send;
      |                                    ^ ~~~~~~~~~~~~~~~
      |                                      |
      |                                      const char [14]
exit status 1
invalid operands of types 'const char [25]' and 'const char [14]' to binary 'operator+'

I feel like I have used string concatenation like this before. What did I miss?

Difficult to say without seeing the code.

Pete.

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 is a copy of your code from above. here it is




void push_some_data()
{
  api_bridge(lock_token,3,"this is a test"); // Token for receiving device, virtual pin number, value to send

}


void api_bridge(String token, int virtual_pin, String data_to_send)
{
  HTTPClient http;
String server_name = "http://ny3.blynk.cloud/";

  String server_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_path.c_str());
  
  // Send HTTP GET request
  Serial.print("Sending ");
  Serial.print(data_to_send);
  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();
}

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 :frowning:

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.

This is the output from the serial port

19:56:57.172 -> Started at [8256] Using default config.
19:56:57.172 -> 
19:56:57.172 -> >[8256] 
19:56:57.172 ->     ___  __          __
19:56:57.172 ->    / _ )/ /_ _____  / /__
19:56:57.172 ->   / _  / / // / _ \/  '_/
19:56:57.172 ->  /____/_/\_, /_//_/_/\_\
19:56:57.172 ->         /___/ v1.0.1 on ESP8266
19:56:57.172 -> 
19:56:57.172 -> [8261] --------------------------
19:56:57.172 -> [8264] Product:  Smart Lock 2
19:56:57.172 -> [8267] Firmware: 0.1.0 (build Mar  1 2022 19:55:57)
19:56:57.172 -> [8272] Device:   ESP8266 @ 160MHz
19:56:57.172 -> [8275] MAC:      B4:E6:2D:04:CB:91
19:56:57.205 -> [8278] Flash:    4096K
19:56:57.205 -> [8280] ESP core: 3.0.2
19:56:57.205 -> [8282] ESP SDK:  2.2.2-dev(38a443e)
19:56:57.205 -> [8285] Boot Ver: 31
19:56:57.205 -> [8287] Boot Mode:1
19:56:57.205 -> [8289] FW info:  516592/1576960, MD5:8c1d65f81552684798e9c4da582a4381
19:56:57.338 -> [8441] Free mem: 25216
19:56:57.338 -> [8441] --------------------------
19:56:57.338 -> [8441] INIT => WAIT_CONFIG
19:56:57.438 -> looking for NFC
19:56:58.101 -> [9186] AP SSID: Blynk Smart Lock 2-31426
19:56:58.101 -> [9187] AP IP:   192.168.4.1
19:56:58.101 -> [9187] AP URL:  blynk.setup
19:57:33.005 -> [44098] WAIT_CONFIG => CONFIGURING
19:57:44.716 -> [55804] Sending board info...
19:57:47.072 -> [58164] Applying configuration...
19:57:47.072 -> [58164] WiFi SSID: LBurton Pass: //?????////????///////
19:57:47.072 -> [58164] Blynk cloud: ????????? @ blynk.cloud:443
19:57:47.072 -> [58168] CONFIGURING => SWITCH_TO_STA
19:57:47.172 -> [58276] Switching to STA...
19:57:48.266 -> [59378] SWITCH_TO_STA => CONNECTING_NET
19:57:48.399 -> [59484] Connecting to WiFi: ?????
19:57:54.138 -> [65250] Using Dynamic IP: ??????
19:57:54.171 -> [65250] CONNECTING_NET => CONNECTING_CLOUD
19:57:54.469 -> [65567] Current time: Wed Mar  2 03:57:54 2022
19:57:54.469 -> [65567] Connecting to blynk.cloud:443
19:57:55.565 -> [66652] Ready (ping: 11ms).
19:57:55.863 -> [66958] Time sync: OK
19:57:55.863 -> [66958] CONNECTING_CLOUD => RUNNING
19:57:55.863 -> [66975] Configuration stored to flash
19:58:13.116 -> Sending this is a test Token of device devicetokehiden to pin V9
19:58:13.150 -> Error code: -1 <-----------------------------------Response time = 3 milliseconds
19:58:13.150 -> 

The device token was correct.

Tried with expose to automatons set to on and off

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…

Pete.

interesting. I made this copy from your code. I wonder how I got the older API. No matter I will try again when I have time.

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.

Pete.

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();
}

Screenshot(11)

I’m a bit confused by what you’re trying to achieve here.

I can’t see anywhere in the Blynk IoT documentation where it says that

http://{server_address}/external/api/update?token={token}&{pin}&string={value}

is an acceptable format.

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.

Pete.

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

Pete.

Now that is a great idea! Thanks

Tried your Idea and changed to only sending a value but still not getting any data.

String server_name = "http://ny3.blynk.cloud/";
float value_to_send = 3.141592;

  String path = server_name + "update?token=" + token + "&pin=v" + String(virtual_pin) + "&value=" + float(value_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());

getting

0:47:05.816 -> Sending 3.14 To device trytoguess pin V9
20:47:05.916 -> HTTP Response code: 301
20:47:05.916 -> Response time = 88 milliseconds
20:47:05.916 -> 

Add a serial print statement before your http.begin command to print your path variable to the serial monitor.

Ensure that it looks the way you expected it to, then copy/paste it into the address bar of your browser and hit Enter.

What result do you see?

Pete.

https://ny3.blynk.cloud/update?token=goodtoken&pin=v9&value=3.14

What should it return. All I get is a blank window.