Total Number of Packets Sent and Received in Contiki - contiki

I'm trying to get the total number of packets transmitted and packets received in RPL. I'm using upd-client.c and udp-server.c and I added printf lines in both files as the following:
PROCESS(udp_client_process, "UDP client process");
AUTOSTART_PROCESSES(&udp_client_process);
/*---------------------------------------------------------------------------*/
static void
tcpip_handler(void)
{
char *str;
if(uip_newdata()) {
str = uip_appdata;
str[uip_datalen()] = '\0';
printf("Data recv");
//printf("DATA recv '%s'\n", str);
}
}
/*---------------------------------------------------------------------------*/
static void
send_packet(void *ptr)
{
static int seq_id;
char buf[MAX_PAYLOAD_LEN];
seq_id++;
printf("Data send");
PRINTF("DATA send to %d 'Hello %d'\n",
server_ipaddr.u8[sizeof(server_ipaddr.u8) - 1], seq_id);
sprintf(buf, "Hello %d from the client", seq_id);
uip_udp_packet_sendto(client_conn, buf, strlen(buf),
&server_ipaddr, UIP_HTONS(UDP_SERVER_PORT));
}
PROCESS(udp_server_process, "UDP server process");
AUTOSTART_PROCESSES(&udp_server_process);
/*---------------------------------------------------------------------------*/
static void
tcpip_handler(void)
{
char *appdata;
if(uip_newdata()) {
appdata = (char *)uip_appdata;
appdata[uip_datalen()] = 0;
printf("Data recv");
// PRINTF("DATA recv '%s' from ", appdata);
PRINTF("%d",
UIP_IP_BUF->srcipaddr.u8[sizeof(UIP_IP_BUF->srcipaddr.u8) - 1]);
PRINTF("\n");
#if SERVER_REPLY
PRINTF("DATA sending reply\n");
uip_ipaddr_copy(&server_conn->ripaddr, &UIP_IP_BUF->srcipaddr);
uip_udp_packet_send(server_conn, "Reply", sizeof("Reply"));
uip_create_unspecified(&server_conn->ripaddr);
#endif
}
}
Then in the simulation script editor, I counted the printed messages:
while (true) {
if (msg) {
if(msg.startsWith("Data send")) {
num_messages_tx += 1;
}
if(msg.startsWith("Data recv")) {
num_messages_rx += 1;
}
}
I'm not sure what I'm doing wrong but it seems that I always have equal numbers of transmitted and received packets.
I appreciate your help..
Hanin

in the project-conf.h define below macros and the contiki link-stats.c count them for you.
#define LOG_CONF_LEVEL_MAC LOG_LEVEL_INFO
#define LINK_STATS_CONF_PACKET_COUNTERS 1

Related

Blue ESP8266-12e tx light staying on

I have some code I have been putting on an ESP8266-12e board. Until recently it always worked fine. Now though when I finish uploading the code the blue light on the ESP8266-12e is staying on. I have tried it on two different board and the blue light stay on on both. I can't figure out what I changed in the code.
I have decided to put it up and have everyone look at it and let me know what I may be missing.
I hope someone can find something.
My code:
//NodeMCU 1.0 (ESP-12E Module constant connect)
#include <ESP8266WiFi.h>
#include <FS.h> //https://github.com/esp8266/Arduino
#include <EEPROM.h>
//needed for library
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h> //https://github.com/tzapu/WiFiManager
#include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_Client.h"
//MQTT stuff
#define AIO_SERVER "go,here"
#define AIO_SERVERPORT SSSS // 8883 for MQTTS
#define AIO_USERNAME "FFFFFF"
#define AIO_KEY "XXXXXXXXXXXXXXXXXXXXXXX"
int tripper = 1;
#define MQTT_CONN_KEEPALIVE 18000000
#define LED3 16
//NEW AUTOCONNECT
const byte numChars = 32;
char receivedChars[numChars];
char Password[36]="";
char apiKey[16]="";
char apiKey2[32]="";
char channelKey[16];
char channelKey2[16];
String channelKey21= "&";
byte pinState = LOW;
char ssid[] = "";
char pass[] = "";
String Label = "";
String TOTAL = "";
uint32_t m=0;
WiFiClient client;
Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);
// Setup a feed called 'onoff' for subscribing to changes.
Adafruit_MQTT_Subscribe trip2 = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/trip");
Adafruit_MQTT_Publish move1 = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/motion");
/*************************** Error Reporting *********************************/
Adafruit_MQTT_Subscribe errors = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/errors");
Adafruit_MQTT_Subscribe throttle = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/throttle");
//NEW AUTOCONNECT
int LED2 = 13;
int MOVEMENT = 5;
//send ssid/pass
String f;
//mqtt
char temperature[]="000";
String level;
String battery;
String trip;
String date;
int addr = 0;
//END NEW AUTOCONNECT
void MQTT_connect();
void setup() {
Serial.begin(115200);
pinMode(MOVEMENT,OUTPUT);
digitalWrite(MOVEMENT,LOW);
pinMode(D5,OUTPUT);
digitalWrite(D5,LOW);
pinMode(LED3,OUTPUT);
digitalWrite(LED3,LOW);
pinMode(LED2,INPUT);
Serial.println(F("Adafruit MQTT demo"));
//NEW AUTOCONNECT
WiFiManager wifiManager;
// put your setup code here, to run once:
WiFiManagerParameter customAPIKey("apiKey", "Time Zone #", apiKey, 16);
wifiManager.addParameter(&customAPIKey);
wifiManager.autoConnect("FloWT2");
Serial.println("Connected");
strcpy(apiKey,customAPIKey.getValue());
EEPROM.begin(512); //Initialize EEPROM
EEPROM.write(addr, 'A'); //Write character A
addr++; //Increment address
EEPROM.write(addr, 'B'); //Write character A
String www = apiKey;
Serial.print("www");
Serial.print (www);
for(int i=0;i<www.length();i++) //loop upto string lenght www.length() returns length of string
{
EEPROM.write(0x0F+i,www[i]); //Write one by one with starting address of 0x0F
}
EEPROM.commit();
delay (2000);
if (WiFi.status() == WL_DISCONNECTED) {
wifiManager.autoConnect("FloWT2");
delay(60000);}
if (WiFi.status() == WL_CONNECTED) { Serial.println("Connected");
delay(1000);
//get time zone
EEPROM.begin(512);
Serial.println(""); //Goto next line, as ESP sends some garbage when you reset it
Serial.print(char(EEPROM.read(addr))); //Read from address 0x00
addr++; //Increment address
Serial.print(char(EEPROM.read(addr))); //Read from address 0x01
addr++; //Increment address
Serial.println(char(EEPROM.read(addr))); //Read from address 0x02
//Read string from eeprom
String www;
//Here we dont know how many bytes to read it is better practice to use some terminating character
//Lets do it manually www.circuits4you.com total length is 20 characters
for(int i=0;i<16;i++)
{
www = www + char(EEPROM.read(0x0F+i)); //Read one by one with starting address of 0x0F
}
Serial.println("this");
Serial.print(www);
Serial.println("IP address: "); Serial.println(WiFi.localIP());
// Setup MQTT subscription for onoff feed
mqtt.subscribe(&trip2);
// Setup MQTT subscriptions for throttle & error messages
mqtt.subscribe(&throttle);
mqtt.subscribe(&errors);
WiFiClient client;
delay(2000);
Serial.printf("SSID: %s\n", WiFi.SSID().c_str());
Serial.printf("SSID: %s\n", WiFi.psk().c_str());
String ssidString = WiFi.SSID().c_str();
String pskString = WiFi.psk().c_str();
f = String('<')+String("Hi")+String(',')+String(ssidString)+String(',')+String(pskString)+String(',')+String(www)+String('>');
delay (1000);
Serial.print(f);
delay(500);
Serial.print(f);
delay(500);
Serial.print(f);
delay(500);
Serial.print(f);
delay(500);
Serial.print(f);
delay(500);
}
client.stop();
}
void loop() {
MQTT_connect();
uint32_t m=0;
Serial.print(F("\nSending motion val "));
Serial.print(m);
Serial.print("...");
if (! move1.publish(m)) {
Serial.println(F("Failed"));
} else {
Serial.println(F("OK!"));
}
long state = digitalRead(LED2);
if(state == HIGH) {
m = 1;
Serial.print(F("\nSending motion val "));
Serial.print(m);
Serial.print("...");
digitalWrite(MOVEMENT,HIGH);
delay(1000);
digitalWrite(MOVEMENT,LOW);
if (! move1.publish(m)) {
Serial.println(F("Failed"));
} else {
Serial.println(F("OK!"));
}
}
else{
}
// this is our 'wait for incoming subscription packets' busy subloop
// try to spend your time here
//12e
Adafruit_MQTT_Subscribe *subscription;
while ((subscription = mqtt.readSubscription(5000))) {
if (subscription == &trip2) {
Serial.print(F("Got onoff: "));
Serial.println((char *)trip2.lastread);
uint16_t sliderval = atoi((char *)trip2.lastread);
//THIS IS FOR LATCHING RELAY TURN ON D5 HIGH THEN OFF AFTER 1 SECOND
//NEXt TURN D6 HIGH THEN OFF AFTER A SECONDS
if((sliderval ==0)&&(tripper == 1)){
digitalWrite(D5,HIGH);
delay(1000);
digitalWrite(D5,LOW);
tripper = 2;
Serial.print(tripper);
Serial.print("tripped");
}
else if(sliderval == 50){
}
else if((sliderval == 100)&&(tripper == 2)){
digitalWrite(LED3,HIGH);
delay(1000);
digitalWrite(LED3,LOW);
tripper = 1;
Serial.print(tripper);
Serial.print("tripped2");
}
} else if(subscription == &errors) {
Serial.print(F("ERROR: "));
Serial.println((char *)errors.lastread);
} else if(subscription == &throttle) {
Serial.println((char *)throttle.lastread);
}
}
}
void MQTT_connect() {
int8_t ret;
// Stop if already connected.
if (mqtt.connected()) {
return;
}
Serial.print("Connecting to MQTT... ");
uint8_t retries = 3;
while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected
Serial.println(mqtt.connectErrorString(ret));
Serial.println("Retrying MQTT connection in 5 seconds...");
mqtt.disconnect();
delay(5000); // wait 5 seconds
retries--;
if (retries == 0) {
// basically die and wait for WDT to reset me
while (1);
}
}
Serial.println("MQTT Connected!");
}
I hope it is not toooo long.
Anyway I hope someone can find my problem. Everything works ok with the blue light on it is just know supposed to be that I can tell.
When I upload another code it doesn't stay on so it has to be in the code.
I will keep looking.
THANKS
So I got the blue light to go off. Instead of pinMode(D4,INPUT); and digitalWrite(D4,LOW); D4 is pin 16 which is the wake pin. So I had to define it thus #define LED3 16 and then pinMode(LED3,INPUT); and digitalWrite(LED3,LOW); I will change my original code to reflect these changes.

How to send a chunk of data using shlib(nghttp2) in esp32?

I want to use HTTP2 to POST data continuously. As I found, the only feasible solution is to use shlib. I can implement it and use it. But there were two problems that I faced:
1- shlib does not let us send a data bigger than 16KB theoretically. Here, the solution that I found was to feed the buffer couple of times without calling NGHTTP2_DATA_FLAG_EOF. But, the main problem is that we cannot return the size of the buffer which although is defined as int, but does not support lengths more than 16K.
2- The fault rate of sending data more than about 3 to 4K goes exponentially high as in these situations, just a few of packets are able to be sent correctly.
Any suggestion?
Thanks
I did all my bests to make sure that the resources don't interfere with each other. Here is my code:
#include <Arduino.h>
#include <WiFiClientSecure.h>
#include "esp_camera.h"
extern "C"
{
#include "sh2lib.h"
}
#if CONFIG_FREERTOS_UNICORE
#define ARDUINO_RUNNING_CORE 0
#else
#define ARDUINO_RUNNING_CORE 1
#endif
// CAMERA_MODEL_AI_THINKER
#define PWDN_GPIO_NUM 32
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 0
#define SIOD_GPIO_NUM 26
#define SIOC_GPIO_NUM 27
#define Y9_GPIO_NUM 35
#define Y8_GPIO_NUM 34
#define Y7_GPIO_NUM 39
#define Y6_GPIO_NUM 36
#define Y5_GPIO_NUM 21
#define Y4_GPIO_NUM 19
#define Y3_GPIO_NUM 18
#define Y2_GPIO_NUM 5
#define VSYNC_GPIO_NUM 25
#define HREF_GPIO_NUM 23
#define PCLK_GPIO_NUM 22
const char* ssid = "NETWORK"; // your network SSID (name of wifi network)
const char* password = "PASSWORD"; // your network password
bool request_finished = false;
String head = "--JPEG_IMAGE\r\nContent-Disposition: form-data; name=\"imageFile\"; filename=\"esp32-cam.jpg\"\r\nContent-Type: image/jpeg\r\n\r\n";
String tail = "\r\n--JPEG_IMAGE--\r\n";
char data_to_post[16000];
uint32_t totalLen;
camera_config_t config;
struct sh2lib_handle hd;
bool is_captured;
bool is_posted;
uint16_t safety_counter;
void setup()
{
// put your setup code here, to run once:
Serial.begin(115200);
delay(100);
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
WiFi.begin(ssid, password);
// attempt to connect to Wifi network:
while (WiFi.status() != WL_CONNECTED)
{
Serial.print(".");
// wait 1 second for re-trying
delay(1000);
}
Serial.print("\n");
Serial.print(F("Connected to: "));
Serial.println(ssid);
// Etablishing Connection
Serial.println(F("Establishing Connection... "));
if (sh2lib_connect(&hd, "My_Server") != ESP_OK)
{
Serial.println("Error connecting to HTTP2 server");
//vTaskDelete(NULL);
}
Serial.println(F("Connected to the webserver"));
delay(1000);
// Configuring the Cam
config.ledc_channel = LEDC_CHANNEL_0;
config.ledc_timer = LEDC_TIMER_0;
config.pin_d0 = Y2_GPIO_NUM;
config.pin_d1 = Y3_GPIO_NUM;
config.pin_d2 = Y4_GPIO_NUM;
config.pin_d3 = Y5_GPIO_NUM;
config.pin_d4 = Y6_GPIO_NUM;
config.pin_d5 = Y7_GPIO_NUM;
config.pin_d6 = Y8_GPIO_NUM;
config.pin_d7 = Y9_GPIO_NUM;
config.pin_xclk = XCLK_GPIO_NUM;
config.pin_pclk = PCLK_GPIO_NUM;
config.pin_vsync = VSYNC_GPIO_NUM;
config.pin_href = HREF_GPIO_NUM;
config.pin_sscb_sda = SIOD_GPIO_NUM;
config.pin_sscb_scl = SIOC_GPIO_NUM;
config.pin_pwdn = PWDN_GPIO_NUM;
config.pin_reset = RESET_GPIO_NUM;
config.xclk_freq_hz = 20000000;
config.pixel_format = PIXFORMAT_JPEG;
// init with high specs to pre-allocate larger buffers
if(psramFound())
{
config.frame_size = FRAMESIZE_VGA;// FRAMESIZE_QVGA
config.jpeg_quality = 10; //0-63 lower number means higher quality
config.fb_count = 2;
}
else
{
config.frame_size = FRAMESIZE_CIF;
config.jpeg_quality = 12; //0-63 lower number means higher quality
config.fb_count = 1;
}
esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK)
{
Serial.printf("Camera init failed with error 0x%x", err);
delay(1000);
ESP.restart();
}
// This task handles the POST requests
xTaskCreatePinnedToCore(
task_http2
, "http2_task"
, (1024 * 24) // Stack size
, NULL
, 3 // Priority
, NULL
, ARDUINO_RUNNING_CORE);
Serial.println(F("Task Called"));
}
void loop()
{
// To prohibit the interference between resources, I used main loop to capture the Images
// Check if the posting has been finished
if (is_posted)
{
Serial.println(F("Call to Capture"));
camera_fb_t * fb = NULL;
fb = esp_camera_fb_get();
if(!fb)
{
Serial.println("Camera capture failed");
delay(1000);
ESP.restart();
}
// to check if the size is not bigger than 16K
uint32_t imageLen = fb->len;
if(imageLen<16000)
{
// Creating the body of the post
uint32_t extraLen = tail.length()+head.length();
totalLen = extraLen + imageLen;
uint8_t *fbBuf = fb->buf;
const char* head_char = head.c_str();
const char* tail_char = tail.c_str();
uint32_t totalLen_copy = totalLen;
char alpha[totalLen];
std::copy(head_char,head_char+head.length(), data_to_post);
std::copy(fbBuf,fbBuf+imageLen , data_to_post+head.length());
std::copy(tail_char,tail_char+ tail.length(), data_to_post+head.length()+imageLen);
esp_camera_fb_return(fb);
Serial.println(F("Camera captured"));
delay(100);
safety_counter++;
// Stopping capturing until posting is finished
is_captured = true;
is_posted = false;
}
}
delay(100);
}
int handle_get_response(struct sh2lib_handle *handle, const char *data, size_t len, int flags)
{
if (len > 0)
{
Serial.printf("%.*s\n", len, data);
}
if (flags == DATA_RECV_RST_STREAM)
{
Serial.println("STREAM CLOSED");
}
return 0;
}
int handle_post_response(struct sh2lib_handle *handle, const char *data, size_t len, int flags)
{
if (len > 0) {
Serial.printf("%.*s\n", len, data);
// decreasing the counter to prevent fault loop
safety_counter--;
}
//Serial.print(F("Safety_Counter in Response: ")); Serial.println(safety_counter);
if (flags == DATA_RECV_RST_STREAM) {
request_finished = true;
Serial.println("STREAM CLOSED");
}
return 0;
}
int send_post_data(struct sh2lib_handle *handle, char *buf, size_t length, uint32_t *data_flags)
{
// To check the body of the post
/*
Serial.println("Post Buffer");
for(int i;i<totalLen;i++)
Serial.print(data_to_post[i]);
Serial.println("Post Buffer End");
*/
if (totalLen < length)
{
memcpy(buf, data_to_post, totalLen);
}
else
{
Serial.println("Cannot write to buffer");
//copylen = 0;
}
(*data_flags) |= NGHTTP2_DATA_FLAG_EOF;
return totalLen;
}
void task_http2(void *args)
{
Serial.println(F("Task Runs"));
// Start capturing
is_posted = true;
int counter = 0;
for(;;)
{
// if capturing finished:
if(is_captured)
{
// after each five unsuccessful posts, reestablish the connection
Serial.print(F("Safety_Counter is: ")); Serial.println(safety_counter);
if(safety_counter>5)
{
is_posted = false;
vTaskDelay(100);
counter = 0;
safety_counter = 0;
sh2lib_free(&hd);
vTaskDelay(100);
Serial.println(F("Safety Counter Occured ... "));
if (sh2lib_connect(&hd, "My_Server") != ESP_OK)
{
Serial.println("Error connecting to HTTP2 server");
//vTaskDelete(NULL);
}
Serial.println(F("Connected to the webserver"));
vTaskDelay(1000);
// Preparing capturing again
is_posted = true;
is_captured = false;
continue;
}
char len[20];
sprintf(len, "%d",totalLen); //length_of_body);
Serial.print("the length is: ");
Serial.println(len);
const nghttp2_nv nva[] = { SH2LIB_MAKE_NV(":method", "POST"),
SH2LIB_MAKE_NV(":scheme", "https"),
SH2LIB_MAKE_NV(":authority", hd.hostname),
SH2LIB_MAKE_NV(":path", "/mvp/upload_image"),
SH2LIB_MAKE_NV("Content-Length", len),
SH2LIB_MAKE_NV("Content-Type", "multipart/form-data; boundary=JPEG_IMAGE")
};
sh2lib_do_putpost_with_nv(&hd, nva, sizeof(nva) / sizeof(nva[0]), send_post_data, handle_post_response);
while (1)
{
if (sh2lib_execute(&hd) != ESP_OK)
{
Serial.println("Error in execute");
break;
}
if (request_finished)
{
// a general counter to reestablish the connection
counter++;
break;
}
//vTaskDelay(1000);
}
}
// General counter
if(counter>30)
{
counter = 0;
sh2lib_free(&hd);
vTaskDelay(100);
Serial.println(F("Establishing Connection... "));
if (sh2lib_connect(&hd, "My_Server") != ESP_OK)
{
Serial.println("Error connecting to HTTP2 server");
//vTaskDelete(NULL);
}
Serial.println(F("Connected to the webserver"));
}
is_captured = false;
is_posted = true;
Serial.println("Sending finished");
vTaskDelay(1000);
}
}

How to fix "WiFi is not declared on the scope."?

In my code I am receiving a "Wifi is not declared in this scope" error when compiling to a NodeMCU board. The code has some customization, but regarding the WiFi and lines where it calls Wifi functions, it has the same structure to the source code.
The source code compiles flawless, what let me think that there is no issue with libraries or any kind of updates. I already reviewed my code many times and don't get the error.
Here follows the complete compiling error:
C:\Users\Administrator\Documents\Arduino\teste_watsoniot\teste_watsoniot.ino:
In function 'void setup()':
teste_watsoniot:65:14: error: 'Wifi' was not declared in this scope
if (strcmp(Wifi.SSID().c_str(), ssid) != 0) {
^
teste_watsoniot:73:59: error: 'Wifi' was not declared in this scope
Serial.print("Connected, IP address: ");
Serial.println(Wifi.localIP());
^
exit status 1 'Wifi' was not declared in this scope
Here is the code:
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <SimpleTimer.h>
#include "DHT.h"
/* Wi-Fi Information */
const char* ssid = "xxx";
const char* password = "xxx";
/* Watson Configurations */
#define DEVICE_TYPE "xxx"
#define DEVICE_ID "xxx"
#define ORG "xxx"
#define TOKEN "xxx" // this authentication token given with API key
char server[] = ORG ".messaging.internetofthings.ibmcloud.com";
char topic[] = "iot-2/evt/status/fmt/json"; //"iot-2/type/xxx/id/xxx/evt/1-anl/fmt/json"; // customize type and ID
char authMethod[] = "use-token-auth";
//char authMeth[] = "xxx"; // here a API key
char token[] = TOKEN;
char clientID[] = "d:" ORG ":" DEVICE_TYPE ":" DEVICE_ID;
/* String to send data */
String Str1 = "hum";
String Str2 = "temp";
String Str3 = "ldrValue1";
String Str4 = "soilValue2";
/* Start Wi-Fi */
WiFiClientSecure wifiClient;
PubSubClient client(server, 1833, wifiClient);
/* TIMER */
SimpleTimer timer;
/* DHT22*/
#define DHTPIN D3
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
float hum = 0;
float temp = 0;
/* Soil Moister and LDR */
int sensorPin = A0; // analog input for both sensors
int enable1 = D1; // enable reading Sensor 1
int enable2 = D2; // enable reading Sensor 2
int ldrValue1 = 0;
int soilValue2 = 0;
void setup()
{
Serial.begin(115200); Serial.println();
Serial.print("Conectando na rede "); Serial.print(ssid);
if (strcmp(Wifi.SSID().c_str(), ssid) != 0) {
WiFi.begin(ssid, password);
}
while (WiFi.status() != WL_CONNECTED) {
delay (500);
Serial.print (".");
}
Serial.println("");
Serial.print("Connected, IP address: "); Serial.println(Wifi.localIP());
timer.setInterval(1000L, getDhtData);
pinMode(enable1, OUTPUT);
pinMode(enable2, OUTPUT);
dht.begin();
}
/* Send to cloud */
void enviaDado(float dado1,float dado2, float dado3, float dado4){
String payload = "{\"d\":{\"" + Str1 + "\":";
payload += dado1;
payload += ", \"" + Str2 + "\":";
payload += dado2;
payload += ", \"" + Str3 + "\":";
payload += dado3;
payload += ", \"" + Str4 + "\":";
payload += dado4;
payload += "}}";
Serial.print("Sending payload: ");
Serial.println(payload);
//__ Envia o dado
if (client.publish(topic, (char*) payload.c_str())) {
Serial.println("Publish ok");
} else {
Serial.println("Publish failed");
}
}
void loop()
{
// Sensor DHT22
getDhtData();
// Sensor 1 LDR
digitalWrite(enable1, HIGH);
ldrValue1 = analogRead(sensorPin);
ldrValue1 = constrain(ldrValue1, 300, 850);
ldrValue1 = map(ldrValue1, 300, 850, 0, 1023);
Serial.print("Light intensity: ");
Serial.println(ldrValue1);
digitalWrite(enable1, LOW);
delay(500);
// Sensor 2 SOIL MOISTURE
digitalWrite(enable2, HIGH);
delay(500);
soilValue2 = analogRead(sensorPin);
soilValue2 = constrain(soilValue2, 300, 0);
soilValue2 = map(soilValue2, 300, 0, 0, 100);
Serial.print("Soil moisture: ");
Serial.println(soilValue2);
Serial.println();
delay(500);
digitalWrite(enable2, LOW);
displayData();
delay(2000); // delay for getting DHT22 data
timer.run(); // Initiates SimpleTimer
}
/* Get DHT data */
void getDhtData(void)
{
float tempIni = temp;
float humIni = hum;
temp = dht.readTemperature();
hum = dht.readHumidity();
if (isnan(hum) || isnan(temp)) // Check if any reads failed and exit early (to try again).
{
Serial.println("Failed to read from DHT sensor!");
temp = tempIni;
hum = humIni;
return;
}
}
/* display DHT data */
void displayData(void)
{
Serial.print(" Temperature: ");
Serial.print(temp);
Serial.print("oC Humidity: ");
Serial.print(hum);
Serial.println("%");
}
Here is the source code:
https://github.com/ibm-watson-iot/device-arduino/blob/master/samples/ESP8266MqttSecure/ESP8266MqttSecure.ino

Memory Leak in C and C++ Code

I am trying to return a pointer from a function and use the return in a different function but I am getting memory leak.
The test code which I wrote and detected with memory leak by CPPCheck.
########################################################################
# include < stdio.h >
# include < malloc.h >
# include < string.h >
char* replace ( char* st, char* word, char *replaceWith );
int main ( void )
{
char str[] = "Hello how are ## and what are ## doing ?";
char word[]="##";
char replaceWith[]="you";
printf("%s",replace(str,word,replaceWith));
getchar();
return 0;
}
char* replace(char* st,char* word,char *replaceWith)
{
int i = 0;
char *sr,*s,*ret;
int oldlen;
int count = 0;
int newlen;
int stlen;
s=(char *)malloc(strlen(st) + 1);
strcpy(s, st);
oldlen=strlen(word);
newlen=strlen(replaceWith);
for (i = 0; s[i]! = '\0'; )
{
if( memcmp( &s[i], word, oldlen ) == 0)
{
count++;
i+=oldlen;
}
else
{
i++;
}
}
sr= (char *) malloc (i+1+count*(newlen-oldlen));
ret = (char *) malloc (i+1+count*(newlen-oldlen));
ret=sr;
while(*s)
{
if(memcmp( s, word, oldlen) == 0)
{
memcpy(sr, replaceWith, newlen);
s+ = oldlen;
sr+ = newlen;
}
else
{
*sr++ = *s++;
}
}
*sr = '\0';
return ret;
}
Try this
#include<stdio.h>
#include<malloc.h>
#include<string.h>
char* replace ( char* st, char* word, char *replaceWith );
int main ( void )
{
char str[] = "Hello how are ## and what are ## doing ?";
char word[]="##";
char replaceWith[]="you";
char * ret = replace(str,word,replaceWith);
printf("%s",ret);
free(ret); //freeing the allocated memory
getchar();
return 0;
}
char* replace(char* st,char* word,char *replaceWith)
{
int i = 0;
char *sr,*s,*ret, *temps;
int oldlen;
int count = 0;
int newlen;
int stlen;
s=(char *)malloc(strlen(st) + 1);
temps = s; // storing the address of s in a temp location
strcpy(s, st);
oldlen=strlen(word);
newlen=strlen(replaceWith);
for (i = 0; s[i]!= '\0';)
{
if( memcmp( &s[i], word, oldlen ) == 0)
{
count++;
i+=oldlen;
}
else
{
i++;
}
}
sr= (char *) malloc (i+1+count*(newlen-oldlen));
ret=sr;
while(*s)
{
if(memcmp( s, word, oldlen) == 0)
{
memcpy(sr, replaceWith, newlen);
s += oldlen;
sr += newlen;
}
else
{
*sr++ = *s++;
}
}
*sr = '\0';
free(temps); // freeing the memory allocated for s
return ret;
}
Always free same count with malloc.
free s, sr at end of replace,
use return value of replace instead of direct use on printf
and free return value (return of ret from replace) when not needed.
I have doing lots of experimenting with the memory leak and meanwhile I wrote the following code. Please comment about the pros and cons side of it.
#include <stdio.h>
#include <string.h>
#include <malloc.h>
// Prototype declaration of replaceAll function
static char* replaceAll(char *pSource, char *pWord, char*pWith);
/////////////////////////////////////////////////////////////////////////////
//
// NAME : main
//
// DESCRIPTION : Implementation of main which invokes the replaceAll
// function and displays the output
//
// PARAMETERS : void
//
// RETURNED VALUE : int
//
/////////////////////////////////////////////////////////////////////////////
int main( void )
{
char *finalString = NULL; // To save the base returned address
char srcString[] = "Hello how r you"; // Actual String
char pWord[] = "r"; // Word to be replaced
char pWith[] = "are"; // Word to be replaced with
printf("\n Before Calling the replaceAll function:");
printf("%s",srcString);
printf("\n");
finalString = replaceAll(srcString, pWord, pWith); //calling the replaceAll function
printf("\n After Calling the replaceAll function:");
// Checking if NULL is returned
if( finalString != NULL )
{
//printing the string
printf("%s", finalString);
}
else
{
printf("\n Error: Blank String returned ");
}
return 0;
}
/////////////////////////////////////////////////////////////////////////////
//
// NAME : replaceAll
//
// DESCRIPTION : Implementation of replaceAll function which replaces
// a word in given string with another word
//
// PARAMETERS : char *
//
// RETURNED VALUE : char *
//
/////////////////////////////////////////////////////////////////////////////
static char* replaceAll(char *pSource, char *pWord, char*pWith)
{
char *pSt = NULL; // Pointer to the source String to avoid modifying the pSource
char *pTarget = NULL; // Target pointer to be malloced
char *pTg = NULL; // Pointer to the target string
int count; // Counter
int nWord = strlen (pWord); // length of the word which needs to be replaced
int nWith = strlen (pWith); // length of the word with which the word needs to be replaced
static const char nullP = '\0'; // null character
int szTarget = 0;
// Assigning the base address of the pSource to a temporary and iterate through
for ( pSt = pSource, count = 0; *pSt != nullP; pSt++ )
{
// Count number of occurances of the Word in the String to calculate the length of the final string
if( memcmp( pSt, pWord, nWord ) == 0)
{
count++;
pSt += nWord-1;
}
}
// Calculate the required target Size
szTarget = strlen (pSource) + count * (nWith - nWord) + sizeof (nullP);
// Allocate memory for the target string
pTarget = (char *)malloc(szTarget);
// Check if the malloc function returns sucessfully
if ( pTarget != NULL)
{
// Copying the string with replacement
for (pTg = pTarget, pSt = pSource; *pSt != nullP; )
{
if( memcmp (pSt, pWord, nWord) == 0)
{
memcpy (pTg,pWith,nWith);
pSt += nWord;
pTg += nWith;
}
else
{
*pTg++ = *pSt++;
}
}
// Assigning NULL Character to the target string after copying
*pTg = '\0';
}
return pTarget;
}

A question of libevent example code: how is invoked?

I'm learning libev however the code is so hard to understand, so I choose to learn libevent first whose code is relatively clearer. But I encounter a problem when try the example (http://www.wangafu.net/~nickm/libevent-book/01_intro.html).
How is the code event_add(state->write_event, NULL) in do_read() make do_write() function invoked?
/* For sockaddr_in */
#include <netinet/in.h>
/* For socket functions */
#include <sys/socket.h>
/* For fcntl */
#include <fcntl.h>
#include <event2/event.h>
#include <assert.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#define MAX_LINE 16384
void do_read(evutil_socket_t fd, short events, void *arg);
void do_write(evutil_socket_t fd, short events, void *arg);
char
rot13_char(char c)
{
return c;
/* We don't want to use isalpha here; setting the locale would change
* which characters are considered alphabetical. */
if ((c >= 'a' && c <= 'm') || (c >= 'A' && c <= 'M'))
return c + 13;
else if ((c >= 'n' && c <= 'z') || (c >= 'N' && c <= 'Z'))
return c - 13;
else
return c;
}
struct fd_state {
char buffer[MAX_LINE];
size_t buffer_used;
size_t n_written;
size_t write_upto;
struct event *read_event;
struct event *write_event;
};
struct fd_state *
alloc_fd_state(struct event_base *base, evutil_socket_t fd)
{
struct fd_state *state = malloc(sizeof(struct fd_state));
if (!state)
return NULL;
state->read_event = event_new(base, fd, EV_READ|EV_PERSIST, do_read, state);
if (!state->read_event) {
free(state);
return NULL;
}
state->write_event =
event_new(base, fd, EV_WRITE|EV_PERSIST, do_write, state);
if (!state->write_event) {
event_free(state->read_event);
free(state);
return NULL;
}
state->buffer_used = state->n_written = state->write_upto = 0;
assert(state->write_event);
return state;
}
void
free_fd_state(struct fd_state *state)
{
event_free(state->read_event);
event_free(state->write_event);
free(state);
}
void
do_read(evutil_socket_t fd, short events, void *arg)
{
struct fd_state *state = arg;
char buf[1024];
int i;
ssize_t result;
while (1) {
assert(state->write_event);
result = recv(fd, buf, sizeof(buf), 0);
if (result <= 0)
break;
for (i=0; i < result; ++i) {
if (state->buffer_used < sizeof(state->buffer))
state->buffer[state->buffer_used++] = rot13_char(buf[i]);
if (buf[i] == '\n') {
assert(state->write_event);
**event_add(state->write_event, NULL);**
state->write_upto = state->buffer_used;
}
}
}
if (result == 0) {
free_fd_state(state);
} else if (result < 0) {
if (errno == EAGAIN) // XXXX use evutil macro
return;
perror("recv");
free_fd_state(state);
}
}
void
**do_write(evutil_socket_t fd, short events, void *arg)**
{
struct fd_state *state = arg;
while (state->n_written < state->write_upto) {
ssize_t result = send(fd, state->buffer + state->n_written,
state->write_upto - state->n_written, 0);
if (result < 0) {
if (errno == EAGAIN) // XXX use evutil macro
return;
free_fd_state(state);
return;
}
assert(result != 0);
state->n_written += result;
}
if (state->n_written == state->buffer_used)
state->n_written = state->write_upto = state->buffer_used = 1;
event_del(state->write_event);
}
void
do_accept(evutil_socket_t listener, short event, void *arg)
{
struct event_base *base = arg;
struct sockaddr_storage ss;
socklen_t slen = sizeof(ss);
int fd = accept(listener, (struct sockaddr*)&ss, &slen);
if (fd < 0) { // XXXX eagain??
perror("accept");
} else if (fd > FD_SETSIZE) {
close(fd); // XXX replace all closes with EVUTIL_CLOSESOCKET */
} else {
struct fd_state *state;
evutil_make_socket_nonblocking(fd);
state = alloc_fd_state(base, fd);
assert(state); /*XXX err*/
assert(state->write_event);
event_add(state->read_event, NULL);
}
}
void
run(void)
{
evutil_socket_t listener;
struct sockaddr_in sin;
struct event_base *base;
struct event *listener_event;
base = event_base_new();
if (!base)
return; /*XXXerr*/
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = 0;
sin.sin_port = htons(40713);
listener = socket(AF_INET, SOCK_STREAM, 0);
evutil_make_socket_nonblocking(listener);
#ifndef WIN32
{
int one = 1;
setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
}
#endif
if (bind(listener, (struct sockaddr*)&sin, sizeof(sin)) < 0) {
perror("bind");
return;
}
if (listen(listener, 16)<0) {
perror("listen");
return;
}
listener_event = event_new(base, listener, EV_READ|EV_PERSIST, do_accept, (void*)base);
/*XXX check it */
event_add(listener_event, NULL);
event_base_dispatch(base);
}
int
main(int c, char **v)
{
setvbuf(stdout, NULL, _IONBF, 0);
run();
return 0;
}
I'm not sure if I'm answering the same question you asked - I understand it as:
How does calling event_add(state->write_event, NULL) in do_read() lead to do_write() being invoked?
The key to figuring this out is understanding what the do_read() function is actually doing. do_read() is a callback function associated with a socket which has data to be read: this is set up with allocate_fd_state():
struct fd_state *
alloc_fd_state(struct event_base *base, evutil_socket_t fd)
{
/*
* Allocate a new fd_state structure, which will hold our read and write events
* /
struct fd_state *state = malloc(sizeof(struct fd_state));
[...]
/*
* Initialize a read event on the given file descriptor: associate the event with
* the given base, and set up the do_read callback to be invoked whenever
* data is available to be read on the file descriptor.
* /
state->read_event = event_new(base, fd, EV_READ|EV_PERSIST, do_read, state);
[...]
/*
* Set up another event on the same file descriptor and base, which invoked the
* do_write callback anytime the file descriptor is ready to be written to.
*/
state->write_event =
event_new(base, fd, EV_WRITE|EV_PERSIST, do_write, state);
[...]
return state;
}
At this point, though, neither of these events have been event_add()'ed to the event_base base. The instructions for what to do are all written out, but no one is looking at them. So how does anything get read? state->read_event is event_add()'ed to the base after an incoming connection is made. Look at do_accept():
void
do_accept(evutil_socket_t listener, short event, void *arg)
{
[ ... accept a new connection and give it a file descriptor fd ... ]
/*
* If the file descriptor is invalid, close it.
*/
if (fd < 0) { // XXXX eagain??
perror("accept");
} else if (fd > FD_SETSIZE) {
close(fd); // XXX replace all closes with EVUTIL_CLOSESOCKET */
/*
* Otherwise, if the connection was successfully accepted...
*/
} else {
[ ... allocate a new fd_state structure, and make the file descriptor non-blocking ...]
/*
* Here's where the magic happens. The read_event created back in alloc_fd_state()
* is finally added to the base associated with it.
*/
event_add(state->read_event, NULL);
}
}
So right after accepting a new connection, the program tells libevent to wait until there's data available on the connection, and then run the do_read() callback. At this point, it's still impossible for do_write() to be called. It needs to be event_add()'ed. This happens in do_read():
void
do_read(evutil_socket_t fd, short events, void *arg)
{
/* Create a temporary buffer to receive some data */
char buf[1024];
while (1) {
[ ... Receive the data, copying it into buf ... ]
[ ... if there is no more data to receive, or there was an error, exit this loop... ]
[ ... else, result = number of bytes received ... ]
for (i=0; i < result; ++i) {
[ ... if there's room in the buffer, copy in the rot13() encoded
version of the received data ... ]
/*
* Boom, headshot. If we've reached the end of the incoming data
* (assumed to be a newline), then ...
*/
if (buf[i] == '\n') {
[...]
/*
* Have libevent start monitoring the write_event, which calls do_write
* as soon as the file descriptor is ready to be written to.
*/
event_add(state->write_event, NULL);
[...]
}
}
}
[...]
}
So, after reading in some data from a file descriptor, the program starts waiting until
the file descriptor is ready to be written to, and then invokes do_write(). Program
flow looks like this:
[ set up an event_base and start waiting for events ]
[ if someone tries to connect ]
[ accept the connection ]
[ ... wait until there is data to read on the connection ... ]
[ read in data from the connection until there is no more left ]
[ ....wait until the connection is ready to be written to ... ]
[ write out our rot13() encoded response ]
I hope that a) that was the correct interpretation of your question, and b) this was a helpful answer.

Resources