Hallo,
ich bastle mir gerade einen Telegrambot mit Python. Der funktioniert auch. Man sendet einen Textbefehl an den Bot und der macht dann irgendwas (eine LED einschalten, ein Foto machen, etc...). Wichtig für meine Frage sind nur die beiden letzten Zeilen und die Funktion handle_text().
!/usr/bin/env python3
import RPi.GPIO as GPIO
import time # ...für den sleep()
import threading
import random
import signal
from pprint import pprint
from picamera import PiCamera
from time import sleep
import telepot
from telepot.loop import MessageLoop
bot = telepot.Bot('BOTID einsetzen')
my_chat_id = meinePersChatid
pprint(bot.getMe())
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(4,GPIO.OUT)
camera = PiCamera()
camera.resolution = (512, 384)
# --- Eingehende Meldungen verarbeiten
def handle_text(msg):
hilfeText = "Hilfe (dieser Text)\nDanke\nLED\nFoto\n'Stein' oder 'Papier' oder 'Schere' (Spiel...)"
pprint(msg)
content_type, chat_type, chat_id = telepot.glance(msg)
if content_type == 'text':
bot.sendMessage(my_chat_id, msg)
if msg['text'].upper() == "HILFE":
bot.sendMessage(chat_id, hilfeText)
elif msg['text'].upper() == "STEIN" or msg['text'].upper() == "SCHERE" or msg['text'].upper() == "PAPIER":
bot.sendMessage(chat_id, spielen(msg['text'].upper()))
elif msg['text'].upper() == "DANKE":
bot.sendMessage(chat_id, "Bitte!")
elif msg['text'].upper() == "LED":
gpio()
elif msg['text'].upper() == "FOTO":
t = threading.Thread(target=gpio) #LED einschalten...
t.daemon = True
t.start()
foto(camera) #...und parallel dazu die LED fotografieren
bot.sendPhoto(chat_id, open(str('foto.jpg'), 'rb'))
else:
bot.sendMessage(chat_id, "ich verstehe '%s' noch nicht!" % msg['text'])
bot.sendMessage(chat_id, "Aber bald!")
def foto(camera):
camera.capture('foto.jpg')
return
def gpio():
GPIO.output(4,True)
time.sleep(10)
GPIO.output(4,False)
def spielen(versuch):
returnWert = "Leer"
myChoiceAuswahl = ["STEIN", "PAPIER", "SCHERE"]
myChoice = random.choice(myChoiceAuswahl)
if versuch.upper() == "STEIN":
if myChoice == "STEIN":
returnWert = "Ich: Stein\n Du: Stein\n Unentschieden"
if myChoice == "PAPIER":
returnWert = "Ich: Papier\n Du: Stein\n Ich, der geile Supertbot gewinnt"
if myChoice == "SCHERE":
returnWert = "Ich: Schere\n Du: Stein\n Du gewinnst"
if versuch.upper() == "PAPIER":
if myChoice == "PAPIER":
returnWert = "Ich: Papier\n Du: Papier\n Unentschieden"
if myChoice == "SCHERE":
returnWert = "Ich: Schere\n Du: Papier\n Ich, der geile Supertbot gewinnt"
if myChoice == "STEIN":
returnWert = "Ich: Stein\n Du: Papier\n Du gewinnst"
if versuch.upper() == "SCHERE":
if myChoice == "SCHERE":
returnWert = "Ich: Schere\n Du: Schere\n Unentschieden"
if myChoice == "STEIN":
returnWert = "Ich: Stein\n Du: Schere\n Ich, der geile Supertbot gewinnt"
if myChoice == "PAPIER":
returnWert = "Ich: Papier\n Du: Schere\n Du gewinnst"
else:
returnwert = "Da ist ein Fehler..."
return returnWert
MessageLoop(bot, handle_text).run_as_thread()
signal.pause()
Alles anzeigen
Problem: Ich kann das Script aber immer nur genau 1x aufrufen. Wenn ich versuche, das Script in der gleichen Terminalinstanz ein zweites mal aufzurufen, bekomme ich folgenden Fehler im Terminal angezeigt:
ZitatAlles anzeigenmmal: mmal_vc_port_enable: failed to enable port vc.null_sink:in:0(OPQV): ENOSPC
mmal: mmal_port_enable: failed to enable connected port (vc.null_sink:in:0(OPQV))0x1bae250 (ENOSPC)
mmal: mmal_connection_enable: output port couldn't be enabled
Traceback (most recent call last):
File "bot11.py", line 23, in <module>
camera = PiCamera()
File "/usr/lib/python3/dist-packages/picamera/camera.py", line 433, in __init__
self._init_preview()
File "/usr/lib/python3/dist-packages/picamera/camera.py", line 513, in _init_preview
self, self._camera.outputs[self.CAMERA_PREVIEW_PORT])
File "/usr/lib/python3/dist-packages/picamera/renderers.py", line 558, in __init__
self.renderer.inputs[0].connect(source).enable()
File "/usr/lib/python3/dist-packages/picamera/mmalobj.py", line 2212, in enable
prefix="Failed to enable connection")
File "/usr/lib/python3/dist-packages/picamera/exc.py", line 184, in mmal_check
raise PiCameraMMALError(status, prefix)
picamera.exc.PiCameraMMALError: Failed to enable connection: Out of resources
Der Fehler tritt erst auf, seit ich die picamera in das Skript eingabaut habe. Vorher konnte ich das Skript beliebig oft starten. Wahrscheinlich hängt es damit zusammen, dass die Funktion handle_text() in einem eigenen Thread abläuft und danach signal.pause() aufgerufen wird.
Ich kann dieses Skript immer nur mit CTRL+Z beenden. Damit hat picamera wohl ein Problem. Um das Skript wieder starten zu können, muss ich ein neues Terminal öffnen.
Ich hätte gerne folgende Lösung: Ich sende einen Textbefehl (z.B. "Ende") über meinen Telegramclient an den Bot. Der Bot erkennt den Befehl (wie die anderen im Beispiel auch) und veranlasst, dass das Skript sauber beendet wird.
Ich hatte mir versuchsweise ein einfaches Script geschrieben, das einfach nur mit picamera ein Foto schiesst und sich dann wieder beendet. Das kann ich beliebig oft aufrufen. Nur in der Kombination mit signal.pause() und dem Thread klappt das nicht.
Ich hatte auch schon versucht, die beiden letzten Zeilen in eine Whileschleife zu stecken (while weiter == 1): und die Variable "weiter" in der Funktion handle_text auf "0"
zu ändern. Klappt aber nicht, weil die Funktion in einem eigenen Thread läuft und die Variable nicht kennt.
Hat jemand eine Idee, wie man das Skript sauber beendet oder den picamera-Fehler abstellt?
Gruß Bernie