Monitoring our cat with Twine

I was lucky enough to be gifted a Twine by my colleagues at Go Free Range last weekend, and I took the opportunity to put together a very simple service that demonstrates how it can be used.

The Twine

If you haven’t heard of Twine, it’s a hardware and software platform for connecting simple sensors to the internet, and it makes it really very easy to do some fun things bridging the physical and online worlds.

Hardware

On the hardware side, there’s a simple 2.7” square that acts as a bridge between your home WiFi network and a set of sensors.

The twine bridge

Some of the sensors are built in to the square itself: temperature, orientation and vibration can be detected without plugging anything else in. You can also get external sensors, which connect to the square via a simple 3.5mm jack cable. If you buy the full sensor package, you’ll get a magnetic switch sensor, a water sensor and a ‘breakout board’ that lets you connect any other circuit (like a doorbell, photoresistor, button and so on) to the Twine.

Setup

Connecting the Twine to a WiFi network is elegant and features a lovely twist: you flip the Twine on its “back”, like a turtle, and it makes its own WiFi network available.

Twine setup

Connect to this from your computer, and you can then give the Twine the necessary credentials to log on to your home network, and once you’re done, flip it back onto its “belly” again and it will be ready to use. I really loved this simple, physical interaction.

Software

On the software side, Twine runs an online service that lets you define and store ‘rules’ to your connected Twine units. These rules take the form of when <X> then <Y>, in a similar style to If This Then That. So, with a rule like when <vibration stops> then <send an email to my phone>, you could pop the Twine on top of your washing machine and be alerted when it had finished the final spin cycle.

Twine rules

Connectivity

As well as emailing, the Twine can flash it’s LED, tweet, send you an SMS, call you, or ping a URL via GET or POST requests including some of the sensor information.

Supermechanical, the company that launched Twine about a year and a half ago via Kickstarter, maintains a great blog with lots of example ideas of things that can be done.

All technology tends towards cat

Just as the internet has found its singular purpose as the most efficient conduit for the sharing of cat pictures, so will the Internet of Things realise its destiny by becoming entirely focussed on physical cats, in all their unpredictable, scampish glory.

It’s neat having something in your house tweet or send you an email, but I like making software so I decided to explore building a simple server than the Twine could interact with, and thus, “Pinky Status” was born:

Pinky Status

What follows is a quick explanation of how easy it was.

The sensor

I hooked up the magnetic switch sensor to the Twine, and then used masking tape to secure the sensor to the side of the catflap, and then the magnet to the flap itself.

Catflap sensor

That way, when “Pinky” (that’s our cat) opened the flap, the magnet moves away from the switch sensor and it enters the ‘open’ state. It’s not pretty, but it works.

The Rule

Next, we need a simple rule so that the Twine knows what to do when the sensor changes:

Pinky Status Twine Rule

When the sensor changes to open, two things happen. Firstly, I get an email, which I really only use for debugging and I should probably turn it off, except that it’s pretty fun to have that subject line appear on my phone when I’m out of the house.

Secondly and far more usefully, the Twine pings the URL of a very, very simple server that I wrote.

A simple service

Here’s the code, but it’s probably clearest to view an earlier Sinatra version than the current Rails implementation:

require "rubygems" require "bundler/setup" require "sinatra" require "data_mapper" DataMapper::setup(:default, ENV['DATABASE_URL'] || 'postgres://localhost/pinky-status') class Event include DataMapper::Resource property :id, Serial property :source, Enum[:manual, :twine], default: :twine property :status, Enum[:in, :out] property :created_at, DateTime def self.most_recent all(order: [:created_at.desc]).first end def self.most_recent_status most_recent ? most_recent.status : nil end def self.next_status if most_recent_status most_recent_status == :in ? :out : :in end end end DataMapper.finalize Event.auto_upgrade! get "/" do @events = Event.all @most_recent_status = Event.most_recent_status erb :index end post "/event" do Event.create!({created_at: Time.now, status: Event.next_status}.merge(params[:event] || {})) redirect "/" end

The key part is at the very bottom – as Twine makes a POST request, the server simply creates another Event record with an alternating status (‘in’ or ‘out’), and then some logic in the view (not shown) can tell us whether or not the cat is in or out of the house.

In more recent versions of the code I’ve moved to Rails because it’s more familiar, but also slightly easier to do things like defend against duplicate events (normally when the cat changes her mind about going outside when her head is already through the flap) and other peripheral things.

But don’t be dissuaded by Rails - it really was as trivial as the short script above , showing some novel information derived from the simple sensor attached to the Twine. Deploying a server is also very easy thanks to tools like Heroku.

Conclusions

A few hours idle work and the secret life of our cat is now a little bit less mysterious than it was. I really enjoyed how quick and painless the Twine was to setup, and I can highly recommend it if you’re perhaps not comfortable enough to dive into deep sea of Arduinos, soldering and programming in C, but would still like to paddle in the shallower waters of the “internet of things”.

interblah.net - index

index

  1. raw
  2. pre
  3. page_title
  4. link_to_current_snip
  5. link_to
  6. index
  7. debug
  8. current_snip
  9. test-code
  10. Site Test
  11. navigation
  12. feed
  13. disqus-commenting
  14. blog-li
  15. title-for
  16. snip-details
  17. show-dynasnip
  18. self
  19. search
  20. plus-one-button
  21. most-recent
  22. l
  23. kind
  24. in-template
  25. excerpt
  26. code
  27. blog-summary
  28. Vanilla
  29. vanilla-rb
  30. tutorial-renderers
  31. tutorial-removing
  32. tutorial-links
  33. tutorial-layout
  34. tutorial-dynasnips
  35. tutorial-basic-snip-inclusion
  36. tutorial-another-snip
  37. textile_example
  38. test
  39. soup
  40. snip
  41. markdown_example
  42. hello_world
  43. bad_dynasnip
  44. On Conferences
  45. Vestibule
  46. Spacemacs
  47. Ru3y Manor
  48. Robby Russell
  49. Doom Emacs
  50. Dokku
  51. Chris Roos
  52. Not all accusations are baseless
  53. Conversations are hard
  54. Weeknotes 2041
  55. Connoisseur
  56. This is for Patrick
  57. Don't cache ActiveRecord objects
  58. Two thoughts about maintainable software
  59. LGTM
  60. I am an omakase chef
  61. Back on the wagon
  62. Getting Started with Spacemacs
  63. Here's to the crazy ones (RailsConf 2018)
  64. Why is nobody using Refinements?
  65. Backing Up 2-Factor Authentication Credentials
  66. Notes on 'Notes on "Counting Tree Nodes"'
  67. Docker on your Server
  68. Reducing risk when running a conference
  69. Let me tell you a bit about what I'm doing
  70. The problem with using fixtures in Rails
  71. Is Ruby Manor X happening this year?
  72. Shooting errors with Raygun.io
  73. Monitoring our cat with Twine
  74. What happens when RSpec runs, or, what I think about testing with blocks
  75. The Postal Inter.net Office is shutting down
  76. Richard Paterson will kill you
  77. What happens when MiniTest runs, or, what I think about testing using classes
  78. Harmonia
  79. "A framework for making decisions"
  80. Ruby Manor 4 tickets sold out in about 12 hours, and it's great and worrying at the same time
  81. reevoo
  82. Tests as documentation for Kintama
  83. Weeknotes 1805
  84. Ruby Manor
  85. vi
  86. Setup vs. Action for Ruby tests
  87. Rerunning tests in Ruby
  88. Kintama
  89. Inventing on Principle
  90. Capturing behaviour in Ruby DSLs
  91. Bret Victor
  92. Blog posts I will never finish
  93. Looking ahead at 2013
  94. About this site
  95. head
  96. Harmonia Beta
  97. Ticketgate Redux
  98. Ticketgate
  99. Do we need Early Bird tickets?
  100. Ruby Manor is not an Unconference
  101. Future Visions
  102. Future Visions: Microsoft
  103. Future Visions: Ericsson
  104. Future Visions: Blackberry
  105. “Sponsor me to talk”?
  106. TDD in early-stage startups
  107. Some thoughts about Ruby Manor
  108. FreeAgent Widget for Mac Dashboard
  109. blog-layout
  110. layout
  111. 404
  112. start
  113. snip-excerpt
  114. site-information
  115. sidebar
  116. footer
  117. blog
  118. blog-template
  119. analytics
  120. gfr
  121. Why I am an Atheist
  122. I wish advertising didn't work
  123. Homoiconicity
  124. hashblue
  125. Free Range
  126. road-testing-macbook-air-day-two
  127. road-testing-macbook-air-day-three
  128. road-testing-macbook-air-day-ten
  129. road-testing-macbook-air-day-one
  130. On Testing
  131. Do We Need Any More Test Frameworks?
  132. vanilla-rb-tutorial
  133. tutorial
  134. Deploying Vanilla.rb
  135. How Interblah Works
  136. Timmy, Redux
  137. Hello, Timmy
  138. Twitter and the Federated Web
  139. Postal Inter.net
  140. Road Testing The 11" MacBook Air
  141. What's in your `~/.gem-this`?
  142. Another FreeAgent Widget Update
  143. Ralph Three, He Is Is Here
  144. Weeknotes - 1670
  145. Weeknotes - 1668
  146. Weeknotes - 1667
  147. Straying from the path
  148. Weeknotes - 1665
  149. Typekit and Legibility
  150. Thoughtbot Ruby Survey 2009
  151. Gratitude
  152. test_ajax
  153. adding ajax to vanilla
  154. update-soup
  155. Wake Remote Machine Automator Action
  156. FreeAgent Widget Update
  157. Rip & Gem Dependencies
  158. Gem This, now a Gem Command
  159. whats-happening-with-the-engines-plugin-comment-2
  160. regarding-plus-ones
  161. Accessing RDoc fast using Quicksilver
  162. things-that-I-think-when-reading-stuff-written-on-the-internet
  163. james
  164. Plugin Migrations
  165. Ajaxworld Presentation
  166. gem-this
  167. leave-a-comment
  168. TDD and the implementation it might drive
  169. sitemap
  170. rails-underground
  171. Rails Maturity Model
  172. Too Clever
  173. web-services-showing-which-clients-access-them
  174. Bad Science
  175. On Commenting
  176. On RSpec
  177. links
  178. Rails Biz Conf
  179. Ruby Manor Videos
  180. Vanilla.rb
  181. Multi-User Gnu Screen
  182. Exporting from Stikkit
  183. leaving-reevoo-comment-1
  184. Ruby Manor was a success!
  185. Leaving Reevoo
  186. Ruby Manor is GO!
  187. fringe-tv-show
  188. syntax-highlighting-demo-comment-2
  189. home-computer-setup
  190. defensio-to-the-rescue-comment-3
  191. defensio-to-the-rescue-comment-2
  192. defensio-to-the-rescue-comment-1
  193. active-record-ideas
  194. Defensio
  195. Defensio to the rescue
  196. Ruby Manor
  197. murray-steele
  198. whats-happening-with-the-engines-plugin-comment-1
  199. And what of the Engines plugin?
  200. engines-fear-uncertainty-and-doubt
  201. syntax-highlighting-demo-comment-1
  202. Wham, Bam, Thank You Spam!
  203. Syntax Highlighting
  204. radiant-cms
  205. rails-engines
  206. reasons-i-love-vanilla
  207. Vanilla
  208. vanilla-rb
  209. Mashed 2008
  210. Comments Are Alive!
  211. out-of-focus-group-11
  212. mashed-2008-comment-4
  213. mashed-2008-comment-3
  214. Reevoo Labs Lives!
  215. luke-redpath
  216. dynasnip
  217. mashed-2008-comment-2
  218. mashed-2008-comment-1
  219. more-vanilla-tweaks-comment-2
  220. more-vanilla-tweaks-comment-1
  221. comments-are-alive-comment-2
  222. More Vanilla Tweaks
  223. comments-are-alive-comment-1
  224. already-we-have-vanilla-goodness-comment-4
  225. already-we-have-vanilla-goodness-comment-3
  226. already-we-have-vanilla-goodness-comment-2
  227. already-we-have-vanilla-goodness
  228. Zuul and Code Etiquette
  229. already-we-have-vanilla-goodness-comment-1
  230. Welcome to Vanilla
  231. random-line-from
  232. site-taglines
  233. soup
  234. snip
  235. I'm Such a Fool
  236. Never Let Me Design a Logo
  237. A Tale of Three Modules
  238. Conferences 2007
  239. durian-fruit-is-like-hell-in-your-mouth
  240. Stikkit Dashboard Widget
  241. Rubyfools, Redux
  242. Ruby and Leopard
  243. Shared Hosting is Alright
  244. lighthouse_ticket
  245. ihatebe.es
  246. Backchat
  247. Thanks, Feedburner
  248. LRUG Logostrosity