Somehow in the confusion of organizing ourselves for this assignment my group became responsible for building two servers. Turns out that I LOVE developing them, and complimenting the work I did last spring in DWD Online Server, I gained better understanding of how to design a RESTful API framework. Though I’d still argue that the demands of both projects would be better served using sockets, I’m glad for the opportunity to dig in and complete the builds for GET and POST requests. Here’s how our projects rounded out.

This week I finished building out the frontends for both devices (the device clients) which informed some minor server-side changes for both projects. Fortunately, problem solving for both in tandem informed possible solutions for programming logic and libraries to include.

Visual Mode offers three modes: waiting for super cool input, GIF mode, and an abstract visual mode. Abstract visual mode includes options to activate five different animations: squares, circles, triangles, arcs, and squiggles. Users many change both the background and foreground colors. In GIF mode, users send a word that triggers the server to make a GET request to the GIPHY API and returns a GIF sticker. Stickers have transparent backgrounds, which means users can still set the background color to their liking.

I ran into two problems to solve when building out the GIF mode features:

How to handle repeat requests with the same word? Part of the fun of submitting a word is that the request uses GIPHY’s random endpoint, so sending the same word again and again returns very different results. I added a counter to the server’s state object as a way to track requests to the /gifword route and poll for changes in that counter on the frontend. An increase in the counter triggered a flow of events to remove any existing GIFs and create a new one from the GIF image url stored server-side.

How to make GIPHY requests without exposing my API key? In the beginning stages of development, the frontend handled the GIPHY request. But when I investigated how to hide my API key, I realized that I would have to move the process to server to prevent exposing it during requests. I remembered how to store sensitive information in a separate file from DWD, but then I had to figure out how to structure the request from the server. I ended up using the Request library to do so.

In addition to these, I considered how the VJ output would appear to users on first start. Without their input it would be blank and very confusing. So gave the server state some initial values to prompt interaction: an initial GIF for that mode and rotating turquoise squares on a red background for the other.

Alden and Beverly created the controller client for their VJ machine (pictured above), and when we sat down to test we also ran into a few issues:

CORS! Right away we ran into these error messages. Actually, they’re not errors; it’s expected behavior for browsers when requests are made from different domains (which is how we developed the client controller and server). Here is a helpful article that explains CORS in a friendly way. Because I built out the server using Express.js, I installed their cors module and required it on my server file. Again, useful documentation on how to do this here and here. (Had we bundled everything together into one project under the same domain, we’d likely avoid this issue.)

The server’s state object expects POST values as strings. Not only did we have to make sure we were using the correct word assignment for variables (those included in the body of the request), but we also made sure that any values arriving in requests from the controller were formatted as strings. Otherwise, they would blow out that part of the server object and the screen would go blank. All requests were packaged by using the deceptively simple Axios library in the controller’s frontend.

For future improvements I’d consider:

I can’t remember why I built out the server state object using all strings (maybe I preferred the consistency?) but since the frontend converts the numerical values to integers anyway perhaps I should revisit this.

Handling multi-word submissions for GIF requests. Right now it’s only set up to take single words. My initial guess is that this would require parsing the words server-side on any spaces and reformatting appropriately for the GIPHY call.

Include error handlers in my route callbacks. During my research to build about various sections of the server, I saw many examples of how to do this.

Related to the above, include methods for handling GIF requests that return no data.

Now to the playing! We finished the Super Cool VJ Machine in time to play test with others on the floor for valuable feedback and a chance to consider the dynamics of play beyond all the technical considerations of getting it to work. We set up the output on a screen in the hallway and gave people the URL to the controller.

Again, the GIFs are random, so the element of surprise and whacky returns made this feature endlessly surprising and fun. Playing with others, there’s element of competition to see who can change the output first, and because it’s anonymous, there are the unanswered questions of who submitted and what word they submitted that to prompt the return of the ridiculous GIF.

Finally, I continued to play with it at home, co-curating the content and dialoguing with some unknown person (Alden?!). The above clip is a sped-up recording of that interaction. Off the floor, there’s the added fun in remembering that your decisions play out in a shared, semi-public space.

Of note: we discovered early on that the GIPHY API limits requests to 42 an hour. Unlimited calls require a production key.

Robo-KaraokeAt the time of this writing, we’ve yet to test our karaoke machine with Roxanne and Jason, but the server and frontend respond to curl requests to select songs for the singer, to pause/play the playback, change its speed, and also submit compliments that display for two seconds at a time.

I added actual karaoke videos from karafun’s Youtube channel of five popular hits. My instinct was to preload these in the P5 sketch, but it turn out that you can only use this for load calls (makes sense), and I couldn’t find any of those for videos. My browser also threw errors when I attempted to push them into an array in for loop. In the end, I landed on a less elegant way that works.

Server-side the list of compliments are also pushed into an array on start. Each time that route is requested, one is randomly chosen to display and is also removed from the array to prevent a repeat appearance. When the array is emptied, it’s replenished with all of them for the next cycle.

The counter worked so well for the Super Cool VJ Machine that I incorporated it into the karaoke server state for to keep track of new song selections. Every time the counter increases, it removes the current video and plays the new one.

Because the other group is also building out an online controller separately, I also added the Express CORS package to this project anticipating similar issues.

This week we flushed out server-side programming for two RESTful project devices along with skeletons of their front ends.

Both devices are similar in that their clients update according to changes in data stored in a JSON object in the back end (and for this assignment, those changes are intended to be made with physical controllers made by other groups). For this we used P5’s loadJSON method (although I suppose httpGet() would work, too) at regular intervals to retrieve the data. I learned that this is called polling. Wondering what other methods we should consider (especially since this is not a socket server)?

Ridwan and I thought it would be fun to make an audience-controlled karaoke machine, with controls for selecting a song video, playing and pausing that video, changing the playback rate, and giving compliments to the karaoke performer.

After some fits and starts, I’m starting to get the hang of how to create a web app with HTTP requests and routes. Talking it through in class, with peers on the floor, and with ITP Resident Alejandro (see his project from last year) clarified my thinking about how to approach this assignment. Coincidentally, in helping a student with their P5 data assignment this week, I found the GIPHY API documentation (see especially the section, Technical Documentation/Specifications) to be a useful example of a clearly-communicated RESTful API.

An API describes a system to access data from a web service. Often we see this data formatted in the HTML pages of the website, but often too, we can retrieve this data formatted in JSON. And REST is a framework or style for retrieving and manipulating that data.

From HTTP Request Methods: “The difference between POST and PUT is that PUT requests are idempotent. That is, calling the same PUT request multiple times will always produce the same result. In contrast, calling a POST request repeatedly have side effects of creating the same resource multiple times.”

ROBO-KARAOKE Our device gives the audience control over the song selection and playback of a karaoke video on a browser window that can be projected onto a screen. It is intended for die-hard karaoke fans in a room with people with whom they feel safe and ready for a good laugh. It is best-suited for use well into the group’s party.

We envision either a physical controller or a digital interface on mobile devices. Either option, however, impacts the game mechanics. With a physical controller, the audience shares or vies for control of it. With a digital interface, each audience member accesses the controller from their own phone and blindly competes with their fellow audience members to influence karaoke video playback.

As the audience decides the level of difficulty for the singer(s), the controller includes the option to send a random compliment to the screen to cheer them on.

Jason and Roxanne will build the controller. Ridwan and I will build the server and video player.