Clients and servers are pieces of software. Servers sit and wait for a client request. The basic blinky of socket programming is to make a connection between a client socket and a server socket, then then do something like print Hello World on both ends of the connection to see that it’s alive, then close the connection. The Blinky_Ping_client.py script (WiPy) does a sort of ping by opening and closing a socket on Blinky_Ping_server.py (laptop). The "ping" time can be seen in how fast the LED blinks. Each time a socket is opened and closed the LED turns on and then off once. Each time the LED turns on or off, the speaker emits a click. The clicks bracket the time spent opening, then interacting, then closing the socket. In my case theinterval ranged from 7ms to 2500ms.
The green and orange jumpers are the speaker leads. The ground side of the speaker passes through a 1uF capacitor. Any value between 1uF and 250uF work fine. Watch for polarity on electrolytic caps!
By ancient custom some port numbers are associated with particular well known services or protocols. Port 80 is used by web servers. A web server socket looks like “192.168.1.1:80”. There are about 65000 possible port numbers. Port numbers are chosen by the program or handed out by the operating system. Port numbers must match expectations on both ends of the connection so that the client and server can find each other.The telnet session and the serial terminal show the same information, but the Cutecom serial terminal is easier to read than the telnet window, IMO. The serial connection often still works if the wireless connection fails.
In small embedded systems, we're used to seeing the server code running on the small device and the client, e.g. a web browser running on the laptop. Not so here. In this case, the WiPy is the client. Servers must listen at all times for a client request, and so must stay awake, thus draining their battery. If the embedded device is the client, it can wake up from hibernate whenever it pleases, then interact with the server, then go back to sleep. Blinky_Ping doesn't use a low-power configuration, but low power is the way of the future.
Here is the client:
# Blinky_Ping_client.py, alias main.py on wipy # Ed Bennett ''' This was helpful: http://www.bogotobogo.com/python/python_network_programming_server_client.php This script does a sort of ping by measuring the time of opening and closing a socket on a remote server. (Blinky_Ping_server.py) The "ping" time can be seen in how fast the LED blinks. When a socket is starting to be opened the LED turns on. When the socket has closed the LED turns off. ''' if __name__ == '__main__': import socket import time from machine import Pin host = '192.168.1.64' # laptop running server port = 9999 addr = socket.getaddrinfo(host, port)[0][-1] # The expansion board is designed so that the"user led" on G16 # is switched on the low side [google for low-side switch], # therefore the LED's logic level is inverted. 1 is off, 0 is on. # The GP16 pin itself is NOT inverted. LED1 = Pin('GP16', mode=Pin.OUT) LED1.value(1) # blink once to check wiring on startup time.sleep_ms(1000) LED1.value(0) time.sleep_ms(1000) w = 0 # while loop counter elapsed = 10 # initialize to 10ms ''' The stop_flag allows you to stop a broken, long, or infinite loop and interact with the filesystem by using commands in the os module, etc. Making GP10 high (touch a jumper between GP10 and +3.3V) causes the while loop to end and return you to the repl. ''' stop_pin = Pin('GP10', mode=Pin.IN, pull=Pin.PULL_DOWN) stop_flag = 0 stop_flag = stop_pin() # check here in case the while loop is broken while w < 1000 and stop_flag == 0: stop_flag = stop_pin() print("stop_flag = ", stop_flag) if stop_flag == 1: print("stopped") break ''' This pauses the loop for the same number of milliseconds as the previous message's round-trip. Otherwise it would be hard to see the LED blinking. The measured value of "elapsed" is not affected. ''' time.sleep_ms(elapsed) ''' Measure the overhead in sending data between my laptop and the WiPy through my home router: start a timer, then connect to the server, then don't send any data, then receive some data from the server, then close the socket, then stop the timer. ''' LED1.value(1) start = time.ticks_ms() # init the elapsed timer: start measuring # create a socket object s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(addr) # This just shows the idea of a small amount of data coming # back from the server. # Receive no more than 1024 bytes tm = s.recv(1024) s.close() elapsed = time.ticks_diff(start, time.ticks_ms()) #measure loop time LED1.value(0) print("Loop #", w, " round trip time was", elapsed, "ms") print("The time got from the server is %s" % tm.decode('ascii')) w += 1
Here is the server:
# Blinky_Ping_server.py # runs on laptop # http://www.bogotobogo.com/python/python_network_programming_server_client.php # This is pretty much the standard minimal server socket demo, but with the # added feature of sending the time to the client. import socket import time # create a socket object mytcpsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) mytcpsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # # get this computer's name # host = socket.gethostname() this was getting machine name not ipaddr host='192.168.1.64' # only the server's actual ip address works here (?!) port = 9999 # bind to the port mytcpsock.bind((host, port)) # queue up to 5 requests mytcpsock.listen(5) while True: # establish a connection clientsocket,addr = mytcpsock.accept() print("Got a connection from %s" % str(addr)) currentTime = time.ctime(time.time()) + "\r\n" clientsocket.send(currentTime.encode('ascii')) clientsocket.close()
Ed Bennett ed atsign kineticsandelectronics dotcom
Comments will be approved before showing up.