cmrust / directv-remote Goto Github PK
View Code? Open in Web Editor NEWNode.js module for manipulating DirecTV STBs over their REST API
License: BSD 3-Clause "New" or "Revised" License
Node.js module for manipulating DirecTV STBs over their REST API
License: BSD 3-Clause "New" or "Revised" License
Hello!
could you point me to where you found these?
Does the MT stand for state? Timezone?
thanks
// "Process a command request from remote control."
// cmd is a required hex value, such as:
// 'FA81' Standby
// 'FA82' Active
// 'FA83' GetPrimaryStatus
// 'FA84' GetCommandVersion
// 'FA87' GetCurrentChannel
// 'FA90' GetSignalQuality
// 'FA91' GetCurrentTime
// 'FA92' GetUserCommand
// 'FA93' EnableUserEntry
// 'FA94' DisableUserEntry
// 'FA95' GetReturnValue
// 'FA96' Reboot
// 'FAA5' SendUserCommand
// 'FAA6' OpenUserChannel
// 'FA9A' GetTuner
// 'FA8A' GetPrimaryStatusMT
// 'FA8B' GetCurrentChannelMT
// 'FA9D' GetSignalQualityMT
// 'FA9F' OpenUserChannelMT
For the sake of not repeating a whole lot of typing, I'm going to link a downstream project issue that I opened for this before I understood that the problem was actually upstream:
ToddGreenfield/homebridge-directv#17
In very, very brief terms - older set top boxes are compatible (mostly), but they do not support the type
argument to /info/getLocations, and depending on how pervasive this is in the code, it could come up elsewhere. Using one of my own STBs as an example:
pi@homebridge:~/scripts/directv$ curl http://172.16.30.79:8080/info/getLocations | jq
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 195 100 195 0 0 1772 0 --:--:-- --:--:-- --:--:-- 1772
{
"locations": [
{
"clientAddr": "0",
"locationName": "LIVING ROOM"
}
],
"status": {
"code": 200,
"commandResult": 0,
"msg": "OK.",
"query": "/info/getLocations"
}
}
Note that "type" isn't being sent. Now let's look at what directv-remote attempts to send to that receiver:
172.16.30.28.54386 > 172.16.30.76.http-alt: Flags [P.], cksum 0x9505 (incorrect -> 0x27e4), seq 1:87, ack 1, win 502, options [nop,nop,TS val 1843789388 ecr 516813839], length 86: HTTP, length: 86
GET /info/getLocations?type=1 HTTP/1.1
Host: 172.16.30.76:8080
Connection: close
/info/getLocations?type=1
If I attempt to do that, here's what happens:
pi@homebridge:~/scripts/directv$ curl http://172.16.30.79:8080/info/getLocations?type=1
{"status": {
"code": 403,
"commandResult": 1,
"msg": "Forbidden.Invalid URL parameter(s) found.",
"query": "/info/getLocations?type=1"
Which makes sense, because if you poll /info/getOptions, you get this back:
pi@homebridge:~/scripts/directv$ curl http://172.16.30.79:8080/info/getOptions | jq
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 5873 100 5873 0 0 20607 0 --:--:-- --:--:-- --:--:-- 20679
{
"options": [
{
"command": "/info/getLocations",
"description": "List of available client locations. Warning: This command may change or be disabled in the future.",
"formControls": [],
"urlParameters": [
{
"isRequired": false,
"name": "wrapper",
"type": "string"
},
{
"isRequired": false,
"name": "callback",
"type": "string"
}
]
},
*snip*
It only supports wrapper and callback. Neither is required. So if we bounce back over to your code, we have this block:
// "List of available client locations."
// Returns an array of the networked set top boxes
// type is an optional parameter
// the docs label it as 'int'
// only 0 and 1 aren't *Forbidden*
// i'm not sure what the difference is yet,
// but 1 shows more of my wireless Genie STBs
this.getLocations = function(type, callback){
var path = '/info/getLocations';
var options = {
hostname: this.IP_ADDRESS,
port: 8080,
path: path
};
if (typeof type !== 'undefined') {
options.path = buildQueryString(options.path, { type: type });
}
makeRequest(options, callbackHandler(callback));
};
So type is "optional", but then a bit further down we check to make sure type isn't undefined. If it is, we don't do anything. If it isn't, we makeRequest(). Best I can tell, there's a line missing to call buildQueryString without the type parameter, probably inside of an else something like this (not a nodeJS dev, please correct if I have syntactical mistakes!):
if (typeof type !== 'undefined') {
options.path = buildQueryString(options.path, { type: type });
}
else {
options.path = buildQueryString(options.path);
}
That way we build the query string no matter what, and then makeRequest should handle the rest from there.
For the sake of completeness, here is the full output of /info/getOptions. I can make a cursory scan to see if this "type" business is present anywhere else, but it is a comparison that will be challenging without output of a more modern set of hardware. My suspicion is that on older hardware, type wasn't defined. On newer genie-era hardware type 0 is likely a standalone STB, and type 1 is a genie with child units. Either way, I think my solution solves for that. Again, not a nodeJS dev - need to go spelunking on my filesystem and see if I can apply this fix and see it work.
{
"options": [
{
"command": "/info/getLocations",
"description": "List of available client locations. Warning: This command may change or be disabled in the future.",
"formControls": [],
"urlParameters": [
{
"isRequired": false,
"name": "wrapper",
"type": "string"
},
{
"isRequired": false,
"name": "callback",
"type": "string"
}
]
},
{
"command": "/info/getSerialNum",
"description": "STB serial number. Warning: This command may change or be disabled in the future.",
"formControls": [],
"urlParameters": [
{
"isRequired": false,
"name": "wrapper",
"type": "string"
},
{
"isRequired": false,
"name": "callback",
"type": "string"
},
{
"isRequired": false,
"name": "clientAddr",
"type": "string"
}
]
},
{
"command": "/info/getVersion",
"description": "Set-top-box and SHEF information. Warning: This command may change or be disabled in the future.",
"formControls": [],
"urlParameters": [
{
"isRequired": false,
"name": "wrapper",
"type": "string"
},
{
"isRequired": false,
"name": "callback",
"type": "string"
}
]
},
{
"command": "/info/mode",
"description": "Set-top-box mode. Warning: This command may change or be disabled in the future.",
"formControls": [],
"urlParameters": [
{
"isRequired": false,
"name": "wrapper",
"type": "string"
},
{
"isRequired": false,
"name": "callback",
"type": "string"
},
{
"isRequired": false,
"name": "clientAddr",
"type": "string"
}
]
},
{
"command": "/remote/processKey",
"description": "Process a key request from the remote control. Warning: This command may change or be disabled in the future.",
"formControls": [],
"urlParameters": [
{
"isRequired": false,
"name": "wrapper",
"type": "string"
},
{
"isRequired": false,
"name": "callback",
"type": "string"
},
{
"isRequired": false,
"name": "clientAddr",
"type": "string"
},
{
"isRequired": false,
"name": "hold",
"type": "string"
},
{
"isRequired": true,
"name": "key",
"type": "string"
}
]
},
{
"command": "/serial/processCommand",
"description": "Process a command request from remote control. Warning: This command may change or be disabled in the future.",
"formControls": [],
"urlParameters": [
{
"isRequired": false,
"name": "wrapper",
"type": "string"
},
{
"isRequired": false,
"name": "callback",
"type": "string"
},
{
"isRequired": true,
"name": "cmd",
"type": "hex"
}
]
},
{
"command": "/tv/getProgInfo",
"description": "Program information of specified channel at current or specific time. Warning: This command may change or be disabled in the future.",
"formControls": [],
"urlParameters": [
{
"isRequired": false,
"name": "wrapper",
"type": "string"
},
{
"isRequired": false,
"name": "minor",
"type": "int"
},
{
"isRequired": false,
"name": "callback",
"type": "string"
},
{
"isRequired": true,
"name": "major",
"type": "int"
},
{
"isRequired": false,
"name": "clientAddr",
"type": "string"
},
{
"isRequired": false,
"name": "time",
"type": "long"
}
]
},
{
"command": "/tv/getTuned",
"description": "Information about the currently viewed program. Warning: This command may change or be disabled in the future.",
"formControls": [],
"urlParameters": [
{
"isRequired": false,
"name": "wrapper",
"type": "string"
},
{
"isRequired": false,
"name": "callback",
"type": "string"
},
{
"isRequired": false,
"name": "videoWindow",
"type": "string"
},
{
"isRequired": false,
"name": "clientAddr",
"type": "string"
}
]
},
{
"command": "/tv/tune",
"description": "Tune to a channel. Warning: This command may change or be disabled in the future.",
"formControls": [],
"urlParameters": [
{
"isRequired": false,
"name": "wrapper",
"type": "string"
},
{
"isRequired": false,
"name": "minor",
"type": "int"
},
{
"isRequired": false,
"name": "callback",
"type": "string"
},
{
"isRequired": true,
"name": "major",
"type": "int"
},
{
"isRequired": false,
"name": "source",
"type": "int"
},
{
"isRequired": false,
"name": "clientAddr",
"type": "string"
}
]
}
],
"status": {
"code": 200,
"commandResult": 0,
"msg": "OK.",
"query": "/info/getOptions"
}
}
Nice piece of work! I noticed that the poweron and poweroff keys do not work on Genie minis. Other keys appear to be working properly.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.