From CHS Sigma
Jump to: navigation, search

Vaughn Woerpel, (Born November 5th, 2001) is a professional student at Charlottesville High School.

Alt text
Vaughn Woerpel in May 2018

Class Projects

My Engineering Notebook

Vaughn's Engineering Notebook

My Engineering IV Notebook

Vaughn's Engineering IV Notebook

Computer Science

Independent Study Computer Science

PID Box Project

Vaughn and Eli's Amazing PID Box

Robot Arm Project

Vaughn and Eli's EVEN MORE AMAZING Robot Arm

Bipedal Robot

Vaughn and Charlie's Bipedal Robot

Large Minute Collider

Vaughn and Charlie's Clock

CNC you later!

CNC Machining Guide

Pi in the Sky!

Vaughn's Pi in the Sky

Random Projects

Raspberry Pi Chat Room

I started to work on a chatroom to use at school or whenever I want to communicate with people. I plan to just make something relatively basic, but I'm using it as a programming exercise to become more familiar with things like networking, encryption, and Python.

Make a working chatroom using Python, and hosting it on my Raspberry Pi. I want to encrypt the messages that are being sent, and possibly host it as a web server for other people to just type the IP into their browser to connect, using Chromebooks.
So far, it is working on a server hosted by DigitalOcean, but I am largely using code that I have found online with minimal changes. I set up SSH to work on my Pi from anywhere, however, the school finds it fun to block people from using port 22, which is essential for this. I wanted to get my server code working on the Pi, but I forgot to open the right port at home, which kind of sucks. I'm going to try to make a web server from the Pi today possibly so that I can get it set up working online rather than through an application.

The code included below is just some code from the internet that I used to test some things out, not my own.

Server Code

#!/usr/bin/env python3
"""Server for multithreaded (asynchronous) chat application."""
from socket import AF_INET, socket, SOCK_STREAM
from threading import Thread
def accept_incoming_connections():
    """Sets up handling for incoming clients."""
    while True:
        client, client_address = SERVER.accept()
        print("%s:%s has joined." % client_address)
        client.send(bytes("Welcome. Type your name.", "utf8"))
        addresses[client] = client_address
        Thread(target=handle_client, args=(client,)).start()
def handle_client(client):  # Takes client socket as argument.
    """Handles a single client connection."""
    name = client.recv(BUFSIZ).decode("utf8")
    welcome = 'Welcome %s! To leave, type {quit} to exit.' % name
    client.send(bytes(welcome, "utf8"))
    msg = "%s has joined." % name
    broadcast(bytes(msg, "utf8"))
    clients[client] = name
    while True:
        msg = client.recv(BUFSIZ)
        if msg != bytes("{quit}", "utf8"):
            broadcast(msg, name+": ")
            client.send(bytes("{quit}", "utf8"))
            del clients[client]
            broadcast(bytes("%s has left." % name, "utf8"))
def broadcast(msg, prefix=""):  # prefix is for name identification.
    """Broadcasts a message to all the clients."""
    for sock in clients:
        sock.send(bytes(prefix, "utf8")+msg)
clients = {}
addresses = {}
HOST = ''
PORT = 33000
BUFSIZ = 1024
if __name__ == "__main__":
    print("Waiting for connection...")
    ACCEPT_THREAD = Thread(target=accept_incoming_connections)

Client Code

#!/usr/bin/env python3
"""Script for Tkinter GUI chat client."""
from socket import AF_INET, socket, SOCK_STREAM
from threading import Thread
import tkinter
def receive():
    """Handles receiving of messages."""
    while True:
            msg = client_socket.recv(BUFSIZ).decode("utf8")
            msg_list.insert(tkinter.END, msg)
        except OSError:  # Possibly client has left the chat.
def send(event=None):  # event is passed by binders.
    """Handles sending of messages."""
    msg = my_msg.get()
    my_msg.set("")  # Clears input field.
    client_socket.send(bytes(msg, "utf8"))
    if msg == "{quit}":
def on_closing(event=None):
    """This function is to be called when the window is closed."""
top = tkinter.Tk()
messages_frame = tkinter.Frame(top)
my_msg = tkinter.StringVar()  # For the messages to be sent.
my_msg.set("Type your messages here.")
scrollbar = tkinter.Scrollbar(messages_frame)  # To navigate through past messages.
# Following will contain the messages.
msg_list = tkinter.Listbox(messages_frame, height=15, width=50, yscrollcommand=scrollbar.set)
scrollbar.pack(side=tkinter.RIGHT, fill=tkinter.Y)
msg_list.pack(side=tkinter.LEFT, fill=tkinter.BOTH)
entry_field = tkinter.Entry(top, textvariable=my_msg)
entry_field.bind("<Return>", send)
send_button = tkinter.Button(top, text="Send", command=send)
top.protocol("WM_DELETE_WINDOW", on_closing)
#----Now comes the sockets part----
#PORT = input('Enter port: ')
#if not PORT:
#    PORT = 33000
#    PORT = int(PORT)
BUFSIZ = 1024
ADDR = ('xxx.xx.x.xx', 33000)
client_socket = socket(AF_INET, SOCK_STREAM)
receive_thread = Thread(target=receive)
tkinter.mainloop()  # Starts GUI execution.


I was able to use apache on the Raspberry Pi to host a super basic website, currently with just an image and text. However, it is possible to see the site from outside the local network, so I see that as an achievement! My next goal is to just add a login screen or something. The tough part is having to use a few different languages to program a website...


I have slowly realized that I probably won't be using Python at ANY point in making this chat room... Most likely I will use something like Node JS, PHP and SQL for the server side stuff, while using HTML, CSS, and Javascript for all of the client side stuff. This poses a problem. I don't know any of these. This will be great, because it will give me an opportunity to learn some new stuff! Today, I was able to make a login page, that displays the password that you put in on the next page. Not very good security, but whatever. The splash page is just some normal HTML while the one that displays the password is in PHP. I think I may change the index page to PHP so that I can do stuff seamlessly from there instead of having it jumping from page to page. The funniest thing about doing this is probably the fact that I now realize I really need more than one monitor. Not enough screen real estate! My plan moving forward from here is to look into hosting a NodeJS server, and also getting a domain so I don't have to keep typing in my IP.
Much progress has been made! I found some awesome guides on setting up the back end of my website using PHP and MySQL. So far, I was able to register a temporary domain so that I can work a lot easier, and I've also set up a login and signup page. The only problem is that the pages routing you to the right place. I think I need to use the header() function, but that isn't quite working. My workflow is super annoying due to switching between computers and my Raspberry Pi server. I think I'd like to set up git so that I can work seamlessly between all of them. My next step is to properly setup the login screen so that people can log in and maybe go to some silly page. After this, the chat window is the next thing I'll work on.


Machine Learning

This summer, I thought it would be fun to go to a camp. Because I've just about lost most interest in very outdoorsy camps, I decided to go to a coding camp. I took a class on Neural Networks, with just about zero prior knowledge. It largely focused on Python with TensorFlow to do image recognition. We had to learn about a lot of the basic stuff, then we got to work on our own project.

Coattails the Computer Composer I thought it would be a lot of fun to try to get a computer to write some music. This proved to be far more of a pain than I thought. Rather than using TensorFlow, I had to use a more fitting neural network called a Long Short-Term Memory Recurrent Neural Network, or LSTM for short. In particular, Andrej Karpathy's LSTM. It's written in Lua, and the source code is freely available on Github. This worked super well, and allowed me to abstract most of the code and math behind the network. The only problem, was that I had to create my own dataset to train my network on. This is where the fun begins.

The dataset
To make the dataset sounds pretty simple. Just consists of downloading a bunch of midi files, and converting them to text files. Great, this will take maybe a half an hour, and I'll be done. I could never have been more wrong. It ended up taking me many many hours, and much more complicated processes than expected. First, I took the midi files, and using Midicsv (An open sourced program to convert midi to csv text files) I turned them into text files. In this form, each line of the text midi file consists of six things: [Track number, millisecond/tick since track start, Note operation (such as Note_on_c, or Note_off_c), the pitch number from 1 to 88, always the number 0, and then the note velocity which goes from 1 to 127]. This takes up a lot of space, and would take forever for the computer to process. I had to make it more efficient. Using a Python script, I translated the data into four easier to understand arguments: [Millisecond space between the operation and the last operation, whether the note is on or off, the pitch as an Ascii character, and then the velocity]. This made it a lot easier for the computer to understand. This was pretty difficult to write, as I'm not exactly an expert in Python, but I managed to do it. After running it through that script, I had my dataset.
The many problems
Too many. I had way too many problems. First of all, the initial training data using Bach was horrible. Bach music is all over the place, so it didn't make for a very good thing to train the computer on. Second off, I was too lazy to read up on the format of midi files, so I accidentaly stacked two tracks on top of eachother, making it so it sounded super nonsensical. This basically means two hands were playing on top of eachother. Next, when I was translating the music back I was reading the wrong element of a split array, making it so that only two notes were being played in the whole piece. The sound produced from those samples were truly things of nightmare. Next, I forgot to change the vocabulary for the training so it ended up learning just about the same thing. The final problem that I haven't solved is efficiency. It takes way too long to translate the files between midi and computer readable text. I could fix this, but I just did not have the time to fix it in the two weeks that I had. When I get home I will probably spend more time working on it so that I can actually send it a lot more training data.