Trying to work with 2 separate lists of received data from arduino

Hi everyone,

I'm building an Arduino project and an app to go with it.

So far I've gotten a lot of things working, sending and receiving bytes to control relays on the arduino and displaying sensor data on the app.

Now I'm expanding to be able to control stored values on the arduino. To do this I'm sending a '9' to the arduino. When the 9 is received the arduino will send the stored values and the value of the EEPROM position the data is stored at. Then I write back the position and the new data.

Now the trouble is the app seems to mix the 2 lists I'm populating with Arduino data.

When I click the 'get settings' button I do not get the values from the SettingsList but from the DataList.
When I go back to the main screen it's supposed to populate from the DataList but I get an error: List index too large, trying to get index 13 from a list of 8.

In the Arduino code I've added something so that when data is recevied on Serial1 it will pause sending sensor data for 2 seconds. This should prevent the sensor data from going into the SettingsList.

Am I missing something?

Don't expect a response from BlueTooth in your Button Click event block. It's too soon.

Instead, only do one BlueTooth input grab attempt in the Clock Timer, and use a global variable set in the Click event to tell it what it should be expecting.

You may need to switch to YAML format messages, because of message length limits.

Some people send temperature and humidity in separate messages with distinctive prefixes like "t:" (for temperature) and "h:" (for humidity).
(That's YAML format.)

The AI2 Charts component can recognize these and graph them. See Bluetooth Client Polling Rate - #12 by ABG

To receive YAML format messages, test if the incoming message contains ':' . If true, split it at ':' into a list variable, and find the prefix in item 1 and the value in item 2.

Well I was going for 2 lists because of the message lenght.
Currently I'm sending this every 2 seconds:

if (BTconnected && !settingsTransfer) {
    //Serial.println("Bluetooth Connected");  
    Serial1.print(temp1, 1); Serial1.print("|");
    Serial1.print(temp2, 1); Serial1.print("|");
    Serial1.print(temp3, 1); Serial1.print("|");
    Serial1.print(temp4, 1); Serial1.print("|");
    Serial1.print(temp5, 1); Serial1.print("|");
    Serial1.print(temp6, 1); Serial1.print("|");
    
    Serial1.print(hum1, 1); Serial1.print("|"); //7
    Serial1.print(hum2, 1); Serial1.print("|");
    Serial1.print(hum3, 1); Serial1.print("|");
    Serial1.print(hum4, 1); Serial1.print("|");
    Serial1.print(hum5, 1); Serial1.print("|");
    Serial1.print(hum6, 1); Serial1.print("|");  
    
    Serial1.print(airTempAverage, 1); Serial1.print("|"); //13
    Serial1.print(humidityAverage, 1); Serial1.print("|");
    Serial1.print(pressureAverage, 1); Serial1.print("|");
    Serial1.print(waterTempAverage, 1); Serial1.print("|");
    
    Serial1.print(relayState[0]); Serial1.print("|"); //17
    Serial1.print(relayState[1]); Serial1.print("|");
    Serial1.print(relayState[2]); Serial1.print("|");
    Serial1.print(relayState[3]); Serial1.print("|");    
    Serial1.print(relayState[4]); Serial1.print("|");
    Serial1.print(relayState[5]); Serial1.print("|");
    Serial1.print(relayState[6]); Serial1.print("|");
    Serial1.print(relayState[7]); 
    
    Serial1.println(); //delimiter to indicate end of batch
  }

temp and hum are all floats, relayStates are booleans.

The other batch I want t send is

Serial1.print(desiredTemp); Serial1.print("|");
      Serial1.print(desiredHumi); Serial1.print("|");
      Serial1.print(dayTemperature); Serial1.print("|");
      Serial1.print(nightTemperature); Serial1.print("|");
      Serial1.print(EEPROM.readByte(desiredTemp)); Serial1.print("|");
      Serial1.print(EEPROM.readByte(desiredHumi)); Serial1.print("|");
      Serial1.print(EEPROM.readByte(dayTemperature)); Serial1.print("|");
      Serial1.print(EEPROM.readByte(nightTemperature));
      Serial1.println(); //delimiter to indicate end of batch

Can you elaborate on that?

In your case, with so much data, I recommend YAML, like

You need a couple dozen tags.

I understand the YAML, I mean elaborate on the global variable to tell it what it should be expecting.

The global variable idea is less robust than the YAML approach.

It depends on avoiding message length limits (20?), and requires requests and responses to work in lockstep.

If you fall behind in your Clock Timer reception, it will fail .

It needs good record keeping and message identifying, like ordering stuff online.

But if I add YAML and adding another 8 chars to my single outgoing data stream won't I complicate the max length issue further?

edit: Also the regular data being sent is updated information. The "settings data" only needs to be sent once. To keep sending it would be a waste

Use a pea shooter, not a spear launcher.
Separate all those concatenated prints into separate println()s, each with "tag:" + value.

That avoids the length issue entirely.

Let me see if I understand correctly:

Serial1.print(temp1, 1); Serial1.print("|");

becomes

Serial1.print("t:"); 
Serial1.print(temp1, 1);
Serial1.println();

?

Correct!

Alright, now I'm wondering if I can make a list for t and h, or do I need to use t1, t2, t3 etc?

I've adapted the code for outgoing data to:

Serial1.print("t:"); Serial1.print(temp1, 1); 
    Serial1.print("t:"); Serial1.print(temp2, 1); 
    Serial1.print("t:"); Serial1.print(temp3, 1);
    Serial1.print("t:"); Serial1.print(temp4, 1); 
    Serial1.print("t:"); Serial1.print(temp5, 1); 
    Serial1.print("t:"); Serial1.print(temp6, 1); Serial1.println();
    
    Serial1.print("h:"); Serial1.print(hum1, 1); 
    Serial1.print("h:"); Serial1.print(hum2, 1); 
    Serial1.print("h:"); Serial1.print(hum3, 1); 
    Serial1.print("h:"); Serial1.print(hum4, 1); 
    Serial1.print("h:"); Serial1.print(hum5, 1); 
    Serial1.print("h:"); Serial1.print(hum6, 1); Serial1.println();  
    
    Serial1.print("a:"); Serial1.print(airTempAverage, 1); 
    Serial1.print("a:"); Serial1.print(humidityAverage, 1); 
    Serial1.print("a:"); Serial1.print(pressureAverage, 1); 
    Serial1.print("a:"); Serial1.print(waterTempAverage, 1); Serial1.println();
    
    Serial1.print("r:"); Serial1.print(relayState[0]); 
    Serial1.print("r:"); Serial1.print(relayState[1]); 
    Serial1.print("r:"); Serial1.print(relayState[2]); 
    Serial1.print("r:"); Serial1.print(relayState[3]); 
    Serial1.print("r:"); Serial1.print(relayState[4]); 
    Serial1.print("r:"); Serial1.print(relayState[5]); 
    Serial1.print("r:"); Serial1.print(relayState[6]); 
    Serial1.print("r:"); Serial1.print(relayState[7]); Serial1.println();

    Serial1.print("s:"); Serial1.print(desiredTemp); 
    Serial1.print("s:"); Serial1.print(desiredHumi); 
    Serial1.print("s:"); Serial1.print(dayTemperature); 
    Serial1.print("s:"); Serial1.print(nightTemperature); 
    Serial1.print("s:"); Serial1.print(EEPROM.readByte(desiredTemp)); 
    Serial1.print("s:"); Serial1.print(EEPROM.readByte(desiredHumi)); 
    Serial1.print("s:"); Serial1.print(EEPROM.readByte(dayTemperature)); 
    Serial1.print("s:"); Serial1.print(EEPROM.readByte(nightTemperature)); Serial1.println();

and the blocks:

But this will only display 1 of each, right?
So then I'd make a seperate, unique label for each incomming data figure and expand the dictionary? That seems like a lot of work.

edit: I realize the code being sent won't be split correctly when received. I was just grouping all the t's and h's together but I see now that won't work

Yes, and you can store the keys and values in a dictionary as they arrive, and have another dictionary mapping those keys into Label components to display them.

You only have 6 temperature sensors, right?

So the general pattern is to pick unique tags , and send one tag:value per line.

Then tell the AI2 coder the tags and what they mean.

Yes.

That seems like a lot of work.

Just in the Designer, where you already made the Labels anyway.

Not if you give up this batching idea.

Alright, statusupdate

I've not yet created the labels for the relais because they are switches and cannot display text.
Aside from that have I got everything correct? I can't test it yet because the setup is disassembled for some soldering today. Hopefully tomorrow I can put evything back together and test.

There is no 32.

There is only 2.

You are only receiving one pair at a time.

Ah I see, I was wondering about that. So this method does not create a list with an index, it just updates any and all labels matched in the dictionary.

is the green block (first operation of split and display) 'set incomming_data.text to get message' really needed or just a visual aid?

It's only there to help debug if something goes wrong, like a message is received with the colon all the way in front. It also helps give an idea of how live the data traffic is moving.
.

I see. I have the button hidden for now anyway. I was just wondering if it's going to cause a problem if the text for the button gets too big.

While working on the visualisation and control of the relays I find myself in a catch 22 situation. When I load the screen the "Switch" user interface updates it's position (on or off) according to the data received. However if I want manual control over the relays by clicking the switches my only option is to use the "when relay1.changed" block.
However if the page loads the state of the switches that are on "change". So because of the change it sends a command back to the arduino, resulting in an endless on-off loop.

Is there any way around this?