Introduction: BharatPi 4G HTTP POST to ThingSpeak - a Practical Guide
ThingSpeak is an Internet of Things (IoT) platform that allows you to collect, analyze, and visualize data from sensors or devices. It provides an easy-to-use interface for users to send data from their IoT devices to ThingSpeak servers using various communication protocols such as HTTP, MQTT, and ThingSpeak API. Once the data is in ThingSpeak, users can perform real-time analytics, create visualizations such as charts and maps, and trigger actions based on predefined conditions. ThingSpeak is often used in various IoT applications including environmental monitoring, home automation, and industrial automation.
Supplies
Step 1: How to Create a Account in Thingspeak
Visit ThingSpeak: Go to the ThingSpeak website at [ThingSpeak thingspeak.com].
Click on Sign Up: In the top right corner of the homepage, you'll see a button labeled "Sign Up." Click on that button.
Fill out the Registration Form: On the registration page, you'll be asked to provide the following information:
- Username: Choose a unique username that you'll use to log in to your ThingSpeak account.
- Email Address: Enter a valid email address that you want to associate with your ThingSpeak account.
- Password: Create a strong password that includes a combination of letters, numbers, and special characters. Make sure it's something you can remember easily but difficult for others to guess.
- Confirm Password: Retype your chosen password to ensure there are no typos.
Create Account: Once you've filled out the form, click on the button that says "Create Account."
Verify Your Email (Optional): ThingSpeak might send a verification email to the address you provided. Check your inbox and follow any instructions in the email to verify your account.
Step 2: How to Create a Channel
Log in to ThingSpeak: Go to the ThingSpeak website ([ThingSpeak thingspeak.com]) and enter your login credentials.
Access Channels: Once logged in, navigate to the "Channels" section. You can usually find this by clicking on the "Channels" tab or a similar option on the ThingSpeak dashboard.
Create New Channel: Look for a button labeled "New Channel" or "Create Channel." Clicking on this button will initiate the channel creation process.
Channel Settings: Here, you'll define the specifics of your channel:
- Name: Choose a descriptive name for your channel that reflects the type of data it will store (e.g., "Home Temperature Monitoring").
- Fields: Select the number of data fields you want your channel to have (usually 1 to 8). Each field will represent a specific sensor measurement you plan to collect.
- You can check the boxes next to "Field 1" to "Field 8" depending on how many data streams you need.
- ThingSpeak allows you to name each field later, making it easier to understand what data is being stored in each slot.
Public View (Optional): By default, channels are private. You can choose to make your channel public if you want to share the data with others.
Save Channel: Once you've filled out the channel settings, click on the "Save Channel" button.
Step 3: How to Create a Channel for MQTT
1 go to devices -> select the mqtt
2 copy paste the mqtt client id
3 "mqtt3.thingspeak.com" change this to as per your server MQTT broker(in the code)
4 click on the edit for the user id and the password
Step 4: Arduino Ide An
code is written in Arduino IDE for the Bharat Pi 4G board. It aims to connect to the internet using a 4G SIM card and send sensor data to a ThingSpeak cloud platform.
Library inclusions:
- TinyGsmClient.h: This library enables communication with the 4G module using AT commands.
- SPI.h: This library provides functions for Serial Peripheral Interface (SPI) communication, which might be used for the 4G module.
- ArduinoJson.h: This library helps with parsing and creating JSON data formats.
- Ticker.h: This library might be used for scheduling tasks or timers.
2. Configuration:
- TINY_GSM_MODEM_SIM7600: This line defines the 4G modem model being used (SIM7600).
- APN: This variable stores the Access Point Name (APN) of your network provider, which is crucial for internet connectivity. You'll need to replace "airtelgprs.com" with the appropriate APN for your SIM card.
- cloud_url: This variable holds the ThingSpeak update URL for sending data as a JSON object.
- apiKey: This variable stores your unique ThingSpeak API key, which is required for authentication. Replace "VJP11NDRLY1BGODD" with your actual key.
3. Modem Functions:
- modemPowerOn(), modemPowerOff(), and modemRestart(): These functions manage the power state of the 4G modem.
- modemInit(): This function initializes the communication with the 4G module.
4. Setup:
- Serial communication is established for the Arduino console and the 4G module.
- The code checks for modem initialization and retrieves basic information like the modem name and information.
- It attempts to connect to the cellular network using different network modes (automatic, GSM only, LTE only, or GSM and LTE) until successful. Signal quality and network operator details are printed during the process.
5. Sending Data to ThingSpeak:
- Dummy temperature values are assigned to variables temperature1 and temperature2. In a real scenario, you would replace these with sensor readings or data from your application.
- A JSON object payloadObj is created, containing the API key and the sensor data (temperature1 and temperature2).
- The code establishes an HTTP connection with the ThingSpeak cloud URL and sets the content type as "application/json".
- It sends the JSON data (payload) to the ThingSpeak server using an HTTP POST request.
- Finally, the HTTP connection is terminated.
6. Loop:
- This section is currently commented out. It might be intended for continuously capturing data from sensors or GPIOs and sending it to ThingSpeak in a loop. You'll need to uncomment this section and replace the placeholder with your sensor data reading logic.
GSM CODE
/*************************************************************************
PROJECT: Bharat Pi 4G Board Sample Code for data push to Thingspeak Cloud
AUTHOR: Bharat Pi
FUNC: 4G testing with HTTP call to Thingspeak cloud server.
SIMCARD: 4G sim cards from Airtel/Vodaphone/Jio/BSNL can be used.
To test HTTP request ensure you have data plan.
IMPORTANT: Configure the APN accordingly as per your Sim provider
GPS: If you have bought Bharat Pi wtih GPS board then you need to connect
the GPS antenna to the UFL connector and antenna should have clear sky visibility
preferrably on the terrace or open field.
TODO: (Before you upload the code to Bharat Pi board)
1) Change APN as per your Sim provider
2) Change the Thingspeak API key as per your account/setup
3) Use a power adapter 9V 2amps as the 4G module requires enough power to operate
DESC: This script will connect using 4G sim and makes a http call
to a Thingspeak cloud server setup as per your Thingspeak API key.
COPYRIGHT: BharatPi @MIT license for usage on Bharat Pi boards
*************************************************************************/
#define TINY_GSM_MODEM_SIM7600 //TINY_GSM_MODEM compatible for 7672 as well
#define TINY_GSM_RX_BUFFER 1024
#define SerialAT Serial1
#define SerialMon Serial
#define UART_BAUD 115200
#define PIN_DTR 25
#define PIN_TX 17
#define PIN_RX 16
#define PWR_PIN 32
#define LED_PIN 2
#include <TinyGsmClient.h>
#include <SPI.h>
#include <ArduinoJson.h>
#include <Ticker.h>
/*********************************************
SECTION: Set APN based on your sim card
AIRTEL: "airtelgprs.com"
BSNL: "bsnlnet"
VI: "portalnmms"
JIO: "jionet"
*********************************************/
const char apn[] = "airtelgprs.com"; //Change this as per your Sim card operator
/*********************************************
SECTION: Set Thingspeak cloud and respective API key
*********************************************/
String cloud_url = "https://api.thingspeak.com/update.json"; //Thingspeak update URL for sending data as JSON object
String apiKey = "VJP11NDRLY1BGODD"; // change this to the thingspeak API key as per your account
StaticJsonDocument<200> payloadObj; //for testing http request
#ifdef DUMP_AT_COMMANDS
#include <StreamDebugger.h>
StreamDebugger debugger(SerialAT, SerialMon);
TinyGsm modem(debugger);
#else
TinyGsm modem(SerialAT);
#endif
/*********************************************
SECTION: Modem operation functions
*********************************************/
void modemPowerOn(){
pinMode(PWR_PIN, OUTPUT);
digitalWrite(PWR_PIN, LOW);
delay(1000);
digitalWrite(PWR_PIN, HIGH);
}
void modemPowerOff(){
pinMode(PWR_PIN, OUTPUT);
digitalWrite(PWR_PIN, LOW);
delay(1500);
digitalWrite(PWR_PIN, HIGH);
}
void modemRestart(){
modemPowerOff();
delay(1000);
modemPowerOn();
}
/*********************************************
SECTION: Main setup
*********************************************/
void setup(){
// Set console baud rate
SerialMon.begin(115200);
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW);
delay(100);
modemPowerOn();
SerialAT.begin(UART_BAUD, SERIAL_8N1, PIN_RX, PIN_TX);
Serial.clearWriteError();
Serial.println();
Serial.println();
Serial.println("/**********************************************************/");
Serial.println(" Bharat Pi 4G/LTE Board Test Program");
Serial.println(" To initialize the network test, please make sure the antenna has been");
Serial.println(" connected and SIM card is inserted in the SIM slot (back side of the board).");
Serial.println("/**********************************************************/\n\n");
delay(5000);
String res;
Serial.println("Initializing Modem...");
if (!modem.init()) {
digitalWrite(LED_PIN, HIGH);
modemRestart();
delay(2000);
Serial.println("Failed to restart modem, continue without restarting");
digitalWrite(LED_PIN, LOW);
return;
}
//Blue LED on the board use as an indicator
//If blinking: Modem not able to boot
//If turned ON: connected to network
//If turned OFF: Modem booted successfully but not connected to network, check your SIM, network coverage etc.
digitalWrite(LED_PIN, LOW);
Serial.println("Running SIMCOMATI command...");
modem.sendAT("+SIMCOMATI"); //Get the module information
modem.waitResponse(1000L, res);
res.replace(GSM_NL "OK" GSM_NL, "");
Serial.println(res);
res = "";
Serial.println();
Serial.println("Preferred mode selection (GSM/LTE)...");
modem.sendAT("+CNMP?");
if (modem.waitResponse(1000L, res) == 1) {
res.replace(GSM_NL "OK" GSM_NL, "");
Serial.println(res);
}
res = "";
Serial.println();
//This section is only applicable for testing modules with NBIoT,
//for other modules the command doesnt return anything and can be ignored while testing
Serial.println("Preferred selection between CAT-M and NB-IoT...");
modem.sendAT("+CMNB?");
if (modem.waitResponse(1000L, res) == 1) {
res.replace(GSM_NL "OK" GSM_NL, "");
Serial.println(res);
}
res = "";
Serial.println();
//Get module manufacturer details
String modemName = modem.getModemName();
Serial.println("Modem Name : " + modemName);
delay(1000);
String modemInfo = modem.getModemInfo();
Serial.println("Modem Info : " + modemInfo);
delay(1000);
/*********************************************
SECTION: Connect to Sim network
*********************************************/
Serial.println("Network mode connectivity testing (GSM, LTE or GSM/LTE)...");
for (int i = 0; i <= 4; i++) {
uint8_t network[] = {
2, /*Automatic*/
13, /*GSM only*/
38, /*LTE only*/
51 /*GSM and LTE only*/
};
Serial.printf("Try %d method\n", network[i]);
modem.setNetworkMode(network[i]);
delay(3000);
bool isConnected = false;
int tryCount = 60;
while (tryCount--) {
String netoworkOerator = modem.getOperator();
Serial.print("Operator: ");
Serial.println(netoworkOerator);
int16_t signal = modem.getSignalQuality();
Serial.print("Signal: ");
Serial.println(signal);
Serial.print("isNetworkConnected: ");
isConnected = modem.isNetworkConnected();
Serial.println( isConnected ? "CONNECTED" : "NOT CONNECTED YET");
if (isConnected) {
break;
}
delay(1000);
digitalWrite(LED_PIN, !digitalRead(LED_PIN));
}
if (isConnected) {
break;
}
}
digitalWrite(LED_PIN, HIGH); //Modem connected to network
Serial.println();
Serial.println("Yehhh....Device is connected to Sim network.");
Serial.println();
delay(1000);
Serial.println("Checking UE (User Equipment) system information...");
Serial.println();
modem.sendAT("+CPSI?");
if (modem.waitResponse(1000L, res) == 1) {
res.replace(GSM_NL "OK" GSM_NL, "");
Serial.println(res);
}
delay(1000);
Serial.println("");
Serial.println("");
delay(2000);
/******************************************************************
SECTION: Set dummpy variable for pushing data to cloud.
If you want to dynamically capture data from
sensors or GPIOs then move this section to Loop
and set variables accordingly to push data to Thingspeak.
*******************************************************************/
String payload;
double temperature1 = 56.9; //Dummy vairable to send temperature
double temperature2 = 23.9; //Dummy vairable to send temperature
payloadObj["api_key"] = apiKey;
payloadObj["field1"] = temperature1;
payloadObj["field2"] = temperature2;
serializeJson(payloadObj, payload); //Convert data to json format
Serial.print("Paylod length: ");
Serial.println(payload.length());
Serial.println();
Serial.println(">>>>> Begin Thingspeak Cloud Sync <<<<<<");
Serial.println();
Serial.println("NOTE: Please ensure to have a Thingspeak account and API is setup.");
Serial.println("Thingspeak URL: " + cloud_url);
Serial.println("Thingspeak API Key: " + apiKey);
Serial.println();
Serial.println();
delay(2000);
Serial.println("Initiating HTTP call to Thingspeak");
modem.sendAT("+HTTPINIT"); //init HTTP
if (modem.waitResponse(10000L) != 1) {
Serial.println("ERROR: HTTP INIT FAILED!");
DBG("+HTTPINIT");
}
delay(5000);
/******************************************************************
SECTION: Make an API call to Thingspeak server with sensor data as a Json object
*******************************************************************/
modem.sendAT("+HTTPPARA=\"URL\"," + cloud_url); //set call back URL to test
if (modem.waitResponse(10000L) != 1) {
Serial.println("ERROR: HTTP URL SETTING FAILED!");
DBG("+HTTPPARA=\"URL\"," + cloud_url);
}
modem.sendAT("+HTTPPARA=\"CONTENT\",\"application/json\""); //For test purpose we are sending plain text data. If sending json data then replace: text/plain -> application/json
if (modem.waitResponse(10000L) != 1) {
Serial.println("ERROR: HTTP CONTENT TYPE SETTING FAILED");
DBG("+HTTPPARA=\"CONTENT\",\"application/json\"");
}
modem.sendAT("+HTTPDATA=" + String(payload.length()) + ",20000"); //length of the body (data) and max time required in milliseconds to input the data
//HTTPDATA responds with DOWNLOAD so need to wait for this and then send the body/data of the post call
while (modem.waitResponse(1000UL, "DOWNLOAD") != 1) {
Serial.print(".");
}
delay(2000);
//Send the body/data of the post call
//JSON payload or it can even be a plain text. Read the Thingspeak API reference manual. https://in.mathworks.com/help/thingspeak/rest-api.html
modem.streamWrite(payload);
if (modem.waitResponse(10000L) != 1) {
Serial.println("ERROR: SENDING POST DATA");
}
delay(2000);
Serial.println("Executing HTTP POST call");
modem.sendAT("+HTTPACTION=1"); //Execute post
if (modem.waitResponse(10000UL) != 1) {
Serial.println("ERROR: HTTP POST CALL FAILED!");
DBG("+HTTPACTION=1");
} else {
Serial.print("Data sent to API: ");
Serial.println(payload);
Serial.print("Post call response:");
modem.sendAT("+HTTPREAD");
if(modem.waitResponse(60000L) !=1 ){
DBG(GF("+HTTPREAD"));
}
delay(2000);
modem.sendAT("+HTTPHEAD");
delay(2000);
Serial.println();
Serial.println("Terminating HTTP");
modem.sendAT("+HTTPTERM");
delay(2000);
}
Serial.println(">>>>> END OF Thingspeak Cloud Sync <<<<<<");
}
/******************************************************************
SECTION: Loop call for capturing synamic data from sensors/GPIOs
*******************************************************************/
void loop(){
//Print data to Arduino serial monitor
while (1) {
while (SerialAT.available()) {
SerialMon.write(SerialAT.read());
}
while (SerialMon.available()) {
SerialAT.write(SerialMon.read());
}
}
}
Step 5: Code for Mqtt
/*************************************************************************
PROJECT: Bharat Pi 4G Board Sample Code for data push to Thingspeak Cloud
AUTHOR: Bharat Pi
FUNC: 4G testing with HTTP call to Thingspeak cloud server.
SIMCARD: 4G sim cards from Airtel/Vodaphone/Jio/BSNL can be used.
To test Mqtt request ensure you have data plan.
IMPORTANT: Configure the APN accordingly as per your Sim provider
GPS: If you have bought Bharat Pi wtih GPS board then you need to connect
the GPS antenna to the UFL connector and antenna should have clear sky visibility
preferrably on the terrace or open field.
TODO: (Before you upload the code to Bharat Pi board)
1) Change APN as per your Sim provider
2) Change the Thingspeak API key as per your account/setup
3) Use a power adapter 9V 2amps as the 4G module requires enough power to operate
DESC: This script will connect using 4G sim and makes a mqtt call
to a Thingspeak cloud server setup as per your Thingspeak API key.
COPYRIGHT: BharatPi @MIT license for usage on Bharat Pi boards
*************************************************************************/
#define TINY_GSM_MODEM_SIM7600 //TINY_GSM_MODEM compatible for 7672 as well
#define TINY_GSM_RX_BUFFER 1024
//#define DUMP_AT_COMMANDS true
#define SerialAT Serial1
#define SerialMon Serial
#define UART_BAUD 115200
#define PIN_DTR 25
#define PIN_TX 17
#define PIN_RX 16
#define PWR_PIN 32
#define LED_PIN 2
#include <TinyGsmClient.h> //Lib version - 0.12.0
#include "SSLClient.h" //Lib version - 2.1.7
#include <PubSubClient.h> //Lib version - 2.8
// certificate for https://mqtt3.thingspeak.com
// DigiCert Global Root G2, valid until Sun Mar 30 2031, size: 1720 bytes
// const char* rootCACertificate = \
// "-----BEGIN CERTIFICATE-----\n" \
// "MIIEyDCCA7CgAwIBAgIQDPW9BitWAvR6uFAsI8zwZjANBgkqhkiG9w0BAQsFADBh\n" \
// "MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n" \
// "d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH\n" \
// "MjAeFw0yMTAzMzAwMDAwMDBaFw0zMTAzMjkyMzU5NTlaMFkxCzAJBgNVBAYTAlVT\n" \
// "MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxMzAxBgNVBAMTKkRpZ2lDZXJ0IEdsb2Jh\n" \
// "bCBHMiBUTFMgUlNBIFNIQTI1NiAyMDIwIENBMTCCASIwDQYJKoZIhvcNAQEBBQAD\n" \
// "ggEPADCCAQoCggEBAMz3EGJPprtjb+2QUlbFbSd7ehJWivH0+dbn4Y+9lavyYEEV\n" \
// "cNsSAPonCrVXOFt9slGTcZUOakGUWzUb+nv6u8W+JDD+Vu/E832X4xT1FE3LpxDy\n" \
// "FuqrIvAxIhFhaZAmunjZlx/jfWardUSVc8is/+9dCopZQ+GssjoP80j812s3wWPc\n" \
// "3kbW20X+fSP9kOhRBx5Ro1/tSUZUfyyIxfQTnJcVPAPooTncaQwywa8WV0yUR0J8\n" \
// "osicfebUTVSvQpmowQTCd5zWSOTOEeAqgJnwQ3DPP3Zr0UxJqyRewg2C/Uaoq2yT\n" \
// "zGJSQnWS+Jr6Xl6ysGHlHx+5fwmY6D36g39HaaECAwEAAaOCAYIwggF+MBIGA1Ud\n" \
// "EwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFHSFgMBmx9833s+9KTeqAx2+7c0XMB8G\n" \
// "A1UdIwQYMBaAFE4iVCAYlebjbuYP+vq5Eu0GF485MA4GA1UdDwEB/wQEAwIBhjAd\n" \
// "BgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwdgYIKwYBBQUHAQEEajBoMCQG\n" \
// "CCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQAYIKwYBBQUHMAKG\n" \
// "NGh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEdsb2JhbFJvb3RH\n" \
// "Mi5jcnQwQgYDVR0fBDswOTA3oDWgM4YxaHR0cDovL2NybDMuZGlnaWNlcnQuY29t\n" \
// "L0RpZ2lDZXJ0R2xvYmFsUm9vdEcyLmNybDA9BgNVHSAENjA0MAsGCWCGSAGG/WwC\n" \
// "ATAHBgVngQwBATAIBgZngQwBAgEwCAYGZ4EMAQICMAgGBmeBDAECAzANBgkqhkiG\n" \
// "9w0BAQsFAAOCAQEAkPFwyyiXaZd8dP3A+iZ7U6utzWX9upwGnIrXWkOH7U1MVl+t\n" \
// "wcW1BSAuWdH/SvWgKtiwla3JLko716f2b4gp/DA/JIS7w7d7kwcsr4drdjPtAFVS\n" \
// "slme5LnQ89/nD/7d+MS5EHKBCQRfz5eeLjJ1js+aWNJXMX43AYGyZm0pGrFmCW3R\n" \
// "bpD0ufovARTFXFZkAdl9h6g4U5+LXUZtXMYnhIHUfoyMo5tS58aI7Dd8KvvwVVo4\n" \
// "chDYABPPTHPbqjc1qCmBaZx2vN4Ye5DUys/vZwP9BFohFrH/6j/f3IL16/RZkiMN\n" \
// "JCqVJUzKoZHm1Lesh3Sz8W2jmdv51b2EQJ8HmA==\n" \
// "-----END CERTIFICATE-----\n" \
// "";
/*********************************************
SECTION: Set APN based on your sim card
AIRTEL: "airtelgprs.com"
BSNL: "bsnlnet"
VI: "portalnmms"
JIO: "jionet"
*********************************************/
const char apn[] = "airtelgprs.com"; //Change this as per your Sim card operator
/*********************************************
SECTION: Set Thingspeak cloud specific
*********************************************/
const char broker[] = "mqtt3.thingspeak.com"; //change this to as per your server MQTT broker
const int port = 1883; //MQTT port
const char* channelID = "2456524"; //Thingspeak channel ID, set this to as per your channels on thingspeak
//thingspeak MQTT Client ID settings. Refer thingspeak MQTT settings
const char* mqttClientID = "Ow0UFh47FzsqHj00JAAuGgo";
const char* mqttUsername = "Ow0UFh47FzsqHj00JAAuGgo";
const char* mqttPassword = "7kq9ySBZd7oxWZln3v58/7R8";
#ifdef DUMP_AT_COMMANDS
#include <StreamDebugger.h>
StreamDebugger debugger(SerialAT, SerialMon);
TinyGsm modem(debugger);
#else
TinyGsm modem(SerialAT);
#endif
TinyGsmClient client(modem);
//SSLClient secure_client(&client);
PubSubClient mqtt(client);
/*********************************************
SECTION: Modem operation functions
*********************************************/
void modemPowerOn(){
pinMode(PWR_PIN, OUTPUT);
digitalWrite(PWR_PIN, LOW);
delay(1000);
digitalWrite(PWR_PIN, HIGH);
}
void modemPowerOff(){
pinMode(PWR_PIN, OUTPUT);
digitalWrite(PWR_PIN, LOW);
delay(1500);
digitalWrite(PWR_PIN, HIGH);
}
void modemRestart(){
modemPowerOff();
delay(1000);
modemPowerOn();
}
void printLocalTime()
{
struct tm timeinfo;
if(!getLocalTime(&timeinfo)){
Serial.println("Failed to obtain time");
return;
}
Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");
}
void mqttConnect(String payload) {
SerialMon.print("Setting MQTT broker: ");
SerialMon.println(broker);
mqtt.setServer(broker, port);
mqtt.setBufferSize(2048);
// Connect to MQTT Broker
SerialMon.println("Connecting to MQTT broker");
if (!mqtt.connect(mqttClientID, mqttUsername, mqttPassword)) {
Serial.println("MQTT Client connect failed");
} else {
Serial.println("MQTT Client connect success...");
const char* topicString = "channels/2456524/publish"; //Refer thingspeak on how to set the MQTT topics
const char* message = payload.c_str();
Serial.println("MQTT publish in progress...");
if(mqtt.connected()){
if(mqtt.publish(topicString, message)){
Serial.println("Data published to MQTT server: " + payload);
} else {
Serial.println("ERROR: Data publish failed to MQTT server!");
}
} else {
Serial.println("MQTT is disconnected!");
}
}
}
/*********************************************
SECTION: Main setup
*********************************************/
void setup(){
// Set console baud rate
SerialMon.begin(115200);
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW);
delay(100);
modemPowerOn();
//secure_layer.setCACert(root_ca);
SerialAT.begin(UART_BAUD, SERIAL_8N1, PIN_RX, PIN_TX);
Serial.clearWriteError();
Serial.println();
Serial.println();
Serial.println("/*******************************************************************************/");
Serial.println(" Bharat Pi Thingspeak Cloud Sync using MQTT over 4G/LTE ");
Serial.println("");
Serial.println(" IMPORTANT: To initialize/latch the 4G/LTE network, please make sure the antenna has been");
Serial.println(" connected, SIM is inserted in the SIM slot (back side of the board) and 9V 2A power adapter is connected.");
Serial.println("/******************************************************************************/\n\n");
delay(2000);
String res;
Serial.println("Initializing Modem...");
if (!modem.init()) {
digitalWrite(LED_PIN, HIGH);
modemRestart();
delay(2000);
Serial.println("Failed to restart modem, continue without restarting");
digitalWrite(LED_PIN, LOW);
return;
}
//Blue LED on the board use as an indicator
//If blinking: Modem not able to boot
//If turned ON: connected to network
//If turned OFF: Modem booted successfully but not connected to network, check your SIM, network coverage etc.
digitalWrite(LED_PIN, LOW);
Serial.println("Running SIMCOMATI command...");
modem.sendAT("+SIMCOMATI"); //Get the module information
modem.waitResponse(1000L, res);
//res.replace(GSM_NL "OK" GSM_NL, "");
Serial.println(res);
res = "";
Serial.println();
Serial.println("Preferred mode selection (GSM/LTE)...");
modem.sendAT("+CNMP?");
if (modem.waitResponse(1000L, res) == 1) {
//res.replace(GSM_NL "OK" GSM_NL, "");
Serial.println(res);
}
res = "";
Serial.println();
//This section is only applicable for testing modules with NBIoT,
//for other modules the command doesnt return anything and can be ignored while testing
Serial.println("Preferred selection between CAT-M and NB-IoT...");
modem.sendAT("+CMNB?");
if (modem.waitResponse(1000L, res) == 1) {
//res.replace(GSM_NL "OK" GSM_NL, "");
Serial.println(res);
}
res = "";
Serial.println();
//Get module manufacturer details
String modemName = modem.getModemModel();
Serial.println("Modem Name : " + modemName);
delay(1000);
String modemInfo = modem.getModemInfo();
Serial.println("Modem Info : " + modemInfo);
delay(1000);
/*********************************************
SECTION: Connect to Sim network
*********************************************/
Serial.println("Network mode connectivity testing (GSM, LTE or GSM/LTE)...");
for (int i = 0; i <= 4; i++) {
uint8_t network[] = {
2, /*Automatic*/
13, /*GSM only*/
38, /*LTE only*/
51 /*GSM and LTE only*/
};
Serial.printf("Try %d method\n", network[i]);
modem.setNetworkMode(network[i]);
delay(3000);
bool isConnected = false;
int tryCount = 60;
while (tryCount--) {
String netoworkOerator = modem.getOperator();
Serial.print("Operator: ");
Serial.println(netoworkOerator);
int16_t signal = modem.getSignalQuality();
Serial.print("Signal: ");
Serial.println(signal);
Serial.print("isNetworkConnected: ");
isConnected = modem.isNetworkConnected();
Serial.println( isConnected ? "CONNECTED" : "NOT CONNECTED YET");
if (isConnected) {
break;
}
delay(1000);
digitalWrite(LED_PIN, !digitalRead(LED_PIN));
}
if (isConnected) {
break;
}
}
digitalWrite(LED_PIN, HIGH); //Modem connected to network
Serial.println();
Serial.println("Yehhh....Device is connected to Sim network.");
Serial.println();
delay(1000);
Serial.println("Checking UE (User Equipment) system information...");
Serial.println();
modem.sendAT("+CPSI?");
if (modem.waitResponse(1000L, res) == 1) {
res.replace(AT_NL "OK" AT_NL, "");
Serial.println(res);
}
delay(1000);
Serial.println("");
Serial.println("");
if(modem.isNetworkConnected()){
Serial.println("Mobile Network is connected.......");
}
// GPRS connection parameters are usually set after network registration
SerialMon.print(F("DATA Connection: Connecting to APN: "));
SerialMon.print(apn);
if (!modem.gprsConnect(apn, "", "")) {
Serial.println("APN connect failed");
delay(10000);
return;
}
Serial.println("APN connect success");
if (modem.isGprsConnected()) {
Serial.println("");
Serial.println("GPRS network is connected");
}
Serial.println("");
/******************************************************************
SECTION: Set variables and values for pushing data to cloud via MQTT.
If you want to dynamically capture data from
sensors or GPIOs then move this section to Loop
and set variables accordingly to push data to Thingspeak.
*******************************************************************/
String payload;
double temperature1 = 32.9; //Dummy vairable to send temperature
double temperature2 = 36.2; //Dummy vairable to send temperature
//Prepare paylod if using the MQTT
payload = "field1=" + String(temperature1) + "&field2=" + String(temperature2) + "&status=MQTTPUBLISH";
Serial.print("Paylod length: ");
Serial.println(payload.length());
Serial.println();
Serial.println(">>>>> Begin Thingspeak Cloud Sync using MQTT <<<<<<");
Serial.println();
Serial.println("NOTE: Please ensure to have a Thingspeak MQTT setup for your channel.\n"
"You can find the steps on Thingspeak portal on how to set MQTT for a channel and use\n"
"the channel IDs to publish the fields (sensors) data.");
//MQTT settings
Serial.println("");
Serial.println(" Thingspeak MQTT: " + String(broker));
Serial.println(" Thingspeak Channel: " + String(channelID));
Serial.println();
Serial.println();
delay(2000);
Serial.println("Initiating MQTT connect to Thingspeak");
/******************************************************************
SECTION: Make an API call to Thingspeak server with sensor data as a Json object
*******************************************************************/
Serial.println("...........MQTT connect and publish in progress..............");
//secure_client.setCACert(rootCACertificate);
//delay(5000);
//Serial.println("Root certificate set successfully................");
mqttConnect(payload);
Serial.println("");
Serial.println(">>>>> END OF Thingspeak Cloud Sync <<<<<<");
}
/******************************************************************
SECTION: Loop call for capturing synamic data from sensors/GPIOs
*******************************************************************/
void loop(){
//Print data to Arduino serial monitor
while (1) {
while (SerialAT.available()) {
SerialMon.write(SerialAT.read());
}
while (SerialMon.available()) {
SerialAT.write(SerialMon.read());
}
}
}
Step 6: Wifi Code
#include <WiFi.h>
#include "DHT.h"
// WiFi credentials
const char* ssid = "smile123";
const char* password = "123456789";
// Thingspeak API key
const String apiKey = "20MNHFQKV1NFW83I";
// Thingspeak server
const char* server = "api.thingspeak.com";
// DHT sensor pin and type
#define DHTPIN 23
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
void setup() {
Serial.begin(115200);
Serial.println("Serial Begin");
// Initialize DHT sensor
dht.begin();
// Connect to WiFi
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
}
void loop() {
// Read DHT sensor data
float humidity = dht.readHumidity();
float temperature = dht.readTemperature();
// Check if any reads failed and exit early (to try again)
if (isnan(humidity) || isnan(temperature)) {
Serial.println("Failed to read from DHT sensor!");
return;
}
// Send data to Thingspeak
if (sendToThingspeak(humidity, temperature)) {
Serial.println("Data sent to Thingspeak successfully");
} else {
Serial.println("Failed to send data to Thingspeak");
}
// Delay before next reading
delay(10000); // Delay for 10 seconds (adjust as needed)
}
bool sendToThingspeak(float humidity, float temperature) {
WiFiClient client;
// Create HTTP request body
String requestBody = "api_key=" + apiKey;
requestBody += "&field1=" + String(humidity);
requestBody += "&field2=" + String(temperature);
// Send HTTP POST request to Thingspeak
if (client.connect(server, 80)) {
client.println("POST /update HTTP/1.1");
client.println("Host: api.thingspeak.com");
client.println("Connection: close");
client.println("Content-Type: application/x-www-form-urlencoded");
client.println("Content-Length: " + String(requestBody.length()));
client.println();
client.print(requestBody);
delay(500); // Allow time for response
client.stop();
return true; // Data sent successfully
} else {
Serial.println("Connection to Thingspeak failed");
return false; // Failed to send data
}
}
- Include necessary libraries:
- WiFi.h: Library for connecting to Wi-Fi networks.
- DHT.h: Library for interfacing with DHT temperature and humidity sensors.
- Define Wi-Fi credentials (ssid and password) and ThingSpeak API key (apiKey).
- Define the ThingSpeak server address (server) and specify the DHT sensor pin and type.
- In the setup() function:
- Initialize serial communication for debugging.
- Initialize the DHT sensor.
- Connect to the Wi-Fi network.
- In the loop() function:
- Read temperature and humidity data from the DHT sensor.
- Check if the sensor readings are valid.
- Send the data to ThingSpeak using the sendToThingspeak() function.
- Delay for a specified time before taking the next reading.
- The sendToThingspeak() function:
- Creates an HTTP POST request body with the API key and sensor data.
- Establishes a connection to the ThingSpeak server.
- Sends the HTTP POST request with the data.
- Checks if the connection to ThingSpeak was successful and returns a boolean value accordingly.