Incoming Data Comparison/Conversion problems

Hello,

I am trying to get some data from Ethernet and process it with Arduino, Have multiple errors/problems .
They all about string types and comparison, Here's my problems:

On setup i open a file on SD Card as a configuration file. and read it as usual :

  configFile = SD.open("ezeinfo");
  String configInfo;
  int linenum = 1;
  while (configFile.available()) {
        char c = configFile.read();
        configInfo += c;
  }
  Serial.println(configInfo);

Serial prints the data Successfully

1234,10,0,0,152

This data will be a connections password "1234", And the IP Address (10,0,0,152)
So I'll use substring & indxOf to cut the needed data.
So the password will be:AccessPassword = String(configInfo.substring(0,4));
And this is the first problem, When i compare this text with the data received from Ethernet, I always got false, after the init for the Ethernet and all setup stuff, This is the code I used :

if (client.connected() && client.available()) getReceivedData();
void getReceivedData(){
  Client client = server.available(); 
  char c;
  int charsWaiting;

  charsWaiting = client.available();
  do {
    c = client.read();
    Command += c;
  } 
  while(String(c,DEC) != 13);
  Serial.println(Command);
  switch (logged) {
  case true:
    // got a new command
    client.println("O");
    break;        
  case false:
    if (Command == AccessPassword) { // this is the problem
      logged = true;
      client.println("R"); // Ready
      digitalWrite(connectedLedPin,HIGH);
    }
    else{
      client.println("E2"); // Wrong Access
      client.stop();
    }
    break;
  }
  Command = ""; // empty buffer
}

The next problem is cutting the IP text from the config file, I get it using substring & indexOf for search for every comma, and printed it to serial.. its OK.. but i can't use it with IP array :

byte DefaultIP[] = {IP1,IP2,IP3,IP4 };

Can any one help ?

Thanks all

String() - Arduino Reference - note the equals() method....

I tried it before, The same, always false

if (Command.equals(AccessPassword))

You are reading when no chars are available, so you get nonsense. You must never read more chars than are available.

MarkT,

Sorry i don't understand, could you explain where i read chars when not available?

Thank you

Posting just snippets of code doesn't really help us solve your problem. But, this bit interests me.

AccessPassword = String(configInfo.substring(0,4));

If configInfo is a String object, you are invoking String::substring() for the configInfo object. Look at the documentation for the String::substring() function.

The substring method returns a String object. You are then passing this String object to the String constructor to make another copy of a String. Why? When this code is done, you have 3 copies of the data. Memory on the Arduino is too precious to waste like this.

PaulS,

Very good notice, I really didn't think about this one at all, I'll take care for not waste Arduino memory.
for my full code, here we go :

// include needed libs
#include <SPI.h>
#include <SD.h>
//#include <Ethernet.h>
#include <MyEthernet.h>


// setup network
byte DefaultMac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte DefaultIP[] = {10,0,0,151 };

Server server(23);
Client client = 0; 

String Command;
String AccessPassword = "hello";
int Connected = 0;
byte clientID;
boolean logged = false;     // used for see if a client send a valid password and is logged in
boolean connectFlag = 0; //we'll use a flag separate from client.connected
//so we can recognize when a new connection has been created


// PIN Configrations
int connectedLedPin = 2;
int ErrorLedPin = 3;
//Pin connected to ST_CP of 74HC595 (latch Pin 12)
int latchPin = 8;
//Pin connected to SH_CP of 74HC595 (Clock pin 11)
int clockPin = 9;
////Pin connected to DS of 74HC595 (Serial Pin 14)
int dataPin = 7;

File configFile;

void setup() {
  // open the serial port for logging
  Serial.begin(9600);
  pinMode(connectedLedPin, OUTPUT);
  pinMode(ErrorLedPin, OUTPUT);
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  pinMode(10, OUTPUT);

  if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    die();
  }
  Serial.println("initialization done.");

  if (SD.exists("config.ini")) {
    Serial.println("Reading Configration.");
  }
  else {
    Serial.println("Config file doesn't exist.");
    die();
  }

  // open config file:
  configFile = SD.open("config.ini");
  String configInfo; // line 1 = password, line 2 =IP, line 3=....!
  while (configFile.available()) {
        char c = configFile.read();
        configInfo += c;
  }
  Serial.println(configInfo);
  AccessPassword = String(configInfo.substring(0,4));
  configFile.close();

  startServer();

}

void startServer() {
  // initialize the ethernet device
  Ethernet.begin(DefaultMac, DefaultIP);
  // start listening for clients
  server.begin();
}

void loop()
{
  // look to see if a new connection is created,
  // print welcome message, set connected flag
  if (server.available() && !connectFlag) {
    connectFlag = 1;
    client = server.available();
    clientID = client.id();
  } 
  else if (server.available()) {
    Client badclient = server.available();
    byte tempid = badclient.id();
    if ( tempid != clientID) {
      badclient.println("E1"); // only one connection
      badclient.stop();
    }
  }

  // check to see if text received
  if (client.connected() && client.available()) getReceivedData();

  if (connectFlag && !client.connected()) {
    client.stop();
    logged = false;
    connectFlag = 0;
    digitalWrite(connectedLedPin,LOW);
  }
  // code to do other things in loop would go here
  if (!logged){
    digitalWrite(connectedLedPin,HIGH);
    delay(250);
    digitalWrite(connectedLedPin,LOW);
    delay(250);
    Serial.println("Waiting");
  }
}

void getReceivedData(){
  Client client = server.available(); 
  char c;
  int charsWaiting;

  charsWaiting = client.available();
  do {
    c = client.read();
    Command += c;
  } 
  while(String(c,DEC) != 13);
  Serial.println(Command);
  switch (logged) {
  case true:
    // got a new command
    client.println("O");
    break;        
  case false:
    if (Command.equals(AccessPassword)) {
      logged = true;
      client.println("R"); // Ready
      digitalWrite(connectedLedPin,HIGH);
    }
    else{
      client.println("E2"); // Wrong Access
      client.stop();
    }
    break;
  }
  Command = ""; // empty buffer
}
void die(){
  digitalWrite(ErrorLedPin,HIGH);
  while(true);
}

Also sure i need your Experiences, If there's more notes.

Thank you

  do...while(String(c,DEC) != 13);

More waste. There is no reason on earth why you can't simply compare c to 13.

Why is Command a global? It is reference only in the getReceivedData() method.

You need to tell us what you config.ini file contains (so we have some idea what is in AccessPassword) and what is being sent to the server (what is in Command), so we can help determine why they are not matching.

PaulS,

If my concept is wrong why not tell me what is the right to do, I am still learning this.
And the config.ini contains posted on first post:

1234,10,0,0,152

Where "1234" is a password, and the rest is the IP address..

And about commands, simply send the access password, if it right accept the connection.
This is what is done in the code I posted, what i'll do after fixing this, I'll send numbers to control shift registers.

Thank you

If my concept is wrong why not tell me what is the right to do

If I thought it was, I'd say so. I don't know that it is. You are the only one that can see what the inputs and outputs are. We're just guessing.

And about commands, simply send the access password, if it right accept the connection.

Send the access password from where? From a browser? From a command line?

It is possible that whatever is sending the access password is adding some additional data that it expects the receiver to strip off/ignore. If that is the case, you need to strip off/ignore the extra input. But, without seeing the actual value in Command, I can't say what you need to do.

PaulS,

I am sending data from my Visual Basic Application, so i am free to add any additional data.
The whole purpose from this project is control multiple shift registers, So after logging in, I'll 8-bit numbers (0-255) for all shift registers.

My problem is this language is completely different from the programming languages I used before, little close but needs alot of training and experiences, But I love learning new stuff.

Thank you, and waiting for your expert advices ( :

I am sending data from my Visual Basic Application, so i am free to add any additional data.

How is that data getting to the ethernet cable? Please show HOW you are sending the data from the VB app.

PaulS,

A small Visual Basic code with WinSock OCX, Code is very simple (yet)

Option Explicit

Private Sub cmdConnect_Click()
sockMain.RemoteHost = txtHost.Text
sockMain.RemotePort = txtPort.Text
sockMain.Connect
End Sub

Private Sub cmdSend_Click()
sockMain.SendData txtSend.Text & Chr(13)

End Sub

Private Sub Form_Load()
txtStatus.Text = ""
End Sub

Private Sub sockMain_Connect()
sockMain.SendData "hello" & Chr(13)
End Sub

Private Sub sockMain_DataArrival(ByVal bytesTotal As Long)
Dim strData As String
sockMain.GetData strData, vbString
txtStatus.Text = txtStatus.Text & strData
End Sub

Its connect to the IP, as soon as it connects i send the password.. If is it right Arduino will send "R" for ready to receive data.

void getReceivedData(){
  Client client = server.available(); 
  char c;
  int charsWaiting;

  charsWaiting = client.available();
  do {
    c = client.read();
    Command += c;
  } 
  while(String(c,DEC) != 13);
  Serial.println(Command);

Looky there. You print the data received. But, you still haven't shared that little tidbit with us.

When using Serial.print to print character data, it's generally a good idea to include some sort of delimiters, so you can see where the data actually ends.

Serial.print("Command: [");
Serial.print(Command);
Serial.println("]");

Now, if you see:
1234
you don't know whether the data that arrived was "1234 " or "1234" or "1234". On the other hand, with the limiters, the difference between
[1234]
[1234 ]
]1234
and
[1234
]
is pretty obvious.

Nice idea, I edited my code, and the data printed with no any more chars:

Command: [hello]

On visual basic app, I send Chr(13) on every line end, Thats why i do buffer until i received a char 13, that mean the end of line,

while(String(c,DEC) != 13);

Also you give me a note on this line code, I don't understand it, can i just compare c to 13 ?

while(c != 13); ?

can i just compare c to 13 ?

Yes.

Command: [hello]

Well, hello is not equal to 1234 on my planet. So, it appears as though your code IS working.

PaulS,

"hello" i copied it by mistake, I used another old source code, But the problem still exists.
here's the new serial log.

Command: [1234]

OK. So, the thing to do is to print out more stuff. What is actually in AccessPassword at the time it is extracted from the config file? What is actually in AccessPassword at the time it is compared to Command?

There's something strange with serial log, On the screen i can see every thing ok, When i copied some text and pasted to anything out i got the code like this :

Command: [1234
]

There's some hidden char that not appear on serial.

i tried to replace the Chr(13) on vb code to "E" as end of line instened of a new line, And chnage the while to while(c != 'E");, also didn't work. any ideas ?

Now the serial log is:

Command: [1234E]
AccessPassword: [1234]

on do ..while I used :

  do {
    c = client.read();
    Command += c;
    Serial.println(String(c,DEC));
  } 
    while(c != 69);

AND

  do {
    c = client.read();
    Command += c;
    Serial.println(String(c,DEC));
  } 
    while(c != 'E');

Got the same result :frowning: