Tivo Telenet Driver

So, I'm no developer but I can hack together a little code and i think I figured it out. I added a "disconnect" command to the metadata:

  command "disconnect"

And then the following function:

  def disconnect() {
  	telnetClose()
  }

I was then able to create custom commands for Initialize, setCH and Disconnect and execute them in my triggered action in that order and the result is that the Telnet session released the network remote after the action is executed so I can use other network remotes. I added a few seconds delay between each command as it seems more reliable that way.

Awesome... Would you mind posting your version of the groovy? I see the OP last updated his code 6 months ago...

As I mentioned, I barely know what I am doing so proceed at your own risk, but here you go:

/********TiV0 Telnet Control
/***************************
/*
ACTION_A
ACTION_B
ACTION_C
ACTION_D

*/

metadata {
	definition (name: "Tivo Telnet", namespace: "jorge.martinez", author: "Jorge Martinez") {
		capability "Telnet"
		capability "Initialize"
		capability "Switch"
		attribute "channel", "NUMBER"
		command "chUp"
		command "chDown"
		command "pause"
		command "myShows"
		command "liveTv"
		command "play"
		command "up"
		command "down"
		command "left"
		command "right"
		command "central"
		command "Netflix"
		command "select"
		command "standby"
		command "clear"
		command "stop"
		command "guide"
		command "setCH", ["STRING"]
		command "nextTrack"
		command "previousTrack"
		command "info"
		command "back"
		command "disconnect"
	}
	preferences {
		section("Device Settings:") {
			input "TiVoIP", "string", title:"TiVoIP", description: "", required: true, displayDuringSetup: true
			input "TiVoMini", "bool", title:"", description: "Is this a tivo mini", required: true, displayDuringSetup: true
		}
	}
}
def one() 	{sendMsg("IRCODE NUM1")} 
def two()	{sendMsg("IRCODE NUM2")}
def three()	{sendMsg("IRCODE NUM3")}
def four()	{sendMsg("IRCODE NUM4")}
def five()	{sendMsg("IRCODE NUM5")}
def six()	{sendMsg("IRCODE NUM6")}
def seven()	{sendMsg("IRCODE NUM7")}
def eight()	{sendMsg("IRCODE NUM8")}
def nine()	{sendMsg("IRCODE NUM9")}
def zero()	{sendMsg("IRCODE NUM0")}
def info()	{sendMsg("IRCODE INFO")}
def guide()	{sendMsg("IRCODE GUIDE")}
def back()	{sendMsg("IRCODE BACK")}
def testCommand(Command){sendMsg(Command)}
def setCH (CH){
	if (settings.TiVoMini){ //if is mark as mini
	}
	else{ //if is not a mini
		sendMsg("SETCH "+ CH)
	}
}
def clear()	{sendMsg("IRCODE CLEAR")}
def standby(){sendMsg("IRCODE STANDBY")}
def select(){sendMsg("IRCODE SELECT")}
def Netflix(){sendMsg("IRCODE NETFLIX")}
def central(){sendMsg("IRCODE TIVO")}
def up (){sendMsg("IRCODE UP")}
def down (){sendMsg("IRCODE DOWN")}
def left (){sendMsg("IRCODE LEFT")}
def right (){sendMsg("IRCODE RIGHT")}
def play (){sendMsg("IRCODE PLAY")}
def liveTv(){sendMsg("IRCODE LIVETV")}
def chUp (){sendMsg("IRCODE CHANNELUP")}
def nextTrack(){chUp()}
def chDown (){sendMsg("IRCODE CHANNELDOWN")}
def previousTrack(){chDown ()}
def myShows (){sendMsg("IRCODE NOWSHOWING")}
def pause (){sendMsg("IRCODE PAUSE")}
def stop(){sendMsg("IRCODE STOP")}
def installed() {
	log.info('Tivo Telnet : installed()')
	initialize()
}
def updated() {
	log.info('Tivo Telnet: updated()')
	initialize()
}
def initialize() {
	log.info('Tivo Telnet: initialize()')
	telnetClose() 
	log.info ("TiVo IP ${settings.TiVoIP}")
	telnetConnect([termChars:[13]], settings.TiVoIP, 31339, settings.username, settings.password)
}
def disconnect() {
	telnetClose()
}
def sendMsg(String msg){
	log.info("Sending telnet msg: " + msg)
	return new hubitat.device.HubAction(msg, hubitat.device.Protocol.TELNET)
}
private parse(String msg){
	log.debug("Parse: " + msg)
	if(msg.startsWith("CH_STATUS"))	{
		log.info "got channel update " + msg.substring(10,14)
		state.channel = msg.substring(10,14).toInteger()
		sendEvent(name: "channel", value: state.channel, isStateChange: true)
	}

}
def telnetStatus(String status){
	log.warn "telnetStatus: error: " + status
	if (status != "receive error: Stream is closed"){
		log.error "Connection was dropped."
		initialize()
	} 
}
def pause(millis) {
   def passed = 0
   def now = new Date().time
   log.debug "pausing... at Now: $now"
   /* This loop is an impolite busywait. We need to be given a true sleep() method, please. */
   while ( passed < millis ) {
       passed = new Date().time - now
   }
//   log.debug "... DONE pausing."
}```

cool, thank you :smile:

Sorry for the super long delay, I want to update my GitHub with your code if you allow me

Sure.

added below, to Find Remote Control only works with RF Remotes

command "findremote"

def findremote() {sendMsg("IRCODE FIND_REMOTE")}

Hi. I am trying to get this on my Tivo Bolt. Most seems to work, except set channel. I'd like to be able to have rule machine automatically switch for SD to the HD channel, but setCH doesn't seem to work. Anyone else have an issue?

In the log, I am receiving "Parse: CH_FAILED NO_LIVE"

I ended up doing several things to bypass setCH. First, it was easier in rule machine to add the actuator capability to the program to allow access to the finer details of the program, next I found out the code for the green, D button on the remote and simply added it to the code. It is called "ACTION_D" if anyone needs it.

I haven't updated this driver in a while (I'm using the Feb '19 version) and setCH is working on my Bolt+. For a channel change the logs show:

2021-02-05 08:30:44.098 am info got channel update 0503
2021-02-05 08:30:44.095 am debugParse: CH_STATUS 0503 LOCAL
2021-02-05 08:30:44.032 am infogot channel update 0503
2021-02-05 08:30:44.029 am debugParse: CH_STATUS 0503 REMOTE
2021-02-05 08:30:43.983 am infoSending telnet msg: SETCH 503

Would you be able to post the driver detail you are using successfully? Not sure what version driver I have, but I got it from inside the thread here.

Give me a sec and I'll try the Sept 2019 version referenced in the first post...

I just updated to the Sept 2019 version; setCH is working with that version as well. Github shows this was last updated Sept. 16 2019.

Okay, thank you for checking must be something weird with my tivo Bolt. Let me know if you would like to have any of my device edits (adds). Thanks - Brock

1 Like

I've just had a quick play with this and my Virgin Media V6 Tivo here in the UK. Had to fix the IP address to its MAC in the router as there was nowhere to do it in the Virgin interface, but on a cursory glance, it seems to do what it says on the tin.

Going to try and mix/match this with my LG 2020 OLED Smart TV and HEOS, now. Wish me luck.

Trying to get this working and I am also having difficulty with the SETCH function. It simply does nothing. I am using an OTA tivo, so I have to specify sub-channels (6.1 or 26.2, etc) I have read that you have to use a space as the delimiter, but this isn’t working for me. I wonder if this driver simply doesn’t work properly with OTA channel numbers.

On my Tivo Bolt, the setCH function gave the "CH_FAILED, NO_LIVE" error as some have noted, so I have a workaround for the driver that uses the IRCODE command instead. Here is the changed function code:

def setCH (CH){
if (settings.TiVoMini){ //if is mark as mini
}
else{ //if is not a mini
/* This uses IRCODE commands concatenated in one telnet message separated by \r */
String cmd = ""
for (i=0; i<CH.length(); i++) {
if (i<CH.length()-1) {
cmd = cmd << "IRCODE NUM"+CH[i]+"\r"
}
else {
cmd = cmd << "IRCODE NUM"+CH[i]
}
}
sendMsg(cmd)
}
}

Not sure how you send sub-channels with the IR remote, but this could be modified to adapt.

Hope this helps!

It's been a while but I just had the need to control Tivo via Telnet...there is a command called ADVANCE that puts out the dash between numbers for OTA channels. So you would send "IRCODE NUM8\rIRCODE ADVANCE\rIRCODE NUM1" for channel 8-1.

1 Like

Thank you for sharing this! I gave up on using the telnet interface with my Tivo OTA device because I couldn't track this info down anywhere. I may give it another shot now. :slight_smile:

1 Like