Cannot connect to ESP32 http page - c++

ESP32S NodeMCU
VSCode with PlatformIO
Hey all,
Apologies if I get terms wrong, this is my first time with an ESP32 and webservers. I'm developing code for an amateur ESP32 project that involves connection to an http page. I have set up an if-else loop that reads the ending of the webserver url to set the waterState variable. The ESP32 will connect to my WiFi network with no issue. However, my computer will not connect to the url. The result should print out the state chosen (ex: morning) and the terminal will indicate that the function has completed execution.
I tried moving around the WiFiClient and WiFiServer instances but that hasn't worked. I was able to get this program working once before when I kept the ScheduleProt code inside the WiFi connect. I tried that replicating that again but it now isn't working.
WiFiConnect.h
#ifndef WIFICONNECT_H
#define WIFICONNECT_H
#include <WiFiClient.h>
#include "Wifi.h"
class WiFiConnect
{
private:
#define WIFI_NETWORK "NetworkName"
#define WIFI_PASSWORD "Password"
#define WIFI_TIMEOUT 20000
public:
void wifiConnect();
void wifiDisconnect();
};
#endif
WiFiConnect.cpp - Handles connection to WiFi
#include <WiFi.h>
#include <WiFiConnect.h>
void WiFiConnect::wifiConnect() {
WiFiServer server(80);
Serial.print("Connecting to WiFi");
WiFi.mode(WIFI_AP);
WiFi.begin(WIFI_NETWORK, WIFI_PASSWORD);
unsigned long startAttemptTime = millis();
//Connection Protocol
while(WiFi.status() != WL_CONNECTED && (millis() - startAttemptTime) < WIFI_TIMEOUT) {
Serial.println("...");
delay(100);
}
if(WiFi.status() != WL_CONNECTED) {
Serial.println("Failed, attempting again...");
delay(5000);
}
else{
Serial.print("Connected: ");
Serial.println(WiFi.localIP());
server.begin();
}
}
void WiFiConnect::wifiDisconnect() {
Serial.println("Disconnecting from WiFi...");
WiFi.disconnect();
}
ScheduleProt.h
#ifndef SCHEDULEPROT_H
#define SCHEDULEPROT_H
class ScheduleProt {
public:
int waterState = -1;
void scheduleWatering();
};
#endif
ScheduleProt.cpp - Reads the URL from the http server
#include <WiFi.h>
#include <Arduino.h>
#include "WiFiConnect.h"
#include "ScheduleProt.h"
void ScheduleProt::scheduleWatering() {
WiFiServer server(80);
WiFiClient client = server.available();
WiFiConnect newConnection;
newConnection.wifiConnect();
while(waterState = -1){
if (client) {
String req = client.readStringUntil('\r');
Serial.println("Waiting for user input...");
//Watering Times
if(req.indexOf("/morning/") != -1){
client.print("Morning");
waterState = 0;
}
else if(req.indexOf("/noon/") != -1){
waterState = 1;
client.print("Noon");
}
else if(req.indexOf("/evening/") != -1){
waterState = 2;
client.print("Evening");
}
else if(req.indexOf("/midnight/") != -1){
waterState = 3;
client.print("Midnight");
}
}
}
Serial.println("User input recieved, Huzzah!" + waterState);
newConnection.wifiDisconnect();
}
Here is the terminal
�Connecting to WiFi...
...
...
...
...
...
...
...
...
Connected: 192.168.1.100
If it helps, here is the main.cpp code
#include <Arduino.h>
#include <time.h>
#include "Wifi.h"
#include "ScheduleProt.h"
#include "WaterProt.h"
#include "CurrentTime.h"
#define DEEPSLEEPTIME 86400000
#define WATER_DURATION 10000
#define MOTORPIN 0
WaterProt waterProtocol;
CurrentTime currentTime;
ScheduleProt newSchedule;
void setup() {
Serial.begin(9600);
newSchedule.scheduleWatering();
}
void loop() {
if (waterProtocol.getWateringHour(newSchedule.waterState) == currentTime.getCurrentHour()){
waterProtocol.waterPlant(MOTORPIN, WATER_DURATION);
}
else {
esp_sleep_enable_timer_wakeup(1800000);
esp_deep_sleep_start();
}
esp_sleep_enable_timer_wakeup(DEEPSLEEPTIME);
esp_deep_sleep_start();
}
The webpage error
[1]: https://i.stack.imgur.com/HLIaH.png
Any help would be appreciated! Thank you!

It looks like you're actually creating two separate WiFiServers, and only calling begin() on one of them.
One WiFiServer is created inside WiFiConnect::wifiConnect(). This is a local variable and so it goes away when that function completes.
The other WiFiServer is created inside ScheduleProt::scheduleWatering(). This one is probably the one you want to keep, but you'll need to add a call to server.begin() before the call to server.available().
My suggestion is:
Remove all references to WiFiServer from WiFiConnect::wifiConnect().
Move the two lines inside ScheduleProt::scheduleWatering() that relate to WiFiConnect to the top of the function, so that they happen before the WiFiServer is initialized.
Add a call to server.begin() just before the call to server.available().
I also notice that ScheduleProt::scheduleWatering() is called from your setup() function, which means that it will only run once (i.e. accept one HTTP connection), and the loop() function will only run after that connection has completed. It looks like this might be intended, but I wasn't sure so thought I should point it out just in case you were unaware.
Update: I just had another look at the docs and it looks like WiFiServer.available() doesn't actually wait for a client to connect, it just returns the connection if there is one already. If that's the case, you really need to call it repeatedly until it returns a connection (or use a blocking function instead - I haven't looked into what's available in terms of that). Probably the easiest way to do this with your current code is to move the WiFiClient client = server.available(); inside the while loop.
It might also be a good idea to add a delay(1); inside that loop, so that it isn't running the processor at 100% load. I can't say this for sure without refreshing my memory on how the ESP32 does power management, but it's likely that adding the delay will save a significant amount of power. Either way, it won't hurt.

Related

Google iot MQTT - ESP32 Connects the first time and only reconnects after 30m

I'm working with google Iot cloud with ESP32, I am sending fake values just to make a test with the MQTT data PUB/SUB, Apparently I'm succeeding in publishing the values, sometimes, I can't reconnect to google iot.
I don't know why it keeps checking wifi...publising and doest check for the JWT key.
I have noticed that if I connect once to the google iot and then I unplug the esp32 from my pc (disconnect no power), and plug it back again and try to connect, I will enter in this "checking wifi" for about 30m, until I can connect back to google iot. How can fix this? I beleived there was something to deal with this:
// Time (seconds) to expire token += 20 minutes for drift
const int jwt_exp_secs = 3600; // Maximum 24H (3600*24)
When I manage to get a good response that send info to the servers, i get this+:
entry 0x400806b8
Setup.....
Starting wifi
Connecting to WiFi
Connected
Waiting on time sync...
checking wifi...
connecting...Refreshing JWT
connected
Library connected!
incoming: /devices/esp32-device/config -
incoming: /devices/esp32-device/config -
Publishing value
Publishing value
Publishing value
Publishing value
Publishing value
There is times that I get a bad response for about 30m, using the same code, it seems to be sending constant data, which shouldn't be constant.(wasn't suppose to happen):
ho 0 tail 12 room 4
load:0x40080400,len:6352
entry 0x400806b8
Setup.....
Starting wifi
Connecting to WiFi
Connected
Waiting on time sync...
checking wifi...Publishing value
checking wifi...checking wifi...checking wifi...Publishing value
(Just keeps repeating)
This is the main connection to MQTT code, with the attempts to fix problems, but didn't work:
// This file contains static methods for API requests using Wifi / MQTT
#ifndef __ESP32_MQTT_H__
#define __ESP32_MQTT_H__
#include <Client.h>
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <MQTT.h>
#include <CloudIoTCore.h>
#include <CloudIoTCoreMqtt.h>
#include "ciotc_config.h" // Update this file with your configuration
void messageReceived(String &topic, String &payload) {
Serial.println("incoming: " + topic + " - " + payload);
}
// Initialize WiFi and MQTT for this board
Client *netClient;
CloudIoTCoreDevice *device;
CloudIoTCoreMqtt *mqtt;
MQTTClient *mqttClient;
unsigned long iat = 0;
String jwt;
String getDefaultSensor() {
return "Wifi: " + String(WiFi.RSSI()) + "db";
}
String getJwt() {
Serial.println("Entered JWT");
delay(5000);
iat = time(nullptr);
Serial.println("Refreshing JWT");
jwt = device->createJWT(iat, jwt_exp_secs);
return jwt;
}
void setupWifi() {
Serial.println("Starting wifi");
Serial.print("WIFI status = ");
Serial.println(WiFi.getMode());
WiFi.disconnect(true);
delay(3000);
WiFi.mode(WIFI_STA);
delay(3000);
Serial.print("WIFI status = ");
Serial.println(WiFi.getMode());
WiFi.begin(ssid, password);
Serial.println("Connecting to WiFi");
while (WiFi.status() != WL_CONNECTED) {
delay(100);
}
Serial.println("Connected");
delay(5000);
configTime(0, 0, ntp_primary, ntp_secondary);
Serial.println("Waiting on time sync...");
while (time(nullptr) < 1510644967) {
delay(10);
}
}
void connectWifi() {
Serial.print("checking wifi...");
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
}
delay(5000);
}
bool publishTelemetry(String data) {
return mqtt->publishTelemetry(data);
}
bool publishTelemetry(const char* data, int length) {
return mqtt->publishTelemetry(data, length);
}
bool publishTelemetry(String subfolder, String data) {
return mqtt->publishTelemetry(subfolder, data);
}
bool publishTelemetry(String subfolder, const char* data, int length) {
return mqtt->publishTelemetry(subfolder, data, length);
}
void connect() {
connectWifi();
mqtt->mqttConnect();
delay(5000);
}
void setupCloudIoT() {
device = new CloudIoTCoreDevice(
project_id, location, registry_id, device_id,
private_key_str);
setupWifi();
netClient = new WiFiClientSecure();
mqttClient = new MQTTClient(512);
mqttClient->setOptions(180, true, 1000); // keepAlive, cleanSession, timeout
mqtt = new CloudIoTCoreMqtt(mqttClient, netClient, device);
mqtt->setUseLts(true);
mqtt->startMQTT();
delay(5000);
}
#endif //__ESP32_MQTT_H__
This is the main.cpp:
#include <Arduino.h>
#include <WiFiClientSecure.h>
#include "esp32-mqtt.h"
#include <ArduinoJson.h>
#define led 14
char buffer[100];
float counter = 0;
float counter1 = 0;
void setup() {
Serial.begin(115200);
Serial.println("Setup.....");
pinMode(led, OUTPUT);
setupCloudIoT();
}
unsigned long lastMillis = 0;
void loop() {
mqtt->loop();
delay(10); // <- fixes some issues with WiFi stability
if (!mqttClient->connected()) {
connect();
}
counter++;
counter1++;
if (millis() - lastMillis > 1000) {
Serial.println("Publishing value");
lastMillis = millis();
float temp = counter;
float hum = counter1;
StaticJsonDocument<100> doc;
doc["temp"] = temp;
doc["humidity"] = hum;
serializeJson(doc, buffer);
publishTelemetry(buffer);
}
}
Does someone know if there is any other module that doesn't have this same issue?
The issue you face is IMHO not a problem of your code or the MQTT-lib you use. There seems to be a problem in the ESP32 core package (1.04 has it still). See this collection of issues from github and some proposed work around, which in the end delay the problem but do not solve it.
Issue with MQTT collection of problems from 2018 till today
These are open issues regarding WiFi re/connection problems
A test case for provoking an error is linked from one of the post.I use for identifying ESP32 specific problems the identical programm on an esp8266 with MQTT connection and there it runs for months.The ESP32 people have the bad habit to leave issues uncommented open for month hopeing the stale bot closes them. So I just cited the open issues, if you search for closed issues you'll find some more) closed by stale bot and not by solution!

ESP8266WebServer - Refactoring class, problems with std::bind and handleRoot

I'm having some trouble while putting my ESP8266WebServer standard connection procedure to its own class. I'm not able to pass the object server to my handleRoot function via bind::std.... I have tried multiple approaches, but right now, nothing succeeds. So maybe you could help me. Right now, the code compiles, I have commented out the corresponding lines. But in order to peform some actions on a client request, I need to have access to the server class methods in the functions handleRoot and handleForm. Here are the corresponding sketches. Thank you for your help.
Arduino sketch:
#include "WiFiHandler.h"
#include <ESP8266WebServer.h>
ESP8266WebServer server(80);
WiFiHandler myWiFiHandler;
void setup(){
Serial.begin(115200);
myWiFiHandler.setupWiFi(server); // Setup WiFi
}
void loop(){
myWiFiHandler.clientHandler(server); //Handle client requests
}
Header file:
#ifndef WiFiHandler_h
#define WiFiHandler_h
#include <WiFiSetup.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include "handleHTML.h"
class WiFiHandler
{
private:
WiFiSetup myWiFiSetup; // Create object myWiFiSetup
handleHTML myHTMLhandler; // Create object myHTMLHandler
char* _ssid;
char* _password;
void handleRoot();
void handleForm();
public:
WiFiHandler();
~WiFiHandler();
void setupWiFi(ESP8266WebServer&);
void clientHandler(ESP8266WebServer&);
};
#endif
Source file:
#include <WiFiSetup.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include "handleHTML.h"
#include "Arduino.h"
#include "WiFiHandler.h"
WiFiHandler::WiFiHandler()
: _ssid(myWiFiSetup.ssid()), _password(myWiFiSetup.passcode())
{
}
WiFiHandler::~WiFiHandler(){/*Nothing to destruct*/}
void WiFiHandler::setupWiFi(ESP8266WebServer& server_)
{
WiFi.begin(_ssid, _password);
// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print("Status: \n");
Serial.println(WiFi.status());
}
//If connection successful show IP address in serial monitor
Serial.print("Connected to ");
Serial.println(_ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP()); //IP address assigned to your ESP
server_.on("/", std::bind(&WiFiHandler::handleRoot, this)); // Which routine to handle at root location
server_.on("/", std::bind(&WiFiHandler::handleForm, this)); // Form action is handled here
server_.begin(); //Start server
Serial.println("HTTP server started");
}
void WiFiHandler::handleRoot()
{
Serial.print("WiFi-Request received");
// server_.send(200, "text/html", myHTMLhandler.getHTML()); //Send web page
}
void WiFiHandler::handleForm()
{
// String buttonState = server.arg("State");
Serial.print("State: ");
// Serial.println(buttonState);
String s = "<a href='/'> Go Back </a>";
// server_.send(200, "text/html", s); //Send web page
}
void WiFiHandler::clientHandler(ESP8266WebServer& server_)
{
server_.handleClient();
}
Changing the callback finally did the job.
server_.on("/", [&]() { handleRoot(server_); });
server_.on("/action_page", [&]() { handleForm(server_); });
and the corresponding function:
void WiFiHandler::handleRoot(ESP8266WebServer& server_)
{
server_.send(200, "text/html", myHTMLhandler.getHTML()); //Send web page
}
I do it the following way, the principle works by the way also with async webserver:
class MY_WebServer : public WebServer { // inherit from the lib class
public:
MY_WebServer();
void begin() {
MDNS.addService("http", "tcp", 80);
WebServer::begin();
}
void startWebServer(); // this function initializes wifi, all handlers and params
private:
void handleFileList();
//.... some 30 handlers ...
}
Works in a quite complex application stable for months.

Arduino WiFi101 Library - Pass WiFi and WiFiClient to child classes

I’m slowly getting to work on an IoT project involving a WiFi client using the Adafruit ItsyBitsy M4, ATWINC1500 and WiFi101 library. All works great when in a single sketch, but this is quickly becoming unmanageably long. I've switched to a PlatformIO environment and am rewriting using CPP.
I want to be able to modularise my code by its purpose into classes which for the most part has been successful. I can then pass pointers (*) of the connected hardware (i.e. NeoPixel and Uart for serial ports) to the classes "set" method. Though, I have been unable to do this with the WiFiClass and WiFiClient classes.
I’ve had a go at passing the WiFi and WiFiClient to my classes as a pointer (see code below), in the same way I have successfully done it with Uart Classe for my serial ports (though I have to use -> and not . for methods). The issue is, whilst I am able to determine (what I believe to be) the current client status, no data is ever returned in my loop(). I have getter and setter methods to get/set the WiFiClient pointer, yet there’s no data when I use them.
It also seems that WiFiClass (the WiFi object) is being automatically created when the sketch starts which makes me uncomfortable as I haven't declared it anywhere.
My questions:
Is there any way to explicitly declare a WiFiClass and initialise a custom WiFi101 connection, as opposed to using the default WiFi class provided by the library? For clarity I like to see where things are initialised and not just accept that they have been.
Is it actually possible for me to pass the WiFiClient class through to my own classes and have all classes use the same single instance back in main.cpp via pointers?
Below is what I have tried so far:
NetworkInterface class
(originally designed to hold the entire instantiated WiFi class, but currently just using WiFiClient):
// network-interface.cpp:
WiFiClient NetworkInterface::getNetworkClient() {
return *_networkClient;
}
byte NetworkInterface::setNetworkInterface(WiFiClient *newNetworkInterface, interfacetype_t mode) {
if (mode >= 0 && mode <= 3) {
networkMode = mode;
} else {
networkMode = -1; // TODO: Use enum
return -1;
}
_networkClient = newNetworkInterface;
return mode;
}
// .header file:
#ifndef NETWORKINTERFACE_H
#define NETWORKINTERFACE_H_
#include "Arduino.h"
typedef enum {
INTERFACETYPE_WIFI = 0,
INTERFACETYPE_ETH = 1,
INTERFACETYPE_BT = 2,
INTERFACETYPE_UNSUPPORTED = -1
} interfacetype_t;
class NetworkInterface {
public:
bool connectToSSID(byte ssid[], byte password[]);
bool getConnectionStatus();
bool disconnectFromNetwork();
interfacetype_t getNetworkMode();
WiFiClient getNetworkClient();
byte setNetworkInterface(WiFiClient *newNetworkInterface, interfacetype_t mode); // 26.01.2019 - LIMITED TO WiFICLIENT, UNSURE ABOUT WiFiClass
private:
interfacetype_t networkMode;
WiFiClient *_networkClient;
};
#endif
main class:
// main.cpp:
#include <SPI.h>
#include <WiFi101.h>
#include "arduino_secrets.h"
#include "network-interface.h"
char ssid[] = SECRET_SSID; // your network SSID (name)
char pass[] = SECRET_PASS; // your network password (use for WPA, or use as key for WEP)
int keyIndex = 0; // your network key Index number (needed only for WEP)
int status = WL_IDLE_STATUS;
char server[] = "www.google.com"; // name address for Google (using DNS)
WiFiClient client;
NetworkInterface networkInterface;
void setup() {
//Initialize serial and wait for port to open:
Serial.begin(9600);
while (!Serial);
Serial.println("= = = Simple Client-Server Test = = = ");
WiFi.setPins(A5, A4, A3, A2);
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("WiFi shield not present");
while (true);
}
// attempt to connect to WiFi network:
while (status != WL_CONNECTED) {
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
// Connect to WPA/WPA2 network. Change this line if using open or WEP network:
status = WiFi.begin(ssid, pass);
// wait for connection
delay(2000);
}
Serial.println("Connected to wifi");
printWiFiStatus();
Serial.println("\nStarting connection to server...");
/*
Pass the network client (and hopefully soon WiFi class with hardware connection data) to NetworkInterface class
TODO: IMPLEMENT ENUM FOR INTERFACE TYPES
*/
networkInterface.setNetworkInterface(&client, 0);
...
}
void loop() {
// if there are incoming bytes available
// from the server, read them and print them:
WiFiClient myClient = networkInterface.getNetworkClient();
if (myClient.available()) {
Serial.print("\n==================================\n");
Serial.print("| REMOTE :: Server Has Responded: |");
Serial.print("\n----------------------------------\n");
while (myClient.available()) {
char c = myClient.read();
Serial.write(c);
}
Serial.print("\n==================================\n");
}
// if the server's disconnected, stop the myClient:
if (!myClient.connected()) {
Serial.println();
Serial.println("CLIENT :: Disconnecting");
myClient.stop();
// do nothing forevermore:
while (true);
}
}
void makeTestCallToPusher() {
char serverURLTest[] = "192.168.2.4";
WiFiClient myClient = networkInterface.getNetworkClient();
if (myClient.connect(serverURLTest, 80)) {
Serial.print("CLIENT :: Connected - ");Serial.print(serverURLTest);Serial.print("\n");
myClient.println("GET /test HTTP/1.1");
myClient.println("Upgrade: WebSocket");
myClient.println("Connection: Upgrade");
myClient.println("Origin: ARDUINO_TEST");
myClient.println("Host: eu");
myClient.println("Connection: close");
myClient.println();
}
}
void printWiFiStatus() {
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// print your WiFi shield's IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
// print the received signal strength:
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.print(rssi);
Serial.println(" dBm");
}
WiFi is a global object declared in WiFi101.h and defined in WiFi.cpp (at the end of both files). To use it, include WiFi101.h or pass a reference to parameter or field of type WiFiClass& (reference to WiFiClass).
From your code it is not clear what you want to do with the client object. You have it global and I don't see where it connects to server. You set a pointer to the global object to the networkInterface object, store a pointer, but the getter function's return type is not a pointer and the local variable myClient isn't a pointer too.
If you want work with pointer, change the getter function to return a pointer. But then the original object must exist somewhere (now it is global).
WiFiClient* myClient = networkInterface.getNetworkClient();
if (myClient->available()) {
But the WiFiClient class is only a wrapper and has the = operator overloaded as copy. If copied it still refers the same underlying TCP socket. So you can assign it without pointer or reference.
WiFiClient _networkClient;
byte setNetworkInterface(WiFiClient &client) {
_networkClient = client; // copy data about TCP socket
}

How to store response from html request in char array on arduino?

I have an Arudino Uno with an Adafruit CC3000 wifi shield attached.
I am trying to send multiple http requests and store the results from the GET requests. I can make and receive the requests successfully, but space on the arduino (in the buffer?) runs out when I try to store more than one of the responses.
I'm happy to store one string at a time so I figured that instead of using the arduino String class if I use a char array instead and allocate memory, I can then free the memory afterwards. That way I could use the memory as required, hopefully not cause any issues in running the rest of the code. I know this also depends on how long the incoming response is, but let's assume the response size is small enough. Feel free to shoot me down if there are flaws in my logic... (likely)
I tried variations of creating the char array without having to define the size beforehand and then using strcpy or strcat to append the new characters, but with no success.
I want to do something in the process of: create char array, fill it, use it, free it from memory.
In the past I've used this method in such a form:
char *array = new char[size_wanted];
strcpy(array,some_char_array);
strcat(array,some_other_char_array);
This of course works well when you know what size_wanted is. I don't until I read the buffer, but once I've read the buffer I've read it, so cannot read it again. Am I missing a trick here?! Is there a simpler way to do this using the Arduino String class? Am I missing the obvious or just not understanding how this works? Any ideas would be greatly appreciated.
My code:
/***************************************************
Adafruit CC3000 Wifi Breakout & Shield Example
****************************************************/
#include <Adafruit_CC3000.h>
#include <ccspi.h>
#include <SPI.h>
#include <string.h>
#include "utility/debug.h"
// These are the interrupt and control pins
#define ADAFRUIT_CC3000_IRQ 2 // MUST be an interrupt pin!
// These can be any two pins
#define ADAFRUIT_CC3000_VBAT 5
#define ADAFRUIT_CC3000_CS 10
// Use hardware SPI for the remaining pins
// On an UNO, SCK = 13, MISO = 12, and MOSI = 11
Adafruit_CC3000 cc3000 = Adafruit_CC3000(ADAFRUIT_CC3000_CS, ADAFRUIT_CC3000_IRQ, ADAFRUIT_CC3000_VBAT,
SPI_CLOCK_DIVIDER); // you can change this clock speed
#define WLAN_SSID "wifi"
#define WLAN_PASS "passoword"
#define WLAN_SECURITY WLAN_SEC_WPA2
#define IDLE_TIMEOUT_MS 3000
// What page to grab!
#define WEBSITE "www.adafruit.com"
#define WEBPAGE "/testwifi/index.html"
uint32_t ip;
int n = 1;
char* result;
void setup(void)
{
Serial.begin(115200);
Serial.println(F("Hello, CC3000!\n"));
Serial.print("Free RAM: "); Serial.println(getFreeRam(), DEC);
/* Initialise the module */
Serial.println(F("\nInitializing..."));
if (!cc3000.begin())
{
Serial.println(F("Couldn't begin()! Check your wiring?"));
while(1);
}
Serial.print(F("\nAttempting to connect to ")); Serial.println(WLAN_SSID);
if (!cc3000.connectToAP(WLAN_SSID, WLAN_PASS, WLAN_SECURITY)) {
Serial.println(F("Failed!"));
while(1);
}
Serial.println(F("Connected!"));
/* Wait for DHCP to complete */
Serial.println(F("Request DHCP"));
while (!cc3000.checkDHCP())
{
delay(100); // ToDo: Insert a DHCP timeout!
}
/* Display the IP address DNS, Gateway, etc. */
while (! displayConnectionDetails()) {
delay(1000);
}
ip = 0;
// Try looking up the website's IP address
Serial.print(WEBSITE); Serial.print(F(" -> "));
while (ip == 0) {
if (! cc3000.getHostByName(WEBSITE, &ip)) {
Serial.println(F("Couldn't resolve!"));
}
delay(500);
}
cc3000.printIPdotsRev(ip);
String r1, r2, r3, r4, r5;
r1 = connect_to_webclient();
r2 = connect_to_webclient();
r3 = connect_to_webclient();
r4 = connect_to_webclient();
r5 = connect_to_webclient();
/*
Serial.println("RESULTS:");
Serial.println("r1:"); Serial.println(r1);
Serial.println("r2:"); Serial.println(r2);
Serial.println("r3:"); Serial.println(r3);
Serial.println("r4:"); Serial.println(r4);
Serial.println("r5:"); Serial.println(r5);
*/
/* You need to make sure to clean up after yourself or the CC3000 can freak out */
/* the next time your try to connect ... */
Serial.println(F("\n\nDisconnecting"));
cc3000.disconnect();
}
void loop(void)
{
delay(1000);
}
bool displayConnectionDetails(void)
{
uint32_t ipAddress, netmask, gateway, dhcpserv, dnsserv;
if(!cc3000.getIPAddress(&ipAddress, &netmask, &gateway, &dhcpserv, &dnsserv))
{
Serial.println(F("Unable to retrieve the IP Address!\r\n"));
return false;
}
else
{
Serial.print(F("\nIP Addr: ")); cc3000.printIPdotsRev(ipAddress);
Serial.print(F("\nNetmask: ")); cc3000.printIPdotsRev(netmask);
Serial.print(F("\nGateway: ")); cc3000.printIPdotsRev(gateway);
Serial.print(F("\nDHCPsrv: ")); cc3000.printIPdotsRev(dhcpserv);
Serial.print(F("\nDNSserv: ")); cc3000.printIPdotsRev(dnsserv);
Serial.println();
return true;
}
}
String connect_to_webclient() {
/* Try connecting to the website.
Note: HTTP/1.1 protocol is used to keep the server from closing the connection before all data is read.
*/
Serial.print("\nConnection number: ");
Serial.println(n);
Adafruit_CC3000_Client www = cc3000.connectTCP(ip, 80);
if (www.connected()) {
Serial.println("Connected succeeded");
www.fastrprint(F("GET "));
www.fastrprint(WEBPAGE);
www.fastrprint(F(" HTTP/1.1\r\n"));
www.fastrprint(F("Host: ")); www.fastrprint(WEBSITE); www.fastrprint(F("\r\n"));
www.fastrprint(F("\r\n"));
www.println();
} else {
Serial.println(F("Connection failed"));
return;
}
Serial.println(F("-------------------------------------"));
/* Read data until either the connection is closed, or the idle timeout is reached. */
unsigned long lastRead = millis();
while (www.connected() && (millis() - lastRead < IDLE_TIMEOUT_MS)) {
while (www.available()) {
char c = www.read();
Serial.print(c);
//strcat(result, c);
lastRead = millis();
}
}
www.close();
Serial.println(F("-------------------------------------"));
n++;
return result;
}

Arduino does not support messages larger than 65535 characters using websocket protocol?

I'm using the following Arduino websocket library, I had a problem when trying to send messages over than 65535 characters, I got handshake fail error.
As long as the message doesn't exceeds this length, it worked perfectly
There's a note on the main web page of the library that states:
Because of limitations of the current Arduino platform (Uno at the time of this writing),
this library does not support messages larger than 65535 characters.
In addition, this library only supports single-frame text frames.
It currently does not recognize continuation frames, binary frames, or ping/pong frames.
In the client header file named WebSocketClient.h there's the following comment:
// Don't allow the client to send big frames of data. This will flood the arduino memory and might even crash it.
#ifndef MAX_FRAME_LENGTH
#define MAX_FRAME_LENGTH 256
#endif
I'm using this old library because it is the only one worked for me on my Arduino WIFI shield, I couldn't find other libraries that support WiFi shield since most of the webscket libraries are written for Arduino Eathernet Shield support, which I don't have.
My Arduino Code is
/*DS18 Libs*/
#include <dht.h>
#include <OneWire.h>
#include <DallasTemperature.h>
/*Websocket Libs*/
#include <WebSocketServer.h>
#include <WebSocketClient.h>
#include <sha1.h>
#include <MD5.h>
#include <global.h>
#include <Base64.h>
#include <SPI.h>
#include <WiFiUdp.h>
#include <WiFiServer.h>
#include <WiFiClient.h>
#include <WiFi.h>
#include <string.h>
char ssid[] = "AMM";
char pass[] = "027274792";
int status = WL_IDLE_STATUS;
IPAddress server(192, 168, 1, 3);
WiFiClient WiFiclient;
WebSocketClient WSclient;
// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 2
// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);
//Humidture
dht DHT;
#define DHT11_PIN 4
void setup()
{
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
//check for the presence of the shield:
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("WiFi shield not present");
// don't continue:
while (true);
}
// 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);
}
// you're connected now, so print out the data:
Serial.print("You're connected to the network");
/* Connect to the websocket server*/
if (WiFiclient.connect(server, 8080)) {
Serial.println("Connected");
}
else {
Serial.println("Connection failed.");
while (1) {
// Hang on failure
}
}
// Handshake with the server
WSclient.path = "/MyServer/endpoint/testtest/device/d6220ae7-caa9-48b5-92db-630c4c296ec4";
WSclient.host = "192.168.1.3:8080";
if (WSclient.handshake(WiFiclient)) {
Serial.println("Handshake successful");
}
else {
Serial.println("Handshake failed.");
while (1) {
// Hang on failure
}
}
/*DS18*/
sensors.begin();
}
void loop()
{
WSclient.sendData("{\"service_code\":\"89c4da72-a561-47db-bf62-8e63f8c4bbf0\",\"data\":[" + getHumidtureValue() + "],\"service_type\":\"TemperatureHumidityAnalysis\"}");
WSclient.sendData("{\"service_code\":\"bdc0f984-6550-4712-881f-b09071da5a73\",\"data\":" + getCBodyTempretureValue() + ",\"service_type\":\"TemperatureGaugeMonitor\"}");
//line-3 commented WSclient.sendData("{\"service_code\":\"8c212432-a86e-4c18-a956-9dc0dbb648d4\",\"data\":[" + getHumidtureValue() + "],\"service_type\":\"HumidityGaugeMonitor\"}");
}
String getCBodyTempretureValue()
{
sensors.requestTemperatures(); // Send the command to get temperatures
char charVal[10];
return dtostrf(sensors.getTempCByIndex(0), 4, 2, charVal);
}
String getHumidtureValue()
{
String str = "";
for (int i = 0; i < 2; i++)
{
int chk = DHT.read11(DHT11_PIN);
switch (chk)
{
case DHTLIB_OK:
Serial.println("OK,\t");
break;
case DHTLIB_ERROR_CHECKSUM:
Serial.println("Checksum error,\t");
break;
case DHTLIB_ERROR_TIMEOUT:
Serial.println("Time out error,\t");
break;
default:
Serial.println("Unknown error,\t");
break;
}
char charVal[10];
double tempF = (DHT.temperature * 9) / 5 + 32;
str = dtostrf(tempF, 3, 1, charVal);
str = str + "," + dtostrf(DHT.humidity, 3, 1, charVal);
Serial.println(str);
delay(200);
}
return str;
}
The code above works perfectly, when I uncomment the third send statement in the loop function, I got the handshake failed error.
-Is it safe to modify the value of MAX_FRAME_LENGTH for the new versions of Arduino board, considering this library is an old one?
-Is there any other libraries better than this one that can support websocket on WiFi shield?
Any solution or idea will appreciated.
Thanks in advance.
Without having looked at the code of the library it is likely not safe to change the max frame length, because the websocket protocol encodes the payload length differently depending on how long it is:
Payload length: 7 bits, 7+16 bits, or 7+64 bits.
The length of the "Payload data", in bytes: if 0-125, that is the payload length. If 126, the following 2 bytes interpreted as a 16-bit unsigned integer are the payload length. If 127, the following 8 bytes interpreted as a 64-bit unsigned integer (the most significant bit MUST be 0) are the payload length.
When the library says it doesn't support payload length above 65535 byte, it likely means that it has no implementation for the 64-bit length encoding.
After many trials and many times the program behaves very strangely, which drives me crazy, I found the problem is that I'm using too much strings in my program which makes the Arduino-Uno easily runs out of RAM.
The main reason I got handshake failed error is that the Arduino cannot read the "Sec-WebSocket-Accept" header of the handshake response message (as many other headers also) which I made sure that they are sent, by debugging code on the server.
Actually this problem and many other strange behaviors keep happening until I reduce the amount of the memory used during program run.