Ceci Semble Absurde.
Ceci Semble Absurde.

Reputation: 530

How do I make an HTTPS request with SIM900 (Arduino)

I try to make an HTTPS GET request and make an HTTPS POST request with the data recieved... I am using an arduino UNO with the library GSM_GPRS_GPS_Shield_GSMSHIELD and the GSM GPRS shield SIM900. Here is my current code below:

//include libs
#include "SIM900.h"
#include "inetGSM.h"
#include <SoftwareSerial.h>

InetGSM inet;

//data holder
int par1 = -1;
int par2 = -1;

void setup() {
  Serial.begin(9600);
  Serial.println("BEGIN");
  boolean started = false;
  SIM900power();
  
  //initialize the SIM900
  if (gsm.begin(2400)){
    Serial.println("READY");
    started=true;
  }else Serial.println("IDLE");
  
  //connect it to the network
  if(started){
    if (inet.attachGPRS("free", "", ""))
      Serial.println("ATTACHED");
    else Serial.println("ERROR");
    delay(1000);
    
    gsm.SimpleWriteln("AT+CIFSR");
    delay(3000);
    gsm.WhileSimpleRead();
    
    //GET request
    char * json = "";
    while(strlen(json) < 4){
      delay(2000);
      char msg[200] = "";
      Serial.println(inet.httpGET("my.site.com", 80, "/somethingToGet?param=1", msg, 200));
      
      //interpret Json
      char * msg_tmp = msg;
      json = strstr (msg_tmp, "[{");
    }
    if(json != ""){
      const byte posPar1 = (int)(strstr(json, "par1") - json) + 7;
      const byte posPar2 = (int)(strstr(json, "par2") - json) + 7;
      if(json[posPar1] != 'u')
      par1 = extractNum(json, posPar1);
      if(json[posPar2] != 'u')
      par2 = extractNum(json, posPar2);
    }
    
    if(json == "" || par1 == -1 || par2 == -1){
      SIM900power();
      Serial.println("A JSON ERROR OCCURED");
      while(1){}}
  }
};

void loop() {
  aPostRequest();
  while(1){}
};

void SIM900power()
{
  digitalWrite(9, HIGH);
  delay(1000);
  digitalWrite(9, LOW);
  delay(8000);
}

//extract the data from the Json string
int extractPar(char * json, byte pos){
  int num = 0;
  while (json[pos] != '"'){
    num = json[pos]-'0' + num * 10;
    pos++;
  }
  return num;
}

//POST request
void aPostRequest(){
  if( par1 != -1 && par2 != -1){
    boolean dataFound = true;
    while(dataFound){
      delay(2000);
      
      char params[100];
      snprintf(params, 100, "par1=%d&par2=%d", par1,par2);
      
      char msg[200] = "";
      
      dataFound = (inet.httpPOST("my.site.com ", 80, "/something", params , msg, 200) == 0);
    }
  }
}

I have two web sites, an HTTP one for my tests and the other one in HTTPS. As you can imagine, it's working on my HTTP one.

I don't know how to solve this problem but I think I need to do some tricky things with certificates in the library... can somebody help?

PS: if you want to test the code, you need to uncomment the HTTPPOST() function in the file inetGSM.h of the library. You can edit the functions httpGET() and HTTPPOST() in the file inetGSM.cpp.

UPDATE

There is the library code for the GET function below (httpPOST() works the same) :

int InetGSM::httpGET(const char* server, int port, const char* path, char* result, int resultlength)
{
        boolean connected=false;
        int n_of_at=0;
        int length_write;
        char end_c[2];
        end_c[0]=0x1a;
        end_c[1]='\0';

        /*
        Status = ATTACHED.
        if(gsm.getStatus()!=GSM::ATTACHED)
        return 0;
        */
        while(n_of_at<3) {
            if(!connectTCP(server, port)) {
#ifdef DEBUG_ON
                Serial.println("DB:NOT CONN");
#endif
                n_of_at++;
            } else {
                connected=true;
                n_of_at=3;
            }
        }

        if(!connected) return 0;

        gsm.SimpleWrite("GET ");
        gsm.SimpleWrite(path);
        gsm.SimpleWrite(" HTTP/1.0\r\nHost: ");
        gsm.SimpleWrite(server);
        gsm.SimpleWrite("\r\n");
        gsm.SimpleWrite("User-Agent: Arduino");
        gsm.SimpleWrite("\r\n\r\n");
        gsm.SimpleWrite(end_c);

        switch(gsm.WaitResp(10000, 10, "SEND OK")) {
        case RX_TMOUT_ERR:
            return 0;
            break;
        case RX_FINISHED_STR_NOT_RECV:
            return 0;
            break;
        }


        delay(50);
#ifdef DEBUG_ON
        Serial.println("DB:SENT");
#endif
        int res = gsm.read(result, resultlength);

        //gsm.disconnectTCP();

        //int res=1;
        return res;
}

I have already tried to change the HTTP/1.0 for HTTPS/1.0, but nothing appends.

UPDATE 2

I redirected my request through my HTTP server because I still have not found an answer, if someone could answer for those who could be blocked!

Upvotes: 3

Views: 3392

Answers (1)

t3rmo
t3rmo

Reputation: 59

I was trying to make a HTTPS request to a Lambda function that i coded in AWS. The function had to send a json body from a WEMOS D1 mini via a POST to AWS. TBH, I don't know, if this will solve your Issue on your Controller, but it might be worth trying :)

#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>

#ifndef STASSID
#define STASSID "<yourWiFiSSID>"
#define STAPSK  "<yourWifiPW>"
#endif

const char* ssid = STASSID;
const char* password = STAPSK;

const char* host = "<the host link here (has to look like **google.com** important, dont add the route here) >";
const int httpsPort = 443;
const String data = "<Json Object here e.g -> **{\"temperature\": 20.5,  \"humidity\": 60}**>";

// Use web browser to view and copy
// SHA1 fingerprint of the certificate
const char fingerprint[] PROGMEM = "5F F1 60 31 09 04 3E F2 90 D2 B0 8A 50 38 04 E8 37 9F BC 76";

void setup() {
  Serial.begin(115200);
  Serial.println();
  Serial.print("connecting to ");
  Serial.println(ssid);
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  // Use WiFiClientSecure class to create TLS connection
  WiFiClientSecure client;
  Serial.print("connecting to ");
  Serial.println(host);

  Serial.printf("Using fingerprint '%s'\n", fingerprint);
  client.setFingerprint(fingerprint);
  client.setInsecure();

  if (!client.connect(host, httpsPort)) {
    Serial.println("connection failed");
    return;
  }

  String url = "<your route here e.g **/photos/test**> ";
  Serial.print("requesting URL: ");
  Serial.println(url);

client.print(String("POST ") + url + " HTTP/1.1\r\n" +
           "Host: " + host + "\r\n" +
           "Connection: close\r\n"+   
           "Content-Length: " + data.length() + "\r\n" +
           "Content-Type: application/json;charset=UTF-8\r\n\r\n"+
            data +"\r\n");


  Serial.println("request sent");

  //READ INCOMING HTML
  uint8_t * _buffer = new uint8_t[128];
  String line = "";
  
  if (client.connected()) {
    int actualLength = client.read(_buffer, 128);
    // If it fails for whatever reason
    if(actualLength <= 0)
    {
        return;
    }
    // Concatenate the buffer content to the final response string
    // I used an arduino String for convenience
    // but you can use strcat or whatever you see fit
    //TRANSFORM EVERY CHAR FROM INCOMING HTML
    line += String((char*)_buffer).substring(0, actualLength);

    if (line == "\r") {
      Serial.println("headers received");
      
    }
  }
  
  Serial.print("Line: ");
  Serial.println(line);
  if (line.startsWith("{\"state\":\"success\"")) {
    Serial.println("esp8266/Arduino CI successfull!");
  } else {
    Serial.println("esp8266/Arduino CI has failed");
  }
  Serial.println("reply was:");
  Serial.println("==========");
  Serial.println(line);
  Serial.println("==========");
  Serial.println("closing connection");
}

void loop() {
}

I really hope this might have helped someone.

Upvotes: 0

Related Questions