var Clay = require('pebble-clay');
var clayConfig = require('./config');
var clay = new Clay(clayConfig);
const jsSHA = require('./sha');
var messageKeys = require('message_keys');
var sid;
var status;
var retry;
retry = 1;
function dec2hex(s) {
return (s < 15.5 ? '0' : '') + Math.round(s).toString(16);
}
function hex2dec(s) {
return parseInt(s, 16);
}
function base32tohex(base32) {
var base32chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
var bits = "";
var hex = "";
for (var i = 0; i < base32.length; i++) {
var val = base32chars.indexOf(base32.charAt(i).toUpperCase());
bits += leftpad(val.toString(2), 5, '0');
}
//console.log('-- bits : ' + bits)
for (var i = 0; i + 4 <= bits.length; i += 4) {
var chunk = bits.substr(i, 4);
hex = hex + parseInt(chunk, 2).toString(16);
}
return hex;
}
function leftpad(str, len, pad) {
if (len + 1 >= str.length) {
str = Array(len + 1 - str.length).join(pad) + str;
}
return str;
}
function getOtp() {
key = base32tohex(JSON.parse(localStorage.getItem('clay-settings')).OTP_seed)
//console.log('-- seed:' + JSON.parse(localStorage.getItem('clay-settings')).OTP_seed)
//console.log('-- key:' + key)
var epoch = Math.round(new Date().getTime() / 1000.0);
var time = leftpad(dec2hex(Math.floor(epoch / 30)), 16, '0');
// updated for jsSHA v2.0.0 - http://caligatio.github.io/jsSHA/
var shaObj = new jsSHA("SHA-1", "HEX");
shaObj.setHMACKey(key, "HEX");
shaObj.update(time);
var hmac = shaObj.getHMAC("HEX");
//console.log('-- hmac:' + hmac)
var offset = hex2dec(hmac.substring(hmac.length - 1));
//console.log('--offset:' + offset)
var otp = (hex2dec(hmac.substr(offset * 2, 8)) & hex2dec('7fffffff')) + '';
otp = (otp).substr(otp.length - 6, 6);
return otp
}
function xhr_to_syno(method, url_path, onload_function, max_retry) {
console.log('------xhr start')
status = "";
if (JSON.parse(localStorage.getItem('clay-settings')).server) {
var server = JSON.parse(localStorage.getItem('clay-settings')).server
url = server + url_path;
var xhr = new XMLHttpRequest();
xhr.timeout = 6000; // time in milliseconds
xhr.open(method, url, true);
console.log('------xhr opened')
xhr.onload = function () {
console.log('------xhr onload')
if (xhr.readyState === 4) {
retry = 1;
console.log('------xhr request returned');
if (xhr.status == 200) {
onload_function(xhr);
return true;
} else {
console.log('------xhr request returned error code ' + xhr.status);
return false;
}
}
};
xhr.ontimeout = function (e) {
retry++;
if (retry < max_retry) {
console.log('------xhr timed out retrying another time ');
xhr_to_syno(method, url_path, onload_function, max_retry);
} else {
console.log('------xhr timed out ' + retry + ' time');
//send back "timeout" to watch
message = "Call to server timed out, verify settings and connectivity";
// Build message
var dict = {
'status': message,
};
// Send the message
Pebble.sendAppMessage(dict, function (e) {
console.log('sent');
}, function () {
console.log('failed');
});
return false;
}
};
xhr.send(null);
} else {
Pebble.showSimpleNotificationOnPebble("DSCam H-S", "You need to set your Synology account and server.");
}
}
function authenticate() {
var response;
sid = "";
console.log('---- authenticate');
if (JSON.parse(localStorage.getItem('clay-settings')).username && JSON.parse(localStorage.getItem('clay-settings')).password) {
var username = JSON.parse(localStorage.getItem('clay-settings')).username;
var password = JSON.parse(localStorage.getItem('clay-settings')).password;
console.log('-- username:' + username);
console.log('-- password:' + password.substring(0, 1) + '...');
var url_path = "/webapi/auth.cgi?api=SYNO.API.Auth&method=Login&version=6&account=" + username + "&passwd=" + password + "&session=SurveillanceStation&format=sid";
if (JSON.parse(localStorage.getItem('clay-settings')).OTP_enabled) {
var otp_code = getOtp()
console.log('-- otp_code is :' + otp_code)
url_path = url_path + "&otp_code=" + otp_code
}
var method = "GET";
onload_function = function (xhr) {
response = JSON.parse(xhr.responseText);
if (response.success == true) {
sid = response.data.sid;
console.log('------Authentication succeeded');
if (sid != "") {
message = "Welcome to Syno Cam Switch ! ready & authenticated";
// Build message
var dict = {
'auth': message,
};
// Send the message
Pebble.sendAppMessage(dict, function (e) {
console.log('sent');
}, function () {
console.log('failed');
});
} else {
console.log('------Unexpected error : authentication is OK but no SID retrieved');
}
} else {
console.log('------Authentication failed : ' + JSON.stringify(response));
}
};
max_retry = 1;
xhr_to_syno(method, url_path, onload_function, max_retry);
} else {
console.log("--- failed to get settings");
Pebble.showSimpleNotificationOnPebble("DSCam H-S", "You need to set your Synology account and server.");
}
}
function get_status() {
var response;
if (sid != "") {
status = "";
console.log('---- get_status');
var url_path = "/webapi/entry.cgi?api=SYNO.SurveillanceStation.HomeMode&version=1&method=GetInfo&_sid=" + sid;
var method = "GET";
onload_function = function (xhr) {
response = JSON.parse(xhr.responseText);
if (response.success == true) {
status = response.data.on;
var message;
switch (status) {
case true:
message = "Your Home mode is ON";
break;
case false:
message = "Your Home mode is OFF";
break;
default:
message = "home mode is unknown !";
}
// Build message
var dict = {
'status': message,
};
// Send the message
Pebble.sendAppMessage(dict, function (e) {
console.log('sent');
}, function () {
console.log('failed');
});
}
}
max_retry = 10;
xhr_to_syno(method, url_path, onload_function, max_retry);
} else {
authenticate();
get_status();
}
}
function switch_home(bool) {
var response;
console.log('---- authenticate');
if (sid != "") {
status = "";
console.log('---- get_status');
url_path = "/webapi/entry.cgi?api=SYNO.SurveillanceStation.HomeMode&version=1&method=GetInfo&_sid=" + sid;
var method = "GET";
onload_status_function = function (xhr) {
response = JSON.parse(xhr.responseText);
if (response.success == true) {
status = response.data.on;
console.log('------ status:' + status);
var message;
var dict;
if (status != bool) {
console.log('---- switching home mode to ' + bool);
url_path = "/webapi/entry.cgi?api=SYNO.SurveillanceStation.HomeMode&version=1&method=Switch&on=" + bool + "&_sid=" + sid;
method = "GET"
onload_switch_function = function (xhr) {
response = JSON.parse(xhr.responseText);
if (response.success == true) {
status = bool;
switch (status) {
case true:
message = "You just set Home mode ON";
break;
case false:
message = "You just set Home mode OFF";
break;
default:
message = "something happened, try again !";
}
// Build message
dict = {
'status': message,
};
// Send the message
Pebble.sendAppMessage(dict, function (e) {
console.log('sent');
}, function () {
console.log('failed');
});
}
}
max_retry = 10;
xhr_to_syno(method, url_path, onload_switch_function, max_retry);
} else {
console.log('---- nothing to do, status already ' + status);
switch (status) {
case true:
message = "Your Home Mode is already ON";
break;
case false:
message = "Your Home Mode is already OFF";
break;
default:
message = "something happened, try again !";
}
// Build message
dict = {
'status': message,
};
// Send the message
Pebble.sendAppMessage(dict, function (e) {
console.log('sent');
}, function () {
console.log('failed');
});
}
}
}
max_retry = 10;
xhr_to_syno(method, url_path, onload_status_function, max_retry);
} else {
authenticate();
switch_home(bool);
}
}
// Get JS readiness events
Pebble.addEventListener('ready', function (e) {
console.log("---- local storage:");
console.log("user " + JSON.parse(localStorage.getItem('clay-settings')).username);
console.log('PebbleKit JS is ready');
// Update Watch on this
Pebble.sendAppMessage({ 'JSReady': 1 });
});
// Get AppMessage events
Pebble.addEventListener('appmessage', function (e) {
// Get the dictionary from the message
var dict = e.payload;
console.log(dict[0].toString());
switch (dict[0]) {
case 'auth':
authenticate();
break;
case 'get':
get_status();
break;
case 'home_on':
switch_home(true);
break;
case 'home_off':
switch_home(false);
break;
default:
console.log('Sorry. I don\'t understand your request :' + dict[0]);
}
});