├── README.md
├── examples
├── ball.js
├── clear.js
├── conway.js
├── glow.js
├── gradient.js
└── scroll.js
├── gradient.jpg
├── iob.js
└── package.json
/README.md:
--------------------------------------------------------------------------------
1 | # internet-of-buckets
2 |
3 | > http wrapper for controlling *The Internet of Buckets* art installation
4 |
5 | *The Internet of Buckets* is a 10x5 stack of buckets with RGB LEDs inside. Each
6 | is controlled independently by a microcontroller with its own IP address, which
7 | responds to HTTP requests. This module wraps the process of addressing and
8 | routing to each bucket.
9 |
10 | There are a small variety of demos under `examples/`.
11 |
12 | ## Usage
13 |
14 | Let's draw a gradient:
15 |
16 | ```js
17 | var draw = require('internet-of-buckets')
18 |
19 | for (var i=0; i < 10; i++) {
20 | for (var j=0; j < 5; j++) {
21 | var red = 255 * i / 10
22 | var green = 0
23 | var blue = 255 - 255 * j / 5
24 | draw(i, j, [red, green, blue])
25 | }
26 | }
27 | ```
28 |
29 | This will output
30 |
31 |
32 |
33 | ## API
34 |
35 | ```js
36 | var draw = require('internet-of-buckets')
37 | ```
38 |
39 | ### draw(x, y, rgb, cb=function noop(){})
40 |
41 | Sets a single bucket at `(x, y)` to the colour `rgb`.
42 |
43 | The top left corner is `(0, 0)`, and the bottom right corner is `(9, 4)`.
44 |
45 | `rgb` is an array of size 3, with values between `0-255`. It represents the red,
46 | green, and blue components respectively.
47 |
48 | If provided, `cb` is a function that will be called once the write is complete.
49 | This can be be useful for e.g. synchronizing several buckets' updates.
50 |
51 |
52 | ## Install
53 |
54 | With [npm](https://npmjs.org/) installed, run
55 |
56 | ```
57 | $ npm install internet-of-buckets
58 | ```
59 |
60 | ## License
61 |
62 | ISC
63 |
64 |
--------------------------------------------------------------------------------
/examples/ball.js:
--------------------------------------------------------------------------------
1 | var set = require('../iob')
2 |
3 | function makeWorld () {
4 | return new Array(5).fill(0).map(function () {
5 | return new Array(10).fill(0)
6 | })
7 | }
8 |
9 | var world = makeWorld()
10 |
11 | function applyLight (world, x, y, radius, rgb) {
12 | var next = makeWorld()
13 | for (var i=0; i < 10; i++) {
14 | for (var j=0; j < 5; j++) {
15 | var dx = x - i
16 | var dy = y - j
17 | var dist = Math.sqrt(dx*dx + dy*dy) + 0.001
18 | var power = radius / (dist*dist)
19 | power = Math.max(0, Math.min(1, power))
20 | // console.log(i, j, power)
21 | next[j][i] = [100 * power, 0, 0]
22 | }
23 | }
24 | return next
25 | }
26 |
27 | function render (world) {
28 | for (var i=0; i < 10; i++) {
29 | for (var j=0; j < 5; j++) {
30 | set(i, j, world[j][i])
31 | }
32 | }
33 | }
34 |
35 | function renderSync (world, cb) {
36 | var n = 50
37 | for (var i=0; i < 10; i++) {
38 | for (var j=0; j < 5; j++) {
39 | set(i, j, world[j][i], function () {
40 | n--
41 | if (n <= 0 && cb) return cb()
42 | })
43 | }
44 | }
45 | }
46 |
47 | var x = 5
48 | var y = 2.5
49 | var ang = Math.random() * 2 * 3.14159
50 | ang = 3.14159 / 4
51 | var xv = Math.cos(ang) * 0.25
52 | var yv = Math.sin(ang) * 0.25
53 |
54 | function step (world) {
55 | x += xv
56 | y += yv
57 | if (x >= 8) xv *= -1
58 | if (x <= 0) xv *= -1
59 | if (y >= 4) yv *= -1
60 | if (y <= 0) yv *= -1
61 | return applyLight(world, x, y, 0.1, [16, 0, 0])
62 | }
63 |
64 | function frame () {
65 | world = step(world)
66 | renderSync(world, frame)
67 | }
68 |
69 | frame()
70 |
71 | // var world =
72 |
--------------------------------------------------------------------------------
/examples/clear.js:
--------------------------------------------------------------------------------
1 | var set = require('../iob')
2 |
3 | for (var i=0; i < 10; i++) {
4 | for (var j=0; j < 5; j++) {
5 | set(i, j, [0, 0, 0])
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/examples/conway.js:
--------------------------------------------------------------------------------
1 | var set = require('../iob')
2 |
3 |
4 | // set(0, 0, [255, 0, 255])
5 |
6 | function makeWorld () {
7 | return new Array(5).fill(0).map(function () {
8 | return new Array(10).fill(0)
9 | })
10 | }
11 |
12 | function rand () {
13 | return Math.floor(Math.random() * 255)
14 | }
15 |
16 | var c1 = [rand(), rand(), rand()]
17 | var c2 = [rand(), rand(), rand()]
18 |
19 |
20 | var world = makeWorld()
21 |
22 | for (var i=0; i < 10; i++) {
23 | for (var j=0; j < 5; j++) {
24 | world[j][i] = Math.random() > 0.8
25 | }
26 | }
27 |
28 | function render (world) {
29 | for (var i=0; i < 10; i++) {
30 | for (var j=0; j < 5; j++) {
31 | set(i, j, world[j][i] ? c1 : c2)
32 | }
33 | }
34 | }
35 |
36 | function neighbours (world, x, y) {
37 | var n = 0
38 | for (var i=-1; i <= 1; i++) {
39 | for (var j=-1; j <= 1; j++) {
40 | if (i !== 0 && j !== 0) continue
41 | var xx = x + i
42 | var yy = y + j
43 | xx = Math.abs(xx) % 10
44 | yy = Math.abs(yy) % 5
45 | n += world[yy][xx] ? 1 : 0
46 | }
47 | }
48 | return n
49 | }
50 |
51 | function step (world) {
52 | var next = makeWorld()
53 | for (var i=0; i < 10; i++) {
54 | for (var j=0; j < 5; j++) {
55 | var n = neighbours(world, i, j)
56 | next[j][i] = (n === 2 || n === 3)
57 | }
58 | }
59 | return next
60 | }
61 |
62 | setInterval(function () {
63 | render(world)
64 | world = step(world)
65 | }, 500)
66 |
67 | // var world =
68 |
--------------------------------------------------------------------------------
/examples/glow.js:
--------------------------------------------------------------------------------
1 | var set = require('../iob')
2 |
3 | // set(0, 0, [255, 0, 255])
4 |
5 | function makeWorld () {
6 | return new Array(5).fill(0).map(function () {
7 | return new Array(10).fill(0)
8 | })
9 | }
10 |
11 | function rand () {
12 | return Math.floor(Math.random() * 255)
13 | }
14 |
15 | var c1 = [rand(), rand(), rand()]
16 | var c2 = [rand(), rand(), rand()]
17 |
18 | var world = makeWorld()
19 |
20 | function applyLight (world, x, y, radius, rgb) {
21 | var next = makeWorld()
22 | for (var i=0; i < 10; i++) {
23 | for (var j=0; j < 5; j++) {
24 | var dx = x - i
25 | var dy = y - j
26 | var dist = Math.sqrt(dx*dx + dy*dy) + 0.001
27 | var power = radius / (dist*dist)
28 | power = Math.max(0, Math.min(1, power))
29 | // console.log(i, j, power)
30 | next[j][i] = [100 * power, 0, 0]
31 | }
32 | }
33 | return next
34 | }
35 |
36 | function render (world) {
37 | for (var i=0; i < 10; i++) {
38 | for (var j=0; j < 5; j++) {
39 | set(i, j, world[j][i])
40 | }
41 | }
42 | }
43 |
44 | function renderSync (world, cb) {
45 | var n = 50
46 | for (var i=0; i < 10; i++) {
47 | for (var j=0; j < 5; j++) {
48 | set(i, j, world[j][i], function () {
49 | n--
50 | if (n <= 0 && cb) return cb()
51 | })
52 | }
53 | }
54 | }
55 |
56 | function step (world) {
57 | var t = new Date().getTime()
58 | var x = 5 + Math.sin(t/1000) * 2
59 | var y = 2 + Math.cos(t/285) * 1.5
60 | x = 5
61 | y = 2
62 | var r = 1 + Math.sin(t/500)
63 | return applyLight(world, x, y, r, [255, 0, 0])
64 | }
65 |
66 | function frame () {
67 | world = step(world)
68 | renderSync(world, frame)
69 | }
70 |
71 | frame()
72 |
73 | // var world =
74 |
--------------------------------------------------------------------------------
/examples/gradient.js:
--------------------------------------------------------------------------------
1 | var set = require('../iob')
2 |
3 | for (var i=0; i < 10; i++) {
4 | for (var j=0; j < 5; j++) {
5 | set(i, j, [255 * (i/50),0,255 * (j/25)])
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/examples/scroll.js:
--------------------------------------------------------------------------------
1 | var set = require('../iob')
2 |
3 | function makeWorld (old) {
4 | var w = new Array(5).fill(0).map(function () {
5 | return new Array(10).fill([0, 0, 0])
6 | })
7 | for (var i=0; i < 10; i++) {
8 | for (var j=0; j < 5; j++) {
9 | w[j][i] = old ? old[j][i] : [0, 0, 0]
10 | }
11 | }
12 | return w
13 | }
14 |
15 |
16 | var world = makeWorld()
17 |
18 | var letters = {
19 | ' ': [
20 | 0, 0, 0,
21 | 0, 0, 0,
22 | 0, 0, 0,
23 | 0, 0, 0,
24 | 0, 0, 0
25 | ],
26 | 'A': [
27 | 1, 1, 1,
28 | 1, 0, 1,
29 | 1, 1, 1,
30 | 1, 0, 1,
31 | 1, 0, 1
32 | ],
33 | 'I': [
34 | 1, 1, 1,
35 | 0, 1, 0,
36 | 0, 1, 0,
37 | 0, 1, 0,
38 | 1, 1, 1
39 | ],
40 | 'B': [
41 | 1, 1, 0,
42 | 1, 0, 1,
43 | 1, 1, 1,
44 | 1, 0, 1,
45 | 1, 1, 0
46 | ],
47 | 'C': [
48 | 1, 1, 1,
49 | 1, 0, 0,
50 | 1, 0, 0,
51 | 1, 0, 0,
52 | 1, 1, 1
53 | ],
54 | 'K': [
55 | 1, 0, 1,
56 | 1, 1, 0,
57 | 1, 0, 0,
58 | 1, 1, 0,
59 | 1, 0, 1
60 | ],
61 | 'T': [
62 | 1, 1, 1,
63 | 0, 1, 0,
64 | 0, 1, 0,
65 | 0, 1, 0,
66 | 0, 1, 0
67 | ],
68 | 'H': [
69 | 1, 0, 1,
70 | 1, 0, 1,
71 | 1, 1, 1,
72 | 1, 0, 1,
73 | 1, 0, 1
74 | ],
75 | 'E': [
76 | 1, 1, 1,
77 | 1, 0, 0,
78 | 1, 1, 0,
79 | 1, 0, 0,
80 | 1, 1, 1
81 | ],
82 | 'P': [
83 | 1, 1, 1,
84 | 1, 0, 1,
85 | 1, 1, 0,
86 | 1, 0, 0,
87 | 1, 0, 0
88 | ],
89 | 'L': [
90 | 1, 0, 0,
91 | 1, 0, 0,
92 | 1, 0, 0,
93 | 1, 0, 0,
94 | 1, 1, 1
95 | ],
96 | 'N': [
97 | 1, 0, 1,
98 | 1, 1, 1,
99 | 1, 1, 1,
100 | 1, 0, 1,
101 | 1, 0, 1
102 | ],
103 | 'N': [
104 | 1, 0, 1,
105 | 1, 1, 1,
106 | 1, 1, 1,
107 | 1, 0, 1,
108 | 1, 0, 1
109 | ],
110 | }
111 |
112 | function letter (world, letter, x, rgb) {
113 | var next = makeWorld(world)
114 | var data = letters[letter]
115 | for (var i=x; i < x+3; i++) {
116 | for (var j=0; j < 5; j++) {
117 | var xx = (i-x) % 10
118 | var col = data[xx + j*3]
119 | next[j][i] = col ? rgb : [0, 0, 0]
120 | // console.log(i, j, col, next[j][i])
121 | }
122 | }
123 | return next
124 | }
125 |
126 | function render (world) {
127 | for (var i=0; i < 10; i++) {
128 | for (var j=0; j < 5; j++) {
129 | set(i, j, world[j][i])
130 | }
131 | }
132 | }
133 |
134 | function renderSync (world, cb) {
135 | var n = 50
136 | for (var i=0; i < 10; i++) {
137 | for (var j=0; j < 5; j++) {
138 | set(i, j, world[j][i], function () {
139 | n--
140 | if (n <= 0 && cb) return cb()
141 | })
142 | }
143 | }
144 | }
145 |
146 | function string (world, txt, offset, rgb) {
147 | return txt.split('').reduce(function (w, l) {
148 | var res = letter(w, l, offset, rgb)
149 | offset += 4
150 | return res
151 | }, world)
152 | }
153 |
154 | var x = 8
155 | function step (world) {
156 | x -= 0.5
157 | var offset = Math.floor(x)
158 | var intensity = ((Math.sin(new Date().getTime() / 500) + 1) / 2) * 8 + 32
159 | return string(makeWorld(), 'HACK THE PLANET', offset, [intensity, 0, 0])
160 | // world = letter(world, 'H', x, [8, 0, 0])
161 | // world = letter(world, 'I', x+4, [8, 0, 0])
162 | return world
163 | }
164 |
165 | function frame () {
166 | world = makeWorld()
167 | world = step(world)
168 | renderSync(world, frame)
169 | }
170 |
171 | frame()
172 |
173 | // var world =
174 |
--------------------------------------------------------------------------------
/gradient.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackergrrl/internet-of-buckets/da68fee06bb15e996275a15849b235f65b73c432/gradient.jpg
--------------------------------------------------------------------------------
/iob.js:
--------------------------------------------------------------------------------
1 | var request = require('request')
2 |
3 | function address (x, y) {
4 | var idx = 201 + (y * 10) + x
5 | return 'http://192.168.16.' + idx
6 | }
7 |
8 | function color (rgb) {
9 | return '?r='+rgb[0]+'&g='+rgb[1]+'&b='+rgb[2]
10 | }
11 |
12 | function set (x, y, rgb, cb) {
13 | request(address(x, y) + color(rgb), function () { if (cb) cb() })
14 | }
15 |
16 | module.exports = set
17 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "internet-of-buckets",
3 | "version": "1.0.2",
4 | "description": "http wrapper for controlling /The Internet of Buckets/ art installation",
5 | "main": "iob.js",
6 | "directories": {
7 | "example": "examples"
8 | },
9 | "scripts": {
10 | "test": "echo \"Error: no test specified\" && exit 1"
11 | },
12 | "keywords": [
13 | "internet",
14 | "of",
15 | "buckets",
16 | "iob"
17 | ],
18 | "author": "Stephen Whitmore ",
19 | "license": "ISC",
20 | "dependencies": {
21 | "request": "^2.74.0"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------