├── requirements.txt ├── .gitignore ├── sfx ├── .DS_Store ├── _jambot-ed.mp3 ├── _jambot-sam.mp3 ├── _jambot-becky.mp3 └── _jambot-ruth.mp3 ├── assets └── circuit.jpg ├── config.example.py ├── jambot.service ├── jambot-sockets.service ├── jambot.py ├── jambot-sockets.py └── README.md /requirements.txt: -------------------------------------------------------------------------------- 1 | socketIO-client-nexus==0.7.6 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | env 2 | deploy.sh 3 | sfx/*.mp3 4 | !sfx/_*.mp3 5 | config.py -------------------------------------------------------------------------------- /sfx/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/orangespaceman/jambot/master/sfx/.DS_Store -------------------------------------------------------------------------------- /assets/circuit.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/orangespaceman/jambot/master/assets/circuit.jpg -------------------------------------------------------------------------------- /sfx/_jambot-ed.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/orangespaceman/jambot/master/sfx/_jambot-ed.mp3 -------------------------------------------------------------------------------- /sfx/_jambot-sam.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/orangespaceman/jambot/master/sfx/_jambot-sam.mp3 -------------------------------------------------------------------------------- /sfx/_jambot-becky.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/orangespaceman/jambot/master/sfx/_jambot-becky.mp3 -------------------------------------------------------------------------------- /sfx/_jambot-ruth.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/orangespaceman/jambot/master/sfx/_jambot-ruth.mp3 -------------------------------------------------------------------------------- /config.example.py: -------------------------------------------------------------------------------- 1 | """ 2 | A sample config file 3 | """ 4 | 5 | websocket = { 6 | "url": "localhost", 7 | "port": 443 8 | } 9 | -------------------------------------------------------------------------------- /jambot.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=jambot 3 | 4 | [Service] 5 | ExecStart=/bin/bash -c '/usr/bin/python -u jambot.py' 6 | WorkingDirectory=/home/pi/jambot 7 | Restart=always 8 | User=pi 9 | 10 | [Install] 11 | WantedBy=multi-user.target -------------------------------------------------------------------------------- /jambot-sockets.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=jambotsockets 3 | 4 | [Service] 5 | ExecStart=/bin/bash -c '/usr/bin/python -u jambot-sockets.py' 6 | WorkingDirectory=/home/pi/jambot 7 | Restart=always 8 | User=pi 9 | 10 | [Install] 11 | WantedBy=multi-user.target -------------------------------------------------------------------------------- /jambot.py: -------------------------------------------------------------------------------- 1 | import os 2 | import random 3 | import time 4 | import RPi.GPIO as GPIO 5 | import pygame 6 | 7 | # button 8 | buttonSwitchPin = 23 9 | buttonState = 0 10 | lastButtonState = 0 11 | 12 | # play 13 | is_playing = False 14 | pygame.init() 15 | pygame.mixer.init() 16 | sfx_path = "/home/pi/jambot/sfx" 17 | 18 | # GPIO 19 | GPIO.setmode(GPIO.BCM) 20 | GPIO.setup(buttonSwitchPin, GPIO.IN) 21 | 22 | while True: 23 | # get state 24 | is_playing = pygame.mixer.music.get_busy() 25 | buttonState = GPIO.input(buttonSwitchPin) 26 | 27 | # play 28 | if buttonState is 1 and lastButtonState is not 1 and is_playing is not True: 29 | sfx = random.choice(os.listdir(sfx_path)) 30 | pygame.mixer.music.load("%s/%s" % (sfx_path, sfx)) 31 | pygame.mixer.music.play() 32 | print sfx 33 | 34 | lastButtonState = buttonState 35 | time.sleep(0.5) 36 | -------------------------------------------------------------------------------- /jambot-sockets.py: -------------------------------------------------------------------------------- 1 | import logging 2 | logging.getLogger('socketIO-client-nexus').setLevel(logging.DEBUG) 3 | logging.basicConfig() 4 | 5 | import os 6 | import pygame 7 | from subprocess import call 8 | from socketIO_client_nexus import SocketIO, LoggingNamespace 9 | 10 | import config 11 | 12 | # play 13 | pygame.init() 14 | pygame.mixer.init() 15 | sfx_path = "/home/pi/jambot/sfx" 16 | 17 | 18 | def on_connect(): 19 | print('connect') 20 | 21 | 22 | def on_disconnect(): 23 | print('disconnect') 24 | 25 | 26 | def on_reconnect(): 27 | print('reconnect') 28 | 29 | 30 | def on_say(words): 31 | print('on_say', words) 32 | call(['espeak "' + words + '"'], shell=True) 33 | 34 | 35 | def on_play(file): 36 | print('on_play', file) 37 | pygame.mixer.music.load("%s/%s" % (sfx_path, file)) 38 | pygame.mixer.music.play() 39 | 40 | 41 | socketIO = SocketIO(config.websocket["url"], 42 | config.websocket["port"], LoggingNamespace) 43 | socketIO.on('connect', on_connect) 44 | socketIO.on('disconnect', on_disconnect) 45 | socketIO.on('reconnect', on_reconnect) 46 | 47 | # Listen 48 | socketIO.on('say', on_say) 49 | socketIO.on('play', on_play) 50 | socketIO.emit('jambot') 51 | socketIO.wait() 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JamBot 2 | 3 | A Raspberry Pi-powered JamBot that plays stupid sound clips when touched in a special place. 4 | 5 | It also listens to a [server](https://github.com/orangespaceman/jambot-server) via websockets for remotely triggering sound clips. 6 | 7 | ## Construction 8 | 9 | This uses a Raspberry Pi Zero and a Speaker pHAT. 10 | 11 | * Set up the pHAT: https://learn.pimoroni.com/tutorial/sandyj/assembling-speaker-phat 12 | 13 | * Add a sensor; this uses a button switch but this could easily be replaced with a tilt switch or similar. 14 | 15 | Wires were wrapped around the header pins 5V, Ground and input 23 for the switch. 16 | 17 | ![Pi](assets/circuit.jpg) 18 | 19 | ## Code 20 | 21 | * Install the software by following these instructions: https://github.com/pimoroni/speaker-phat 22 | 23 | * Optional step - also install airdac: 24 | 25 | ``` 26 | curl -sS get.pimoroni.com/airdac | bash 27 | ``` 28 | 29 | * Install mpg321 to play mp3s: 30 | 31 | ``` 32 | sudo apt-get install mpg321 33 | ``` 34 | 35 | * Check this repo out onto the pi 36 | 37 | * Update the config file to point to the websocket [server](https://github.com/studio-awkward/jambot-server) 38 | 39 | * Set up the script to run on boot by editing the following file: 40 | 41 | ``` 42 | sudo nano /etc/rc.local 43 | ``` 44 | 45 | Add to the bottom of the file: 46 | 47 | ``` 48 | # jambot 49 | python /home/pi/jambot/jambot.py & 50 | python /home/pi/jambot/jambot-sockets.py & 51 | ``` 52 | 53 | * Or alternatively, copy and enable the two service files: 54 | 55 | ``` 56 | sudo cp jambot.service /lib/systemd/system/ 57 | sudo cp jambot-sockets.service /lib/systemd/system/ 58 | sudo systemctl enable jambot.service 59 | sudo systemctl enable jambot-sockets.service 60 | ``` 61 | 62 | ## Misc 63 | 64 | Add .mp3 files to the `sfx` directory. 65 | 66 | To adjust the volume control: 67 | 68 | ``` 69 | $ alsamixer 70 | ``` 71 | --------------------------------------------------------------------------------