/*jshint esversion: 6,node: true,-W041: false */
const express = require('express');
const fs = require('fs');
const Alexa = require('./lib/alexa-remote.js');
let alexa;
//var XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest ;
const request = require('request');
const amazonserver = process.argv[3];
const alexaserver = process.argv[4];
const IPJeedom = process.argv[2];
const ClePlugin = process.argv[5];
const logLevel = process.argv[6];
//if (process.argv[7] == 1) useWsMqtt=true; else useWsMqtt=false; abandonné
var useWsMqtt=true;
//const debug=1; //mettre 1 pour debug
// Références :
// https://openclassrooms.com/fr/courses/1173401-les-closures-en-javascript
/* Configuration */
const config = {
cookieLocation: __dirname + '/data/alexa-cookie.json',
cookieRefreshInterval: 3 * 24 * 60 * 60 * 1000,
logger: consoleSigalou,
alexaServiceHost: alexaserver,
useWsMqtt: useWsMqtt,
listeningPort: 3456
};
var dernierStartServeur=0;
// Par sécurité pour détecter un éventuel souci :
if (!amazonserver) config.logger('Alexa-Config: *********************amazonserver NON DEFINI*********************');
if (!alexaserver) config.logger('Alexa-Config: *********************alexaserver NON DEFINI*********************');
// Speed up calls to hasOwnProperty - Pour le test function isEmpty(obj)
var hasOwnProperty = Object.prototype.hasOwnProperty;
function isEmpty(obj) {
// null and undefined are "empty"
if (obj == null) return true;
// Assume if it has a length property with a non-zero value
// that that property is correct.
if (obj.length > 0) return false;
if (obj.length === 0) return true;
// If it isn't an object at this point
// it is empty, but it can't be anything *but* empty
// Is it empty? Depends on your application.
if (typeof obj !== "object") return true;
// Otherwise, does it have any properties of its own?
// Note that this doesn't handle
// toString and valueOf enumeration bugs in IE < 9
for (var key in obj) {
if (hasOwnProperty.call(obj, key)) return false;
}
return true;
}
// arguments[0] c'est le texte
// arguments[1] c'est le niveau de log ou un array
//niveaudeLog=5 c'est tout
//niveaudeLog=2 c'est reduit
function consoleSigalou(text, level='') {
var today = new Date();
// 100=DEBUG
// 200=INFO
// 300=WARNING
// 400=ERROR
//1000=AUCUN
try {
var niveauLevel;
switch (level) {
case "ERROR":
niveauLevel=400;
break;
case "WARNING":
niveauLevel=300;
break;
case "INFO":
niveauLevel=200;
break;
case "DEBUG":
niveauLevel=100;
break;
default:
niveauLevel=400; //pour trouver ce qui n'a pas été affecté à un niveau
break;
}
if (logLevel<=niveauLevel)
console.log("[" + today.toLocaleString() + "]["+ level+"] : " + arguments[0].concat(Array.prototype.slice.call(arguments, 2)));
} catch (e) {
console.log(arguments[0]);
}
}
/* Routing */
const app = express();
let server = null;
/* Objet contenant les commandes pour appeler via chaine */
var CommandAlexa = {};
/* Apply callback on every cluster's membre (for multiroom device) */
function forEachDevices(nameOrSerial, callback) {
var device = alexa.find(nameOrSerial);
if (device === undefined)
return;
if (device.clusterMembers.length == 0)
callback(device.serialNumber);
for (var i in device.clusterMembers) {
if (device.clusterMembers.hasOwnProperty(i)) {
// We are sure that obj[key] belongs to the object and was not inherited.
callback(device.clusterMembers[i]);
}
}
}
function LancementCommande(commande, req)
{
config.logger('{API} ╔═══════[Lancement /'+commande, "INFO");
}
CommandAlexa.query = function(req,res){
res.type('json');
//config.logger('{API} ╔═══════[Lancement /query');
config.logger('VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV');
config.logger('VVVVVVVVVVVVVVVVVVVVVVVV--- R E Q U E T E U R ---VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV');
config.logger('VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV');
config.logger('Send Request with '+decodeURIComponent(req.query.query));
config.logger('and data='+decodeURIComponent(req.query.data));
config.logger('^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^');
alexa.httpsGetCall(decodeURIComponent(req.query.query), function(err) {
if (err)
return res.status(500).json(error(500, req.route.path, 'Requeteur', err));
res.status(200).json({});
}, decodeURIComponent(req.query.data));
};
/***** checkAuth *****
URL: /checkAuth
Return the status of the Auth
[{
auth - binary - authentified or not
}]
*/
CommandAlexa.checkAuth = function(req,res){
res.type('json');
config.logger('{API} ╔═══════[Lancement '+req.path+' sur '+req.query.device, 'INFO');
alexa.checkAuthentication(function(auth) {
res.status(200).json({
authenticated: auth
});
});
};
/**** Alexa.Speak *****
URL: /speak?device=?&text=?
device - String - name of the device
text - String - Text to speech
*/
CommandAlexa.Speak = function(req,res){
res.type('json');
config.logger('{API} ╔═══════[Lancement /Speak avec paramètres -> device:' + req.query.device+'/text:' + req.query.text +'/ssml:' + req.query.ssml +'/jingle:' + req.query.jingle +'/volume:'+ req.query.volume +'/lastvolume:' + req.query.lastvolume, 'INFO');
if ('device' in req.query === false) return res.status(500).json(error(500, req.route.path, 'Alexa.Speak', 'Missing parameter "device"'));
if ('text' in req.query === false) return res.status(500).json(error(500, req.route.path, 'Alexa.Speak', 'Missing parameter "text"'));
var SpeakouAnnouncement = 'speak';
if (('jingle' in req.query === true) && (req.query.jingle == true)) SpeakouAnnouncement = 'announcement';
if (('ssml' in req.query === true) && (req.query.ssml == true)) {
SpeakouAnnouncement = 'ssml';
//Si c'est un test, ajouter la balise Speak
if (req.query.text.indexOf ("Ceci est un test de message pour la commande")==0) req.query.text=""+req.query.text+"";
// Prévenir si le text envoyé ne contient pas la balise speak
if (req.query.text.indexOf ("")!=0) req.query.text="La syntaxe au format SSML n'est pas correct";
}
let Commands = [];
var test = ('volume' in req.query === true) && (req.query.volume != "");
if (test) Commands.push({command: 'volume', value: req.query.volume});
var TXTchaine = req.query.text;
var TABdecoupeMot;
var TABdecoupe;
var NBmots;
const LimiteAlexa = 250;
var Phrase2 = '';
var Phrase = '';
if (TXTchaine.length <= LimiteAlexa) {
Commands.push({command: SpeakouAnnouncement, value: req.query.text});
}
else {
TABdecoupe = req.query.text.split(/[;,.—]+/); // on met chaque phrase separer d'une ponctuation dans des elements d'un tableau
for(var i = 0; i < TABdecoupe.length ; i++) { //on parcourt chaque morceau
if (TABdecoupe[i].length > LimiteAlexa) { //si l'element est trop grand au decoupe au niveau des mots
Phrase2 ='';
TABdecoupeMot = TABdecoupe[i].split(" "); // on met chaque mot du moceau un tableau
NBmots = TABdecoupeMot.length; //on determine le nombre de mots dans la phrase
for(var xx = 0; xx < NBmots; xx ++){ //autant de boucle que de mot par morceau
if ( (Phrase.length + TABdecoupeMot[xx].length) < LimiteAlexa ){
Phrase = Phrase + " " + TABdecoupeMot[xx]; //on construit le premier morceau mot par mot
}else{
if (Phrase != '') Commands.push({command: SpeakouAnnouncement, value: Phrase});
Phrase = TABdecoupeMot[xx];
}
}
if ((Phrase != '') && (i == TABdecoupe.length -1 )) Commands.push({command: SpeakouAnnouncement, value: Phrase});
}else{ //si c'est pas trop grand alors on regarde le morceau
if ( Phrase != '' && ((Phrase.length + TABdecoupe[i].length ) < LimiteAlexa) ){ //traiement s'il reste un mocreau decoupé mot a mot
Phrase2 = Phrase + "," + TABdecoupe[i] ;
}
if ( (Phrase2.length + TABdecoupe[i].length) < LimiteAlexa ){ //si le precedent morceau + le nouveau ca ne depaase pas la limite
if (i < TABdecoupe.length /*-1*/ ){
if ((i < TABdecoupe.length -1) && (TABdecoupe[i+1].length < LimiteAlexa)){
Phrase2 = Phrase2 + TABdecoupe[i] + ","; //on construit les bloc separé par des virgules
}else{
Phrase2 = Phrase2 + TABdecoupe[i] + ".";
if ((Phrase2 != '') && (i < TABdecoupe.length -1 )) Commands.push({command: SpeakouAnnouncement, value: Phrase2});
}
}else{
Phrase2 = Phrase2 + TABdecoupe[i]; //on construit les bloc separé par des point
if ((Phrase2 != '') && (i == TABdecoupe.length -1 )) Commands.push({command: SpeakouAnnouncement, value: Phrase2});
}
}else{ //sinon si c'est trop grand je prononce la phrase d'avant et je garde le morceau actuel pour le prochain passage
if ((Phrase2 != '') && (Phrase == '') && ( i < TABdecoupe.length )) Commands.push({command: SpeakouAnnouncement, value: Phrase2}); //ne plus toucher -
if (Phrase == '') {
Phrase2 = TABdecoupe[i] + ",";
}
}
}
if ((Phrase2 != '') && (i == (TABdecoupe.length - 1 ) )) Commands.push({command: SpeakouAnnouncement, value: Phrase2});//dernier morceau
}
}
if (('lastvolume' in req.query === true) && test) Commands.push({command: 'volume', value: req.query.lastvolume});
boucleSurSerials_sendMultiSequenceCommand(req, Commands);
res.status(200).json({value: "Send"}); //ne teste pas le résultat//supprimé 16/11/2019
};
CommandAlexa.DisplayPower = function(req,res){
res.type('json');
config.logger('{API} ╔═══════[Lancement /DisplayPower avec paramètres -> device: ' + req.query.device+' & value: ' + req.query.value, "INFO");
if ('device' in req.query === false) return res.status(500).json(error(500, req.route.path, 'Alexa.DisplayPower', 'Missing parameter "device"'));
if ('value' in req.query === false) return res.status(500).json(error(500, req.route.path, 'Alexa.DisplayPower', 'Missing parameter "value"'));
//Il faut recupérer le deviceAccountID
let dev =alexa.find(req.query.device);
let deviceAccountId = dev.deviceAccountId;
let flags = {
data: JSON.stringify({value:'"' + req.query.value +'"'}),
method: 'PUT'
};
let callback = function(testErreur){
if (testErreur)
{traiteErreur(testErreur, 'DisplayPower', req.query);
res.status(500).json(error(500, req.route, 'Alexa.DeviceControls.DisplayPower', testErreur.message));
}
else
res.status(200).json({value: "OK"}); //ne teste pas le résultat
};
let url = `/api/v1/devices/${deviceAccountId}/settings/displayPower`;
alexa.httpsGet (url, callback,flags);
};
/**** Alexa.Announcement *****
URL: /announcement?device=?&text=?
device - String - name of the device
text - String - Text to speech
*/
CommandAlexa.Announcement = function(req,res){
res.type('json');
config.logger('{API} ╔═══════[Lancement /Announcement avec paramètres -> device:' + req.query.device+'/text:' + req.query.text +'/volume:' + req.query.volume +'/lastvolume:' + req.query.lastvolume);
if ('device' in req.query === false) return res.status(500).json(error(500, req.route.path, 'Alexa.Announcement', 'Missing parameter "device"'));
if ('text' in req.query === false) return res.status(500).json(error(500, req.route.path, 'Alexa.Announcement', 'Missing parameter "text"'));
let Commands = [];
var test = ('volume' in req.query === true) && (req.query.volume != "");
if (test) Commands.push({command: 'volume', value: req.query.volume});
Commands.push({command: 'announcement', value: req.query.text});
if (('lastvolume' in req.query === true) && test) Commands.push({command: 'volume', value: req.query.lastvolume});
boucleSurSerials_sendMultiSequenceCommand(req, Commands);
//boucleSurSerials_sendMultiSequenceCommand(req, 'announcement');
// pour ne pas boucler mais ne fonctionne pas sur les groupes
/*
alexa.sendSequenceCommand(req.query.device, 'announcement', req.query.text,
//alexa.sendCommand('G0911W079304113M', 'announcement', 'coucou',
function(testErreur){
if (testErreur)
{traiteErreur(testErreur);
res.status(500).json(error(500, req.route, 'Alexa.DeviceControls.Announcement', testErreur.message));
}
else
res.status(200).json({value: "OK"}); //ne teste pas le résultat
}
);
*/
res.status(200).json({value: "Send2"}); //ne teste pas le résultat//supprimé 16/11/2019
};
/**** Alexa.Radio *****
URL: /radio?device=?&text=?
device - String - name of the device
text - String - Text to speech
*/
CommandAlexa.Radio = function(req,res){
res.type('json');
if ('device' in req.query === false) return res.status(500).json(error(500, req.route.path, 'Alexa.Radio', 'Missing parameter "device"'));
if ('station' in req.query === false) return res.status(500).json(error(500, req.route.path, 'Alexa.Radio', 'Missing parameter "station"'));
config.logger('{API} ╔═══════[Lancement /Radio avec paramètres -> device: ' + req.query.device+' & station: ' + req.query.station);
// Suppression de la boucle des serial, en effet, si on envoi sur un groupe, la radio fonctionne en multiroom
//boucleSurSerials_setTunein(req);
alexa.setTunein(req.query.device, req.query.station,
function(testErreur){
if (testErreur)
{traiteErreur(testErreur, 'radio', req.query);
res.status(500).json(error(500, req.route, 'Alexa.DeviceControls.Radio', testErreur.message));
}
else
res.status(200).json({value: "OK"}); //ne teste pas le résultat
}
);
};
/***** Alexa.Volume *****
URL: /volume?device=?&value=?
device - String - name of the device
value - Integer - Determine the volume level between 0 to 100 (0 is mute and 100 is max)
*/
CommandAlexa.Volume = function(req,res){
res.type('json');
//Quand Volume est lancé par une autre fonction, la valeur du volume n'est pas value mais volume
if ('volume' in req.query) req.query.value=req.query.volume;
config.logger('{API} ╔═══════[Lancement /Volume avec paramètres -> device: ' + req.query.device+' & value: ' + req.query.value+'══════════════════════════════════', "INFO");
if ('device' in req.query === false) return res.status(500).json(error(500, req.route.path, 'Alexa.Volume', 'Missing parameter "device"'));
if ('value' in req.query === false) return res.status(500).json(error(500, req.route.path, 'Alexa.Volume', 'Missing parameter "value"'));
/*
for (var i = 0; i < 9; i++) {
alexa.sendSequenceCommand(req.query.device, 'volume', req.query.value, function(testErreur){if (testErreur) {traiteErreur(testErreur, 'volume', req.query);}});
}
*/
alexa.sendSequenceCommand(req.query.device, 'volume', req.query.value,
function(testErreur){
if (testErreur)
{traiteErreur(testErreur, 'volume', req.query);
//config.logger('{API} ERREUR ', "INFO");
res.status(500).json(error(500, req.route, 'Alexa.DeviceControls.Volume', testErreur.message));
}
else {
//config.logger('{API} pAS ERREUR ', "INFO");
res.status(200).json({value: "OK"}); //ne teste pas le résultat
}
}
);
};
/***** Alexa.textCommand *****
URL: /textCommand?device=?&value=?
device - String - name of the device
value - Integer - Determine the volume level between 0 to 100 (0 is mute and 100 is max)
*/
CommandAlexa.textCommand = function(req,res){
res.type('json');
config.logger('{API} ╔═══════[Lancement /textCommand avec paramètres -> device: ' + req.query.device+' & text: ' + req.query.text+'══════════════════════════════════', "INFO");
if ('device' in req.query === false) return res.status(500).json(error(500, req.route.path, 'Alexa.textCommand', 'Missing parameter "device"'));
if ('text' in req.query === false) return res.status(500).json(error(500, req.route.path, 'Alexa.textCommand', 'Missing parameter "text"'));
//req.query.text="je suis fatigué";
alexa.sendSequenceCommand(req.query.device, 'textCommand', req.query.text,
function(testErreur){
if (testErreur)
{traiteErreur(testErreur, 'textCommand', req.query);
res.status(500).json(error(500, req.route, 'Alexa.DeviceControls.textCommand', testErreur.message));
}
else
res.status(200).json({value: "OK"}); //ne teste pas le résultat
}
);
};
/***** Alexa.playList *****
URL: /volume?device=?&value=?
device - String - name of the device
value - Integer - Determine the volume level between 0 to 100 (0 is mute and 100 is max)
*/
CommandAlexa.playList = function(req,res){
res.type('json');
config.logger('{API} ╔═══════[Lancement /playList avec paramètres -> device: ' + req.query.device+' & playlist: ' + req.query.playlist);
if ('device' in req.query === false) return res.status(500).json(error(500, req.route.path, 'Alexa.playList', 'Missing parameter "device"'));
if ('playlist' in req.query === false) return res.status(500).json(error(500, req.route.path, 'Alexa.playList', 'Missing parameter "playlist"'));
alexa.playList(req.query.device, req.query.playlist,
function(testErreur){
if (testErreur){
traiteErreur(testErreur, 'playlist', req.query);
res.status(500).json(error(500, req.route, 'Alexa.DeviceControls.playList', testErreur.message));
}
else
res.status(200).json({value: "OK"}); //ne teste pas le résultat
}
);
};
/***** CommandAlexa.playMusicTrack *****
*/
CommandAlexa.playMusicTrack = function(req,res){
res.type('json');
config.logger('{API} ╔═══════[Lancement /playMusicTrack avec paramètres -> device: ' + req.query.device+' & trackId: ' + req.query.trackId);
if ('device' in req.query === false) return res.status(500).json(error(500, req.route.path, 'Alexa.playMusicTrack', 'Missing parameter "device"'));
if ('trackId' in req.query === false) return res.status(500).json(error(500, req.route.path, 'Alexa.playMusicTrack', 'Missing parameter "trackId"'));
alexa.playMusicTrack(req.query.device, req.query.trackId,
function(testErreur){
if (testErreur) {
traiteErreur(testErreur, 'playmusictrack', req.query);
res.status(500).json(error(500, req.route, 'Alexa.DeviceControls.playMusicTrack', testErreur.message));
}
else
res.status(200).json({value: "OK"}); //ne teste pas le résultat
}
);
};
/***** Alexa.Command *****
URL: /command?device=?&command=?
device - String - name of the device
command - String - command : pause|play|next|prev|fwd|rwd|shuffle|repeat
*/
CommandAlexa.Command = function(req,res){
res.type('json');
config.logger('{API} ╔═══════[Lancement /Command avec paramètres -> device: ' + req.query.device+' & command: ' + req.query.command);
if ('device' in req.query === false) return res.status(500).json(error(500, req.route.path, 'Alexa.Command', 'Missing parameter "device"'));
if ('command' in req.query === false) return res.status(500).json(error(500, req.route.path, 'Alexa.Command', 'Missing parameter "command"'));
// suppression de la boucle des serial
//boucleSurSerials_sendCommand(req);
//config.logger('{API}: *******************************************');
alexa.sendCommand(req.query.device, req.query.command, req.query.value,
function(testErreur){
if (testErreur) {
traiteErreur(testErreur, 'command', req.query);
res.status(500).json(error(500, req.route, 'Alexa.DeviceControls.Command', testErreur.message));
}
}
);
res.status(200).json({value: "Send"}); //ne teste pas le résultat
setTimeout(refreshPlayer.bind(null, req.query.device), 3000); // Dans 3s, actualiser le player
};
function refreshPlayer(deviceSerialNumber) {
//config.logger('{API}: *******************************************7 Lancement /Command avec paramètres -> device: ');
var action="REFRESH";
httpPost('refreshPlayer', {
deviceSerialNumber: deviceSerialNumber,
audioPlayerState: action
});
//config.logger('{API}: *******************************************8 Lancement /Command avec paramètres -> device: ');
}
// This is a fairly complete list of all the colors that Alexa will respond to and their associated RGB value.
ALEXA_COLORS = {
'alice_blue': [240, 248, 255],
'antique_white': [250, 235, 215],
'aqua': [0, 255, 255],
'aquamarine': [127, 255, 212],
'azure': [240, 255, 255],
'beige': [245, 245, 220],
'bisque': [255, 228, 196],
'black': [0, 0, 0],
'blanched_almond': [255, 235, 205],
'blue': [0, 0, 255],
'blue_violet': [138, 43, 226],
'brown': [165, 42, 42],
'burlywood': [222, 184, 135],
'cadet_blue': [95, 158, 160],
'chartreuse': [127, 255, 0],
'chocolate': [210, 105, 30],
'coral': [255, 127, 80],
'cornflower_blue': [100, 149, 237],
'cornsilk': [255, 248, 220],
'crimson': [220, 20, 60],
'cyan': [0, 255, 255],
'dark_blue': [0, 0, 139],
'dark_cyan': [0, 139, 139],
'dark_goldenrod': [184, 134, 11],
'dark_green': [0, 100, 0],
'dark_grey': [169, 169, 169],
'dark_khaki': [189, 183, 107],
'dark_magenta': [139, 0, 139],
'dark_olive_green': [85, 107, 47],
'dark_orange': [255, 140, 0],
'dark_orchid': [153, 50, 204],
'dark_red': [139, 0, 0],
'dark_salmon': [233, 150, 122],
'dark_sea_green': [143, 188, 143],
'dark_slate_blue': [72, 61, 139],
'dark_slate_grey': [47, 79, 79],
'dark_turquoise': [0, 206, 209],
'dark_violet': [148, 0, 211],
'deep_pink': [255, 20, 147],
'deep_sky_blue': [0, 191, 255],
'dim_grey': [105, 105, 105],
'dodger_blue': [30, 144, 255],
'firebrick': [178, 34, 34],
'floral_white': [255, 250, 240],
'forest_green': [34, 139, 34],
'fuchsia': [255, 0, 255],
'gainsboro': [220, 220, 220],
'ghost_white': [248, 248, 255],
'gold': [255, 215, 0],
'goldenrod': [218, 165, 32],
'green': [0, 128, 0],
'green_yellow': [173, 255, 47],
'grey': [128, 128, 128],
'honey_dew': [240, 255, 240],
'hot_pink': [255, 105, 180],
'indian_red': [205, 92, 92],
'indigo': [75, 0, 130],
'ivory': [255, 255, 240],
'khaki': [240, 230, 140],
'lavender': [230, 230, 250],
'lavender_blush': [255, 240, 245],
'lawn_green': [124, 252, 0],
'lemon_chiffon': [255, 250, 205],
'light_blue': [173, 216, 230],
'light_coral': [240, 128, 128],
'light_cyan': [224, 255, 255],
'light_goldenrod_yellow': [250, 250, 210],
'light_green': [144, 238, 144],
'light_grey': [211, 211, 211],
'light_pink': [255, 182, 193],
'light_salmon': [255, 160, 122],
'light_sea_green': [32, 178, 170],
'light_sky_blue': [135, 206, 250],
'light_slate_grey': [119, 136, 153],
'light_steel_blue': [176, 196, 222],
'light_yellow': [255, 255, 224],
'lime': [0, 255, 0],
'lime_green': [50, 205, 50],
'linen': [250, 240, 230],
'magenta': [255, 0, 255],
'maroon': [128, 0, 0],
'medium_aqua_marine': [102, 205, 170],
'medium_blue': [0, 0, 205],
'medium_orchid': [186, 85, 211],
'medium_purple': [147, 112, 219],
'medium_sea_green': [60, 179, 113],
'medium_slate_blue': [123, 104, 238],
'medium_spring_green': [0, 250, 154],
'medium_turquoise': [72, 209, 204],
'medium_violet_red': [199, 21, 133],
'midnight_blue': [25, 25, 112],
'mint_cream': [245, 255, 250],
'misty_rose': [255, 228, 225],
'moccasin': [255, 228, 181],
'navajo_white': [255, 222, 173],
'navy': [0, 0, 128],
'old_lace': [253, 245, 230],
'olive': [128, 128, 0],
'olive_drab': [107, 142, 35],
'orange': [255, 165, 0],
'orange_red': [255, 69, 0],
'orchid': [218, 112, 214],
'pale_goldenrod': [238, 232, 170],
'pale_green': [152, 251, 152],
'pale_turquoise': [175, 238, 238],
'pale_violet_red': [219, 112, 147],
'papaya_whip': [255, 239, 213],
'peach_puff': [255, 218, 185],
'peru': [205, 133, 63],
'pink': [255, 192, 203],
'plum': [221, 160, 221],
'powder_blue': [176, 224, 230],
'purple': [128, 0, 128],
'rebecca_purple': [102, 51, 153],
'red': [255, 0, 0],
'rosy_brown': [188, 143, 143],
'royal_blue': [65, 105, 225],
'saddle_brown': [139, 69, 19],
'salmon': [250, 128, 114],
'sandy_brown': [244, 164, 96],
'sea_green': [46, 139, 87],
'sea_shell': [255, 245, 238],
'sienna': [160, 82, 45],
'silver': [192, 192, 192],
'sky_blue': [135, 206, 235],
'slate_blue': [106, 90, 205],
'slate_grey': [112, 128, 144],
'snow': [255, 250, 250],
'spring_green': [0, 255, 127],
'steel_blue': [70, 130, 180],
'tan': [210, 180, 140],
'teal': [0, 128, 128],
'thistle': [216, 191, 216],
'tomato': [255, 99, 71],
'turquoise': [64, 224, 208],
'violet': [238, 130, 238],
'wheat': [245, 222, 179],
'white': [255, 255, 255],
'white_smoke': [245, 245, 245],
'yellow': [255, 255, 0],
'yellow_green': [154, 205, 50],
}
function red_mean(color1, color2) {
/* Get an approximate 'distance' between two colors using red mean.
Wikipedia says this method is "one of the better low-cost approximations".
*/
r_avg = (color2[0] + color1[0]) / 2;
r_delta = color2[0] - color1[0];
g_delta = color2[1] - color1[1];
b_delta = color2[2] - color1[2];
r_term = (2 + r_avg / 256) * Math.pow(r_delta, 2);
g_term = 4 * Math.pow(g_delta, 2);
b_term = (2 + (255 - r_avg) / 256) * Math.pow(b_delta, 2);
return Math.sqrt(r_term + g_term + b_term);
}
function rgb_to_alexa_color(rgb) {
var keys = Object.keys(ALEXA_COLORS);
return keys.reduce(function (previous, current) {
if (red_mean(ALEXA_COLORS[current] , rgb) < red_mean( ALEXA_COLORS[previous[0]], rgb)) {
return [current];
}
if (ALEXA_COLORS[current] === ALEXA_COLORS[previous[0]]) {
previous.push(current);
}
return previous;
}, [keys.shift()])[0];
}
function hexToBytes(hex) {
for (var bytes = [], c = 0; c < hex.length; c += 2)
bytes.push(parseInt(hex.substr(c, 2), 16));
return bytes;
}
/***** Alexa.SmarthomeCommand *****
*/
CommandAlexa.SmarthomeCommand = function(req,res){
res.type('json');
config.logger('{API} ╔═══════[Lancement /SmarthomeCommand avec paramètres -> device: ' + req.query.device+' & command: ' + req.query.command);
if ('device' in req.query === false) return res.status(500).json(error(500, req.route.path, 'Alexa.SmarthomeCommand', 'Missing parameter "device"'));
if ('command' in req.query === false) return res.status(500).json(error(500, req.route.path, 'Alexa.SmarthomeCommand', 'Missing parameter "command"'));
var parameters = {};
var toReturn = [];
if (req.query.entityType=='')
req.query.entityType="APPLIANCE";
parameters.action = 'turnOn'; // Même opération mais d'une autre manière
parameters.action = 'turnOff'; // Même opération mais d'une autre manière
parameters.action = 'setColor'; // Même opération mais d'une autre manière
parameters.action = req.query.command;
if (parameters.action == "turnOn" || parameters.action == "turnOff") {
var powerState="0";
if (parameters.action == 'turnOn') powerState="1";
toReturn.push({
'device': req.query.device,
'command': parameters.action,
'powerState': powerState
});
} else if (parameters.action == "setColorTemperature") {
toReturn.push({
'device': req.query.device,
'command': parameters.action,
'color': req.query.color
});
parameters.colorTemperatureName=req.query.color;
} else if (parameters.action == "setColor") {
toReturn.push({
'device': req.query.device,
'command': parameters.action,
'color': req.query.color
});
parameters.colorName=req.query.color;
} else if (parameters.action == "setRgbColor") {
toReturn.push({
'device': req.query.device,
'command': parameters.action,
'color': req.query.color
});
parameters.action = "setColor"
parameters.colorName = rgb_to_alexa_color(hexToBytes(req.query.color));
} else if (parameters.action == "setBrightness") {
parameters.brightness=req.query.brightness;
toReturn.push({
'device': req.query.device,
'command': parameters.action,
'brightness': req.query.brightness
});
} else if (parameters.action == "setTargetTemperature") {
parameters={'action': parameters.action,"targetTemperature.value":req.query.targetTemperature,"targetTemperature.scale":"celsius"};
toReturn.push({
'device': req.query.device,
'command': parameters.action,
'targetSetpoint': req.query.targetTemperature
});
} else if (parameters.action == "setThermostatMode") {
parameters={'action': 'setThermostatMode',"thermostatMode.value":req.query.thermostatMode};
toReturn.push({
'device': req.query.device,
'command': parameters.action,
'thermostatMode': req.query.thermostatMode
});
} else if (parameters.action == "Fan.Speed") {
parameters={'instance': parameters.action,'action': 'setRangeValue','rangeValue': {'value':req.query.rangeValue,'unitOfMeasure':''}};
toReturn.push({
'device': req.query.device,
'command': req.query.action,
'rangeValue': req.query.rangeValue
});
} else if (parameters.action == "Blind.Lift") {
parameters={'instance': parameters.action,'action': 'setRangeValue','rangeValue': {'value':req.query.rangeValue,'unitOfMeasure':'Alexa.Unit.Percent'}};
toReturn.push({
'device': req.query.device,
'command': req.query.action,
'rangeValue': req.query.rangeValue
});
}
//executeSmarthomeDeviceAction(entityIds, parameters, entityType, callback) {
alexa.executeSmarthomeDeviceAction(req.query.device, parameters, req.query.entityType,
function(testErreur){
if (testErreur) traiteErreur(testErreur);
}
);
res.status(200).json(toReturn);
//res.status(200).json({value: "Send"}); //ne teste pas le résultat
};
CommandAlexa.querySmarthomeDevices = function(req,res){
//-----------------------------------------------------------------------------------
// NE FONCTIONNE PAS IL MANQUE applicanceIds QUI EST DIFF2RENT DE entityIds
//-----------------------------------------------------------------------------------
res.type('json');
if ('device' in req.query === false) return res.status(500).json(error(500, req.route.path, 'Alexa.SmarthomeCommand', 'Missing parameter "device"'));
var entityType;
if (req.query.entityType!='')
entityType=req.query.entityType;
else
entityType="APPLIANCE";
//executeSmarthomeDeviceAction(entityIds, parameters, entityType, callback) {
config.logger('{API} ╔═══════[Lancement /querySmarthomeDevices avec paramètres !-> device: ' + req.query.device+'req.query.entityType: ' + req.query.entityType+ ' req.query.type: ' + req.query.type, 'INFO');
//config.logger('{API} >>>>>>>>>>Debug:' + JSON.stringify(req.query), 'INFO');
/*
alexa.querySmarthomeDevices(req.query.device, entityType,
function(devices){
config.logger('{API}: trouvé :'+devices);
//valeurvolume=devices["volume"];
res.status(200).json({ value: devices });
//if (testErreur) traiteErreur(testErreur);
}
);
*/
alexa.querySmarthomeDevices2(req.query.device, entityType,
function(deviceStatesErrors){
try {
deviceStates=deviceStatesErrors.deviceStates;
errors=deviceStatesErrors.errors;
}
catch(error) {
//config.logger('Souci, le serveur Amazon est bien disponible ? Erreur sur '+entityType+"/"+req.query.device,'DEBUG');
config.logger('{Remote} ║ Souci, le serveur Amazon est bien disponible ? Erreur sur : ['+entityType+"/"+req.query.device+"]",'ERROR');
}
//config.logger('deviceStatesErrors>'+JSON.stringify(deviceStatesErrors),'DEBUG');
//config.logger('>'+JSON.stringify(deviceStates),'DEBUG');
//config.logger('>entity>'+JSON.stringify(deviceStates."0"),'DEBUG');
var toReturn = [];
try {
//config.logger('1','DEBUG');
//config.logger('deviceStatesErrors>'+JSON.stringify(deviceStatesErrors),'DEBUG');
if (JSON.stringify(deviceStates[0]) === undefined) {
//config.logger('2','DEBUG');
//config.logger('0>'+JSON.stringify(errors[0]),'DEBUG');
//config.logger('--->'+JSON.stringify(errors),'DEBUG');
//config.logger('--0->'+JSON.stringify(errors[0]),'DEBUG');
//config.logger('{Remote} : !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!','DEBUG');
config.logger('{Remote} ║ Il y a une erreur sur la communication le device : [['+JSON.stringify(errors[0]['code'])+"]]",'DEBUG');
//config.logger('1','DEBUG');
toReturn.push({
'entityType': entityType,
'type': req.query.type,
'applicanceId': req.query.device,
// 'name': capabilityState['name'],
// 'value': capabilityState['value'],
'error': JSON.stringify(errors[0]['code'])
});
//config.logger('20','DEBUG');
}
else {
//config.logger('3','DEBUG');
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//config.logger('0>'+JSON.stringify(deviceStates[0]),'DEBUG'); // provoque souci
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//config.logger('>deviceState>>'+JSON.stringify(deviceStates[0]),'DEBUG');
//config.logger('>entity>>'+JSON.stringify(deviceStates[0].entity),'DEBUG');
//config.logger('queryState:entityId>'+JSON.stringify(deviceStates[0].entity.entityId),'DEBUG');
if (JSON.stringify(deviceStates[0].entity.entityType) != undefined)
entityType=JSON.stringify(deviceStates[0].entity.entityType);
//config.logger('queryState:entityType>'+JSON.stringify(deviceStates[0].entity.entityType),'DEBUG');
//config.logger('>entityType>>'+JSON.stringify(deviceStates[0].entity.entityType),'DEBUG');
var capabilityState=JSON.parse(deviceStates[0].capabilityStates[0]);
var capabilityStates=deviceStates[0].capabilityStates;
//config.logger('>>>capabilityState>>'+JSON.stringify(capabilityState),'DEBUG');
//config.logger('>>>entityType>>'+entityType,'DEBUG');
//for (value in capabilityStates) {
//config.logger(value+"<=>"+capabilityStates[value],'DEBUG');
//}
toReturn.push({
'entityType': entityType,
'type': req.query.type,
'applicanceId': req.query.device,
// 'name': capabilityState['name'],
// 'value': capabilityState['value'],
'capabilityStates': capabilityStates
});
//config.logger('queryState:name>'+capabilityState['name'],'DEBUG');
//config.logger('queryState:>value>'+capabilityState['value'],'DEBUG');
}
}
catch(error) {
//config.logger('deviceStates.entity.entityId>NON trouvé sur '+entityType+"/"+req.query.device,'DEBUG');
//config.logger('{Remote} ║ deviceStates.entity.entityId>NON trouvé sur ['+entityType+"/"+req.query.device+"]",'ERROR');
}
/*
for (var deviceState in deviceStates[0]) {
//config.logger('>deviceState>>'+JSON.stringify(deviceState),'DEBUG');
for (var entity in deviceState) {
config.logger('>>>>'+JSON.stringify(entity),'DEBUG');
config.logger('>>>>>'+JSON.stringify(deviceState.entity),'DEBUG');
//var device = notifications[serial];
toReturn.push({
'entityType': entityType,
'applicanceId': req.query.device,
'deviceState': deviceState.capabilityStates,
'entityType2': entityType
});
}
}*/
if (toReturn == "") {
toReturn.push("vide");
}
config.logger('{Remote} ╚════════════════════════════════════════════════════════════════════════════════════════','INFO');
res.status(200).json(toReturn);
});
//config.logger("fini");
//config.logger('Alexa*********************************************************************');
//res.status(200).json({value: "Send"}); //ne teste pas le résultat
};
// Les boucles qui lancent les commandes sur chaques device d'un multiroom
// PAS UTILISÉ
function boucleSurSerials_setTunein (req, callback) {
forEachDevices(req.query.device, (serial) => {
alexa.setTunein(serial, req.query.station,
function(testErreur){
if (testErreur) traiteErreur(testErreur);
}
);
});
}
function boucleSurSerials_sendMultiSequenceCommand (req, actions, callback) {
if (!!req.query.text) req.query.value=req.query.text; // dans l'hypothèse où la valeur est dans un champ text
/*
Version initiale qui donne le résultat
alexa.sendSequenceCommand(req.query.device, 'speak', req.query.text, function(err)
{
if (err)
return res.status(500).json(error(500, req.route.path, 'Alexa.Speak', err));
res.status(200).json({});
});
let Commands = [];
var test = ('volume' in req.query === true) && (req.query.volume != "");
if (test) Commands.push({command: 'volume', value: req.query.volume});
Commands.push({command: SpeakouAnnouncement, value: req.query.text});
if (('lastvolume' in req.query === true) && test) Commands.push({command: 'volume', value: req.query.lastvolume});
*/
forEachDevices(req.query.device, (serial) => {
alexa.sendMultiSequenceCommand(serial, actions, "SerialNode",
function(testErreur){
if (testErreur) {
traiteErreur(testErreur, actions, req.query);
}
}
);
});
}
//PAS UTILISÉ
function boucleSurSerials_sendCommand (req, callback) {
//pas sur qu'on l'utilise encore !!!!!!!!!!!!
forEachDevices(req.query.device, (serial) => {
alexa.sendCommand(serial, req.query.command,
function(testErreur){
if (testErreur) traiteErreur(testErreur);
config.logger('{API}: >>>>>>>>>>>>>>>>>>>>>>>on est la 8888888888>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> OK Refresh playinfo ');
}
);
//setTimeout(function() { RefreshApresCommand (serial); }, 5000);
});
}
/*
function RefreshApresCommand (serial) {
config.logger('{API}: >>>>>>>>>>>>>>>>>>>>>>>on est la>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> OK Refresh playinfo ');
Appel_getPlayerInfo(serial, function(retourAmazon) {
fichierjson = __dirname + '/data/playerInfo-'+serial+'.json';
fs.writeFile(fichierjson, JSON.stringify(retourAmazon, null, 2), err =>
{
config.logger('{API}: >>>>>>>>>>>>>>>>>>>>>>>on est la 5555>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> OK Refresh playinfo ');
//if (err) return res.sendStatus(500)
});
config.logger('{API}: >>>>>>>>>>>>>>>>>>>>>>>on est la 66666>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> OK Refresh playinfo ');
//res.status(200).json(retourAmazon);
});
}
*/
/***** Alexa.Notifications.SendMobilePush *****
URL /push?device=?&text=?
device - String - name of the device
text - String - Text to display in the push notification
*/
CommandAlexa.Push = function(req,res){
res.type('json');
config.logger('{API} ╔═══════[Lancement /Push avec paramètres -> device: ' + req.query.device+' & text: ' + req.query.text);
if ('device' in req.query === false) return res.status(500).json(error(500, req.route.path, 'Alexa.Push', 'Missing parameter "device"'));
if ('text' in req.query === false) return res.status(500).json(error(500, req.route.path, 'Alexa.Push', 'Missing parameter "text"'));
let Commands = [];
//Commands.push({command: 'volume', value: '60'});
Commands.push({command: 'notification', value: req.query.text});
//Commands.push({command: 'volume', value: '10'});
boucleSurSerials_sendMultiSequenceCommand(req, Commands);
res.status(200).json({value: "Send"}); //ne teste pas le résultat//supprimé 16/11/2019
};
/*
CommandAlexa.MultipleNext = function(req,res){
res.type('json');
config.logger('{API} ╔═══════[Lancement /MultipleNext avec paramètres -> device: ' + req.query.device+' & nb: ' + req.query.text);
if ('device' in req.query === false) return res.status(500).json(error(500, req.route.path, 'Alexa.MultipleNext', 'Missing parameter "device"'));
//if ('text' in req.query === false) return res.status(500).json(error(500, req.route.path, 'Alexa.MultipleNext', 'Missing parameter "text"'));
req.query.command="next";
alexa.sendCommand(req.query.device, req.query.command,
function(){
alexa.sendCommand(req.query.device, req.query.command,
function(){
alexa.sendCommand(req.query.device, req.query.command,
function(){
});
});
});
res.status(200).json({value: "Send"}); //ne teste pas le résultat//supprimé 16/11/2019
}
*/
/***** DeleteReminder *****
URL: /deletereminder
Return the list of reminders
[{
id - String - id of the reminder (unique identifier)
}]
*/
CommandAlexa.deleteReminder = function(req,res){
config.logger('{API}: deleteReminder' );
LancementCommande("deleteReminder",req);
res.type('json');
if ('id' in req.query === false)
return res.status(500).json(error(500, req.route.path, 'Alexa.DeleteReminder', 'Missing parameter "id"'));
const notification = {
'id': req.query.id
};
alexa.deleteNotification(notification, function(err) {
if (err)
return res.status(500).json(error(500, req.route.path, 'Alexa.Notifications.DeleteReminder', err));
res.status(200).json({});
});
};
//!!!!!!!!!!!!!!!! Ne fonctionne pas, Response: {"message":"user not authorized"}
// Faudra creuser
/*
CommandAlexa.disableReminder = function(req,res){
LancementCommande("disableReminder",req);
res.type('json');
if ('id' in req.query === false)
return res.status(500).json(error(500, req.route.path, 'Alexa.disableReminder', 'Missing parameter "id"'));
const notification = {
'id': req.query.id
};
const value = {
'status': 'OFF'
};
config.logger('*************di>>>>>>>>>>>>>>>>>>>>><<<' );
console.log(notification);
alexa.changeNotification(notification,value,function(err) {
if (err)
return res.status(500).json(error(500, req.route.path, 'Alexa.Notifications.disableReminder', err));
res.status(200).json({});
});
}
CommandAlexa.enableReminder = function(req,res){
LancementCommande("enableReminder",req);
res.type('json');
if ('id' in req.query === false)
return res.status(500).json(error(500, req.route.path, 'Alexa.disableReminder', 'Missing parameter "id"'));
const notification = {
'id': req.query.id
};
config.logger('*************en>>>>>>>>>>>>>>>>>>>>><<<' );
alexa.deleteNotification(notification, function(err) {
if (err)
return res.status(500).json(error(500, req.route.path, 'Alexa.Notifications.disableReminder', err));
res.status(200).json({});
});
}
*/
app.get('/checkAuth', CommandAlexa.checkAuth);
app.get('/query', CommandAlexa.query);
app.get('/command', CommandAlexa.Command);
app.get('/SmarthomeCommand', CommandAlexa.SmarthomeCommand);
app.get('/querySmarthomeDevices', CommandAlexa.querySmarthomeDevices);
app.get('/volume', CommandAlexa.Volume);
app.get('/textCommand', CommandAlexa.textCommand);
app.get('/speak', CommandAlexa.Speak);
app.get('/DisplayPower', CommandAlexa.DisplayPower);
app.get('/announcement', CommandAlexa.Announcement);
app.get('/radio', CommandAlexa.Radio);
app.get('/push', CommandAlexa.Push);
//app.get('/multiplenext', CommandAlexa.MultipleNext);
app.get('/deletereminder', CommandAlexa.deleteReminder);
//app.get('/enablereminder', CommandAlexa.enableReminder);
//app.get('/disablereminder', CommandAlexa.disableReminder);
/***** Alexa.Routine *****
URL /routine?device=?&name=?
device - String - name of the device
routine - String - name of routine
*/
//app.get('/routine', (req, res) => {
CommandAlexa.Routine = function(req,res){
LancementCommande("Routine",req);
//config.logger('{API} ╔═══════[Lancement /Routine avec paramètres -> device: ' + req.query.device+' & value: ' + req.query.routine);
res.type('json');
if ('device' in req.query === false)
return res.status(500).json(error(500, req.route.path, 'Alexa.Routine', 'Missing parameter "device"'));
//config.logger('{API} ╠═══> Device : ' + req.query.device, 'DEBUG');
if ('routine' in req.query === false)
return res.status(500).json(error(500, req.route.path, 'Alexa.Routine', 'Missing parameter "routine"'));
//config.logger('{API}: routine: ' + req.query.routine);
alexa.getAutomationRoutines2(function(niveau0) {
var routineaexecuter = "";
for (var serial in niveau0) {
if (niveau0.hasOwnProperty(serial)) {
var routine = niveau0[serial];
if (routine.creationTimeEpochMillis == req.query.routine)
routineaexecuter = routine;
}
}
if (routineaexecuter != '')
alexa.executeAutomationRoutine(req.query.device, routineaexecuter, traiteErreur);
else
config.logger('{API}: routine - ECHEC (introuvable) - Lancement routine: ' + req.query.routine);
res.status(200).json({});
});
};
app.get('/routine', CommandAlexa.Routine);
/***** Create a reminder *****
URL /reminder?device=?&text=?&when=?&recurring=? // Fix Aidom 01/03/2020
device - String - name of the device
text - String - Content of the reminder
when - String - Date at which the reminder should occur. Date format: YYYY-MM-DD HH24:MI:SS
recurring - String - Get parameter, depending on the requests recognized by Alexa // Fix Aidom 01/03/2020
Return an empty object if the function succeed.
Otherwise, an error object is returned.
*/
app.get('/reminder', (req, res) => {
config.logger('{API}: Alexa.Reminder');
res.type('json');
if ('device' in req.query === false)
return res.status(500).json(error(500, req.route.path, 'Alexa.Reminder', 'Missing parameter "device"'));
config.logger('{API} ╠═══> Device : ' + req.query.device, 'DEBUG');
if ('text' in req.query === false)
return res.status(500).json(error(500, req.route.path, 'Alexa.Reminder', 'Missing parameter "text"'));
config.logger('{API}: text: ' + req.query.text);
if ('when' in req.query === false)
return res.status(500).json(error(500, req.route.path, 'Alexa.Reminder', 'Missing parameter "when"'));
config.logger('{API}: when: ' + req.query.when);
// Fix Aidom 01/03/2020
if ('recurring' in req.query === false)
return res.status(500).json(error(500, req.route.path, 'Alexa.Reminder', 'Missing parameter "recurring"'));
config.logger('{API}: recurring: ' + req.query.recurring);
// End Fix
// when: YYYY-MM-DD HH:MI:SS
let dateValues = req.query.when.match(/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/);
if (dateValues === null)
return res.status(500).json(error(500, req.route.path, 'Alexa.Reminder', 'Invalid "when" format. Expected: YYYY-MM-DD HH:MI:SS'));
let when = new Date(dateValues[1], dateValues[2] - 1, dateValues[3], dateValues[4], dateValues[5], dateValues[6]);
config.logger('{API}: when: ' + when);
alexa.setReminder(req.query.device, when.getTime(), req.query.text, req.query.recurring, function(err) { // Fix Aidom 01/03/2020
if (err)
return res.status(500).json(error(500, req.route.path, 'createReminder', err));
res.status(200).json({});
});
});
/***** Create a alarm *****
URL /alarm?device=?&text=?&when=?
device - String - name of the device
text - String - Content of the alarm
when - String - Date at which the alarm should occur. Date format: YYYY-MM-DD HH24:MI:SS
Return an empty object if the function succeed.
Otherwise, an error object is returned.
*/
app.get('/alarm', (req, res) => {
config.logger('{API}: Alexa.Alarm');
res.type('json');
if ('device' in req.query === false)
return res.status(500).json(error(500, req.route.path, 'Alexa.Alarm', 'Missing parameter "device"'));
config.logger('{API} ╠═══> Device : ' + req.query.device, 'DEBUG');
if ('when' in req.query === false)
return res.status(500).json(error(500, req.route.path, 'Alexa.Alarm', 'Missing parameter "when"'));
config.logger('{API}: when: ' + req.query.when);
if ('recurring' in req.query === false)
return res.status(500).json(error(500, req.route.path, 'Alexa.Alarm', 'Missing parameter "recurring"'));
config.logger('{API}: recurring: ' + req.query.recurring);
config.logger('{API}: sound: ' + req.query.sound);
// when: YYYY-MM-DD HH:MI:SS
let dateValues = req.query.when.match(/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/);
if (dateValues === null)
return res.status(500).json(error(500, req.route.path, 'Alexa.Alarm', 'Invalid "when" format. Expected: YYYY-MM-DD HH:MI:SS'));
let when = new Date(dateValues[1], dateValues[2] - 1, dateValues[3], dateValues[4], dateValues[5], dateValues[6]);
config.logger('{API}: when: ' + when);
alexa.setAlarm(req.query.device, when.getTime(), req.query.recurring, req.query.sound, function(err) {
if (err)
return res.status(500).json(error(500, req.route.path, 'createReminder', err));
res.status(200).json({});
});
});
/***** Get devices *****
URL: /devices
Return the list of Alexa devices
[{
serial - String - Serial number of the device (unique identifier)
name: String - name of the device. Use this name (or serial) to call as "device" parameter of others methods
type: String - Device family as defined by Amazon. Known type: TABLET (for tablet device), ECHO (for ECHO device), WHA (for group of devices), VOX (for smartphone? Webpage?)
online: Boolean - true when the device is connected, false otherwise,
capabilities: [String] - List of available capabilties of the device, few example: VOLUME_SETTING, REMINDERS, MICROPHONE, TUNE_IN, ...
}]
*/
app.get('/devices', (req, res) => {
config.logger('{API} ╔═══════[Lancement '+req.path+' sur '+req.query.device, 'INFO');
res.type('json');
alexa.getDevices(function(devices) {
var toReturn = [];
for (var serial in devices) {
if (devices.hasOwnProperty(serial)) {
var device = devices[serial];
toReturn.push({
'serial': serial,
'name': device.accountName,
'family': device.deviceFamily,
'type': device.deviceType,
'online': device.online,
'capabilities': device.capabilities,
'members': device.clusterMembers
});
}
}
res.status(200).json(toReturn);
});
});
/***** Get devices *****
URL: /devices
Return the list of Alexa devices
[{
serial - String - Serial number of the device (unique identifier)
name: String - name of the device. Use this name (or serial) to call as "device" parameter of others methods
type: String - Device family as defined by Amazon. Known type: TABLET (for tablet device), ECHO (for ECHO device), WHA (for group of devices), VOX (for smartphone? Webpage?)
online: Boolean - true when the device is connected, false otherwise,
capabilities: [String] - List of available capabilties of the device, few example: VOLUME_SETTING, REMINDERS, MICROPHONE, TUNE_IN, ...
}]
*/
// ---- Toutes les commandes qui n'ont pas de paramètres :
CommandAlexa.wakeWords = function(req, res) {
var commandeEnvoyee = req.path.replace("/", "");
config.logger('{API} ╔═══════[Lancement /'+commandeEnvoyee+' sur '+req.query.device, 'INFO');
res.type('json');
Appel_getWakeWords(function(retourAmazon) {
var fichierjson = __dirname + '/data/'+commandeEnvoyee+'.json';
fs.writeFile(fichierjson, JSON.stringify(retourAmazon, null, 2), err =>
{if (err) return res.sendStatus(500);});
res.status(200).json(retourAmazon);
});
};
CommandAlexa.musicProviders = function(req, res) {
var commandeEnvoyee = req.path.replace("/", "");
config.logger('{API} ╔═══════[Lancement /'+commandeEnvoyee+' sur '+req.query.device, 'INFO');
res.type('json');
Appel_getMusicProviders(function(retourAmazon) {
var fichierjson = __dirname + '/data/'+commandeEnvoyee+'.json';
fs.writeFile(fichierjson, JSON.stringify(retourAmazon, null, 2), err =>
{if (err) return res.sendStatus(500);});
res.status(200).json(retourAmazon);
});
};
CommandAlexa.discoverSmarthomeDevice = function(req, res) {
var commandeEnvoyee = req.path.replace("/", "");
config.logger('{API} ╔═══════[Lancement /'+commandeEnvoyee+' sur '+req.query.device, 'INFO');
res.type('json');
Appel_discoverSmarthomeDevice(function(retourAmazon) {
var fichierjson = __dirname + '/data/'+commandeEnvoyee+'.json';
fs.writeFile(fichierjson, JSON.stringify(retourAmazon, null, 2), err =>
{if (err) return res.sendStatus(500);});
res.status(200).json(retourAmazon);
});
};
CommandAlexa.historyFull = function(req, res) {
var commandeEnvoyee = req.path.replace("/", "");
config.logger('{API} ╔═══════[Lancement /'+commandeEnvoyee+' sur '+req.query.device, 'INFO');
res.type('json');
Appel_getHistory(function(retourAmazon) {
var fichierjson = __dirname + '/data/'+commandeEnvoyee+'.json';
fs.writeFile(fichierjson, JSON.stringify(retourAmazon, null, 2), err =>
{if (err) return res.sendStatus(500);});
res.status(200).json(retourAmazon);
});
};
CommandAlexa.devicesFull = function(req, res) {
var commandeEnvoyee = req.path.replace("/", "");
config.logger('{API} ╔═══════[Lancement /'+commandeEnvoyee+' sur '+req.query.device, 'INFO');
res.type('json');
alexa.getDevices(function(retourAmazon) {
var fichierjson = __dirname + '/data/'+commandeEnvoyee+'.json';
fs.writeFile(fichierjson, JSON.stringify(retourAmazon, null, 2), err =>
{if (err) return res.sendStatus(500);});
res.status(200).json(retourAmazon);
});
};
CommandAlexa.devicePreferences = function(req, res) {
var commandeEnvoyee = req.path.replace("/", "");
config.logger('{API} ╔═══════[Lancement /'+commandeEnvoyee+' sur '+req.query.device, 'INFO');
res.type('json');
Appel_getDevicePreferences(function(retourAmazon) {
var fichierjson = __dirname + '/data/'+commandeEnvoyee+'.json';
fs.writeFile(fichierjson, JSON.stringify(retourAmazon, null, 2), err =>
{if (err) return res.sendStatus(500);});
res.status(200).json(retourAmazon);
});
};
CommandAlexa.allDeviceVolumes = function(req, res) {
var commandeEnvoyee = req.path.replace("/", "");
config.logger('{API} ╔═══════[Lancement /'+commandeEnvoyee, 'INFO');
res.type('json');
Appel_getAllDeviceVolumes(function(retourAmazon) {
var fichierjson = __dirname + '/data/'+commandeEnvoyee+'.json';
fs.writeFile(fichierjson, JSON.stringify(retourAmazon, null, 2), err =>
{if (err) return res.sendStatus(500);});
res.status(200).json(retourAmazon);
});
};
CommandAlexa.smarthomeBehaviourActionDefinitions = function(req, res) {
var commandeEnvoyee = req.path.replace("/", "");
config.logger('{API} ╔═══════[Lancement /'+commandeEnvoyee+' sur '+req.query.device, 'INFO');
res.type('json');
Appel_getSmarthomeBehaviourActionDefinitions(function(retourAmazon) {
var fichierjson = __dirname + '/data/'+commandeEnvoyee+'.json';
fs.writeFile(fichierjson, JSON.stringify(retourAmazon, null, 2), err =>
{if (err) return res.sendStatus(500);});
res.status(200).json(retourAmazon);
});
};
CommandAlexa.smarthomeGroups = function(req, res) {
var commandeEnvoyee = req.path.replace("/", "");
config.logger('{API} ╔═══════[Lancement /'+commandeEnvoyee+' sur '+req.query.device, 'INFO');
res.type('json');
Appel_getSmarthomeGroups(function(retourAmazon) {
var fichierjson = __dirname + '/data/'+commandeEnvoyee+'.json';
fs.writeFile(fichierjson, JSON.stringify(retourAmazon, null, 2), err =>
{if (err) return res.sendStatus(500);});
res.status(200).json(retourAmazon);
});
};
CommandAlexa.smarthomeEntities = function(req, res) {
var commandeEnvoyee = req.path.replace("/", "");
config.logger('{API} ╔═══════[Lancement /'+commandeEnvoyee+' sur '+req.query.device, 'INFO');
res.type('json');
Appel_getSmarthomeEntities(function(retourAmazon) {
var fichierjson = __dirname + '/data/'+commandeEnvoyee+'.json';
fs.writeFile(fichierjson, JSON.stringify(retourAmazon, null, 2), err =>
{if (err) return res.sendStatus(500);});
res.status(200).json(retourAmazon);
});
};
CommandAlexa.homeGroup = function(req, res) {
var commandeEnvoyee = req.path.replace("/", "");
config.logger('{API} ╔═══════[Lancement /'+commandeEnvoyee+' sur '+req.query.device, 'INFO');
res.type('json');
Appel_getHomeGroup(function(retourAmazon) {
var fichierjson = __dirname + '/data/'+commandeEnvoyee+'.json';
fs.writeFile(fichierjson, JSON.stringify(retourAmazon, null, 2), err =>
{if (err) return res.sendStatus(500);});
res.status(200).json(retourAmazon);
});
};
CommandAlexa.smarthomeDevices = function(req, res) {
var commandeEnvoyee = req.path.replace("/", "");
config.logger('{API} ╔═══════[Lancement /'+commandeEnvoyee+' sur '+req.query.device, 'INFO');
res.type('json');
Appel_getSmarthomeDevices(function(retourAmazon) {
var fichierjson = __dirname + '/data/'+commandeEnvoyee+'.json';
fs.writeFile(fichierjson, JSON.stringify(retourAmazon, null, 2), err =>
{if (err) return res.sendStatus(500);});
res.status(200).json(retourAmazon);
});
};
CommandAlexa.remindersFull = function(req, res) {
var commandeEnvoyee = req.path.replace("/", "");
config.logger('{API} ╔═══════[Lancement /'+commandeEnvoyee+' sur '+req.query.device, 'INFO');
res.type('json');
Appel_getNotifications(function(retourAmazon) {
var fichierjson = __dirname + '/data/'+commandeEnvoyee+'.json';
fs.writeFile(fichierjson, JSON.stringify(retourAmazon, null, 2), err =>
{if (err) return res.sendStatus(500);});
res.status(200).json(retourAmazon);
});
};
CommandAlexa.carts = function(req, res) {
var commandeEnvoyee = req.path.replace("/", "");
config.logger('{API} ╔═══════[Lancement /'+commandeEnvoyee+' sur '+req.query.device, 'INFO');
res.type('json');
Appel_getCards(function(retourAmazon) {
var fichierjson = __dirname + '/data/'+commandeEnvoyee+'.json';
fs.writeFile(fichierjson, JSON.stringify(retourAmazon, null, 2), err =>
{if (err) return res.sendStatus(500);});
res.status(200).json(retourAmazon);
});
};
CommandAlexa.deviceStatusList = function(req, res) {
var commandeEnvoyee = req.path.replace("/", "");
config.logger('{API} ╔═══════[Lancement /'+commandeEnvoyee+' sur '+req.query.device, 'INFO');
res.type('json');
Appel_getDeviceStatusList(function(retourAmazon) {
var fichierjson = __dirname + '/data/'+commandeEnvoyee+'.json';
fs.writeFile(fichierjson, JSON.stringify(retourAmazon, null, 2), err =>
{if (err) return res.sendStatus(500);});
res.status(200).json(retourAmazon);
});
};
CommandAlexa.lists = function(req, res) {
var commandeEnvoyee = req.path.replace("/", "");
config.logger('{API} ╔═══════[Lancement /'+commandeEnvoyee+' sur '+req.query.device, 'INFO');
res.type('json');
Appel_getLists(function(retourAmazon) {
var fichierjson = __dirname + '/data/'+commandeEnvoyee+'.json';
fs.writeFile(fichierjson, JSON.stringify(retourAmazon, null, 2), err =>
{if (err) return res.sendStatus(500);});
res.status(200).json(retourAmazon);
});
};
/*
CommandAlexa.doNotDisturb = function(req, res) {
var commandeEnvoyee = req.path.replace("/", "");
config.logger('{API} ╔═══════[Lancement /'+commandeEnvoyee+' sur '+req.query.device, 'INFO');
res.type('json');
Appel_getDoNotDisturb(function(retourAmazon) {
var fichierjson = __dirname + '/data/'+commandeEnvoyee+'.json';
fs.writeFile(fichierjson, JSON.stringify(retourAmazon, null, 2), err =>
{if (err) return res.sendStatus(500);});
res.status(200).json(retourAmazon);
});
};*/
// ---- Toutes les commandes qui ont DEVICE comme paramètre
CommandAlexa.media = function(req, res) {
var commandeEnvoyee = req.path.replace("/", "");
config.logger('{API} ╔═══════[Lancement /'+commandeEnvoyee+' sur '+req.query.device, 'INFO');
res.type('json');
if ('device' in req.query === false) return res.status(500).json(error(500, req.route.path, 'Alexa.'+commandeEnvoyee, 'Missing "device"'));
//config.logger('{API} ╠═══> Device : ' + req.query.device, 'DEBUG');
Appel_getMedia(req.query.device, function(retourAmazon) {
var fichierjson = __dirname + '/data/'+commandeEnvoyee+'-'+req.query.device+'.json';
if(typeof JSON.stringify(retourAmazon, null, 2) == "undefined") {
config.logger('{API} ╠═══> Réponse est undefined - A voir pourquoi ?!', 'DEBUG');
return res.sendStatus(500);
}
fs.writeFile(fichierjson, JSON.stringify(retourAmazon, null, 2), err =>
{if (err) return res.sendStatus(500);});
res.status(200).json(retourAmazon);
});
};
CommandAlexa.playerInfo = function(req, res) {
var commandeEnvoyee = req.path.replace("/", "");
config.logger('{API} ╔═══════[Lancement /'+commandeEnvoyee+' sur '+req.query.device, 'INFO');
res.type('json');
if ('device' in req.query === false) return res.status(500).json(error(500, req.route.path, 'Alexa.'+commandeEnvoyee, 'Missing "device"'));
config.logger('{API} ╠═══> Device : ' + req.query.device, 'DEBUG');
Appel_getPlayerInfo(req.query.device, function(retourAmazon) {
var fichierjson = __dirname + '/data/'+commandeEnvoyee+'-'+req.query.device+'.json';
if(typeof JSON.stringify(retourAmazon, null, 2) == "undefined") {
config.logger('{API} ╠═══> Réponse est undefined - A voir pourquoi ?!', 'DEBUG');
return res.sendStatus(500);
}
fs.writeFile(fichierjson, JSON.stringify(retourAmazon, null, 2), err =>
{if (err) return res.sendStatus(500);});
res.status(200).json(retourAmazon);
});
};
CommandAlexa.Bluetooth = function(req, res) {
var commandeEnvoyee = req.path.replace("/", "");
config.logger('{API}: **************/'+commandeEnvoyee);
res.type('json');
Appel_getBluetooth(false, function(retourAmazon) {
var fichierjson = __dirname + '/data/'+commandeEnvoyee+'-'+req.query.device+'.json';
fs.writeFile(fichierjson, JSON.stringify(retourAmazon, null, 2), err =>
{if (err) return res.sendStatus(500);});
res.status(200).json(retourAmazon);
});
};
CommandAlexa.notificationSounds = function(req, res) {
var commandeEnvoyee = req.path.replace("/", "");
config.logger('{API}: **************/'+commandeEnvoyee);
res.type('json');
if ('device' in req.query === false) return res.status(500).json(error(500, req.route.path, 'Alexa.'+commandeEnvoyee, 'Missing "device"'));
config.logger('{API} ╠═══> Device : ' + req.query.device, 'DEBUG');
Appel_getNotificationSounds(req.query.device, function(retourAmazon) {
var fichierjson = __dirname + '/data/'+commandeEnvoyee+'-'+req.query.device+'.json';
fs.writeFile(fichierjson, JSON.stringify(retourAmazon, null, 2), err =>
{if (err) return res.sendStatus(500);});
res.status(200).json(retourAmazon);
});
};
CommandAlexa.Playlists = function(req, res) {
var commandeEnvoyee = req.path.replace("/", "");
config.logger('{API} ╔═══════[Lancement /'+commandeEnvoyee+' sur '+req.query.device, 'INFO');
res.type('json');
if ('device' in req.query === false) return res.status(500).json(error(500, req.route.path, 'Alexa.'+commandeEnvoyee, 'Missing "device"'));
config.logger('{API} ╠═══> Device : ' + req.query.device, 'DEBUG');
Appel_Playlists(req.query.device, function(retourAmazon) {
//config.logger('{API}: retour: ' + commandeEnvoyee);
var fichierjson = __dirname + '/data/'+commandeEnvoyee+'-'+req.query.device+'.json';
fs.writeFile(fichierjson, JSON.stringify(retourAmazon, null, 2), err =>
{if (err) return res.sendStatus(500);});
res.status(200).json(retourAmazon);
});
};
CommandAlexa.activities = function(req, res) {
var commandeEnvoyee = req.path.replace("/", "");
config.logger('{API} ╔═══════[Lancement /'+commandeEnvoyee+' sur '+req.query.device, 'INFO');
res.type('json');
if ('device' in req.query === false) return res.status(500).json(error(500, req.route.path, 'Alexa.'+commandeEnvoyee, 'Missing "device"'));
config.logger('{API} ╠═══> Device : ' + req.query.device, 'DEBUG');
Appel_getActivities(req.query.device, function(retourAmazon) {
var fichierjson = __dirname + '/data/'+commandeEnvoyee+'-'+req.query.device+'.json';
fs.writeFile(fichierjson, JSON.stringify(retourAmazon, null, 2), err =>
{if (err) return res.sendStatus(500);});
res.status(200).json(retourAmazon);
});
};
CommandAlexa.deviceNotificationState = function(req, res) {
var commandeEnvoyee = req.path.replace("/", "");
config.logger('{API} ╔═══════[Lancement /'+commandeEnvoyee+' sur '+req.query.device, 'INFO');
res.type('json');
if ('device' in req.query === false) return res.status(500).json(error(500, req.route.path, 'Alexa.'+commandeEnvoyee, 'Missing "device"'));
config.logger('{API} ╠═══> Device : ' + req.query.device, 'DEBUG');
Appel_getDeviceNotificationState(req.query.device, function(retourAmazon) {
var fichierjson = __dirname + '/data/'+commandeEnvoyee+'-'+req.query.device+'.json';
fs.writeFile(fichierjson, JSON.stringify(retourAmazon, null, 2), err =>
{if (err) return res.sendStatus(500);});
res.status(200).json(retourAmazon);
});
};
// ---- Functions d'appel des Commandes de la librairie
function Appel_getWakeWords(callback)
{
alexa.getWakeWords((err, res) => {if (err || !res || !res.wakeWords || !Array.isArray(res.wakeWords)) return callback && callback();
callback && callback(res);});
}
function Appel_getDevicePreferences(callback)
{
alexa.getDevicePreferences((err, res) => {if (err) return callback && callback();
callback && callback(res);});
}
function Appel_getAllDeviceVolumes(callback)
{
alexa.getAllDeviceVolumes((err, res) => {if (err) return callback && callback();
callback && callback(res);});
}
function Appel_getMusicProviders(callback)
{
alexa.getMusicProviders((err, res) => {if (err) return callback && callback();
callback && callback(res);});
}
function Appel_getHistory(callback)
{
//!!!!!!!!!!! remplacé alexa.getHistory((err, res) => {if (err) return callback && callback();
alexa.getCustomerHistoryRecords((err, res) => {if (err) return callback && callback();
callback && callback(res);});
}
function Appel_getDeviceNotificationState(serialOrName,callback)
{
alexa.getDeviceNotificationState(serialOrName,(err, res) => {if (err) return callback && callback();
callback && callback(res);});
}
function Appel_getNotifications(callback)
{
alexa.getNotifications((err, res) => {if (err) return callback && callback();
callback && callback(res);});
}
function Appel_getSmarthomeBehaviourActionDefinitions(callback)
{
alexa.getSmarthomeBehaviourActionDefinitions((err, res) => {if (err) return callback && callback();
callback && callback(res);});
}
function Appel_getCards(callback)
{
alexa.getCards((err, res) => {if (err) return callback && callback();
callback && callback(res);});
}
function Appel_getSmarthomeGroups(callback)
{
alexa.getSmarthomeGroups((err, res) => {if (err) return callback && callback();
callback && callback(res);});
}
function Appel_getSmarthomeEntities(callback)
{
alexa.getSmarthomeEntities((err, res) => {if (err) return callback && callback();
callback && callback(res);});
}
function Appel_getHomeGroup(callback)
{
alexa.getHomeGroup((err, res) => {if (err) return callback && callback();
callback && callback(res);});
}
function Appel_discoverSmarthomeDevice(callback)
{
alexa.discoverSmarthomeDevice((err, res) => {if (err) return callback && callback();
callback && callback(res);});
}
function Appel_getSmarthomeDevices(callback)
{
alexa.getSmarthomeDevices((err, res) => {if (err) return callback && callback();
callback && callback(res);});
}
function Appel_getDeviceStatusList(callback)
{
alexa.getDeviceStatusList((err, res) => {if (err) return callback && callback();
callback && callback(res);});
}
function Appel_getLists(callback)
{
alexa.getLists((err, res) => {if (err) return callback && callback();
callback && callback(res);});
}
function Appel_Playlists(serialOrName,callback)
{
alexa.Playlists(serialOrName,(err, res) => {if (err) return callback && callback();
callback && callback(res);});
}
/*
function Appel_getDoNotDisturb(callback)
{
alexa.getDoNotDisturb((err, res) => {if (err) return callback && callback();
callback && callback(res);});
} */
function Appel_getMedia(serialOrName,callback)
{
alexa.getMedia(serialOrName,(err, res) => {if (err || !res ) return callback && callback();
callback && callback(res);});
}
function Appel_getPlayerInfo(serialOrName,callback)
{
alexa.getPlayerInfo(serialOrName,(err, res) => {if (err || !res ) return callback && callback();
callback && callback(res);});
}
function Appel_getBluetooth(cached,callback)
{
alexa.getBluetooth(cached,(err, res) => {if (err || !res ) return callback && callback();
callback && callback(res);});
}
function Appel_getNotificationSounds(serialOrName, callback)
{
alexa.getNotificationSounds(serialOrName,(err, res) => {if (err || !res ) return callback && callback();
callback && callback(res);});
}
function Appel_getActivities(serialOrName,callback)
{
alexa.getActivities(serialOrName,(err, res) => {if (err || !res ) return callback && callback();
callback && callback(res);});
}
// Tous les appels GET
app.get('/wakeWords', CommandAlexa.wakeWords);
app.get('/media', CommandAlexa.media);
app.get('/playerInfo', CommandAlexa.playerInfo);
app.get('/bluetooth', CommandAlexa.Bluetooth);
app.get('/notificationSounds', CommandAlexa.notificationSounds);
app.get('/activities', CommandAlexa.activities);
app.get('/devicePreferences', CommandAlexa.devicePreferences);
app.get('/allDeviceVolumes', CommandAlexa.allDeviceVolumes); //http://192.168.1.21:3456/allDeviceVolumes affiche tous les volumes, à voir l'utilité !
app.get('/homeGroup', CommandAlexa.homeGroup);
app.get('/smarthomeDevices', CommandAlexa.smarthomeDevices);
app.get('/smarthomeBehaviourActionDefinitions', CommandAlexa.smarthomeBehaviourActionDefinitions);
app.get('/smarthomeGroups', CommandAlexa.smarthomeGroups);
app.get('/smarthomeEntities', CommandAlexa.smarthomeEntities);
app.get('/devicesFull', CommandAlexa.devicesFull);
app.get('/historyFull', CommandAlexa.historyFull);
app.get('/discoverSmarthomeDevice', CommandAlexa.discoverSmarthomeDevice);
app.get('/musicProviders', CommandAlexa.musicProviders);
app.get('/remindersFull', CommandAlexa.remindersFull);
app.get('/lists', CommandAlexa.lists);
app.get('/carts', CommandAlexa.carts);
app.get('/deviceNotificationState', CommandAlexa.deviceNotificationState);
app.get('/deviceStatusList', CommandAlexa.deviceStatusList);
app.get('/playlists', CommandAlexa.Playlists);
app.get('/playlist', CommandAlexa.playList);
app.get('/playmusictrack', CommandAlexa.playMusicTrack);
app.get('/getvolume', (req, res) => {
res.type('json');
config.logger('{API} ╔═══════[Lancement '+req.path+' sur '+req.query.device, 'INFO');
if ('device' in req.query === false)
return res.status(500).json(error(500, req.route.path, 'Alexa.getVolume', 'Missing parameter "device"'));
config.logger('{API} ╠═══> Device : ' + req.query.device, 'DEBUG');
//var valeurvolume="";
alexa.getMedia2(req.query.device, function(devices) {
//var toReturn = [];
config.logger('{API}: trouve volume :'+devices.volume);
//valeurvolume=devices["volume"];
res.status(200).json({ value: devices.volume });
});
});
app.get('/history', (req, res) => {
config.logger('{API} ╔═══════[Lancement '+req.path+' sur '+req.query.device, 'INFO');
res.type('json');
if ('maxRecordSize' in req.query === false)
req.query.maxRecordSize = 5;
if ('recordType' in req.query === false)
req.query.recordType = 'VOICE_HISTORY';
const options = {
maxRecordSize: req.query.maxRecordSize,
recordType: req.query.recordType
};
alexa.getHistory2(options, function(devices) {
var toReturn = [];
//console.log(devices);
for (var serial in devices) {
if (devices.hasOwnProperty(serial)) {
var activities = devices[activities];
var device = devices[serial];
toReturn.push({
'serial': serial,
'activityStatus': device.activityStatus,
'deviceSerialNumber': device.deviceSerialNumber,
'creationTimestamp': device.creationTimestamp,
'summary': device.description.summary
});
}
}
res.status(200).json(toReturn);
});
});
/***** routines *****
URL: /routines
*/
app.get('/routines', (req, res) => {
config.logger('{API} ╔═══════[Lancement '+req.path, 'INFO');
res.type('json');
//config.logger('{API}: type of devices : '+typeof devices);
alexa.getAutomationRoutines2(function(niveau0) {
//devices='{"notifications":'+devices+'}';
//config.logger('{API}: routines2');
// config.logger(JSON.stringify(devices));
// config.logger(devices);
//config.logger('{API}: type of devices : '+typeof devices);
var resultatutterance;
var resultatlocale;
var resultattriggerTime;
var resultattimeZoneId;
var resultatrecurrence;
//config.logger('{API}: routines3b2');
var toReturn = [];
// config.logger('************DEBUG DE ROUTINES*******************');
// config.logger('************Résultat de la requète Routines : '+JSON.stringify(niveau0));
for (var serial in niveau0) {
if (niveau0.hasOwnProperty(serial)) {
//config.logger('************************************************');
var routine = niveau0[serial];
//config.logger('(general)----- '+routine.status);
//config.logger('(general)----- '+routine.creationTimeEpochMillis);
if (routine.status === 'ENABLED') {
//config.logger('(SUPPRESSION)----- '+routine.creationTimeEpochMillis);
alexa.executeAutomationRoutine("", routine, function(err) {
//config.logger('(SUPPRESSION DEDANS)----- '+routine.creationTimeEpochMillis);
//executeAutomationRoutine(serialOrName, routine, callback)
//res.status(200).json({});
});
//config.logger('(SUPPRESSION)----- '+routine.creationTimeEpochMillis);
}
for (var serial2 in routine.triggers) {
if (routine.triggers.hasOwnProperty(serial2)) {
var niveau2 = routine.triggers[serial2];
resultatutterance = "";
resultatlocale = "";
resultattriggerTime = "";
resultattimeZoneId = "";
resultatrecurrence = "";
for (var triggers in niveau2.payload) { //Partie PAYLOAD
if (niveau2.payload.hasOwnProperty(triggers)) {
var niveau3 = niveau2.payload[triggers];
//config.logger('(triggers1)----- '+triggers.locale);
//config.logger('(triggers2)----- '+niveau3.locale);
//config.logger('(triggers3)----- '+triggers+' : '+niveau3);
switch (triggers) {
case 'utterance':
resultatutterance = niveau3;
break;
case 'locale':
resultatlocale = niveau3;
break;
case 'schedule':
for (var schedule in niveau3) { //Partie schedule
if (niveau3.hasOwnProperty(schedule)) {
var niveau4 = niveau3[schedule];
//config.logger('(schedule)----- '+schedule+' : '+niveau4);
switch (schedule) {
case 'triggerTime':
resultattriggerTime = niveau4;
break;
case 'timeZoneId':
resultattimeZoneId = niveau4;
break;
case 'recurrence':
resultatrecurrence = niveau4;
break;
}
}
}
break;
}
}
}
}
}
/*
for (Var serial2 in routine.sequence) //partie SEQUENCE non utilisé à ce stade
{
var niveau2 = routine[serial2];
config.logger('(sequence)----- '+serial2+' : '+niveau2);
}
*/
toReturn.push({
'status': routine.status,
'locale': resultatlocale,
'utterance': resultatutterance,
'triggerTime': resultattriggerTime,
'timeZoneId': resultattimeZoneId,
'recurrence': resultatrecurrence,
'creationTimeEpochMillis': routine.creationTimeEpochMillis,
'lastUpdatedTimeEpochMillis': routine.lastUpdatedTimeEpochMillis
// 'members': device.clusterMembers
});
}
}
res.status(200).json(toReturn);
});
});
/***** Reminders *****
URL: /reminders
Return the list of reminders
[{
serial - String - Serial nu=mber of the device (unique identifier)
name: String - name of the device. Use this name (or serial) to call as "device" parameter of others methods
type: String - Device family as defined by Amazon. Known type: TABLET (for tablet device), ECHO (for ECHO device), WHA (for group of devices), VOX (for smartphone? Webpage?)
online: Boolean - true when the device is connected, false oe,
capabilities: [String] - List of available capabilties of the device, few example: VOLUME_SETTING, REMINDERS, MICROPHONE, TUNE_IN, ...
}]
*/
app.get('/reminders', (req, res) => {
config.logger('{API} ╔═══════[Lancement '+req.path+' sur '+req.query.device, 'INFO');
res.type('json');
//config.logger('{API}: (reminders) Lancement','DEBUG');
alexa.getNotifications2(function(notifications) {
//config.logger('{API}: (reminders) function','DEBUG');
var toReturn = [];
for (var serial in notifications) {
if (notifications.hasOwnProperty(serial)) {
var device = notifications[serial];
toReturn.push({
'serial': serial,
'deviceSerialNumber': device.deviceSerialNumber,
'type': device.type,
'originalTime': device.originalTime,
'musicEntity': device.musicEntity,
'soundDisplayName': device.sound.displayName,
'originalDate': device.originalDate,
'remainingTime': device.remainingTime,
'status': device.status,
'recurringPattern': device.recurringPattern,
'reminderLabel': device.reminderLabel,
'id': device.id
});
}
}
res.status(200).json(toReturn);
});
});
/***** DeleteAllAlarms *****
URL: /deleteallalarms
Supprime toutes les alamrmes et/ou tous les rappels
[{
}]
*/
app.get('/deleteallalarms', (req, res) => {
config.logger('{API} ╔═══════[Lancement '+req.path+' sur '+req.query.device, 'INFO');
res.type('json');
alexa.getNotifications2(function(notifications) {
//var toReturn = [];
//config.logger('{API} - prepa boucle 1:'+JSON.stringify(notifications),'INFO');
//config.logger('{API} - prepa boucle 1 nb:'+Object.keys(notifications).length,'INFO');
// Filtre et ne garde que les enregistrements du device selctionné
const notificationsfiltrees = notifications.filter(tmp => tmp.deviceSerialNumber == req.query.device);
notifications = notificationsfiltrees;
//config.logger('{API} - on filtre sur req.query.device:'+req.query.device,'INFO');
//config.logger('{API} - prepa boucle 2:'+JSON.stringify(notifications),'INFO');
//config.logger('{API} - prepa boucle 2 nb:'+Object.keys(notifications).length,'INFO');
//config.logger('{API} - deleteallalarms req.query.type: ' + req.query.type,'DEBUG');
//config.logger('{API} - on filtre sur req.query.type:'+req.query.type,'INFO');
if ((req.query.type != 'all') && (req.query.type != 'ALL')) {
var notificationsfiltrees1;
if ((req.query.type.toUpperCase() == 'reminder'.toUpperCase()) || (req.query.type.toUpperCase() == 'reminders'.toUpperCase()))
notificationsfiltrees1 = notifications.filter(tmp => tmp.type == "Reminder");
else
notificationsfiltrees1 = notifications.filter(tmp => tmp.type == "Alarm"); //Par défaut donc
notifications = notificationsfiltrees1;
}
//config.logger('{API} - prepa boucle 3:'+JSON.stringify(notifications),'INFO');
//config.logger('{API} - prepa boucle 3 nb:'+Object.keys(notifications).length,'INFO');
// Filtre et ne garde que les enregistrements qui ont un status qui correspond à req.query.status
if ((req.query.status != 'all') && (req.query.status != 'ALL')) {
var FiltreSurStatus = 'ON';
if ((req.query.status == 'off') || (req.query.status == 'OFF')) FiltreSurStatus = 'OFF';
const notificationsfiltrees2 = notifications.filter(tmp => tmp.status == FiltreSurStatus);
notifications = notificationsfiltrees2;
}
//config.logger('{API} - prepa boucle 5:'+JSON.stringify(notifications),'INFO');
config.logger('{API} - prepa boucle 5 nb:'+Object.keys(notifications).length,'INFO');
for (var serial in notifications) {
//config.logger('{API} - boucle ','INFO');
if (notifications.hasOwnProperty(serial)) {
// On va parcourir les résultats et supprimer chaque enregistrement
var device = notifications[serial];
config.logger('{API} - DeleteAllAlarms delete id: ' + device.id);
const notification = {
'id': device.id
};
//config.logger('{API} - AVANT deleteallalarms device.id: ' + device.id,'INFO');
alexa.deleteNotification(notification, function(err) {});
}
}
});
res.status(200).json({
value: "Fini"
});
});
/***** WhenNextAlarm *****
URL: /whennextalarm
Return la prochaine alarme
[{
position => 1= prochaine 2=suivante ...
status => Filtre sur le status (active=ON, désactive=OFF, Tous =ALL)
format => Format du résultat (HOUR=réduit HH:SS)
}]
*/
app.get('/whennextalarm', (req, res) => {
config.logger('{API} ╔═══════[Lancement '+req.path+' sur '+req.query.device, 'INFO');
res.type('json');
alexa.getNotifications2(function(notifications) {
//config.logger('{API}: (WhenNextAlarm) function' );
//var toReturn = [];
if (isEmpty(notifications))
return res.status(500).json(error(500, req.route.path, 'Alexa.whennextalarm', 'Retour vide'));
// Filtre et ne garde que les enregistrements du device selctionné
const notificationsfiltrees = notifications.filter(tmp => tmp.deviceSerialNumber == req.query.device);
notifications = notificationsfiltrees;
// Filtre et ne garde que les enregistrements qui ont le type ALARM
const notificationsfiltrees1 = notifications.filter(tmp => tmp.type == "Alarm");
notifications = notificationsfiltrees1;
// Filtre et ne garde que les enregistrements qui sont supérieure à l'heure du jour
//Maintenant :
var d = new Date();
var date_format_str = d.getFullYear().toString() + "-" + ((d.getMonth() + 1).toString().length == 2 ? (d.getMonth() + 1).toString() : "0" + (d.getMonth() + 1).toString()) + "-" + (d.getDate().toString().length == 2 ? d.getDate().toString() : "0" + d.getDate().toString()) + " " + (d.getHours().toString().length == 2 ? d.getHours().toString() : "0" + d.getHours().toString()) + ":" + ((parseInt(d.getMinutes() / 5) * 5).toString().length == 2 ? (parseInt(d.getMinutes() / 5) * 5).toString() : "0" + (parseInt(d.getMinutes() / 5) * 5).toString()) + ":00";
const notificationsfiltrees4 = notifications.filter(tmp => (tmp.originalDate + ' ' + tmp.originalTime > date_format_str));
notifications = notificationsfiltrees4;
// Filtre et ne garde que les enregistrements qui ont un status qui correspond à req.query.status
if ((req.query.status != 'all') && (req.query.status != 'ALL')) {
var FiltreSurStatus = 'ON';
if ((req.query.status == 'off') || (req.query.status == 'OFF')) FiltreSurStatus = 'OFF';
const notificationsfiltrees2 = notifications.filter(tmp => tmp.status == FiltreSurStatus);
notifications = notificationsfiltrees2;
}
// Trie par Date/Heure
const notificationsfiltrees3 = notifications.sort(function(a, b) {
var x = a.originalDate + a.originalTime;
var y = b.originalDate + b.originalTime;
return ((x < y) ? -1 : ((x > y) ? 1 : 0));
});
notifications = notificationsfiltrees3;
var compteurdePosition = 1;
var compteurdePositionaTrouver = 1;
var stringarenvoyer = 'none';
if (req.query.position > 1) {
compteurdePositionaTrouver = req.query.position;
}
for (var serial in notifications) {
if (notifications.hasOwnProperty(serial)) {
// On va parcourir les résultats en allant à la position demandée.
if (compteurdePositionaTrouver == compteurdePosition) {
var device = notifications[serial];
switch (req.query.format) {
case 'hour':
case 'HOUR':
stringarenvoyer = device.originalTime.substring(0, 5);
break;
case 'full':
case 'FULL':
stringarenvoyer = device.originalDate + " " + device.originalTime;
break;
default: //ou HHMM
stringarenvoyer = device.originalTime.substring(0, 5).replace(':', ''); // Utilisation du format HH:MM
}
}
compteurdePosition++;
}
}
res.status(200).json({
value: stringarenvoyer
});
});
});
/***** updateallalarms *****
URL: /updateallalarms
*/
app.get('/updateallalarms', (req, res) => {
config.logger('{API} ╔═══════[Lancement '+req.path+' sur '+req.query.device, 'INFO');
res.type('json');
// c'était pour générer la liste des devices
/*alexa.getDevices(function(devices) {
var lesDevices = [];
for (var serial in devices) {lesDevices.push(serial);}
config.logger('{API}: DEVICES '+JSON.stringify(lesDevices), 'INFO');
*/
function ajouteZero(n){
if(n <= 9){
return "0" + n;
}
return n;
}
alexa.getNotifications2(function(notifications) {
//config.logger('{API}: (WhenNextAlarm) function' );
//var toReturn = [];
if (isEmpty(notifications))
return res.status(500).json(error(500, req.route.path, 'Alexa.updateallalarms', 'Retour vide'));
// Filtre et ne garde que les enregistrements du device selctionné
const notificationsfiltrees = notifications.filter(tmp => tmp.deviceSerialNumber == req.query.device);
notifications = notificationsfiltrees;
// Filtre et ne garde que les enregistrements qui sont supérieure à l'heure du jour
//Maintenant :
var d = new Date();
var date_format_str = d.getFullYear().toString() + "-" + ((d.getMonth() + 1).toString().length == 2 ? (d.getMonth() + 1).toString() : "0" + (d.getMonth() + 1).toString()) + "-" + (d.getDate().toString().length == 2 ? d.getDate().toString() : "0" + d.getDate().toString()) + " " + (d.getHours().toString().length == 2 ? d.getHours().toString() : "0" + d.getHours().toString()) + ":" + ((parseInt(d.getMinutes() / 5) * 5).toString().length == 2 ? (parseInt(d.getMinutes() / 5) * 5).toString() : "0" + (parseInt(d.getMinutes() / 5) * 5).toString()) + ":00";
const notificationsfiltrees4 = notifications.filter(tmp => (tmp.originalDate + ' ' + tmp.originalTime > date_format_str));
notifications = notificationsfiltrees4;
// Filtre et ne garde que les enregistrements qui ont un status qui correspond à req.query.status
//if ((req.query.status != 'all') && (req.query.status != 'ALL')) {
var FiltreSurStatus = 'ON';
//if ((req.query.status == 'off') || (req.query.status == 'OFF')) FiltreSurStatus = 'OFF';
const notificationsfiltrees2 = notifications.filter(tmp => tmp.status == FiltreSurStatus);
notifications = notificationsfiltrees2;
//}
// Trie par Date/Heure
const notificationsfiltrees3 = notifications.sort(function(a, b) {
var x = a.originalDate + a.originalTime;
var y = b.originalDate + b.originalTime;
return ((x < y) ? -1 : ((x > y) ? 1 : 0));
});
notifications = notificationsfiltrees3;
var whennextmusicalalarminfo='none';
var musicalalarmmusicentityinfo='';
var whennextreminderinfo='none';
var whennextreminderlabelinfo='';
var whennextalarminfo='none';
whennextmusicalalarminfo='none';
whennextreminderinfo='none';
var whennexttimerinfo='none';
var toReturn = [];
var original;
// Filtre et ne garde que les enregistrements qui ont le type ALARM
const quelesAlarmes = notifications.filter(tmp => tmp.type == "Alarm");
let device=quelesAlarmes.shift();
if (device) {
//var h=device.originalTime;
//var d=device.originalDate;
original=new Date(device.originalDate + ' ' + device.originalTime);
let formatted_date = original.getFullYear() + "-" + ajouteZero(original.getMonth() + 1) + "-" + ajouteZero(original.getDate()) + " " + ajouteZero(original.getHours()) + ":" + ajouteZero(original.getMinutes()) + ":" + ajouteZero(original.getSeconds());
whennextalarminfo=formatted_date;
}
const quelesMinuteurs = notifications.filter(tmp => tmp.type == "Timer");
device=quelesMinuteurs.shift();
// config.logger('{API}: (---) :'+JSON.stringify(device));
//config.logger('{API}: (---) :'+device.remainingTime);
if (device) {
let A = new Date();
A.setSeconds(device.remainingTime/1000);
var secondes = A.getSeconds();
if(secondes < 10)
secondes = "0" + secondes;
var minutes = A.getMinutes();
if(minutes < 10)
minutes = "0" + minutes;
var jours = A.getDate();
if(jours < 10)
jours = "0" + jours;
var month = [];
month[0] = "01";
month[1] = "02";
month[2] = "03";
month[3] = "04";
month[4] = "05";
month[5] = "06";
month[6] = "07";
month[7] = "08";
month[8] = "09";
month[9] = "10";
month[10] = "11";
month[11] = "12";
//whennexttimerinfo=minutes+" "+A.getHours()+" "+jours+ " "+month[A.getMonth()]+ " "+A.getDay()+ " "+A.getFullYear();
whennexttimerinfo=A.getFullYear()+"-"+month[A.getMonth()]+"-"+jours+ " "+A.getHours()+":"+minutes+":"+secondes;
//2019-12-02 19:04:01
}
const quelesAlarmesMusicales = notifications.filter(tmp => tmp.type == "MusicAlarm");
device=quelesAlarmesMusicales.shift();
if (device) {
original=new Date(device.originalDate + ' ' + device.originalTime);
let formatted_date = original.getFullYear() + "-" + ajouteZero(original.getMonth() + 1) + "-" + ajouteZero(original.getDate()) + " " + ajouteZero(original.getHours()) + ":" + ajouteZero(original.getMinutes()) + ":" + ajouteZero(original.getSeconds());
whennextmusicalalarminfo=formatted_date;
musicalalarmmusicentityinfo=device.musicEntity;
}
const quelesRappels = notifications.filter(tmp => tmp.type == "Reminder");
device=quelesRappels.shift();
if (device) {
original=new Date(device.originalDate + ' ' + device.originalTime);
let formatted_date = original.getFullYear() + "-" + ajouteZero(original.getMonth() + 1) + "-" + ajouteZero(original.getDate()) + " " + ajouteZero(original.getHours()) + ":" + ajouteZero(original.getMinutes()) + ":" + ajouteZero(original.getSeconds());
whennextreminderinfo=formatted_date;
whennextreminderlabelinfo=device.reminderLabel;
}
toReturn.push({
'musicalalarmmusicentityinfo': musicalalarmmusicentityinfo,
'whennextalarminfo': whennextalarminfo,
'whennextmusicalalarminfo': whennextmusicalalarminfo,
'whennextreminderinfo': whennextreminderinfo,
'whennexttimerinfo': whennexttimerinfo,
'whennextreminderlabelinfo': whennextreminderlabelinfo
});
res.status(200).json(toReturn);
});
//});// retour de alexa.getDevices
});
/***** WhenNextMusicalAlarm *****
URL: /whennextalarm
Return la prochaine alarme musicale
[{
position => 1= prochaine 2=suivante ...
status => Filtre sur le status (active=ON, désactive=OFF, Tous =ALL)
format => Format du résultat (HOUR=réduit HH:SS)
}]
*/
app.get('/whennextmusicalalarm', (req, res) => {
config.logger('{API} ╔═══════[Lancement '+req.path+' sur '+req.query.device, 'INFO');
res.type('json');
alexa.getNotifications2(function(notifications) {
//config.logger('{API}: (WhenNextAlarm) function' );
//var toReturn = [];
if (isEmpty(notifications))
return res.status(500).json(error(500, req.route.path, 'Alexa.whennextalarm', 'Retour vide'));
// Filtre et ne garde que les enregistrements du device selctionné
const notificationsfiltrees = notifications.filter(tmp => tmp.deviceSerialNumber == req.query.device);
notifications = notificationsfiltrees;
// Filtre et ne garde que les enregistrements qui ont le type ALARM
const notificationsfiltrees1 = notifications.filter(tmp => tmp.type == "MusicAlarm");
notifications = notificationsfiltrees1;
// Filtre et ne garde que les enregistrements qui sont supérieure à l'heure du jour
//Maintenant :
var d = new Date();
var date_format_str = d.getFullYear().toString() + "-" + ((d.getMonth() + 1).toString().length == 2 ? (d.getMonth() + 1).toString() : "0" + (d.getMonth() + 1).toString()) + "-" + (d.getDate().toString().length == 2 ? d.getDate().toString() : "0" + d.getDate().toString()) + " " + (d.getHours().toString().length == 2 ? d.getHours().toString() : "0" + d.getHours().toString()) + ":" + ((parseInt(d.getMinutes() / 5) * 5).toString().length == 2 ? (parseInt(d.getMinutes() / 5) * 5).toString() : "0" + (parseInt(d.getMinutes() / 5) * 5).toString()) + ":00";
const notificationsfiltrees4 = notifications.filter(tmp => (tmp.originalDate + ' ' + tmp.originalTime > date_format_str));
notifications = notificationsfiltrees4;
// Filtre et ne garde que les enregistrements qui ont un status qui correspond à req.query.status
if ((req.query.status != 'all') && (req.query.status != 'ALL')) {
var FiltreSurStatus = 'ON';
if ((req.query.status == 'off') || (req.query.status == 'OFF')) FiltreSurStatus = 'OFF';
const notificationsfiltrees2 = notifications.filter(tmp => tmp.status == FiltreSurStatus);
notifications = notificationsfiltrees2;
}
// Trie par Date/Heure
const notificationsfiltrees3 = notifications.sort(function(a, b) {
var x = a.originalDate + a.originalTime;
var y = b.originalDate + b.originalTime;
return ((x < y) ? -1 : ((x > y) ? 1 : 0));
});
notifications = notificationsfiltrees3;
var compteurdePosition = 1;
var compteurdePositionaTrouver = 1;
var stringarenvoyer = 'none';
var stringMusicarenvoyer = 'none';
if (req.query.position > 1) {
compteurdePositionaTrouver = req.query.position;
}
for (var serial in notifications) {
if (notifications.hasOwnProperty(serial)) {
// On va parcourir les résultats en allant à la position demandée.
if (compteurdePositionaTrouver == compteurdePosition) {
var device = notifications[serial];
stringMusicarenvoyer = device.musicEntity;
switch (req.query.format) {
case 'hour':
case 'HOUR':
stringarenvoyer = device.originalTime.substring(0, 5);
break;
case 'full':
case 'FULL':
stringarenvoyer = device.originalDate + " " + device.originalTime;
break;
default: //ou HHMM
stringarenvoyer = device.originalTime.substring(0, 5).replace(':', ''); // Utilisation du format HH:MM
}
}
compteurdePosition++;
}
}
res.status(200).json({
value: stringarenvoyer,
music: stringMusicarenvoyer
});
});
});
/***** musicalalarmmusicentity *****
Return la musique de la prochaine alarme musicale
[{
position => 1= prochaine 2=suivante ...
status => Filtre sur le status (active=ON, désactive=OFF, Tous =ALL)
}]
*/
app.get('/musicalalarmmusicentity', (req, res) => {
config.logger('{API} ╔═══════[Lancement '+req.path+' sur '+req.query.device, 'INFO');
res.type('json');
alexa.getNotifications2(function(notifications) {
if (isEmpty(notifications))
return res.status(500).json(error(500, req.route.path, 'Alexa.whennextalarm', 'Retour vide'));
// Filtre et ne garde que les enregistrements du device selctionné
const notificationsfiltrees = notifications.filter(tmp => tmp.deviceSerialNumber == req.query.device);
notifications = notificationsfiltrees;
// Filtre et ne garde que les enregistrements qui ont le type ALARM
const notificationsfiltrees1 = notifications.filter(tmp => tmp.type == "MusicAlarm");
notifications = notificationsfiltrees1;
// Filtre et ne garde que les enregistrements qui sont supérieure à l'heure du jour
//Maintenant :
var d = new Date();
var date_format_str = d.getFullYear().toString() + "-" + ((d.getMonth() + 1).toString().length == 2 ? (d.getMonth() + 1).toString() : "0" + (d.getMonth() + 1).toString()) + "-" + (d.getDate().toString().length == 2 ? d.getDate().toString() : "0" + d.getDate().toString()) + " " + (d.getHours().toString().length == 2 ? d.getHours().toString() : "0" + d.getHours().toString()) + ":" + ((parseInt(d.getMinutes() / 5) * 5).toString().length == 2 ? (parseInt(d.getMinutes() / 5) * 5).toString() : "0" + (parseInt(d.getMinutes() / 5) * 5).toString()) + ":00";
const notificationsfiltrees4 = notifications.filter(tmp => (tmp.originalDate + ' ' + tmp.originalTime > date_format_str));
notifications = notificationsfiltrees4;
// Filtre et ne garde que les enregistrements qui ont un status qui correspond à req.query.status
if ((req.query.status != 'all') && (req.query.status != 'ALL')) {
var FiltreSurStatus = 'ON';
if ((req.query.status == 'off') || (req.query.status == 'OFF')) FiltreSurStatus = 'OFF';
const notificationsfiltrees2 = notifications.filter(tmp => tmp.status == FiltreSurStatus);
notifications = notificationsfiltrees2;
}
// Trie par Date/Heure
const notificationsfiltrees3 = notifications.sort(function(a, b) {
var x = a.originalDate + a.originalTime;
var y = b.originalDate + b.originalTime;
return ((x < y) ? -1 : ((x > y) ? 1 : 0));
});
notifications = notificationsfiltrees3;
var compteurdePosition = 1;
var compteurdePositionaTrouver = 1;
//var stringarenvoyer = 'none';
var stringMusicarenvoyer = 'none';
if (req.query.position > 1) {
compteurdePositionaTrouver = req.query.position;
}
for (var serial in notifications) {
if (notifications.hasOwnProperty(serial)) {
// On va parcourir les résultats en allant à la position demandée.
if (compteurdePositionaTrouver == compteurdePosition) {
var device = notifications[serial];
stringMusicarenvoyer = device.musicEntity;
/*
switch (req.query.format) {
case 'hour':
case 'HOUR':
stringarenvoyer = device.originalTime.substring(0, 5);
break;
case 'full':
case 'FULL':
stringarenvoyer = device.originalDate + " " + device.originalTime;
break;
default: //ou HHMM
stringarenvoyer = device.originalTime.substring(0, 5).replace(':', ''); // Utilisation du format HH:MM
}*/
}
compteurdePosition++;
}
}
res.status(200).json({
value: stringMusicarenvoyer
});
});
});
/***** WhenNextReminder *****
URL: /whennextreminder
Return le prochain rappel
[{
position => 1= prochaine 2=suivante ...
status => Filtre sur le status (active=ON, désactive=OFF, Tous =ALL)
format => Format du résultat (HOUR=réduit HH:SS)
}]
*/
app.get('/whennextreminder', (req, res) => {
config.logger('{API} ╔═══════[Lancement '+req.path+' sur '+req.query.device, 'INFO');
res.type('json');
alexa.getNotifications2(function(notifications) {
if (isEmpty(notifications))
return res.status(500).json(error(500, req.route.path, 'Alexa.whennextreminder', 'Retour vide'));
// Filtre et ne garde que les enregistrements du device selctionné
const notificationsfiltrees = notifications.filter(tmp => tmp.deviceSerialNumber == req.query.device);
notifications = notificationsfiltrees;
// Filtre et ne garde que les enregistrements qui ont le type ALARM
const notificationsfiltrees1 = notifications.filter(tmp => tmp.type == "Reminder");
notifications = notificationsfiltrees1;
// Filtre et ne garde que les enregistrements qui sont supérieure à l'heure du jour
//Maintenant :
var d = new Date();
var date_format_str = d.getFullYear().toString() + "-" + ((d.getMonth() + 1).toString().length == 2 ? (d.getMonth() + 1).toString() : "0" + (d.getMonth() + 1).toString()) + "-" + (d.getDate().toString().length == 2 ? d.getDate().toString() : "0" + d.getDate().toString()) + " " + (d.getHours().toString().length == 2 ? d.getHours().toString() : "0" + d.getHours().toString()) + ":" + ((parseInt(d.getMinutes() / 5) * 5).toString().length == 2 ? (parseInt(d.getMinutes() / 5) * 5).toString() : "0" + (parseInt(d.getMinutes() / 5) * 5).toString()) + ":00";
const notificationsfiltrees4 = notifications.filter(tmp => (tmp.originalDate + ' ' + tmp.originalTime > date_format_str));
notifications = notificationsfiltrees4;
// Filtre et ne garde que les enregistrements qui ont un status qui correspond à req.query.status
if ((req.query.status != 'all') && (req.query.status != 'ALL')) {
var FiltreSurStatus = 'ON';
if ((req.query.status == 'off') || (req.query.status == 'OFF')) FiltreSurStatus = 'OFF';
const notificationsfiltrees2 = notifications.filter(tmp => tmp.status == FiltreSurStatus);
notifications = notificationsfiltrees2;
}
// Trie par Date/Heure
const notificationsfiltrees3 = notifications.sort(function(a, b) {
var x = a.originalDate + a.originalTime;
var y = b.originalDate + b.originalTime;
return ((x < y) ? -1 : ((x > y) ? 1 : 0));
});
notifications = notificationsfiltrees3;
var compteurdePosition = 1;
var compteurdePositionaTrouver = 1;
var stringarenvoyer = 'none';
if (req.query.position > 1) {
compteurdePositionaTrouver = req.query.position;
}
for (var serial in notifications) {
if (notifications.hasOwnProperty(serial)) {
if (compteurdePositionaTrouver == compteurdePosition) {
var device = notifications[serial];
//C'est bon, on est sur la bonne position, on renvoie le résultat
switch (req.query.format) {
case 'hour':
case 'HOUR':
stringarenvoyer = device.originalTime.substring(0, 5);
break;
case 'full':
case 'FULL':
stringarenvoyer = device.originalDate + " " + device.originalTime;
break;
default: //ou HHMM
stringarenvoyer = device.originalTime.substring(0, 5).replace(':', ''); // Utilisation du format HH:MM
}
}
compteurdePosition++;
}
}
res.status(200).json({
value: stringarenvoyer
});
});
});
/***** WhenNextReminderLabel *****
URL: /whennextreminderlabel
Return le texte du prochain rappel
[{
position => 1= prochaine 2=suivante ...
status => Filtre sur le status (active=ON, désactive=OFF, Tous =ALL)
}]
*/
app.get('/whennextreminderlabel', (req, res) => {
config.logger('{API} ╔═══════[Lancement '+req.path+' sur '+req.query.device, 'INFO');
res.type('json');
alexa.getNotifications2(function(notifications) {
if (isEmpty(notifications))
return res.status(500).json(error(500, req.route.path, 'Alexa.whennextreminder', 'Retour vide'));
// Filtre et ne garde que les enregistrements du device selctionné
const notificationsfiltrees = notifications.filter(tmp => tmp.deviceSerialNumber == req.query.device);
notifications = notificationsfiltrees;
// Filtre et ne garde que les enregistrements qui ont le type ALARM
const notificationsfiltrees1 = notifications.filter(tmp => tmp.type == "Reminder");
notifications = notificationsfiltrees1;
// Filtre et ne garde que les enregistrements qui sont supérieure à l'heure du jour
//Maintenant :
var d = new Date();
var date_format_str = d.getFullYear().toString() + "-" + ((d.getMonth() + 1).toString().length == 2 ? (d.getMonth() + 1).toString() : "0" + (d.getMonth() + 1).toString()) + "-" + (d.getDate().toString().length == 2 ? d.getDate().toString() : "0" + d.getDate().toString()) + " " + (d.getHours().toString().length == 2 ? d.getHours().toString() : "0" + d.getHours().toString()) + ":" + ((parseInt(d.getMinutes() / 5) * 5).toString().length == 2 ? (parseInt(d.getMinutes() / 5) * 5).toString() : "0" + (parseInt(d.getMinutes() / 5) * 5).toString()) + ":00";
const notificationsfiltrees4 = notifications.filter(tmp => (tmp.originalDate + ' ' + tmp.originalTime > date_format_str));
notifications = notificationsfiltrees4;
// Filtre et ne garde que les enregistrements qui ont un status qui correspond à req.query.status
if ((req.query.status != 'all') && (req.query.status != 'ALL')) {
var FiltreSurStatus = 'ON';
if ((req.query.status == 'off') || (req.query.status == 'OFF')) FiltreSurStatus = 'OFF';
const notificationsfiltrees2 = notifications.filter(tmp => tmp.status == FiltreSurStatus);
notifications = notificationsfiltrees2;
}
// Trie par Date/Heure
const notificationsfiltrees3 = notifications.sort(function(a, b) {
var x = a.originalDate + a.originalTime;
var y = b.originalDate + b.originalTime;
return ((x < y) ? -1 : ((x > y) ? 1 : 0));
});
notifications = notificationsfiltrees3;
var compteurdePosition = 1;
var compteurdePositionaTrouver = 1;
var stringarenvoyer = 'none';
if (req.query.position > 1) {
compteurdePositionaTrouver = req.query.position;
}
for (var serial in notifications) {
if (notifications.hasOwnProperty(serial)) {
if (compteurdePositionaTrouver == compteurdePosition) {
var device = notifications[serial];
stringarenvoyer=device.reminderLabel;
//C'est bon, on est sur la bonne position, on renvoie le résultat
/*
switch (req.query.format) {
case 'hour':
case 'HOUR':
stringarenvoyer = device.originalTime.substring(0, 5);
break;
case 'full':
case 'FULL':
stringarenvoyer = device.originalDate + " " + device.originalTime;
break;
default: //ou HHMM
stringarenvoyer = device.originalTime.substring(0, 5).replace(':', ''); // Utilisation du format HH:MM
}*/
}
compteurdePosition++;
}
}
res.status(200).json({
value: stringarenvoyer
});
});
});
/***** Stop the server *****/
app.get('/stop', (req, res) => {
//config.logger('{API}: Shuting down','INFO');
config.logger('{API} ╔═════════════════════════════════════════════╗','INFO');
config.logger('{API} ║ Lien au serveur Amazon En COURS D ARRET ║' ,'INFO');
config.logger('{API} ╚═════════════════════════════════════════════╝','INFO');
res.status(200).json({});
server.close(() => {
process.exit(0);
});
});
/***** Restart server *****/
app.get('/restart', (req, res) => {
config.logger('{API}: Restart');
res.status(200).json({});
config.logger('{API}: ******************************************************************');
config.logger('{API}: *****************************Relance forcée du Serveur*************');
config.logger('{API}: ******************************************************************');
startServer();
});
/* Main */
fs.readFile(config.cookieLocation, 'utf8', (err, data) => {
if (err) {
config.logger('{API}: Error while loading the file: ' + config.cookieLocation);
config.logger('{API}: ' + err);
process.exit(-1);
}
try {
config.cookie = JSON.parse(data);
startServer(); // remonté de 5 lignes, inutile de lancer le serveur si cookier pose souci
} catch (err) {
config.logger('{API}: *********************************************************************');
config.logger('{API}: *********************************************************************');
config.logger('{API}: ** Relancez la génération du COOKIE AMAZON, il y a un souci dessus **');
config.logger('{API}: *********************************************************************');
config.logger('{API}: *********************************************************************');
config.logger('{API}: ');
httpPost('message_add', {message: "Relancez la génération du COOKIE AMAZON, il y a un souci dessus"});
//config.logger('{API}: ' + err);
}
});
function startServer(force=false) {
if (force||(Date.now()-dernierStartServeur)>20000)
{
dernierStartServeur=Date.now();
alexa = null;
alexa = new Alexa();
let lancerOuPasMQTT=false;
if (force) config.logger('{API} ╠═══════════════════[Relance du lien au Serveur Amazon (avec nouveau cookie)]═════════════════════════════════════════════════════════','INFO');
else {
config.logger(' ','INFO');
config.logger('{API} ╔═══════════════════[Lancement du lien au Serveur Amazon]═════════════════════════════════════════════════════════','INFO');
lancerOuPasMQTT=config.useWsMqtt;
}
alexa.init({
cookie: config.cookie,
logger: config.logger,
alexaServiceHost: config.alexaServiceHost,
cookieRefreshInterval: config.cookieRefreshInterval,
useWsMqtt: lancerOuPasMQTT
},
(err) => {
// Unable to init alexa
if (err) {
config.logger('{API} ╠════════════════════════════════════════════════════════════════════════════════════════','ERROR');
config.logger("{API} ║ Souci dans l'initiatlisation du serveur " + err ,'ERROR');
config.logger("{API} ║ ou le serveur " + config.alexaServiceHost + " n'est pas joignable" ,'ERROR');
config.logger('{API} ╚════════════════════════════════════════════════════════════════════════════════════════','ERROR');
process.exit(-1);
}
if (alexa.cookieData) {
if (alexa.cookieaSauvegarder) {
fs.writeFile(config.cookieLocation, JSON.stringify(alexa.cookieData), 'utf8', (err) => {
if (err) {
config.logger('{API}: Error while saving the cookie to: ' + config.cookieLocation);
config.logger('{API}: ' + err);
}
config.logger('{API} ╠═══> New cookie saved to:' + config.cookieLocation,'DEBUG');
config.logger("{API} ╠═══> On doit relancer l'initialisation avec le nouveau Cookie",'DEBUG');
startServer(true);
});
//-------------------------------------------------------------------------------------------------
// Sauvegarde a supprimer plus tard, pour trouver souci du cookie qui n'est plus valide Sigalou
/*
var d = new Date();
var date_format_str = d.getFullYear().toString() + "-" + ((d.getMonth() + 1).toString().length == 2 ? (d.getMonth() + 1).toString() : "0" + (d.getMonth() + 1).toString()) + "-" + (d.getDate().toString().length == 2 ? d.getDate().toString() : "0" + d.getDate().toString()) + "_" + (d.getHours().toString().length == 2 ? d.getHours().toString() : "0" + d.getHours().toString()) + ":" + ((parseInt(d.getMinutes() / 5) * 5).toString().length == 2 ? (parseInt(d.getMinutes() / 5) * 5).toString() : "0" + (parseInt(d.getMinutes() / 5) * 5).toString()) + ":00";
fs.writeFile("/var/www/html/plugins/alexaapi/resources/data/alexa-cookie_"+date_format_str+".json", JSON.stringify(alexa.cookieData), 'utf8', (err) => {
config.logger('{API} ╠═══> Copie du cookie saved to:' + "/var/www/html/plugins/alexaapi/resources/data/alexa-cookie_"+date_format_str+".json",'DEBUG');
});
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
*/
}
// Start the server
if (server) {
config.logger('{API} ╠════════════════════════════════════════════════════════════════════════════════════════','INFO');
config.logger('{API} ║ Le lien vers le serveur Amazon est bien lancé sur le port ' + server.address().port ,'INFO');
config.logger('{API} ╠════════════════════════════════════════════════════════════════════════════════════════','INFO');
} else {
server = app.listen(config.listeningPort, () => {
config.logger('{API} ╠════════════════════════════════════════════════════════════════════════════════════════','INFO');
config.logger('{API} ║ Activation du port ' + server.address().port ,'INFO');
config.logger('{API} ╠════════════════════════════════════════════════════════════════════════════════════════','INFO');
//server.close(() => {
//server = app.listen(config.listeningPort);
//});
});
}
} else {
config.logger('{API} ╠════════════════════════════════════════════════════════════════════════════════════════','INFO');
config.logger('{API} ║ Ne devrait jamais arriver !! On a pas de cookieData' ,'INFO');
config.logger('{API} ╠════════════════════════════════════════════════════════════════════════════════════════','INFO');
}
});
}
else
{
config.logger('{API}: ******************** Lancement Serveur annulé (dernière relance trop récente)***********************');
}
}
//alexa.sendSequenceCommand(serial, 'speak', req.query.text, GestionErreur);
//Gestion des erreurs et surtout pour détecter les ConnexionClose
function traiteErreur(err, commandesEnErreur=null, queryEnErreur=null) {
if (err)
{
//config.logger('{API}: ******************************************************************');
//config.logger('{API}: *****************************ERROR********************************');
//config.logger('{API}: ******************************************************************');
if (err.message == "Connexion Close") {
config.logger("{API} ╠═══>Connexion Close détectée et donc relance du lien au serveur Amazon", 'WARNING');
startServer();
}
else if (err.message == "Unauthorized") {
config.logger("{API} ╠═══>Unauthorized détecté et donc relance du lien au serveur Amazon", 'WARNING');
startServer();
}
//else
//{
if (Array.isArray(commandesEnErreur)) {
config.logger("Alexa-API: "+err+" Commands: "+JSON.stringify(commandesEnErreur)+" Query: "+JSON.stringify(queryEnErreur), 'ERROR');
if (!(queryEnErreur.replay)) { // si c'est pas défini c'est que c'est le premier essai, donc on rejoue
var listeCommandesEnErreur=[];
listeCommandesEnErreur.push(commandesEnErreur);
httpPost('commandesEnErreur', {
queryEnErreur: queryEnErreur,
listeCommandesEnErreur: commandesEnErreur
});
config.logger("{API} ╠═══>"+commandesEnErreur.length+" commandes en erreur: "+JSON.stringify(commandesEnErreur)+" query: "+JSON.stringify(queryEnErreur), 'WARNING');
} else {
config.logger("{API} ╠═══>Traitement de l'erreur (2ème tour): "+err+" sur les commandes: "+JSON.stringify(commandesEnErreur)+" Query: "+JSON.stringify(queryEnErreur), 'ERROR');
config.logger("{API} ╠═══>ICI IL FAUDRAIT RELANCER LE LIEN SERVEUR", 'ERROR');
}
}
else if (typeof (commandesEnErreur) == "string") {
config.logger("{API} ╠═══>"+err+" Command: "+commandesEnErreur+" Query: "+JSON.stringify(queryEnErreur), 'ERROR');
if (!(queryEnErreur.replay)) { // si c'est pas défini c'est que c'est le premier essai, donc on rejoue
httpPost('commandesEnErreur', {
queryEnErreur: queryEnErreur,
listeCommandesEnErreur: commandesEnErreur
});
config.logger("{API} ╠═══>commande en erreur: "+commandesEnErreur+" query: "+JSON.stringify(queryEnErreur), 'WARNING');
} else {
config.logger("{API} ╠═══>Traitement de l'erreur (2ème tour): "+err+" sur la commande: "+JSON.stringify(commandesEnErreur)+" Query: "+JSON.stringify(queryEnErreur), 'ERROR');
config.logger("{API} ╠═══>ICI IL FAUDRAIT RELANCER LE LIEN SERVEUR", 'ERROR');
}
}
//config.logger('{API}: ******************************************************************');
//config.logger('{API}: ******************************************************************');
//}
}
}
function httpPost(nom, jsonaenvoyer) {
//config.logger && config.logger('httpPost httpPost httpPost httpPost httpPost httpPost httpPost httpPost httpPost httpPost httpPost '+nom);
var url=IPJeedom+"/plugins/alexaapi/core/php/jeeAlexaapi.php?apikey="+ClePlugin+"&nom="+nom;
config.logger && config.logger('URL envoyée: '+url, "DEBUG");
jsonaenvoyer=JSON.stringify(jsonaenvoyer);
config.logger && config.logger('DATA envoyé:'+jsonaenvoyer,'DEBUG');
request.post(url, {
json : true,
gzip : false,
multipart: [
{
body: jsonaenvoyer
}
]
}, function (err, response, json) {
if (!err && response.statusCode == 200) {
//if(!json.result && json.error)
//{
// //error json.error
// }
// else {
// //json.result;
// }
} else
{
//error err est une erreur html
}
});
/**/
}
// config.logger(JSON.stringify(devices));
function error(status, source, title, detail) {
let error = {
'status': status,
'title': title,
'detail': detail
};
config.logger('{API}: ' + title + ': ' + detail,'DEBUG');
return error;
}