[vc_row][vc_column width=”1/1″]
WorkToy is a desktop toy and internet of things object made with a Spark Core. WorkToy sits on a platform that acts as a button- recording whether or not the toy is on the platform.
Many of the libraries and even the example code didn’t work “out of the box” like they were promoted, so I decided to stick with pretty simple code on the Spark Core:
int button =0; char publishString[40]; void setup() { Serial.begin(9600); Spark.variable("button", &button, INT); pinMode(D2, INPUT); } void loop() { button = digitalRead(D2); sprintf(publishString,"%u:%u:%u"); Spark.publish("button",publishString); }
Rather than use an actual button, I created by own “button”. When the toy was placed on the platform, the circuit connected, and the button result is 1; when the toy is off the platform, the circuit is not connected, and the button result is 0.
A Google Spreadsheet checks the status of the button on the platform once a minute and records the results, along with the date and time of the recording.
I found this helpful bit of code on a forum — I pasted this into the Google spreadsheet script editor and set the trigger to run the script and retrieve data once a minute:
function collectData() { var sheet = SpreadsheetApp.getActiveSheet(); var response = UrlFetchApp.fetch("https://api.spark.io/v1/devices/"INSERT SPARK CORE DEVICE ID"/button?access_token="INSERT ACCESS TOKEN"); try { var response = JSON.parse(response.getContentText()); // parse the JSON the Core API created var result = unescape(response.result); // you'll need to unescape before your parse as JSON try { var p = JSON.parse(result); // parse the JSON you created var d = new Date(); // time stamps are always good when taking readings sheet.appendRow([d, p]); // append the date, data1, data2 to the sheet } catch(e) { Logger.log("Unable to do second parse"); } } catch(e) { Logger.log("Unable to return JSON"); } }
In order for this to work, I had to publish the Google spreadsheet and make it publicly accessible in the settings.
Then, I used the public link to the Google spreadsheet (published in JSON), and called it in my p5.js sketch to manipulate the visualization:
var buttonReadings = []; var brecord = []; var playcount = 0; function setup() { createCanvas(1000, 1000); loadJSON('https://spreadsheets.google.com/feeds/list/1rLcko-chM7IQ74HcIXJrVI6sCV4fW2bfXspuUFEfbSo/od6/public/values?alt=json', drawData); } function draw() { background (255); blendMode(MULTIPLY); var yalpha = map(buttonReadings.length-playcount, 0, buttonReadings.length , 0, 255); var yellow = color(242, 255, 0, yalpha); stroke(yellow); strokeWeight(5); //for each buttonReading array object, draw a yellow line in the background for (var i = 0; i < buttonReadings.length; i++){ var x = random(-10, windowWidth+10); var y = random(-10, windowHeight+10); line(x, y, px, py); var px = x; var py = y; } textFont("Arial Black") textSize(32); fill(0); noStroke(); //print the playcount (equal to the number of minutes spent playing) text(playcount, 20, 100); text(buttonReadings.length, 20, 140); //print "work hard" textSize(200); //make the transparency (alpha) dependent on the playcount var balpha = map(buttonReadings.length-playcount, 0, buttonReadings.length , 50, 255); //make the text blue var blue = color(13, 123, 255, balpha); fill(blue); tint(balpha); //draw the text text("WORK", buttonReadings.length-playcount, windowHeight/2); text("HARD", buttonReadings.length-playcount, windowHeight/2 + 150); //print "play hard" textSize(200); //make the transparency (alpha) dependent on the playcount var palpha = map(playcount, 0, buttonReadings.length , 0, 255); //make the text pink var pink = color(255, 5, 201, palpha); fill(pink); tint(palpha); //draw the text text("PLAY", (windowWidth/2-playcount), windowHeight/2); text("HARD", (windowWidth/2-playcount), windowHeight/2 + 150); } function drawData(data){ // go through each "entry" in the JSON and assign it to an array brecord for (var i = 2; i < data.feed.entry.length; i++){ brecord[i] = (data.feed.entry[i]); } //assign each buttonstate record to a spot in the array buttonReadings for (var j = 2; j < data.feed.entry.length; j++){ buttonReadings[j] = (data.feed.entry[j].gsx$buttonstate.$t); //console.log("newreadings: "+buttonReadings[j]); } //go through buttonReadings and count the number of records in which the toy was off the platform //the variable playcount represents the number of entries in which the toy was off the platform // each buttonReading represents 1 minute in time for (var b = 3; b < buttonReadings.length; b++){ if (buttonReadings[b] == 0){ playcount ++; // console.log(playcount); } } // for (var k = 0; k < data.feed.entry.length; k++){ // console.log(data.feed.entry[k].gsx$buttonstate.$t); // } }
The visualization changes based on the number of minutes spent playing compared to the total number of minutes recorded. I riffed off of the common phrase “work hard, play hard” emphasizing the work phrase more when less play is recorded, and the play phrase more when more play is recorded. The transparency and the position of the phrases is affected by the readings from the Spark Core. The number of lines in the background correlates to the total number of recordings, and the transparency of the lines is affected by the number of minutes spent playing.
I also created a simulation for this model so that people could see the whole array of visualizations, as opposed to just seeing the current recorded values:
var buttonReadings = []; var brecord = []; var playcount = 0; var slider1; function setup() { createCanvas(1000, 1000); loadJSON('https://spreadsheets.google.com/feeds/list/1rLcko-chM7IQ74HcIXJrVI6sCV4fW2bfXspuUFEfbSo/od6/public/values?alt=json', drawData); slider1 = createSlider(0, 720); slider1.position(windowWidth/2, windowHeight-50); } function draw() { background (255); //set the playcount equal to the slider value playcount = slider1.value(); buttonReadings.length = 720; blendMode(MULTIPLY); var yalpha = map(playcount, 0, buttonReadings.length , 0, 255); var yellow = color(242, 255, 0, yalpha); stroke(yellow); strokeWeight(5); //for each buttonReading array object, draw a yellow line in the background for (var i = 0; i < buttonReadings.length/2; i++){ var x = random(-10, windowWidth+10); var y = random(-10, windowHeight+10); line(x, y, px, py); var px = x; var py = y; } textFont("Arial Black") textSize(32); fill(0); noStroke(); //print the playcount (equal to the number of minutes spent playing) text("Minutes spent playing: "+ playcount, 20, 100); text("Minutes recorded: "+ buttonReadings.length, 20, 140); //print "work hard" textSize(200); //make the transparency (alpha) dependent on the playcount var balpha = map(buttonReadings.length-playcount, 0, buttonReadings.length , 50, 255); //make the text blue var blue = color(13, 123, 255, balpha); fill(blue); tint(balpha); //draw the text text("WORK", playcount/2, windowHeight/2); text("HARD", playcount/2, windowHeight/2 + 150); //print "play hard" textSize(200); //make the transparency (alpha) dependent on the playcount var palpha = map(playcount, 0, buttonReadings.length , 50, 255); //make the text pink var pink = color(255, 5, 201, palpha); fill(pink); tint(palpha); //draw the text var xpos = map(playcount, 0, 720, width/6, width/3); text("PLAY", xpos, windowHeight/2); text("HARD", xpos, windowHeight/2 + 150); //draw text to help people understand the slider fill(0); textSize(18); text("work", (windowWidth/2)-200, windowHeight-50); text("play", (windowWidth/2)+200, windowHeight-50); //console.log(slider1.value()); } function drawData(data){ // go through each "entry" in the JSON and assign it to an array brecord for (var i = 2; i < data.feed.entry.length; i++){ brecord[i] = (data.feed.entry[i]); } //assign each buttonstate record to a spot in the array buttonReadings for (var j = 2; j < data.feed.entry.length; j++){ buttonReadings[j] = (data.feed.entry[j].gsx$buttonstate.$t); //console.log("newreadings: "+buttonReadings[j]); } }
asd[/vc_column][/vc_row]