Tag Archives: TV

Even More MQTT enabled TVs

Kevin Modelling the headset

A project at work recently came up to do with using one of the Emotiv headsets to help out a former Italian IBMer who was suffering from locked in syndrome. The project was being led by Kevin Brown who was looking for ways to use the headset to drive things sending email and browsing the web but he was also looking for a way to interact with some other tech around the house. The TV was the first on the list.

Continuing on from my previous work with controlling TVs and video walls with MQTT I said I would have a crack at this. My earlier solution was limited to LG TVs with serial ports and this needed to work with any make so a different approach was needed. It also needed to run on Windows so it was also a chance to play with C# and .Net.

To be TV agnostic it was decided to use a USB IR remote from a company called RedRat. They make a number of solutions, but their RedRat III was perfect for what was needed.

RedRat IR transmitter & receiver

The RedRat API comes with bindings for C++, .Net on Windows (and a LIRC plugin for Linux). The RedRat III is not just a IR transmitter, it is also a receiver which means it can “learn” from existing remote controls so it can be used with any TV.

Kevin is using Emotiv headset to drive Dasher as the input device. Dasher is a sort of keyboard replacement that allows the user to build up words using at a minimum a single input e.g. a single push button. As well as building words other actions can be added to the selector, Kevin added actions for browsing and also to control the TV. These actions publish MQTT messages to a topic with payloads like “volUp”, “chanDown” or “power”.

So now we had the inputs it was time to get round to writing the code to turn those messages into IR signals. There are 2 MQTT .NET libraries listed on the MQTT.org software page. I grabbed the first off the list MqttDotNet and got things working pretty quickly.

The following few lines sets up a connection and subscribes to a topic.

String connectionString = "tcp://" + 
  Properties.Settings.Default.host.Trim() + ":" +
  Properties.Settings.Default.port;
IMqtt client = MqttClientFactory.CreateClient(connectionString, "mqtt2ir");
try
{
	client.Connect(true);
	client.PublishArrived += new PublishArrivedDelegate(onMessage);
	client.ConnectionLost += new ConnectionDelegate(connectionLost);
	client.Subscribe(Properties.Settings.Default.topic.Trim(), 
	  QoS.BestEfforts);
}

Where the onMessage callback looks like this:

bool onMessage(object sender, PublishArrivedArgs msg)
{
	String command = msg.Payload.ToString().Trim();
	IRPacket packet = loadSignal(command);
	if (packet != null) 
	{
		redrat.OutputModulatedSignal(packet);
	}
	return true;
}

MQTT2IR Settings Window

And that is pretty much the meat of the whole application, the rest was just some code to initialise the RedRat and to turn it into a System Tray application with a window for entering the broker details and training the commands.

Unfortunately just a few days before we were due to have delivered this project we learned that the intended recipient had picked up a respiratory infection and had passed away. I would like to extend my thoughts to their family and I hope we can find somebody who may find this work useful in the future.

First Android App

After mentioning my new toy a couple of posts ago I mentioned I was hoping to do a bit of Android development.

I’ve been doing a bit of Android work as part of my new job (I recently joined a very cool team at work) making some existing Java code run, but this is my first real application.

I had left the TV on and gone to the office one day last week and while it did not permanent damage, there was a slight bit of ghosting from the MythTV menu for a day or 2 afterwards. I already have my TV hooked up a couple of topic on my home MQTT broker, so I though that running up a simple Android Widget to show the state would be a good starting point.

MQTT Topic Tree
MQTT Topic Tree

The TV/Status topic updates every 30 seconds and currently shows either off or a string like on:RGB:6 which is made up of state, input and volume.

The first task is to create a Android Service that will subscribe to this topic and watch for changes. The standard IA92 MQTT drivers can be used with the Android SDK to get access to the broker, so the connect code is very similar to the code used in my Twitter2MQTT bridge except the id for the client is generated from the phones unique id.

private String android_id =Secure.getString(this.getContentResolver(),Secure.ANDROID_ID);

private boolean connect() {
  try {
    client = (MqttClient) MqttClient.createMqttClient("tcp://tiefighter.loc:1883", null);
    client.registerSimpleHandler(new MessageHandler());
    client.connect("droid-"+android_id, true, (short) 240);
    String topics[] = {"TV/Status"};
    int qos[] = {1};
    client.subscribe(topics, qos);
    return true;
  } catch (MqttException e) {
    e.printStackTrace();
    return false;
  }
}

The MessageHandler is an inner class and handles both incoming messages and reconnection using the following 2 methods.

public void publishArrived(String topic, byte[] payload, int qos, boolean retained) throws Exception {
	String message = new String(payload);
	// This is to allow access to the notification service from a none 	
	if (Looper.myLooper() == null) {
		Looper.prepare();
	}
			
	RemoteViews updateViews = new RemoteViews(TVLongService.this.getPackageName(), R.layout.main);
			
	String toastMsg = "";
	String toastHead = "";
	int icon = 0;
	boolean alert = false;

	if (message.equals("off")) {
		if (TVWidget.on) {
			toastMsg = "TV now OFF";
			toastHead = "TV OFF";
			icon = R.drawable.tv_off;
			alert = true;
			TVWidget.on = false;
		}
	} else {
		if (!TVWidget.on) {
			toastMsg = "TV now ON";
			toastHead = "TV ON";
			icon = R.drawable.tv_on;
			alert = true;
			TVWidget.on = true;
		}
	}

	if (alert) {
		Intent intent = new Intent();
		PendingIntent contentIntent = PendingIntent.getActivity(TVLongService.this, 0, intent, 0);
		NotificationManager notificationManager = (NotificationManager) TVLongService.this.getSystemService(Context.NOTIFICATION_SERVICE);
		Notification notification = new Notification(icon, toastHead, System.currentTimeMillis());
		notification.setLatestEventInfo(TVLongService.this, "TV Monitor", toastMsg, contentIntent);
		notificationManager.notify(1, notification);
		updateViews.setImageViewResource(R.id.img, icon);
	}

	ComponentName componentName = new ComponentName(TVLongService.this, TVWidget.class);
	AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(TVLongService.this);
	appWidgetManager.updateAppWidget(componentName, updateViews);
}

TVWidget
The MessageHandler onMessage method fires when a message is posted to the TV/Status topic and then updates the widget Icon from tv_on to tv_off and then triggers a notification pop-up if the state has changed since the previous state.

The connectionLost method fires up a background thread to try and reconnect to the broker every 10 seconds.
TVWidget_on

TVWidget_toast

public void connectionLost() throws Exception {
	client = null;
	Log.v("TVMonitor","connection dropped");
	Thread t = new Thread(new Runnable() {
		
		@Override
		public void run() {
			do {//pause for 5 seconds and try again;
				Log.v("TVMonitor","sleeping for 10 seconds before trying to reconnect");
				try {
					Thread.sleep(10 * 1000);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			} while (!connect());
			System.err.println("reconnected");
		}
	});			
}

Next Steps

  • Survive network changes

    At the moment the code does not handle moving from WIFI to 3G networking all that well, there are collection of BroadCast future PendingIntents that should signal changes in network state.

  • Geo-Fencing

    I don’t really need to know that the TV is on while I’m at home, so I’m planning on adding a filter so notifications are only fired when I’m outside say 200m of home

  • MythTV

    May be add some indication as to what channel is currently being watched and what the upcoming recordings may be

TV Scrobbling

Having seen Dale Lane’s work with VDR to build something similar to Last.FM for the TV he’s been watching, I’ve been looking to see if I could do the same with MythTV.

MythTV 0.23 has shipped recently and with it came a new event system. Having had a quick look at the feature for this it looked like it would be a good starting point for this. The following events looked like they may be able to provide what I needed.

  • Playback started
  • Playback stopped
  • Playback changed

To use events you specify a command to run when each fires. You can set these up with the mythtvsetup command. As well as specifying a command you can also pass arguments, these arguments are passed using the same tokens used for the MythTV job system. The following is not the full list, but should be enough to do what I’m looking for.

  • %TITLE% – Title
  • %SUBTITLE% – Episode subtitle
  • %CHANID% – MythTV channel id
  • %DESCRIPTION% – The blurb from EPG
  • %PROGSTART% – The listed started time for the programme
  • %PROGEND% – The listed end time for the programme

There is also an option to add a command that fires on every event which you can also pass a %EVENTNAME% argument, this is very useful for debugging event ordering. Not all of the events support all of the arguments as the data is not relevant.

After a bit of playing I managed to get most of what I needed, but there where a few problems

  1. No way to tell the difference between watching recorded and live TV
  2. No way to tell when you change channel when watching live TV
  3. No way to tell when one live programme ends and a new one starts with live TV

I raised a bug in the MythTV tracker (#8388) to cover the first 2 (since the 3rd one didn’t occur to me until I got a bit further). Which the guys very quickly added. So there is now a LiveTV Started event fired when a frontend starts watching live tv followed by a Playback Started event with the details of the programme. I’ll raise a ticket for the last one and assuming I can get sign off from the boss I’ll see about submitting a patch to add it in. In the mean time with a little extra work I can infer the programme change from the Record Started and Record Finished events.

Acting on the events

So with all these events which may be reported on either the backend or frontend it’s looking good for another messaging solution. Luckily I already broker up and running for my home power monitoring and security setup. So now I just needed to run up a script or two to publish the events and a consumer with a state machine to act on them.


#!/bin/sh
#
# playStarted.sh %TITLE% %SUBTITLE% %DESCRIPTION% %CHANID%

/home/mythtv/bin/sendMessage TV/watching/start “$1/$2 ($3) on $4″

mythtvsetup events screen

Where sendMessage is a small script that publishes the second argument to the topic in the first. The other end is Java JMS application that keeps the state machine up to date and update the database when a show ends. Dale was kind enough to send me his database schema, so the data should look the same.

What next

Now I’ve got my data logging to a local database I need to come up with a front end to present it all. Next time I get 5mins to chat to Dale when we are both in the office I will see if I can borrow some of his code and if he wants to look at if we can build a site where we can all share what we’ve been watching?

Along with the events for the internal workings of the front and backends there are 10 user configurable events that can be bound to key presses, assuming I can find a spare button on the remote it should be possible to bind one of these to something like Favourite.


Resources

A different kind of TV remote control

This was originally posted to the eightbar blog back in June 2009.

I got a new TV around Christmas last year and while unpacking it I noticed along with the HDMI, SCART and other sockets on the back it had a 9-pin socket labelled “RS232C IN CONTROL&SERVICE”. I didn’t think that much of it at the time, but I remembered it last week while thinking about a couple of problems that had come up.

Tidy TV setup The first of these was that I had got home twice recently to find I’d left the TV turned on while I was at work, this was mainly because I use MythTV and I’d left it at the menu screen rather than turning the screen off as well. This had left shadow on the menu on the screen for a day or so afterwards (luckily no permanent damage as would have happened with a plasma or CRT TV).

The other point was from when we all first got hold of our Current Cost meters, there had been a lot of thought about how to work out exactly what appliances were on at any given time. While spotting when things like an electric water heater turned on was relatively easy, it was proving difficult to spot some of the lower power devices.

A plan started to form and I ordered a null modem cable from Amazon (£2.18 with free shipping) and went looking for some documentation on the protocol. The manual that came with the TV while being nearly an inch thick just covers the basics of how to plug it in and turn it on, but there was a CD-ROM with a much more detailed PDF document. The version for my TV is here. While searching round I found manuals for several other LG LCD/plasma TVs and they all seem to use the same basic protocol.

The protocol is relatively simple

[cmd1][cmd2] [setid] [data]

Where the cmd1 & cmd2 are 1 letter code, setid is for if you have multiple TVs connected to the same cable, the default id is 01 but you can change if needed, using 00 will work for all connected TVs. And data is a hex value of the option to pass the command.

The response from the TV looks like this for a success

[cmd2] [setid] OK[data]x

and like this for a failure

[cmd2] [setid] NG[data]x

The command to turn the TV on and off is “ka” so sending

ka 00 1

turns the TV on and sending

ka 00 0

turns it off. Most of the commands will reply with the current status if they are passed ff as the data. So sending

ka 00 ff

gets the following when the TV is off

a 00 OK0x

So now I had a way to turn the TV on and off along with checking its current status. The next step was to surface this some way and given the fascination we all seem to have with messaging, MQTT seemed like a good idea. A little bit of Java and the Java COMM API later and I had 2 topics TV/Commands & TV/Status.

I already have a topic that publishes if my mobile phone is in the flat by pinging it with Bluetooth. Combining this with the two new topics I can ensure that the TV is turned off when I leave. I’m also wondering if I should start to log the amount of time the TV is on, but I think the results may scare me a little…