Subscribing to DigiLinX

As a developer who is interested in working with the NetStreams DigiLinX infrastructure, you have two basic integration options. This blog has focused mostly on the first option, which is to develop Lua drivers that allow the DigiLinX system to issue commands to an external system. A good example of this is the Proliphix driver I recently published.

The other option, which I haven’t yet covered on this blog, is to communicate with DigiLinX using their ASCII protocol. DigiLinX devices communicate with each other by broadcasting specially formatted ASCII instructions to a multicast address, allowing other devices who are interested to “tune in” for updates. These messages contain data that contains either control or status information. My DigiLinX debugger works in this fashion, listening for all debug messages that arrive at the multicast address.

But what if, as a third party system, we’re not interested in every message that is sent across the wire? What if we’re writing an application that simply wants to know when a song on a stream has changed or when a specific SpeakerLinX amplifier has been turned on? DigiLinX offers us an alternative solution in this case. Using Dealer Setup, one can configure what NetStreams refers to as a “subscription”. By providing an IP address and port number, the integrator can direct the DigiLinX system to sent ASCII messages to a device using UDP. The integrator can further specify what they are interested in by subscribing only to those services which interest him. Let’s look at an example.

Setting Up A Subscriber

My goal for this exercise is to be alerted whenever an event occurs within an amplifier in one of the rooms. Maybe I’d like to shut off one amplifier when another one is turned on. Maybe I’d like to update a UI with the current volume level in each room. Maybe I just need an example.

In this test project, I have one SL220, one TL380, and a CL100. I’ve also added a dummy SL220 to give my system interface a second room.

Project List

I’d like to configure my development machine as a subscriber. I’ll write code that listens on a specific port for messages arriving from the Digi system. To do this, from within Dealer Setup 2.2 I click Tools -> Edit Subscribers. I see the following screen (click to expand):


As you can see, I’ve specified that my development machine Silver, with an IP Address of, will be listening on port 10590 for messages from the Bedroom and Study player services. There are other services available to me as well, but they’re outside of the scope of this post. For more information on which services are made available by which devices, refer to the DigiLinX Programming for 3rd Party Control document available in the dealer area on

Once my machine is subscribed, I’ll send the updated configuration to the devices and wait for them to restart. When they do, status updates will start being delivered to my machine for the services I’ve subscribed to. Let’s see what they’re saying to me by writing code to listen on that port.

A Basic Client

I’m going to throw together a basic client that simply dumps the arriving messages to the console. Using Visual Studio.Net, I’ll create a new C# Console application. Visual Studio creates a default Program.cs file with a static void Main method in it. This is the code that will run automatically when the console app is executed. I’ll stub out a method call:

private static void Main(string[] args) {

Now I have to write my TestSubscriber method. It need to:

  1. Open a socket and bind to port 10590 (the subscriber port)
  2. Create a buffer that’s large enough to handle the incoming messages
  3. Tell the socket that we want the next arriving UDP packet and then
  4. Write it to the console.

Easy enough, since I do much the same thing with my DigiLinX Debugger. Sorry about the formatting:

private static void TestSubscriber() {
  Socket aSocket = new Socket(AddressFamily.InterNetwork,

  IPEndPoint anEndpoint = new IPEndPoint(IPAddress.Any, 10590);
  char[] myTrimChars = new char[] {”, ‘\n’, ‘\r’};

  while (true) {
      byte[] buffer = new byte[8192];
      int numBytes = aSocket.Receive(buffer);
      Console.WriteLine(“{0} – {1}”,

And there you go – that’s all the code you need to act as a subscriber. Fire it up, press a few buttons on the TouchLinX while listening to audio, and you’ll see the following:

Subscriber Output

All that’s left now is to write some code to parse the messages, looking for those that interest you. Again, information about the formatting of these messages can be found in the Programming for 3rd Party Control document published by NetStreams. 


Lots of Updates!

I just released updates to the following:

DigiLinX Debugger – look for a lot more stability, as well as some more advanced logging and filtering options. I feel like I’m close to a 1.0 release, having squashed a few bugs that have been bothering me for some time.

HTTP Library – Yup, another release today. This is a good one, as I managed to catch a number of edge case bugs and smack them down. I also did some code readability updates and improved some tracing output. I’ve had this running in a dev environment for days, being called every 10 seconds, and my ControlLinX hasn’t caught fire.

Proliphix Driver – This is the target I’ve had in my sights for some time now. With the HTTP library finally stabilizing, I’ve been able to wrap this bad boy up into an alpha release. Want to play but don’t have a Proliphix thermostat? No problem – you can use my Proliphix emulators on an XP or Vista machine that has Internet Information Services installed and fool Digi into thinking that it’s talking to a live thermostat.

The Proliphix driver is definitely an alpha build, but I wanted to get a release out to the community for a couple of reasons. First, I wanted to draw a line in the sand and declare the driver to be ready for general consumption. This should help me version in future changes at a regular pace. Second, I’ve had a number of direct requests for the driver, and I’ve seen a couple of questions on the forums about the feasibility of integrating another HVAC vendor.

I’ve also started another CodePlex project to host the Http and Proliphix assets. Version management for plain text code files is a pain without something like CodePlex, and I wanted to be sure that people were always using the proper version of my drivers.

That’s it! Have at them!

A Proliphix thermostat driver for NetStreams’ HVAC interface

The DigiLinX system has a nice looking interface that allows users to monitor and control the current status of their HVAC system. The screen’s appearance and layout make it one of the more compelling features of the Digi system. Unfortunately, it was built to support the AprilAire line of automated thermostats. I’ll resist my compulsion to lambaste the AprilAire system, but as a whole it

  • costs a heckuva lot to put together because of the cost of the individual parts, and the number of devices required to make it work
  • only offers setback programming if you purchase a “system controller” which can cost consumers ~$850. This is amazing – several thousand dollars into an install you may find that you can’t turn the A/C off when you go to work every day unless you do it manually at each thermostat.
  • has been reported that it occasionally stops responding to third party system commands, including NetStreams, Crestron, and AMX
  • offers no remote administration or interface without the part mentioned above

Anyway, it’s safe to say that I’m not a fan. At all. I suppose it could be that pile of thermostats, controllers, and temp sensors that I have sitting in the corner of my office. I ripped it out of my home after the above points came to light when I began testing the Digi integration. A nice lesson that only cost me ~$1500. Yes, I’m bitter.

Enter Proliphix

But good things come to those who hate overpriced crap! I discovered the Proliphix line of thermostats when looking for a replacement for my AprilAire system. Proliphix thermostats are great, and include the following features:

  • They are IP based, like DigiLinX, and require no central brain to operate.
  • They have an embedded web server that enables remote monitoring, setback scheduling, and the ability to set vacation cooling schedules
  • They have a fully documented open API that is based upon the open standard of Http
  • They offer advanced features found in top quality systems, such as humidity monitoring, remote sensors, and alarms
  • They have a free service that allows you to monitor all your thermostats while away from home. The thermostats report to a central server stored at Proliphix, and you can pull up a dashboard in a web browser from anywhere.
  • They are competitively priced for the feature set that they provide

More good news for those of you who have wired for an AprilAire system – they use the same cabling approach. A Cat-5 run back to a head end connects the thermostats to a mini hub which provides network access and Power Over Ethernet to the devices themselves.

So once I decided on Proliphix, I went to work on writing a driver to tie the HVAC interface found in DigiLinX to the API made available by Proliphix. The API allows a programmer to retrieve and configure many of the settings and statuses related to the HVAC system. By sending simple HTTP POSTs to a device, one can change the setback temperature, query for current zone temps (both local and remote), determine if the fan is running, and more. The API is secured with a username and password configured when you first install the thermostat, which you pass along with your commands using the Basic Authentication scheme. I adopted an implementation of HTTP from LuaSocket, which I’ve posted on my projects page. This library allowed me to focus on the basics of the API in my driver implementation.

Driver Design

I won’t get into the details of how the driver works in this post, but I wanted to point out one design decision that I made. Since a home usually has more than one thermostat in it, I broke the driver into two files. The first, pro.lua, is simply the setup and scheduler for the implementation. It is responsible for binding to the thermostats during the initial load, and then scheduling and executing the status updates.

The second part of the driver is a module that marries the Proliphix API and the DigiLinX system. ProliphixAdapter.lua is self-contained, and is an implementation wrapper for a single thermostat. The host driver (pro.lua) actually creates one adapter for each thermostat in the system. This gives good code isolation, and makes it easier to determine which thermostat is generating trace messages.

I plan to write more posts in the future explaining how the driver works, especially if I see questions from the community on it.

Caveats and Configuration

Since this driver was not built by NetStreams, you must configure it manually by editing the text of the driver file. In pro.lua you will see  the following code:

thermostatIPlist = {“″,””}

Replace the list of IP addresses with the IP addresses of the thermostats that are installed in the home. You should ensure that the thermostats are on the same subnet as the DigiLinX system, and that a patch cable connects the SwitchLinX to the POE hub that the thermostats are wired to. You will also want to replace the username and password values with the admin username and password for your Proliphix thermostats. Note that all thermostats must have the same username and password configured. That’s is for pro.lua, unless you want to flip debugging categories on and off.

ProliphixAdapter.lua doesn’t require any configuration if you have Proliphix thermostats installed. However, the driver also supports using the asp emulators I developed during the authoring of this driver. If you would like to use these instead, drop them in the root of the web server for the development machine that will emulate the Proliphix thermostat, and change the doDebug in proliphixadapter.lua variable from false to true. Note! The drivers ship in Debug mode!

Read the comments at the top of both files for more information on driver assumptions and caveats.

Lastly, here is a list of all the files that will need to be installed on the ControlLinX that hosts the HVAC interface. You’ll need to use the Dealer Setup “Load Files ” feature, as explained in my Sample HTTP Driver posting to download them all. As I mentioned, the actual driver to use as the Driver File for the ControlLinX is pro.lua.

  • http.lua
  • httpPrivate.lua
  • url.lua
  • ProliphixAdapter.lua
  • pro.lua

Don’t Skip This Section!

I hope everyone who downloads this driver reads this first: I’m releasing this driver before I get it fully working. Yes, that’s right – the driver only works a little. Occasionally. My decision to release this was based upon wanting to help people understand the HVAC interface, and to offer more code samples to the DigiLinX development community. This driver should be treated as an alpha build, and should not be installed at a customer location. If you want to play with it without installing a Proliphix ‘stat, you can run it against the Proliphix emulator I wrote in classic ASP.

Also, these drivers contain a ton of debugging messages. The sheer volume of messages introduced into your network may have some adverse effect on your Digi system. When I feel that the drivers are stable enough, I will maintain two versions of each of these files – one that has debugging stubs left in, and another that doesn’t.

This driver is the result of a lot of work, so I’d really appreciate any feedback, bug reports, or overall comments from those who use it.

More information on where to obtain the drivers can be found on my projects page.

New Version of Http Support Modules Released

Technorati Tags: ,,,

I just posted an updated version of the Http LUA modules for NetStreams support on my projects page. The new version handles a few things better, including an offline server.

This is in preparation of the upcoming release of a beta version of my Proliphix driver in the near future.

I Are In Control. Or Not. – IRLinX Tracing

Technorati Tags: ,,

Got this tidbit of information from NetStreams today while working with someone on my IRLinX reliability issues. It is possible to switch on a flag that provides additional output tracing information between the IRLinX and the host SpeakerLinX.

First, use the socket generic tool to connect to the host SpeakerLinX. Then send the following command to the SpeakerLinX:


I haven’t had a chance to test it yet, but I’ve been told that this flips on some extended tracing. To turn the extended tracing off, send:


As a side note, it appears that the problems I’ve experienced controlling Digi from my T4 are related to noise that’s produced by the RP-6 when trigger commands are sent from the T4 to the RP-6 using RF instead of IR. NetStreams is working on a fix to filter out the extra noise. I hear they’re also working on filtering out extra signals from certain plasma displays. I hope these changes make it to a firmware update soon.

I Are In Control. Or Not. – Volume Control

This is the second posting in a series about controlling DigiLinX with IR. It assumes that you are familiar with the system that I described in my original post in this series, as it makes reference to rooms and devices described in that posting.

The Challenge

Working with a single IRLinX at the head end introduces a challenge with volume control. The published Mute, Volume+ and Volume- IR commands for DigiLinX adjust the volume in the current room only. In my case this would adjust the speakers (were there any) connected to the Head End SpeakerLinX in the A/V closet. Instead, what I want to do is adjust the volume in the room that I’m currently controlling with my T4.

The Approach

My T4 design allows me to be aware of which room the user is when I’m setting it up. This means that each page of the T4 can have specific commands assigned to the volume buttons. My approach will be to build macros that adjust the volume in a specific room, and assign that macro to the volume buttons in the appropriate room.

Using macros gives me one more advantage. The Kitchen and Family room zones are essentially one large room. Macros will allow me to treat them as a single zone, adjusting the volume and mute in both places at the same time.

The Solution

The macro builder in Dealer Setup 2.1 doesn’t provide a way to adjust volume or down for a specific audio source. Don’t be mislead by the VOL UP and VOL DN commands that appear for a player service – they refer to the IR commands that you learn into a ControlLinX. There’s an option for Set Volume Level, but that only allows you to set the volume to a specific level. What we want is the ability to adjust the volume or down by a tick.

So how do we adjust the volume level for a specific player? You have to go to the ASCII reference in the Programming for Third Party Control manual to find the answer. The format to do this is:


You’ll have to switch to advanced view in Macro Builder to do this. I’ll also add in Mute Off here in case the user has muted the sound, so they don’t have to turn the sound back on manually. Imagine if they cranked the sound all the way up, then realized it was muted and switched the sound on.

The Implementation

In the end, I created 6 macros:

Volume Up Family Room
Volume Down Family Room
Volume Up Living Room
Volume Down Living Room
Mute Toggle Family Room
Mute Toggle Living Room

Here’s my Volume Up Family Macro:

vol up fam macro

In my Head End SpeakerLinX, I assigned these macros to User Commands:

Macros In Head End

Lastly, I assigned the IR codes for user commands to the volume buttons on the proper pages in the T4 setup. In the following example, the user has selected the Family Room, so I know that I need to assign the Family Room macros on this page:

T4 Assigned Macro

Now when the user presses Volume Up on the Family Room screen, the Head End SpeakerLinX will should run the vol up Family Rm macro.


All in all, this is a fairly straight forward approach. I wish there were Volume Up and Volume Down options in Macro Builder for a specified player, but it’s no big deal to switch to advanced mode and type them in manually.

One of the problems I’ve had with this approach (aside from real reliability issues with IRLinX) is that the user has to click the volume up and down buttons once for each adjustment in volume level. A sustained hold on volume doesn’t appear to call the macro repeatedly. I’m still looking for a solution to this, but one work around might be to adjust the macro to turn the volume up and down by 3 levels, rather than just one. This should at least make volume adjustments quicker.

Lastly, a common thread across this series of postings is that IR control of Digi is remarkably unreliable. I’m getting about 60-70% (non-scientific, of course) reliability when issuing commands. What that means is that the user might have to press Mute twice or three times before the volume actually shuts off. What makes matters worse is that macros sometimes take a couple of seconds to actually execute, so you might press mute twice in a row thinking that the command failed, only to have both presses execute, thus canceling each other out.

One way to determine if a macro has executed or not is to use my DigiLinX Debugger, filter output to only show the device with the IRLinX you’re using, and watch for messages that say “HandlePress Button 255, Time 0” followed by an ASCII command that represents your macro, such as:

CKeypadButton:SendCommand:#@SL2200604700116100B7D2_3SL2200604700116100B7D2_6#MACRO {{#@Family Player#MUTE TOGGLE|#@Kitchen Player#MUTE TOGGLE}}

When the IRLinX fails to interpret the command, you’ll see the message “Suspicious stuck bit” or “NQueue::Put: queue NQueue full, message droped”. If you see the later message, try turning down the output level on the RP6 flasher port. A good practice is to always turn the port down to the lowest level.

I’m interested in hearing your approach to this problem, if it differs from mine.

I Are In Control. Or Not.

Technorati Tags: ,,,

For the end user, the ultimate measurement of satisfaction with their distributed audio/video system is the interaction point. For DigiLinX customers, these touch points are TouchLinX and KeyLinX devices. The TouchLinX device is a decent implementation of usability, with a few shortcomings. Ask any Digi customer, and they’ll generally have some sort of complaint – from device size and navigation flow, to skin choices and response times.

Those shortcomings are generally minor or a matter of taste, but one of the largest obstacles is that Digi is a hardwired system, meaning control is embedded in a wall. This is a real problem when you’re using it in conjunction with Panorama to control a video source. How realistic is it to ask a customer to control what they see on TV while standing next to a wall? If your customer wants to do something as simple as change the channel from the couch in the Living Room, you will be faced with integrating a remote control into the system.

Getting IR to work behave cooperate with DigiLinX has been one of the most frustrating, least rewarding tasks I have experienced since I began working with NetStreams products. I plan to do a series of postings on controlling DigiLinX with IR, based upon the experiences I’ve had over the past few months.

Up front I’ll tell you that, with the firmware and hardware available today, IR control of DigiLinX sucks. I mean it sucks big time. One of the absolute requirements of IR for the end user is that when they press a button on a remote control, the action they initiated will execute. If once in a while my customer hits the mute button on the remote and the sound is still on, they’re going to be perplexed. If the button fails to work 30-40% of the time, they’re going to be pissed. And they should be.

My experience thus far is that the shortcomings of IR control of DigiLinX is with the IRLinX receiver. Suggestions from NetStreams support focus on isolating the IRLinX device and minimizing interference or signal reflection. The current “best practice” for an IRLinX location is to stick it in a small cardboard box that measures 6″ x 2″ x 1″, and to tape the receiver to one end and the flasher on the other.

IRLinX in Box

This picture speaks for itself. It doesn’t exactly look like something you want at a crucial pivot point for your $50,000 install, though, does it? To be honest, I wouldn’t care if it actually solved the problem. Which it doesn’t.

The Environment

My series of postings will revolve around an IR install I’m (still) working on for a client of mine. I’ll focus on controlling two logical areas – the Family Area and the Living Room. The Family Area is actually one large area made up of two audio zones – Family Room and Kitchen. I’ll take this into account as I build my control, keeping the two audio zones synched.

Each logical room has a plasma TV in it, and each TV has a Vutec Art Screen in front of it. For purposes of this posting, we can assume that there are two Panorama sources, both of which are DirecTV satellite boxes. One is a DVR and the other is simple an HD box. Note that they both understand the same set of IR commands, so their flashers will have to be isolated from each other.

This is a system I inherited from another installer, so I’m somewhat stuck with the design they put in place before the walls went up. The home is block construction, and has nicer finishes such as tongue and groove wood ceilings and plaster walls. It’s not the kind of home that you want to start cutting in to. On top of that, there are a few isolated attic areas, but they are separated from each other. The attic space above the A/V room is small, and doesn’t offer access to the rest of the house. Because of all these factors, I’ve decided to install a single SpeakerLinX in the A/V closet (which I’ll name Head End), and attach an IRLinX to it. An RTI T4 will send RF commands to an RP6 in the closet, which will flash the IRLinX.

Abrams Design

IR Flow

The remote control will add to the functionality provided by the TouchLinX, but it won’t replace them. The user wants to be able to use either one to control the system. This means that the IR receiver on each satellite box will have two flashers on it – one from the RP6 for commands originating from the T4, and the other from the MLA-101 that is driven by the DigiLinX interface.

Abrams IR Flow

Because of the reliability issues of DigiLinX IR, I’ll send as few commands as possible to the IRLinX, and as many as possible directly to the satellite boxes. This means that I won’t be using the Digi IR pass-through feature. I consider this a huge win, having used IR pass-through in other jobs. With IR pass through, first you have to hope that the IRLinX will recognize the IR command, and then you have to pray that the command will actually reach the source. It’s a numbers game, and if you play it, you’re a loser.

So for this system, I’ll only have Digi do the following things:

  • Control volume in each logical zone, including volume up and down, and mute. For the family area, I want to direct commands to both audio zones at the same time.
  • Switch the display sources between the DVR and HD satellite boxes for a given room.
  • Send the IR commands I’ve stored in Panorama to turn the TV on and off, and to raise and lower the Vutec screen.
  • As an added bonus, I’ll also include a button that will allow the user to “Watch TV everywhere”. This will turn the audio on in every room set to the given satellite source, and will turn on every display.

Everything else, including channel changing, guide, favorites, etc will use the RP6 to flash DirecTV commands straight to the satellite box.

The T4 Interface

To make my intentions clearer, I wanted to show how the user will control the system. The home page allows the user to select one of the rooms. If they select Home Audio, I use the RTI browser interface to load the DigiLinX flash interface from the Head End device.

T4 home

Once they do this, I ask them to select one of the two Panorama sources. When they click one, I switch the selected room (Family Room, in this example), turn on the audio and TV, and raise the screen. Note that on this screen, I can present them with TV on and off for the Family Room display, since they’ve already made that selection.

T4 Select family

Now the TV should be on, and the user has control of the TV. Note that at this point, the only Digi IR commands that I’ll send are volume and Mute. Everything else goes directly to the DVR satellite box.

T4 DVR control


Another option I had when offering control to my client was to simply provide them with a tablet PC or UMPC, and have them use the flash interface off a Digi device. That would be ok, but it requires that my clients always be aware of what room they’re in, what source they’re on, and where the TV controls are located. When a device is installed in a wall and the default room is the current room, there is much less for the end user to think about. Not so when that control is mobile.

Additionally, the DVR interface for DigiLinX doesn’t have channel up and down. I’m not sure how that was left out of an interface that is meant to control a TV source, but that’s the way it is. The lack of a channel favorites screen is also noticeable, as is the absence of the required number of DVR keys that DirecTV offers, such as List and Active.

Now that I’ve explained the environment that I’m working in, look for future postings on how I made it all work.