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

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);
}
}

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 convert an image file to base64 string using Arduino UNO or using any other Microcontroller?

Suppose I am in a room which is totally locked and I am begging for the key, so I can go outside. But the person who locked the door behind me is asking to solve a problem for him. The problem is that I have an SD card, SD card module, Arduino UNO, power, a laptop with internet access. What I need to do for the person is that I have to convert an image file stored in the SD card to a base64 string using the Arduino. Now I want to know how to this task for the person, so I can go out freely. Kindly remember the title of this question, otherwise, my life is in danger, and please avoid suggestions only. If you have done this before, then you might answer the question, otherwise please do not. Sorry for being harsh, but it is really bad to have a bad answer. StackOverflow is my last hope.
I have used a library called base64 for Arduino, but I didn't solve my problem. Here is the library. https://github.com/adamvr/arduino-base64
My aim was to convert image to the Base64 string format and then send this string through ESP8266 module to the webserver.
Until now, I didn't find any solution to this problem. I found an alternative to send images taken by a camera. That alternative is a camera module with ESP32-S. This module is "ESP32-S Cam", which takes pictures and sends them to an online webserver.
Here is the code for ESP32 Cam for taking and sending picture to the server where we will have a PHP Scrip given under this code.
#include "esp_http_client.h"
#include "esp_camera.h"
#include <WiFi.h>
#include "Arduino.h"
const char* ssid = "ashiq"; // my wifi "SSID" name
const char* password = "11585858"; // my wifi Password
int capture_interval = 20000; // Microseconds between captures
const char *post_url = "http://app.softwarism.com/esp32/getPhoto.php"; // Location where images are POSTED
bool internet_connected = false;
long current_millis;
long last_capture_millis = 0;
//for indicating that the picture has been taken and then sent
#define GPIO_PIN_WAKEUP GPIO_NUM_12
// 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
void setup()
{
Serial.begin(115200);
//Setup indication pin Mode
pinMode(GPIO_PIN_WAKEUP,OUTPUT);
if (init_wifi()) { // Connected to WiFi
internet_connected = true;
Serial.println("Internet connected");
}
camera_config_t config;
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_UXGA;
config.jpeg_quality = 10;
config.fb_count = 2;
} else {
config.frame_size = FRAMESIZE_SVGA;
config.jpeg_quality = 12;
config.fb_count = 1;
}
// camera init
esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) {
Serial.printf("Camera init failed with error 0x%x", err);
return;
}
}
bool init_wifi()
{
int connAttempts = 0;
Serial.println("\r\nConnecting to: " + String(ssid));
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED ) {
delay(500);
Serial.print(".");
if (connAttempts > 10) return false;
connAttempts++;
}
return true;
}
esp_err_t _http_event_handler(esp_http_client_event_t *evt)
{
switch (evt->event_id) {
case HTTP_EVENT_ERROR:
Serial.println("HTTP_EVENT_ERROR");
break;
case HTTP_EVENT_ON_CONNECTED:
Serial.println("HTTP_EVENT_ON_CONNECTED");
break;
case HTTP_EVENT_HEADER_SENT:
Serial.println("HTTP_EVENT_HEADER_SENT");
break;
case HTTP_EVENT_ON_HEADER:
Serial.println();
Serial.printf("HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value);
break;
case HTTP_EVENT_ON_DATA:
Serial.println();
Serial.printf("HTTP_EVENT_ON_DATA, len=%d", evt->data_len);
if (!esp_http_client_is_chunked_response(evt->client)) {
// Write out data
// printf("%.*s", evt->data_len, (char*)evt->data);
}
break;
case HTTP_EVENT_ON_FINISH:
Serial.println("");
Serial.println("HTTP_EVENT_ON_FINISH");
break;
case HTTP_EVENT_DISCONNECTED:
Serial.println("HTTP_EVENT_DISCONNECTED");
break;
}
return ESP_OK;
}
static esp_err_t take_send_photo()
{
Serial.println("Taking picture...");
camera_fb_t * fb = NULL;
esp_err_t res = ESP_OK;
fb = esp_camera_fb_get();
if (!fb) {
Serial.println("Camera capture failed");
return ESP_FAIL;
}else{
indication();
}
esp_http_client_handle_t http_client;
esp_http_client_config_t config_client = {0};
config_client.url = post_url;
config_client.event_handler = _http_event_handler;
config_client.method = HTTP_METHOD_POST;
http_client = esp_http_client_init(&config_client);
esp_http_client_set_post_field(http_client, (const char *)fb->buf, fb->len);
esp_http_client_set_header(http_client, "Content-Type", "image/jpg");
esp_err_t err = esp_http_client_perform(http_client);
if (err == ESP_OK) {
Serial.print("esp_http_client_get_status_code: ");
Serial.println(esp_http_client_get_status_code(http_client));
}
esp_http_client_cleanup(http_client);
esp_camera_fb_return(fb);
}
void loop()
{
// TODO check Wifi and reconnect if needed
current_millis = millis();
if (current_millis - last_capture_millis > capture_interval) { // Take another picture
last_capture_millis = millis();
take_send_photo();
//indicate that the picture has been taken and sent
indication();
}
}
void indication(){
digitalWrite(GPIO_PIN_WAKEUP,HIGH);
delay(1000);
digitalWrite(GPIO_PIN_WAKEUP,LOW);
}
Here is the PHP Script waiting to get the picture sent by the camera.
<?php
require_once("con.php");
$received = file_get_contents('php://input');
$fileToWrite = "uploads/smart_tick_".time().".jpg";
if(file_put_contents($fileToWrite, $received)){
echo "Uploaded";
}
?>
Note: Do not forget to create a folder "uploads" in the same directory where the PHP Script is.

I am writing a code to read DHT11 value and control 4 relay but temp. sensor is showing me "nan" everytime

I am making a project on home automation with temperature reading using NodeMCU (ESP8266-12E). I am using a DHT11 sensor with DHT11.h library, but my temperature sensor is showing me "nan" instead of any value. I don't know where I am lagging.
My code is given below:
#include "DHT.h" // including the library of DHT11 temperature and humidity sensor
#define DHTTYPE DHT11 // DHT 11
#include <ESP8266WiFi.h>
#include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_Client.h"
#define Relay1 D1
#define Relay2 D2
#define Relay3 D3
#define Relay4 D4
#define DHTPIN D0
DHT dht(DHTPIN, DHTTYPE);
float temp_f;
String webString = "";
unsigned long previousMillis = 0;
const long interval = 2300;
#define WLAN_SSID "internet" // Your SSID
#define WLAN_PASS "*********" // Your password
/************************* Adafruit.io Setup *********************************/
#define AIO_SERVER "io.adafruit.com" //Adafruit Server
#define AIO_SERVERPORT 1883
#define AIO_USERNAME "foo" // Username
#define AIO_KEY "bar" // Auth Key
//WIFI CLIENT
WiFiClient client;
Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);
// Setup a feed called 'photocell' for publishing.
// Notice MQTT paths for AIO follow the form: <username>/feeds/<feedname>
const char TEMP_FEED[] PROGMEM = AIO_USERNAME "/feeds/photocell";
Adafruit_MQTT_Publish photocell = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME"/feeds/photocell");
Adafruit_MQTT_Subscribe Light1 = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME"/feeds/Relay1"); // Feeds name should be same everywhere
Adafruit_MQTT_Subscribe Light2 = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME"/feeds/Relay2");
Adafruit_MQTT_Subscribe Light3 = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME"/feeds/Relay3");
Adafruit_MQTT_Subscribe Light4 = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME"/feeds/Relay4");
void MQTT_connect();
void setup()
{
Serial.begin(115200);
delay(10);
dht.begin();
// Print temperature sensor details.
pinMode(Relay1, OUTPUT);
pinMode(Relay2, OUTPUT);
pinMode(Relay3, OUTPUT);
pinMode(Relay4, OUTPUT);
// Connect to WiFi access point.
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(WLAN_SSID);
WiFi.begin(WLAN_SSID, WLAN_PASS);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println();
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
temp_f = dht.readTemperature(true);
Serial.println();
Serial.print("Initial Temp: ");
Serial.println(temp_f);
Serial.println();
mqtt.subscribe(&Light1);
mqtt.subscribe(&Light3);
mqtt.subscribe(&Light2);
mqtt.subscribe(&Light4);
}
int delayTime = 300000; //Wait 5 minutes before sending data to web
int startDelay = 0;
void loop()
{
MQTT_connect();
if (millis() - startDelay < delayTime) {
Serial.println("waiting delaytime");
}
else {
temp_f = dht.readTemperature(true); //Get temp in Farenheit
startDelay = millis();
Serial.print(F("\nSending temp: "));
Serial.print(temp_f);
Serial.print("...");
if (!photocell.publish(temp_f)) { //Publish to Adafruit
Serial.println(F("Failed"));
}
else {
Serial.println(F("Sent!"));
}
}
/* //int t = dht.readTemperature(true);
// t = t/100000000;
Serial.print(F("\nSending photocell val "));
Serial.print(t);
Serial.print("...");
if (! photocell.publish(t)) {
Serial.println(F("Failed"));
} else {
Serial.println(F("OK!"));
}*/
Adafruit_MQTT_Subscribe* subscription;
while ((subscription = mqtt.readSubscription(2000))) {
if (subscription == &Light1) {
Serial.print(F("Got: "));
Serial.println((char*)Light1.lastread);
int Light1_State = atoi((char*)Light1.lastread);
digitalWrite(Relay1, Light1_State);
}
if (subscription == &Light2) {
Serial.print(F("Got: "));
Serial.println((char*)Light2.lastread);
int Light2_State = atoi((char*)Light2.lastread);
digitalWrite(Relay2, Light2_State);
}
if (subscription == &Light3) {
Serial.print(F("Got: "));
Serial.println((char*)Light3.lastread);
int Light3_State = atoi((char*)Light3.lastread);
digitalWrite(Relay3, Light3_State);
}
if (subscription == &Light4) {
Serial.print(F("Got: "));
Serial.println((char*)Light4.lastread);
int Light4_State = atoi((char*)Light4.lastread);
digitalWrite(Relay4, Light4_State);
}
}
// this is our 'wait for incoming subscription packets and callback em' busy subloop
// try to spend your time here:
mqtt.processPackets(500);
}
void MQTT_connect()
{
int8_t ret;
if (mqtt.connected()) {
return;
}
Serial.print("Connecting to MQTT... ");
uint8_t retries = 3;
while ((ret = mqtt.connect()) != 0) {
Serial.println(mqtt.connectErrorString(ret));
Serial.println("Retrying MQTT connection in 5 seconds...");
mqtt.disconnect();
delay(5000);
retries--;
if (retries == 0) {
while (1);
}
}
Serial.println("MQTT Connected!");
}
you try to read temperature and humidity in setup(). but you need to wait 2s at minima after the dht.begin and before reading, because Sensor readings may also be up to 2 seconds
so add delay(2000) before the first reading..

arduino uno + wifishield cannot connect bluemix using token

I have arduino uno + wifishield and if fails to connect to Bluemix. It gives this error:
"Closed connection from 194.228.11.222. The operation is not authorized."
Any idea why the connection gets kicked out? What operation is not authorized?
Thanks for any idea ;)
======
Here is the code:
#include <SPI.h>
#include <Ethernet.h>
#include <WiFi.h>
#include <WifiIPStack.h>
#include <IPStack.h>
#include <Countdown.h>
#include <MQTTClient.h>
#define MQTT_MAX_PACKET_SIZE 100
#define SIZE 100
#define MQTT_PORT 1883
#define PUBLISH_TOPIC "iot-2/evt/status/fmt/json"
#define SUBSCRIBE_TOPIC "iot-2/cmd/+/fmt/json"
#define USERID "use-token-auth"
#define CLIENT_ID "d:6735ra:hlinoponie:petasek"
#define MS_PROXY "6735ra.messaging.internetofthings.ibmcloud.com"
#define AUTHTOKEN “xxxxx”
byte mac[] = { 0x90, 0xA2, 0xDA, 0x0F, 0xD6, 0x8F };
WiFiClient c;
IPStack ipstack(c);
MQTT::Client<IPStack, Countdown, 100, 1> client = MQTT::Client<IPStack, Countdown, 100, 1>(ipstack);
String deviceEvent;
char ssid[] = “XXXXX”; // your network SSID (name)
char pass[] = “XXXXX”; // your network password
int status = WL_IDLE_STATUS; // the Wifi radio's status
void setup() {
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("WiFi shield not present");
// don't continue:
while (true);
}
String fv = WiFi.firmwareVersion();
if ( fv != "1.1.0" )
Serial.println("Please upgrade the firmware");
// attempt to connect to Wifi network:
while ( status != WL_CONNECTED) {
Serial.print("Attempting to connect to WPA SSID: ");
Serial.println(ssid);
// Connect to WPA/WPA2 network:
status = WiFi.begin(ssid, pass);
// wait 5 seconds for connection:
delay(5000);
}
// you're connected now, so print out the data:
Serial.print("Hooray!!! You're connected to the network\n");
}
void loop() {
float tep = mojeDHT.readTemperature();
float vlh = mojeDHT.readHumidity();
int rc = -1;
if (!client.isConnected()) {
Serial.println("Connecting to Watson IoT Foundation ...");
rc = ipstack.connect((char*)MS_PROXY, MQTT_PORT);
MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
data.MQTTVersion = 3;
data.clientID.cstring = (char*)CLIENT_ID;
data.username.cstring = (char*)USERID;
data.password.cstring = (char*)AUTHTOKEN;
data.keepAliveInterval = 60;
rc = -1;
while ((rc = client.connect(data)) != 0) {
Serial.println("rc=");
Serial.println(rc);
delay(2000);
}
Serial.println("Connected successfully\n");
// Serial.println("Temperature(in C)\tDevice Event (JSON)");
Serial.println("____________________________________________________________________________");
}
Serial.println("\n");
MQTT::Message message;
message.qos = MQTT::QOS0;
message.retained = false;
deviceEvent = String("{\"d\":{\"myName\":\"Arduino Uno\",\"temperature\":");
char buffer[60];
// convert double to string
dtostrf(getTemp(),1,2, buffer);
deviceEvent += buffer;
deviceEvent += "}}";
Serial.print("\t");
Serial.print(buffer);
Serial.print("\t\t");
deviceEvent.toCharArray(buffer, 60);
Serial.println(buffer);
message.payload = buffer;
message.payloadlen = strlen(buffer);
rc = client.publish(PUBLISH_TOPIC, message);
if (rc != 0) {
Serial.print("return code from publish was ");
Serial.println(rc);
}
client.yield(5000);
}
/*
This function is reproduced as is from Arduino site => http://playground.arduino.cc/Main/InternalTemperatureSensor
*/
double getTemp(void) {
unsigned int wADC;
double t;
ADMUX = (_BV(REFS1) | _BV(REFS0) | _BV(MUX3));
ADCSRA |= _BV(ADEN); // enable the ADC
delay(20); // wait for voltages to become stable.
ADCSRA |= _BV(ADSC); // Start the ADC
// Detect end-of-conversion
while (bit_is_set(ADCSRA,ADSC));
// Reading register "ADCW" takes care of how to read ADCL and ADCH.
wADC = ADCW;
// The offset of 324.31 could be wrong. It is just an indication.
t = (wADC - 324.31 ) / 1.22;
// The returned temperature is in degrees Celcius.
return (t);
}
It might be the case your organizations is configured to block non-secure connections (since you are using port 1883). Check the step 5 on this recipe
https://developer.ibm.com/recipes/tutorials/connect-an-arduino-uno-device-to-the-ibm-internet-of-things-foundation/
I noticed this error in the log: The topic is not valid: Topic="lwt" ClientID="d:6735ra:hlinoponie:petasek" Reason="The topic does not match an allowed rule".
I didn't see that topic listed in your code, but you may want to check to see how that may be getting set as topic.

Use AudioQueue to play AAC, but the callback function doesn't work

Recently, my project wants to achieving audio communication by AAC, so i use the AudioQueue, but there is a problem that my player's callback function doesn't work, in my project the callback function has worked 3 times. that is for function work 3 times. and when active AudioQueueStart(mQueue, NULL), the callback function never be called.
I use two iPhone to run. they are connect by udp socket, and i'm sure this part is fine. i can get the correct audio data.
And i modify a demo which is play a file data not memory. so i don't know is it a problem?
here is my code: AQPlayer.h
#include <AudioToolbox/AudioToolbox.h>
#include "CAStreamBasicDescription.h"
#include "CAXException.h"
#define kNumberBuffers 3
#define kBufferDurationSeconds 0.5
class AQPlayer
{
public:
AQPlayer();
~AQPlayer();
OSStatus StartQueue(BOOL inResume);
OSStatus StopQueue();
OSStatus PauseQueue();
AudioQueueRef Queue() { return mQueue; }
CAStreamBasicDescription DataFormat() const { return mDataFormat; }
Boolean IsRunning() const { return (mIsRunning) ? true : false; }
Boolean IsInitialized() const { return mIsInitialized; }
CFStringRef GetFilePath() const { return (mFilePath) ? mFilePath : CFSTR(""); }
Boolean IsLooping() const { return mIsLooping; }
void SetLooping(Boolean inIsLooping) { mIsLooping = inIsLooping; }
void CreateQueueForFile(CFStringRef inFilePath);
void DisposeQueue(Boolean inDisposeFile);
void prepareAudioQueue();
void start();
void stop();
private:
UInt32 GetNumPacketsToRead() { return mNumPacketsToRead; }
SInt64 GetCurrentPacket() { return mCurrentPacket; }
AudioFileID GetAudioFileID() { return mAudioFile; }
void SetCurrentPacket(SInt64 inPacket) { mCurrentPacket = inPacket; }
void SetupNewQueue();
AudioQueueRef mQueue;
AudioQueueBufferRef mBuffers[kNumberBuffers];
AudioFileID mAudioFile;
CFStringRef mFilePath;
CAStreamBasicDescription mDataFormat;
Boolean mIsInitialized;
UInt32 mNumPacketsToRead;
SInt64 mCurrentPacket;
UInt32 mIsRunning;
Boolean mIsDone;
Boolean mIsLooping;
static void isRunningProc( void * inUserData,
AudioQueueRef inAQ,
AudioQueuePropertyID inID);
static void AQBufferCallback( void * inUserData,
AudioQueueRef inAQ,
AudioQueueBufferRef inCompleteAQBuffer);
void CalculateBytesForTime( CAStreamBasicDescription & inDesc,
UInt32 inMaxPacketSize,
Float64 inSeconds,
UInt32 *outBufferSize,
UInt32 *outNumPackets);
};
and here is AQPlayer.mm
#include "package.h"
#include "udpsocket.h"
#define MAXPACKETSIZE 1000
#define BUFFER_SIZE 4000
#include "AQPlayer.h"
extern udpsocket *udp;
void AQPlayer::AQBufferCallback(void * inUserData,
AudioQueueRef inAQ,
AudioQueueBufferRef inCompleteAQBuffer)
{
AQPlayer *THIS = (AQPlayer *)inUserData;
dispatch_semaphore_wait(udp->sempahore,DISPATCH_TIME_FOREVER);
NSLog(#"read begin");
while ([udp->AudioQueue count]>0 &&
![[udp->AudioQueue objectAtIndex:0] isKindOfClass:[AUDIO_CACHE_OBJECT class]])
{
[udp->AudioQueue removeObjectAtIndex:0];
}
if([udp->AudioQueue count]<1){
[NSThread sleepForTimeInterval:0.05];
AQBufferCallback(inUserData, inAQ, inCompleteAQBuffer);
return;
}
int packets = 0;
int dataLen = 0;
AUDIO_CACHE_OBJECT *pack;
char *data = (char*)malloc(sizeof(char)*BUFFER_SIZE);;
memset(data, 0, BUFFER_SIZE);
pack = [udp->AudioQueue firstObject];
while (dataLen+pack.datalen<BUFFER_SIZE && [udp->AudioQueue count]>0 /*&& packets<21*/) {
memcpy(data+dataLen, [pack GetData], [pack datalen]);
dataLen+=[pack datalen];
[udp->AudioQueue removeObjectAtIndex:0];
// [pack memset];
packets ++;
while ([udp->AudioQueue count]>1 &&
![[udp->AudioQueue objectAtIndex:0] isKindOfClass:[AUDIO_CACHE_OBJECT class]])
{
[udp->AudioQueue removeObjectAtIndex:0];
}
if([udp->AudioQueue count]<1){
break;
}
pack = [udp->AudioQueue firstObject];
}
memcpy(inCompleteAQBuffer->mAudioData, data, dataLen);
inCompleteAQBuffer->mAudioDataByteSize = dataLen;
inCompleteAQBuffer->mPacketDescriptionCount = packets;
AudioQueueEnqueueBuffer(inAQ, inCompleteAQBuffer, 0,NULL);
THIS->mCurrentPacket += packets;
free(data);
NSLog(#"read end --- %lld",THIS->mCurrentPacket);
}
void AQPlayer::isRunningProc ( void * inUserData,
AudioQueueRef inAQ,
AudioQueuePropertyID inID)
{
AQPlayer *THIS = (AQPlayer *)inUserData;
UInt32 size = sizeof(THIS->mIsRunning);
OSStatus result = AudioQueueGetProperty (inAQ, kAudioQueueProperty_IsRunning, &THIS->mIsRunning, &size);
if ((result == noErr) && (!THIS->mIsRunning))
[[NSNotificationCenter defaultCenter] postNotificationName: #"playbackQueueStopped" object: nil];
}
void AQPlayer::CalculateBytesForTime (CAStreamBasicDescription & inDesc, UInt32 inMaxPacketSize, Float64 inSeconds, UInt32 *outBufferSize, UInt32 *outNumPackets)
{
// we only use time here as a guideline
// we're really trying to get somewhere between 16K and 64K buffers, but not allocate too much if we don't need it
static const int maxBufferSize = 0x10000; // limit size to 64K
static const int minBufferSize = 0x4000; // limit size to 16K
if (inDesc.mFramesPerPacket) {
Float64 numPacketsForTime = inDesc.mSampleRate / inDesc.mFramesPerPacket * inSeconds;
*outBufferSize = numPacketsForTime * inMaxPacketSize;
} else {
// if frames per packet is zero, then the codec has no predictable packet == time
// so we can't tailor this (we don't know how many Packets represent a time period
// we'll just return a default buffer size
*outBufferSize = maxBufferSize > inMaxPacketSize ? maxBufferSize : inMaxPacketSize;
}
// we're going to limit our size to our default
if (*outBufferSize > maxBufferSize && *outBufferSize > inMaxPacketSize)
*outBufferSize = maxBufferSize;
else {
// also make sure we're not too small - we don't want to go the disk for too small chunks
if (*outBufferSize < minBufferSize)
*outBufferSize = minBufferSize;
}
*outNumPackets = *outBufferSize / inMaxPacketSize;
}
AQPlayer::AQPlayer() :
mQueue(0),
mAudioFile(0),
mFilePath(NULL),
mIsRunning(false),
mIsInitialized(false),
mNumPacketsToRead(0),
mCurrentPacket(0),
mIsDone(false),
mIsLooping(false) { }
AQPlayer::~AQPlayer()
{
DisposeQueue(true);
}
OSStatus AQPlayer::StartQueue(BOOL inResume)
{
if (mQueue == NULL)
CreateQueueForFile(mFilePath);
mIsDone = false;
if (!inResume)
mCurrentPacket = 0;
for (int i = 0; i < kNumberBuffers; ++i) {
AQBufferCallback (this, mQueue, mBuffers[i]);
}
NSLog(#"audioqueuestart");
UInt32 i =0;
AudioQueuePrime(mQueue, 0, &i);
NSLog(#"%d",(unsigned int)i);
return AudioQueueStart(mQueue, NULL);
}
OSStatus AQPlayer::StopQueue()
{
OSStatus result = AudioQueueStop(mQueue, true);
if (result) printf("ERROR STOPPING QUEUE!\n");
return result;
}
OSStatus AQPlayer::PauseQueue()
{
OSStatus result = AudioQueuePause(mQueue);
return result;
}
void AQPlayer::CreateQueueForFile(CFStringRef inFilePath)
{
try {
UInt32 size = sizeof(mDataFormat);
mDataFormat.mSampleRate = 44100;
mDataFormat.mFormatID = kAudioFormatMPEG4AAC;
mDataFormat.mFormatFlags = 0;
mDataFormat.mFramesPerPacket = 1024;
mDataFormat.mChannelsPerFrame = 2;
mDataFormat.mBitsPerChannel = 0;//表示这是一个压缩格式
mDataFormat.mBytesPerPacket = 0;//表示这是一个变比特率压缩
mDataFormat.mBytesPerFrame = 0;
mDataFormat.mReserved = 0;
//aqc.bufferByteSize = 2000;
SetupNewQueue();
}
catch (NSException *e) {
fprintf(stderr, "Error: %# (%#)\n", [e debugDescription], [e description]);
}
}
void AQPlayer::SetupNewQueue()
{
AudioQueueNewOutput(&mDataFormat, AQPlayer::AQBufferCallback, this,//NULL,NULL,0,&mQueue);
CFRunLoopGetCurrent(), kCFRunLoopCommonModes, 0, &mQueue);
UInt32 bufferByteSize;
UInt32 maxPacketSize = MAXPACKETSIZE;
UInt32 size = sizeof(maxPacketSize);
CalculateBytesForTime (mDataFormat, maxPacketSize, kBufferDurationSeconds, &bufferByteSize, &mNumPacketsToRead);
size = sizeof(UInt32);
AudioQueueAddPropertyListener(mQueue, kAudioQueueProperty_IsRunning, isRunningProc, this);
bool isFormatVBR = (mDataFormat.mBytesPerPacket == 0 || mDataFormat.mFramesPerPacket == 0);
AudioQueueSetParameter(mQueue, kAudioQueueParam_Volume, 1.0);
for (int i = 0; i < kNumberBuffers; ++i) {
AudioQueueAllocateBuffer(mQueue, bufferByteSize, &mBuffers[i]);
}
// set the volume of the queue
mIsInitialized = true;
}
void AQPlayer::DisposeQueue(Boolean inDisposeFile)
{
if (mQueue)
{
AudioQueueDispose(mQueue, true);
mQueue = NULL;
}
if (inDisposeFile)
{
if (mAudioFile)
{
AudioFileClose(mAudioFile);
mAudioFile = 0;
}
if (mFilePath)
{
CFRelease(mFilePath);
mFilePath = NULL;
}
}
mIsInitialized = false;
}
Thank for your time.
Your input is VBR so your buffers need an accompanying packet description array. Use AudioQueueAllocateBufferWithPacketDescriptions: instead of AudioQueueAllocateBuffer: when you are initially creating your buffers. Then set mStartOffset, mDataByteSize, and mVariableFramesInPacket (always zero) for each packet inside your while loop in your callback procedure.

Resources