From f9f2bfcdd7f159aeb1d65664c3305908b82aa3e9 Mon Sep 17 00:00:00 2001 From: Tilman Date: Tue, 31 Oct 2017 16:22:41 +0100 Subject: [PATCH] Before putting all into callbacks --- code/piplayer3.py | 62 ++++++---- code/piplayer3.py.bak | 222 +++++++++++++++++++++++++++++++++++ code/piplayer3_noCallback.py | 194 ++++++++++++++++++++++++++++++ code/piplayer_pulse.py | 176 +++++++++++++++++++++++++++ code/test/sensor.py | 4 +- notes.md | 39 ++++-- 6 files changed, 665 insertions(+), 32 deletions(-) create mode 100644 code/piplayer3.py.bak create mode 100644 code/piplayer3_noCallback.py create mode 100644 code/piplayer_pulse.py diff --git a/code/piplayer3.py b/code/piplayer3.py index 332aee4..ab2ab8c 100644 --- a/code/piplayer3.py +++ b/code/piplayer3.py @@ -23,6 +23,10 @@ QR_SCANNER_TIMEOUT = 3 MOPIDY_RPC_URL = 'http://127.0.0.1:6680/mopidy/rpc' MUSIC_EXTENSIONS = ('.aac', '.ac3', '.aiff', '.amr', '.au', '.flac', '.m4a', '.mid', '.mka', '.mp3', '.ogg', '.ra', '.voc', '.wav', '.wma') +REQUEST_TIMEOUT = 5 +creating_playlist = False +request_running = False + # photo sensor on PIN 17 PIN_SENSOR = 17 @@ -53,15 +57,18 @@ GPIO.setup(PIN_PLAY, GPIO.IN, pull_up_down=GPIO.PUD_UP) GPIO.setup(PIN_NEXT, GPIO.IN, pull_up_down=GPIO.PUD_UP) - def call(method, params=None): if (params is None): json = '{"jsonrpc": "2.0", "id": 1, "method": "' + method + '"}' else: json = '{"jsonrpc": "2.0", "id": 1, "method": "' + method + '" , "params": ' + params + '}' - response = requests.post(MOPIDY_RPC_URL, data=json) - logging.debug(response.text) + logging.info('Request: ' + json) + try: + response = requests.post(MOPIDY_RPC_URL, data=json, timeout=REQUEST_TIMEOUT) + except: + logging.error('Exeption during request') + logging.info('Response: ' + response.text) return response def add_uri(filename): @@ -85,44 +92,56 @@ def list_files(dir): -def btn1_callback(channel): - logging.debug("PREV") +def prev_callback(channel): + logging.info("PREV") json = call('core.playback.get_time_position').json() if (json['result'] < 4000): call('core.playback.previous') else: call('core.playback.seek', '{ "time_position": 0 }') -def btn2_callback(channel): - logging.debug("PLAY/PAUSE") +def play_callback(channel): + logging.info("PLAY/PAUSE") json = call('core.playback.get_state').json() if (json['result'] == 'playing'): call('core.playback.pause') else: call('core.playback.play') -def btn3_callback(channel): - logging.debug("NEXT") +def next_callback(channel): + logging.info("NEXT") call('core.playback.next') +def sensor_callback(channel): + logging.info("SENSOR!!!!! ================================================================= !!!11!1elf") -GPIO.add_event_detect(PIN_PREV, GPIO.FALLING, callback=btn1_callback, bouncetime=400) -GPIO.add_event_detect(PIN_PLAY, GPIO.FALLING, callback=btn2_callback, bouncetime=400) -GPIO.add_event_detect(PIN_NEXT, GPIO.FALLING, callback=btn3_callback, bouncetime=400) + +GPIO.add_event_detect(PIN_PREV, GPIO.FALLING, callback=prev_callback, bouncetime=400) +GPIO.add_event_detect(PIN_PLAY, GPIO.FALLING, callback=play_callback, bouncetime=400) +GPIO.add_event_detect(PIN_NEXT, GPIO.FALLING, callback=next_callback, bouncetime=400) + +#GPIO.add_event_detect(PIN_SENSOR, GPIO.RISING, callback=sensor_callback, bouncetime=400) try: - # FIXME turn this into a proper service and wait for the network interface (and mopidy) - # https://www.dexterindustries.com/howto/run-a-program-on-your-raspberry-pi-at-startup/#systemd - time.sleep(20) + # wait for the web server to be available + response = '' + while response == '': + try: + logging.info("Trying to connect to the server...") + response = requests.post(MOPIDY_RPC_URL, data='{"jsonrpc": "2.0", "id": 1, "method": "core.tracklist.clear"}', timeout=REQUEST_TIMEOUT) + except: + logging.debug("Connection refused by the server, wait 5 seconds") + time.sleep(5) + continue play_sound(SOUND_OK) while True: - logging.debug('Wait for photo sensor') + logging.info('Wait for photo sensor') GPIO.wait_for_edge(PIN_SENSOR, GPIO.RISING) - logging.debug('Photo sensor active, activating light and camera') + logging.info('Photo sensor active, activating light and camera') play_sound(SOUND_SCANNING) # turn LED on @@ -147,7 +166,7 @@ try: play_sound(SOUND_OK) call('core.tracklist.clear') - logging.debug("Stopped") + logging.info("Stopped") qr_code = zbarcam.stdout.readline().rstrip() qr_code = qr_code.decode("utf-8") # python3 @@ -155,6 +174,8 @@ try: if (not (qr_code.startswith("http://") or qr_code.startswith("spotify:"))): # create full path + if (qr_code.startswith("/")): + qr_code = qr_code[1:] full_path = MUSIC_BASE_DIRECTORY + qr_code if (not os.path.isfile(full_path)): @@ -165,9 +186,8 @@ try: if filename.lower().endswith(MUSIC_EXTENSIONS): add_uri("file://" + urllib.parse.quote(filename)) if (not playback_started): - call('core.playback.play') playback_started = True - + call('core.playback.play') else: logging.debug("It's a file") @@ -192,8 +212,6 @@ try: play_sound(SOUND_SCAN_FAIL) zbarcam.terminate() - - # LED off GPIO.output(PIN_LED, GPIO.LOW) # wait until sensor is not blocked anymore diff --git a/code/piplayer3.py.bak b/code/piplayer3.py.bak new file mode 100644 index 0000000..6f75e24 --- /dev/null +++ b/code/piplayer3.py.bak @@ -0,0 +1,222 @@ +# piplayer3 - AudioSaucer +# http://www.tilman.de/piplayer3 +import RPi.GPIO as GPIO +import logging +import time +import subprocess +import select # for polling zbarcam, see http://stackoverflow.com/a/10759061/3761783 +import os +import requests +import urllib + +logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)s - %(message)s') +logging.info('Initializing') + +# Configuration +MUSIC_BASE_DIRECTORY = "/media/share/Kinder/" +SOUND_SCANNING = "file:///home/pi/sounds/scanning.mp3" +SOUND_OK = "file:///home/pi/sounds/ok.mp3" +SOUND_SCAN_FAIL = "file:///home/pi/sounds/fail.mp3" +SOUND_PLAYBACK_ERROR = "file:///home/pi/sounds/error.mp3" +QR_SCANNER_TIMEOUT = 3 + +MOPIDY_RPC_URL = 'http://127.0.0.1:6680/mopidy/rpc' +MUSIC_EXTENSIONS = ('.aac', '.ac3', '.aiff', '.amr', '.au', '.flac', '.m4a', '.mid', '.mka', '.mp3', '.ogg', '.ra', '.voc', '.wav', '.wma') + +# photo sensor on PIN 17 +PIN_SENSOR = 17 + +# IR LED on PIN 22 +PIN_IR_LED = 22 + +# LED on PIN 27 +PIN_LED = 27 + +# Buttons on PINs 9, 10 and 11 +PIN_PREV = 9 +PIN_PLAY = 10 +PIN_NEXT = 11 + + +GPIO.setmode(GPIO.BCM) + +GPIO.setup(PIN_SENSOR, GPIO.IN) + +GPIO.setup(PIN_IR_LED, GPIO.OUT) +GPIO.output(PIN_IR_LED, GPIO.LOW) + +GPIO.setup(PIN_LED, GPIO.OUT) +GPIO.output(PIN_LED, GPIO.LOW) + +GPIO.setup(PIN_PREV, GPIO.IN, pull_up_down=GPIO.PUD_UP) +GPIO.setup(PIN_PLAY, GPIO.IN, pull_up_down=GPIO.PUD_UP) +GPIO.setup(PIN_NEXT, GPIO.IN, pull_up_down=GPIO.PUD_UP) + + + +def call(method, params=None): + if (params is None): + json = '{"jsonrpc": "2.0", "id": 1, "method": "' + method + '"}' + else: + json = '{"jsonrpc": "2.0", "id": 1, "method": "' + method + '" , "params": ' + params + '}' + + response = requests.post(MOPIDY_RPC_URL, data=json) + logging.debug(response.text) + return response + +def add_uri(filename): + logging.debug('Adding ' + filename) + call('core.tracklist.add', '{"uri": "' + filename + '"}') + +def play_sound(filename): + call('core.tracklist.clear') + logging.debug('Cleared tracklist, now playing ' + filename) + add_uri(filename) + call('core.playback.play') + +def list_files(dir): + r = [] + for path, dirs, files in os.walk(dir): + dirs.sort() + files.sort() + for name in files: + r.append(os.path.join(path, name)) + return r + + + +def btn1_callback(channel): + logging.debug("PREV") + json = call('core.playback.get_time_position').json() + if (json['result'] < 4000): + call('core.playback.previous') + else: + call('core.playback.seek', '{ "time_position": 0 }') + +def btn2_callback(channel): + logging.debug("PLAY/PAUSE") + json = call('core.playback.get_state').json() + if (json['result'] == 'playing'): + call('core.playback.pause') + else: + call('core.playback.play') + +def btn3_callback(channel): + logging.debug("NEXT") + call('core.playback.next') + + +GPIO.add_event_detect(PIN_PREV, GPIO.FALLING, callback=btn1_callback, bouncetime=400) +GPIO.add_event_detect(PIN_PLAY, GPIO.FALLING, callback=btn2_callback, bouncetime=400) +GPIO.add_event_detect(PIN_NEXT, GPIO.FALLING, callback=btn3_callback, bouncetime=400) + + +try: + # wait for the web server to be available + response = '' + while response == '': + try: + logging.debug("Trying to connect to the server...") + response = requests.post(MOPIDY_RPC_URL, data='{"jsonrpc": "2.0", "id": 1, "method": "core.tracklist.clear"}', timeout=5) + except: + logging.debug("Connection refused by the server, wait 5 seconds") + time.sleep(5) + continue + + play_sound(SOUND_OK) + + while True: + logging.debug('Wait for photo sensor') + GPIO.wait_for_edge(PIN_SENSOR, GPIO.RISING) + + logging.debug('Photo sensor active, activating light and camera') + play_sound(SOUND_SCANNING) + + # turn LED on + GPIO.output(PIN_LED, GPIO.HIGH) + + # scan QR code + zbarcam = subprocess.Popen(['zbarcam', '--quiet', '--nodisplay', '--raw', '-Sdisable', '-Sqrcode.enable', '--prescale=320x240', '/dev/video0'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) + + poll_obj = select.poll() + poll_obj.register(zbarcam.stdout, select.POLLIN) + + # wait for scan result (or timeout) + start_time = time.time() + poll_result = False + while ((time.time() - start_time) < QR_SCANNER_TIMEOUT and (not poll_result)): + poll_result = poll_obj.poll(100) + + if (poll_result): + + try: + # play confirmation sound + play_sound(SOUND_OK) + + call('core.tracklist.clear') + logging.debug("Stopped") + + qr_code = zbarcam.stdout.readline().rstrip() + qr_code = qr_code.decode("utf-8") # python3 + logging.info("QR Code: " + qr_code) + + if (not (qr_code.startswith("http://") or qr_code.startswith("spotify:"))): + # create full path + if (qr_code.startswith("/")): + qr_code = qr_code[1:] + + full_path = MUSIC_BASE_DIRECTORY + qr_code + + if (not os.path.isfile(full_path)): + logging.debug("Not a file, recursively add all audio files in directory") + filenames = list_files(full_path) + playback_started = False + for filename in filenames: + if filename.lower().endswith(MUSIC_EXTENSIONS): + add_uri("file://" + urllib.parse.quote(filename)) + if (not playback_started): + logging.debug("starting playback") + call('core.playback.play') + playback_started = True + + + else: + logging.debug("It's a file") + add_uri("file://" + urllib.parse.quote(full_path)) + call('core.playback.play') + + else: + logging.debug("URL, open directly") + add_uri(qr_code) + call('core.playback.play') + + except subprocess.CalledProcessError as e: + logging.error("Error starting playback, mocp returned {}".format(e.returncode)) + logging.error(e.output) + play_sound(SOUND_PLAYBACK_ERROR) + except FileNotFoundError as e: + logging.error("Could not open directory {}".format(directory)) + play_sound(SOUND_PLAYBACK_ERROR) + + else: + logging.warning('Timeout on zbarcam') + play_sound(SOUND_SCAN_FAIL) + + zbarcam.terminate() + + # LED off + GPIO.output(PIN_LED, GPIO.LOW) + + # wait until sensor is not blocked anymore + if (GPIO.input(PIN_SENSOR) == GPIO.HIGH): + GPIO.wait_for_edge(PIN_SENSOR, GPIO.FALLING) + time.sleep(1) + + +# Exit when Ctrl-C is pressed +except KeyboardInterrupt: + logging.info('Shutdown') + +finally: + logging.info('Reset GPIO configuration and close') + GPIO.cleanup() diff --git a/code/piplayer3_noCallback.py b/code/piplayer3_noCallback.py new file mode 100644 index 0000000..cdc16a1 --- /dev/null +++ b/code/piplayer3_noCallback.py @@ -0,0 +1,194 @@ +# Control script for the piPlayer. In order to run with PulseAudio, the OSS +# sound driver has to be set as first option in ~/.moc/config +# The mocp server is then run over the padsp wrapper. +# +# ~/.moc/config +# # Use OSS for Pulseaudio compatibility (run 'padsp mocp') +# SoundDriver = OSS:ALSA:JACK + +import RPi.GPIO as GPIO +import logging +import time +import subprocess +import select # see http://stackoverflow.com/a/10759061/3761783 +import os + +logging.basicConfig(level=logging.INFO, format='%(asctime)s %(levelname)s - %(message)s') +logging.info('Initializing') + +# Configuration +MUSIC_BASE_DIRECTORY = "/media/share/Kinder/" +SOUND_SCANNING = "file:///home/pi/sounds/scanning.mp3" +SOUND_OK = "file:///home/pi/sounds/ok.mp3" +SOUND_SCAN_FAIL = "file:///home/pi/sounds/fail.mp3" +SOUND_PLAYBACK_ERROR = "file:///home/pi/sounds/error.mp3" +QR_SCANNER_TIMEOUT = 3 +BUTTON_PAUSE = 0.4 + +# photo sensor on PIN 17 +PIN_SENSOR = 17 + +# IR LED on PIN 22 +PIN_IR_LED = 22 + +# LED on PIN 27 +PIN_LED = 27 + +# Buttons on PINs 9, 10 and 11 +PIN_PREV = 9 +PIN_PLAY = 10 +PIN_NEXT = 11 + + +GPIO.setmode(GPIO.BCM) + +GPIO.setup(PIN_SENSOR, GPIO.IN) + +GPIO.setup(PIN_IR_LED, GPIO.OUT) +GPIO.output(PIN_IR_LED, GPIO.LOW) + +GPIO.setup(PIN_LED, GPIO.OUT) +GPIO.output(PIN_LED, GPIO.LOW) + +GPIO.setup(PIN_PREV, GPIO.IN, pull_up_down=GPIO.PUD_UP) +GPIO.setup(PIN_PLAY, GPIO.IN, pull_up_down=GPIO.PUD_UP) +GPIO.setup(PIN_NEXT, GPIO.IN, pull_up_down=GPIO.PUD_UP) + + + +photo_sensor_still_active = False + +try: + logging.info('Start moc server') + subprocess.call(["padsp", "mocp", "--server"]) + subprocess.call(["mocp", "--clear"]) + subprocess.call(["mocp", "-l", SOUND_OK]) + + while True: + + # TODO what's a good value here? + time.sleep(0.01) + + if (GPIO.input(PIN_PREV) == False): + logging.debug('mocp --previous') + subprocess.call(["mocp", "--previous"]) + time.sleep(BUTTON_PAUSE) + # TODO wait for ~0.25 s, if button is still pressed, seek instead of skipping + + if (GPIO.input(PIN_PLAY) == False): + logging.debug('mocp --toggle-pause') + subprocess.call(["mocp", "--toggle-pause"]) + time.sleep(BUTTON_PAUSE) + + if (GPIO.input(PIN_NEXT) == False): + logging.debug('mocp --next') + subprocess.call(["mocp", "--next"]) + time.sleep(BUTTON_PAUSE) + # TODO wait for ~0.25 s, if button is still pressed, seek instead of skipping + + # check photo sensor + if ((not photo_sensor_still_active) and (GPIO.input(PIN_SENSOR) == GPIO.HIGH)): + logging.debug('Photo sensor active, activating light and camera') + subprocess.call(["mocp", "-l", SOUND_SCANNING]) + + # turn LED on + GPIO.output(PIN_LED, GPIO.HIGH) + + # scan QR code + zbarcam = subprocess.Popen(['zbarcam', '--nodisplay', '--raw', '-Sdisable', '-Sqrcode.enable', '--prescale=320x240', '/dev/video0'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) + + poll_obj = select.poll() + poll_obj.register(zbarcam.stdout, select.POLLIN) + + # wait for scan result (or timeout) + start_time = time.time() + poll_result = False + while ((time.time() - start_time) < QR_SCANNER_TIMEOUT and (not poll_result)): + poll_result = poll_obj.poll(100) + + if (poll_result): + + try: + + qr_code = zbarcam.stdout.readline().rstrip() + qr_code = qr_code.decode("utf-8") # python3 + logging.debug("QR Code: {}".format(qr_code)) + + if (not qr_code.startswith("http://")): + # create full path + full_path = MUSIC_BASE_DIRECTORY + qr_code + + logging.debug("Full Path {}".format(full_path)) + if (not os.path.isfile(full_path)): + logging.debug("not a file > add as directory") + directory = full_path + logging.debug("Directory {}".format(directory)) + else: + logging.debug("it's a file") + directory = os.path.dirname(os.path.realpath(full_path)) + filename = os.path.basename(full_path) + logging.debug("Directory {}".format(directory)) + logging.debug("Filename {}".format(filename)) + + os.chdir(directory) + + #onlyfiles = [f for f in os.listdir('.') if os.path.isfile(os.path.join('.', f))] + #logging.debug(onlyfiles) + + else: + logging.debug("URL > open as stream") + stream_url = qr_code + + subprocess.call(["mocp", "--clear"]) + subprocess.call(["mocp", "--stop"]) + + logging.debug("Stopped") + + # play confirmation sound + subprocess.call(["mocp", "-l", SOUND_OK]) + + if ('stream_url' in locals()): + logging.debug("Add stream") + subprocess.check_call(["mocp", "-a", stream_url]) + del stream_url + elif ('filename' in locals()): + logging.debug("Add file {}".format(filename)) + subprocess.check_call(["mocp", "-a", filename]) + del filename + else: + logging.debug("Add directory {}".format(directory)) + subprocess.check_call(["mocp", "-a", "."]) + + # subprocess.check_call(["mocp", "-a", target, "-p"]) + logging.debug("Start playback") + subprocess.check_call(["mocp", "-p"]) + + except subprocess.CalledProcessError as e: + logging.debug("Error starting playback, mocp returned {}".format(e.returncode)) + logging.debug(e.output) + subprocess.call(["mocp", "-l", SOUND_PLAYBACK_ERROR]) + except FileNotFoundError as e: + logging.debug("Could not open directory {}".format(directory)) + subprocess.call(["mocp", "-l", SOUND_PLAYBACK_ERROR]) + else: + logging.debug('Timeout on zbarcam') + subprocess.call(["mocp", "-l", SOUND_SCAN_FAIL]) + + # consider the photo sensor to be blocked + photo_sensor_still_active = True + + zbarcam.terminate() + + # LED off + GPIO.output(PIN_LED, GPIO.LOW) + + elif (GPIO.input(PIN_SENSOR) == GPIO.LOW): + # the photo sensor is not blocked (anymore) + photo_sensor_still_active = False + +# Exit when Ctrl-C is pressed +except KeyboardInterrupt: + logging.info('Close moc server') + subprocess.call(["mocp", "--exit"]) + logging.info('Reset GPIO configuration and close') +GPIO.cleanup() \ No newline at end of file diff --git a/code/piplayer_pulse.py b/code/piplayer_pulse.py new file mode 100644 index 0000000..38c5cfc --- /dev/null +++ b/code/piplayer_pulse.py @@ -0,0 +1,176 @@ +# Control script for the piPlayer. In order to run with PulseAudio, the OSS +# sound driver has to be set as first option in ~/.moc/config +# The mocp server is then run over the padsp wrapper. +# +# ~/.moc/config +# # Use OSS for Pulseaudio compatibility (run 'padsp mocp') +# SoundDriver = OSS:ALSA:JACK + +import RPi.GPIO as GPIO +import logging +import time +import subprocess +import select # see http://stackoverflow.com/a/10759061/3761783 +import os + +# Configuration +MUSIC_BASE_DIRECTORY = "/media/share/Audio/Kinder/" +SOUND_SCANNING = "/home/pi/scanning.mp3" +SOUND_OK = "/home/pi/263133__pan14__tone-beep.mp3" +SOUND_SCAN_FAIL = "/home/pi/159367__huminaatio__7-error.mp3" +SOUND_PLAYBACK_ERROR = "/home/pi/no.mp3" +QR_SCANNER_TIMEOUT = 3 +BUTTON_PAUSE = 0.4 + +logging.basicConfig(level=logging.DEBUG, format='%(asctime)s.%(msecs)d %(levelname)s - %(message)s') +logging.info('Initializing') + +# photo sensor on PIN 4 +GPIO.setmode(GPIO.BCM) +GPIO.setup(4, GPIO.IN) + +# LED on PIN 17 +GPIO.setup(17, GPIO.OUT) +GPIO.output(17, GPIO.LOW) + +# Buttons on PINs 14, 15 and 18 +GPIO.setup(14, GPIO.IN, pull_up_down=GPIO.PUD_UP) +GPIO.setup(15, GPIO.IN, pull_up_down=GPIO.PUD_UP) +GPIO.setup(18, GPIO.IN, pull_up_down=GPIO.PUD_UP) + +photo_sensor_still_active = False + +try: + logging.info('Start moc server') + subprocess.call(["padsp", "mocp", "--server"]) + subprocess.call(["mocp", "--clear"]) + subprocess.call(["mocp", "-l", SOUND_OK]) + + while True: + + # TODO what's a good value here? + time.sleep(0.01) + + if (GPIO.input(14) == False): + logging.debug('mocp --previous') + subprocess.call(["mocp", "--previous"]) + time.sleep(BUTTON_PAUSE) + # TODO wait for ~0.25 s, if button is still pressed, seek instead of skipping + + if (GPIO.input(15) == False): + logging.debug('mocp --toggle-pause') + subprocess.call(["mocp", "--toggle-pause"]) + time.sleep(BUTTON_PAUSE) + + if (GPIO.input(18) == False): + logging.debug('mocp --next') + subprocess.call(["mocp", "--next"]) + time.sleep(BUTTON_PAUSE) + # TODO wait for ~0.25 s, if button is still pressed, seek instead of skipping + + # check photo sensor + if ((not photo_sensor_still_active) and (GPIO.input(4) == GPIO.HIGH)): + logging.debug('Photo sensor active, activating light and camera') + subprocess.call(["mocp", "-l", SOUND_SCANNING]) + + # turn LED on + GPIO.output(17, GPIO.HIGH) + + # scan QR code + zbarcam = subprocess.Popen(['zbarcam', '--nodisplay', '--raw', '-Sdisable', '-Sqrcode.enable', '--prescale=320x240', '/dev/video0'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) + + poll_obj = select.poll() + poll_obj.register(zbarcam.stdout, select.POLLIN) + + # wait for scan result (or timeout) + start_time = time.time() + poll_result = False + while ((time.time() - start_time) < QR_SCANNER_TIMEOUT and (not poll_result)): + poll_result = poll_obj.poll(100) + + if (poll_result): + + try: + + qr_code = zbarcam.stdout.readline().rstrip() + qr_code = qr_code.decode("utf-8") # python3 + logging.debug("QR Code: {}".format(qr_code)) + + if (not qr_code.startswith("http://")): + # create full path + full_path = MUSIC_BASE_DIRECTORY + qr_code + + logging.debug("Full Path {}".format(full_path)) + if (not os.path.isfile(full_path)): + logging.debug("not a file > add as directory") + directory = full_path + logging.debug("Directory {}".format(directory)) + else: + logging.debug("it's a file") + directory = os.path.dirname(os.path.realpath(full_path)) + filename = os.path.basename(full_path) + logging.debug("Directory {}".format(directory)) + logging.debug("Filename {}".format(filename)) + + os.chdir(directory) + + #onlyfiles = [f for f in os.listdir('.') if os.path.isfile(os.path.join('.', f))] + #logging.debug(onlyfiles) + + else: + logging.debug("URL > open as stream") + stream_url = qr_code + + subprocess.call(["mocp", "--clear"]) + subprocess.call(["mocp", "--stop"]) + + logging.debug("Stopped") + + # play confirmation sound + subprocess.call(["mocp", "-l", SOUND_OK]) + + if ('stream_url' in locals()): + logging.debug("Add stream") + subprocess.check_call(["mocp", "-a", stream_url]) + del stream_url + elif ('filename' in locals()): + logging.debug("Add file {}".format(filename)) + subprocess.check_call(["mocp", "-a", filename]) + del filename + else: + logging.debug("Add directory {}".format(directory)) + subprocess.check_call(["mocp", "-a", "."]) + + # subprocess.check_call(["mocp", "-a", target, "-p"]) + logging.debug("Start playback") + subprocess.check_call(["mocp", "-p"]) + + except subprocess.CalledProcessError as e: + logging.debug("Error starting playback, mocp returned {}".format(e.returncode)) + logging.debug(e.output) + subprocess.call(["mocp", "-l", SOUND_PLAYBACK_ERROR]) + except FileNotFoundError as e: + logging.debug("Could not open directory {}".format(directory)) + subprocess.call(["mocp", "-l", SOUND_PLAYBACK_ERROR]) + else: + logging.debug('Timeout on zbarcam') + subprocess.call(["mocp", "-l", SOUND_SCAN_FAIL]) + + # consider the photo sensor to be blocked + photo_sensor_still_active = True + + zbarcam.terminate() + + # LED off + GPIO.output(17, GPIO.LOW) + + elif (GPIO.input(4) == GPIO.LOW): + # the photo sensor is not blocked (anymore) + photo_sensor_still_active = False + +# Exit when Ctrl-C is pressed +except KeyboardInterrupt: + logging.info('Close moc server') + subprocess.call(["mocp", "--exit"]) + logging.info('Reset GPIO configuration and close') +GPIO.cleanup() \ No newline at end of file diff --git a/code/test/sensor.py b/code/test/sensor.py index a3475ef..20783dc 100644 --- a/code/test/sensor.py +++ b/code/test/sensor.py @@ -13,7 +13,7 @@ try: print('Start sensor test') while True: - time.sleep(0.25) + time.sleep(0.75) if (GPIO.input(17) == GPIO.LOW): print('LOW') GPIO.output(27, GPIO.LOW) @@ -22,6 +22,6 @@ try: GPIO.output(27, GPIO.HIGH) except KeyboardInterrupt: - print('bye') + print('KeyboardInterrupt') GPIO.cleanup() diff --git a/notes.md b/notes.md index 099f7b9..70feadc 100644 --- a/notes.md +++ b/notes.md @@ -1,6 +1,7 @@ # To Do ## mopidy / spotify + ### Installation https://www.raspberrypi.org/documentation/remote-access/ssh/ --> file "ssh" on boot partition @@ -33,7 +34,6 @@ sudo apt-get install ncmpcpp --> https://www.mopidy.com/authenticate/#spotify - ### installation for user pi # create config mopidy config @@ -139,16 +139,13 @@ tmpfs /home/pi/.config tmpfs nodev,nosuid,mode=1777,uid=pi tmpfs /var/lib/mopidy/.config tmpfs nodev,nosuid,mode=1777,uid=mopidy 0 0 - - - -### mopidy Dokumentation +#### mopidy Dokumentation http://localhost:6680/api_explorer/#/library.search https://docs.mopidy.com/en/latest/api/core/#mopidy.core.mopidy.core.LibraryController https://docs.mopidy.com/en/latest/ext/file/ https://docs.mopidy.com/en/latest/service/ -### ncmpcpp +#### ncmpcpp sudo apt-get install ncmpcpp https://wiki.archlinux.org/index.php/ncmpcpp#Basic_usage @@ -179,8 +176,6 @@ curl -X POST -H Content-Type:application/json -d '{"jsonrpc": "2.0", "id": 1, "m curl -X POST -H Content-Type:application/json -d '{ "method": "core.playback.get_state", "jsonrpc": "2.0", "id": 1 }' http://192.168.1.142:6680/mopidy/rpc - - ### Spotify URLs https://open.spotify.com/track/3jQyadhLTxpxadQlkFh2b8 https://open.spotify.com/episode/1o8HWRR0mx5TfyxLlnKv8e @@ -188,6 +183,34 @@ https://open.spotify.com/show/4zQKHBLkM3puG5n3jAU2H4 https://open.spotify.com/album/0BajiiFeEZv9eEx07Hw2C0 +### piplayer as service +sudo nano /lib/systemd/system/piplayer.service + [Unit] + Description=piplayer + After=mopidy.service + Requires=mopidy.service + + [Service] + Type=simple + #ExecStart=/usr/bin/python3 /home/pi/piplayer3.py > /tmp/piplayer3.log 2>&1 + ExecStart=/bin/bash -c 'exec python3 /home/pi/piplayer3.py >> /tmp/piplayer3.log 2>&1' + User=pi + + [Install] + WantedBy=multi-user.target + +sudo systemctl daemon-reload +sudo systemctl enable piplayer.service + +-- nach reboot +systemctl +systemctl list-dependencies piplayer +journalctl -e +sudo systemctl restart piplayer.service + + + + ## Hardware - PHAT DAC installieren - http://www.instructables.com/id/Multiroom-Client-With-Raspberry-Pi-ZERO-and-PHAT-D/?ALLSTEPS