Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Arduino Jukebox Project
#1
I am in way over my head. I thought this project was going to be easy but there's too many variables that I just don't understand.

Story: I work at an adult medical day care facility and I secured a 1963 Seeburg LPC1 jukebox. Turns out, it's crap. A professional jukebox repair man told me to throw it away, but I decided to buy an Arduino and power it from an old laptop. I used code borrowed from https://github.com/sprinkmeier/jukebox . I modified the arduino code and got it reading the push buttons correctly. I installed Ubuntu on the old laptop and started following the README.md file. I had problems with apache running the cgi file so I followed some tutorial to tell apache what to do with .cgi files. Now, when I go to the index.html it jumps to the cgi file and gives me an internal service error.

Anyway, the readme says to modify rc.local to have the script autoload on start. I don't have enough experience in linux to know if it's working correctly or not, but I have tried python jukebox.py in terminal. that results in the follow responses:

Traceback (most recent call last):
File "jukebox.py", line 46, in <module>
ser.setBaudrate(9600)
AttributeError: 'Serial' object has no attribute 'setBaudrate'
{'dup': False, 'lim': 0, 'rpt': False, 'rnd': False}

Can anyone help me make sense of this? Should I delete this thread and post it to the arduino forums?
Reply
#2
Show code, at least how serial was imported and initialized.
with what you've posted, try: ser.setBaudrate = 9600
Reply
#3
This is the jukebox.py script which is supposed to auto run.

#!/usr/bin/env python

import glob
import json
import os
import random
import select
import serial
import socket
import subprocess
import sys
import time
import traceback

SERIAL  = (glob.glob('/dev/ttyUSB*') + glob.glob('/dev/ttyACM*') + [''])[0]
PORT    = 55555

LETTERS = "ABCDEFGHJKLMNPQRSTUV"
NUMBERS = range(1,9)

CONFIG = '/var/jukebox/config.json'

DevNull = open('/dev/null','rw')

config = {}

def readConfig():
    global config
    config = {
        'dup': False,
        'rpt': False,
        'rnd': False,
        'lim': 0,
        }
    try:
        conf = json.loads(open(CONFIG).read())
        for k,v in config.items():
            config[k] = type(v)(conf[k])
    except:
        pass

readConfig()

try:
    ser = serial.Serial(SERIAL)
    ser.setBaudrate(9600)
except:
    ser = None
    traceback.print_exc()

Q = []

p = None
filename = None

def play(filename):
    p = subprocess.Popen(('play', filename),
                         stdout = DevNull,
                         stdin  = DevNull,
                         stderr = DevNull)

    return p

def playGlob(filenameGlob):
    filenames = glob.glob(filenameGlob)
    if (len(filenames) == 1):
        filename = filenames[0]
        return (filename, play(filename))
    return None

class AtomicFile(object):
    def __init__(self, filename, mode = 'w'):
        self.filename = filename
        self.new = filename + ".new"
        self.w = open(self.new, mode)

    def __enter__(self, *extra):
        #print(extra)
        return self.w

    def __exit__(self, *extra):
        #print(extra)
        self.w.close()
        os.rename(self.new, self.filename)

def process(data, address):
    global p
    global Q


    if not data: return

    print(data, address)

    if (data == 'Stop'):
        if p:
            p.kill()
        return

    if (data == 'Flush'):
        Q = []
        return

    if (data == 'Shutdown'):
        os.system("sudo /sbin/poweroff")
        return

    if (data == 'Play'):
        return
    try:
        data = data.split()
        if (len(data) != 2): return
        (letter, number) = data
        assert(letter in LETTERS)
        number = int(number)
        assert(number in NUMBERS)
        Q.append((letter, number, time.time(), address))
    except:
        traceback.print_exc()

def dump(data):
    with AtomicFile('/dev/shm/jukebox.json') as w:
        w.write(json.dumps(data, indent=4, sort_keys=1))


# Create a UDP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# Bind the socket to the port
sock.bind(('0.0.0.0', PORT))

if ser:
    rs = (sock, ser)
else:
    rs = (sock,)

while True:
    readConfig()
    print(config)
    if config['lim']:
        Q = Q[:config['lim']]

    if config['rnd']:
        random.shuffle(Q)

    (r,w,x) = select.select(rs,(),(),1)

    try:
        if sock in r:
            (data, address) = sock.recvfrom(4096)
            process(data, address)
        elif ser in r:
            try:
                data = ser.readline().strip()
            except:
                rs = (sock,)
            process(data, SERIAL)
    except:
        pass

    if p:
        if p.poll() is not None:
            print(p.wait())
            p = None
            filename = None
        else:
            print(filename)
    if Q:
        if p:
            print(Q)
        else:
            (letter, number, epoch, address) = Q.pop(0)
            if config['rpt']:
                Q.append((letter, number, epoch, address))
            if not config['dup']:
                while Q:
                    (l, n, e, a) = Q[0]
                    if (l == letter) and (n == number):
                        Q.pop(0)
                    else:
                        break
            p = playGlob("/var/jukebox/%s/%d/*" % (letter, number))
            if p:
                (filename, p) = p
    elif p:
        print(filename)
    else:
        print('.')

    dump({'current': filename,
          'length' : len(Q),
          'queue'  : Q,
})

Wow, editing that one line got the cgi working! Thank you!
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020