Managing TiVO with the Cynical Network PluginThis is a worked example for using Cynical Network, involving our old friend TiVO. Here is a good example of a device that is useful to manage with Indigo, but whose interface is not rich or interesting enough to warrant writing a dedicated plugin for it.
So let's get started. First we must know what this device does, and how to talk to it. This is often the hardest part, because companies often like to hide this, giving it out only to specially favored "strategic" partners. Luckily for us, TiVO is somewhat more enlightened and has documented their interface publicly. Go, take a look: as these things go, this is good documentation. Sadly, it's also a bit threadbare where it comes to function: you can press buttons on a virtual remote control, switch a few states around, and TiVO can tell you which channel it's currently watching. Well, it's better than nothing.
Creating the Connection
The documentation says to connect to port 31339 of TiVO. So we create a TCP Out device and configure it for TiVO's address and port 31339. Since we have no reason to explicitly mess with connection setup or teardown, we check the Auto-Connect checkbox. And since the documentation says commands are "terminated by a carriage return," we pick that setting for line endings: Click Save and you're connecting to TiVO - if you select your new device in Indigo, you'll see its state changing to Connected, and there you are.
Now what? Well, you need to send commands to TiVO to make it do things, so (again from the nice documentation) we find that to toggle TiVO's pause function, we need to send it the string IRCODE PAUSE. So we create a Send Text action like this: Save that and trigger the action, and your TiVO will behave as if you had pressed the Pause button on its remote. That wasn't so hard, was it? You can use such actions in all the usual Indigo ways - run them from event triggers, put them into action groups, and so on. It's a good idea to create a library of simple action groups that just send one command, and use those everywhere. Put them all into an action group folder for extra tidiness.
Now that we know how to tell TiVO to do things, we might want to return the favor and respond to TiVO telling us things. In other words, we need to listen to what it is saying on its network connection. TiVo's documentation tells us that TiVO will send us a line like CH_STATUS 047 LOCAL when it changes channels, where 047 is the channel that TiVO has tuned to. How nice, but how do we get the channel out of that string? Easy: We create a Recognized Input trigger like this:
The only magic here is the use of a regular expression to pry the channel number out of its line - we look for CH_STATUS and a space character, followed by a string of digits, and we ask Cynical Network to put that string of digits into the Indigo variable TiVO_channel. Save that trigger, reach over to your TiVO remote and change the (live) channel, and you'll see the variable appearing containing the current channel number. What you do with that is up to you.
Digging deeper into TiVO's documentation, we find that in order to watch live TV on a given channel, we have to do two things: first, we must send TELEPORT LIVETV, then we must wait until TiVO says LIVETV_READY, and then we must SETCH channel with the desired channel number. How do we get this done reliably? Of course we could insert what we think is a suitable delay and get away with it (if we wait several seconds), but let's do this right.
The first step is obvious: We create an action that sends TELEPORT LIVETV. Then we create an event trigger looking for the string LIVETV_READY. In the trigger's action, we put the second Send Text command, so send the SETCH command. This is obvious if the channel number is fixed. If it's something you looked up or calculated, you can use a plugin formula: ="SETCH %s" % channel_number, where channel_number can be any Python expression, but might well be an Indigo variable where you stashed the desired number.
One last wrinkle needs to be addressed: What we just did will send the SETCH command every time TiVO teleports to live mode. That will get you into trouble if you have several TiVO-related actions all active inside your Indigo at once. There are many ways to make that more robust. A simple one is to dedicate an Indigo variable (say, TiVO_set_channel) to this job, set it in the initial action (right before sending TELEPORT), add a condition (TiVO_set_channel is not empty) to the trigger, and clear the variable in the final action sequence. Essentially, you need some way to remember that you're in the middle of a sequence. I prefer using Indigo variables for that. (Computer people call that a state machine, with the variable standing as the state).
Dealing With Errors
Sometimes things go wrong. Your TiVO might be unplugged, say. Cynical Network (like virtually all Cynical Plugins) reflects connection problems in a state variable called state. You can use ordinary Indigo event triggers to notice changes in state and respond appropriately. Of course, the Auto-Connect checkbox ensures that the plugin will keep trying to reconnect to TiVO until it succeeds, but in the meantime you may want to do something interesting, like alert yourself.