Sending decimal numbers from Arduino WebServer to Client via Ethernet

Hi everyone,

Currently, I am trying to send a floating point number every two seconds from an Arduino WebServer, running off an Arduino Uno R3 with an Ethernet Shield 2 (W5500), to a python client. Currently, the client can connect to server, but every time the value is grabbed from the server by the client, I get something like this in the terminal:

b'1'
b'.00'
b'1'
b'.00'
....

If I remove the delay(2000), I then obtain:

b'1.001.001.001.001.001.001.001.001.001.001.001.001.001'
b'1.001.001.001.001.001.001.001.001.001.001.001.001.001'
b'1.001.001.001.001.001.001.001.001.001.001.001.001.001'

I would like to get something like:

1.00
1.00
1.00
1.00

Given that I want to simply send 1.00 as one whole character string and not have it displayed in two separate lines, nor as a byte string, what can I do to achieve this? How can floating point numbers be sent via Ethernet?

(The reason why I want this delay is I eventually want to use this to record the number of pulses from a Hall Sensor arriving per second and then send this value to the client via the Ethernet)
Below is my basic Arduino Code for completeness:

#include <SPI.h>
#include <Ethernet.h>

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {0xA8, 0x61, 0x0A, 0xAE, 0x69, 0x13};
IPAddress ip(198, 162, 1, 177);

// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
EthernetServer server(80);



void setup() {
  Serial.begin(9600);  //Starting serial monitor

  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
  Serial.println("Ethernet WebServer Example");

  // start the Ethernet connection and the server:
  Ethernet.begin(mac, ip);

  // Check for Ethernet hardware present
  if (Ethernet.hardwareStatus() == EthernetNoHardware) {
    Serial.println("Ethernet shield was not found.  Sorry, can't run without hardware. :(");
    while (true) {
      delay(1); // do nothing, no point running without Ethernet hardware
    }
  }
  if (Ethernet.linkStatus() == LinkOFF) {
    Serial.println("Ethernet cable is not connected.");
  }

  // start the server
  server.begin();
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());
}



void loop() {

  EthernetClient client = server.available();
  if (client)
  {
    boolean currentLineIsBlank = true;
    while (client.connected())
      if (client.available())
        {
          delay(2000);
          client.print(1.00);
          client.println();
        }

  }
 
}

The python code for the client is given below:

import asyncio
import websockets
import socket
import time
import datetime
import struct

starttime = time.time() # start value for timed data acquisition

# setup socket 1
s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s1.connect(("198.162.1.177",80))
s1.send('Hello Server'.encode())
if True:
    print('Connected')
def acquire():
    
    data = s1.recv(6000)
    dataline_tmc1 = datetime.datetime.today().isoformat() + "," + str(data) + "," + str(0) + "\n" # format and assemble data line
    print(dataline_tmc1)
    file_name_tmc1 = '{:%Y%m%d}'.format(datetime.datetime.today()) + "-test.csv" # generate file name
    with open(file_name_tmc1, "a") as tmc_file1: # append dataline to file
        tmc_file1.write(dataline_tmc1)
        
while True:
   acquire()
   time.sleep(1.0 - ((time.time() - starttime) % 1.0)) # continue every  (1.0 seconds)

s1.close()

why if (client.available())?

you receive it wrong

What do you mean by that? Can you elaborate?

client.available() returns count of received bytes.

what prints the b'xy'? it should read the whole line until \n, not separate characters

The b'xy' comes from the python client code that I am using to interact with this Arduino webserver. I was under the impression that the client.available() checks if a client is available to the Arduino webserver. As far as I am aware, the python code works as expected, but I can post that if needed.

it is the same available() of Stream as with Serial. Ethernet - Arduino Reference

the receiving python code is wrong

I have added the Python code to the original question for you to look at

I don't know python libraries

ok, so removing the if client.available() clause does nothing to affect the Arduino code. It still produces the same error as outlined in the original question.

there is nothing what could be wrong in the Arduino sketch. you could do client.println(1.00) or client.println("1.00") it would be still the same.

It looks to me as though you are quite new to the concept of socket programming, perhaps reading this will help: Socket Programming HOWTO — Python 3.9.5 documentation
The main problem is just using recv does not indicate anything about when one lot of data ends and the next begins, it just treats the whole lot as a stream. That means you have to either define a protocol that suits your data, such as fixed length data - say 4 bytes and handle each piece of data accordingly, or use delimiters such as /n (as Juraj has suggested by using println rather than print, or a combination such as first 2 bytes indicate how much data follows - this works much better for binary data which could be variable length and include your delimiters.

Yes, I am very new to socket programming. Thank you very much. I will take a look at the provided resource.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.