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

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!

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.

Related

Electric UI example ESP32 websockets example code issue

This is the example code given for Electric UI's ESP32 websockets intergration.
// This example was written with the ESP8266 and ESP32 as the target hardware.
// Connects to a wifi access point and runs a websockets server as a transport for eUI.
// The ws path is hinted to the UI over the serial connection which ruggedises connection discovery.
// Base wifi libraries from the ESP library pack
#include "WiFi.h"
#include "WiFiMulti.h"
#include "WiFiClientSecure.h"
// Websockets library https://github.com/Links2004/arduinoWebSockets
#include "WebSocketsServer.h"
#include "electricui.h"
#define LED_PIN LED_BUILTIN
// Define default network credentials
char * wifi_ssid = "ssid";
char * wifi_pass = "password";
uint8_t ws_connected = 0; //state indication
uint8_t ws_port = 80;
char ws_path[] = "ws(s)://255.255.255.255:81";
// Simple variables to modify the LED behaviour
uint8_t blink_enable = 1; //if the blinker should be running
uint8_t led_state = 0; //track if the LED is illuminated
uint16_t glow_time = 200; //in milliseconds
// Keep track of when the light turns on or off
uint32_t led_timer = 0;
//example variables
uint8_t example_uint8 = 21;
uint16_t example_uint16 = 321;
uint32_t example_uint32 = 654321;
float example_float = 3.141592;
char demo_string[] = "ESP32 Test Board";
eui_message_t dev_msg_store[] = {
EUI_UINT8( "wsc", ws_connected),
EUI_CHAR_ARRAY( "ws", ws_path ),
EUI_UINT8( "led_blink", blink_enable ),
EUI_UINT8( "led_state", led_state ),
EUI_UINT16( "lit_time", glow_time ),
EUI_UINT8( "ui8", example_uint8 ),
EUI_UINT16( "i16", example_uint16 ),
EUI_UINT32( "i32", example_uint32 ),
EUI_FLOAT( "fPI", example_float ),
EUI_CHAR_ARRAY_RO( "name", demo_string ),
};
WiFiMulti WiFiMulti;
WebSocketsServer webSocket = WebSocketsServer(ws_port);
void tx_putc(uint8_t *data, uint16_t len);
void ws_tx_putc(uint8_t *data, uint16_t len);
eui_interface_t comm_links[] = {
EUI_INTERFACE(&tx_putc),
EUI_INTERFACE(&ws_tx_putc),
};
void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length)
{
uint8_t * iter = payload;
uint8_t * end = payload + length;
switch(type)
{
case WStype_DISCONNECTED:
ws_connected = 2;
break;
case WStype_CONNECTED:
ws_connected = 3;
break;
case WStype_TEXT:
// send data to all connected clients
// webSocket.broadcastTXT("message here");
break;
case WStype_BIN:
while( iter < end )
{
eui_parse(*iter++, &comm_links[1]);
}
break;
case WStype_ERROR:
case WStype_FRAGMENT_TEXT_START:
case WStype_FRAGMENT_BIN_START:
case WStype_FRAGMENT:
case WStype_FRAGMENT_FIN:
ws_connected = 4;
break;
}
}
void wifi_handle()
{
if( WiFiMulti.run() == WL_CONNECTED )
{
//we have a wifi connection
if(!ws_connected)
{
webSocket.begin();
webSocket.onEvent(webSocketEvent);
ws_connected = 1;
// The hint is formatted like ws://255.255.255.255:81
memset( ws_path, 0, sizeof(ws_path) ); //clear the string first
snprintf(ws_path, sizeof(ws_path), "ws://%s:%d", WiFi.localIP().toString().c_str(), ws_port);
glow_time = 200;
// Using Arduino Strings
// String ws_path_string = "ws://" + WiFi.localIP().toString().c_str() + ":" + String(ws_port);
// ws_path_string.toCharArray(ws_path, sizeof(ws_path));
}
else
{
webSocket.loop();
}
}
else
{
//no connection, try again later
ws_connected = 0;
}
}
void eui_callback( uint8_t message )
{
switch(message)
{
case EUI_CB_TRACKED:
// UI recieved a tracked message ID and has completed processing
break;
case EUI_CB_UNTRACKED:
{
// UI passed in an untracked message ID
// Grab parts of the inbound packet which are are useful
eui_header_t header = comm_links[0].packet.header;
uint8_t *name_rx = comm_links[0].packet.id_in;
void *payload = comm_links[0].packet.data_in;
// See if the inbound packet name matches our intended variable
if( strcmp( (char *)name_rx, "talk" ) == 0 )
{
webSocket.broadcastTXT("hello over websockets");
glow_time = 50;
}
}
break;
case EUI_CB_PARSE_FAIL:
break;
}
}
void setup()
{
Serial.begin(115200);
pinMode( LED_BUILTIN, OUTPUT );
//eUI setup
comm_links[0].interface_cb = &eui_callback;
eui_setup_interfaces(comm_links, 2);
EUI_TRACK(dev_msg_store);
eui_setup_identifier("esp32", 5);
WiFiMulti.addAP(wifi_ssid, wifi_pass);
led_timer = millis();
}
void loop()
{
wifi_handle();
while(Serial.available() > 0)
{
eui_parse(Serial.read(), &comm_links[0]);
}
if( blink_enable )
{
// Check if the LED has been on for the configured duration
if( millis() - led_timer >= glow_time )
{
led_state = !led_state; //invert led state
led_timer = millis();
}
}
digitalWrite( LED_PIN, led_state ); //update the LED to match the intended state
}
void tx_putc( uint8_t *data, uint16_t len )
{
Serial.write( data, len );
}
void ws_tx_putc( uint8_t *data, uint16_t len )
{
webSocket.broadcastBIN( data, len);
}
When I enter my SSID and Password the serial monitor just displays:
E (2462) wifi:Association refused temporarily, comeback time 200 mSec
However the LED is blinking as it should.... The Electric UI shows no devices found....

How to recieve a Direct Method on the ESP32 with azure-sdk-for-c-arduino

For a school project I am using IoT Hub to connect between different devices (ESP32), The intention is to use a web application to retrieve data from a device. I want to do this by using a Direct Method.
Now I have seen in the past some direct methods using python and how I can use this in Azure Functions but not yet on an ESP32. By the way, I am programming in C on the ESP32.
Does anyone have an example code for this? I am not finding really much info about direct methods in C with the library "azure-sdk-for-c-arduino".
Thanks in advance
My code at the moment (This is test code):
// Copyright (c) Microsoft Corporation. All rights reserved.
// SPDX-License-Identifier: MIT
/*
This is an Arduino-based Azure IoT Hub sample for ESPRESSIF ESP32 boards.
It uses our Azure Embedded SDK for C to help interact with Azure IoT.
For reference, please visit https://github.com/azure/azure-sdk-for-c.
To connect and work with Azure IoT Hub you need an MQTT client, connecting, subscribing
and publishing to specific topics to use the messaging features of the hub.
Our azure-sdk-for-c is an MQTT client support library, helping composing and parsing the
MQTT topic names and messages exchanged with the Azure IoT Hub.
This sample performs the following tasks:
- Synchronize the device clock with a NTP server;
- Initialize our "az_iot_hub_client" (struct for data, part of our azure-sdk-for-c);
- Initialize the MQTT client (here we use ESPRESSIF's esp_mqtt_client, which also handle the tcp connection and TLS);
- Connect the MQTT client (using server-certificate validation, SAS-tokens for client authentication);
- Periodically send telemetry data to the Azure IoT Hub.
To properly connect to your Azure IoT Hub, please fill the information in the `iot_configs.h` file.
*/
//Variabeles for drukknop
const int PushButton = 35;
//Variables for weight sensor;
double weight = 5.0;
// C99 libraries
#include <cstdlib>
#include <string.h>
#include <time.h>
// Libraries for MQTT client and WiFi connection
#include <WiFi.h>
#include <mqtt_client.h>
// Azure IoT SDK for C includes
#include <az_core.h>
#include <az_iot.h>
#include <azure_ca.h>
// Libraries for SendingJson
#include <ArduinoJson.h>
// Additional sample headers
#include "AzIoTSasToken.h"
#include "SerialLogger.h"
#include "iot_configs.h"
// When developing for your own Arduino-based platform,
// please follow the format '(ard;<platform>)'.
#define AZURE_SDK_CLIENT_USER_AGENT "c/" AZ_SDK_VERSION_STRING "(ard;esp32)"
// Utility macros and defines
#define sizeofarray(a) (sizeof(a) / sizeof(a[0]))
#define NTP_SERVERS "pool.ntp.org", "time.nist.gov"
#define MQTT_QOS1 1
#define DO_NOT_RETAIN_MSG 0
#define SAS_TOKEN_DURATION_IN_MINUTES 60
#define UNIX_TIME_NOV_13_2017 1510592825
#define PST_TIME_ZONE -8
#define PST_TIME_ZONE_DAYLIGHT_SAVINGS_DIFF 1
#define GMT_OFFSET_SECS (PST_TIME_ZONE * 3600)
#define GMT_OFFSET_SECS_DST ((PST_TIME_ZONE + PST_TIME_ZONE_DAYLIGHT_SAVINGS_DIFF) * 3600)
// Translate iot_configs.h defines into variables used by the sample
static const char* ssid = IOT_CONFIG_WIFI_SSID;
static const char* password = IOT_CONFIG_WIFI_PASSWORD;
static const char* host = IOT_CONFIG_IOTHUB_FQDN;
static const char* mqtt_broker_uri = "mqtts://" IOT_CONFIG_IOTHUB_FQDN;
static const char* device_id = IOT_CONFIG_DEVICE_ID;
static const int mqtt_port = AZ_IOT_DEFAULT_MQTT_CONNECT_PORT;
// Memory allocated for the sample's variables and structures.
static esp_mqtt_client_handle_t mqtt_client;
static az_iot_hub_client client;
static char mqtt_client_id[128];
static char mqtt_username[128];
static char mqtt_password[200];
static uint8_t sas_signature_buffer[256];
static unsigned long next_telemetry_send_time_ms = 0;
static char telemetry_topic[128];
static uint8_t telemetry_payload[100];
static uint32_t telemetry_send_count = 0;
#define INCOMING_DATA_BUFFER_SIZE 128
static char incoming_data[INCOMING_DATA_BUFFER_SIZE];
// Auxiliary functions
#ifndef IOT_CONFIG_USE_X509_CERT
static AzIoTSasToken sasToken(
&client,
AZ_SPAN_FROM_STR(IOT_CONFIG_DEVICE_KEY),
AZ_SPAN_FROM_BUFFER(sas_signature_buffer),
AZ_SPAN_FROM_BUFFER(mqtt_password));
#endif // IOT_CONFIG_USE_X509_CERT
static void connectToWiFi()
{
Logger.Info("Connecting to WIFI SSID " + String(ssid));
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println("");
Logger.Info("WiFi connected, IP address: " + WiFi.localIP().toString());
}
static void initializeTime()
{
Logger.Info("Setting time using SNTP");
configTime(GMT_OFFSET_SECS, GMT_OFFSET_SECS_DST, NTP_SERVERS);
time_t now = time(NULL);
while (now < UNIX_TIME_NOV_13_2017)
{
delay(500);
Serial.print(".");
now = time(nullptr);
}
Serial.println("");
Logger.Info("Time initialized!");
}
void receivedCallback(char* topic, byte* payload, unsigned int length)
{
Logger.Info("Received [");
Logger.Info(topic);
Logger.Info("]: ");
for (int i = 0; i < length; i++)
{
Serial.print((char)payload[i]);
}
Serial.println("");
}
static esp_err_t mqtt_event_handler(esp_mqtt_event_handle_t event)
{
switch (event->event_id)
{
int i, r;
case MQTT_EVENT_ERROR:
Logger.Info("MQTT event MQTT_EVENT_ERROR");
break;
case MQTT_EVENT_CONNECTED:
Logger.Info("MQTT event MQTT_EVENT_CONNECTED");
r = esp_mqtt_client_subscribe(mqtt_client, AZ_IOT_HUB_CLIENT_C2D_SUBSCRIBE_TOPIC, 1);
if (r == -1)
{
Logger.Error("Could not subscribe for cloud-to-device messages.");
}
else
{
Logger.Info("Subscribed for cloud-to-device messages; message id:" + String(r));
}
break;
case MQTT_EVENT_DISCONNECTED:
Logger.Info("MQTT event MQTT_EVENT_DISCONNECTED");
break;
case MQTT_EVENT_SUBSCRIBED:
Logger.Info("MQTT event MQTT_EVENT_SUBSCRIBED");
break;
case MQTT_EVENT_UNSUBSCRIBED:
Logger.Info("MQTT event MQTT_EVENT_UNSUBSCRIBED");
break;
case MQTT_EVENT_PUBLISHED:
Logger.Info("MQTT event MQTT_EVENT_PUBLISHED");
break;
case MQTT_EVENT_DATA:
Logger.Info("MQTT event MQTT_EVENT_DATA");
for (i = 0; i < (INCOMING_DATA_BUFFER_SIZE - 1) && i < event->topic_len; i++)
{
incoming_data[i] = event->topic[i];
}
incoming_data[i] = '\0';
Logger.Info("Topic: " + String(incoming_data));
for (i = 0; i < (INCOMING_DATA_BUFFER_SIZE - 1) && i < event->data_len; i++)
{
incoming_data[i] = event->data[i];
}
incoming_data[i] = '\0';
if (String(incoming_data) == "GETWEIGHT")
{
Logger.Info("Send Data To The Cloud ");
sendTelemetry();
}
else
{
Logger.Info("Data: " + String(incoming_data));
}
break;
case MQTT_EVENT_BEFORE_CONNECT:
Logger.Info("MQTT event MQTT_EVENT_BEFORE_CONNECT");
break;
default:
Logger.Error("MQTT event UNKNOWN");
break;
}
return ESP_OK;
}
static void initializeIoTHubClient()
{
az_iot_hub_client_options options = az_iot_hub_client_options_default();
options.user_agent = AZ_SPAN_FROM_STR(AZURE_SDK_CLIENT_USER_AGENT);
if (az_result_failed(az_iot_hub_client_init(
&client,
az_span_create((uint8_t*)host, strlen(host)),
az_span_create((uint8_t*)device_id, strlen(device_id)),
&options)))
{
Logger.Error("Failed initializing Azure IoT Hub client");
return;
}
size_t client_id_length;
if (az_result_failed(az_iot_hub_client_get_client_id(
&client, mqtt_client_id, sizeof(mqtt_client_id) - 1, &client_id_length)))
{
Logger.Error("Failed getting client id");
return;
}
if (az_result_failed(az_iot_hub_client_get_user_name(
&client, mqtt_username, sizeofarray(mqtt_username), NULL)))
{
Logger.Error("Failed to get MQTT clientId, return code");
return;
}
Logger.Info("Client ID: " + String(mqtt_client_id));
Logger.Info("Username: " + String(mqtt_username));
}
static int initializeMqttClient()
{
#ifndef IOT_CONFIG_USE_X509_CERT
if (sasToken.Generate(SAS_TOKEN_DURATION_IN_MINUTES) != 0)
{
Logger.Error("Failed generating SAS token");
return 1;
}
#endif
esp_mqtt_client_config_t mqtt_config;
memset(&mqtt_config, 0, sizeof(mqtt_config));
mqtt_config.uri = mqtt_broker_uri;
mqtt_config.port = mqtt_port;
mqtt_config.client_id = mqtt_client_id;
mqtt_config.username = mqtt_username;
#ifdef IOT_CONFIG_USE_X509_CERT
Logger.Info("MQTT client using X509 Certificate authentication");
mqtt_config.client_cert_pem = IOT_CONFIG_DEVICE_CERT;
mqtt_config.client_key_pem = IOT_CONFIG_DEVICE_CERT_PRIVATE_KEY;
#else // Using SAS key
mqtt_config.password = (const char*)az_span_ptr(sasToken.Get());
#endif
mqtt_config.keepalive = 30;
mqtt_config.disable_clean_session = 0;
mqtt_config.disable_auto_reconnect = false;
mqtt_config.event_handle = mqtt_event_handler;
mqtt_config.user_context = NULL;
mqtt_config.cert_pem = (const char*)ca_pem;
mqtt_client = esp_mqtt_client_init(&mqtt_config);
if (mqtt_client == NULL)
{
Logger.Error("Failed creating mqtt client");
return 1;
}
esp_err_t start_result = esp_mqtt_client_start(mqtt_client);
if (start_result != ESP_OK)
{
Logger.Error("Could not start mqtt client; error code:" + start_result);
return 1;
}
else
{
Logger.Info("MQTT client started");
return 0;
}
}
/*
#brief Gets the number of seconds since UNIX epoch until now.
#return uint32_t Number of seconds.
*/
static uint32_t getEpochTimeInSecs()
{
return (uint32_t)time(NULL);
}
static void establishConnection()
{
connectToWiFi();
initializeTime();
initializeIoTHubClient();
(void)initializeMqttClient();
}
static void getTelemetryPayload(az_span payload, az_span* out_payload)
{
az_span original_payload = payload;
payload = az_span_copy(
payload, AZ_SPAN_FROM_STR("{ \"deviceId\": "));
payload = az_span_copy(payload, AZ_SPAN_FROM_STR( IOT_CONFIG_DEVICE_ID ));
payload = az_span_copy(payload, AZ_SPAN_FROM_STR( "," ));
payload = az_span_copy(payload, AZ_SPAN_FROM_STR( "\" weight\": "));
(void)az_span_u32toa(payload, weight , &payload);
payload = az_span_copy(payload, AZ_SPAN_FROM_STR(" }"));
payload = az_span_copy_u8(payload, '\0');
*out_payload = az_span_slice(original_payload, 0, az_span_size(original_payload) - az_span_size(payload) - 1);
}
static void sendTelemetry()
{
az_span telemetry = AZ_SPAN_FROM_BUFFER(telemetry_payload);
Logger.Info("Sending telemetry ...");
// The topic could be obtained just once during setup,
// however if properties are used the topic need to be generated again to reflect the
// current values of the properties.
if (az_result_failed(az_iot_hub_client_telemetry_get_publish_topic(
&client, NULL, telemetry_topic, sizeof(telemetry_topic), NULL)))
{
Logger.Error("Failed az_iot_hub_client_telemetry_get_publish_topic");
return;
}
getTelemetryPayload(telemetry, &telemetry);
if (esp_mqtt_client_publish(
mqtt_client,
telemetry_topic,
(const char*)az_span_ptr(telemetry),
az_span_size(telemetry),
MQTT_QOS1,
DO_NOT_RETAIN_MSG)
== 0)
{
Logger.Error("Failed publishing");
}
else
{
Logger.Info("Message published successfully");
}
}
// Arduino setup and loop main functions.
void setup()
{
establishConnection();
pinMode(PushButton, INPUT);
}
void loop()
{
if (WiFi.status() != WL_CONNECTED)
{
connectToWiFi();
}
#ifndef IOT_CONFIG_USE_X509_CERT
else if (sasToken.IsExpired())
{
Logger.Info("SAS token expired; reconnecting with a new one.");
(void)esp_mqtt_client_destroy(mqtt_client);
initializeMqttClient();
}
#endif
int Push_button_state = digitalRead(PushButton);
// if condition checks if push button is pressed
if ( Push_button_state == HIGH )
{
Serial.println("De Button Is ingedrukt");
sendTelemetry();
delay(500);
}
}
The idea is that when I send a Direct Method "GETWEIGHT" I get a json value back.
In your initializeMqttClient method, you can add the following line.
mqtt_client.setCallback(receivedCallback);
Your receivedCallback method can have the following definition (code from a Microsoft sample)
void receivedCallback(char* topic, byte* payload, unsigned int length)
{
Logger.Info("Received [");
Logger.Info(topic);
Logger.Info("]: ");
for (int i = 0; i < length; i++)
{
Serial.print((char)payload[i]);
}
Serial.println("");
}
You mentioned you want to retrieve data from the device, so you probably want to respond to the message. This is done by sending a message on the right topic. You need to include the status (for instance a 200 indicating 'OK') and the ID of the direct method. This id is included when you receive the direct method. For instance, if you receive a direct method with ID 42, you can respond to it by publishing:
void RespondToDirectMethod()
{
mqtt_client.publish("$iothub/methods/res/200/?$rid=42", "", false);
}

Arduino web socket autoreconnect

I am using 2 esp8266, both connected to same network. Esp1 send some data to esp2 using websocket. So basically esp2 connect to esp1 websocket and read data.
My problem is that if esp1 is restarted, after is up again, esp2 does not connect anymore to it and needs restart to connect
This is code I am using on esp2
#include <ESP8266WiFi.h>
#include <WebSocketsClient.h>
#include <ESP8266WebServer.h>
#include <SoftwareSerial.h>
#define USE_SERIAL Serial
#define LEDS 0 //Status led
WebSocketsClient webSocket;
SoftwareSerial COM(5, 4);
long previousMillis = 0;
long interval = 50;
String data;
void webSocketEvent(WStype_t type, uint8_t * payload, size_t length) {
switch(type) {
case WStype_DISCONNECTED:
yield();
break;
case WStype_CONNECTED: {
webSocket.sendTXT("Connected");
}
yield();
break;
case WStype_TEXT:
if(payload[0] == '#') {
uint32_t dataz = (uint32_t) strtol((const char *) &payload[1], NULL, 10);
if (dataz < 99911) {
data = "0" + String(dataz);
}
else {
data = String(dataz);
}
}
yield();
if (data.length() == 6 ) {
COM.print('<'); // start marker
COM.print(data);
COM.println('>'); // end marker
}
break;
}
}
void setup() {
pinMode(LEDS, OUTPUT);
digitalWrite(LEDS, LOW);
for(uint8_t t = 4; t > 0; t--) {
delay(1000);
}
WiFi.mode(WIFI_STA);
WiFi.begin("xxx", "xxx");
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
}
// server address, port and URL
webSocket.begin("192.168.0.30", 81, "/");
// event handler
webSocket.onEvent(webSocketEvent);
// use HTTP Basic Authorization this is optional remove if not needed
//webSocket.setAuthorization("user", "Password");
// try ever 5000 again if connection has failed
webSocket.setReconnectInterval(5000);
digitalWrite(LEDS, HIGH);
}
void loop() {
unsigned long currentMillis = millis();
if(currentMillis - previousMillis > interval) {
previousMillis = currentMillis;
webSocket.loop();
}
}
I would need some help to make it reconnect when the esp1 is available again after was disconnected
Thank you very much
webSocket.loop(); should be outside of if statement.

NodeMCU Get data from webswerver and update value

I am using Nodenmcu with arduino IDE . I have used DHT11 IC to read temperature and humidity. Now i would like to add parameter in web page called set_temp . When Set_temp value being set to value the value should get updated when change icon has been pressed. Here is my code. My code is working till to enter the text from web but it wont update set_temp value
#include <ESP8266WiFi.h>
#include "DHT.h"
static float Set_Temp;
DHT dht;
int value = LOW;
const char* ssid = "esp8266";
const char* password = "Test123456";
int ledPin = 13; // GPIO13
WiFiServer server(80);
void setup() {
Serial.begin(115200);
delay(10);
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, LOW);
dht.setup(D3); /* D1 is used for data communication */
// Connect to WiFi network
Serial.println();
Serial.println();
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");
// Start the server
server.begin();
Serial.println("Server started");
// Print the IP address
Serial.print("Use this URL to connect: ");
Serial.print("http://");
Serial.print(WiFi.localIP());
Serial.println("/");
}
void loop() {
// Check if a client has connected
WiFiClient client = server.available();
if (!client) {
return;
}
// Wait until the client sends some data
Serial.println("new client");
while(!client.available()){
delay(1);
}
// New code has been added
delay(dht.getMinimumSamplingPeriod()); /* Delay of amount equal to sampling period */
float humidity = dht.getHumidity(); /* Get humidity value */
float temperature = dht.getTemperature(); /* Get temperature value */
// Serial.print(dht.getStatusString()); /* Print status of communication */
if(temperature>=Set_Temp)
{
digitalWrite(ledPin, HIGH);
value = HIGH;
}else
{
digitalWrite(ledPin, LOW);
value = LOW;
}
// Read the first line of the request
String request = client.readStringUntil('\r');
Serial.println(request);
client.flush();
// Match the request
/* if (request.indexOf("/LED=ON") != -1) {
digitalWrite(ledPin, HIGH);
value = HIGH;
}
if (request.indexOf("/LED=OFF") != -1) {
digitalWrite(ledPin, LOW);
value = LOW;
}*/
// Set ledPin according to the request
//digitalWrite(ledPin, value);
// Return the response
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println(""); // do not forget this one
client.println("<!DOCTYPE HTML>");
client.println("<html>");
client.print("Relay_Turn_On_Status: ");
if(value == HIGH) {
client.print("On");
} else {
client.print("Off");
}
// client.println("<br><br>");
// client.println("<button>Turn On </button>");
// client.println("<button>Turn Off </button><br />");
// client.println("</html>");
client.print("</html>");
client.print("<head>");
client.print("<title>My Page</title>");
client.print("</head>");
client.print("<body>");
client.print("<br><br>");
client.print("Set_Temp: ");
client.println("<input type=text name=textbox size=5 value=Enter_Temp_Here");
client.println("<br><input type=submit value=Change ><br>");
client.println("</div>");
client.println("</body>");
client.println("</html>");
Set_Temp:"<br><input type=submit value=Change ><br>";
//Set_Temp:"<input type=text name=textbox size=5 value=Enter_Temp_Here>";
Serial.println(Set_Temp);
client.println("<br><br>");
client.println("DHT11_HumidityReading: ");
client.println(humidity,1);
client.println("<br><br>");
client.println("DHT11_Temprature Reading: ");
client.println(temperature,1);
client.println("<br><br>");
client.println("Set_Temp: ");
client.println(Set_Temp);
client.println("<br><br>");
delay(1);
Serial.println("Client disonnected");
Serial.println("");
}
My main doubt in this part of code where once i read it wont update.
Set_Temp:"<br><input type=submit value=Change ><br>";
//Set_Temp:"<input type=text name=textbox size=5 value=Enter_Temp_Here>";
Serial.println(Set_Temp);
If i use like this. it will display -1
Set_Temp=readString.indexOf(2);
I followed the method of get & post from HTTP https://www.w3schools.com/htmL/[Serial Out Here][web page]
How can i change my Set_Temp value from text box.
Take a look to this article, I follow it to turn on and turn off a light in NodeMCU with Arduino IDE. The client in the web is written on PHP.
https://blog.nyl.io/esp8266-led-arduino/
<?php
$light = $_GET['light'];
if($light == "on") {
$file = fopen("light.json", "w") or die("can't open file");
fwrite($file, '{"light": "on"}');
fclose($file);
}
else if ($light == "off") {
$file = fopen("light.json", "w") or die("can't open file");
fwrite($file, '{"light": "off"}');
fclose($file);
}
?>
I hope this help you.
Regards

Whats the purpose of "num" in arduinoWebSockets?

Whats the purpose of num in webSocket.sendTXT(num, "Connected"); or at any other place its used in the code, what function does it serve? Because it doesn't ever get defined as anything anywhere, but it is required to
be passed as a function argument for it to work.
In void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) it's set as a function parameter.
Links2004/arduinoWebSockets Library
/*
* WebSocketServer_LEDcontrol.ino
*
* Created on: 26.11.2015
*
*/
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <WebSocketsServer.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include <Hash.h>
#define LED_RED 15
#define LED_GREEN 12
#define LED_BLUE 13
#define USE_SERIAL Serial
ESP8266WiFiMulti WiFiMulti;
ESP8266WebServer server = ESP8266WebServer(80);
WebSocketsServer webSocket = WebSocketsServer(81);
void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) {
switch(type) {
case WStype_DISCONNECTED:
USE_SERIAL.printf("[%u] Disconnected!\n", num);
break;
case WStype_CONNECTED: {
IPAddress ip = webSocket.remoteIP(num);
USE_SERIAL.printf("[%u] Connected from %d.%d.%d.%d url: %s\n", num, ip[0], ip[1], ip[2], ip[3], payload);
// send message to client
webSocket.sendTXT(num, "Connected");
}
break;
case WStype_TEXT:
USE_SERIAL.printf("[%u] get Text: %s\n", num, payload);
if(payload[0] == '#') {
// we get RGB data
// decode rgb data
uint32_t rgb = (uint32_t) strtol((const char *) &payload[1], NULL, 16);
analogWrite(LED_RED, ((rgb >> 16) & 0xFF));
analogWrite(LED_GREEN, ((rgb >> 8) & 0xFF));
analogWrite(LED_BLUE, ((rgb >> 0) & 0xFF));
}
break;
}
}
void setup() {
//USE_SERIAL.begin(921600);
USE_SERIAL.begin(115200);
//USE_SERIAL.setDebugOutput(true);
USE_SERIAL.println();
USE_SERIAL.println();
USE_SERIAL.println();
for(uint8_t t = 4; t > 0; t--) {
USE_SERIAL.printf("[SETUP] BOOT WAIT %d...\n", t);
USE_SERIAL.flush();
delay(1000);
}
pinMode(LED_RED, OUTPUT);
pinMode(LED_GREEN, OUTPUT);
pinMode(LED_BLUE, OUTPUT);
digitalWrite(LED_RED, 1);
digitalWrite(LED_GREEN, 1);
digitalWrite(LED_BLUE, 1);
WiFiMulti.addAP("SSID", "passpasspass");
while(WiFiMulti.run() != WL_CONNECTED) {
delay(100);
}
// start webSocket server
webSocket.begin();
webSocket.onEvent(webSocketEvent);
if(MDNS.begin("esp8266")) {
USE_SERIAL.println("MDNS responder started");
}
// handle index
server.on("/", []() {
// send index.html
server.send(200, "text/html", "<html><head><script>var connection = new WebSocket('ws://'+location.hostname+':81/', ['arduino']);connection.onopen = function () { connection.send('Connect ' + new Date()); }; connection.onerror = function (error) { console.log('WebSocket Error ', error);};connection.onmessage = function (e) { console.log('Server: ', e.data);};function sendRGB() { var r = parseInt(document.getElementById('r').value).toString(16); var g = parseInt(document.getElementById('g').value).toString(16); var b = parseInt(document.getElementById('b').value).toString(16); if(r.length < 2) { r = '0' + r; } if(g.length < 2) { g = '0' + g; } if(b.length < 2) { b = '0' + b; } var rgb = '#'+r+g+b; console.log('RGB: ' + rgb); connection.send(rgb); }</script></head><body>LED Control:<br/><br/>R: <input id=\"r\" type=\"range\" min=\"0\" max=\"255\" step=\"1\" oninput=\"sendRGB();\" /><br/>G: <input id=\"g\" type=\"range\" min=\"0\" max=\"255\" step=\"1\" oninput=\"sendRGB();\" /><br/>B: <input id=\"b\" type=\"range\" min=\"0\" max=\"255\" step=\"1\" oninput=\"sendRGB();\" /><br/></body></html>");
});
server.begin();
// Add service to MDNS
MDNS.addService("http", "tcp", 80);
MDNS.addService("ws", "tcp", 81);
digitalWrite(LED_RED, 0);
digitalWrite(LED_GREEN, 0);
digitalWrite(LED_BLUE, 0);
}
void loop() {
webSocket.loop();
server.handleClient();
}
Looking at the library's source code, it reveals that it's a client id, so you can differentiate between multiple clients, that are connected at the same time.
/*
* send text data to client
* #param num uint8_t client id
* #param payload uint8_t *
* #param length size_t
* #param headerToPayload bool (see sendFrame for more details)
* #return true if ok
*/
bool WebSocketsServer::sendTXT(uint8_t num, uint8_t * payload, size_t length, bool headerToPayload) {
if(num >= WEBSOCKETS_SERVER_CLIENT_MAX) {
return false;
}
if(length == 0) {
length = strlen((const char *) payload);
}
WSclient_t * client = &_clients[num];
if(clientIsConnected(client)) {
return sendFrame(client, WSop_text, payload, length, false, true, headerToPayload);
}
return false;
}

Resources