Check if var in array. If not in array, add it in

Hi All,

I am trying to check an array for a string. If the string is not in the array, add it to the array.

Here's what I have so far:

//Should check if string in array. If string not in array, add it to array.
//gives error messages
String knownAddr[20];
String newAddr2 = "address1";
//char newAddr2;
void setup() {
  Serial.begin(115200);
}
void loop() {
  for (int i = 0; i < 20; i++) {
    if (strcmp(newAddr2, knownAddr[i]) == 0) {
      Serial.println("Matching Addr already inside array.");
      break;
    }
    else {
      strcat(knownAddr, newAddr2);
      Serial.println("newAddr3 added to knownAddr array!");
    }
  }
}

The error code I am getting is:


Arduino: 1.8.16 (Windows 10), Board: "WEMOS LOLIN32 Lite, 80MHz, No OTA (Large APP), 240MHz (WiFi/BT), 921600"
In function 'void loop()':

serial_input_demo:12:16: error: cannot convert 'String' to 'const char*'

     if (strcmp(newAddr2, knownAddr[i]) == 0) {

                ^~~~~~~~

In file included from C:\Users\triop\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.1\cores\esp32/Arduino.h:29,

                 from sketch\serial_input_demo.ino.cpp:1:

c:\users\triop\appdata\local\arduino15\packages\esp32\tools\xtensa-esp32-elf-gcc\gcc8_4_0-esp-2021r2\xtensa-esp32-elf\sys-include\string.h:36:14: note:   initializing argument 1 of 'int strcmp(const char*, const char*)'

 int  strcmp (const char *, const char *);

              ^~~~~~~~~~~~

serial_input_demo:17:14: error: cannot convert 'String*' to 'char*'

       strcat(knownAddr, newAddr2);

              ^~~~~~~~~

In file included from C:\Users\triop\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.1\cores\esp32/Arduino.h:29,

                 from sketch\serial_input_demo.ino.cpp:1:

c:\users\triop\appdata\local\arduino15\packages\esp32\tools\xtensa-esp32-elf-gcc\gcc8_4_0-esp-2021r2\xtensa-esp32-elf\sys-include\string.h:34:16: note:   initializing argument 1 of 'char* strcat(char*, const char*)'

 char  *strcat (char *__restrict, const char *__restrict);

                ^

exit status 1

cannot convert 'String' to 'const char*'

In the ultimate end purpose of this function, it would take a string from a bluetooth scan as input. The string is encoded like this:

newAddressdetected = (advertisedDevice.getDevice().toString().c_str());

You are trying to manipulate Strings (capital S) with functions such as strcmp() and strcat() that work with strings (lowercase s)

Use Strings or preferably strings throughout

@triops124 you posted in the wrong section troubleshooting and installation is only for getting the system going. It says it is NOT for your project.

Your post is clearly about your project so I have moved it here.

Straight forward. Arduino is C++ so there are numerous fun ways to solve... however, read the link:
https://forum.arduino.cc/t/correct-way-to-dynamically-resize-an-array-using-new-and-delete/508315/2

I've attached something I did similar for WiFi on the ESP8266. 'tis been a while and both ESP8266 core and IDF have advanced as has ArduinoIDE ... may not compile now error-free wo some tinkering :sunglasses:

ESP8266 Min-Sniff.zip (5.4 KB)

Try:
if (newAddr2 == knownAddr[i]) {

That is not how you add an element to an array. You have to keep count of how many of your 20 entries you have used:
int knownAddrIndex = 0;

Then you can:
knownAddr[knownAddrIndex++] = newAddr2;

Then change:

to:
for (int i = 0; i < knownAddrIndex; i++) {

You are using String class, it can be compared to other String with ==

I followed your recommendation but neither "if" or "else" statement is printing to the serial monitor. See code below:

int knownAddrIndex = 0;
String knownAddr[20];
String newAddr2 = "address1";


void setup() {
  Serial.begin(115200);
  delay(5000);
  Serial.println("started up");
}
void loop() {
  for (int i = 0; i < knownAddrIndex; i++) {
    delay(3000);
     if (newAddr2 == knownAddr[i]) {
      Serial.println("Matching Addr already inside array.");
        }
    else {
      knownAddr[knownAddrIndex++] = newAddr2;
      Serial.println("newAddr2 added to knownAddr array!");
      }
   
  }
}

Hello

As knownAddrIndex is 0, the for loop will not execute at all because the condition i < knownAddrIndex is immediately false

And your logic is wrong : your for loop - if it was looping at all - would check only the first item in the array, then if that item is not the same String, it will add the String in the array without checking all other items.

You have to check all items of the array before deciding to add your String or not

Wokwi example : t937558.ino - Wokwi Arduino and ESP32 Simulator

Just needs a minor tweak. You want to add the new entry only if NONE of the existing entries matches, not if ANY of the existing entries don't match.

void loop()
{
  boolean found = false;

  for (int i = 0; i < knownAddrIndex; i++)
  {
    delay(3000);
    if (newAddr2 == knownAddr[i])
    {
      Serial.println("Matching Addr already inside array.");
      found = true;
    }
  }

  if (!found)
  {
    knownAddr[knownAddrIndex++] = newAddr2;
    Serial.println("newAddr2 added to knownAddr array!");
  }
}

Results:

started up
newAddr2 added to knownAddr array!
Matching Addr already inside array.
Matching Addr already inside array.
Matching Addr already inside array.
Matching Addr already inside array.

Thanks!

Below is the script for the use case applied to this question.

It does send an alert via telegram app when the first bluetooth device within the signal strength threshold is detected, however, it fails to send alerts for any further devices detected after that.

I am trying to send an alert message upon detection of every new bluetooth device scanned, only once per device ble address.

I think it has something to do with the nested loops logic but I don't know for certain.



#include <BLEDevice.h>
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h>
#include <ArduinoJson.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>

// Replace with your network credentials
const char* ssid = "mywifiapssid";
const char* password = "mywifipassword";

// Initialize Telegram BOT
#define BOTtoken "mybottoken"  // your Bot Token (Get from Botfather)

// Use @myidbot to find out the chat ID of an individual or a group
// Also note that you need to click "start" on a bot before it can
// message you
#define CHAT_ID "mychatid"
int scanTime = 5; //In seconds
int RSSI_THRESHOLD = -99;
String notifyAlert = "";
String knownAddr[20];
int knownAddrIndex = 0;
boolean found = false;
boolean sendfound = false;
BLEScan* pBLEScan;

WiFiClientSecure client;
UniversalTelegramBot bot(BOTtoken, client);

class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
    void onResult(BLEAdvertisedDevice advertisedDevice) {
      //Serial.printf("Advertised Device: %s \n", advertisedDevice.toString().c_str());
      notifyAlert = (advertisedDevice.getAddress().toString().c_str());
      for (int i = 0; i < knownAddrIndex; i++) {
     if (notifyAlert == knownAddr[i]) {
      Serial.println("Matching Addr already inside array.");
      found = true;
     }
     
  }
  if (!found)
  {
    knownAddr[knownAddrIndex++] = notifyAlert;
    Serial.println("new device added to known device array!");
    Serial.print("array index:");
    Serial.println(knownAddrIndex);
    sendfound = true;
    found = false; //added 12/26/2021 to allow more than one result.
  }
    }
};

void setup() {
  Serial.begin(115200);

  // Attempt to connect to Wifi network:
  Serial.print("Connecting Wifi: ");
  Serial.println(ssid);

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  client.setCACert(TELEGRAM_CERTIFICATE_ROOT); // Add root certificate for api.telegram.org
  
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }

  Serial.println("");
  Serial.println("WiFi connected");
  //Serial.print("IP address: ");
  //Serial.println(WiFi.localIP());

  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

  bot.sendMessage(CHAT_ID, "Bot started up", "");
  Serial.println("Sent startup notification");
}

void loop() {
  BLEScanResults foundDevices = pBLEScan->start(scanTime, false);
 Serial.print("Devices found: ");
  Serial.println(foundDevices.getCount());
  Serial.println("Scan done!");
  for (int i = 0; i < foundDevices.getCount(); i++)
  {
    BLEAdvertisedDevice device = foundDevices.getDevice(i);
    int rssi = device.getRSSI();
    Serial.print("RSSI: ");
    Serial.println(rssi);
    if (rssi > RSSI_THRESHOLD)
    {
      Serial.println("RSSI past threshold");
     
      if (sendfound == true) {
    Serial.println("New device detected!");
    Serial.println(notifyAlert);
    bot.sendMessage(CHAT_ID, notifyAlert, "");
    Serial.println("notified");
    sendfound = false;
  
    }
   }

  }
  pBLEScan->clearResults();   // delete results fromBLEScan buffer to release memory
  delay(2000);
  
}

You are setting 'found' to false in the wrong place. Do it here:

      notifyAlert = (advertisedDevice.getAddress().toString().c_str());
      found = false;
      for (int i = 0; i < knownAddrIndex; i++)
      {