リモートセンサー接続が有効になっている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()
これが私のメインの外部ループになりました うまくいくようです:)