29 Nov 2016, 20:45

All the grisly details of Skeletony and the Halloween Doorbell of Doooooom V2.0

Intro

After the silly complexity and Hackaday article! of last year, I decided to keep it simple for Halloween this year. Of course that worked out :-)

The kids’ favourite thing from all our Halloweens was the doorbell that made scary sounds. So that became the focus. As I hadn’t really done anything with my two C.H.I.P.s, I picked one to handle the bulk of the activity. I immediately became a big fan of its small size, built-in Wifi and simple Linux UI.

Image

But of course I couldn’t leave it at that. I hauled out an old cheap scary mini skeleton we bought a few years back in Woodies and decided to add him to the mix.

It also wouldn’t be Halloween/Christmas without a touch of the Griswalds, so I added some LED strips to light the way.

The “smoke machines” weren’t great but added another layer of spookiness.

Finally, the disco lights in the entrance pillars were the icing on the cake.

The result was something that seemed to go down very well with all the trick-or-treaters and even had a neighbour come down to check out what was going on.

Code

All of the code is in this repo on GitHub (Arduino, Go, C, STL, F3D) if you don’t want to read further.

Doorbell of Doooooom V2.0

The initial setup for the Doorbell was dead simple. A push-to-make button connected to a GPIO on the C.H.I.P which caused some code to randomly play out various MP3 files over the audio-out to some big speakers cunningly hidden near the door.

The end result was far far more complex than I ever imagined.

  • I decided to use Gobot to handle the pin scanning and calling out to mpg123 to play the mp3 files. Of course I used youtube-dl to download videos from YouTube and then WinFF to convert to MP3 followed by Audacity to clip them appropriately.

  • I had a couple of problems with Gobot initially. The main one was that all of the GPIOs were renamed in Linux 4.4 on the C.H.I.P. So I vendored in Gobot to my project and manually changed them all to be correct. I really such PR my changes on GitHub.

  • Once that was done, the sample code for reading the XIO-P0 pin connected to the button worked perfectly and calling out to mpg123 also worked well. I added a few extra lines of code to ignore multiple button presses during music playing and finally I added a simple http GET to Skeletony’s API end-point over Wifi to get him to do his magic when the button was pressed.

“Please press the button, pretty please”

Every year I’ve done a doorbell I’ve had to put up some sort of sign saying “please press the button”. I’ve also had to cover over our normal doorbell to really get people to focus.

This year I thouhgt “I’ll add a simple LCD message to guide people”. Then I thought I’d use my Adafruit OLED screen. Luckily most of the code I needed was out there and it was case of a few evenings of tying it all together.

A very nice person has created https://github.com/vkomenda/ssd1306 which is C code for the SSD1306 OLED display. It basically worked on the C.H.I.P. with some changes for my particular setup.

  • I had to use the 2nd I2C port for some reason so I used:
#define SSD1306_I2C_ADDR 0x3D 

in ssd1306.h

  • The Adafruit SSD1306 screen also needed to have its reset pin pulled low before it would work. So I added a variation of some code from here to both setup the GPIO pin XIO-P1 correctly and toggle it in ssd1306_demo.c. My final version of that code is here

  • The pin connections from the C.H.I.P to the screen are as follows:

  • I2C SLK - TWI2-SCK

  • I2C SDA - TWI2-SDA

  • VCC - VCC-3V

  • GND - GND

  • RESET - XIO-P1

You then run

make
sudo ./ssd1306_demo /dev/i2c-2

That shows some demo text as an image.

To show your own image you need to create it in Windows Paint (for realz) as a 128x64 monochrome BMP. Here’s mine. Then use LCD Asistant which is a simple Windows tool that takes the BMP file and turns it into a .h file. I then replaced the array in font5x7.h with that one in the generated h file. I re-ran Make and then ran the code. It took a few iterations to get an image I was happy with.

Doorbell Enclosure

I had a few goes at creating an enclosure for the doorbell button itself in Autodesk Fusion 360. The end-result was fine but not perfect.

Image

I also printed off a bunch of halloween designs from Thingiverse to act as the think you pushed rather than a raw button. The skull ones were scary but awkward to attach. In the end I used this pumpkin one. But I had to create a simple attachment for it too in Fusion.

I then poked an LED out through a hole I’d designed into the enclosure. Rather than make the wiring any messier. I wired it up to a tiny LiPo battery with a tiny switch. It worked well and lit up the pumpkin nicely, if a little lopsidedly. I then added a small metal nail to the back of the pumpkin to stop the button rotating.

I needed an enclosure for the OLED screen. That worked well but was slightly too big. I forgot to add a cut-out for the wires to escape so a soldering iron was used to melt the plastic.

I ran the wiring for the screen and the switch iself in through the letterbox and had the C.H.I.P. dangling inside and powered by a phone charger.

Image

Skeletony

Now that the main aim of the project was achieved I could relax since if nothing else worked, I still had the doorbell. I thought more about Skeletony and started “upgrading” him in iterations.

Heart

This gave huge bang for the buck. I took this 3D design from Thingiverse and printed it in semi-transparent red. I then dremeled a hole into and and stuck a bright LED in. Then I found some “pulse” Arduino code from here which looked a lot better than simple on-off. Job done.

Eyes

Even easier. Dremel out holes in the eye sockets and stuff two orange LEDs with wires into the holes. Bring wires out to the back of the head. The LEDs are just toggled on/off but due to the power glitching caused by the servo, they actually glowed. So a feature for free.

This glitched a lot but again, huge impact for such a simple idea. I ripped Skeletony’s head off and hot-glued it to a generic dx.com tiny servo. I cable-tied and hot glued the servo onto Skeletony’s spine. The bog-standard Arduino Servo code from here did the job and I just made go 90 degrees, pause and return. The servo was very noisy at rest so I found some good tips on turning it off rather than holding it at a point.

Guts

I hot-glued some creepy crawlies to his belly to hide all of the electronics.

Image

Ears

So at this point we have heart, eyes and head all controlled by an Arduino Nano and kicking off whenever a particular pin was toggled. I could have run some wires from the C.H.I.P around the door frame and onto Skeletony but of course I wasn’t happy with that.

I needed to wifi-enabled Skeletony and we all know what that means - yep our old friend the ESP8266. Over the past year I’ve gone from using NodeMCU Lua to Espruino to Arduino on the ESP. The biggest community seems to be Arduino so that’s what I’ve settled on.

The basic code was trivial really. Run the off-the-shelf server code with a single API end-point. When C.H.I.P calls the end-point, toggle a GPIO pin which in turn is connected to the Arudino Nano and causes all of Skeletony’s shenanigans.

But I’ve also been playing with the fantastic Wifi Manager code for Arduino on ESP8266. It gives you the ability to run the ESP as a Wifi access point, connect to it with your phone/tablet/laptop and configure with the usual access point it should connect to. This means you don’t have to hard-code the SSID/Password into your Arduino code. Awesome!

But I went a step further and spent quite a while figuring out how mDNS works. It’s actually very cool and much more than “DNS”. It meant I could have N Skeletonys all advertising themselves as Skeletonies and then I could dynamically get their IP addresses on the C.H.I.P. and communicate with them. It makes everything extremely flexible.

It all worked beautifully until the day itself and, as ever, something went wrong. In this case it was the mDNS piece only. But some quick hard-coding of IP addresses in the C.H.I.P code at the last minute took care of that.

I powered him from two USB powerbanks on his back. (The two were an unsuccessful attempt to deal with the servo glitching).

Image

LED strips

Just a quick note about the analogue RGB LED strips I put down to guide people to the door. Wow, did they exceed expectations! They lit up the entire house and make it look extremely spooky. The spookiness doesn’t really come across in the video. These were bog standard 5050 waterproof strips that you can get on DX.com or Aliexpress.

Image

Rotating Lightbulbs

I learned about these from Big Clive on YouTube. His channel is a geek delight and highly recommended. He breaks apart electronic gadgets and lights from eBay and explains how they work. It’s nearly always interesting and he comes across as a thoroughly nice man. I got mine from here on eBay. They worked ok but really aren’t intended for outdoors. They work brilliantly indoors.

Fog/Smoke/Steam Machine

I learned about these devices from NightHawkInLight on YouTube. They were fine but the “fog” was not that impressive. The cheaper ones seemed to work slightly better than the bigger one with the LED. All from eBay obvs.

And finally

Next year? Yeah, next year we go simple. I swear. Says the man who has already set reminders in Google Calendar for purchases and 3D printing in September 2017.

02 Oct 2016, 17:45

Quick review of the BLU Life Mark £80 Android phone

A couple of weeks ago, I took my Galaxy S6 out for a run in the rain and it died. Based on previous experience with the horror known as Vodafone Ireland Insurance, I figured I’d be looking at 10 days minimum to get a replacement. This proved 100% accurate as the usual completely inept software that connects Vodafone’s PDP-11 to Stay Mobile’s Commodore 64 had cancelled my insurance without notification several months previously. It took them a week to sort this out before they could even look at replacing the phone.

So the same day it died, I ordered a cheap replacement backup phone which arrived within 2 days from Amazon UK. Yep, you can order and receive a new phone from the UK faster than two groups of circus clowns in Dublin can fix a mistake they made.

BLU Life Mark

The BLU Life Mark is an utterly generic low-mid range Android phone from a US-based company. It’s very similar to the Wileyfox Swift I got my mother-in-law a few months back, which she loves.

BLU Life Mark Bits

This won’t be a long review as there really isn’t anything new to say about modern smartphones. Slabs of glass that still can’t tell the difference between accidental and intended touch or learn anything about your usage and optimise accordingly.

It has a 720p screen of decent brightness and perfectly acceptable touch responsiveness. It uses a Mediatek chipset which, whilst it isn’t particularly fast, is fine for 90% of the population. It lags when opening the camera or launching Facebook but otherwise it’s grand.

It can take 2 SIM cards or a SIM plus an SD Card. Which is more than can be said for Samsung or HTC.

Battery life seemed a bit weak compared to an S6.

The fingerprint scanner is superb. It’s not only in the correct place, the back, it is also extremely fast. I can’t abide the one on the S6 and have it disabled.

The camera isn’t brilliant. 13MP in theory but nowhere close to the S6. But for day to day, it does the job.

The GPS/Compass is a bit crap. Google Maps spun around like a tasmanian devil whilst trying to navigate on foot around Berlin. Positional accuracy seemed ok tho. Both Google Maps and Scout worked fine otherwise in Berlin.

The only seriously bad part of using it for a week was the Bluetooth. I paired it to Sync 2 on my Mondeo and initially it streamed my Adam Buxton podcast perfectly. But after a few miles driving, it started cutting in and out “randomly”. It was driving me nuts. Then I sussed that the cut-outs happened when I was passing other cars. So I’m now pretty sure the bloody thing was trying to have a Bluetooth chat with every phone and car it could see. Unfortunately this high-speed connect/disconnect sent the car’s Bluetooth stack nuts. I then couldn’t connect properly from any phone. Factory defaults and Master Reset failed to fix it. Eventually I had to disconnect the car battery to reboot the car! That worked. Now I know this might have been the car’s fault but it has worked seamlessly with the S6 and an iPhone for months so I’m blaming the BLU.

Overall, unless you are a Bluetooth streaming fiend like me, you’ll find little to complain about in this phone. It’s really quite wonderful that you can have a supercomputer in your hand with access to all the world’s information for £80 without any contract. It’s a great time to be alive.

Oh and the S6 somehow fully recovered after I kept it in a very warm place for a few days. So that’s €60 I won’t be giving to the Stay Mobile Clown Retirement Fund.

02 May 2016, 19:32

Introducing YTPodders - Get your fave YouTubers as audio podcasts on your phone

Like my kids, I love regular YouTubers. My particular favourites are the tech, craft, metal and woodworking people who make amazing things every week. Those gals and guys have to be watched to really get the value from them and here’s a few more worth looking at too, of course not forgetting these other gems.

But there are others I love equally where it’s mostly about what they are saying. For example, Ethan Newberry (aka The Ginger Runner) does a fantastic weekly live session where he mostly interviews Ultra runners. This works just as well without the video. I listen to this when running or driving. It’s seriously one of the best motivational things you can listen to on a marathon!

For a few months I was using youtube-dl to grab the latest episode video file, then Winff/ffmeg to convert to MP3, then I manually copied the file to the music player on my Android phone. Not exactly slick.

Of course, I decided to automate it and figured it’d take a couple of evenings. Two months later, here we are :-)

YTPodders

Introducing YTPodders, an App that does everything you need to have automated podcastification of YouTube Users and Channels. It works very similarly to my manual process as follows:

  • When you run ytpodders, it checks the list of YouTube Users and Channels you previously added for any new content. It downloads any new ones it finds using youtube-dl
  • As part of that download process, youtube-dl uses ffmpeg to convert the videos to MP3 audio
  • It copies the MP3s to the YTPodders App directory in Dropbox and waits until they are all synced properly with Dropbox
  • It then generates an rss.xml file containing all the entries and tells you the URL of that rss.xml file
  • You subscribe to that rss.xml file in your Podcasting App on your phone e.g. BeyondPod on Android.
  • The Podcasting App then regularly checks for updates and pulls any new content from Dropbox on to your phone for offline listening.

BeyondPod

This has been working really well for me for several weeks now. I have a Windows 10 Scheduled Task setup which runs it every morning at 6am. And I have BeyondPod checking a few times a day too. So my phone always has the latest and greatest YouTube MP3s.

The code needs lots of work and there is still a lot of maintenance type functionality that needs to be added (pruning old MP3s; cleaning up when you remove subscriptions etc).

The important thing you need to do is to give YTPodders authorisation to access your Dropbox. It only gets access to its own sub-directory in the Apps directory in Dropbox so it can’t mess anything else up.

Full installation and usage instructions for End-Users and Developers are over on GitHub here.

It has been mostly tested on Windows 10 but also runs on Mac and Linux. The server runs on Windows, OSX, CentOS and Fedora too (presumably any Linux distro).

As this is basically time-shifting for personal use only, it should come under US fair use. The download of the video by youtube-dl should count as a view for advertising purposes. If you are concerned about depriving your favourite YouTubers of income, why not back them on Patreon, if they use it? I did that for Ethan because I get so much value as a runner from the videos he creates and the interviews that he does.

Improvements, suggestions and bug reports all gladly accepted over on GitHub. The code is written in Go/GoLang, yes it’s a giant awful ball of mud hack and it doesn’t do multiple downloads in parallel on purpose, not because I can’t figure out goroutines :-) But it works.

08 Feb 2016, 17:43

Three ways to build Go 1.4 binaries for MIPS32 Onion Omega #golang #docker

I previously wrote about using gccgo to build Go binaries for the Onion Omega due to Go’s lack of support for MIPS CPUs. But TBH it’s a pain in the butt. Things were looking up when it was revealed that Go 1.6 would have MIPS support but sadly it’s for MIPS64 only, for datacenter applications I guess.

Onion Omega

However Cathal Garvey discovered a GitHub repo where some lovely person has ported v1.4.2 of Go to MIPS32 and it works perfectly on the Onion Omega (and presumably all other Atheros AR9331 boards).

This is a huge jump forward for the Onion Omega. Language support has been a bit of a problem for me with both Node.js and Go not really being usable there until now.

Due to the lack of storage on the Omega, you won’t be able to install the full Go build system there so a cross-compilation setup is needed.

I’ve been able to build the binaries on Linux, Windows and in a Docker container. All are easy.

Linux (or Linux VM on Windows)

Following Cathal’s simple instructions, I was able to build Go for MIPS32 in a few minutes in a Linux VM on my main Windows machine. I then cross-compiled a Hello World and scp’ed it to the Omega. It worked first time!

My steps:

cd
git clone https://github.com/gomini/go-mips32.git
cd go-mips32/src
export GOOS=linux
export GOARCH=mips32
sudo mkdir /opt/mipsgo
./make.bash
cd ..
sudo cp -R * /opt/mipsgo
export GOROOT=/opt/mipsgo
export PATH=/opt/mipsgo/bin:$PATH
vi helloworld.go
go build helloworld.go

Windows 10

I was very surprised this worked but of course Go is strongly cross-platform. My standard build setup for Node.js native modules did the trick. You’ll probably need Visual Studio Community 2015 and Git for Windows. Then:

Open a CMD prompt (note I have all my code on D: drive)

d:
cd gitwork
git clone https://github.com/gomini/go-mips32.git
cd go-mips32\src
set GOOS=linux
set GOARCH=mips32
make.bat

I then created a simple CMD file which sets everything up when I need to build for MIPS so it doesn’t interfere with my main Go install.

set GOOS=linux
set GOARCH=mips32
set GOROOT=d:\gitwork\go-mips32
set GOPATH=d:\gitwork\go
set PATH=d:\gitwork\go-mips32\bin;%PATH%
CMD

When I launch that, I can do the usual go build filename.go. Note that the MIPS port seems to be able to share the same GOPATH as my x86-64 one. Not sure that will work in every case tho e.g. If C modules are bound?

For Windows I use WinSCP to copy the files to the Omega. For some reason Filezilla SFTP has a problem talking to it.

Docker Container on Windows

Hello World

To get more familiar with Docker I decided to create a Docker image that others can use. That turned out to be pretty easy too. Here is the Dockerfile:

FROM alpine:3.3

ENV GOLANG_VERSION 1.4.2
ENV GOLANG_SRC_URL https://github.com/gomini/go-mips32.git
ENV GOOS linux
ENV GOARCH mips32
ENV GOROOT /usr/local/go

RUN set -ex \
	&& apk add --no-cache --virtual .build-deps \
        bash \
        git \
        file \
        ca-certificates \
        gcc \
        musl-dev \
        openssl \
        openssh \
	\
  && cd /usr/local/ \
	&& git clone "$GOLANG_SRC_URL" go \
	&& cd /usr/local/go/src \
	&& ./make.bash \
	\
	&& apk del .build-deps

ENV GOPATH /go
ENV PATH $GOPATH/bin:/usr/local/go/bin:$PATH

RUN rm -rf "$GOROOT/src"
RUN rm -rf "$GOROOT/test"
RUN rm -rf "$GOROOT/doc"
RUN mkdir -p "$GOPATH/src" "$GOPATH/pkg" "$GOPATH/bin" && chmod -R 777 "$GOPATH"
WORKDIR $GOPATH/src

And you can grab the image from Docker Hub here.

The full set of steps for Windows are as follows:

  • Install Docker Toolbox for Windows. It’ll also install VirtualBox if you don’t already have it.
  • Run a Docker shell and type:
docker run -t -i conoro/go-mips32:v1 /bin/sh

(Note v2 has some problems I need to fix so you’ll need to manually install openssh and git on v1)

  • You’ll now be at a Linux prompt and you can type: go version
  • Then create a Hello World using: vi helloworld.go
package main

import "fmt"

func main() {
	fmt.Println("Hello, Conor")
}
  • Compile it with: go build helloworld.go
  • Copy it to the Onion Omega with: scp helloworld root@ip-of-your-onion/helloworld
  • Open a shell on your Omega with the webapp or Putty and just type: helloworld

Web App

A more advanced example which also works perfectly is to run a web-app using the Gin framework. For that, all you need to do is:

go get github.com/gin-gonic/gin
vi gintest.go

then in vi:

package main

import "github.com/gin-gonic/gin"

func main() {
    r := gin.Default()
    r.GET("/ping", func(c *gin.Context) {
        c.JSON(200, gin.H{
            "message": "pong",
        })
    })
    r.Run() // listen and server on 0.0.0.0:8080
}

Then build that, scp it to the Omega and run it. Then open http://ip-of-your-onion:8080/ping to see everything working nicely.

Gin Ping Onion Omega

Note I also built this using the Windows setup for comparison and it worked too.

Database

Not so much luck with embedded databases I’m afraid. I suspect Bolt and LevelDB are using some more advanced filesystem features which are causing issues on OpenWRT. I lack the expertise to debug.

  • Bolt has some CPU specific code which prevented building. I added an entry for MIPS32 (based on i386) and it then cross-compiled but throws error EINVAL when opening DB. Possibly OpenWRT FS related or down to bug in the Go MIPS port. But I’m using Bolt with Stow successfully on another non-MIPS32 project.
  • go-sqlite3 has a C library dependency so it also won’t cross-compile.
  • I gave up trying to get ql to do anything, even on Windows and Linux. It doesn’t like standard SQL syntax and I ran out of patience with the lack of example code.
  • kv has no sample code and my frustration levels with nothing working meant I gave up instantly
  • tiedot generates a large number of massive files which the Onion wouldn’t be able to handle. If I can get it down to LevelDB sizes, I might retry. Actually it doesn’t like 32-bit systems so forget that.
  • goleveldb looked like it would be perfect but it crashes trying to open a DB it created on the Onion. I have a feeling this is a bug in the MIPS32 port of Go. The crash happens in the Snappy library from what I can see. It can create an empty DB and it can read an empty DB but it crashes on a DB that has entries whether the DB was created on the Onion or on Windows.
  • gkvlite - It works! Hurrah! Well the sample code works. Now to try it on some simple stuff I’ve done elsewhere
  • diskv - Double hurrah, it seems to work too.

Conclusion

I’m looking forward to running a lot more code on the Omega now.

02 Jan 2016, 13:00

When will Car Insurance Monitoring Apps become mandatory? 5yrs?

My Car Insurance Broker, 123.ie just offered me up to 10% off my 2016 premium if I installed a driving monitoring app on my phone.

No thanks

But when does it go from “get a discount” to “we won’t insure you unless you install this app”?

The email:

123 Discount

01 Jan 2016, 10:59

How cheaply can you build a full Raspberry #PiZero computer?

When the incredible $5 Pi Zero was launched, the usual suspects were so busy snarking how it wasn’t really $5, that they completely missed what an important moment in computer history this is. You know the type. The ones who would have ridiculed Tim Berners-Lee’s design for the web. Or would have told Linus in no uncertain terms that he was misguided and that microkernels were the future.

Whilst you can’t turn on a #PiZero for $5, you also can’t connect to the LAN with your $1500 Macbook Pro without buying an adapter.

So assuming we don’t factor in electricity costs, carbon credits and depreciation on your chair, how cheaply can you build a fully functioning Raspberry Pi Zero, living in the UK?

Here’s what you need:

Total: £29.01

Or with obvious re-use/borrowing of stuff: £16.70

In Ireland? Add £1 extra for shipping the Pi Zero. Possibly a bit for the SD card from Amazon. Everything else free P&P from China.

Do you need a screen? Yup. Now walk into the sitting room and see if you can spot one. Well done.

A £29 fully fitted-out computer, that you could build the next global webapp on, remains completely revolutionary. All for around the same price as an Apple Thunderbolt-to-Ethernet adapter :-)

You've Quacked the case

31 Dec 2015, 21:20

What excited Conor in tech in 2015?

A completely random braindump of stuff that got my juices flowing this year.

ESP8266 $1 Wifi modules

I’ve talked about the ESP8266 constantly all year. A price-point of ~$1 in volume means that you can wifi-enable anything. Where previously you might have used one of the many low bandwidth “IoT” protocols internally and connected them to hub-device, now you can do Wifi and IP end-to-end. The only downside is high power consumption. I’d actually prefer if they did a low-power V2 instead of the bells-and-whistles ESP32.

The number of projects and initiatives that have grown up around ESP8266 is impossible to keep track of. Ones to check out are:

  • NodeMCU - A really nice dev board and Lua-based stack. This is what I used for most of this year but will be switching to Espruino
  • Espruino on ESP8266 - Still in heavy development but feels like a complete winner. JavaScript + Wifi for $4 is a killer solution.
  • Cesanta Smart.js - A Dublin-based company. Ex-Googlers I think. Similar to Espruino but without the community. Wish they’d join forces instead.
  • Arduino - Yup, you can run a huge amount of Arduino code straight on the ESP8266. Really exciting to have this. Only drawback is that native AVR code and (I think) interrupt-driven code will not compile. Also far fewer IOs than normal Arduinos.

Raspberry Pi Zero and The Mag Pi Issue 40

A $5 computer that came free on the front of a magazine. Very little else needs to be said here. $5 for 1GHz, 512MB RAM, 1080p HDMI, Linux, Mathematica, Node-Red, Kodi and anything else you want to try. I still get the shivers thinking about it. Meanwhile the never-satisfieds will whine about $1 adapters or the fact that it needs electricity. I’m framing my first one.

PiZero

Let’s Encrypt

Anyone who has had to go through the rigmarole of setting up a https server knows what a pain it is. The certs are generally completely overpriced too. Let’s Encrypt Certs are free and full automation is already available for Apache, NGINX, Caddy and more. Now you basically have no reason not to use https.

This is a massive industry segment disruption. I’m thrilled to see it happen.

Security First and Privacy First

I use uBlock Origin, Pop-up Blocker, Do Not Track and Ghostery on all my browsers. A lot of the time I use BlackVPN too. Yet somehow, with my anti-business setup, many many companies received online orders and money from me this Christmas. I’m done with the online advertising industry. All the stuff Doc Searls has been talking about for years is still valid. As for governments thinking our online activities are their business, you need to start fighting back now.

Google Cardboard and YouTube 360

Somehow I completely missed the launch of Cardboard support in YouTube and the creation of 360 videos by an ever growing set of people. The first one I saw was Colin Furze and it’s just incredible. The second was one based on Star Wars The Force Awakens, and is 100x better than the movie. I went and got a much more high quality plastic “Cardboard” as a result. It’s excellent. The recently launched Google Cardboard Camera is also superb but images are sadly locked to the device the panoramic photo was taken on.

This is one overall technology-set that myself and the kids are 100% in agreement on. It rocks. The next Star Wars movie should be launched on Cardboard (or Oculus or whatevs).

Node.js 4.x

Phew. The schism has been healed and 4.x is a really great release. Initially I had lots of problems with native modules on Windows which I hope are finally starting to settle down now. Node is still the best choice for a huge range of workloads and cannot be beaten for mobile back-ends.

Embedded JavaScript

I think JavaScript will completely take over the Embedded world where hard realtime is not required. The Espruino project has shown what is possible here and should be much more widely used. I’m looking forward to seeing it running on the BBC’s micro:bit. Other projects like Cylon.js are also worth a look.

Go/Golang

I’ll be honest, C has been the only language I really loved working in. I like Python and I really enjoy the productivity of Node.js but C was what I spent most of my real programming years using. C++ is an abomination and Java always feels like a crazy amount of work to eventually run some bloated barely-portable thing.

And then I found Go and immediately felt comfortable. It’s C with the sharp edges removed and some really useful stuff added. Static compilation is the killer feature for me. Just drop the very-quickly-compiled binary in anywhere and run it. I’m using it more and more for small projects that aren’t backing a webapp or mobile app. It could work in both those cases too but it just doesn’t have the community in that area the way Node.js has.

I think Node.js and Go will dominate software development over the next few years.

Left-field: Go is slowly getting some Android capabilities. Google should go all-in on it and replace Java. If Apple can manage it so well with the move to Swift on iOS (and they used 3 CPU architectures on Mac!), why not? It would kill all the Oracle problems completely and move them away from a legacy language.

Scriptcraft & Minecraft

Minecraft continues to dominate my younger kids’ lives. From Stampy to Servers, they are never bored playing it or watching videos about it. My buddy Walter built the amazing Scriptcraft which enables you to build mods and control Minecraft in, yes you guessed it, JavaScript. His book is a must-read for anyone looking for an interesting way to teach kids how to program. I really want to try out some stuff where it interfaces with the real world. I think Microsoft are missing a trick by not rowing in behind Walter and this wonderful project.

It’s also a huge pity to watch Lego completely miss the boat here and continue to sell the crazily overpriced and overspecced Mindstorms. There is a sweetspot to be found in an online-world + real-world + electronics + JavaScript and it ain’t Lego bleedin Dimensions.

Particle Photon

I was given a Particle Photon recently and was blown away by how easy the setup was and how slickly the Cloud IDE works even through firewalls and NAT. Despite the Open Source nature of it, I still worry about lock-in to some degree. Having said that, my DigiStump Oak just shipped (ESP8266 again!) and it it now Particle API compatible. I’d love to see some sort of multi-vendor federated distributed Particle clouds where you aren’t betting your IoT strategy on the financial stability of one startup.

React Native

Use JavaScript to build Native Apps on iOS and Android. What’s not to like? Weird how I hate Facebook the site/app but love so much of their Engineering.

RGB LEDs / Neopixels

Ridiculous amount of fun with simple individually controllable RGB LEDs. These are going to be everywhere in 2016. Everywhere.

3D Printing

I still adore my Printrbot Simple Maker’s Edition. I continue to be surprised by the quality of prints from such a cheap printer. I’ve had some fun with Ninjaflex and unusual colours this year. Also a multitude of #PiZero cases! If funds permit, I’ll probably start looking at one of the Prusa i3 variants to get a bigger print area but otherwise it does everything I need.

eFibre by Eir

We get 92Mbs down, 19Mbs up. It’s completely changed how we use the internet. Bravo Eir(com). Genuinely surpassed all expectations. Getting speeds like that on a poxy twisted pair is staggering.

But let’s be absolutely clear about broadband in this country, the Government’s latest target of 30Mbs for everyone is a joke. By the time it’s done, it’ll be completely out of date. Why can these people not understand that ultra-fast broadband everywhere will do more for employment in this country than anything else. They’d be heroes in history for doing this right, not remembered as a bunch of clowns who couldn’t properly roll out a water quango and postcode quango.

Statically hosted Blogs

It feels like every day there is another WordPress security scare. And that’s without mentioning the plugin ecosystem horror. I got sick of the upgrade cycle treadmill and constant exploits last year and moved everything to statically hosted blogs. First with Harp.js, then with Hexo and now with Hugo. All fine tools, all work well with GitHub Pages and OpenShift. The incredible speed of Hugo is what makes it my current favourite. Edit, build, deploy, fuggedaboudit. I will never go back to a traditional DB-backed CMS.

Dirt-cheap Android phones and tablets

I got a Doogee X5 Android phone for €55 a few weeks ago as a backup device. Apart from the case being a bit plasticky, it could pass for €200 worth. It has a great screen and surprising speed. 2 SIM slots and an SD card slot. Samsung could learn a lot from Doogee.

One of my daughters got the lowest-level Kindle Fire as a Christmas present. The specs are garbage. She loves it. It does absolutely everything she needs and she hasn’t asked to use the iPad Mini once since she got it.

I seriously doubt I’ll ever buy a premium phone on contract again. Once One Plus return to removable backs, replaceable batteries and SD card slots, I’ll jump to either them or the Wileyfox. Apart from the camera, there is practically nothing on my Galaxy S6 that I couldn’t do with an S4 or HTC Sensation. And they are both more robust and have replaceable batteries and SD card slots.

Linux everywhere

Everywhere. This makes me happy. I was very surprised my other daughter was more than happy to get an old hand-me-down laptop running Fedora 23. As long as it had Chrome, YouTube, Kodi and Minecraft she didn’t give a damn what the OS was. The OS is irrelevant to all my kids. In our house we segue seamlessly from Android to iOS to Windows to OSX to Fedora to Raspbian. The only things that matter are the apps and the content.

Messaging Apps

Our entire extended family is on WhatsApp including grandparents. SMS is dead to us. MMS was never a thing. I’d prefer if we were all using an Open Source secure P2P system but we’ll get there. The family breakdown is as follows:

  • Adults: WhatsApp. Tiny amount of FB Messenger
  • Teens: FB Messenger, some Viber and some WhatsApp to the (grand)parents
  • Tweens/Smallies: Viber, Snapchat and some WhatsApp to the (grand)parents
  • Youngest: Uses Hangouts to her cousin. Including live video!
  • No one: Telegram.
  • Curveball - Tweens using Instagram comments as a weird chat channel

Top tip - WhatsApp needs a phone number, Viber doesn’t. Many many smaller kids have tablets, not phones. WhatsApp really missing out here. Our solution is to put free Tesco Mobile SIMs in old phones and never put credit on them. Gets over the WhatsApp problem.

9yo yesterday: “What’s ‘Messaging’ on my iPhone”. Me: “It’s SMS”. Her: “What’s that”. Me: “Texts”. Her: “Ah ok. Why are there so many apps for messaging? Why not just one?”

2FA and Authy

Two Factor Authentication is a complete pain in the neck. It really is.

Turn it on everywhere now. Do it. Do it now.

The fact that PayPal still doesn’t have it is a complete disgrace. I’d strongly recommend using Authy instead of the Google Authenticator App. The main reason is that you can install Authy on multiple phones/tablets which you cannot do with Authenticator. They also have a Chrome extension.

Things that continue to disappoint

  • Twitter - Useless Web App and Mobile App. Still hostile to developers who make better ones. And still no Filters, in 2015!
  • Facebook - Uninstalled the mobile Apps. A hand-crafted List is the only way to put it under your control. Impossible to use FB for realtime events. Ugh.
  • Google - Local Search and Reviews remain a complete embarrassment. Have them AdBlocked and Ghostery-ed. Maps degenerating. Photos great tho!
  • Google Compute Cloud - Awful. Amateur hour. Avoid. Particularly the MySQL service.
  • Mobile device form factors - Nothing new since 2007. Bored to death of glass slabs.
  • Mobile device usability - I’ll still use a desktop for anything other than quick glance. Everything feels slow and awkward. Android and iOS
  • Batteries - Hurry up already. The only excitement here seems to be exploding LiPos
  • AMD CPUs - RIP AMD. After decades of building PCs with AMD CPUs, I got my first i7 in December. It’s over AMD, give up.
  • Emojis - All those emojis but they never have the one I want.
  • Blockchain - Hype machine in overdrive far too soon. Show me something a kid can understand in 30 seconds and delivers immediate benefit. Everything I’ve tried has been a giant pain in the arse including Identity, Money, DNS and Messaging.

31 Dec 2015, 18:41

My 2015 Christmas turkey oven thermometer and clock

For the third year in a row I decided to build a new oven thermometer for the Christmas turkey, as all of the markings on our temperature knob have been gone for years. We also have one of those mechanical dial thermometers you place inside the oven but they are hard to read and get in the way. My last two attempts worked ok but I was concerned about accuracy. I also used a temperature probe in the meat for belt and braces. The setup was as follows:

The code is a mix of Adafruit, Paul Stoffregen for the improved LCD code with lovely Magenta Comic Sans Font :-) and my own.

I didn’t bother with averaging the values but the jumpiness of the temperature compared to room temp or boiling water tells me our old oven is a disaster and needs replacing.

And just like the previous two years, the turkey was dry despite spatchcocking it, dry-brining it and watching the temperature closely :-( Next year I’m doing a boned and rolled one and I’ve ordered a cheap but protected Chinese oven probe and temperature readout.

I really like the DX voltage booster. It enables you to connect a LiPo battery and a micro-USB power source. It then provides 5V on a standard USB socket. The power source can also charge the battery whilst powering the device. You can then remove the power source and the battery will power the device without interruption. It’s almost perfect except for one stupid feature. You can’t connect a battery to it to power a device without connecting (even momentarily) the power source (e.g. a phone charger). If it could do that then it’d be pretty much at the same level as the Adafruit boost devices. I’ve been unable to find any datasheets for it but ordered two more anyway.

Prototype

Prototype

Completed Board

Completed board

Lego Case

Lego Case

Side View

Side View

Code (latest always on Gist here )

// Temperature from AD8495 K-type Thermocoule adapter and Datetime from DS1307 RTC. Displayed on ILI9341 LCD.
//
// MIT License (MIT)
// Copyright (c) 2015 Conor O'Neill
// Portions copyright Limor Fried/Ladyada for Adafruit Industries and others
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

#include <Wire.h>
#include "RTClib.h"

#include "SPI.h"
#include "Adafruit_GFX.h"
#include "ILI9341_t3.h"
#include "font_ComicSansMSBold.h"

#if defined(__SAM3X8E__)
    #undef __FlashStringHelper::F(string_literal)
    #define F(string_literal) string_literal
#endif

// These are the pins used for the UNO and Teensy
#define _sclk 13
#define _miso 12
#define _mosi 11
#define _cs 10
#define _dc 9
#define _rst 8

// Using software SPI is really not suggested, its incredibly slow
//Adafruit_ILI9340 tft = Adafruit_ILI9340(_cs, _dc, _mosi, _sclk, _rst, _miso);
// Use hardware SPI
ILI9341_t3 tft = ILI9341_t3(_cs, _dc, _rst);

RTC_DS1307 RTC;

String dateOut="";
String timeOut="";
String datePrev="";
String timePrev="";
float temperature=0;
float temperaturePrev=0;

void setup () {
    Serial.begin(57600);

    tft.begin();  
    tft.fillScreen(ILI9341_BLACK);

    Wire.begin();
    RTC.begin();

    // following line sets the RTC to the date & time this sketch was compiled
    // Uncomment this once per power down of the RTC and flash it. Then re-comment-out and reflash
    //RTC.adjust(DateTime(__DATE__, __TIME__));

  if (! RTC.isrunning()) {
    Serial.println("RTC is NOT running!");
    // following line sets the RTC to the date & time this sketch was compiled
    //RTC.adjust(DateTime(__DATE__, __TIME__));
  }

}

void loop () {

    // Read temperature as analogue voltage from AD8495
    analogReadResolution(13);  
    int raw = analogRead(A7);
    float Vout = raw * (3.3 / 8191.0);
    temperature = (Vout - 1.25)/0.005;

    // Print Temperature to Serial console
    Serial.println(temperature);

    // Get current DateTime from DS1307 RTC
    DateTime now = RTC.now();

    // Print it to Serial Console
    Serial.print(now.year(), DEC);
    Serial.print('/');
    Serial.print(now.month(), DEC);
    Serial.print('/');
    Serial.print(now.day(), DEC);
    Serial.print(' ');
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);

    // Generate nicely formatted datetime string for ILI9341
    dateOut="";
    timeOut="";
    if (now.hour() < 10){
        timeOut += "0";
    }
    timeOut += now.hour();
    timeOut += ':';
    if (now.minute() < 10){
        timeOut += "0";
    }
    timeOut += now.minute();
    timeOut += ':';
    if (now.second() < 10){
        timeOut += "0";
    }
    timeOut += now.second();
    Serial.println();
    if (now.day() < 10){
        dateOut += "0";
    }
    dateOut += now.day();
    dateOut += '/';
    if (now.month() < 10){
        dateOut += "0";
    }
    dateOut += now.month();
    dateOut += '/';
    dateOut += now.year();

    // Print Temperature and Datetime to ILI9341 LCD
    unsigned long start = micros();
    tft.setCursor(0, 0);
    tft.setTextColor(ILI9341_MAGENTA);
    tft.setFont(ComicSansMS_24_Bold);
    tft.println("Temperature:");

    // Wipe out previous text and write new text
    tft.setCursor(0, 45);
    tft.setTextColor(ILI9341_BLACK);
    tft.println(temperaturePrev);
    tft.setTextColor(ILI9341_MAGENTA);
    tft.println(temperature);
    temperaturePrev = temperature;

    // Wipe out previous text and write new text
    tft.setCursor(0, 100);
    tft.setTextColor(ILI9341_BLACK);
    tft.println(datePrev);
    tft.setTextColor(ILI9341_MAGENTA);
    tft.println(dateOut);
    datePrev = dateOut;

    // Wipe out previous text and write new text
    tft.setCursor(0, 145);
    tft.setTextColor(ILI9341_BLACK);
    tft.println(timePrev);
    tft.setTextColor(ILI9341_MAGENTA);
    tft.println(timeOut);
    timePrev = timeOut;

    delay(1000);
}

30 Dec 2015, 17:15

Auto-tweeting the #Bandon floods with Twilio, Tasker, Let's Encrypt, a #PiZero, golang, Caddy and an Asus router

Intro

I haven’t blogged properly about the $5 Raspberry Pi Zero computer yet, despite Tweeting non-stop about it. I will soon. In the meantime, I’ll just repeat that

It’s a major moment in computing

The inclusion of a free one on the cover of the MagPi Magazine will be remembered for years to come.

The town in which I live, Bandon, flooded again recently, because Ireland. I’ve had a simple Node.js app running on a Gen 1 Raspberry Pi B, scraping the Bandon Flood Warning site every 15 minutes for the past four years and saving the data in Google Fusion Tables.

Yes that’s how Cork County Council’s/OPW’s Flood Warning site looks in the middle of one of our biggest floods ever:

FEWS Unavailable

With all this flooding, I decided to finally create a related setup which takes the SMS Flood alerts from the County Council and auto-tweets them to the @BandonFEWS Twitter account which I created and have manually updated since 2011.

The Details

So the final $7 hardware (including Wifi adapter) now looks as follows:

PiZero FEWS

  • My phone is registered with the Bandon Flood Warning site (it has been for years)
  • I have a Twilio account with a $1 per month UK SMS number. Irish numbers are $6 per month :-(
  • SMSes are sent to my phone from Cork CoCo announcing a new flood warning level or severe weather alert (two different systems and numbers)
  • The Android Tasker App watches for SMS from these sources with particular contents
  • Tasker auto-forwards these SMSes to my Twilio number

Tasker

  • I have the Twilio number configured to call a my simple API end-point with the SMS contents
  • The API end-point is running on one of my $5 Raspberry Pi Zeros and is written in Go. Code below.
  • The PiZero is behind my home router which is an Asus RT-AC68 so somehow Twilio had to connect through that to the Zero
  • I initially setup a simple port forward to the Zero and I already use no-IP.com for Dynamic DNS. So Twilio called http://something.no-ip.net:1234 and my router passed the request to the PiZero server app on port blah
  • The PiZero server app parsed the POST request and extracted out the SMS. It split this into multiple Tweets (a la Tweetstorm) if more than 140 chars and used the Anaconda Go client library to post that to @BandonFEWS on Twitter
  • Done

But I wasn’t happy with http, nooooo, I wanted https and I wanted to use Let’s Encrypt. Cue rabbit hole.

Let’s Encrypt and Caddy

Let’s Encrypt offers free https certs.

It’s as revolutionary as the PiZero.

It also provides APIs so this can be done completely automatically. This resulted in lots of people adding easy Let’s Encrypt integration and client libraries very quickly.

  • Caddy is a really nice simple-to-use web-server written in Go. It runs perfectly on the PiZero. It also has completely automatic Let’s Encrypt integration if you want it. So I stuck it in front of my Go server to turn it into a https server. Except life is never that easy.
  • I hit two immediate problems:
    • I’d have to drop no-IP for Dynamic DNS since I’m trying to register for my own https cert
    • To stop baddies registering domains they don’t own, Let’s Encrypt calls back to you and insists on doing that on port 443. So my random high port number on my router wasn’t going to work
  • Then I realised that my DNS provider, DNSMadeEasy has Dynamic DNS built-in. So I grabbed one of my parked domains and set it up with a Dynamic DNS A Record, giving it a dedicated password. But then of course I discovered that my Asus Router doesn’t have support for Custom Dynamic DNS out of the box.
  • I quickly found the Merlin Firmware which is interesting. The standard Asus firmware is just a simplified fork of Tomato so Merlin forks again and adds back in the stuff that Asus removed. So you keep the same UI and general functionality, just with more customisation.
  • Installation was a doddle and then I just had to whip up a simple script a few lines long to call out to DNSMadeEasy whenever the router’s IP address changed (see below).
  • I then temporarily port forwarded 443 on the router to the Pi Zero and started Caddy with this incredibly complicated config file :-)

Caddyfile:

file
https://www.conorsdomain.com
proxy / localhost:9998
  • Caddy saw that I wanted https, so it connected to Let’s Encrypt and a minute later I had everything necessary for my secure web-server.

Jaw-drop time

  • Once the registration was done I could remove the 443 port forward and switch to a non-standard port
  • I went over to Twilio and provided the new https://conorsdomain.com:9999 as the end-point to call. No joy. But a quick support ticket later and they made a change over the weekend(!) to fix it. Boom, everything working fine.
  • With the terrible weather, I didn’t have to wait long for the first non-test SMS to appear. A couple of seconds later it was on Twitter:

Bandon Flood Warning

Alternatives

  • Of course I could exclude Twilio from this entire flow and call the end-point directly from Tasker but SMS will often work when no data connection is available.
  • Having said that, the connection to the phone is a big worry as we are in a poor signal area. But registering my UK Twilio number on the Flood Warning site didn’t work (local warnings for local people) and I’m not paying $6 a month for an Irish number.
  • In theory I could take the scraped data from the site and generate my own alerts but the Council rightly overrides the default trigger levels on occasion to warn people of impending flooding.

Go Code (See for https://gist.github.com/conoro/f1a3f7c5b96e2b033119 for latest)

package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"net/url"
	"os"
	"strconv"
	"strings"
	"time"

	"github.com/ChimeraCoder/anaconda"
)

type Configuration struct {
	ConsumerKey       string
	ConsumerSecret    string
	AccessToken       string
	AccessTokenSecret string
}

func main() {
	file, _ := os.Open("conf.json")
	//file, _ := os.Open("conf-test.json")
	decoder := json.NewDecoder(file)
	configuration := Configuration{}
	err := decoder.Decode(&configuration)
	if err != nil {
		fmt.Println("config error:", err)
	}
	anaconda.SetConsumerKey(configuration.ConsumerKey)
	anaconda.SetConsumerSecret(configuration.ConsumerSecret)
	api := anaconda.NewTwitterApi(configuration.AccessToken, configuration.AccessTokenSecret)

	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		body := r.PostFormValue("Body")
		log.Println(string(body))
		if strings.Contains(body, "Bandon FEWS") || strings.Contains(body, "Met Eireann") {
			fmt.Fprintf(w, "Thanks for the update")

			a := []rune(body)
			if len(a) <= 140 {
				// Just post normal Tweet
				result, err := api.PostTweet(body, nil)
				if err != nil {
					fmt.Println(err)
				} else {
					fmt.Println(result)
					fmt.Println("Tweet ID: ", result.Id)
				}
			} else {
				// have to split into a Tweetstorm
				var originalTweetID int64
				var subTweet string = ""
				var tweetCount int64 = 0
				tweetParams := url.Values{}
				for i, r := range a {
					subTweet = subTweet + string(r)
					if i > 0 && (i+1)%137 == 0 {
						tweetCount++
						// Need to do normal first tweet but in_reply_to successive tweets
						if tweetCount == 1 {
							// Just Tweet and extract the ID from the response
							result, err := api.PostTweet("1/ "+subTweet, nil)
							if err != nil {
								fmt.Println(err)
							} else {
								fmt.Println(result)
								originalTweetID = result.Id
							}
						} else {
							// adding one second delay in Tweetstorm to prevent any throttling by Twitter
							time.Sleep(time.Second)
							// Tweet in reply to the first tweet by setting in_reply_to_status_id
							// originalTweetID
							tweetParams.Set("in_reply_to_status_id", strconv.FormatInt(originalTweetID, 10))
							result, err := api.PostTweet(strconv.FormatInt(tweetCount, 10)+"/ "+subTweet, tweetParams)
							if err != nil {
								fmt.Println(err)
							} else {
								fmt.Println(result)
							}
						}
						subTweet = ""
					}
					if i == len(a)-1 && subTweet != "" {
						// just Tweet whatever text is left at the end
						time.Sleep(time.Second)
						tweetCount++
						// Tweet in reply to the first tweet by setting in_reply_to_status_id
						// originalTweetID
						tweetParams.Set("in_reply_to_status_id", strconv.FormatInt(originalTweetID, 10))
						result, err := api.PostTweet(strconv.FormatInt(tweetCount, 10)+"/ "+subTweet, tweetParams)
						if err != nil {
							fmt.Println(err)
						} else {
							fmt.Println(result)
						}
					}
				}
			}
		}
	})

	log.Fatal(http.ListenAndServe(":8333", nil))

}

Asus DNSMadeEasy Update

This is smidge fiddly. More details here. Once you have Merlin installed and you are happily connected to the internet again (you did remember to write down all the settings for your ISP didn’t you?). You need to:

  • Go to Administration -> System
  • Enable SSH, which also obviously gives you SFTP
  • Toggle “Format JFFS partition at next boot” to Yes
  • Toggle “Enable JFFS custom scripts and configs” to Yes
  • Click Apply
  • SSH on to the box with your router’s Admin username and password
  • Create a file called /jffs/scripts/ddns-start
  • Make it executable (chmod 755 ddns-start)
  • Copy these contents into ddns-start
#!/bin/sh
USERNAME="yourDNSMadeEasyUsername"
PASSWORD="TheSpecificPasswordYouSetOnThatDNSRecord"
IP=${1}
ID="TheSpecificRecordIDAssignedbyDNSMaseEasy"

curl -k "https://cp.dnsmadeeasy.com/servlet/updateip?username=${USERNAME}&password=${PASSWORD}&id=${ID}&ip=${IP}" >/dev/null

if [ $? -eq 0 ]; then
    /sbin/ddns_custom_updated 1
else
    /sbin/ddns_custom_updated 0
fi

  • Do a reboot for good measure and you should see DDNS displaying success on the main dashboard

27 Dec 2015, 16:38

Blogging from my phone with DroidEdit, Hugo, GitHub Pages and Travis

I switched this blog to the superb Go-based tool Hugo earlier in the year. Its staggering speed compared to HarpJS and Hexo plus a single executable you can drop in anywhere, make it a no-brainer for static blogs.

I continued to host for free on GitHub Pages which means I never ever ever have to worry about WordPress security exploits or badly written plugins again. However using GH Pages means you are quite limited in how things work.

For several months I used Hugo in the recommended way of having one Git repo for the blog’s “source files” and then the original conoro.github.io repo as a Git sub-module for the deployed HTML. I’ve never heard a good word said about Git sub-modules and now I understand why. Nasty awkward things that mess everything up if you blink wrong. But it worked ok-ish until I decided to try Travis CI.

Travis is a continuous integration tool that can watch for changes in your GitHub repos and then run “jobs” on them. It’s mainly used for building software but there is no reason you can’t use it for building a blog. So the initial idea was that I would git add/commit a new blog post in my source repo and then Travis would run Hugo on it and commit the generated HTML to the blog, thereby publishing it.

The real intent was so I could blog from devices that don’t run Hugo like phones and tablets. Of course they’d somehow need to support a text editor and Git but not Hugo itself.

For Android I quickly found the superb DroidEdit which has Git support built-in. It was dead easy to use it to generate a new post and add that to my repo. So I would have almost WordPress-level of easiness in blogging on the fly. Its only real drawback is the lack of Markdown syntax highlighting.

DroidEdit

Except then I tried to get it working with Travis. Several weekends of effort trying to wrangle the Git sub-module setup into submission ended in total frustration. Finally today I said “sod sub-modules” and went old-school “copy the files from one repo to the other and commit them there”. And ye know what? It worked!

There’s a few bits in there to do with using https:// instead of git://. But the critical one-off steps on your PC are:

  1. get a Github token for Travis
  2. Then install Travis locally
  3. and encrypt your token via: bash travis encrypt GH_TOKEN=<secret token here>
  4. Finally add that output to the “secure” string in .travis.yml.

So here you go with the files you need to do the same:

.travis.yml

language: go
go:
  - 1.5.1
sudo: required
env:
  global:
  - USER: Conor O'Neill
  - EMAIL: cwjoneill@gmail.com
  - GH_REF: github.com/conoro/conoro.github.io.git
  - REPO: conoro.github.io
  - GH_REPO: github.com/conoro/${REPO}.git
  - secure: "hHQScM7MWsK/74fvtoBn7lKuTKx1XlU08Ee4UD6ce0wfKNdE/W8z2dn8qzEsSw3YaoU6AULQgXthX+LVAXVZr1wIC6H9Kvjilaj+9ffRXFKrUv79q8s4EiOKqIvYGla5XlhIzP1Qu1qyLCA4dzgaQF6Cn2jB9AkkObnd8YArf3aW3LUbAnRy0ySo0A/QRupN/ckb81LXYnfbzQZB9zniBIhvGPipR0KdQL7GePShPWDeXJPpblo5kEXiIvHo7b1XYx+xACmaQR9PdoDgoTCAFqz2tJzCU92PnbIGw4Jv/ZdnWmt8Z6/4dO73UhcE3PokPvmg7tdsHbFWxhEzg0NaC7cvYsH3xWy9uTipwYLRd3eGbBt+htCZOj+slNHzREkPJBtEBw+b4iLDAr0T5V0kyflgsGOcgSXPyLIKsI0rHFRVAsZxowowK1UjZ05tnSIlFcIK8DX9c0JoXpM2ktOUt8/2EPCbaoKv17HW4BVDb7vXR8VzBf5MY4qku9NrmmYTMJXrzcdQU8JrbASPlHyF79n5xiiyg74Vq2OYCgHPg1nzmSrC1YgQu0W5WXNjWo9jt8h9C3ztuNYvDJkKkXl7KZDTq/s2XEzpzuLIA4rdTX+7lUB93ggN2YFeh6LV+kq58L8BpMPyiT8kxZLMF0HFTzaRNNwymelkPsV/+QZydro="
git:
  submodules: false
# Use sed to replace the SSH URL with the public URL, then initialize submodules
before_install:
  - sed -i 's/git@github.com:/https:\/\/github.com\//' .gitmodules
install:
  - sudo pip install Pygments
  - go get github.com/spf13/hugo
script: bash ./deploy.sh

deploy.sh

#!/bin/bash

echo -e "\033[0;32mDeploying updates to GitHub...\033[0m"

git config --global user.email "cwjoneill@gmail.com"
git config --global user.name "Conor O'Neill"

# Build the project.
hugo # if using a theme, replace by `hugo -t <yourtheme>`

git clone https://github.com/conoro/conoro.github.io.git
cp -R public/* ${REPO}
cd ${REPO}
git remote
git add -A :/
git commit -a -m "latest via travis"
git push "https://${GH_TOKEN}@${GH_REPO}" master > /dev/null 2>&1