3

リモートセンサー接続が有効になっているScratchプログラムをリッスン/送信するこのコードがあります(たとえば、127.0.0.1のポート42001で通信します)

# 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) & sensor_value) >> 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) > 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()

私が抱えている問題は、コードのこのセクションにあります

    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

クライアントが切断された場合、たとえば Scratch が閉じられた場合、基本的にこのプログラムを再起動して接続を再度探し、Scratch が再接続するのを待つ必要があります。私はPythonの初心者なので、これを達成する方法についていくつかの提案をお願いしますサイモンについて

私の解決策は、グローバル変数を使用してメインループ構造を変更することでした

        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

ループから抜け出すために使用され、

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()

これが私のメインの外部ループになりました うまくいくようです:)

4

0 に答える 0