Note that there are some explanatory texts on larger screens.

plurals
  1. PORestarting socket connection following client disconnect
    primarykey
    data
    text
    <p>I have this code which listens/sends from/to a Scratch program with remote sensor connections enabled (e.g communicates by Port 42001 on 127.0.0.1)</p> <pre><code># This code is copyright Simon Walters under GPL v2 # This code is derived from scratch_handler by Thomas Preston # Version 5dev 11Aug08 Much better looping supplied by Stein @soilandreyes # and someone else @MCrRaspJam who've name I've forgotton! # Version 6dev - Moved Allon/AllOff to be processed before single pins :) # Vesion 7dev - start to tidy up changes # Vesion 8dev - use gpio-output system and broadcast allon, 1on system # V0.1 - change to 6 out 2 in and sanitise the code # V0.2 - from array import * import threading import socket import time import sys import struct import RPi.GPIO as GPIO GPIO.setmode(GPIO.BOARD) GPIO.setup(11,GPIO.OUT) GPIO.setup(12,GPIO.OUT) GPIO.setup(13,GPIO.OUT) GPIO.setup(15,GPIO.OUT) GPIO.setup(16,GPIO.OUT) GPIO.setup(18,GPIO.OUT) GPIO.setup(22,GPIO.IN,pull_up_down=GPIO.PUD_UP) GPIO.setup(7,GPIO.IN,pull_up_down=GPIO.PUD_UP) ''' from Tkinter import Tk from tkSimpleDialog import askstring root = Tk() root.withdraw() ''' PORT = 42001 DEFAULT_HOST = '127.0.0.1' #HOST = askstring('Scratch Connector', 'IP:') BUFFER_SIZE = 240 #used to be 100 SOCKET_TIMEOUT = 1 SCRATCH_SENSOR_NAME_INPUT = ( 'gpio-input0', 'gpio-input1' ) SCRATCH_SENSOR_NAME_OUTPUT = ( 'gpio-output0', 'gpio-output1', 'gpio-output2', 'gpio-output3', 'gpio-output4', 'gpio-output5' ) SCRATCH_BROADCAST_NAME_OUTPUT = ( '1on','1off','2on','2off','3on','3off','4on','4off','5on','5off','6on','6off' ) #Map gpio to real connector P1 Pins GPIO_PINS = array('i',[11,12,13,15,16,18,22,7]) GPIO_PIN_OUTPUT = array('i') GPIO_PIN_INPUT = array('i') print "Output Pins are:" for i in range(0,len(SCRATCH_SENSOR_NAME_OUTPUT)): print GPIO_PINS[i] GPIO_PIN_OUTPUT.append(GPIO_PINS[i]) print "Input Pins are:" for i in range(len(SCRATCH_SENSOR_NAME_OUTPUT),8): print GPIO_PINS[i] GPIO_PIN_INPUT.append(GPIO_PINS[i]) class ScratchSender(threading.Thread): #Not needed as its a Listening issue ... class ScratchListener(threading.Thread): def __init__(self, socket): threading.Thread.__init__(self) self.scratch_socket = socket self._stop = threading.Event() def stop(self): self._stop.set() def stopped(self): return self._stop.isSet() def physical_pin_update(self, pin_index, value): physical_pin = GPIO_PIN_OUTPUT[pin_index] print 'setting GPIO %d (physical pin %d) to %d' % (pin_index,physical_pin,value) GPIO.output(physical_pin, value) def run(self): #This is main listening routine while not self.stopped(): #time.sleep(0.1) # be kind to cpu try: data = self.scratch_socket.recv(BUFFER_SIZE) dataraw = data[4:].lower() print 'Length: %d, Data: %s' % (len(dataraw), dataraw) if len(dataraw) == 0: #This is probably due to client disconnecting #I'd like the program to retry connecting to the client time.sleep(2) except socket.timeout: print "sockect timeout" time.sleep(1) continue except: break if 'sensor-update' in dataraw: #gloablly set all ports if 'gpio-outputall' in dataraw: outputall_pos = dataraw.find('gpio-outputall') sensor_value = dataraw[(outputall_pos+16):].split() #print sensor_value[0] for i in range(len(SCRATCH_SENSOR_NAME_OUTPUT)): self.physical_pin_update(i,int(sensor_value[0])) #check for individual port commands for i in range(len(SCRATCH_SENSOR_NAME_OUTPUT)): if 'gpio-output'+str(i) in dataraw: #print 'Found '+ 'gpio-output'+str(i) outputall_pos = dataraw.find('gpio-output'+str(i)) sensor_value = dataraw[(outputall_pos+14):].split() #print sensor_value[0] self.physical_pin_update(i,int(sensor_value[0])) #Use bit pattern to control ports if 'gpio-pattern' in dataraw: #print 'Found gpio-outputall' num_of_bits = len(SCRATCH_SENSOR_NAME_OUTPUT) outputall_pos = dataraw.find('gpio-pattern') sensor_value = dataraw[(outputall_pos+14):].split() #print sensor_value[0] bit_pattern = ('0000000000000000'+sensor_value[0])[-num_of_bits:] #print 'bit_pattern %s' % bit_pattern for i in range(len(SCRATCH_SENSOR_NAME_OUTPUT)): #bit_state = ((2**i) &amp; sensor_value) &gt;&gt; i #print 'dummy gpio %d state %d' % (i, bit_state) physical_pin = GPIO_PIN_OUTPUT[i] if bit_pattern[-(i+1)] == '0': print 'setting GPIO %d (physical pin %d) low' % (i,physical_pin) GPIO.output(physical_pin, 0) else: print 'setting GPIO %d (physical pin %d) high' % (i,physical_pin) GPIO.output(physical_pin, 1) elif 'broadcast' in dataraw: #print 'received broadcast: %s' % data if 'allon' in dataraw: for i in range(len(SCRATCH_SENSOR_NAME_OUTPUT)): self.physical_pin_update(i,1) if 'alloff' in dataraw: for i in range(len(SCRATCH_SENSOR_NAME_OUTPUT)): self.physical_pin_update(i,0) for i in range(len(SCRATCH_SENSOR_NAME_OUTPUT)): #check_broadcast = str(i) + 'on' #print check_broadcast if str(i+1)+'on' in dataraw: self.physical_pin_update(i,1) if str(i+1)+'off' in dataraw: self.physical_pin_update(i,0) if 'pin' + str(GPIO_PIN_OUTPUT[i])+'on' in dataraw: GPIO.output(physical_pin, 1) if 'pin' + str(GPIO_PIN_OUTPUT[i])+'off' in dataraw: GPIO.output(physical_pin, 0) elif 'stop handler' in dataraw: cleanup_threads((listener, sender)) sys.exit() else: print 'received something: %s' % dataraw def create_socket(host, port): while True: try: print 'Trying' scratch_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) scratch_sock.connect((host, port)) break except socket.error: print "There was an error connecting to Scratch!" print "I couldn't find a Mesh session at host: %s, port: %s" % (host, port) time.sleep(3) #sys.exit(1) return scratch_sock def cleanup_threads(threads): for thread in threads: thread.stop() for thread in threads: thread.join() if __name__ == '__main__': if len(sys.argv) &gt; 1: host = sys.argv[1] else: host = DEFAULT_HOST # open the socket print 'Connecting...' , the_socket = create_socket(host, PORT) print 'Connected!' the_socket.settimeout(SOCKET_TIMEOUT) listener = ScratchListener(the_socket) sender = ScratchSender(the_socket) listener.start() sender.start() # wait for ctrl+c try: while True: time.sleep(0.5) except KeyboardInterrupt: cleanup_threads((listener, sender)) sys.exit() </code></pre> <p>The issue I'm having is in this section of code</p> <pre><code> def run(self): #This is main listening routine while not self.stopped(): #time.sleep(0.1) # be kind to cpu try: data = self.scratch_socket.recv(BUFFER_SIZE) dataraw = data[4:].lower() print 'Length: %d, Data: %s' % (len(dataraw), dataraw) if len(dataraw) == 0: #This is probably due to client disconnecting #I'd like the program to retry connecting to the client time.sleep(2) except socket.timeout: print "sockect timeout" time.sleep(1) continue except: break </code></pre> <p>If the client disconnects e.g Scratch is closed, I need this program to basically restart looking for a connection again and wait for Scratch to re-connect. Could I have some suggestions as to how to achieve this please as I am a python newbie regards Simon</p> <p>My solution was to use a global variable and change main loop structure</p> <pre><code> if len(dataraw) == 0: #This is probably due to client disconnecting #I'd like the program to retry connecting to the client #tell outer loop that Scratch has disconnected if cycle_trace == 'running': cycle_trace = 'disconnected' break </code></pre> <p>is used to break out of loop and</p> <pre><code>cycle_trace = 'start' while True: if (cycle_trace == 'disconnected'): print "Scratch disconnected" cleanup_threads((listener, sender)) time.sleep(1) cycle_trace = 'start' if (cycle_trace == 'start'): # open the socket print 'Starting to connect...' , the_socket = create_socket(host, PORT) print 'Connected!' the_socket.settimeout(SOCKET_TIMEOUT) listener = ScratchListener(the_socket) sender = ScratchSender(the_socket) cycle_trace = 'running' print "Running...." listener.start() sender.start() # wait for ctrl+c try: #just pause time.sleep(0.5) except KeyboardInterrupt: cleanup_threads((listener,sender)) sys.exit() </code></pre> <p>this is now my main outer loop Seems to work :)</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload