Another TCP Data Problem

Hello guys, im trying to come up with a remote controller for a motor and a few pneumatic solenoids, using two photons and TCP. i have most of it working. they connect to one another and i can see what the server is sending and i can watch the serial of the client and see what its receiving. flush doesn’t seem to help either case, i still cant seem to get things to line up just right so i can read the server info and then wiggle different wires to control external things. if someone could take a look at my code and point me in the right direction i would appreciate it. lets see if i can post the code right…
Server code:

SYSTEM_MODE(SEMI_AUTOMATIC);
SYSTEM_THREAD(ENABLED);

TCPClient client;
TCPServer server = TCPServer(79);

//////////////////////////////////////////////////////////////////////////////////////////////////
//BATTERY MONITOR INFORMATION//

#include <PowerShield.h>

PowerShield batteryMonitor;
int usbpg = 0;
int acpg = 0;

//////////////////////////////////////////////////////////////////////////////////////////////////

int Estop = A0;                     // E-STOP CONNECTED TO              D1
int Direction = D4;                 // DIRECTION SWITCH CONNECTED TO    D4
int LumberStop = D5;                // LUMBER STOP CONNECTED TO         D5
int FootControl = D6;               // FOOT CONTROL SWITCH CONNECTED TO D6
int LED = D7;                       // LED CONNECTED TO                 D7

int EstopButton = 1;                //BUTTON START POSITION, 1=ON, 0=OFF
int DirSwitch = 0;                  //BUTTON START POSITION, 1=ON, 0=OFF
int LumberSwitch = 0;               //BUTTON START POSITION, 1=ON, 0=OFF
int FootSwitch = 0;                 //BUTTON START POSITION, 1=ON, 0=OFF




//////////////////////////////////////////////////////////////////////////////////////////////////
//SETUP FOR TCP INFORMATION//


//String esp = String("estop_pressed");           // TCP CONTROL PACKET
char esp[] = "estop_pressed";
//String esr = String("estop_released");          // TCP CONTROL PACKET
char esr[] = "estop_released";
//String For = String("forward");                 // TCP CONTROL PACKET
char For[] = "forward";
//String rev = String("reverse");                 // TCP CONTROL PACKET
char rev[] = "reverse";
//String lumup = String("lumber_stop_up");        // TCP CONTROL PACKET
char lumup[] = "lumber_stop_up";
//String lumdwn = String("lumber_stop_down");     // TCP CONTROL PACKET
char lumdwn[] = "lumber_stop_down";
//String fsp = String("foot_switch_pressed");     // TCP CONTROL PACKET
char fsp[] = "foot_switch_pressed";
//String fsr = String("foot_switch_released");    // TCP CONTROL PACKET
char fsr[] = "foot_switch_released";

//////////////////////////////////////////////////////////////////////////////////////////////////
//FLAGS TO ONLY SEND ONE BUTTON STATE, ON CHANGE//

bool ESstate = 0;                //  FLAG FOR THE STATE OF THE E-STOP BUTTON
bool Dirstate = 0;               //  FLAG FOR THE STATE OF THE DIRECTION  SWITCH
bool LSstate = 0;                //  FLAG FOR THE STATE OF THE LUMBER STOP SWITCH
bool FCstate = 0;                //  FLAG FOR THE STATE OF THE FOOT CONTROL BUTTON

//////////////////////////////////////////////////////////////////////////////////////////////////



void setup() {
    WiFi.on();
    delay(5000);
    //WiFi.setCredentials("");
    WiFi.connect();
    waitUntil(WiFi.ready);
    
    delay(1000);
    
    server.begin();
    
    Particle.subscribe("battery", fuelgauge, MY_DEVICES);
    pinMode(Estop, INPUT_PULLUP);           // SETTING THE E-STOP BUTTON AS AN INPUT
    pinMode(Direction, INPUT_PULLUP);       // SETTING THE DIRECTION SWITCH AS AN INPUT
    pinMode(LumberStop, INPUT_PULLUP);      // SETTING THE LUMBER STOP SWITCH AS AN INPUT
    pinMode(FootControl, INPUT_PULLUP);     // SETTING THE FOOT CONTROL SWITCH AS AN INPUT
    pinMode(LED, OUTPUT);                   // SET LED AS AN OUTPUT
    pinMode(D2,INPUT);
    pinMode(D3,INPUT);
    digitalWrite(LED, LOW);                 // SET THE LED OFF DURING START UP
    pinMode(A7, INPUT_PULLUP);
    attachInterrupt(A7, Connect, FALLING);
    pinMode(A6, INPUT_PULLUP);
    attachInterrupt(A6, Disconnect, FALLING);
    
    
    // This essentially starts the I2C bus
    batteryMonitor.begin();
    // This sets up the fuel gauge
    batteryMonitor.quickStart();
    // Wait for it to settle down


}

void fuelgauge(const char *event, const char *data){
    
    usbpg = digitalRead(D2);
    acpg = digitalRead(D3);
     
    // Read the volatge of the LiPo
    float cellVoltage = batteryMonitor.getVCell();
    // Read the State of Charge of the LiPo
    float stateOfCharge = batteryMonitor.getSoC();

    // Publish Cell Voltage to cloud
    Particle.publish("Battery Voltage", String(cellVoltage));

    // Publish State of Charge to Cloud
    Particle.publish("Battery %", String(stateOfCharge));
    
    //Particle.publish("Charging Via USB", String(usbpg));
    //Particle.publish("Charging Via Acc",String(acpg));
    
}

void Connect(){
    Particle.connect();
}

void Disconnect(){
    Particle.disconnect();
}

void wificonnect(){
    //WiFi.setCredentials("");
    WiFi.connect();
    waitUntil(WiFi.ready);
}



void loop() {

    if(!WiFi.ready()){
    wificonnect;    
    
    }

    
    if (client.connected()) {
        digitalWrite(LED, HIGH);
    } 
    else {
    // if no client is yet connected, check for a new connection
    digitalWrite(LED, LOW);
    client = server.available();
  }
    
    
    
    
    
    
int ES = digitalRead(Estop);                                // DECLARING A VARIABLE FOR THE STATUS OF THE INPUT PIN
int Dir = digitalRead(Direction);                           // DECLARING A VARIABLE FOR THE STATUS OF THE INPUT PIN
int LS = digitalRead(LumberStop);                           // DECLARING A VARIABLE FOR THE STATUS OF THE INPUT PIN
int FC = digitalRead(FootControl);                          // DECLARING A VARIABLE FOR THE STATUS OF THE INPUT PIN

    

    
  

    
   if (ES == LOW && ESstate == 0){
       
       server.println(esp);
        ESstate = 1;
       
   }
   
    if (ES == HIGH && ESstate == 1){
        server.println(esr);
        ESstate = 0;
    }



        
        if (Dir == LOW && Dirstate == 0){
            server.println(For);
            Dirstate = 1;
            
            }
   
        if (Dir == HIGH && Dirstate == 1){
            server.println(rev);
            Dirstate = 0;
        }



                
                if (LS == LOW && LSstate == 0){
                    server.println(lumup);
                    LSstate = 1;
                    
                    }
   
                if (LS == HIGH && LSstate == 1){
                    server.println(lumdwn);
                    LSstate = 0;
                }
                
                
                        
                        if (FC == LOW && FCstate == 0){
                            server.println(fsp);
                            FCstate = 1;
                            
                        }
   
                        if (FC == HIGH && FCstate == 1){
                            server.println(fsr);
                            FCstate = 0;
                        }


    delay(100);

}

And the client -v

SYSTEM_MODE(SEMI_AUTOMATIC);
SYSTEM_THREAD(ENABLED);

TCPClient client;
byte server[] = { 192, 168, 86, 101 }; 



int LED = D7;
int Relay1 = D3;
int Relay2 = D4;
int Relay3 = D5;
int Relay4 = D6;


bool relaystate1 = 1;
bool relaystate2 = 0;
bool relaystate3 = 0;
bool relaystate4 = 0;
bool connection = 0;
bool estop = 0;
bool conn = 0;




void setup()
{
    
    pinMode(LED, OUTPUT);
    pinMode(Relay1, OUTPUT);
    pinMode(Relay2, OUTPUT);
    pinMode(Relay3, OUTPUT);
    pinMode(Relay4, OUTPUT);
    
     pinMode(D1, INPUT_PULLUP);
    attachInterrupt(D1, Connect, FALLING);
    
     pinMode(D2, INPUT_PULLUP);
    attachInterrupt(D2, Disconnect, FALLING);


    digitalWrite(LED, LOW);
    digitalWrite(Relay1, relaystate1);
    digitalWrite(Relay2, relaystate2);
    digitalWrite(Relay3, relaystate3);
    digitalWrite(Relay4, relaystate4);
    
    
    delay(1000);
    Serial.begin(9600);
    WiFi.on();
    delay(5000);
    //WiFi.setCredentials("");
    Serial.println("Connecting To WiFi");
    WiFi.connect();
    waitUntil(WiFi.ready);
    
    
    
    
    delay(100);
    
    client.connect(server, 79);
    
    delay(1000);
   
    Serial.print("Setup Complete, Starting Code");
    delay(500);
    Serial.print(".");
    delay(500);
    Serial.print(".");
    delay(500);
    Serial.print(".");
    delay(500);
    Serial.print(".");
    delay(500);
    Serial.print(".");
    delay(500);
    Serial.print(".");
    Serial.print(".");
    delay(500);
    Serial.print(".");
    delay(500);
    Serial.print(".");
    delay(500);
    Serial.println(".");

}


void Connect(){
    Particle.connect();
}

void Disconnect(){
    Particle.disconnect();
}

void wificonnect(){
    WiFi.connect();
    waitUntil(WiFi.ready);
}



   

void loop() {
    
        if (client.connected() && conn == 0)
  {
      digitalWrite(LED, HIGH);
      Serial.println("Connected To The TCP Server");
      conn = 1;
      
  }
  if (!client.connected() && conn == 1)
  {
      digitalWrite(LED, LOW);
      Serial.println("Connection Failed");
      conn = 0;
      
  }
    const size_t bufSize = 28;
    unsigned char data[bufSize];
    
   
   //stream.readString();
   client.read(data, bufSize);
   
   
   
   delay(10);
   
    Serial.write(data, bufSize);
   
   //client.flush();
   
    //int data1;
    //String data1;
    //float data1;

    //data1 = client.read();
    
    
    //Serial.write(data1); 
    
    
    //client.flush();
    
    

    
   
     if (!WiFi.ready())
     {
        wificonnect();
     }


}

Ive found i get results much closer to what i think im looking for if i use “float” which doesn’t make sense to me. if the images uploaded you can see the serial difference between using the different code. not sure where im going wrong. when float prints the words its one character at a time. id really like if i could load the sent phrase into a buffer and then compare it to what i expect to see, something like a string compare and then switch a relay if its correct… any help is good help thanks again!

Use "float" where and why?
Can you be a bit clearer about what you actually mean?

Also with client.read(data, bufSize) you should be aware of this documented behaviour
https://docs.particle.io/reference/firmware/photon/#read--2

If you haven't yet received all bufSize bytes you'll be looking at an inconsistent set of bytes and when Serial.write()ing the complete buffer you'll probably get garbage.

Hence you should either check client.available() to ensure you already have at least bufSize bytes in the buffer or - which you should do in any case - check the return value of client.read()

1 Like

Basically im trying to Particle.publish() and Particle.subscribe() without the cloud in a sense. when one photon triggers a "switch" lets say, it sends "data" to the client, the client gets the data, interprets it and then does the function associated with that ever switch was thrown.

Using float was the only way i could get the read information to come out of the serial port looking "right". im not sure if you noticed the difference between the putty windows over top of the code that was loaded, the lower image displays what i would have expected to see but using float which i didn't even think would compile.

Out of desperation trying to understand how client.read() works and only being able to get garbage out. and the reference telling me that int read(uint8_t *buffer, size_t size) reads all readily available bytes up to size from the server the client is connected to into the provided buffer. and
Returns the number of bytes (or characters) read into buffer.

well i don't want to know how many bytes (or characters) are in the buffer, i wanted to know what was in the buffer. so i just chose float just to try, weather that was dumb or stupid or just a newbie mistake and the wrong way of going about it, whatever you want to call it, it was closer then anything else.

i understand what your saying about Serialwrite()ing before everything has been received, i will look into the use of client.available() and also into utilizing the return value of client.read() before trying to Serialwrite()

i will adapt my code this evening to utilize your suggestions so the code is proper. and see if i can get things working.

I contradict. Yes, you want to know how many bytes you have received to be able to tell whether or not you have received all the bytes that are needed to form a complete data package you were sending. If you expect 23 bytes but only received 5 (all the readily available ones at that point of time) so far, all you will get in your buffer is 5 valid bytes and 18 garbage bytes of whatever was in the buffer already. Only when you received 23 of 23 bytes your data will be consistent.

1 Like

After your first post i do agree with you about knowing whats coming in and if the buffer is full, my

Was more the thinking in my head not understanding the importance of knowing. I will look back at my code and add the things you've suggested. thx for your help, i will post back with success or more garbage...