BLE using ESP 32 - c++

I am trying to program a BLE client using an ESP32. I have used the attached code (which is the example code from the example section). My problem right now is, how do I get it to show the MAC address of the scanned device only, and how do I change this MAC address into a JSON format for a LoRa chip to transmit? Thank you so much for your time to read this post.
/*
Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleScan.cpp
Ported to Arduino ESP32 by Evandro Copercini
*/
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>
int scanTime = 5; //In seconds
BLEScan* pBLEScan;
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
void onResult(BLEAdvertisedDevice advertisedDevice) {
Serial.printf("Advertised Device: %s \n", advertisedDevice.toString().c_str());
}
};
void setup() {
Serial.begin(115200);
Serial.println("Scanning...");
BLEDevice::init("");
pBLEScan = BLEDevice::getScan(); //create new scan
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster
pBLEScan->setInterval(100);
pBLEScan->setWindow(99); // less or equal setInterval value
}
void loop() {
// put your main code here, to run repeatedly:
BLEScanResults foundDevices = pBLEScan->start(scanTime, false);
Serial.print("Devices found: ");
Serial.println(foundDevices.getCount());
Serial.println("Scan done!");
pBLEScan->clearResults(); // delete results fromBLEScan buffer to release memory
delay(2000);
}

The result of your scan is foundDevices, which contains a list of all found devices. We can iterate through it to access the devices. The List contains BLEAdvertisedDevices which have a method called getAddress(). The address can be converted to a string using toString(). You can print the string or put it into your json container.
Your loop-code could look like this:
void loop() {
// put your main code here, to run repeatedly:
BLEScanResults foundDevices = pBLEScan->start(scanTime, false);
Serial.print("Devices found: ");
for (int i = 0; i < foundDevices.getCount(); ++i)
{
std::string address = foundDevices.getDevice(i).getAddress().toString();
int rssi = foundDevices.getDevice(i).getRSSI();
Serial.print(address.c_str());
Serial.print(rssi);
// TODO: Insert into JSON
}
Serial.println(foundDevices.getCount());
Serial.println("Scan done!");
pBLEScan->clearResults(); // delete results fromBLEScan buffer to release memory
delay(2000);
}

Related

Arduino - GUISlice - gslc_ElemSetTxtStr not updating the text

I am trying to update the text of a dynamic text field created in GUISlice Builder. The code displays the GUI but does not update the text element on the GUI, could someone point out what I am missing? Thanks in advance.
Properties of the text from GUISlice Builder:
ElementRef: pElemDol1
External Storage Size: 7
The code from Arduino IDE (snipped):
#include "Arduino.h"
#include "test_GSLC.h"
// gui elements
#define MAX_STR 100
gslc_tsElemRef* pElemDol1 = NULL;
// dec functions
void lcdFunc();
void setup()
{
// Initiate Serial
Serial.begin(9600);
while (!Serial) ; // wait for serial port to connect
// Initiate the LCD
gslc_InitDebug(&DebugOut);
InitGUIslice_gen();
}
void loop()
{
gslc_Update(&m_gui);
lcdFunc();
}
void lcdFunc()
{
char acTxt[MAX_STR];
snprintf(acTxt, MAX_STR, "%s", "1234");
gslc_ElemSetTxtStr(&m_gui, pElemDol1, "acTxt");
}
Anyone with this problem:
You need to have the gslc_Update(&m_gui); after the elements were updated.
void lcdFunc()
{
char acTxt[MAX_STR];
snprintf(acTxt, MAX_STR, "%s", "1234");
gslc_ElemSetTxtStr(&m_gui, pElemDol1, "acTxt");
gslc_Update(&m_gui);
}

How to store JSON Array in arduino program?

I was working on IOT project for which I needed JSON parsing in NodeMCU.
I saw this sample code for arduino for parsing JSON with the help of ArduinoJson library which worked well and I was able to get and parse the data from url(say url_1) successfully. Now I want to store this data in an array so that when I get data from the other ur2(say url_2) I can compare them with each other and trigger an event repective to the result.
Data in url_1 and url_2 is of form,
["1","1","1","1","0","0","0","0"]
and assume that url_1 had same values as specified.
What I did was I declared an array Data[] in which I stored the parsed JSON values so that I could use them later on in if else statements in the code.
As you can see that the data I am retrieving in url have 1's and 0's only, so what I want to do is that "If get 1 do this", "else do that", which you can see in the code. But the problem is that once I end the connection to the url the Data[] array gives only garbage values which I checked by printing them on serial monitor as shown in the code.
What I believe is that "const char* Data[20];" stores the position of JSON data and when I end the connection, the data at those position is also lost that's why I'm getting the garbage values. Now, I could be wrong since I'm new to this stuff. That's why I wanted to know how to solve this problem which is that if what I said was right, then how could I store the parsed json data in an array so that it is not lost even if the connection to the url has been ended.
(I'm new to this platform so If I did something wrong and wish that you guys can guide me for the future and I also apologize for my broken english).
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <ArduinoJson.h>
const char* Data[20];
const char* ssid = "SSID";
const char* password = "Password";
//Connecting to WiFi
void setup() {
WiFi.mode(WIFI_OFF);
delay(1000);
WiFi.mode(WIFI_STA);// Hides the viewing of ESP as wifi Hotspot
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting...");
}
Serial.println("Connected to WiFi Successfully");
}
void loop()
{
if(WiFi.status()== WL_CONNECTED)
{
HTTPClient http;
//Starting connection to url_1
http.begin("url_1");
int httpCode = http.GET();
if(httpCode > 0)
{
String data = http.getString();
const size_t bufferSize = JSON_ARRAY_SIZE(8) + 20;
DynamicJsonBuffer jsonBuffer(bufferSize);
JsonArray& root = jsonBuffer.parseArray(data);
for(int i=0;i<8;i++){
Data[i] = root[i];
Serial.println("Printing whole Data");
Serial.println(Data[i]);
}
}
http.end();//ending the connetion
for(int i=0;i<8;i++)
{
if(strcmp(Data[i],"1")==0){
Serial.print("if satement, Data = ");
Serial.println(Data[i]);
}
else
{
Serial.print("else satement, Data = ");
Serial.println(Data[i]);
}
}
}
}
Data[] contains pointers to dynamically allocated strings. When you leave the code block with the JSON parser, its destructor is called and therefore the allocated memory can and has been overwritten by something else.
I would suggest to use instead
bool Data[...];
...
// true for "1", false for "0"
Data[i] = strcmp(root[i], "1") == 0;
...
EDIT if you need to store more "complicated" data, e.g. actual strings, you will need to make a copy of the string pointed to by root[i].

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

Write from Serial Port to SD card

I am trying to write from the Serial Port to an SD Card in my Arduino Mega 2560, using a card module.
I want to be able to write in a txt file what I type in the serial com.
#include <SPI.h>
#include <SD.h>
const int chipSelect = 4;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
Serial.print("This is a test and should be ignored");
if (!SD.begin(chipSelect)) {
Serial.println("\nCard failed, or not present");
// don't do anything more:
return;
}
else{
Serial.println("\ncard initialized.");
}
}
void loop() {
// put your main code here, to run repeatedly
File OpenFile = SD.open("test.txt", FILE_WRITE);
if(OpenFile and Serial.available());
{
OpenFile.println(Serial1.read());
OpenFile.close();
}
}
However a continous line of "-1" and "1", without the ", is written to the SD.
Yes, I am able to write to the SD card through other methods...
Cheers, PoP
I notice you are checking Serial.available() but using Serial1 to read from :)
As you have a Mega, you wouldn't get an error as there is Serial and Serial1. I'd say this is your culprit!
The Stream read function will return -1 when there is no data. Also you could lessen the load on your Arduino and do the operation all at once (not open/close for each byte) and purge all available data (Serial.read() only reads a single byte in case you did not know).
void loop() {
File OpenFile = SD.open("test.txt", FILE_WRITE);
if(OpenFile){
while(Serial.available()){
OpenFile.println(Serial.read());
}
OpenFile.close();
}
}
You may want to check if the SD lib supports appending by default or a flag like FILE_APPEND as you will overwrite the file on the next loop if more data becomes available (Serial data isn't instant, your code may loop while receiving the rest of the data).

Using SD.remove() and SD library in Arduino

I'm building a program which takes 10 measurements of an analog voltage on pin0 and is printing it to a log file. The issue I'm running into comes when I try to ensure that the file is blank. I am using SD.remove() in order to remove a previous logfile. When I do this, the new log file is never actually written to. When I remove the call to SD.remove(), the program works correctly. Is this some known bug in the SD library or is there some sneaky way around this?
The code is below.
#include <SD.h>
#define OUTPUT_PIN 9 //Using SparkFun MP3 shield
#define DEFAULT_OUTPUT 10
#define VOLTAGE_REF (5)
//Reads a voltage on pin0. by default, the reference voltage is set to 5 V, but
//it can be changed by changing VOLTAGE_REF.
void setup() {
Serial.begin(9600);
Serial.println("Program Initialized");
pinMode(DEFAULT_OUTPUT ,OUTPUT); //Needs to be on to use the library
pinMode(0, INPUT);
if (!SD.begin(OUTPUT_PIN)) {
//init error
Serial.println("Error initializing SD card. Reset the Arduino and try again");
return;
}
Serial.println("Card sucessfully initialized");
if (SD.exists("LOGFILE.LOG") {
SD.remove("LOGFILE.LOG"); //We don't want to use the same file <<THIS IS THE BUG?
}
delay(10); //Make sure changes are applied
File logFile = SD.open("ANALOG.LOG", FILE_WRITE); //Create a new one every time
if (!SD.exists("LOGFILE.LOG")) {
Serial.println("There was some error making a new instance of the logfile?");
delay(1000);
SD.open("ANALOG.LOG", FILE_WRITE);
}
int i;
if (logFile) {
for(i=0;i<10;i++) {
int j = 0;
char str[64];
Serial.print("Reading analog sensor value");
for(j=0;j<=i;j++) {
Serial.print(".");
}
Serial.println();
logFile.print("Read #");
logFile.print(i+1);
logFile.print(" : ");
logFile.print(doVoltageRead(0));
unsigned char l = logFile.println(" V");
if (!l)
Serial.println("No data written");
delay(500);
}
Serial.println("Done.");
logFile.close(); //Close the logfile
Serial.println("Data sucessfully written");
}
else {
//Couldn't create file
Serial.println("There was an error creating the logfile");
}
}
void loop() {
//We don't really need to do anything here
}
float doVoltageRead(int pin) {
int voltageRead = analogRead(pin);
double divisor = (voltageRead * 0.00097752);
float finalVoltage =(VOLTAGE_REF * divisor);
Serial.println(finalVoltage);
return finalVoltage;
}
So.. First you see if LOGFILE.LOG exists, if it does you delete ANALOG.LOG. Then you create ANALOG.LOG. After that you check if LOGFILE.LOG exists. If it doesn't, you print an error and open ANALOG.LOG.
What exactly is the purpose of LOGFILE.LOG? Shouldn't you just change LOGFILE to ANALOG?
I have found the source of the error. When I called if(SD.exists()) after opening a new logfile, the library didn't like that. I am assuming SD.exists() just checks if the address or object returned by open is NULL. However, calling it when the file is already open would cause some strange behaviors. After removing that call inside open, all is well. Thanks for all the suggestions!