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 :
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.
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.
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.
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.
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.
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 ( :
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.
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.
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 ?