How do I use serial.available 2 times in this code? - arduino-ide

int input;
int choices;
void setup() {
Serial.begin(9600);
Serial.println("BIN, DEC, HEX, OCT Converter\n");
retry:
Serial.println("Kindly choose a number system to convert (1, 2, 3, 4)");
Serial.println("1. BIN\n2. DEC\n3. HEX\n4. OCT\n");
while (Serial.available() == 0) {}
choices = Serial.parseInt();
if (choices == 1) {
Serial.println("You have chosen BIN, please enter a valid input");
}
else if (choices == 2) {
Serial.println("You have chosen DEC, please enter a valid input");
}
else if (choices == 3) {
Serial.println("You have choses HEX, please enter a valid input");
}
else if (choices == 4) {
Serial.println("You have chosen OCT, please enter a valid input");
}
else {
Serial.println("Invalid choice."); \
goto retry;
}
switch (choices) {
case 1: while (Serial.available() == 0) {}
input = Serial.parseInt();
Serial.print("You have input ");
Serial.print(input);
break;
case 2: while (Serial.available() == 0) {}
input = Serial.parseInt();
Serial.print("You have input ");
Serial.print(input);
break;
}
}
void loop() {
}
In the part switch, when I run the code, it shows only 0 and it doesn't give me the option to enter at the serial monitor again.
I can't seem to figure this out, I'm a beginner who's trying to improve in the semantics of Arduino IDE. Thank you

Related

How to write multiple ssid's and passwords to the same json file ESP32

I am currently testing a piece of code using arduinojson6. My goal is to store multiple ssid's and passwords to the esp32 SPIFF.
The uneddited question contained a piece of code that would append to the file rather than reading doc, deleting /SSID.json, adding to doc serialization and saving the file again like I have now, is also not the solution.
the desired json file would be:
{"information":[{ "SSID":"variable blaat1", "PASS1":"variable Abc1", "NUMBER": "1" },{ "SSID":"variable blaat2", "PASS2":"variable Abc2", "NUMBER": "2" },{ "SSID":"variable blaat3", "PASS3":"variable Abc3", "NUMBER": "3" },{ "SSID":"variable blaat4", "PASS4":"variable Abc4", "NUMBER": "4" },{ "SSID":"variable blaat5", "PASS5":"variable Abc5", "NUMBER": "5" }]}
Instead, when more then 1 value is serialized and appended it will read like this:
{
"information": {},
"test": [
"mooiman\n",
"mooiweer\n"
],
"number": [
1,
2
]
}
Maybe some of you know how to serialize it properly.
The code I test with:
#include <Arduino.h>
#include <WiFi.h>
//#include <time.h>
//#include <ESP32Ping.h>
#include "FS.h"
#include "SPIFFS.h"
//#include <HTTPClient.h>
#include <ArduinoJson.h>
int numberofInputs = 1;
String ssid = "YourSSID";
String passwords = "YourPassword";
String readString;
char FileReadBuff[1024];
DynamicJsonDocument doc(1024);
void readFile(fs::FS &fs, const char * path){
if (SPIFFS.exists("/SSID.json") == false)
{
File file = SPIFFS.open("/SSID.json", FILE_WRITE);
if (!file) {
Serial.println("There was an error opening the file for writing");
return;
}
if (file.print("SSID")) {
Serial.println("File was written");
} else {
Serial.println("File write failed");
}
file.close();
}
Serial.printf("Reading file: %s\r\n", path);
File file = fs.open(path);
if(!file || file.isDirectory()){
Serial.println("- failed to open file for reading");
return;
}
uint16_t i = 0;
Serial.println("reading");
while (file.available()) {
FileReadBuff[i] = file.read();
i++;
}
file.close();
}
void CleanFile(fs::FS &fs, const char * path, const char * message) {
for( int i = 0; i < sizeof(FileReadBuff); ++i ){
FileReadBuff[i] = (char)0;
}
File file = SPIFFS.open(path, FILE_WRITE);
if (fs.remove(path)) {
Serial.println("\r\n- file cleaned");
} else {
Serial.println("\r\n- Cleaning failed");
}
file.print(path);
}
void appendFile(fs::FS &fs, const char * path, const char * message){
if (SPIFFS.exists("/SSID.json") == false)
{
File file = SPIFFS.open("/SSID.json", FILE_WRITE);
if (!file) {
Serial.println("There was an error opening the file for writing");
return;
}
if (file.print("SSID")) {
Serial.println("File was written");
} else {
Serial.println("File write failed");
}
file.close();
}
Serial.printf("Appending to file: %s\r\n", path);
File file = fs.open(path, FILE_APPEND);
if(!file){
Serial.println("- failed to open file for appending");
return;
}
if(file.println(message)){
Serial.println("- message appended");
} else {
Serial.println("- append failed");
}
file.close();
}
void Deserialization(){
for( int i = 0; i < sizeof(FileReadBuff); ++i ){
FileReadBuff[i] = (char)0;
}
readFile(SPIFFS, "/SSID.json"); //read everything from ssid.json file
const char * JsonFF = FileReadBuff; // put everything in to const char
Serial.print("Json From File:"); Serial.println(JsonFF);
DeserializationError error = deserializeJson(doc, JsonFF);
if(error){
Serial.print(F("deserializeJson() failed: ")); Serial.println(error.f_str()); // if not legit print error
}
if(!error){
String information = doc["information"];
Serial.println(information);
information = "";
}
}
void testjson(){
readString = "";
while(readString.length() < 1) {
while (Serial.available()) {
delay(10); //small delay to allow input buffer to fill
if (Serial.available() > 0) {
char c = Serial.read(); //gets one byte from serial buffer
if (c == ',') {
break;
} //breaks out of capture loop to print readstring
readString += c;
} //makes the string readString
}
if (readString.length() > 0) {
Serial.println(readString); //prints string to serial port out
if (readString.indexOf("READ") >= 0) {
Serial.println("reading file");
readFile(SPIFFS, "/SSID.json");
Serial.println(FileReadBuff);
for( int i = 0; i < sizeof(FileReadBuff); ++i ){
FileReadBuff[i] = (char)0;
}
}
if (readString.indexOf("DES") >= 0) { //DEZ deserialize will result in an error because json file is currently not valid
Serial.println("reading deserialized json");
Deserialization();
}
if (readString.indexOf("CLEAN") >= 0) { //CLEAN cleans the SSID.json file
Serial.println("reading deserialized json");
CleanFile(SPIFFS, "/SSID.json", "");
}
if (readString.indexOf("WRANDOM") >= 0){ //WRANDOM writes a random string to the SSID.json file
readString = "";
Serial.println("Going to write the following input:"); //waiting for user input
while(readString.length() < 1) {
while (Serial.available()) {
delay(10); //small delay to allow input buffer to fill
if (Serial.available() > 0) {
char c = Serial.read(); //gets one byte from serial buffer
if (c == ',') {
break;
} //breaks out of capture loop to print readstring
readString += c;
} //makes the string readString
}
if (readString.length() > 0) {
Serial.println(readString); //prints string to serial port out
`here is the part we're talking about`
CleanFile(SPIFFS, "/SSID.json", "");
JsonObject information = doc.createNestedObject("information");
String SerializedJson = "";
doc["test"].add(readString);
doc["number"].add(numberofInputs);
serializeJsonPretty(doc, SerializedJson);
appendFile(SPIFFS, "/SSID.json", SerializedJson.c_str());
SerializedJson = "";
numberofInputs ++;
return;
}
}
}
}
}
}
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
if (!SPIFFS.begin(true)) {
Serial.println("An Error has occurred while mounting SPIFFS");
return;
}
if (SPIFFS.exists("/SSID.json") == false)
{
File file = SPIFFS.open("/SSID.json", FILE_WRITE);
if (!file) {
Serial.println("There was an error opening the file for writing");
return;
}
if (file.print("SSID")) {
Serial.println("File was written");
} else {
Serial.println("File write failed");
}
file.close();
}
WiFi.mode(WIFI_MODE_STA);
WiFi.begin(ssid.c_str(), passwords.c_str());
while (WiFi.status() != WL_CONNECTED) { //Check for the connection
delay(1000);
Serial.print(".");
}
Serial.println("Connected");
}
void loop() {
// put your main code here, to run repeatedly:
readString = ""; //clears variable for new input
Serial.println("Ready for new input: ");
testjson();
}
So when you serial write WRANDOM you'll get promted to put in something.
When that is recieved it will store that in json.
Do that another time.
Next when you serial write READ it will show you the saved /SSID.json.
Thanks in advance.
Note that the DynamicJsonDocument startsof empty.
PS. I know littlefs is the new spiff but lets first try to make this work (or I need to make sepperate files for every ssid+password)
Here is a test sketch you can implement to your project.
I did not had the time to write more detailed sketch than this.
Let me know if you have any question about this
#include <Arduino.h>
#include "FS.h"
#include <LittleFS.h>
#include <ArduinoJson.h>
#define DOC_SIZE 5000
/*
Example JSON :
{
"information":[
{ "SSID":"variable blaat1", "PASS1":"variable Abc1", "NUMBER": "1" },
{ "SSID":"variable blaat2", "PASS2":"variable Abc2", "NUMBER": "2" },
{ "SSID":"variable blaat3", "PASS3":"variable Abc3", "NUMBER": "3" },
{ "SSID":"variable blaat4", "PASS4":"variable Abc4", "NUMBER": "4" },
{ "SSID":"variable blaat5", "PASS5":"variable Abc5", "NUMBER": "5" }
]
}
*/
/*
When you create a JSON array, you don't need to push the index of the object, since you can later
ask for the array size, therefor you know the indexes. Also you don't need to separate the passwords
like PASS1 or PASS2 since every cred is a separate object.
*/
void addCredentials( const char* SSID, const char* PW ){
// Create a static JSON document.
StaticJsonDocument fileDoc(DOC_SIZE);
// Open the file containing the credentials
File credFile = LittleFS.open(FILE_PATH,FILE_READ);
// Check if it opened.
if( !credFile ){ Serial.println("Failed to open file"); return; }
// Deserialize the file
DeserializationError error = deserializeJson(fileDoc, credFile );
// Check if the deserialization has any errors.
if( error ){ Serial.printf("Error on deserialization: %s\n", error.c_str() );
// Get the info array from the JSON.
JsonArray infoArr = fileDoc["information"].as<JsonArray>();
// Create a new object inside the array.
JsonObject newCred = infoArr.createNestedObject();
// Add credentials to the object.
newCred["SSID"] = SSID;
newCred["PASS"] = PW;
// Serialize everythig back to the file.
serializeJson(fileDoc, credFile);
// Close the file.
credFile.close();
}
// Open the file and put the pretty json into the serial directly.
void printFileContent(){
File credFile = LittleFS.open(FILE_PATH,FILE_READ);
if( !credFile ){ Serial.println("Failed to open file"); return; }
serializeJsonPretty(Serial, credFile);
credFile.close();
}
void clearFile(){
if( !LittleFS.exists(FILE_PATH) ){ Serial.println("Credentials file does not exists yet!"); return; }
File credFile = LittleFS.open(FILE_PATH,FILE_READ);
credFile.remove();
}
void getUserInput(){
if( !Serial.available() ){ return; }
// Get the credentials or whatever from the serial
// and call the **addCredentials( const char* SSID, const char* PW );** function.
}
void setup() {
Serial.begin(115200);
}
void loop() {
getUserInput();
}
I got it figured out with help from Dr.Random. It wasn't the full answer but it helped getting the json format and apend to that file correctly. The following code is a working example.
#include <Arduino.h>
#include <WiFi.h>
#include "FS.h"
#include "LittleFS.h"
#include <ArduinoJson.h>
#define FORMAT_LITTLEFS_IF_FAILED true
#define DOC_SIZE 5000
#define FILE_PATH "/SSID.json"
String ssid = "yourssid";
String passwords = "yourpass";
String readString;
char FileReadBuff[1024];
void readFile(fs::FS &fs, const char * path){
Serial.printf("Reading file: %s\r\n", path);
File file = fs.open(path);
if(!file || file.isDirectory()){
Serial.println("- failed to open file for reading");
return;
}
Serial.println("- read from file:");
while(file.available()){
Serial.write(file.read());
}
file.close();
}
void Showone(int wichone){
DynamicJsonDocument doc(DOC_SIZE);
File credFile = LittleFS.open(FILE_PATH, FILE_READ);// open file for reading
DeserializationError error = deserializeJson(doc, credFile);// deserialize json
if( !credFile ){ Serial.println("Failed to open file"); return; }// if file doesn't exist, return
const char* SSID = doc[wichone]["SSID"]; //
const char* PASS = doc[wichone]["PASS"]; //
Serial.print("SSID and PASS = "); Serial.print(SSID); Serial.print(PASS); Serial.print(" "); Serial.println(" ");
credFile.close();
}
void addCredentials(const char * input){
DynamicJsonDocument doc(DOC_SIZE);// create json doc
String Serialized; // create string to store serialized json
File credFile = LittleFS.open(FILE_PATH, FILE_READ);// open file for reading
if( !credFile ){ Serial.println("Failed to open file"); return; }// if file doesn't exist, return
DeserializationError error = deserializeJson(doc, credFile);// deserialize json
if( error ){ Serial.printf("Error on deserialization: %s\n", error.c_str() );} //error when spiff is empty or not formatted correctly
JsonArray inforArr = doc["information"].as<JsonArray>();// get array from json
JsonObject newCred = doc.createNestedObject();// create new object in json
newCred["SSID"] = input;
newCred["PASS"] = input;
serializeJsonPretty(doc, Serialized);
Serial.print("input = "); Serial.println(input);
Serial.print("Serialized: "); Serial.println(Serialized);
File credFile2 = LittleFS.open(FILE_PATH, FILE_WRITE);// open file for writing
credFile2.print(Serialized);
credFile2.close();
credFile.close();
Serialized = "";
}
void testjson(){
readString = "";
while(readString.length() < 1) {
while (Serial.available()) {
delay(10); //small delay to allow input buffer to fill
if (Serial.available() > 0) {
char c = Serial.read(); //gets one byte from serial buffer
if (c == ',') {
break;
} //breaks out of capture loop to print readstring
readString += c;
} //makes the string readString
}
if (readString.length() > 0) {
Serial.println(readString); //prints string to serial port out
if (readString.indexOf("READ") >= 0) {
Serial.println("reading file");
readFile(LittleFS, "/SSID.json");
Serial.println(FileReadBuff);
for( int i = 0; i < sizeof(FileReadBuff); ++i ){
FileReadBuff[i] = (char)0;
}
}
if (readString.indexOf("SHOW") >= 0) {
readString = "";
Serial.println("Showing the following input(number): "); //waiting for user input
while(readString.length() < 1) {
while (Serial.available()) {
delay(10); //small delay to allow input buffer to fill
if (Serial.available() > 0) {
char c = Serial.read(); //gets one byte from serial buffer
if (c == ',') {
break;
} //breaks out of capture loop to print readstring
readString += c;
} //makes the string readString
}
if (readString.length() > 0) {
Serial.println(readString); //prints string to serial port out
Showone(readString.toInt());
}
}
}
if (readString.indexOf("CLEAN") >= 0) { //CLEAN cleans the SSID.json file
Serial.println("reading deserialized json");
File credFile = LittleFS.open(FILE_PATH, FILE_WRITE);// open file for writing
credFile.print("");
credFile.close();
}
if (readString.indexOf("WRANDOM") >= 0){ //WRANDOM writes a random string to the SSID.json file
readString = "";
Serial.println("Going to write the following input:"); //waiting for user input
while(readString.length() < 1) {
while (Serial.available()) {
delay(10); //small delay to allow input buffer to fill
if (Serial.available() > 0) {
char c = Serial.read(); //gets one byte from serial buffer
if (c == ',') {
break;
} //breaks out of capture loop to print readstring
readString += c;
} //makes the string readString
}
if (readString.length() > 0) {
Serial.println(readString); //prints string to serial port out
addCredentials(readString.c_str());
}
}
}
}
}
}
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
if(!LittleFS.begin(FORMAT_LITTLEFS_IF_FAILED)){
Serial.println("LittleFS Mount Failed");
return;
}
//if /ssid.json doesn't exist, create it littlefs
if(!LittleFS.exists(FILE_PATH)){
Serial.println("File doesn't exist, creating it");
File credFile = LittleFS.open(FILE_PATH, FILE_WRITE);
if(!credFile){
Serial.println("Failed to create file");
return;
}
credFile.close();
}
WiFi.mode(WIFI_MODE_STA);
WiFi.begin(ssid.c_str(), passwords.c_str());
while (WiFi.status() != WL_CONNECTED) { //Check for the connection
delay(1000);
Serial.print(".");
}
Serial.println("Connected");
}
void loop() {
// put your main code here, to run repeatedly:
readString = ""; //clears variable for new input
Serial.println("Ready for new input: ");
testjson();
}
Any improvements are still desirable.

Arduino IDE does not recognize struct

I am trying to send 2 int variables from client to server using ESP-NOW.
The full code of the client is:
/**
ESPNOW - Basic communication - Master
Date: 26th September 2017
Author: Arvind Ravulavaru <https://github.com/arvindr21>
Purpose: ESPNow Communication between a Master ESP32 and a Slave ESP32
Description: This sketch consists of the code for the Master module.
Resources: (A bit outdated)
a. https://espressif.com/sites/default/files/documentation/esp-now_user_guide_en.pdf
b. http://www.esploradores.com/practica-6-conexion-esp-now/
<< This Device Master >>
Flow: Master
Step 1 : ESPNow Init on Master and set it in STA mode
Step 2 : Start scanning for Slave ESP32 (we have added a prefix of `slave` to the SSID of slave for an easy setup)
Step 3 : Once found, add Slave as peer
Step 4 : Register for send callback
Step 5 : Start Transmitting data from Master to Slave
Flow: Slave
Step 1 : ESPNow Init on Slave
Step 2 : Update the SSID of Slave with a prefix of `slave`
Step 3 : Set Slave in AP mode
Step 4 : Register for receive callback and wait for data
Step 5 : Once data arrives, print it in the serial monitor
Note: Master and Slave have been defined to easily understand the setup.
Based on the ESPNOW API, there is no concept of Master and Slave.
Any devices can act as master or salve.
*/
#include <esp_now.h>
#include <WiFi.h>
// Global copy of slave
esp_now_peer_info_t slave;
#define CHANNEL 1
#define PRINTSCANRESULTS 0
#define DELETEBEFOREPAIR 0
// Init ESP Now with fallback
void InitESPNow() {
WiFi.disconnect();
if (esp_now_init() == ESP_OK) {
Serial.println("ESPNow Init Success");
}
else {
Serial.println("ESPNow Init Failed");
// Retry InitESPNow, add a counte and then restart?
// InitESPNow();
// or Simply Restart
ESP.restart();
}
}
// Scan for slaves in AP mode
void ScanForSlave() {
int8_t scanResults = WiFi.scanNetworks();
// reset on each scan
bool slaveFound = 0;
memset(&slave, 0, sizeof(slave));
Serial.println("");
if (scanResults == 0) {
Serial.println("No WiFi devices in AP Mode found");
} else {
Serial.print("Found "); Serial.print(scanResults); Serial.println(" devices ");
for (int i = 0; i < scanResults; ++i) {
// Print SSID and RSSI for each device found
String SSID = WiFi.SSID(i);
int32_t RSSI = WiFi.RSSI(i);
String BSSIDstr = WiFi.BSSIDstr(i);
if (PRINTSCANRESULTS) {
Serial.print(i + 1);
Serial.print(": ");
Serial.print(SSID);
Serial.print(" (");
Serial.print(RSSI);
Serial.print(")");
Serial.println("");
}
delay(10);
// Check if the current device starts with `Slave`
if (SSID.indexOf("Slave") == 0) {
// SSID of interest
Serial.println("Found a Slave.");
Serial.print(i + 1); Serial.print(": "); Serial.print(SSID); Serial.print(" ["); Serial.print(BSSIDstr); Serial.print("]"); Serial.print(" ("); Serial.print(RSSI); Serial.print(")"); Serial.println("");
// Get BSSID => Mac Address of the Slave
int mac[6];
if ( 6 == sscanf(BSSIDstr.c_str(), "%x:%x:%x:%x:%x:%x", &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5] ) ) {
for (int ii = 0; ii < 6; ++ii ) {
slave.peer_addr[ii] = (uint8_t) mac[ii];
}
}
slave.channel = CHANNEL; // pick a channel
slave.encrypt = 0; // no encryption
slaveFound = 1;
// we are planning to have only one slave in this example;
// Hence, break after we find one, to be a bit efficient
break;
}
}
}
if (slaveFound) {
Serial.println("Slave Found, processing..");
} else {
Serial.println("Slave Not Found, trying again.");
}
// clean up ram
WiFi.scanDelete();
}
// Check if the slave is already paired with the master.
// If not, pair the slave with master
bool manageSlave() {
if (slave.channel == CHANNEL) {
if (DELETEBEFOREPAIR) {
deletePeer();
}
Serial.print("Slave Status: ");
// check if the peer exists
bool exists = esp_now_is_peer_exist(slave.peer_addr);
if ( exists) {
// Slave already paired.
Serial.println("Already Paired");
return true;
} else {
// Slave not paired, attempt pair
esp_err_t addStatus = esp_now_add_peer(&slave);
if (addStatus == ESP_OK) {
// Pair success
Serial.println("Pair success");
return true;
} else if (addStatus == ESP_ERR_ESPNOW_NOT_INIT) {
// How did we get so far!!
Serial.println("ESPNOW Not Init");
return false;
} else if (addStatus == ESP_ERR_ESPNOW_ARG) {
Serial.println("Invalid Argument");
return false;
} else if (addStatus == ESP_ERR_ESPNOW_FULL) {
Serial.println("Peer list full");
return false;
} else if (addStatus == ESP_ERR_ESPNOW_NO_MEM) {
Serial.println("Out of memory");
return false;
} else if (addStatus == ESP_ERR_ESPNOW_EXIST) {
Serial.println("Peer Exists");
return true;
} else {
Serial.println("Not sure what happened");
return false;
}
}
} else {
// No slave found to process
Serial.println("No Slave found to process");
return false;
}
}
void deletePeer() {
esp_err_t delStatus = esp_now_del_peer(slave.peer_addr);
Serial.print("Slave Delete Status: ");
if (delStatus == ESP_OK) {
// Delete success
Serial.println("Success");
} else if (delStatus == ESP_ERR_ESPNOW_NOT_INIT) {
// How did we get so far!!
Serial.println("ESPNOW Not Init");
} else if (delStatus == ESP_ERR_ESPNOW_ARG) {
Serial.println("Invalid Argument");
} else if (delStatus == ESP_ERR_ESPNOW_NOT_FOUND) {
Serial.println("Peer not found.");
} else {
Serial.println("Not sure what happened");
}
}
//=================DATA======================
typedef struct test_struct {
int x;
int y;
} test_struct;
test_struct test;
test.x = 10;
test.y = 20;
//uint8_t data = 0;
// send data
void sendData() {
//data++;
const uint8_t *peer_addr = slave.peer_addr;
Serial.print("Sending: "); Serial.println(test);
esp_err_t result = esp_now_send(peer_addr, (uint8_t *) &test,
sizeof(test_struct));
Serial.print("Send Status: ");
if (result == ESP_OK) {
Serial.println("Success");
} else if (result == ESP_ERR_ESPNOW_NOT_INIT) {
// How did we get so far!!
Serial.println("ESPNOW not Init.");
} else if (result == ESP_ERR_ESPNOW_ARG) {
Serial.println("Invalid Argument");
} else if (result == ESP_ERR_ESPNOW_INTERNAL) {
Serial.println("Internal Error");
} else if (result == ESP_ERR_ESPNOW_NO_MEM) {
Serial.println("ESP_ERR_ESPNOW_NO_MEM");
} else if (result == ESP_ERR_ESPNOW_NOT_FOUND) {
Serial.println("Peer not found.");
} else {
Serial.println("Not sure what happened");
}
}
// callback when data is sent from Master to Slave
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
char macStr[18];
snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x",
mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
Serial.print("Last Packet Sent to: "); Serial.println(macStr);
Serial.print("Last Packet Send Status: "); Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
}
void setup() {
Serial.begin(115200);
//Set device in STA mode to begin with
WiFi.mode(WIFI_STA);
Serial.println("ESPNow/Basic/Master Example");
// This is the mac address of the Master in Station Mode
Serial.print("STA MAC: "); Serial.println(WiFi.macAddress());
// Init ESPNow with a fallback logic
InitESPNow();
// Once ESPNow is successfully Init, we will register for Send CB to
// get the status of Trasnmitted packet
esp_now_register_send_cb(OnDataSent);
}
void loop() {
// In the loop we scan for slave
ScanForSlave();
// If Slave is found, it would be populate in `slave` variable
// We will check if `slave` is defined and then we proceed further
if (slave.channel == CHANNEL) { // check if slave channel is defined
// `slave` is defined
// Add slave as peer if it has not been added already
bool isPaired = manageSlave();
if (isPaired) {
// pair success or already paired
// Send data to device
sendData();
} else {
// slave pair failed
Serial.println("Slave pair failed!");
}
}
else {
// No slave found to process
}
// wait for 3seconds to run the logic again
delay(3000);
}
everything worked when the data sent was just 0, when I substituted this struct ( it's just past the =========DATA======== line in the main code)
typedef struct test_struct {
int x;
int y;
} test_struct;
test_struct test;
test.x = 10;
test.y = 20;
I get an error message 'test' does not name a type.
any ideas?
I figured it out, the struct definition has to be inside a function, be it setup or any other. Thank you all for looking at this
Ok I thought I figured it out, but I just wrote another sketch and placed the struct ahead of all functions and it's working , so honestly I have no idea of what is going on, anybody else know the answer, or is this question so stupid that no one wants to comment? Which is fine with me, I am still a great neophyte at this, so if you can help, great, if not , thank you anyway, this is still a great resource for a newbie😅
You're trying to assign a value to test outside of any executable code. The definition is fine, the assignment test.x=10 is code that needs to be executed inside a new or existing function like setup() or loop(). Try assigning the value during initialization as shown below. That way the compiler puts the value in when it assigns memory to that variable.
typedef struct{
int x;
int y;
} test_struct;
test_struct t={10,20};

Stm Cube IDE ERROR : Comparison error for function

I am experimenting with the STM32f407vg board through the STMBUBEIDE program.
First of all, I prepare my own library file and make the settings in the interrupt section.
What if the reason I can't get rid of this error?
First of all, I have a griodriver.c file for my src file. And my definition in it:
uint8_t portcode = GPIO_BASE_ADDR_TO_CODE (pGPIOHandle-> pGPIOx);
Then I write my function so that this comes back.
uint16_t GPIO_BASE_ADDR_TO_CODE(*x)
{
if(x==GPIOA) { return 0; }
else if(x==GPIOB) { return 1; }
else if(x==GPIOC) { return 2; }
else if(x==GPIOD) { return 3; }
else if(x==GPIOE) { return 4; }
else if(x==GPIOF) { return 5; }
else if(x==GPIOG) { return 6; }
}
If I remove the pointer inside the loop, I get a comparison between pointer and interger error.
Whenever I compile I get an error.
My error says this for the function:
This is warnings error.
Description Resource Path Location Type
implicit declaration of function 'GPIO_BASE_ADDR_TO_CODE'; did you mean 'GPIOJ_BASEADDR'?
[- Wimplicit-function-declaration] stm32f407xx_gpio_driver.c /stm32f407xx/drivers/Src
line 253 C/C++ Problem
But there are 2 other errors I get as ERROR.
enter image description here
enter image description here
First:
1. ERROR: Description Resource Path Location Type
make: *** [drivers/Src/subdir.mk:18: drivers/Src/stm32f407xx_gpio_driver.o]
Error 1 stm32f407xx C/C++ Problem
SEcond:
Description Resource Path Location Type
expected declaration specifiers or '...' before '*' token stm32f407xx_gpio_driver.c
/stm32f407xx/drivers/Src line 168 C/C++ Problem
Error Screen:
enter image description here
When I change this part like a below,
uint16_t GPIO_BASE_ADDR_TO_CODE(uint8_t x)
{
if( x==GPIOA) { return 0; }
else if(x==GPIOB) { return 1; }
else if(x==GPIOC) { return 2; }
else if(x==GPIOD) { return 3; }
else if(x==GPIOE) { return 4; }
else if(x==GPIOF) { return 5; }
else if(x==GPIOG) { return 6; }
return 0;
}
My errors change like that :
enter image description here
Instead of calling it in a function, I defined it as #define for
GPIO_BASEADDR_TO_CODE
Also removed if else condition. I used a C third conditional.
Now is no errors after 3 days later:))
You can see it below pictures what I did.
#define GPIO_BASEADDR_TO_CODE(x) ((x == GPIOA)?0 :\
(x == GPIOB)?1 :\
(x == GPIOA)? :\
(x == GPIOA)?3 :\
(x == GPIOA)?4 :\
(x == GPIOA)?5 :\
(x == GPIOA)?6 :\
(x == GPIOA)?7 :0 )
enter image description here

C++/CLI & mySQL: How to form queries from user input/choice

This is for homework, so I understand if you don't want to just give me the answer. That being said, if you do decide to "give" me anything, please explain what it does, and why, and how, because, to be perfectly honest, I'm in an online program and the teacher/class style is very unhelpful. I.E. When we ask for help, we just get a link to the MSDN main page and are told to figure it out. (PS: if anyone ever considers going to 'City University' for a MS in CS: don't).
I've been working on this 1 problem for over 30 hours now, and searched high and low on this website and many others, and have been coming up with not much to show for it. Any help, explanations, tips, etc, would be greatly appreciated.
The assignment is to take user input in a C++/CLI console app, connect it to a mySQL database via ODBC32, and run a loop asking for user choice about which table to pull up and display. I have done the loop, I have gotten the db connected (I think/hope), but I can't seem to convert the users choice into a valid SQL query, or maybe it's just a display issue. Since I am quite literally teaching myself, I have to admit that I don't really know if this is where the true root of the problem lies, or if I have grossly misunderstood what this code is and does.
My current code:
#include "stdafx.h"
#include <string>
#include <sql.h>
#include <sqlext.h>
#pragma comment( lib, "odbc32.lib" )
#define EMPLOYEE_ID_LEN 32
SQLHENV henv = NULL;
SQLHDBC hdbc = NULL;
SQLRETURN retcode;
SQLHSTMT hstmt = NULL;
SQLSMALLINT sCustID;
SQLCHAR szEmployeeID[EMPLOYEE_ID_LEN];
SQL_DATE_STRUCT dsOrderDate;
SQLINTEGER cbCustID = 0, cbOrderDate = 0, cbEmployeeID = SQL_NTS;
int main()
{
retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER*)SQL_OV_ODBC3, 0);
retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
retcode = SQLSetConnectAttr(hdbc, SQL_LOGIN_TIMEOUT, (SQLPOINTER)5, 0);
retcode = SQLConnect(hdbc, (SQLWCHAR*) "MySqlWorld", SQL_NTS, (SQLWCHAR*)NULL, 0, NULL, 0);
retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
bool boolExit = false;
while (boolExit == false)
{
String^ strChoice = "";
do {
if (strChoice == "a")
{
strChoice = "city";
break;
}
else if (strChoice == "b")
{
strChoice = "country";
break;
}
else if (strChoice == "c")
{
strChoice = "countrylanguage";
break;
}
else if (strChoice == "e")
{
boolExit = true;
break;
}
else
{
Console::WriteLine();
Console::WriteLine("Please choose from the following options:");
Console::WriteLine("A: Enter last name to retreive first name, home address, and work phone number.");
Console::WriteLine("B: Enter last name to retrieve department.");
Console::WriteLine("C: Enter department to retrieve list of employee last names, addresses, and work phone numbers for members of that department.");
Console::WriteLine("E: Exit");
strChoice = Console::ReadLine()->ToLower();
}
} while (true);
if (boolExit == false)
{
char* cstrTempQuery = (char*)(void*)System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(strChoice);
SQLCHAR sqlTempQuery[32];
strcpy_s((char*)sqlTempQuery, _countof(sqlTempQuery), (const char *)cstrTempQuery);
retcode = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, EMPLOYEE_ID_LEN, 0, sqlTempQuery, 0, &cbEmployeeID);
retcode = SQLPrepare(hstmt, (SQLWCHAR*)"SELECT * from ?", SQL_NTS);
retcode = SQLExecute(hstmt);
}
} // end while (boolExit == false)
} // end main()
The code results in no errors of any sort, but doesn't do anything. My loop shows, I make a selection, and nothing happens, except that the loop repeats.
I got most of this code from this page: https://learn.microsoft.com/en-us/sql/odbc/reference/syntax/sqlbindparameter-function
You cannot bind tablename or field name parameters. You can dynamically construct the query using using curly braces. It is not advised but possible with this:
https://stackoverflow.com/a/11327831/5389997
Something similar to : SELECT * FROM {$mytable}
Since you're specifying your tables that you need then you don't have to worry so much about the SQL injection angle.
It also looks like you're not updating the boilerplate code to have your variables.
#include "stdafx.h"
#include <string>
#include <sql.h>
#include <sqlext.h>
#pragma comment( lib, "odbc32.lib" )
#define QUERY_LEN 32
SQLHENV henv = NULL;
SQLHDBC hdbc = NULL;
SQLRETURN retcode;
SQLHSTMT hstmt = NULL;
SQLCHAR szQueryVar[QUERY_LEN];
SQLCHAR queryVar = SQL_NTS;
int main()
{
retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER*)SQL_OV_ODBC3, 0);
retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
retcode = SQLSetConnectAttr(hdbc, SQL_LOGIN_TIMEOUT, (SQLPOINTER)5, 0);
retcode = SQLConnect(hdbc, (SQLWCHAR*) "MySqlWorld", SQL_NTS, (SQLWCHAR*)NULL, 0, NULL, 0);
retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
bool boolExit = false;
while (boolExit == false)
{
String^ strChoice = "";
String^ tableName = "";
String^ queryField = "";
String^ queryVar = "";
do {
if (strChoice == "a")
{
tableName = "address";
queryField = "last_name";
queryVar = Console::ReadLine();
break;
}
else if (strChoice == "b")
{
tableName = "department";
queryField = "last_name";
queryVar = Console::ReadLine();
break;
}
else if (strChoice == "c")
{
tableName = "department";
queryField = "department";
queryVar = Console::ReadLine();
break;
}
else if (strChoice == "e")
{
boolExit = true;
break;
}
else
{
Console::WriteLine();
Console::WriteLine("Please choose from the following options:");
Console::WriteLine("A: Enter last name to retreive first name, home address, and work phone number.");
Console::WriteLine("B: Enter last name to retrieve department.");
Console::WriteLine("C: Enter department to retrieve list of employee last names, addresses, and work phone numbers for members of that department.");
Console::WriteLine("E: Exit");
strChoice = Console::ReadLine()->ToLower();
}
} while (true);
if (boolExit == false)
{
char* cstrTempQuery = (char*)(void*)System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(strChoice);
SQLCHAR sqlTempQuery[32];
strcpy_s((char*)sqlTempQuery, _countof(sqlTempQuery), (const char *)cstrTempQuery);
retcode = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, QUERY_LEN, 0, sqlTempQuery, 0, &queryVar);
query = (SQLCHAR*)"SELECT * from {$tableName} where {$queryField} = ?";
retcode = SQLPrepare(hstmt, queryVar, SQL_NTS);
retcode = SQLExecute(hstmt);
}
} // end while (boolExit == false)
} // end main()

QSqlTableModel: last checkstate change doesn't reflect on database

I have MySQL database, QSqlTableModel and QTableView with few checkbox columns. It works, but the last click on checkbox does not cause changes in database. It means that if I launch a program, click on some checkbox once and close program, no changes in database will be made. If I'll change the state of several checkboxes, the last change will not be shown in database. Maybe there's something wrong in my setData method?
bool PartyModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
QString h=headerData(index.column(),Qt::Horizontal).toString();
QVariant v=value;
switch(role)
{
case Qt::CheckStateRole:
if(h=="One" || h=="Two" || h=="Three" || h=="Four")
{
if(value.toInt()==Qt::Unchecked) v=0;
else v=1;
bool ret = QSqlTableModel::setData(index,v,Qt::EditRole);
if(ret) emit dataChanged(index,index);
return ret;
}
break;
case Qt::DisplayRole:
case Qt::EditRole:
.......
break;
default:
break;
}
return QSqlTableModel::setData(index,v,role);
}
QVariant PartyModel::data(const QModelIndex &idx, int role) const
{
QString h=headerData(idx.column(),Qt::Horizontal).toString();
QVariant v=QSqlTableModel::data(idx,role);
switch(role)
{
case Qt::CheckStateRole:
if(h=="One" || h=="Two" || h=="Three" || h=="Four")
v = (QSqlTableModel::data(idx,Qt::DisplayRole).toInt()==0 ? Qt::Unchecked : Qt::Checked);
break;
case Qt::DisplayRole:
if(h=="One" || h=="Two" || h=="Three" || h=="Four")
v="";
break;
default:
break;
}
return v;
}
Qt::ItemFlags PartyModel::flags(const QModelIndex &index) const
{
QString h=headerData(index.column(),Qt::Horizontal).toString();
Qt::ItemFlags f=QSqlQueryModel::flags(index);
if(h=="One" || h=="Two" || h=="Three" || h=="Four")
{
f |= Qt::ItemIsUserCheckable;
f &= ~Qt::ItemIsEditable;
}
return f;
}
The default "edit strategy" of QSqlTabelModel is OnRowChange, which means that changes are only submitted, as the name suggests, when the selected row changes. To submit changes to the database at other times, you need to either change the edit strategy to OnFieldChange, or manually call submit() or submitAll() at appropriate times.