Using Ross Dashboard and the Companion Satellite API to create a virtual touch surface on a Ross Video Ultritouch

My church, Fellowship Greenville, has been building a second campus now for a little over a year. It’s been an exciting process. The new auditorium will feature a control room much like what we have at our existing campus.

One of the newer pieces of equipment that we are putting in is a Ross Video UltriTouch HR. It’s a 2RU touch screen computer essentially, running Ross Dashboard. (I’ve written about Ross Dashboard before if you want to read about any of those.) Dashboard is a very flexible program that lets you program very custom interfaces to control your gear. We used it heavily until I started investing a lot of time toward Companion.

Once I knew we were getting one of these, I knew right away that I wanted to be able to use it as a satellite surface for Companion. Taking what I learned from my ScreenDeck project, and my OGScript knowledge (Ross’s flavor of Java/JavaScript that powers the custom panels in Dashboard), I was able to make this:

It was pretty easy to get simple buttons with text on them, and get the colors of the buttons to match Companion button colors. But I wanted the buttons to look like Companion buttons, and that took some work. Dashboard doesn’t have any image editing libraries that I was aware of, so I had to get creative. The image data coming from Companion is base64 encoded 8-bit RGB. I reached out to the Ross staff on their forums and they quickly got back to me with a helpful decoder function. It was similar to the one I had already written to decode the base64 encoded text data that comes from the Companion Satellite API.

Once I was able to decode it back to the binary RGB data, it was “simply” a matter of writing a function that saves these as bitmap files in a folder local to the panel and then changing the style of the button to show the new bitmap image.

And there we have it! I’m looking forward to using this on our UltriTouch as well as the TouchDrive touch screen as well.

The panel supports turning the bitmaps on/off, setting the button size, total keys, keys per row, and of course the IP/port to Companion. The satellite port is changeable on the Dashboard side but is currently fixed in Companion to 16622.

If you’re a Ross Dashboard user and want to tinker with the panel, I’ve made it available via Github on my RossDashboardPanels repository where I have shared some other panels as well.

If you ever need any custom Dashboard panels created (or Companion modules!), I do this for hire on the side to support my family. You can reach out to me via my website, josephadams.dev.

Sending OSC messages from Ross Dashboard

Just thought I would share a quick custom panel that shows how to send OSC from Ross Dashboard to other devices.

If you’re not familiar with OSC (Open Sound Control), you can read about it here. Essentially, it is a protocol used for real-time communication between (typically) media devices, synthesizers, etc. It has grown to be used by a wide variety of software for remote control purposes.

To send a message, first a byte array must be constructed. In Dashboard, the easiest way to do this is to use a messageBuilder object and then convert it to a byte array at the end.

function createOSCMessage(cmd, val, varType)
   {
      var messageBuilder = ogscript.createMessageBuilder();
      var len = cmd.length+1;
      var pad = (4 - len%4)%4;
      messageBuilder.writeString(cmd);      
      
      // put null terminator at end of command string
      messageBuilder.writeChar(0); // null terminator
      
      // pad end of command string with nulls
      for (var i=0; i<pad; ++i) 
      {
         messageBuilder.writeChar(0);
      }

This creates the message builder object, inserts the OSC command, and then pads the rest of the bytes with nulls. The command byte must be a multiple of 4, so the pad is calculated.

Next, the type (float, int, or string) is determined and the value applied:

     // set the 4 bytes that identify the format
     messageBuilder.writeChar(',');

     if (varType == 'float')
     {
          messageBuilder.writeChar('f');
          messageBuilder.writeChar(0);
          messageBuilder.writeChar(0);
          messageBuilder.writeFloat(val);
     }
     else if (varType == 'int')
     {
          messageBuilder.writeChar('i');
          messageBuilder.writeChar(0);
          messageBuilder.writeChar(0);
          messageBuilder.writeInt(val);
     }
     else
     {
          messageBuilder.writeChar('s');
          messageBuilder.writeChar(0);
          messageBuilder.writeChar(0);
          messageBuilder.writeString(val);
     }

     return messageBuilder.toByteArray();
}

The resulting byte array is returned to the function that called it.

To send a float:

function sendOSCMessageFloat(ip, port, cmd, val)
{
     ogscript.sendUDPBytes(ip, port, createOSCMessage(cmd, val, 'float'));
     ogscript.debug('OSC Float Sent');
}

var host = '127.0.0.1';
var port = '12321';
var oscCommand = '/command/float';
var oscFloat = 1.1;
sendOSCMessageFloat(host, port, oscCommand, oscFloat);

To send an int:

function sendOSCMessageInt(ip, port, cmd, val)
{
     ogscript.sendUDPBytes(ip, port, createOSCMessage(cmd, val, 'int'));
     ogscript.debug('OSC Int Sent');
}

var host = '127.0.0.1';
var port = '12321';
var oscCommand = '/command/int';
var oscInt = 1;
sendOSCMessageInt(host, port, oscCommand, oscInt);

To send a string:

function sendOSCMessageString(ip, port, cmd, val)
{
     ogscript.sendUDPBytes(ip, port, createOSCMessage(cmd, val, 'string'));
     ogscript.debug('OSC String Sent');
}

var host = '127.0.0.1';
var port = '12321';
var oscCommand = '/command/string';
var oscString = 'TEST';
sendOSCMessageString(host, port, oscCommand, oscString);

That’s it! Pretty simple using the message builder and byte array.

I’ve made the custom panel available on Github.

Using the iOS Shortcuts app to automate production workflows

I love automation. I love making things more efficient and consistent, and I’ve found that on a particular level, automating or simplifying certain tasks through automation can make it easier for volunteers when working in a church production environment.

The latest app that I’ve been enjoying is the iOS “Shortcuts” app that was added to my phone in a recent iOS upgrade. It allows you to use actions within apps or activity on your phone to spawn other actions. Things like “Text my wife how long it will take me to get home, when I leave work” by using the GPS location on my phone. Or, make a shortcut that when you take a picture using the camera app, it is automatically posted to Facebook.

1200x630wa
Look for this app on your iOS device.

If you’ve ever used the service IFTTT, you’ll find familiarity with the Shortcuts app in some of the concepts. Of course, the integration into the phone at a core level with Shortcuts is much nicer. One thing I particularly like is that, once you name a shortcut, you can simply say, “Hey Siri, [shortcut name]” and it will run it.

And, Shortcuts can make HTTP requests (GET, POST, with JSON, etc.) as actions. So, it’s super easy to add a shortcut that triggers a Companion button or a task in a Ross Dashboard custom panel, for example. And that’s one of the ways I’m using the Shortcuts app.

In our production workflow, we use Ross Dashboard custom panels that I created to control nearly every aspect of our video system (and slowly, audio and lighting as I create the connections). It’s very easy to trigger a button via HTTP request, so I set up several shortcuts that I can use to save me time, especially when I am away from the production area or not near a computer running one of the Dashboard panels, as long as my phone is connected to the production network wifi (or I’m connected via VPN if remote).

Photo Nov 18, 2 22 59 PM
Here are a few of the shortcuts I’ve created.

Photo Nov 18, 2 23 21 PM.png
All this particular shortcut does is make an HTTP GET request to my master Ross Dashboard Custom Panel, which is listening to Port 5400, and triggers the GPI, “aud1_psl”.

Screen Shot 2019-11-18 at 2.23.52 PM
It’s the same as clicking on this yellow button, but I can run it from my phone, as long as I am connected to the production network!

So, just like that, it’s very easy to do something like this: “Hey Siri, go to Pre Service in Auditorium 1”, and have all of the lights change (by sending a midi-relay command to a MIDI Show Control message to our Vista lighting console) and the program screens go to the pre-service loop (by sending a RossTalk command to execute a custom control on the Carbonite to change inputs).

Here’s a video of it in action!

[wpvideo URjPHb4M]

Go check out the Shortcuts app if you aren’t using it already in your production workflow!

Server-based countdown clocks with multiple client viewers using Node.js and a Raspberry Pi

A few months back, I shared about the client-side countdown clock script that I created for our team to use. It worked pretty well for its purposes, using Dropbox as the platform to share and update data between the computer creating the clocks and the computer viewing the clocks. The initial goal was to create something that required no backend server and would be easy to run on any computer.

It served us well but we quickly outgrew it with the desire to be able to publish clocks in realtime, not simply relying on the viewer client to refresh itself every 15 seconds to look for new data. So, I created a server based solution using Node.js.

I decided I wanted to run this project on a Raspberry Pi 3 B+, so I picked up this kit on Amazon. I wanted an easy way to spin up a web server that wasn’t tied to any production machine, and this does a great job.

img_7113
Here is the Raspberry Pi 3 B+, neatly installed in one of the video racks. I’m using the HDMI output and converting it to SDI to go into our video system.

Dubbed TimeKeeper, this project runs an Express web server within Node and has a REST API, which allows the user to poll for existing data as well as create new entries. As new entries are added, they are sent out to all connected clients in real time using the socket.io library.

Screen Shot 2018-11-29 at 2.08.23 PM
Here is a screenshot of a web browser client. This is actually running on the same Raspberry Pi that is hosting the Node.js server, with Chromium in kiosk mode.

Rooms:
Rooms allow you to control and specify which timers appear. This is helpful if you are running clocks in multiple venues or instances, and only want certain timers to appear on certain viewer screens.

Timers:
Timers are the objects that TimeKeeper will count down to, based on the viewer’s current local system time.

Messages:
Messages can be sent and displayed on viewer clients.

After implementing the API, I created a Dashboard custom panel to interact with the server. This serves as the primary interface for our volunteers. Because the panel fetches new data from the server on a recurring schedule, multiple computers can have the panel open and all stay in sync about what timer and message objects are currently being displayed.

Screen Shot 2018-11-29 at 2.09.55 PM
Screenshot of the custom panel in Dashboard.

We’ve been using this software for a few months now and it’s working great! I intended to write about it sooner, but with a busy work and family life, finding time to write for this blog can be a challenge!

The next version will support trigger actions when clocks hit a specified time or run out. I also plan to integrate with other clock systems to show time left on video playbacks, Planning Center Online, etc., when I have the time!

If this is useful or helpful to you, I’ve made it available on my Github repository.

Controlling a Wifi Plug over the network using TCP Messages

We recently purchased some TP-Link HS100 Kasa Smart Wi-Fi Plugs to allow us to remotely turn on speaker amps to support our outdoor speaker systems. Turning the amps on each time by going to the physical amp location in the racks located all across the campus was very inconvenient, so this was a great upgrade.

HS100(US)2.0-package_1508143441338j.jpg
This is what the plug looks like.

It pairs with an app called Kasa to allow you to turn the outlets on and off pretty easily, however in our testing, we couldn’t get it to work with more than one smartphone. Plus, we didn’t want volunteers to have to install this app on their phone, or provide a phone just to run this app.

The TP-Link protocol has been reverse engineered pretty well, so I had hopes that this would be a quick and easy project, and it was! The core protocol uses JSON to communicate, however it is obfuscated heavily to the user and you have to send a hexadecimal payload to it in the end in order to trigger an action.

Once we set up the devices as recommended through the app to use our internal network WiFi, I had our IT department create IP address reservations based on the MAC addresses of the outlets, so that they would always have the same IP address. If you use these plugs, I recommend doing that in your setup as well.

Then, I researched the protocol and figured out what the hexadecimal payloads needed to be to power it on and off. I didn’t really care about any of the other status settings. Just a simple on and off.

Here is the function needed to do that, written in ogScript for Ross Dashboard:

function tellOutlet(address, port, protocol, command)
{
    var enabled = ogscript.getObject('outletEnabled');

    if (enabled)
    {
        switch(protocol)
        {
            case "TPLINK-HS100":
                var payload_on_hex = "0000002AD0F281F88BFF9AF7D5EF94B6C5A0D48BF99CF091E8B7C4B0D1A5C0E2D8A381F286E793F6D4EEDFA2DFA2";
                var payload_off_hex = "0000002AD0F281F88BFF9AF7D5EF94B6C5A0D48BF99CF091E8B7C4B0D1A5C0E2D8A381F286E793F6D4EEDEA3DEA3";
                  
                var sendCommand = "";
                  
                if (command == "on")
                {
                    sendCommand = payload_on_hex;
                }
                else if (command == "off")
                {
                    sendCommand = payload_off_hex;
                }
                                 
                rosstalk.sendAsBytes(address, port, sendCommand, callback);
                ogscript.debug("Outlet turned " + command + ".");
                break;
            default:
                break;
        }
    }
}

The key function here is the RossTalk SendAsBytes command which sends the TCP message as hexadecimal data.

Once I did a test and was satisfied it was working properly, I built out custom panels that use our master production control system, so now volunteers can easily turn the amps on or off by just clicking a button!

I also built a stand-alone version in case anyone else could benefit from it.

Screen Shot 2018-07-25 at 4.06.54 PM.png
The buttons are first disabled when you open the panel until you’ve configured the outlet in the setup tab.

Screen Shot 2018-07-25 at 4.07.00 PM.png
In the setup tab, you can configure the outlet IP address, the port (the default is 9999), and choose the protocol. Currently, the panel only supports the TP-Link HS100/101 models.

Screen Shot 2018-07-25 at 4.06.42 PM.png
Just click On or Off to toggle the outlet!

The panel is up on my Github repository, if you’d like to download it.

Two Quick Updates

Just two quick updates, if you are using my software.

First, I’ve added a couple more features to the Countdowns/Clock system. You can now have a custom name for each countdown, which is pretty helpful. And, the page now displays a progress bar/meter that shows how long until the next page refresh, which has been increased to 15 seconds.

Screen Shot 2018-07-02 at 3.05.06 PM

Second, my VideoHub custom panel for Dashboard will now auto detect how many inputs/outputs you have on your router, which is mainly used for building out the drop down lists of inputs and outputs to choose a route.

Hope this helps! You can get the latest versions on my Github repository.

Customizable Clock and Countdowns for Production, in a Web Browser, Part 2

A quick update on this post.

We used this in production this week and it worked great! I decided quickly though that this needed some form and style, not just function.

Screen Shot 2018-06-25 at 7.54.31 AM

I also added the ability to be able to send a custom message to the screen!

Screen Shot 2018-06-25 at 7.52.58 AM

The two buttons, “Send to Screens” and “Screens Back to Normal” in this panel are for my team, we use them to control MiniMEs on our Ross Carbonite switchers that send to our confidence monitors in the auditoriums.

I’ve updated the files on Github, if you want to go grab them!

Customizable Clock and Countdowns for Production, in a Web Browser

Accurate clocks and countdowns can be a huge help when it comes to keeping services and productions on time. In our control rooms, we use these clocks:

943

They’re made by a company called ESE and they are basically network-based POE-powered NTP clocks. Because they are synced to NTP (Network Time Protocol), they are all in sync to the exact same time down to the second. We like them because they are big and grab your attention. We have them mounted above the multiviewers in each control room along with a couple of others in the actual tech booths out in the auditoriums.

But what about everyone else, like the band or people on stage? We don’t have clocks like this where they can easily see. And, the ESE clocks just tell the time, they don’t count down to a specific time.

I decided to do something about that. We have a server in the video rack room that has a video out connection into the video systems. It’s just a simple output of the secondary monitor. So, I figured it would be pretty easy to display a clock in a browser, and run it full screen on that secondary monitor, that feeds into the video router where I can then easily send it to any screen in the system that needs it.

I found some examples online and eventually came across this article where someone had created a full screen clock: https://www.nayuki.io/page/full-screen-clock-javascript

clockThis computer’s time is synced to NTP, so it stays in sync with the clocks in the control rooms, too.

I quickly decided to take this a step further and incorporate some countdowns. I had a couple of self-imposed restrictions though:

  1. I wanted the countdowns to be customizable as our needs change, not just always count down to the same date/time.
  2. I didn’t want to run a web server just to accomplish this, in order to pass new data to the locally running page/JavaScript.

I decided an easy method would be to have a separate JavaScript file that defines some countdown data, and include that in my main clock page, and just refresh the page to get the new data. I set the page to reload every 30 seconds by putting this in the <head> of the HTML:

<meta http-equiv="refresh" content="30">

I want my volunteers to be able to easily change this countdown data, without having to know JavaScript. Time for Dashboard! My directors have a Dashboard Custom Panel that I created for them which they use every week. It has a myriad of control options for them, so it was simple to just add another tab for the new countdowns.

countdowns_

Dashboard has a built in date picker and time picker, which makes it super easy.

I added two options in addition to the date and time, publish time, and expire time.

countdowns_publishtime
I limited it to these few options, between 2 minutes and 7 days. This determines when the countdown will appear on the screen.

countdowns_expiretime
When a countdown expires, it turns red so it grabs your attention.

When the user clicks, “Update”, it runs a simple function that grabs all of this data, writes the JavaScript into a string, and then saves that into a file using the ogscript.saveToFile function. The file is saved to a common Dropbox folder that the server running the web page clock has access to.

countdowndata

clock-and-countdowns.png
Here it is in action. The countdowns automatically update when the page reloads every 30 seconds.

 

I’ve made the files available on my Github, if you can benefit from them! We will be giving this a trial run on Sunday.

Triggering Wirecast Remotely using Elgato Stream Deck

Wirecast is a great tool for live streaming. At Fellowship Greenville, we use it as our encoder to stream to YouTube Live, whether it be the regular Sunday morning sermon live stream, or for special events, conferences, funerals, etc.

Lately, I’ve been working specifically on some improvements to make it easier for me to operate a live stream from our second auditorium, where we typically host funeral services and special events. Our live stream server is located in our control rooms in the main building, so when I am working tech for an event in the second auditorium, I am completely separated from the control rooms.

For regular Sunday services, that’s not a problem to be separated because we have a great team of volunteers working in both areas who stay in communication with and support each other. But for smaller services like a funeral, where it is typically only me and one other staff member running everything, it can be challenging to run a full production while I am sitting in the tech booth, far away from the control room areas where the live stream server and video switcher are located.

This is where my Stream Deck Production Controller software is going to be a great help. I have created a button set that allows me to send RossTalk commands to the Ross Carbonite switcher, change the necessary routes on the BlackMagic VideoHub router, and start/stop the Wirecast live stream.

IMG_5668.JPG-1.jpeg

So how does this work? The Stream Deck software is sending a GPI trigger request to Dashboard, where I have these buttons in my production control custom panel:

Screen Shot 2018-06-15 at 11.18.59 AM

Clicking the “Wirecast – Start Streaming” button runs a custom ogscript function that runs this AppleScript:

Screen Shot 2018-06-15 at 11.23.04 AM

And that’s it! By using the existing infrastructure I’ve designed for our production control, I’m now able to easily run the live stream but still maintain high value in what is streamed. By using the stream deck to operate not only Wirecast, but the video switcher remotely, I can change sources as needed, play videos, show cameras, etc. I even have a button that jumps to my PTZ camera control where I can recall presets that I’ve designed specifically for special events like this!

My Stream Deck software is available on Github if you would like to use it, and feel free to reach out if I can help!

Controlling BlackMagic VideoHub from Ross Dashboard, Part 2

In Part 1 of this post, I wrote about the technical side of how to use Ross Dashboard to send a TCP message to a Blackmagic VideoHub video router.

I thought I would expand on that recently and now I have made available a panel that, when set up with the IP address and port of the router, will automatically load the input (source) and output (destination) names into dropdown lists where the user can easily choose a source and destination to make a route.

Screen Shot 2018-06-14 at 2.32.25 PM

Screen Shot 2018-06-14 at 2.32.39 PM

Screen Shot 2018-06-14 at 2.32.31 PM

It’s up on my Github respository if you can benefit from it!