Sending Sensor Data to Firebase using ESP32+Sim800L - firebase

I have a TTGO T-CALL ESP32+Sim800L board and I want to send accelerometer data to Firebase.
I am using the TinyGSM library which supports SSL/https connections for Sim800L.
I am currently sending dummy data to see if it works but it is giving me a failed flag.
Why is it not sending data to Firebase?
#define FIREBASE_HOST "https://XXXXXXXXXXXXXXXXXfirebaseio.com/"
#define FIREBASE_AUTH "XXXXXXXXXXXXXXXXXXXXhevKwQ3LALblGclqCk"
FirebaseData firebaseData;
void setup()
{
// Set console baud rate
Serial.begin(115200);
// Set-up modem reset, enable, power pins
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);
// Set GSM module baud rate and UART pins
SerialAT.begin(115200, SERIAL_8N1, MODEM_RX, MODEM_TX);
delay(3000);
SerialMon.println("Initializing modem...");
modem.init();
SerialMon.print("Connecting to APN: ");
SerialMon.print(apn);
if (!modem.gprsConnect(apn, gprsUser, gprsPass)) {
SerialMon.println(" fail");
}else {
SerialMon.println(" OK");
Firebase.begin(FIREBASE_HOST,FIREBASE_AUTH);
SerialMon.println(" Connection to Firebase Successful");
}
}
void loop()
{
String data = "5";
bool res = Firebase.pushString(firebaseData,"/ax", data);
Serial.println("Data sent");
Serial.println(res);
Serial.println(firebaseData.errorReason());
delay(1000);
}
This is the output:

I didn't find a lot of resources online, however, I did manage to do this and I made a GitHub repo for anyone who needs help with the same.
Basically as Firebase accepts only Https requests, it is not possible to formulate that on most microcontrollers and GSM modules.
To circumvent this problem, I created a php server to which I can send an HTTP POST request and the script can get the data from it and push it to Firebase with a php firebase library.

Related

Arduino UNO & Modem Sim800L Can't write setup commands to send data to server

I am using arduino UNO board, with modem sim800l. I want use it to send data to server, but the problem is that I can't write the setup commands.
What am I doing wrong? Are not this the right commands to use for sim800l?
I've tried with different commands and the output is the same.
#include <SoftwareSerial.h>
//Create software serial object to communicate with SIM800L
SoftwareSerial mySerial(3, 2); //SIM800L Tx & Rx is connected to Arduino #3 & #2
void setup()
{
//Begin serial communication with Arduino and Arduino IDE (Serial Monitor)
Serial.begin(9600);
//Begin serial communication with Arduino and SIM800L
mySerial.begin(9600);
Serial.println("Initializing...");
delay(100);
delay(1000);
mySerial.println("AT+CMEE=2"); // Error mode
delay(100);
updateSerial();
mySerial.println("AT"); //Once the handshake test is successful, i t will back to OK
delay(100);
updateSerial();
mySerial.println("AT+CFUN=1"); //Level "full functionality"
delay(100);
updateSerial();
mySerial.println("AT+CGATT?"); //attach or detach from GPRS service
delay(100);
updateSerial();
mySerial.println("AT+CSTT=\"net\",\"\",\"\""); //AT+CSTT AT command sets up the apn, user name and password for the PDP context.
delay(2000);
updateSerial();
mySerial.println("AT+CSTT?"); //AT+CSTT show apn
delay(2000);
updateSerial();
mySerial.println("AT+CIICR"); // Brings up wireless connection
delay(2000);
updateSerial();
mySerial.println("AT+CIFSR"); // Get local IP address if connected
delay(2000);
updateSerial();
}
Here is the output from the console of Arduino IDE:
Initializing...
AT+CHEE=2
OK
AT
OK
AT+CFUN=1
OK
AT+CGAIT?
+CGATT: 1
OK
AT+CSTT="net","",""
+CME ERROR: operation not allowed
AT+CSTT?
+CSTT: "CMNET","",""
OK
AT+CIICR
+CME ERROR: operation not allowed
AT+CIFSR
+CME ERROR: operation not allowed
You have my sympathies, it took me weeks to get my Arduino talking to the net. I think your problem is happening on the line containing "CSTT", which I don't think SIM800L recognises.
Try the below setup instead, with "SAPBR" in its place:
SoftwareSerial gprsSerial(7, 8); // working here with Arduino ports 7 and 8
void setup() {
gprsSerial.begin(19200);
Serial.begin(19200);
Serial.println("connect to GPRS");
gprsSerial.println("AT");
toSerial();
gprsSerial.println("AT+CREG?");
toSerial();
gprsSerial.println("AT+CGATT?");
toSerial();
gprsSerial.println("AT+CSQ ");
toSerial();
gprsSerial.println("AT+SAPBR=3,1,\"Contype\",\"GPRS\"");
delay(2000);
toSerial();
gprsSerial.println("AT+SAPBR=3,1,\"APN\",\"" + String(APN) + "\"");
delay(300);
gprsSerial.println("AT+SAPBR=3,1,\"USER\",\"" + String(USER) + "\"");
delay(300);
gprsSerial.println("AT+SAPBR=3,1,\"PWD\",\"" + String(PWD) + "\"");
delay(1000);
toSerial();
gprsSerial.println("AT+SAPBR=1,1");
delay(2000);
toSerial();
gprsSerial.println("AT+SAPBR=2,1");
delay(2000);
toSerial();
}
Your run loop:
void loop(){
// Do your stuff
}
And your toSerial function:
void toSerial()
{
delay(200);
if(gprsSerial.available()>0){
textMessage = gprsSerial.readString();
delay(100);
Serial.print(textMessage);
}
}
Your call server function should be like this:
void callServer() {
Serial.println("Calling server");
gprsSerial.println("AT+CCLK?");
toSerial();
gprsSerial.println("AT+HTTPINIT");
toSerial();
gprsSerial.println("AT+HTTPPARA=\"CID\",1");
toSerial();
gprsSerial.println("AT+HTTPPARA=\"URL\",\"http:[YOURURL]") // NOTE: NOT HTTPS!
delay(1000);
toSerial();
gprsSerial.println("AT+HTTPACTION=0");
delay(3000);
toSerial();
gprsSerial.println("AT+HTTPREAD");
delay(3000);
toSerial();
}
The sequence of send commands to set up TCP/IP connection:
//Check the registration status
AT+CREG?
//Check attach status
AT+CGACT?
//Attach to the network
AT+CGATT=1
//Wait for Attach
WAIT=7
//Start task ans set the APN. Check your carrier APN
AT+CSTT="bluevia.movistar.es" // Here you havve net which I guess is not a NetworkAPN you have to use the APN from your provider (= sim card)
//Bring up the wireless connection
AT+CIICR
//Wait for bringup
WAIT=6
//Get the local IP address
AT+CIFSR
//Start a TCP connection to remote address. Port 80 is TCP.
AT+CIPSTART="TCP","74.124.194.252","80"
//Set prompt of '>' when module sends data
AT+CIPSPRT=1
//Send the TCP data
AT+CIPSEND
If you want to test quickly a stable setup use this 7 days free to use tool for SIM800, SIM900 and then copy the succesfull process into code.

POST request to firebase functions with sim900 arduino

Im trying to send POST request with sim900 connected to arduino uno.
I send it to firebase functions but I dont get it in the function.
I will be happy to get solution for my problem,
or alternative way that i can store data from sensors to firebase with sim900 or any other celular network solution).
arduino code:
#include<SoftwareSerial.h>
SoftwareSerial client(7,8);
String reading="{ \"testID\" : 1, }";
void setup()
{
Serial.begin(9600);
client.begin(9600);
delay(500);
if(client.available())
{
Serial.println("Connected");
}
else
{
Serial.println("NotConnected");
}
//initSIM();
connectGPRS();
connectHTTP();
}
void loop()
{
}
void connectGPRS()
{
client.println("AT+SAPBR=3,1,\"Contype\",\"GPRS\"");
delay(1000);
ShowSerialData();
client.println("AT+SAPBR=3,1,\"APN\",\"www\"");//APN
delay(1000);
ShowSerialData();
client.println("AT+SAPBR=1,1");
delay(1000);
ShowSerialData();
client.println("AT+SAPBR=2,1");
delay(1000);
ShowSerialData();
}
void connectHTTP()
{
client.println("AT+HTTPINIT");
delay(1000);
ShowSerialData();
client.println("AT+HTTPPARA=\"CID\",1");
delay(1000);
ShowSerialData();
client.println("AT+HTTPPARA=\"URL\",\"www.us-central1-**************.cloudfunctions.net/helloWorld\"");//Public server IP address
delay(1000);
ShowSerialData();
client.println("AT+HTTPPARA=\"CONTENT\",\"application/json\"");
delay(1000);
ShowSerialData();
client.println("AT+HTTPDATA=" + String(reading.length()) + ",100000");
delay(1000);
ShowSerialData();
client.println(reading);
delay(1000);
ShowSerialData;
client.println("AT+HTTPACTION=1");
delay(1000);
ShowSerialData();
client.println("AT+HTTPREAD");
delay(1000);
ShowSerialData();
client.println("AT+HTTPTERM");
delay(1000);
ShowSerialData;
}
void ShowSerialData()
{
while(client.available()!=0)
{
Serial.write(client.read());
delay(100);
}
}
firebase function:
const functions = require('firebase-functions');
// Create and Deploy Your First Cloud Functions
// https://firebase.google.com/docs/functions/write-firebase-functions
exports.helloWorld = functions.https.onRequest((request, response) => {
response.send("Hello from Firebase!");
// Check for POST request
if (request.method !== "POST") {
console.log('Please send a POST request');
}
if (request.method !== "GET") {
console.log('Please send a GET request');
}
let data = request.body;
console.log(`Hello from Firebase! ${JSON.stringify(data)}`);
// console.log('testing: ' + data[0]);
// console.log('testing: ' + data.longitude);
// console.log('testing: ' + data['longitude']);
});
Thank you all!
This is by no means a definitive solution but should work on most SIM modules but make sure you have up to date firmware for SSL connection.
This is only a snip of code from my project, you can only POST, GET and DELETE using these SIM modules built in HTTP functions, there's no PUT and PATCH so a bit limited for Firebase.
This is very basic code so you may have to tweak some timing here and there. It will work a lot faster if you put code to check the responses, most delays are not necessary.
Try this command first:
AT+HTTPSSL=1
If you get an error you MUST update the module's firmware before using Firebase.
Firebase will only work with HTTPS connection.
// Firebase HTTPS connection, POST example
#define MODEM_TX 16
#define MODEM_RX 17
// Set serial for debug console (to Serial Monitor, default speed 115200)
#define SerialMon Serial
// Set serial for AT commands (to SIM808 module)
#define client Serial1
void setup()
{
SerialMon.begin(115200);
// Set GSM module baud rate and UART pins
client.begin(115200, SERIAL_8N1, MODEM_RX, MODEM_TX);
delay(1000);
float tempIn = 21.5;
float humidity = 54.6;
float pressure = 1010.64;
char fbtimebuff[32] = "1:30 20/2/21";
char dataTEST[256];
char FirebaseUrl[300]; // dimension to suit required character space
const char FirebaseID[100] = "https://my-project-details.firebaseio.com"; // project ID
const char FirebaseAuth[100] = "YPXm66X-My-Big-Secrete-J9xsZsL"; // secret
strcpy(FirebaseUrl, FirebaseID); // Firebase account ID
strcat(FirebaseUrl, "/GPRS-Test/.json?auth="); // Parenet/child path + .json and auth
strcat(FirebaseUrl, FirebaseAuth);
sprintf(dataTEST, "{\"TempIn\" : \"%3.2f\",\"Humidity\" : \"%2.2f\",\"Pressure\" : \"%4.2f\",\"Time\" : \"%s\"}", tempIn, humidity, pressure, fbtimebuff);
// connect to GPRS network
SerialMon.printf("\n\nConnect to GPRS\n");
client.println("AT+CIPSHUT");
ShowSerialData();
delay(500);
client.println("AT+CGATT=1");
ShowSerialData();
delay(1000);
client.println("AT+SAPBR=3,1,\"Contype\",\"GPRS\"");
ShowSerialData();
delay(1000);
client.println("AT+SAPBR=1,1");
ShowSerialData();
delay(1000);
client.println("AT+SAPBR=2,1");
ShowSerialData();
delay(1000);
// post to Firebase
SerialMon.printf("post function to Firebase\n");
client.println("AT+HTTPINIT");
ShowSerialData();
delay(1000);
client.println("AT+HTTPSSL=1"); // set SSL for HTTPS
ShowSerialData();
delay(1000);
client.println("AT+HTTPPARA=\"CID\",1");
ShowSerialData();
delay(1000);
client.println("AT+HTTPPARA=\"URL\"," + String(FirebaseUrl));
ShowSerialData();
delay(1000); client.println("AT+HTTPPARA=\"CONTENT\",\"application/json\"");
ShowSerialData();
delay(1000);
int stlen = strlen(dataTEST);
SerialMon.printf("length: %d\n", stlen);
client.println("AT+HTTPDATA=" + String(stlen) + ",100000");
ShowSerialData();
delay(1000);
SerialMon.printf("set data\n");
client.println(dataTEST);
ShowSerialData();
delay(1000);
SerialMon.printf("POST data to Firebase\n");
client.println("AT+HTTPACTION=1");
ShowSerialData();
delay(6000);
client.println("AT+HTTPREAD");
ShowSerialData();
delay(1000);
SerialMon.printf("Dissconect\n");
client.println("AT+HTTPTERM");
ShowSerialData();
delay(1000);
// now disconnect from GPRS network
client.println("AT+CIPSHUT");
ShowSerialData();
delay(1000);
client.println("AT+SAPBR=0,1");
ShowSerialData();
delay(1000);
client.println("AT+CGATT=0");
ShowSerialData();
delay(1000);
}
void loop()
{
}

How to control an led from Thingspeak server using SIM900A and Arduino?

I am trying to control a LED from Thingspeak server by using the GSM module.
The data received is successfully being printed on serial monitor(which is '1' as last updated) but when I am trying to assign that data to a variable so as to control the inbuilt LED of Arduino, nothing happens.
#include <SoftwareSerial.h>
SoftwareSerial SIM900A(10, 11);
void setup()
{
pinMode(LED_BUILTIN, OUTPUT);
SIM900A.begin(9600);
Serial.begin(9600);
while (!Serial)
;
Serial.println("Arduino is ready");
SIM900A.begin(9600);
Serial.println("SIM900A started at 9600");
delay(1000);
Serial.println("Setup Complete");
}
void loop()
{
SIM900A.println("AT");
delay(1000);
ShowSerialData();
SIM900A.println("AT+CIPSHUT");
delay(2000);
ShowSerialData();
SIM900A.println("AT+CIPMUX=0");
delay(2000);
ShowSerialData();
SIM900A.println("AT+CGATT=1");
delay(5000);
SIM900A.println("AT+CSTT=\"INTERNET\",\"\",\"\"");
delay(4000);
SIM900A.println("AT+CIICR");
delay(3000);
ShowSerialData();
SIM900A.println("AT+CIFSR");
delay(5000);
ShowSerialData();
SIM900A.println("AT+CIPSTART=\"TCP\",\"184.106.153.149\",\"80\"");
delay(4000);
ShowSerialData();
SIM900A.println("AT+CIPSEND");
delay(4000);
SIM900A.print("GET /channels/798173/fields/1/last");
SIM900A.print("\r\n\x1A");
ShowSerialData();
char led = SIM900A.read();
Serial.print(led);
if (led == '1')
{
digitalWrite(LED_BUILTIN, HIGH);
}
else if (led == '0')
{
digitalWrite(LED_BUILTIN, LOW);
}
delay(8000);
}
void ShowSerialData()
{
while (SIM900A.available() != 0)
Serial.print(char(SIM900A.read()));
}
Last portion of the output from the serial monitor:
CONNECT OK
AT+CIPSEND
> ⸮GET /channels/798173/fields/1/last
SEND OK
1
As pointed out by #Saurabh P Bhandari, you cannot read the same data from the serial twice, thus you'd need to read the data in a variable in the first place if you wish to use it.
String getSerialData(){
String buffer="";
while (SIM900A.available() ){
char c = SIM900A.read();
buffer+=c;
}
return buffer;
}
Then you can use String led = getSerialData() to populate led with the buffer.
Here, you need to beware that the function getSerialData would return anything present on the buffer and would look something like:
GET /channels/798173/fields/1/last
SEND
HTTP RESPONSE
It appears that you're only interested in HTTP RESPONSE, thus you can update your conditionals to be
if(led.endsWith("1"))
...
else if(led.endsWith("0"))
From what I have understood so far, in this snippet
SIM900A.print("GET /channels/798173/fields/1/last");
SIM900A.print("\r\n\x1A");
ShowSerialData();
ShowSerialData() is printing the output which is '1'. Then immediately your are reading data into the variable led. Since, the actual data received is being printed already from ShowSerialData(), the next time you call SIM900A.read() will return either nothing or next set of data being sent by your module.
You are likely getting rate limited because you are hitting ThingSpeak servers too frequently. You can only update a channel once every 15s with a free account. Obviously, it makes no sense to ask for a value faster than it can be updated, i.e., once every 15s with a free account.
Consider putting some required delays in your code to ensure your device is not blacklisted for abuse of terms.

Unable to SMS using AT commands for arduino uno

#include <SoftwareSerial.h>
SoftwareSerial mySerial(0, 1);
void setup()
{
mySerial.begin(9600); // Setting the baud rate of GSM Module
Serial.begin(9600); // Setting the baud rate of Serial Monitor (Arduino)
delay(100);
}
void loop()
{
if (Serial.available()>0)
SendMessage();
if (mySerial.available()>0)
Serial.write(mySerial.read());
}
void SendMessage()
{
mySerial.println("AT+CMGF=1"); //Sets the GSM Module in Text Mode
delay(1000); // Delay of 1000 milli seconds or 1 second
mySerial.println("AT+CMGS=\"+1876xxxxxxx\"\r"); // Replace x with mobile number
delay(1000);
mySerial.println("I am SMS from GSM Module");// The SMS text you want to send
delay(100);
mySerial.println((char)26);// ASCII code of CTRL+Z
delay(1000);
}
I am trying to send a sms using SIM 800 RPI GSM ADD-on v2.3 module through the arduino platform however everything I try fails. Please assist and explain where i am going wrong. Thank you. My code is above. Thanks
You are missing a carriage return in "AT+CMGF=1".
Change "AT+CMGF=1" to "AT+CMGF=1\r"
Although having delays between command works and suffices the purpose but is not recommended.
It is preferable to catch and analyze the messages returned by the SIM800 especially in case of error has occurred.

Arduino GSM SIM900 does not receiving messages

Following URL will be appear my GSM module and it is included data sheet of the SIM900 module.
http://www.pennybuying.com/gsm-gprs-module-sim900-development-board-lbs-mms-support-arduino-uno-ttl-rs232.html
I have connected only RX,TX,GND and PWR pin between GSM module and Arduino mega board.
Sending a SMS is work properly but receiving SMS is doesn't work.
This is the Arduino Code of sending sms - (Reference - http://tronixstuff.com/2014/01/08/tutorial-arduino-and-sim900-gsm-modules/)
#include <SoftwareSerial.h>
SoftwareSerial SIM900(15,14);
char incoming_char=0;
void setup()
{
Serial.begin(19200); // for serial monitor
SIM900.begin(19200); // for GSM shield
SIM900power(); // turn on shield
delay(20000); // give time to log on to network.
SIM900.print("AT+CMGF=1\r"); // set SMS mode to text
delay(100);
SIM900.print("AT+CNMI=2,2,0,0,0\r");
// blurt out contents of new SMS upon receipt to the GSM shield's serial out
delay(100);
}
void SIM900power()
// software equivalent of pressing the GSM shield "power" button
{
digitalWrite(9, HIGH);
delay(1000);
digitalWrite(9, LOW);
delay(7000);
}
void loop()
{
// Now we simply display any text that the GSM shield sends out on the serial monitor
Serial.println("loop");
if(SIM900.available() > 0)
{
Serial.print("waiting");
incoming_char=SIM900.read(); //Get the character from the cellular serial port.
Serial.print(incoming_char); //Print the incoming character to the terminal.
while(1){};
}
}
Try to add SIM900.print("AT+CMGD=1,4\r"); in your setup(). I faced similar problems and the reason was that sim-card memory for messages is full.
You wont get any messages or notification if there is no space in sim memory!
So your setuo loop would look like this
void setup()
{
Serial.begin(19200); // for serial monitor
SIM900.begin(19200); // for GSM shield
SIM900power(); // turn on shield
delay(20000); // give time to log on to network.
SIM900.print("AT+CMGF=1\r"); // set SMS mode to text
delay(100);
SIM900.print("AT+CMGD=1,4\r"); // Deletes all SMS saved in SIM memory
delay(100);
SIM900.print("AT+CNMI=2,2,0,0,0\r");
// blurt out contents of new SMS upon receipt to the GSM shield's serial out
delay(100);
}

Resources