Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable HomeLink and Autopark (Summon) #118

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 18 additions & 2 deletions examples/teslacmd.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ var JSONbig = require('json-bigint');
var util = require('util');
var teslams = require('../teslams.js');
var argv = require('optimist')
.usage('Usage: $0 -u <username> -p <password> || --id <id_string> --token <bearer_token> \n -acdDFgHimMPtvVwXZ -A [on|off] -C [start|stop] -L [lock|unlock] -O offset -R [std|max|50-90,100] -S [close|vent|comfort|open|0-100] -T temp')
.usage('Usage: $0 -u <username> -p <password> || --id <id_string> --token <bearer_token> \n -acdDFfghHimMPrtvVwXZ -A [on|off] -C [start|stop] -L [lock|unlock] -O offset -R [std|max|50-90,100] -S [close|vent|comfort|open|0-100] -T temp')
.string('id')
.string('token')
.alias('u', 'username')
.describe('u', 'Teslamotors.com login')
.alias('p', 'password')
.describe('p', 'Teslamotors.com password')
.boolean(['a', 'c', 'd', 'D', 'F', 'g', 'H', 'i', 'm', 'M', 'P', 't', 'v', 'V', 'w', 'X', 'Z'])
.boolean(['a', 'c', 'd', 'D', 'f', 'F', 'g', 'h', 'H', 'i', 'm', 'M', 'P', 'r', 't', 'v', 'V', 'w', 'X', 'Z'])
.alias('a', 'all')
.describe('a', 'Print information about all vehicles on the account')
.describe('c', 'Display the charge state')
Expand All @@ -25,6 +25,12 @@ var argv = require('optimist')
.alias('F', 'flash')
.describe('g', 'Display the GUI settings')
.alias('g', 'gui')
.alias('h', 'homelink')
.describe('h', 'Activate Homelink')
.alias('f', 'AutoPark Forward')
.describe('f', 'Activate Summon Forward')
.alias('r', 'AutoPark Reverse')
.describe('r', 'Activate Summon Reverse')
.alias('H', 'honk')
.describe('H', 'Honk the car horn')
.alias('i', 'info')
Expand Down Expand Up @@ -86,6 +92,7 @@ if ( argv.help === true ) {
console.log( ' -D, --debug Display debug information [boolean]');
console.log( ' -F, --flash Flash the car headlights [boolean]');
console.log( ' -g, --gui Display the GUI settings [boolean]');
console.log( ' -h, --homelink Activate Homelink [boolean]');
console.log( ' -H, --honk Honk the car horn [boolean]');
console.log( ' -i, --info Print vehicle info [boolean]');
console.log( ' -m, --mobile Display the mobile state [boolean]');
Expand Down Expand Up @@ -178,6 +185,15 @@ function parseArgs( vehicle ) {
if (argv.F) {
teslams.flash( vid, pr );
}
if (argv.h) {
teslams.trigger_homelink( {id: vehicle.id, vehicle_id: vehicle.vehicle_id, token: vehicle.tokens[0] }, pr );
}
if (argv.f) {
teslams.trigger_autopark_forward( {id: vehicle.id, vehicle_id: vehicle.vehicle_id, token: vehicle.tokens[0] }, pr );
}
if (argv.r) {
teslams.trigger_autopark_reverse( {id: vehicle.id, vehicle_id: vehicle.vehicle_id, token: vehicle.tokens[0] }, pr );
}
if (argv.H) {
teslams.honk( vid, pr );
}
Expand Down
146 changes: 146 additions & 0 deletions teslams.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,18 @@
var request = require('request');
var util = require('util');
var JSONbig = require('json-bigint');
var WebSocket = require('ws');

var portal = 'https://owner-api.teslamotors.com/api/1';
exports.portal = portal;
var owner_api = 'https://owner-api.teslamotors.com';
exports.portal = owner_api;
var token = '';
exports.token = token;
var username = '';
exports.username = username;
var password = '';
exports.password = password;

// emulate the android mobile app
var version = '2.1.79';
Expand All @@ -35,6 +40,8 @@ var report2 = function(call, body, cb) {
// get_vid gives the callback the ID of the first vehicle in the array returned
var all = exports.all = function(options, cb) {
if (!cb) cb = function(error, response, body) {/* jshint unused: false */};
exports.username = options.email;
exports.password = options.password;
//add option to call without using email and password
if (options.token) {
exports.token = options.token;
Expand Down Expand Up @@ -621,6 +628,145 @@ exports.ROOF_VENT = ROOF_VENT;
exports.ROOF_COMFORT = ROOF_COMFORT;
exports.ROOF_OPEN = ROOF_OPEN;

function keep_alive (ws) {
if (ws.readyState == ws.OPEN) {
var msg = {
msg_type: 'control:ping',
timestamp: Date.now(),
}
ws.send(JSON.stringify(msg));
}
}

function keep_alive_autopark (ws) {
if (ws.readyState == ws.OPEN) {
var msg = {
msg_type: 'autopark:heartbeat_app',
timestamp: Date.now(),
}
ws.send(JSON.stringify(msg));
}
}

function send_message (ws, command, latitude, longitude) {
var cmd = {
msg_type: command,
latitude: latitude,
longitude: longitude,
}
var message = JSON.stringify(cmd);
console.log('Sending message: ' + message);
ws.send(message);
}

function streaming_interface (params, command, cb) {
var error = false;
var token = params.token;
var vehicle_id = params.vehicle_id;
var autopark_timerId = 0;
var timerId = 0;
var frequency = 0;
var autopark_started = false;

var latitude = params.latitude;
var longitude = params.longitude;

var ws = new WebSocket('wss://' + exports.username + ':' + token + '@streaming.vn.teslamotors.com/connect/' + vehicle_id);

ws.onmessage = function (event) {
// console.log('Server data is: ' + event.data);
var msg = JSON.parse(event.data);
// console.log( util.inspect(msg) );
switch (msg.msg_type) {
// heartbeat
case 'control:hello':
console.log('Received message type: ' + msg.msg_type + ', msg is ' + util.inspect(msg));
var freq = msg.autopark.heartbeat_frequency;
console.log('Frequency is: ' + freq);
timerId = setInterval(keep_alive, msg.connection_timeout/2, ws);
break;
case 'control:pong':
// console.log('Ignoring heartbeat (pong)');
break;
// HomeLink
case 'homelink:status':
console.log('Received message type: ' + msg.msg_type + ', nearby is ' + msg.homelink_nearby );
if ( (msg.homelink_nearby == true) && (command == 'homelink:cmd_trigger') ) {
send_message(ws, command, latitude, longitude);
};
break;
case 'homelink:cmd_result':
console.log('Received message type: ' + msg.msg_type + ', reason is ' + msg.reason );
ws.close();
break;
// Summon
case 'autopark:status':
console.log('Received message type: ' + msg.msg_type + ', autopark_state is ' + msg.autopark_state );
switch (msg.autopark_state) { // ready, paused, resuming, preparing, aborting...
case 'ready':
if (autopark_started) {
// autopark is done.
clearInterval(autopark_timerId);
ws.close();
} else {
// start autopark if needed.
if ((command == 'autopark:cmd_forward') || (command == 'autopark:cmd_reverse')) {
send_message(ws, command, latitude, longitude);
autopark_timerId = setInterval(keep_alive_autopark, freq, ws);
autopark_started = true;
}
}
break;
}
break;
case 'autopark:cmd_result':
console.log('Received message type: ' + msg.msg_type + ', reason is ' + msg.reason );
break;
case 'autopark:heartbeat_car':
// console.log('Ignoring heartbeat_car');
break;
default:
// console.log('Received unknown message type: ' + util.inspect(msg.msg_type) );
}
};

ws.onopen = function (event) {
console.log('WS connection opened');
};

ws.onclose = function (event) {
console.log('WS connection closed, status code: ' + event.code);
clearInterval(timerId);
};

}

function prepare_required_data (params, command, cb) {
var vid = params.id;
get_drive_state(vid, function (ds) {
// console.log( util.inspect(ds) );
params.latitude = ds.latitude;
params.longitude = ds.longitude;

streaming_interface (params, command, cb);
});
}

function trigger_autopark_forward( params, cb ) {
prepare_required_data (params, 'autopark:cmd_forward', cb);
}
exports.trigger_autopark_forward = trigger_autopark_forward;

function trigger_autopark_reverse( params, cb ) {
prepare_required_data (params, 'autopark:cmd_reverse', cb);
}
exports.trigger_autopark_reverse = trigger_autopark_reverse;

function trigger_homelink( params, cb ) {
prepare_required_data (params, 'homelink:cmd_trigger', cb);
}
exports.trigger_homelink = trigger_homelink;

//left off here//
// Streaming API stuff is below. Everything above is the REST API
//
Expand Down