Quantcast
Channel: Raspberry Pi Forums
Viewing all articles
Browse latest Browse all 4525

MicroPython • AP with multiple clients issue

$
0
0
Hi All.
My project involves 3 Pico-Ws.
One of them is set up as an AP and the other 2 as Clients. We will call them Client # 1 and Client # 2.
Upon code execution, the AP Pico sends the current time data to both clients.
Ideally, both clients receive the current time data and set the Real Time Clock modules attached to them. Job is done.

Here is the issue:
When I run the AP code, 60% of the time, it runs fine and both clients receive the data and life is good. Both clients have an 'Output type 1'.
( Please see the quotes below for the 3 types of output )

The other 25% of the times that I run the AP code, Client # 1 produces an 'Output type 1' and Client # 2 produces and 'Output type 3'.
The other 15% of the times that I run the AP code, Client # 1 produces an 'Output type 2' and Client # 2 produces and 'Output type 3'.
( I use Thonny. I click 'run' on the AP code, then 'run' on Client # 1's code and then 'run' on Client # 2's code; in that sequence )

I tried resetting the Pico-W before running code each time but that doesn't seem to help.
I tried putting a pause in the AP's code but that didn't help.
I did a ton of other things but this random behavior keeps popping up.

My reading online tells me that 'Output type # 3' happens due to the connection being forcibly closed by the remote host. This Output type # 3 can also mean that the AP is overloaded or misconfigured, which causes it to drop connections. It just probably cant handle multiple simultaneous connections properly.

When I have just a single client, I never have any issues and the output is always 'Output type 1'.

Can someone please give me feedback on whats going on?
Ty for the replies!
Output type 1.
MPY: soft reboot
Checking for Network: Switch_LED
Connecting to Network...
IP: 192.168.10.3
Ready
Connected to AP
Received the following date and time from the AP: 33 30 20 11 26 06 2024 4
The time has been set to 2024-06-26 11:20:30 AM
Day of the week: Wednesday
Disconnected from Network.
Output type 2.
MPY: soft reboot
Checking for Network: Switch_LED
Network not found...
Disconnected from Network.
All received messages: []
Output type 3.
MPY: soft reboot
Checking for Network: Switch_LED
Connecting to Network...
IP: 192.168.10.4
Ready
Socket error: [Errno 104] ECONNRESET
Socket error: [Errno 104] ECONNRESET
Socket error: [Errno 104] ECONNRESET
Failed to connect after 3 retries.
Disconnected from Network.
All received messages: []

AP CODE below:

Code:

import networkimport socketimport utimeserver_ip = '192.168.10.1'gateway_ip = '192.168.10.1'port = 5263ssid = 'Switch_LED'password = '2468013579'wlan = network.WLAN(network.AP_IF)wlan.active(True)wlan.config(essid=ssid, password=password)wlan.ifconfig((server_ip, '255.255.255.0', gateway_ip, '8.8.8.8'))server_sock = socket.socket()try:    server_sock.bind((server_ip, port))    server_sock.listen(15)    print(f'Server listening on {server_ip}:{port}')        while True:        client_sock, client_addr = server_sock.accept()        print(f'Client connected from {client_addr}')                # Handle client communication here        try:            data = client_sock.recv(1024)            if data:                print(f'Received data from {client_addr}: {data.decode()}')                # Get current time and format it                current_time = utime.localtime()                # Must set the time in message_to_send in this format!!!: hundredths, seconds, minutes, hours, date, month, year, day_of_week# Example: June 20, 2024, 20:20:45.50 (hundredths: 50), Thursday (day_of_week: 4). Week begins on Mon , not Sun!                                message_to_send = f"33 30 20 11 26 06 2024 4"                client_sock.send(message_to_send.encode())                print(f'Sent the following message to the client at {client_addr}: {message_to_send}')        except Exception as e:            print(f'Error processing client data: {e}')                # Close client socket        client_sock.close()        print(f'Client {client_addr} disconnected')        print(f'   ')except KeyboardInterrupt:    print('Server stopped by user')except Exception as e:    print(f'Error occurred: {e}')finally:    if server_sock:        server_sock.close()    wlan.active(False)

Client # 1 code below:

Code:

#RemoteSetTime-Client-A.pyimport networkimport socketimport timefrom machine import Pin, I2Cfrom rv1805 import RV1805  # Assuming you have the RV1805 RTC class implementedhost = '192.168.10.3'  # Assuming Device B's IP (must be unique in the subnet)serverAP = '192.168.10.1'gatewayAP = '192.168.10.1'port = 5263ssid = 'Switch_LED'pw = '2468013579'  # Password needs to be 8 characters or morewlan = network.WLAN(network.STA_IF)wlan.active(True)Onboard_LED = Pin("LED", Pin.OUT, value=0)# Initialize I2C interface with SCL on GPIO9 and SDA on GPIO8i2c = I2C(0, scl=Pin(9), sda=Pin(8))# Initialize RV1805 RTCrtc = RV1805(i2c)# Function to convert decimal to BCDdef dec_to_bcd(val):    return (val // 10) << 4 | (val % 10)# Function to convert BCD to decimaldef bcd_to_dec(val):    return (val >> 4) * 10 + (val & 0x0F)# Function to set time on RV1805def set_time(hund, sec, min, hour, date, month, year, day):    rtc.writeRegister(RV1805.RV1805_HUNDREDTHS, dec_to_bcd(hund))    rtc.writeRegister(RV1805.RV1805_SECONDS, dec_to_bcd(sec))    rtc.writeRegister(RV1805.RV1805_MINUTES, dec_to_bcd(min))    rtc.writeRegister(RV1805.RV1805_HOURS, dec_to_bcd(hour))    rtc.writeRegister(RV1805.RV1805_DATE, dec_to_bcd(date))    rtc.writeRegister(RV1805.RV1805_MONTHS, dec_to_bcd(month))    rtc.writeRegister(RV1805.RV1805_YEARS, dec_to_bcd(year))    rtc.writeRegister(RV1805.RV1805_WEEKDAYS, dec_to_bcd(day))        # Calculate day of the week (0 = Sunday, 6 = Saturday)    # Adjusted calculation to match desired input where 0=Sunday, 1=Monday, ..., 6=Saturday    day_of_week = (day + 6) % 7    # Define weekday names    weekdays = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]    # Print the set time in a readable format    am_pm = "AM" if hour < 12 else "PM"    hour_12 = hour % 12    hour_12 = 12 if hour_12 == 0 else hour_12    print(f"The time has been set to {year:02}-{month:02}-{date:02} {hour_12:02}:{min:02}:{sec:02} {am_pm}")    print(f"Day of the week: {weekdays[day_of_week]}")# Function to check if AP (Switch_LED) is availabledef check_SSID():    print('Checking for Network:', ssid)    networks = wlan.scan()    found = False    for w in networks:        if w[0].decode() == ssid:            found = True    return found# Function to handle connection failuresdef connect_Fail(s):    errors = {        0: 'Link Down',        1: 'Link Join',        2: 'Link NoIP',        -1: 'Link Fail',        -2: 'NoNet',        -3: 'BadAuth'    }    error_msg = 'Connect Fail: ' + errors.get(s, 'Unknown')    print(error_msg)# Function to connect to the networkdef connect_to_network():    try:        if check_SSID():            print('Connecting to Network...')            wlan.active(True)            wlan.config(pm=0xa11140)  # Disable power-save mode            wlan.connect(ssid, pw)            while not wlan.isconnected():                time.sleep(1)            status = wlan.status()            if status == 3:                # Set IP address to the network we want, otherwise it uses 192.168.4.XXX                wlan.ifconfig((host, '255.255.255.0', gatewayAP, '8.8.8.8'))                status = wlan.ifconfig()                print('IP:', status[0])                return True            else:                connect_Fail(status)                print('Cannot connect...')                return False        else:            print('Network not found...')            return False    except Exception as e:        print('Error occurred:', e)        return False# Function to print current RTC datetimedef print_current_datetime():    hund = bcd_to_dec(rtc.readRegister(RV1805.RV1805_HUNDREDTHS))    sec = bcd_to_dec(rtc.readRegister(RV1805.RV1805_SECONDS))    min = bcd_to_dec(rtc.readRegister(RV1805.RV1805_MINUTES))    hour = bcd_to_dec(rtc.readRegister(RV1805.RV1805_HOURS))    date = bcd_to_dec(rtc.readRegister(RV1805.RV1805_DATE))    month = bcd_to_dec(rtc.readRegister(RV1805.RV1805_MONTHS))    year = bcd_to_dec(rtc.readRegister(RV1805.RV1805_YEARS))    day = bcd_to_dec(rtc.readRegister(RV1805.RV1805_WEEKDAYS))    # Calculate day of the week (0 = Sunday, 6 = Saturday)    # Adjusted calculation to match desired input where 0=Sunday, 1=Monday, ..., 6=Saturday    day_of_week = (day + 6) % 7    # Define weekday names    weekdays = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]    # Print the current datetime in a readable format    am_pm = "AM" if hour < 12 else "PM"    hour_12 = hour % 12    hour_12 = 12 if hour_12 == 0 else hour_12    print(f"Current datetime: 20{year:02}-{month:02}-{date:02} {weekdays[day_of_week]}, {hour_12:02}:{min:02}:{sec:02}.{hund:02} {am_pm}")# Main program executionOnboard_LED.on()received_messages = []rtc_set = Falsetry:    if connect_to_network():        print('Ready')        while not rtc_set:            s = socket.socket()            try:                s.connect((serverAP, port))                print('Connected to AP')                s.send(b'Hello from Client A!')                response = s.recv(1024)                message = response.decode()                print('Received the following date and time from the AP:', message)                received_messages.append(message)                                # Set RTC time from received data                hund, sec, min, hour, date, month, year, day_of_week = message.split()                set_time(int(hund), int(sec), int(min), int(hour), int(date), int(month), int(year), int(day_of_week))                                # Set flag to indicate RTC time is set                rtc_set = True            except OSError as e:                print('Socket error:', e)            finally:                s.close()                #time.sleep(2)  # Adjust timing as needed        # Print current RTC time every 2 seconds        while True:            print_current_datetime()            time.sleep(15)except Exception as e:    print('Error occurred:', e)finally:    wlan.disconnect()    wlan.active(False)    print('Disconnected from Network.')    Onboard_LED.off()print('All received messages:', received_messages)

Client # 2 code below:

Code:

#RemoteSetTime-Client-B.pyimport networkimport socketimport timefrom machine import Pin, I2Cfrom rv1805 import RV1805  # Assuming you have the RV1805 RTC class implementedhost = '192.168.10.4'  # Assuming Device B's IP (must be unique in the subnet)serverAP = '192.168.10.1'gatewayAP = '192.168.10.1'port = 5263ssid = 'Switch_LED'pw = '2468013579'  # Password needs to be 8 characters or morewlan = network.WLAN(network.STA_IF)wlan.active(True)Onboard_LED = Pin("LED", Pin.OUT, value=0)# Initialize I2C interface with SCL on GPIO9 and SDA on GPIO8i2c = I2C(0, scl=Pin(9), sda=Pin(8))# Initialize RV1805 RTCrtc = RV1805(i2c)# Function to convert decimal to BCDdef dec_to_bcd(val):    return (val // 10) << 4 | (val % 10)# Function to convert BCD to decimaldef bcd_to_dec(val):    return (val >> 4) * 10 + (val & 0x0F)# Function to set time on RV1805def set_time(hund, sec, min, hour, date, month, year, day):    rtc.writeRegister(RV1805.RV1805_HUNDREDTHS, dec_to_bcd(hund))    rtc.writeRegister(RV1805.RV1805_SECONDS, dec_to_bcd(sec))    rtc.writeRegister(RV1805.RV1805_MINUTES, dec_to_bcd(min))    rtc.writeRegister(RV1805.RV1805_HOURS, dec_to_bcd(hour))    rtc.writeRegister(RV1805.RV1805_DATE, dec_to_bcd(date))    rtc.writeRegister(RV1805.RV1805_MONTHS, dec_to_bcd(month))    rtc.writeRegister(RV1805.RV1805_YEARS, dec_to_bcd(year))    rtc.writeRegister(RV1805.RV1805_WEEKDAYS, dec_to_bcd(day))        # Calculate day of the week (0 = Sunday, 6 = Saturday)    # Adjusted calculation to match desired input where 0=Sunday, 1=Monday, ..., 6=Saturday    day_of_week = (day + 6) % 7    # Define weekday names    weekdays = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]    # Print the set time in a readable format    am_pm = "AM" if hour < 12 else "PM"    hour_12 = hour % 12    hour_12 = 12 if hour_12 == 0 else hour_12    print(f"The time has been set to {year:02}-{month:02}-{date:02} {hour_12:02}:{min:02}:{sec:02} {am_pm}")    print(f"Day of the week: {weekdays[day_of_week]}")# Function to check if AP (Switch_LED) is availabledef check_SSID():    print('Checking for Network:', ssid)    networks = wlan.scan()    found = False    for w in networks:        if w[0].decode() == ssid:            found = True    return found# Function to handle connection failuresdef connect_Fail(s):    errors = {        0: 'Link Down',        1: 'Link Join',        2: 'Link NoIP',        -1: 'Link Fail',        -2: 'NoNet',        -3: 'BadAuth'    }    error_msg = 'Connect Fail: ' + errors.get(s, 'Unknown')    print(error_msg)# Function to connect to the networkdef connect_to_network():    try:        if check_SSID():            print('Connecting to Network...')            wlan.active(True)            wlan.config(pm=0xa11140)  # Disable power-save mode            wlan.connect(ssid, pw)            while not wlan.isconnected():                time.sleep(1)            status = wlan.status()            if status == 3:                # Set IP address to the network we want, otherwise it uses 192.168.4.XXX                wlan.ifconfig((host, '255.255.255.0', gatewayAP, '8.8.8.8'))                status = wlan.ifconfig()                print('IP:', status[0])                return True            else:                connect_Fail(status)                print('Cannot connect...')                return False        else:            print('Network not found...')            return False    except Exception as e:        print('Error occurred:', e)        return False# Function to print current RTC datetimedef print_current_datetime():    hund = bcd_to_dec(rtc.readRegister(RV1805.RV1805_HUNDREDTHS))    sec = bcd_to_dec(rtc.readRegister(RV1805.RV1805_SECONDS))    min = bcd_to_dec(rtc.readRegister(RV1805.RV1805_MINUTES))    hour = bcd_to_dec(rtc.readRegister(RV1805.RV1805_HOURS))    date = bcd_to_dec(rtc.readRegister(RV1805.RV1805_DATE))    month = bcd_to_dec(rtc.readRegister(RV1805.RV1805_MONTHS))    year = bcd_to_dec(rtc.readRegister(RV1805.RV1805_YEARS))    day = bcd_to_dec(rtc.readRegister(RV1805.RV1805_WEEKDAYS))    # Calculate day of the week (0 = Sunday, 6 = Saturday)    # Adjusted calculation to match desired input where 0=Sunday, 1=Monday, ..., 6=Saturday    day_of_week = (day + 6) % 7    # Define weekday names    weekdays = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]    # Print the current datetime in a readable format    am_pm = "AM" if hour < 12 else "PM"    hour_12 = hour % 12    hour_12 = 12 if hour_12 == 0 else hour_12    print(f"Current datetime: 20{year:02}-{month:02}-{date:02} {weekdays[day_of_week]}, {hour_12:02}:{min:02}:{sec:02}.{hund:02} {am_pm}")# Main program executionOnboard_LED.on()received_messages = []rtc_set = Falsetry:    if connect_to_network():        print('Ready')        while not rtc_set:            s = socket.socket()            try:                s.connect((serverAP, port))                print('Connected to AP')                s.send(b'Hello from Client B!')                response = s.recv(1024)                message = response.decode()                print('Received the following date and time from the AP:', message)                received_messages.append(message)                                # Set RTC time from received data                hund, sec, min, hour, date, month, year, day_of_week = message.split()                set_time(int(hund), int(sec), int(min), int(hour), int(date), int(month), int(year), int(day_of_week))                                # Set flag to indicate RTC time is set                rtc_set = True            except OSError as e:                print('Socket error:', e)            finally:                s.close()                time.sleep(2)  # Adjust timing as needed        # Print current RTC time every 2 seconds        while True:            print_current_datetime()            time.sleep(2)except Exception as e:    print('Error occurred:', e)finally:    wlan.disconnect()    wlan.active(False)    print('Disconnected from Network.')    Onboard_LED.off()print('All received messages:', received_messages)

Statistics: Posted by Blue Mountain — Thu Jun 27, 2024 4:11 am — Replies 0 — Views 40



Viewing all articles
Browse latest Browse all 4525

Trending Articles