I'm working on getting location from google geolocation api and sending this data to firebase. Theese two service using https ssl connections. And SIM800L very bad at ssl/tls connections. So I added my own server between SIM800L and internet. My server takes http request without ssl/tls from SIM800L and send them to they needs to go. A couple of lines PHP code doing this.
This method is working for me, I can take geolocation data and can send them to firebase. The problem is, sometimes request fails with using SIM800L. It's no problem with postman or reqbin, it never fails. But with sim800l mostly 3 out of 5 requests fail. what causes this I don't know.
This is my PHP code handles requests:
<?php
require 'firebaseLib.php';
// Tüm hataları göster
error_reporting(E_ALL);
ini_set('display_errors', 1);
// POST verilerini al
$postData = file_get_contents('php://input');
// POST verilerini bir değişkene atama ve JSON verisi varsa decode et
$receivedData = json_decode($postData, true);
// Google Geolocation API bilgileri
$geolocation_hostname = "www.googleapis.com";
$geolocation_resource = "/geolocation/v1/geolocate?key=****************************";
$geolocation_port = 443;
const DEFAULT_URL = 'https://*******************.firebasedatabase.app/';
const DEFAULT_TOKEN = '****************************';
$DEFAULT_PATH = '/location_app'; // Firebase'deki ana yolunuzu düzenleyin
// Google Geolocation API'ye cURL ile POST isteği gönderme
$ch = curl_init("https://{$geolocation_hostname}{$geolocation_resource}");
curl_setopt($ch, CURLOPT_PORT, $geolocation_port);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($receivedData));
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_VERBOSE, true); // verbose çıktı için bu satırı ekleyin
// Güvenlik katmanlarını devre dışı bırakma
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
// API'den gelen cevabı al
$response = curl_exec($ch);
// verbose çıktıyı sayfaya yazdır
echo '<pre>';
echo "Verbose Çıktı:\n" . curl_getinfo($ch, CURLINFO_HEADER_OUT) . $response;
echo '</pre>';
// İstek başarılı mı kontrol et
if (curl_errno($ch)) {
echo 'Hata:' . curl_error($ch);
} else {
// API'den gelen veriyi decode et ve latitude, longitude değişkenlerine atayarak sakla
$apiResponse = json_decode($response, true);
if (isset($apiResponse['location']['lat']) && isset($apiResponse['location']['lng'])) {
$latitude = $apiResponse['location']['lat'];
$longitude = $apiResponse['location']['lng'];
// Alınan latitude ve longitude değerlerini Firebase'e gönder
$firebase = new \Firebase\FirebaseLib(DEFAULT_URL, DEFAULT_TOKEN);
$_devicestatus = array(
'latitude' => $latitude,
'longitude' => $longitude
);
$firebase->update($DEFAULT_PATH, $_devicestatus);
echo "Firebase'e başarıyla gönderildi.<br>";
echo "Latitude: {$latitude}<br>";
echo "Longitude: {$longitude}<br>";
} else {
echo "API'den beklenen veri alınamadı.";
}
}
// cURL bağlantısını kapat
curl_close($ch);
?>
And this is my arduino code (sim800l):
#include <Arduino.h>
#if defined ARDUINO_ARCH_ESP8266
#include <ESP8266WiFi.h>
#elif defined ARDUINO_ARCH_ESP32
#include <WiFi.h>
#else
#error Wrong platform
#endif
#define TINY_GSM_MODEM_SIM800
// Set serial for debug console (to the Serial Monitor, default speed 115200)
#define SerialMon Serial
#define SerialAT Serial1
//#if !defined(TINY_GSM_RX_BUFFER)
#define TINY_GSM_RX_BUFFER 2048
//#endif
#define TINY_GSM_DEBUG SerialMon
#define MODEM_RST 5
#define MODEM_PWKEY 4
#define MODEM_POWER_ON 23
#define MODEM_TX 27
#define MODEM_RX 26
#define MAX_CONNECTION_TIMEOUT 5000
#define MAX_WIFI_SCAN 127
// Your GPRS credentials, if any
const char apn[] = "internet";// CHANGES: Add your apn from the service provider of your simcard
const char gprsUser[] = "";
const char gprsPass[] = "";
// Server details
// CHANGES: Add the name of your website. NOTE: DONT put any preceeding headers like "https://.."
const char server[] = "********.com";
/*
* The data that you want to send should be in this format
* /upload.php is the php file on the server and a=8 is data
* sent to it.
*
* To record a datapoint, append the value at the end of the
* character array resource
*
* if you want to send an array of data values, form the request as
* a[]=1&a[]=2....
*
*/
char resource[] = "/upload.php";
const int port = 80;
#include <ArduinoHttpClient.h>
#include <TinyGsmClient.h>
#ifdef DUMP_AT_COMMANDS
#include <StreamDebugger.h>
StreamDebugger debugger(SerialAT, SerialMon);
TinyGsm modem(debugger);
#else
TinyGsm modem(SerialAT);
#endif
TinyGsmClient gsm_modem(modem);
HttpClient client(gsm_modem, server, port);
unsigned long lastUpdateTime = 0;
const unsigned long updateInterval = 1L * 1000L;
void setup() {
// Set console baud rate
SerialMon.begin(115200);
delay(10);
pinMode(MODEM_PWKEY, OUTPUT);
pinMode(MODEM_RST, OUTPUT);
pinMode(MODEM_POWER_ON, OUTPUT);
digitalWrite(MODEM_PWKEY, LOW);
digitalWrite(MODEM_RST, HIGH);
digitalWrite(MODEM_POWER_ON, HIGH);
SerialMon.println("Wait...");
// Set GSM module baud rate
SerialAT.begin(115200, SERIAL_8N1, MODEM_RX, MODEM_TX);
SerialMon.println("Initializing modem...");
modem.init();
SerialMon.print(F("Connecting to "));
SerialMon.print(apn);
if (!modem.gprsConnect(apn, gprsUser, gprsPass)) {
SerialMon.println(" fail");
delay(10000);
return;
}
SerialMon.println(" success");
if (modem.isGprsConnected()) {
SerialMon.println("GPRS connected");
}
SerialMon.print("Connecting to ");
SerialMon.println(server);
if (!client.connect(server, port)) {
SerialMon.println(" fail");
delay(10000);
return;
}
SerialMon.println(" success");
}
void loop() {
// send HTTP request every one second
if(millis() - lastUpdateTime >= updateInterval) {
httpPostRequest();
lastUpdateTime = millis();
}
}
void httpPostRequest(){
// Makes the HTTP POST request
SerialMon.println("Performing HTTP POST request...");
if (client.connect(server,port)) {
// CHANGES: Add server name in place of XXXX
client.beginRequest();
String body = "{\"considerIP\":false,\"wifiAccessPoints\":" + getSurroundingWiFiJson() + "}";
String request = "POST " + String(resource) +" HTTP/1.1\r\n";
request += "Host: " + String(server) + "\r\n";
request += "Content-Type: application/json\r\n";
request += "User-Agent: ESP32\r\n";
request += "Content-Length:" + String(body.length()) + "\r\n";
request += "Connection: keep-alive\r\n\r\n";
request += body;
client.println(request);
client.endRequest();
Serial.println("*****************************");
Serial.println(request);
Serial.println("------------------------------");
uint32_t timeout = millis();
while (client.connected() && millis() - timeout < 10000L) {
// Print available data
while (client.available()) {
char c = client.read();
SerialMon.print(c);
timeout = millis();
}
}
}
client.stop();
Serial.println("Server Disconnected");
}
String getSurroundingWiFiJson()
{
String wifiArray = "[";
int8_t numWifi = WiFi.scanNetworks();
if (numWifi > MAX_WIFI_SCAN)
{
numWifi = MAX_WIFI_SCAN;
}
for (uint8_t i = 0; i < numWifi; i++)
{
wifiArray += "{\"macAddress\":\"" + WiFi.BSSIDstr(i) + "\",";
wifiArray += "\"signalStrength\":" + String(WiFi.RSSI(i)) + ",";
wifiArray += "\"channel\":" + String(WiFi.channel(i)) + "}";
if (i < (numWifi - 1))
{
wifiArray += ",\n";
}
}
WiFi.scanDelete();
wifiArray += "]";
return wifiArray;
}
Fail is something like this: it fails here and not takeing respons (also at the server side nothing happens when fail)
In console output is directly "server disconnect".
(As I said sometimes its working and giving proper response but not mostly)
I increased timeout but nothing changed. I guess server closing connections or refuse something sometimes. But I don't know why sometimes it's working and sometimes not.
Do you have any advice?