jeroends / velserv

A TCP to Velbus gateway for Linux
6 stars 5 forks source link

In client mode velserv does not detect is the server is stopped/re-connect. #1

Open matthijsfh opened 5 months ago

matthijsfh commented 5 months ago

I am experimenting with a split Velbus network. The 2nd parts is in the garage and has its own raspberry pi.

When I connect velserv in client mode: sudo ./velserv -f -v -c -a 192.168.3.130 -p 3788 it does work great. I can scan the whole network from velbuslink as if it was 1 network.

However, it does not disconnect when the connection to instance of velserv in server mode is lost. It also therefore does not re-connect.

When I stop the velserver "in server mode", the velserv in client mode stays connected. And it does not really re-connect when the server is back and running again, because there is no data exchanged between them anymore. A scan in Velbuslink shows that the "remote" modules are not responding indeed.

Hope this makes sense, I can explain in more detail when needed.

What I need would be that the velserv in client mode, stops working. Then it is easy to check and restart (if neede) on a regular time interval.

Grt Matthijs

MDAR commented 5 months ago

Quick question.

Are you forcing the server side to stop / restart? I'm which case it would be fairly easy to add a line to the service file on the server side to send a restart command via ssh to the remote unit to restart the client

(Which would happen if the server failed for whatever reason)

Or are you suggesting that you have a network issue that is breaking the link?

matthijsfh commented 5 months ago

Or are you suggesting that you have a network issue that is breaking the link?

Yes, the wifi "link" to the garage is not extremely stable. Also I do reboot my RPI every now and then when working on OpenHab.

Would be nice if Velserv could detect the "other" velserv is down and re-connect. Guess I can make a script to check if the velserv in server mode is up and running, and restart the client instance when needed.

matthijsfh commented 5 months ago

Did some testing:

ChatGPT came with this solution to create a bridge (both velserv in server mode)

import socket
import threading

def handle_connection(source, destination, label):
    while True:
        data = source.recv(1024)
        print(label)
        if not data:
            break
        destination.sendall(data)

def connect_and_copy(source_host, source_port, dest_host, dest_port):
    try:
        # Create sockets for both connections
        source_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        dest_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        # Connect to the source and destination servers
        source_socket.connect((source_host, source_port))
        dest_socket.connect((dest_host, dest_port))

        # Start threads to copy data between connections
        t1 = threading.Thread(target=handle_connection, args=(source_socket, dest_socket, '>'))
        t2 = threading.Thread(target=handle_connection, args=(dest_socket, source_socket, '<'))
        t1.start()
        t2.start()

        # Wait for threads to finish
        t1.join()
        t2.join()

    except ConnectionRefusedError:
        print("Connection refused, the server may be down.")
    except Exception as e:
        print("An error occurred:", e)
    finally:
        # Close the connections
        source_socket.close()
        dest_socket.close()
        print("Connections closed.")

        # Define the source and destination server addresses and ports
source_host = '192.168.3.130'
source_port = 3788         
dest_host = '192.168.3.85' 
dest_port = 3788           
        # Connect to both servers and start copying data
connect_and_copy(source_host, source_port, dest_host, dest_port)

This works out of the box! Which inspired me to check why. The needed solution is in these lines:

// wait for data to receive from socket (blocking option)
bytes_recieved=recv(sock,recv_data,1,0);

if (bytes_recieved > 0)
{
}
else
{
 // need something here to stop the client completely (there is no reconnect anyway, so best is to end the program?
}

Received <= 0 (btw recieved is a typo in your code) can be the escape I need.

matthijsfh commented 5 months ago

I forked the repro and fixed the issue. Please have a look if you like it and if you can add it to the master branch too.

Greetings Matthijs

jeroends commented 5 months ago

Hello Matthijs, I'll have a look and try to understand what you meant ;-). Is it possible to make a drawing of your configuration to see if there's something you're overlooking which is causing the race condition. It's been 14 years that I've adjusted something in the code (and the original date is +/-2007), so 'll have to figure out back again what's happening and see if your adjustments are ok.

matthijsfh commented 5 months ago

Hai Jeroen,

Thanks for responding. I think this thread has all information you are looking for. I put 6 drawings in there of various options to have a split velbus network.

https://forum.velbus.eu/t/building-custom-velbus-devices/4125/71

Greetings Matthijs