Sniff is a "Scratch-like" programming language that's designed to help Scratchers move gently from Scratch to more conventional languages. They can start writing programs, without having to learn a new language because Sniff is based on Scratch. They learn a little more about variables, compiling, syntax errors (!), and they can have fun controlling real hardware while they're doing it.

Saturday, 11 March 2017

Cheerlights (and a bit of MQTT)

One of the things we added in the last release is a simple cheerlights client. Cheerlights is a system that scans twitter looking for posts are sent to it, using the tag @cheerlights, or simply including the word cheerlights, and a colour. Whenever anyone does that, every cheer light in the world switches over to showing that colour. What's the point? None at all, but its lots of fun knowing that you can control lights all over the world with just a tweet, and that you can build something that's part of a giant network.
The Sniff cheer light client runs on your computer and all you need to do is make a cheer light device:

make server cheerlight device

make red number
make green number
make blue number

make hue number
make saturation number
make brightness number
make shade number

make name string

Rather than just telling you the name of the colour (as it was in the tweet), it can find the numeric representation in lots of different formats, making it easy to use with lots of different hardware. Here's some simple diagnostic code to check in with the server, and print out the latest values.


when start
.forever
..tell server to "update"
..say name
..say join "red:" [red]
..say join "green:" [green]
..say join "blue:" [blue]
..say ""
..say join "hue:" [hue]
..say join "saturation:" [saturation]
..say join "brightness:" [brightness]
..say join "shade:" [shade]
..say ""
..say ""
..wait 10 secs


This tells the server to update every 10 seconds. You might want to think a little about how often up call update, as each time it sends a message to the central cheer lights server. While every 10 seconds isn't exactly going to generate a lot of traffic, and is a reasonable value for testing purposes, you might want to increase that a little if you decide to run a cheerlight client full time. After all checking once every minute or two isn't really going to make much difference if its just running in the corner of a room somewhere.

Now we need to get some coloured lights going, and the easiest way is with a flotilla rainbow:

make server cheerlight device

make hue number
make shade number
make name string

when start
.forever
..tell server to "update"
..wait 30 secs

We can start with the code from above, but chop it down quite a lot, as we don't need to know all those different formats.

make flotilla device
make lights flotillaRainbow device
make rainbowColor list of numbers
make rainbowShade list of numbers

when start
.repeat 5
..add 0 to rainbowColor
..add 0 to rainbowShade
.tell lights to "update"
.
.forever
..wait 0.5 secs
..delete 1 of rainbowShade
..add shade to rainbowShade
..delete 1 of rainbowColor
..add hue to rainbowColor
..tell lights to "update"


Next we make the flotilla rainbow device, and initialise the 5 LED's to be black. Then every half second we shuffle up the colours by deleting the first colour, and then add the current cheer light colour to the end of the list. This means when the lights change we get a nice animation effect.

That's pretty neat, but what if we want to control some more interesting hardware, perhaps attached to an Arduino. Well we could have re-writtten the cheer lights client to run on Arduino, but instead we wrote a cheer lights to MQTT bridge:

when start
.forever
..tell cheerServer to "update"
..broadcast display and wait
..wait 30 secs

We need to create a cheerlights device as before, and then check the status every 30 seconds.

make mqtt device
make clientid string
make message string
make topic string

make networkConnected boolean
make networkPeer string

when start
.set clientid to "sniffSendClient"
.set networkPeer to "raspberrypi.local."
.tell mqtt to "connect"
.
.if not networkConnected
..say "connect failed"
..stop script
.say "connected"
.
.forever
..tell mqtt to "loop"
..wait 1 secs

We also set up an Mqtt device, and tell it to connect to a server on raspberrypi.local (which is running Mosquito).

when display
.set topic to "cheerlights/red"
.set message to [red]
.tell mqtt to "publish"
.
.set topic to "cheerlights/green"
.set message to [green]
.tell mqtt to "publish"
.
.set topic to "cheerlights/blue"
.set message to [blue]
.tell mqtt to "publish"
.
.
.set topic to "cheerlights/hue"
.set message to [hue]
.tell mqtt to "publish"
.
.set topic to "cheerlights/saturation"
.set message to [saturation]
.tell mqtt to "publish"
.
.set topic to "cheerlights/brightness"
.set message to [brightness]
.tell mqtt to "publish"
.
.set topic to "cheerlights/shade"
.set message to [shade]
.tell mqtt to "publish"
.
.set topic to "cheerlights/name"
.set message to name
.tell mqtt to "publish"


After checking the cheer light serverver the code calls runs display, which pushes all of the data out to different topics.

Then we can run an mitt client on Arduino:

make spi device
make ethernet device D10
make networkMAC string "b6:ee:63:ed:95:cb"
make networkIP string "192.168.0.200"
make networkConnected boolean
make networkPort number
make networkPeer string

make mqtt device
make clientid string
make message string
make topic string


make neoPixels ws2811 device A1
make neoColor list of numbers
make neoShade list of numbers

make hue number
make shade number

when start
.set clientid to networkMAC
.set networkPeer to "192.168.0.108" #No DNS on Arduino!
.tell mqtt to "connect"
.if not networkConnected
..say "connection failed"
..stop all
.
.set topic to "cheerlights/hue"
.tell mqtt to "subscribe"
.set topic to "cheerlights/shade"
.tell mqtt to "subscribe"
.
.forever
..tell mqtt to "loop"
..if not topic = ""
...if topic = "cheerlights/hue"
....set hue to value of message
...if topic = "cheerlights/shade"
....set shade to value of message
..wait 1 secs

when start
.repeat 10
..add 0 to neoColor
..add 0 to neoShade
.
.forever
..delete item 1 of neoShade
..add shade to neoShade
..delete item 1 of neoColor
..add hue to neoColor
..tell neoPixels to "show"
..wait 0.25 secs

It connects to the server, and subscribes to the cheer lights topics for hue and shade. Then the neoPixel part of the code scrolls the colours just as we did for flotilla!


No comments:

Post a Comment