ESP32 reboots unexpected - problematic variable? - c++
I have a problem with (at least) one row in my code. My intention is to instantiate some objects for HTTP requests. I store their pointers in an array requestsBatch because I will call them from within a helper function. After storing them I'll do some time checks and then send the request to the server. After a successful request, the object will be deleted.
It seems the variable address is problematic but I can't see why.
const char* root_ca_sherz = "myCert";
int currentRequestsBatchIndex=0;
class HTTPREQUESTS {
public:
HTTPREQUESTS(String strAddress = "", String strParameters = "", bool bSendImmediately=false, const char* cert=root_ca_sherz) {
address = strAddress;
parameters = strParameters;
certificate = cert;
currentRequestsBatchIndex++;
Serial.println("New object instantiated");
Serial.println(address);
Serial.println(parameters);
}
~HTTPREQUESTS() {
currentRequestsBatchIndex--;
}
bool sendRequest() {
Serial.println("Called from within sendRequest()");
Serial.println(address); // <<<<<< THIS ROW CAUSES THE REBOOT
/*
http.begin(address+"/"+parameters, certificate); //, root_ca_sherz
int httpCode = http.GET();
Serial.print("HTTP Code: ");
Serial.println(httpCode);
Serial.print("Payload: ");
Serial.println(http.getString());
if (httpCode > 0) { //Check for the returning code
return true;
}
else {
Serial.println("Error on HTTP request");
return false;
}
http.end();
delay(1000);
return false;
*/
return true;
}
private:
const char* certificate="";
String parameters;
String device;
String address;
unsigned long timestamp=0;
int sendAttempts=0;
bool sendImmediately = false;
unsigned long lastSendAttemp=0;
};
HTTPREQUESTS *requestsBatch[5];
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
delay(3000);
Serial.println("Ready");
String address = "https://myAddress.com";
String parameters = "?secret=XXXXX&deviceName=deviceName&status=1&value=999&time=123456789&functionName=functionName";
HTTPREQUESTS *req01 = new HTTPREQUESTS(address, parameters);
// Store pointer to array to use it later
requestsBatch[currentRequestsBatchIndex] = req01;
Serial.println("Object stored in array");
Serial.print(F("Send request: "));
if(requestsBatch[0]->sendRequest()) {
//delete requestsBatch[0];
Serial.println("requestsBatch[0] deleted");
}
}
void loop() {
// put your main code here, to run repeatedly:
}
SOLUTION:
Replacing
currentRequestsBatchIndex++;
by
if(address != "") {
currentRequestsBatchIndex++;
}
because currentRequestsBatchIndex is also incrementing when creating the empty *requestsBatch[5] array.
As I dont like the String class (will cause you memory problems later on)I rewrote with char arrays and it works as expected (Included your "solution" but have you checked serial monitor output):
const char* root_ca_sherz = "myCert";
char address[128] = {'\0'};
int currentRequestsBatchIndex = 0;
class HTTPREQUESTS {
public:
HTTPREQUESTS(char strAddress[128] = {'\0'}, char strParameters [128] = {'\0'}, bool bSendImmediately = false, const char* cert = root_ca_sherz) {
strcpy (address, strAddress);
strcpy (parameters, strParameters);
certificate = cert;
if (address[0] != '\0') {
currentRequestsBatchIndex++;
}
currentRequestsBatchIndex++;
Serial.println("New object instantiated");
Serial.println(address);
Serial.println(parameters);
}
~HTTPREQUESTS() {
currentRequestsBatchIndex--;
}
bool sendRequest() {
char testAddress [128] = {'\0'};
Serial.println("Called from within sendRequest()");
strcpy (testAddress, address);
Serial.print("Will work: ");
Serial.println(testAddress); // <<<<<< THIS ROW CAUSES THE REBOOT
Serial.print("Will also work: ");
Serial.println(address); // but over written at next creation
/*
http.begin(address+"/"+parameters, certificate); //, root_ca_sherz
int httpCode = http.GET();
Serial.print("HTTP Code: ");
Serial.println(httpCode);
Serial.print("Payload: ");
Serial.println(http.getString());
if (httpCode > 0) { //Check for the returning code
return true;
}
else {
Serial.println("Error on HTTP request");
return false;
}
http.end();
delay(1000);
return false;
*/
return true;
}
private:
const char* certificate = "";
char parameters[128] = {'\0'};
char device[128] = {'\0'};
// char address[128] = {'\0'};
unsigned long timestamp = 0;
int sendAttempts = 0;
bool sendImmediately = false;
unsigned long lastSendAttemp = 0;
};
HTTPREQUESTS *requestsBatch[5];
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
delay(3000);
Serial.println("Ready");
const char address[] = "https://myAddress.com";
const char parameters[] = "?secret=XXXXX&deviceName=deviceName&status=1&value=999&time=123456789&functionName=functionName";
HTTPREQUESTS *req01 = new HTTPREQUESTS(address, parameters);
// Store pointer to array to use it later
requestsBatch[currentRequestsBatchIndex] = req01;
Serial.println("Object stored in array");
Serial.print(F("Send request: "));
if (requestsBatch[0]->sendRequest()) {
//delete requestsBatch[0];
Serial.println("requestsBatch[0] deleted");
}
}
void loop() {
// put your main code here, to run repeatedly:
Serial.println("Still running !");
delay(1000);
}
Related
PubSubClient ESP32 disconnected while receive message
I create a project to receive message from MQTT. My full code is here https://github.com/kamshory/OTP-Mini/blob/main/Server/Server.ino WiFiClient espClient; PubSubClient client(espClient); void setup() { char * mqttServer = "192.168.1.3"; client.setServer(mqttServer, 1883); client.setCallback(mqttCallback); } void mqttCallback(const char* topic, byte* payload, unsigned int length) { Serial.print("Message arrived on topic: "); Serial.print(topic); Serial.print("Message: "); char * mqttTopic = "sms"; String messageTemp; for (int i = 0; i < length; i++) { Serial.print((char)payload[i]); messageTemp += (char)payload[i]; } Serial.println(); // Feel free to add more if statements to control more GPIOs with MQTT // If a message is received on the topic esp32/output, you check if the message is either "on" or "off". // Changes the output state according to the message if (String(topic) == String(mqttTopic)) { } } void mqttReconnect() { Serial.print("WiFi status = "); Serial.println(WiFi.status()); char * clientId = "php"; char * mqttUsername = "user"; char * mqttPassword = "pass"; char * mqttTopic = "sms"; // Loop until we're reconnected while (!client.connected()) { Serial.print("Attempting MQTT connection "); // Attempt to connect if (client.connect(clientId, mqttUsername, mqttPassword)) { Serial.println("connected"); // Subscribe boolean sub = client.subscribe("sms"); Serial.println(sub); } else { Serial.print("failed, rc="); Serial.print(client.state()); Serial.println(" try again in 5 seconds"); // Wait 5 seconds before retrying delay(5000); } } } When ESP32 publish a message in a topic, the message is received by subscriber (I create the subscriber with Java). But when it try to receive the message with callback, the client is disconnected. I try to debug with edit library on file PubSubClient.cpp boolean PubSubClient::loop() { if (connected()) { unsigned long t = millis(); if ((t - lastInActivity > MQTT_KEEPALIVE*1000UL) || (t - lastOutActivity > MQTT_KEEPALIVE*1000UL)) { if (pingOutstanding) { this->_state = MQTT_CONNECTION_TIMEOUT; _client->stop(); return false; } else { buffer[0] = MQTTPINGREQ; buffer[1] = 0; _client->write(buffer,2); lastOutActivity = t; lastInActivity = t; pingOutstanding = true; } } if (_client->available()) { uint8_t llen; uint16_t len = readPacket(&llen); uint16_t msgId = 0; uint8_t *payload; if (len > 0) { lastInActivity = t; uint8_t type = buffer[0]&0xF0; if (type == MQTTPUBLISH) { if (callback) { uint16_t tl = (buffer[llen+1]<<8)+buffer[llen+2]; /* topic length in bytes */ memmove(buffer+llen+2,buffer+llen+3,tl); /* move topic inside buffer 1 byte to front */ buffer[llen+2+tl] = 0; /* end the topic as a 'C' string with \x00 */ char *topic = (char*) buffer+llen+2; // msgId only present for QOS>0 if ((buffer[0]&0x06) == MQTTQOS1) { msgId = (buffer[llen+3+tl]<<8)+buffer[llen+3+tl+1]; payload = buffer+llen+3+tl+2; callback(topic,payload,len-llen-3-tl-2); buffer[0] = MQTTPUBACK; buffer[1] = 2; buffer[2] = (msgId >> 8); buffer[3] = (msgId & 0xFF); _client->write(buffer,4); lastOutActivity = t; } else { payload = buffer+llen+3+tl; callback(topic,payload,len-llen-3-tl); } } } else if (type == MQTTPINGREQ) { buffer[0] = MQTTPINGRESP; buffer[1] = 0; _client->write(buffer,2); } else if (type == MQTTPINGRESP) { pingOutstanding = false; } } else if (!connected()) { // readPacket has closed the connection return false; } } return true; } return false; } The type value is 208 which is MQTTPINGRESP not 48 which is MQTTPUBLISH. So, where is the problem? Is my library or my code? I download library from https://www.arduino.cc/reference/en/libraries/pubsubclient/
Arduino compiler failing with error code - invalid types 'int[int]' for array subscript
Quite a bit of untested code but the only thing really concerning me at the moment is my DISPLAY variable. I don't see how it is much different than my FONT array (which works fine) yet DISPLAY is the one that gets 'invalid types 'int[int]' for array subscript' I should be able to index an array of integers with integers (at least I have been with FONT). #include <WiFiNINA.h> #include <NTPClient.h> #include <WiFiUdp.h> #include "font.h" const int PIXEL_WIDTH = 30; const int PIXEL_HEIGHT = 5; int DISPLAY[PIXEL_HEIGHT][PIXEL_WIDTH] = {}; bool MILI_TIME = false; String FORMATTING[2] = {"LONGS","SHORTH:LONGM"}; char ssid[] = "REMOVED"; // your network SSID (name) between the " " char pass[] = "REMOVED"; // your network password between the " " int keyIndex = 0; // your network key Index number (needed only for WEP) int status = WL_IDLE_STATUS; // connection status WiFiServer server(80); // server socket WiFiClient client = server.available(); WiFiUDP ntpUDP; NTPClient timeClient(ntpUDP); int ledPin = LED_BUILTIN; void setup() { Serial.begin(9600); pinMode(ledPin, OUTPUT); while (!Serial); // dont do anything until there is a serial connection enable_WiFi(); connect_WiFi(); server.begin(); printWifiStatus(); timeClient.begin(); timeClient.setTimeOffset(-14400); } void loop() { timeClient.update(); client = server.available(); if (client) { printWEB(); } preRender(); } void preRender(){ String FILLED_FORMATTING[2] = FORMATTING; for(int i=0;i<2;i++){ FILLED_FORMATTING[i].replace("LONGH",leadWithZero(timeHours())); FILLED_FORMATTING[i].replace("LONGM",leadWithZero(timeMinutes())); FILLED_FORMATTING[i].replace("LONGS",leadWithZero(timeSeconds())); FILLED_FORMATTING[i].replace("SHORTH",timeHours()); FILLED_FORMATTING[i].replace("SHORTM",timeMinutes()); FILLED_FORMATTING[i].replace("SHORTS",timeSeconds()); } int x = 0; for(int i=0;i<FILLED_FORMATTING[0].length();i++){ int c_ID = charID(FILLED_FORMATTING[0][i]); if(c_ID < 38){ for(int j=0;j<5;j++){ DISPLAY[j][x] = FONT[c_ID][j][0]; x += 1; DISPLAY[j][x] = FONT[c_ID][j][1]; x += 1; DISPLAY[j][x] = FONT[c_ID][j][2]; x += 1; if(i != FILLED_FORMATTING[0].length()){ DISPLAY[j][x] = 0; x += 1; } } } } x = PIXEL_WIDTH-1; for(int i=FILLED_FORMATTING[1].length()-1;i>=0;i--){ int c_ID = charID(FILLED_FORMATTING[1][i]); if(c_ID < 38){ for(int j=0;j<5;j++){ DISPLAY[j][x] = FONT[c_ID][j][0]; x -= 1; DISPLAY[j][x] = FONT[c_ID][j][1]; x -= 1; DISPLAY[j][x] = FONT[c_ID][j][2]; x -= 1; if(i != 0){ DISPLAY[j][x] = 0; //<----------- compiler error here, and ofc all instances above x -= 1; } } } } } int charID(char c){ for(int i=0;i<FONT_ID.length();i++){ if(FONT_ID[i] == c){ return i; } } return 40; } String timeHours(){ if(MILI_TIME){ return String(timeClient.getHours()); } else{ return convFromMili(timeClient.getHours()); } } String timeMinutes(){ return String(timeClient.getMinutes()); } String timeSeconds(){ return String(timeClient.getSeconds()); } String leadWithZero(String t){ if(t.length() < 2){ t = "0"+t; return t; } } String convFromMili(int t){ if(t > 12){ t -= 12; }else if(t == 0){ t += 12; } String ts = String(t); return ts; } void printWifiStatus() { // print the SSID of the network you're attached to: Serial.print("SSID: "); Serial.println(WiFi.SSID()); // print your board'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"); Serial.print("To see this page in action, open a browser to http://"); Serial.println(ip); } void enable_WiFi() { // check for the WiFi module: if (WiFi.status() == WL_NO_MODULE) { Serial.println("Communication with WiFi module failed!"); // don't continue while (true); } String fv = WiFi.firmwareVersion(); if (fv < "1.0.0") { Serial.println("Please upgrade the firmware"); } } void connect_WiFi() { while (status != WL_CONNECTED) { Serial.print("Attempting to connect to SSID: "); Serial.println(ssid); status = WiFi.begin(ssid, pass); delay(10000); } } void printWEB() { if (client) { // if you get a client, Serial.println("new client"); // print a message out the serial port String currentLine = ""; // make a String to hold incoming data from the client while (client.connected()) { // loop while the client's connected if (client.available()) { // if there's bytes to read from the client, char c = client.read(); // read a byte, then Serial.write(c); // print it out the serial monitor if (c == '\n') { // if the byte is a newline character // if the current line is blank, you got two newline characters in a row. // that's the end of the client HTTP request, so send a response: if (currentLine.length() == 0) { // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK) // and a content-type so the client knows what's coming, then a blank line: client.println("HTTP/1.1 200 OK"); client.println("Content-type:text/html"); client.println(); //create the buttons client.print(WiFi.getTime()); client.print("<br>"); client.print(timeClient.getEpochTime()); client.print("<br>"); client.print(timeClient.getFormattedTime()); client.print("<br>"); client.print(timeClient.getDay()); client.print("<br>"); client.print(timeClient.getHours()); client.print("<br>"); client.print(timeClient.getMinutes()); client.print("<br>"); client.print(timeClient.getSeconds()); client.print("<br>"); client.print("<div style=\"display:block;padding-left:calc(50% - 150px);margin-bottom:50px\"><div style=\"background-color:#e3e3e3;width:300px;height:120px;font-size:50px;text-align:center;padding-top:50px\">ON</div></div>"); client.print("<div style=\"display:block;padding-left:calc(50% - 150px)\"><div style=\"background-color:#e3e3e3;width:300px;height:120px;font-size:50px;text-align:center;padding-top:50px\">OFF</div></div>"); // The HTTP response ends with another blank line: client.println(); // break out of the while loop: break; } else { // if you got a newline, then clear currentLine: currentLine = ""; } } else if (c != '\r') { // if you got anything else but a carriage return character, currentLine += c; // add it to the end of the currentLine } if (currentLine.endsWith("GET /H")) { digitalWrite(ledPin, HIGH); } if (currentLine.endsWith("GET /L")) { digitalWrite(ledPin, LOW); } if (currentLine.endsWith("%VAL")) { // Trim 'GET /' and '%VAL' currentLine.remove(0,5); currentLine.remove(currentLine.indexOf("%"),4); Serial.println(currentLine); Serial.println(); } } } // close the connection: client.stop(); Serial.println("client disconnected"); } } font.h: int FONT[37][5][3] = {{{1,1,1},{1,0,1},{1,0,1},{1,0,1},{1,1,1},},{{1,1,0},{0,1,0},{0,1,0},{0,1,0},{1,1,1},},{{1,1,1},{0,0,1},{1,1,1},{1,0,0},{1,1,1},},{{1,1,1},{0,0,1},{1,1,1},{0,0,1},{1,1,1},},{{1,0,1},{1,0,1},{1,1,1},{0,0,1},{0,0,1},},{{1,1,1},{1,0,0},{1,1,1},{0,0,1},{1,1,1},},{{1,1,1},{1,0,0},{1,1,1},{1,0,1},{1,1,1},},{{1,1,1},{0,0,1},{0,0,1},{0,0,1},{0,0,1},},{{1,1,1},{1,0,1},{1,1,1},{1,0,1},{1,1,1},},{{1,1,1},{1,0,1},{1,1,1},{0,0,1},{1,1,1},},{{1,1,1},{1,0,1},{1,1,1},{1,0,1},{1,0,1},},{{1,1,0},{1,0,1},{1,1,0},{1,0,1},{1,1,0},},{{1,1,1},{1,0,0},{1,0,0},{1,0,0},{1,1,1},},{{1,1,0},{1,0,1},{1,0,1},{1,0,1},{1,1,0},},{{1,1,1},{1,0,0},{1,1,1},{1,0,0},{1,1,1},},{{1,1,1},{1,0,0},{1,1,1},{1,0,0},{1,0,0},},{{1,1,1},{1,0,0},{1,0,1},{1,0,1},{1,1,1},},{{1,0,1},{1,0,1},{1,1,1},{1,0,1},{1,0,1},},{{1,1,1},{0,1,0},{0,1,0},{0,1,0},{1,1,1},},{{0,0,1},{0,0,1},{0,0,1},{1,0,1},{1,1,1},},{{1,0,1},{1,0,1},{1,1,0},{1,0,1},{1,0,1},},{{1,0,0},{1,0,0},{1,0,0},{1,0,0},{1,1,1},},{{1,1,1},{1,1,1},{1,0,1},{1,0,1},{1,0,1},},{{1,1,0},{1,0,1},{1,0,1},{1,0,1},{1,0,1},},{{1,1,1},{1,0,1},{1,0,1},{1,0,1},{1,1,1},},{{1,1,1},{1,0,1},{1,1,1},{1,0,0},{1,0,0},},{{1,1,1},{1,0,1},{1,0,1},{1,1,0},{0,0,1},},{{1,1,1},{1,0,1},{1,1,0},{1,0,1},{1,0,1},},{{0,1,1},{1,0,0},{0,1,0},{0,0,1},{1,1,0},},{{1,1,1},{0,1,0},{0,1,0},{0,1,0},{0,1,0},},{{1,0,1},{1,0,1},{1,0,1},{1,0,1},{1,1,1},},{{1,0,1},{1,0,1},{1,0,1},{0,1,0},{0,1,0},},{{1,0,1},{1,0,1},{1,0,1},{1,1,1},{1,1,1},},{{1,0,1},{1,0,1},{0,1,0},{1,0,1},{1,0,1},},{{1,0,1},{1,0,1},{1,1,1},{0,0,1},{1,1,1},},{{1,1,1},{0,0,1},{0,1,0},{1,0,0},{1,1,1},},{{0,0,0},{0,1,0},{0,0,0},{0,1,0},{0,0,0}}}; String FONT_ID = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ:"; did check - int D[5][30]; void setup() { } void loop() { D[0][0] = 0; } and of course its fine, so I'm just wondering where I went wrong in the mess above? and yes there's a good bit of mess/debugging stuff
Simple solution... don't use DISPLAY as a variable it seems. Changing to DISPLAY_ fixed it, figured the variable was defined as a normal integer somewhere... just not in my code.
ArduinoJson parsing fail when reading string from EEPROM
Before someone flags this as duplicate I have found these two links and neither totally apply although I have implemented at least a little of both. Buffer gets overwritten Arduino reading json from EEPROM / converting uint8_t to char My problem is this. I am trying to read and write a JSON string to an Arduinos EEPROM using ArduinoJson library (https://github.com/bblanchon/ArduinoJson). In the below code I generate a JsonObject from a hard coded JSON string (this works). I then write it to EEPROM (this works). It then gets read back from EEPROM (this works) but when I try and parse the second string using ArduinoJSON i get a parse failure. For the purpose of testing I also clear the EEPROM each time just in case although eventually this will be removed. The code compiles with no errors. I am hoping that someone more knowledgable in C++ than myself will spot something really obvious. I am compiling this onto a NodeMCU (esp8266). #include <ArduinoJson.h> #include <EEPROM.h> StaticJsonBuffer<400> jsonBuffer; JsonObject *jsonObject; JsonObject *config; String dummyJson = "{\"name\":\"RGB LED 1\",\"io\":[\"pwm1\",\"pwm2\",\"pwm3\"],\"io_type\":\"output\",\"device\":\"pwm_output\",\"uuid\":\"5a81f424aaf8d1e951ae78d270668337\",\"ip\":\"255.255.255.255\"}"; void setup() { Serial.begin(9600); while (!Serial) { continue; } EEPROM.begin(512); Serial.println("\n\n"); clearEEPROM(); createDummyJsonObject(); writeJsonToEEPROM(); readJsonFromEEPROM(); } void createDummyJsonObject() { jsonObject = &jsonBuffer.parseObject(dummyJson); if (!jsonObject->success()) { Serial.println("jsonBuffer.parseObject() failed"); return; } else { Serial.println("JSON object generated from dummy string"); jsonObject->prettyPrintTo(Serial); Serial.println("\n\n"); } } void loop() { // not used } void clearEEPROM() { for (int i = 0; i < 512 + 1; i++) { EEPROM.write(i, 0); } EEPROM.commit(); } void writeJsonToEEPROM() { String jsonStr; jsonObject->printTo(jsonStr); for (int i = 0; i < jsonStr.length(); ++i) { EEPROM.write(i, jsonStr[i]); } EEPROM.write(jsonStr.length(), byte(0)); EEPROM.commit(); } void readJsonFromEEPROM() { String jsonStr; for (int i = 0; i < 512; ++i) { char c = char(EEPROM.read(i)); if (c != 0) { jsonStr += c; delay(1); } else { break; } } Serial.println(jsonStr); char charBuf[jsonStr.length()]; jsonStr.toCharArray(charBuf, jsonStr.length()); config = &jsonBuffer.parseObject(charBuf); if (!config->success()) { Serial.println("jsonObject.parseObject() failed "); return; } else { // Never reaches this point! Serial.println("\nJSON object generated from EEPROM data"); config->prettyPrintTo(Serial); Serial.println("\n\n"); } }
The size allocated for charBuf should be jsonStr.length() + 1 because you need space for a string terminator. Therefore you should also add something like charBuf[jsonStr.length()] = '\0'; to provide that string terminator: int const jsonStringLengh = jsonStr.length(); char charBuf[jsonStringLengh + 1]; jsonStr.toCharArray(charBuf, jsonStringLengh); charBuf[jsonStringLengh] = '\0';
Ok so this solved it. All I had to do was create a new StaticJsonBuffer for the second string parse. For anyone who is having a similar issue here's the working code. #include <ArduinoJson.h> #include <EEPROM.h> StaticJsonBuffer<512> jsonBuffer; JsonObject *jsonObject; JsonObject *config; String dummyJson = "{\"name\":\"RGB LED 1\",\"io\":[\"pwm1\",\"pwm2\",\"pwm3\"],\"io_type\":\"output\",\"device\":\"pwm_output\",\"uuid\":\"5a81f424aaf8d1e951ae78d270668337\",\"ip\":\"255.255.255.255\"}"; void setup() { Serial.begin(9600); while (!Serial) { continue; } EEPROM.begin(512); clearEEPROM(); createDummyJsonObject(); writeJsonToEEPROM(); readJsonFromEEPROM(); } void createDummyJsonObject() { jsonObject = &jsonBuffer.parseObject(dummyJson); if (!jsonObject->success()) { Serial.println("jsonBuffer.parseObject() failed"); return; } else { Serial.println("JSON object generated from dummy string"); } } void loop() { // not used } void clearEEPROM() { for (int i = 0; i < 512 + 1; i++) { EEPROM.write(i, 0); } EEPROM.commit(); } void writeJsonToEEPROM() { String jsonStr; jsonObject->printTo(jsonStr); for (int i = 0; i < jsonStr.length(); ++i) { EEPROM.write(i, jsonStr[i]); } EEPROM.write(jsonStr.length(), byte(0)); EEPROM.commit(); } void readJsonFromEEPROM() { String jsonStr; for (int i = 0; i < 512; ++i) { char c = char(EEPROM.read(i)); if (c != 0) { jsonStr += c; delay(1); } else { break; } } StaticJsonBuffer<512> jsonBuffer2; config = &jsonBuffer2.parseObject(jsonStr); if (!config->success()) { Serial.println("jsonObject.parseObject() failed "); return; } else { Serial.println("\nJSON object generated from EEPROM data"); config->prettyPrintTo(Serial); Serial.println("\n\n"); } }
Arduino Serial parsing
I'm working on an Arduino sketch and I'm trying to change a variable with serial. I'm using some example code that I found on arduino.cc to start with. I'm trying to modify the code with an "if statement" to update a variable timevar with integerFromPC; the problem I'm having is if I type a number higher than 4 digits like 99999 it prints out the wrong data and the variable timevar doesn't get updated correctly? I'm not sure what to do? unsigned long timevar = 1000000; const byte numChars = 32; char receivedChars[numChars]; char tempChars[numChars]; // temporary array for use when parsing // variables to hold the parsed data char messageFromPC[numChars] = {0}; int integerFromPC = 0; int ifpc = 0; float floatFromPC = 0.0; boolean newData = false; //============ void setup() { Serial.begin(9600); Serial.println("This demo expects 3 pieces of data - text, an integer and a floating point value"); Serial.println("Enter data in this style <HelloWorld, 12, 24.7> "); Serial.println(); } //============ void loop() { recvWithStartEndMarkers(); if (newData == true) { strcpy(tempChars, receivedChars); // this temporary copy is necessary to protect the original data // because strtok() used in parseData() replaces the commas with \0 parseData(); showParsedData(); newData = false; } } //============ void recvWithStartEndMarkers() { static boolean recvInProgress = false; static byte ndx = 0; char startMarker = '<'; char endMarker = '>'; char rc; while (Serial.available() > 0 && newData == false) { rc = Serial.read(); if (recvInProgress == true) { if (rc != endMarker) { receivedChars[ndx] = rc; ndx++; if (ndx >= numChars) { ndx = numChars - 1; } } else { receivedChars[ndx] = '\0'; // terminate the string recvInProgress = false; ndx = 0; newData = true; } } else if (rc == startMarker) { recvInProgress = true; } } } //============ void parseData() { // split the data into its parts char * strtokIndx; // this is used by strtok() as an index strtokIndx = strtok(tempChars,","); // get the first part - the string strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC strtokIndx = strtok(NULL, ","); // this continues where the previous call left off integerFromPC = atoi(strtokIndx); strtokIndx = strtok(NULL, ","); floatFromPC = atof(strtokIndx); // convert this part to a float } //============ void showParsedData() { if (strcmp(messageFromPC, "set time") == 0) timevar = integerFromPC; Serial.print("Time Set To "); Serial.println(integerFromPC); Serial.println(timevar); } //do other stuff
You declare int integerFromPC. int on Arduino is 16 bits. 99999 doesn't fit into 16 bits, so will appear mod 2^16 as 34463. Use long instead as you do for timeVar and it will be ok for up to +/- 2^31 .
CoreAudio Stuff From C++ to Swift
How to convert the code below to swift? Someone help. I want to convert this cpp code to swift, from project FreeStreamer. But some C++ struct and some C callback drive me crazy. Help. Here is the code from audio_stream.h and audio_stream.cpp // var queued_packet_t *m_queuedHead; queued_packet_t *m_queuedTail; queued_packet_t *m_playPacket; std::list <queued_packet_t*> m_processedPackets; //struct typedef struct queued_packet { UInt64 identifier; AudioStreamPacketDescription desc; struct queued_packet *next; char data[]; } queued_packet_t; //function one OSStatus Audio_Stream::encoderDataCallback(AudioConverterRef inAudioConverter, UInt32 *ioNumberDataPackets, AudioBufferList *ioData, AudioStreamPacketDescription **outDataPacketDescription, void *inUserData) { Audio_Stream *THIS = (Audio_Stream *)inUserData; pthread_mutex_trylock(&THIS->m_packetQueueMutex); // Dequeue one packet per time for the decoder queued_packet_t *front = THIS->m_playPacket; if (!front) { /* Don't deadlock */ AS_LOCK_TRACE("encoderDataCallback 2: unlock\n"); pthread_mutex_unlock(&THIS->m_packetQueueMutex); pthread_mutex_trylock(&THIS->m_streamStateMutex); THIS->m_converterRunOutOfData = true; pthread_mutex_unlock(&THIS->m_streamStateMutex); *ioNumberDataPackets = 0; ioData->mBuffers[0].mDataByteSize = 0; return noErr; } *ioNumberDataPackets = 1; ioData->mBuffers[0].mData = front->data; ioData->mBuffers[0].mDataByteSize = front->desc.mDataByteSize; ioData->mBuffers[0].mNumberChannels = THIS->m_srcFormat.mChannelsPerFrame; if (outDataPacketDescription) { *outDataPacketDescription = &front->desc; } THIS->m_playPacket = front->next; THIS->m_processedPackets.push_front(front); AS_LOCK_TRACE("encoderDataCallback 5: unlock\n"); pthread_mutex_unlock(&THIS->m_packetQueueMutex); return noErr; } //function two void Audio_Stream::streamDataCallback(void *inClientData, UInt32 inNumberBytes, UInt32 inNumberPackets, const void *inInputData, AudioStreamPacketDescription *inPacketDescriptions) { AS_TRACE("%s: inNumberBytes %u, inNumberPackets %u\n", __FUNCTION__, (unsigned int)inNumberBytes, (unsigned int)inNumberPackets); Audio_Stream *THIS = static_cast<Audio_Stream*>(inClientData); if (!THIS->m_audioStreamParserRunning) { AS_TRACE("%s: stray callback detected!\n", __PRETTY_FUNCTION__); return; } for (int i = 0; i < inNumberPackets; i++) { /* Allocate the packet */ UInt32 size = inPacketDescriptions[i].mDataByteSize; queued_packet_t *packet = (queued_packet_t *)malloc(sizeof(queued_packet_t) + size); packet->identifier = THIS->m_packetIdentifier; // If the stream didn't provide bitRate (m_bitRate == 0), then let's calculate it if (THIS->m_bitRate == 0 && THIS->m_bitrateBufferIndex < kAudioStreamBitrateBufferSize) { // Only keep sampling for one buffer cycle; this is to keep the counters (for instance) duration // stable. THIS->m_bitrateBuffer[THIS->m_bitrateBufferIndex++] = 8 * inPacketDescriptions[i].mDataByteSize / THIS->m_packetDuration; if (THIS->m_bitrateBufferIndex == kAudioStreamBitrateBufferSize) { if (THIS->m_delegate) { THIS->m_delegate->bitrateAvailable(); } } } AS_LOCK_TRACE("streamDataCallback: lock\n"); pthread_mutex_trylock(&THIS->m_packetQueueMutex); /* Prepare the packet */ packet->next = NULL; packet->desc = inPacketDescriptions[i]; packet->desc.mStartOffset = 0; memcpy(packet->data, (const char *)inInputData + inPacketDescriptions[i].mStartOffset, size); if (THIS->m_queuedHead == NULL) { THIS->m_queuedHead = THIS->m_queuedTail = THIS->m_playPacket = packet; } else { THIS->m_queuedTail->next = packet; THIS->m_queuedTail = packet; } THIS->m_cachedDataSize += size; THIS->m_packetIdentifier++; AS_LOCK_TRACE("streamDataCallback: unlock\n"); pthread_mutex_unlock(&THIS->m_packetQueueMutex); } THIS->determineBufferingLimits(); }
All the FreeStreamer project has been rewrite wieth Swift 3.0 in here FreePlayer Answer can be found here AudioStream