Skip to content

Instantly share code, notes, and snippets.

@stephenyeargin
Last active April 27, 2017 11:41
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stephenyeargin/29c6e3a22fb86f6961ac to your computer and use it in GitHub Desktop.
Save stephenyeargin/29c6e3a22fb86f6961ac to your computer and use it in GitHub Desktop.
Using Dashing with Hubot to control which dashboard is being shown.

Remotely control your Dashing Dashboard

The problem

We have a dashboard at the office that displays some internal company metrics so everyone can be up to speed on them. However, when we have guests, we have to either SSH into the Raspberry Pi or simply turn off the television. This seems clumsy, and we can do better than that.

The solution

Dashing works by adding event listeners in Javascript and updating the associated widgets. We're going to hijack this process to build a simple redirect that can accept a posted value and send the dashboard to another screen.

Adding the code to dashboards/layout.erb

We're adding it here so that every dashboard has a listener available.

<script>
  // Redirect handler
  (function() {
    var delayInSeconds = 5;
    var pageLoaded = Date.now();
    var source = new EventSource('events')
    source.addEventListener('message', function(e) {
      var data = JSON.parse(e.data);
      if (data.id === 'redirect' && typeof data.location != 'undefined') {
        if (data.updatedAt - pageLoaded/1000 > delayInSeconds) {
          window.location = data.location;
        } else {
          console.log('Refresh was too fast (or initial page load).');
        }
      }
    });
  })();
</script>

You will see that the delayInSeconds is configurable. The initial load of the page (if you have previously used the redirect) will be sent along as well, and you don't want to get it stuck in an infinite loop. This simply tells it to ignore any command if it was received less than 5 seconds ago. You can up or decrease this amount of time, but in most cases this should be fine for the stated use case.

The important part of the script above is that we have reserved the redirect event type.

Controlling the Dashboard

To demonstrate how to do this (you probably will have a different mechanism for actually controlling it), here is a simple cURL command:

curl -d '{ "auth_token": "yourauthtokengoeshere", "location": "/dashboard_1" }' \http://localhost:3030/widgets/redirect

This is taking a JSON string and posting it to a non-existent widget (we never created one). You will want to change the host to your Dashboard and its running port. The auth_token is configured in config.ru, such as:

configure do
  set :auth_token, 'yourauthtokengoeshere'
  ...

Bonus: Control it with Hubot

Here is a simple Hubot script that does the commands above. You can customize it to match your dashboard naming scheme. This one assumes you've named them dashboard_[0-9]+ and have another one called dashboard_off.

# Description:
#   Control the Dashboard
#
# Configure:
#   TV_HOST - Path to the dashboard
#   TV_AUTH_KEY - Auth key for the dashboard
# Commands:
#   hubot tv off - send television screen to particular dashboard
#   hubot tv on - send television screen to the default screen
#   hubot tv <number> - send television to a specific screen

module.exports = (robot) ->

  # Turn "off" television
  robot.respond /tv off/i, (msg) ->
    goToDashboard msg, '/dashboard_off'

  # Turn "on" television
  robot.respond /tv on/i, (msg) ->
    goToDashboard msg, '/dashboard_1'

  # Send television to a specific screen
  robot.respond /tv ([0-9]+)/i, (msg) ->
    goToDashboard msg, "/dashboard_#{msg.match[1]}"

# Send television to a specified dashboard
goToDashboard = (msg, dashboard) ->
  try
    data = JSON.stringify({ 'auth_token': process.env.TV_AUTH_KEY, 'location': dashboard })
    msg.http("#{process.env.TV_HOST}/widgets/redirect")
      .post(data) (err,res,body) ->
        console.log 'body', body
        if !err
          msg.send "Television changed to '#{dashboard}'"
        else
          msg.send err
  catch error
    console.log error
    msg.send "Unable to connect to television."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment