JAndrassy / WiFiEspAT

Arduino networking library. Standard Arduino WiFi networking API over ESP8266 or ESP32 AT commands.
GNU Lesser General Public License v2.1
290 stars 44 forks source link

How to make REST API HTTPS POST Request in WiFiespAT library #50

Closed supekshala closed 3 years ago

supekshala commented 3 years ago

I need to send data to the power bi dashboard using arduinomega+esp8266 inbuilt board. I successfully install AT firmware and test example codes. but still, I could not manage to make the post request to power bi streaming data set API. Previously I used a nodemcu board to this task and it worked flawlessly. this is the code I used in nodemcu.

#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClientSecureBearSSL.h>

#define SERVER_IP "https://api.powerbi.com/beta/d1323671-cdbe-4417-b4d4-bdb24b51316b/datasets/ce600abb-0afd-47e1-bdaf-6491f91945bd/rows?noSignUpCheck=1&key=stAvYHSNB6lDf%2BEEXS%2BU%2BsA2Kbyd3%2Bx9NKnWyZj5Uz5YPp%2Bbu7zdPUxboto4aXhls8rObnfYQXFPoIeo9ALrAA%3D%3D"

#define WI_SSID "SLT_FIBRE"
#define WI_PW  "dehff"
WiFiClient client;
void sendData(int temp){
  std::unique_ptr<BearSSL::WiFiClientSecure>client(new BearSSL::WiFiClientSecure);
  client->setInsecure();
  HTTPClient https;

  Serial.print("[HTTP] begin...\n");
  // configure traged server and url
  https.begin(client, SERVER_IP); //HTTPS
  https.addHeader("Content-Type", "application/json");

  Serial.print("[HTTP] POST...\n");
  // start connection and send HTTP header and body
  int httpCode = https.POST("[{\"Value\": " + String(temp) + "}]");

  // httpCode will be negative on error
  if (httpCode > 0) {
    // HTTP header has been send and Server response header has been handled
    Serial.printf("[HTTP] POST... code: %d\n", httpCode);

    // file found at server
    if (httpCode == HTTP_CODE_OK) {
      const String& payload = https.getString();
      Serial.println("received payload:\n<<");
      Serial.println(payload);
      Serial.println(">>");
    }
  } else {
    Serial.printf("[HTTP] POST... failed, error: %s\n", https.errorToString(httpCode).c_str());
  }

  https.end();

}

void setup() {
  Serial.begin(115200);

  Serial.println();
  Serial.println();
  Serial.println();

  WiFi.begin(WI_SSID, WI_PW);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected! IP address: ");
  Serial.println(WiFi.localIP());

}

void loop() {
  // wait for WiFi connection
  int temp = analogRead(A0);
  Serial.println(temp);
  if ((WiFi.status() == WL_CONNECTED)) {
    sendData(temp);
  }

}

This the code I tried in Arduino mega +ESP8266 board but it didn't work.

/*
  Web client

 This sketch connects to https
 using the WiFi module.

 created 13 July 2010
 by dlf (Metodo2 srl)
 modified 31 May 2012
 by Tom Igoe
 modified in Jul 2019 for WiFiEspAT library
 by Juraj Andrassy https://github.com/jandrassy
 */

#include <WiFiEspAT.h>

const char* server = "api.powerbi.com/beta/d1323671-cdbe-4417-b4d4-bdb24b51316b/datasets/60dfb0df-9bf8-4c05-8505-69a32ec90a95/rows?tenant=&UPN=&key=H1wfQ3c5rxxmgrDqcZkARXK%2FCypXYyN77IDXoYA13z5%2FnXN9JRAXGehl15Tb0is43ikRShQauxuQH45p%2FJV8dg%3D%3D";
char ssid[] = "SLT_FIBRE";            
char pass[] = "kavsds";  
WiFiSSLClient client;

void setup() {
  Serial.begin(115200);
  while (!Serial);

  Serial1.begin(115200);
  WiFi.init(Serial3);
  if (WiFi.status() == WL_NO_MODULE) {
    Serial.println();
    Serial.println("Communication with WiFi module failed!");
    // don't continue
    while (true);
  }

  WiFi.begin(ssid, pass);

  // waiting for connection to Wifi network set with the SetupWiFiConnection sketch
  Serial.println("Waiting for connection to WiFi");
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.print('.');
  }
  Serial.println();
  Serial.println("Connected to WiFi network.");

  Serial.println("Starting connection to server...");
  if (client.connect(server, 443)) { // port 443 is the default https port
    Serial.println("connected to server");
  int value=10;
  // send the HTTP POST request  
  client.println("POST  HTTP/1.1");
  client.println("Host: server");
  client.println("Content-Type: application/json");
  String content = "{\"temperature\":\""+String(value)+"\"}";
  client.println("Content-Length: 16"); //insert, well, your content length
  client.println(content);

}
else {
  // if you couldn't make a connection
  Serial.println("Connection failed");
}

}

void loop() {

  // if there are incoming bytes available
  // from the server, read them and print them
  while (client.available()) {
    char c = client.read();
    Serial.write(c);
  }

  // if the server's disconnected, stop the client
  if (!client.connected()) {
    Serial.println();
    Serial.println("disconnecting from server.");
    client.stop();

    // do nothing forevermore
    while (true);
  }
}

This is the dataset I tried to connect. API = https://api.powerbi.com/beta/d1323671-cdbe-4417-b4d4-bdb24b51316b/datasets/60dfb0df-9bf8-4c05-8505-69a32ec90a95/rows?tenant=&UPN=&key=H1wfQ3c5rxxmgrDqcZkARXK%2FCypXYyN77IDXoYA13z5%2FnXN9JRAXGehl15Tb0is43ikRShQauxuQH45p%2FJV8dg%3D%3D tss [ { "temperature" :98.6 } ]

JAndrassy commented 3 years ago

try it with ArduinoHttpClient library over WiFiEspAT as you use ESP8266HTTPClient library over ESP8266WiFi.

your code building the HTTP request has many errors. there is no path in request line, Host and Content-Length values are wrong and the empty line separating the headers and the content is missing.

supekshala commented 3 years ago

Could you please correct this post request code. That would be a huge help. Iam really frustrated because of this. what should put to server and URI. Only I got from power bi dataset is this API URL=> https://api.powerbi.com/beta/d1323671-cdbe-4417-b4d4-bdb24b51316b/datasets/60dfb0df-9bf8-4c05-8505-69a32ec90a95/rows?tenant=&UPN=&key=H1wfQ3c5rxxmgrDqcZkARXK%2FCypXYyN77IDXoYA13z5%2FnXN9JRAXGehl15Tb0is43ikRShQauxuQH45p%2FJV8dg%3D%3D

Should I separate this URL like this? Server="api.powerbi.com" URI="beta/d1323671-cdbe-4417-b4d4-bdb24b51316b/datasets/60dfb0df-9bf8-4c05-8505-69a32ec90a95/rows?tenant=&UPN=&key=H1wfQ3c5rxxmgrDqcZkARXK%2FCypXYyN77IDXoYA13z5%2FnXN9JRAXGehl15Tb0is43ikRShQauxuQH45p%2FJV8dg%3D%3D"

if (client.connect(server, 443)) {
    Serial.println(F("con..."));
    // send the HTTP GET request:
 String content = "{\"temperature\":\""+String(value)+"\"}";
    client.println("POST " + URI + " HTTP/1.1");
    client.println("Host: " + String(server));
    client.println("Content-Type: application/json");
    client.print("Content-Length: ");
    client.println(content.length());
    client.println();
    client.println(content);
    // note the time that the connection was made:

  } else {
    // if you couldn't make a connection:
    Serial.println(F("con failed"));
  }
JAndrassy commented 3 years ago

use ArduinoHttpClient

supekshala commented 3 years ago

I tried several times to connect and a post request to power bi but I don't how to do it using AT commands. I attempt to do it below code. but I doesnt work.

/*
  Simple POST client for ArduinoHttpClient library
  Connects to server once every five seconds, sends a POST request
  and a request body

  created 14 Feb 2016
  modified 22 Jan 2019
  by Tom Igoe

  this example is in the public domain
 */
#include <WiFiEspAT.h>
#include <ArduinoHttpClient.h>

/////// Wifi Settings ///////
char ssid[] = "SLT_FIBRE";
char pass[] = "kavindusupekshala";

char serverAddress[] = "https://api.powerbi.com/beta/d1323671-cdbe-4417-b4d4-bdb24b51316b/datasets/60dfb0df-9bf8-4c05-8505-69a32ec90a95/rows?key=H1wfQ3c5rxxmgrDqcZkARXK%2FCypXYyN77IDXoYA13z5%2FnXN9JRAXGehl15Tb0is43ikRShQauxuQH45p%2FJV8dg%3D%3D";  // server address
int port = 443;

WiFiClient wifi;
HttpClient client = HttpClient(wifi, serverAddress, port);
int status = WL_IDLE_STATUS;

void setup() {
  Serial.begin(115200);
  while ( status != WL_CONNECTED) {
    Serial.print("Attempting to connect to Network named: ");
    Serial.println(ssid);                   // print the network name (SSID);

    // Connect to WPA/WPA2 network:
  Serial3.begin(115200);
  WiFi.init(Serial3);

  WiFi.begin(ssid, pass);

    status = WiFi.begin(ssid, pass);
  }

  // print the SSID of the network you're attached to:
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // print your WiFi shield's IP address:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);
}

void loop() {
  int value=10;
  String postData ="[{\"temperature\":\" "+String(value)+"\"}]";
  Serial.println("making POST request");
  String contentType = "application/json";
  client.post("/", contentType, postData);

  // read the status code and body of the response
  int statusCode = client.responseStatusCode();
  String response = client.responseBody();

  Serial.print("Status code: ");
  Serial.println(statusCode);
  Serial.print("Response: ");
  Serial.println(response);

  Serial.println("Wait five seconds");
  delay(5000);
}
JAndrassy commented 3 years ago

With AT 1.7 WiFiEspAT doesn't support secure connection (WiFiSSLClient for https). Even with AT 2.1 TLS 1.2 is not supported by AT firmware and it is very possible that powerbi uses TLS 1.2 for https. servername is only "api.powerbi.com" post("/" should be post("/beta/d1323671-cdbe....

supekshala commented 3 years ago

Thanks. Do you know a firmware that can support TLS 1.2?if so I can install that firmware to the board

JAndrassy commented 3 years ago

https://github.com/jandrassy/WiFiEspAT#capabilities-comparison