Add values from Code to Menu Item

Is it possible to add some values to menu item within my code.

Example: i read all usb devices. If i found a device which have some files on it i would like to change the list and add only the usb devices which have some file on it.

Is that possible?

This is not possible at the moment. But idea is nice. We didn’t think in that direction.

+1 for this idea. In my scenario, I want to scan for a list of WiFi access points (looking for a FlashAir card) and populate the results in a menu list.

I also have other values that are programatically determined from lookups and calculations that would be great to have in a menu, but it doesn’t look like there’s a way to pass those dynamically - I’d have to know the list at compile-time.

While we’re at it, it would be super cool if the Menu control could hold both Label and Value, and if it were wrapped in a widget.

Basically, I want a Table widget that presents itself in the UI like a Menu. I might use a table for now as a workaround.

Thanks for considering!

You mean like this…

//change MENU labels
Blynk.setProperty(V0, "labels", "Menu Item 1", "Menu Item 2", "Menu Item 3");

Pete.

Maybe this is a gap in my knowledge of C/C++, but how can I do that if I don’t have those values as literals at compile-time?

In my simplest scenario, I have a CSV of Name/Value pairs that I’m storing on an SD card. I want to populate that list to the menu. Given the syntax, how would I pass this list of values, since the length of the list is not known ahead of time?

In the Table Widget, this is easy - there’s an AddRow().

Is there a way to achieve the same with the Menu?

You can create BlynkParamAllocated object, populate it with your values and pass to setProperty function. Check the example called SetProperty_MultiValue

2 Likes

I’d assume that it works with variables as well as string literals, but I don’t use menus in Blynk, so I’ve never tried it.

Pete.

Thanks, all - that’s exactly what I was looking for! In case it’s helpful to others, here is my routine as a snippet.

I’m reading a 2-column CSV from the SD card where column 0 is a string label and column 1 is a float value.

//
//	Reading from a CSV stored on the SD card
//	File structure in this example is 2 columns: String,Float
//

File file;

//from https://arduino.stackexchange.com/a/1237
String explode(String data, char separator, int index)
{
	int found = 0;
	int strIndex[] = { 0, -1 };
	int maxIndex = data.length() - 1;

	for (int i = 0; i <= maxIndex && found <= index; i++) {
		if (data.charAt(i) == separator || i == maxIndex) {
			found++;
			strIndex[0] = strIndex[1] + 1;
			strIndex[1] = (i == maxIndex) ? i + 1 : i;
		}
	}
	return found > index ? data.substring(strIndex[0], strIndex[1]) : "";
}

void PopulateMenuFromCSV()
{

	file = SD.open("/myFile.csv", FILE_READ);

	if (!file) {
		Serial.println("Error opening file.");
		return;
	}

	//first we need to count the number of lines in the file so we know how large to allocate the colleciton
	int numlines = 0;
	while (file.available())
	{
		file.readStringUntil('\n'); //in this CSV, each line is terminated with a newline character
		numlines++;
	}

	String line;
	file.seek(0); //seek back to the beginning of the file

	//Use the BlynkParamAllocated object to contain the menu labels we want to add
	BlynkParamAllocated items(sizeof(String)*numlines);

	for (int i = 0; i< numlines; i++)
	{
		line = file.readStringUntil('\n');
		
		//split the line at a comma, expecting line format of String,Float
		String name = explode(line, ',', 0); //this will get the item in the first column
		String value = explode(line, ',', 1); //this will get the item in the 2nd column
		float floatval = value.toFloat(); //we expect the second column to contain floats
		if (floatval != 0) //only add a line if we got a valid float (we don't expect 0 as a value in this list)
		{
			items.add(name); //add it to the collection of menu items
		}
	}

	Blynk.setProperty(V30, "labels", items); //push it back to our menu, in this case, Pin 30

	file.close();
}

float GetValueFromMenuSelection(int selectedIndex)
{
	//Blynk menus return 1-based index, so we need to decrement
	selectedIndex = selectedIndex - 1;

	file = SD.open("/myFile.csv", FILE_READ);
	if (!file) {
		Serial.println("Error opening file.");
		return -1;
	}

	for (int i = 0; i < selectedIndex; i++)
	{
		if (file.available())
		{
			file.readStringUntil('\n');
		}
		else
		{
			Serial.println("Error seeking to " + String(selectedIndex));
		}
	}
	//the next line we read should be the selected index line
	String line = file.readStringUntil('\n');
	file.close();

	String name = explode(line, ',', 0);
	String value = explode(line, ',', 1);
	float floatval = value.toFloat();
	if (floatval != 0) { //again, a test to see if we got a valid float and we're not expecting a 0
		Serial.print("Menu item set to " + name + " : ");
		Serial.println(value);
		return floatval;
	}

	else return -1;
}

There’s likely a more efficient way to do this, but hopefully this snippet will help others.

Still, it’d be super awesome to have a menu Widget wrapper that could store both key and value for scenarios like this. The WidgetTable class is so easy to work with in this way - if only I could bind it to a menu :slight_smile:

Anyhow, thanks again. The Blynk platform and community are so awesome.

1 Like