User Tools

Site Tools


squawk

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
squawk [2024-12-04 05:12] riversquawk [2024-12-07 21:22] (current) aria
Line 27: Line 27:
 mosquitto_pub -h mqtt -t 'sound/g1/announce' -m "Good evening, my sensors indicate that the laser cutter may be on fire." mosquitto_pub -h mqtt -t 'sound/g1/announce' -m "Good evening, my sensors indicate that the laser cutter may be on fire."
 </code> </code>
- 
-**Theory:** You could direct sound two only two rooms at once by playing the left or right channel only. By default mpg123 is called with the -m option to ensure that the output is mono and thus the same sound comes out every speaker. 
  
 ===== Adding new sounds ===== ===== Adding new sounds =====
  
-Use the web file browser at http://squawk.hacklab:8080/.+<del>Use the web file browser at http://squawk.hacklab:8080/.</del> 
 + 
 +For now, use scp to squawk.hacklab.
  
 ===== Raspberry Pi OS ===== ===== Raspberry Pi OS =====
  
 Latest Raspberry Pi OS, installed using Raspberry Pi Imager. Latest Raspberry Pi OS, installed using Raspberry Pi Imager.
 +
 ==== raspi-config ==== ==== raspi-config ====
  
Line 74: Line 75:
  
 [Service] [Service]
-ExecStart=/home/pi/startup.sh & /home/pi/respawn --syslog --max-backoff=10 /home/pi/squawk.pi+WorkingDirectory=/home/pi/newsquawk 
 +ExecStart=/home/pi/newsquawk/venv/bin/python /home/pi/newsquawk/main.py 
 +User=pi 
 +Restart=always 
 +RestartSec=3
  
 [Install] [Install]
 WantedBy=multi-user.target WantedBy=multi-user.target
- 
 </code> </code>
  
Line 87: Line 91:
 $ sudo systemctl enable squawk $ sudo systemctl enable squawk
 </code> </code>
 +
 ===== Scripts ===== ===== Scripts =====
  
-Various scripts to make things happen. +The code for squawk is stored in <code>/home/pi/newsquawk</code>TODOthis should probably be mirrored somewhere.
- +
-==== /home/pi/squawk.py ==== +
- +
-<code python> +
-#!/usr/bin/env python +
- +
-import paho.mqtt.client as mqtt +
-import subprocess +
-import os +
-import logging +
-import signal +
-import time +
-import random +
- +
-logging.basicConfig(level=logging.INFO) +
- +
-max_playtime  = 15 +
-sounds_path = "/home/pi/sounds" +
- +
-status = 'closed' +
- +
-# runs a command and terminates it after a specified timeout +
-def call_with_timeout(command, timeout): +
-    logging.info('call_with_timeout(%r, %r)' % (command, timeout)) +
-    class TimeoutException(Exception): +
-        pass +
-    def alrm_handler(signum, frame): +
-        raise TimeoutException() +
-    try: +
-        old_handler = signal.signal(signal.SIGALRM, alrm_handler) +
-        signal.alarm(timeout) +
-        p = subprocess.Popen(command) +
-        retcode = p.wait() +
-        logging.info('call_with_timeout: command exited with code %s' % (retcode)) +
-    except TimeoutException: +
-        logging.info('call_with_timeout: command exceeded timeout, terminating...'+
-        p.terminate() +
-        retcode = p.wait() +
-    finally: +
-        signal.signal(signal.SIGALRM, old_handler) +
-    signal.alarm(0) +
-    return retcode +
- +
-# waffle waffle +
-def speak(data, timeout=max_playtime): +
-    command = ['/home/pi/pico.sh', data] +
-    call_with_timeout(command, timeout=timeout) +
- +
-def getfiles(path, exts=[".mp3", ".wav"]): +
-    allfiles = [] +
-    for dirpath, dirnames, filenames in os.walk(path): +
-        for filename in filenames: +
-            base, ext = os.path.splitext(filename) +
-            if ext in exts: +
-                #allfiles.append(os.path.relpath(os.path.join(dirpath, filename), path)) +
-                allfiles.append(os.path.join(dirpath, filename)) +
-    return allfiles +
- +
-# make some noise for the vengaboys +
-def play(filename, timeout=max_playtime): +
-    allfiles = getfiles(sounds_path) +
-    filename = os.path.join(sounds_path, filename) +
- +
-    if filename.endswith('/'): +
-        # pick a random file from a directory +
-        candidates = [] +
-        for f in allfiles: +
-            if f.startswith(filename): +
-                candidates.append(f) +
-        if len(candidates) == 0: +
-            logging.error('No files matching %s' % (filename)) +
-            return +
-        filename = random.choice(candidates) +
-    else: +
-        # single file requested +
-        if filename not in allfiles: +
-            logging.error('File %s not found' % (filename)) +
-            return +
-    base, ext = os.path.splitext(filename) +
-    if ext == '.mp3': +
-        command = ['mpg123', '-q', '-m', filename] +
-        call_with_timeout(command, timeout=timeout) +
-    else: +
-        command = ['play', '-q', filename] +
-        call_with_timeout(command, timeout=timeout) +
- +
-def on_connect(client, userdata, flags, rc): +
-    client.subscribe("sound/g1/play"+
-    client.subscribe("sound/g1/speak"+
-    client.subscribe("sound/g1/announce"+
-    client.subscribe("display/doorbot/intercom"+
-    client.subscribe("labstatus"+
- +
-def on_message(client, userdata, msg): +
- +
-    global status +
- +
-    if msg.topic == 'labstatus': +
-        if msg.payload == 'open': +
-           status = 'open' +
-        else: +
-           status = 'closed' +
- +
-    # ignore retained (non-realtime) messages +
-    if msg.retain: +
-        return +
- +
-    if msg.topic == 'sound/g1/play': +
-        play(msg.payload) +
- +
-    if msg.topic == 'sound/g1/speak': +
-        play('dongq.mp3'+
-        speak(msg.payload) +
- +
-    if msg.topic == 'sound/g1/announce': +
-        play('chime.mp3'+
-        speak(msg.payload) +
- +
-    if msg.topic == 'access/entrance/request': +
-        if status == 'closed': +
-            play('doorbell.mp3'+
- +
-m = mqtt.Client() +
-m.on_connect = on_connect +
-m.on_message = on_message +
-m.connect("mqtt"+
-m.loop_forever() +
-</code> +
- +
-==== /home/pi/respawn ==== +
- +
-<code python> +
-#!/usr/bin/env python +
-+
-# Tim Hawes <me@timhawes.com> +
-# April 2015 +
-+
- +
-import argparse +
-import logging +
-import logging.handlers +
-import os +
-import signal +
-import subprocess +
-import sys +
-import time +
- +
-process = None +
-hup_received = False +
-term_received = False +
- +
-parser = argparse.ArgumentParser(description='Respawn an application.'+
-parser.add_argument('--name', type=str, dest='name', action='store'+
-parser.add_argument('--delay', type=int, dest='delay', action='store', default=1) +
-parser.add_argument('--min-backoff', type=int, dest='min_backoff', action='store', default=1) +
-parser.add_argument('--max-backoff', type=int, dest='max_backoff', action='store', default=60) +
-parser.add_argument('--reset-backoff-after', type=int, dest='backoff_reset_after', action='store', default=30) +
-parser.add_argument('--syslog', dest='syslog', action='store_true', default=False) +
-parser.add_argument('--debug', dest='debug', action='store_true', default=False) +
-parser.add_argument('command', nargs='*'+
-args = parser.parse_args() +
- +
-def setup_logging(log_level=logging.INFO, syslog=True, stdout=False, ident=os.path.basename(sys.argv[0])): +
-    logger = logging.getLogger() +
-    logger.setLevel(log_level) +
-    if syslog: +
-        syslog_format_string = ident + "[%(process)d]: %(message)s" +
-        syslog_handler = logging.handlers.SysLogHandler(address="/dev/log", facility=logging.handlers.SysLogHandler.LOG_USER) +
-        syslog_handler.log_format_string = "<%d>%s" +
-        syslog_handler.setFormatter(logging.Formatter(fmt=syslog_format_string)) +
-        syslog_handler.setLevel(log_level) +
-        logger.addHandler(syslog_handler) +
-    if stdout: +
-        stream_format_string = "%(asctime)s %(message)s" +
-        stream_handler = logging.StreamHandler(stream=sys.__stdout__) +
-        stream_handler.setFormatter(logging.Formatter(fmt=stream_format_string)) +
-        stream_handler.setLevel(log_level) +
-        logger.addHandler(stream_handler) +
- +
-def run(): +
-    global process +
- +
-    start_time = time.time() +
-    process = subprocess.Popen(args.command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) +
-    while True: +
-        line = process.stdout.readline() +
-        if line == '': +
-            break +
-        logging.info("< " + line.rstrip()) +
-    returncode = process.wait() +
-    runtime = time.time()-start_time +
-    process = None +
-    if returncode == 0: +
-        logging.info('exit=%d runtime=%.3f' % (returncode, runtime)) +
-    else: +
-        logging.warning('exit=%d runtime=%.3f' % (returncode, runtime)) +
-    return returncode, runtime +
- +
-def hup_handler(signum, frame): +
-    global process +
-    global hup_received +
- +
-    if process is not None: +
-        logging.warning("received SIGHUP, sending SIGTERM to process"+
-        hup_received = True +
-        process.send_signal(signal.SIGTERM) +
-    else: +
-        logging.warning("received SIGHUP, but no process running"+
- +
-def term_handler(signum, frame): +
-    global process +
-    global term_received +
- +
-    if process is not None: +
-        logging.warning("received SIGTERM, sending SIGTERM to process"+
-        term_received = True +
-        process.send_signal(signal.SIGTERM) +
-    else: +
-        logging.warning("received SIGTERM, but no process running"+
-        term_received = True +
- +
-signal.signal(signal.SIGHUP, hup_handler) +
-signal.signal(signal.SIGTERM, term_handler) +
- +
-ident = os.path.basename(sys.argv[0]) +
-if args.name is not None: +
-    ident = ident + "/" + args.name +
- +
-if args.debug: +
-    setup_logging(log_level=logging.DEBUG, stdout=True, syslog=False, ident=ident) +
-else: +
-    setup_logging(log_level=logging.INFO, stdout=False, syslog=True, ident=ident) +
- +
-if args.delay > args.min_backoff: +
-    logging.debug('increasing min-backoff to match delay (%d)' % (args.delay)) +
-    args.min_backoff = args.delay +
-if args.min_backoff > args.max_backoff: +
-    logging.debug('increasing max-backoff to match min-backoff (%d)' % (args.min_backoff)) +
-    args.max_backoff = args.min_backoff +
- +
-exit_requested = False +
-backoff = args.min_backoff +
- +
-logging.info("command: %r" % (args.command)) +
- +
-while True: +
-    start_time = time.time() +
-    returncode, runtime = run() +
-    if term_received: +
-        logging.debug("exited after SIGTERM"+
-        break +
-    if hup_received: +
-        logging.debug("exited after SIGHUP, restarting immediately"+
-        hup_received = False +
-        continue +
-    if returncode == 0: +
-        if runtime > args.backoff_reset_after: +
-            backoff = args.min_backoff +
-            logging.debug('resetting backoff to %d' % (backoff)) +
-        else: +
-            logging.debug('delaying for %d after a successful run' % (args.delay)) +
-            time.sleep(args.delay) +
-    else: +
-        logging.info('backing-off for %d seconds' % (backoff)) +
-        time.sleep(backoff) +
-        backoff = min(backoff*2, args.max_backoff) +
-        logging.debug('next backoff will be %d seconds' % (backoff)) +
- +
-logging.info('exiting respawn'+
-</code> +
- +
-==== /home/pi/pico.sh ==== +
- +
-<code bash> +
-#!/bin/bash +
-pico2wave -l en-GB -w /tmp/pico.wav "$1" +
-play -q /tmp/pico.wav +
-rm -f /tmp/pico.wav +
-</code> +
- +
-==== /home/pi/startup.sh ==== +
- +
-<code bash> +
-#!/bin/bash +
-sleep 3 +
-_IP4=$(hostname -I | cut -d ' ' -f 1) || true +
- +
-mpg123 -m -q /home/pi/sounds/indyboot.mp3 +
-/home/pi/pico.sh "System boot complete. IP address is $_IP4" +
-</code>+
  
 ===== Audio files ===== ===== Audio files =====
Line 401: Line 116:
 -rw-r--r-- 1 pi pi   6414 Oct  4 22:32 uhoh.mp3 -rw-r--r-- 1 pi pi   6414 Oct  4 22:32 uhoh.mp3
 -rw-r--r-- 1 pi pi  27584 Oct  4 22:32 whistle.mp3 -rw-r--r-- 1 pi pi  27584 Oct  4 22:32 whistle.mp3
-</code> 
- 
-===== Pico TTS ===== 
- 
-**This is probably not required as we now use AWS TTS service.** 
- 
-<code> 
-mkdir ~/pico 
-cd ~/pico 
-wget  http://incrediblepbx.com/picotts-raspi.tar.gz 
-tar -zxf picotts-raspi.tar.gz 
-sudo cp -R usr / 
-cd /usr/src/pico_build 
-sudo dpkg -i libttspico-data_1.0+git20110131-2_all.deb 
-sudo dpkg -i libttspico0_1.0+git20110131-2_armhf.deb 
-sudo dpkg -i libttspico-utils_1.0+git20110131-2_armhf.deb 
-rm -rf ~/pico 
 </code> </code>
  
squawk.1733289136.txt.gz · Last modified: 2024-12-04 05:12 by river

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki