Hi…mein Problem das ich noch nicht genau weiß wie die Fehlermeldung und Script lesen soll !
Gibt es dazu eine Anleitung. Ständig Fragen nervt. :roll: Wie es ja auch lernen....
! // AlexaControl
! //
! // Version: v0.1.6
! // Author: Hauke
! // Dank an ruhr70 dessen Skript als Vorlage diente
! // http://forum.iobroker.net/viewtopic.php?f=37&t=6035
! // und Stefan.Franke, dessen Skript den Login per Cookie ermöglicht
! // http://forum.iobroker.net/viewtopic.php … gOn#p98493
! // Changelog:
! // v.0.1.6 Fehler behoben: Cannot use 'in' operator to search for 'provider' in undefined
! // v.0.1.5 Dummy-Objekte, falls Alexa {"message":null} antwortet, weil das Device derzeit nicht aktiv ist
! // v.0.1.4 Spielzeit und Titellänge werden nun im 2-Sekunden-Takt berechnet
! // v.0.1.3 WiFi ESSID / MAC werden ausgelesen
! // v.0.1.2 Playlists
! // v.0.1.1 History
! // v.0.1.0 erste brauchbare Version
! // ----------------------------------------------------------------------------------------------------
! // Settings:
! // ----------------------------------------------------------------------------------------------------
! // Loglevel kann folgenden Wert haben: debug, info, warn, error, none
! var logLevel = 'info';
! // true: Datenpunkte werden überschrieben (wenn z.B. Bezeichnungen geändert wurden)
! var forceCreation = true;
! // Pfad im Javascript-Adapter unter dem die Geräte angelegt werden sollen bei "Alexa" wird daraus z.B.: javascript.0.Alexa
! var pfad = "AlexaControl";
! // Hier die Datenpunkti mit dem Cookie und CSRF aus dem Script von Stefan.Franke
! var idCookie = "javascript.0.productive.alexalogon.cookie";
! var idCsrf = "javascript.0.productive.alexalogon.csrf";
! // Einslive - Default Radiostation für den Radio an Button.
! var defaultRadiostation = "s24885";
! // Jede Minute History auslesen? Wert im üblichen Unix Crontab-Stil
! // Manuell jeder Zeit per Button möglich.
! var updateHistoryScheduler = "* * * * ";
! // Wie oft Playlists automatisch auslesen? Wert im üblichen Unix Crontab-Stil
! // Manuell jeder Zeit per Button möglich.
! var updatePlaylistScheduler = "0 0 * * ";
! // Sollen Geräte gelistet werden, die nicht Kontrolliert werden können? (TV-Stick, etc.)
! // Hier wird dann nur die Gruppe "device" erstellt. "player" und "control" werden nicht erstellt.
! var listNonCotrollable = false;
! // Liste der bekannten Devicetypen, Geräte mit bekannten DeviceType
! // auf das ursprüngliche "anlegen" kann verzichtet werden, da die Capabilities geparst werden.
! // Nur Steuerbare Devices werden mit Steuer-Objekten versehen
! var knownDeviceType = {
! "A3S5BH2HU6VAYF": "Echo Dot 2.Gen",
! "AB72C64C86AW2": "Echo",
! "A7WXQPH584YP": "Echo 2.Gen",
! "A10A33FOX2NUBK": "Echo Spot",
! "A1NL4BVLQ4L3N3": "Echo Show",
! "A15ERDAKK5HQQG": "Sonos",
! "A2E0SNTXJVT7WK": "Fire TV V1",
! "ADVBD696BHNV5": "Fire TV Stick V1",
! "A2LWARUGJLBYEW": "Fire TV Stick V2",
! "A2T0P32DY3F7VB": "echosim.io",
! "AILBSA2LNTOYL": "reverb App",
! "A2M35JJZWCQOMZ": "Echo Plus"
! };
! // ----------------------------------------------------------------------------------------------------
! // Skript, ab hier nichts ändern
! // ----------------------------------------------------------------------------------------------------
! // Initiale Variablen setzen
! // ------------------------------------------------------
! //Script von Stefan.Franke nötig, welches csrf und cookie ausliest
! var csrf = getState(idCsrf).val;
! var cookie = getState(idCookie).val;
! cookie = cookie.replace(/\/g, "");
! // Object-Pfad definieren unter dem Devices angelegt werden
! var deviceObjectPath = pfad + ".Devices.";
! // Node Module https verwenden
! var https = require('https');
! // CUSTOMERID wird später aus der Geräteliste ausgelesen
! var mediaOwnerCustomerId;
! // globales Objekt mit allen Devices
! var devices = {};
! // LoglevelInt defniniern und dann Wert aus den Settings setzen
! var logLevelInt = 5;
! setLoglevel(logLevel);
! // Beim Programmende eine Info ausgeben
! onStop(function skriptStop () {
! logInfo("** AlexaControl wurde gestoppt ");
! }, 2000 /ms/);
! // Das eigentliche Programm läuft ab hier
! // ------------------------------------------------------
! logInfo(" AlexaControl wurde gestartet ");
! if(forceCreation) {
! logWarn("Forcecreation ist eingeschaltet. Wenn nicht mehr benötigt, bitte im Skript auf false setzen");
! }
! // Objekte auslegen und anlegen
! initAlexa();
! // updates History
! schedule(updateHistoryScheduler, function () {rescanHistory();});
! // updates Playlists
! schedule(updatePlaylistScheduler, function () {updatePlaylists();});
! // -------------------------------------------------------------------------------------------------------
! // Objekte Auslesen
! // -------------------------------------------------------------------------------------------------------
! /
! * liest per https-GET die aktuellen Playlists von Amazon ein und speichert diese in die "Playlists.X" States
! /
! function updatePlaylists() {
! logInfo('[updatePlaylists]');
! // zur Abfrage wird der erste Echo mit MusicPlayer verwendet
! var echoWithMusicPlayer = getEchoWithMusicPlayerFromDevices();
! var path = '/api/cloudplayer/playlists?deviceSerialNumber=' + echoWithMusicPlayer.serialNumber + '&deviceType=' + echoWithMusicPlayer.deviceType + '&mediaOwnerCustomerId=' + mediaOwnerCustomerId;
! httpsReqGet(
! path,
! function (result) {
! tmpListe = JSON.parse(result).playlists;
! var playlistsJSON = [];
! var playlistsTitles = [];
! var playlistsIDs = [];
! for (playlist in tmpListe) {
! var obj = {
! "title": tmpListe[playlist][0].title,
! "playlistId": tmpListe[playlist][0].playlistId
! };
! playlistsJSON.push(obj);
! playlistsTitles.push(tmpListe[playlist][0].title);
! playlistsIDs.push(tmpListe[playlist][0].playlistId);
! }
! setState(pfad + ".Playlists.JSON", JSON.stringify(playlistsJSON));
! setState(pfad + ".Playlists.Titles", playlistsTitles.join(';'));
! setState(pfad + ".Playlists.IDs", playlistsIDs.join(';'));
! }
! );
! }
! /
! * liest per https-GET die letzten 20 Alexa-History-Einträge von Amazon ein und speichert diese in die "Playlists.X" States
! /
! function rescanHistory() {
! logInfo('[rescanHistory]');
! var path = 'https://alexa.amazon.de/api/activities? … 0&offset=1';
! httpsReqGet(
! path,
! function (result) {
! activities = JSON.parse(result).activities;
! creationTime = getState(pfad + ".History.creationTime").val;
! for(var i = (activities.length - 1); i > 0; i--) {
! if ((activities__.creationTimestamp > creationTime) || creationTime === null) {
! deviceName = getDeviceNameBySerialNumber(activities__.sourceDeviceIds[0].serialNumber);
! setState(pfad + ".History.creationTime", activities__.creationTimestamp);
! setState(pfad + ".History.deviceName", deviceName);
! setState(pfad + ".History.summary", JSON.parse(activities__.description).summary);
! }
! }
! }
! );
! }
! /
! * Updated ein Device per DatenpunktName, sowohl "control", als auch "player" wird
! * abgerufen und gespeichert befindet sich currentState im Modus "PLAYING", so wird
! * mit einem Timeout diese Funktion für das Device erneut aufgerufen
! *
! * @param string deviceDpName
! /
! function updateDevice(deviceDpName){
! if(typeof(devices[deviceDpName]) != "undefined") {
! if (deviceIsControllable(devices[deviceDpName].capabilities)) {
! logInfo('[updateDevice] ' + deviceDpName);
! var controlPath = deviceObjectPath + clearName(deviceDpName) + ".control";
! // deviceObjectPath + clearName(deviceDpName) + ".control.lastState"
! getDeviceStateBySerialAndType(devices[deviceDpName].serialNumber, devices[deviceDpName].deviceType, function(deviceState){
! // nur updaten, wenn unterschiedlich
! if (deviceState.volume != getState(controlPath + ".volume").val) {
! setState(controlPath + ".volume", parseInt(deviceState.volume));
! }
! if(deviceHasMusicPlayer(devices[deviceDpName].capabilities)){
! if (deviceState.shuffling != getState(controlPath + ".shuffle").val) {
! setState(controlPath + ".shuffle", deviceState.shuffling);
! }
! if (deviceState.looping != getState(controlPath + ".repeat").val) {
! setState(controlPath + ".repeat", deviceState.looping);
! }
! }
! getDevicePlayerBySerialAndType(devices[deviceDpName].serialNumber, devices[deviceDpName].deviceType, function(devicePlayer){
! // player
! var playerPath = deviceObjectPath + clearName(deviceDpName) + ".player";
! setState(playerPath + ".contentType", getStringOrEmpty(deviceState.contentType));
! setState(playerPath + ".currentState", getStringOrEmpty(deviceState.currentState));
! setState(playerPath + ".imageURL", getStringOrEmpty(deviceState.imageURL));
! setState(playerPath + ".muted", deviceState.muted);
! setState(playerPath + ".providerId", getStringOrEmpty(deviceState.providerId));
! setState(playerPath + ".radioStationId", getStringOrEmpty(deviceState.radioStationId));
! setState(playerPath + ".service", getStringOrEmpty(deviceState.service));
! var providerName = '';
! if ((devicePlayer !== undefined) && ("provider" in devicePlayer) && (devicePlayer.provider !== null)){
! providerName = getStringOrEmpty(devicePlayer.provider.providerName);
! }
! setState(playerPath + ".providerName", providerName);
! var title = '';
! var interpreter = '';
! var album = '';
! if ((devicePlayer !== undefined) &&("infoText" in devicePlayer) && (devicePlayer.infoText !== null)){
! title = getStringOrEmpty(devicePlayer.infoText.title);
! interpreter = getStringOrEmpty(devicePlayer.infoText.subText1);
! album = getStringOrEmpty(devicePlayer.infoText.subText2);
! }
! setState(playerPath + ".title", title);
! setState(playerPath + ".interpreter", interpreter);
! setState(playerPath + ".album", album);
! var mainArtUrl = '';
! if ((devicePlayer !== undefined) &&("mainArt" in devicePlayer) && (devicePlayer.mainArt !== null)){
! mainArtUrl = getStringOrEmpty(devicePlayer.mainArt.url);
! }
! setState(playerPath + ".mainArtUrl", mainArtUrl);
! var miniArtUrl = '';
! if ((devicePlayer !== undefined) &&("miniArt" in devicePlayer) && (devicePlayer.miniArt !== null)){
! miniArtUrl = getStringOrEmpty(devicePlayer.miniArt.url);
! }
! setState(playerPath + ".miniArtUrl", miniArtUrl);
! var mediaLength = 0;
! var mediaProgress = 0;
! var mediaProgressPercent = 0;
! if ((devicePlayer !== undefined) &&("progress" in devicePlayer) && (devicePlayer.progress !== null)){
! mediaLength = parseInt(devicePlayer.progress.mediaLength);
! mediaProgress = parseInt(devicePlayer.progress.mediaProgress);
! if (mediaLength > 0) {
! mediaProgressPercent = Math.round(((mediaProgress * 100) / mediaLength));
! }
! }
! setState(playerPath + ".mediaLength", mediaLength);
! setState(playerPath + ".mediaLengthStr", sekToHMS(mediaLength));
! setState(playerPath + ".mediaProgress", mediaProgress);
! setState(playerPath + ".mediaProgressStr", sekToHMS(mediaProgress));
! setState(playerPath + ".mediaProgressPercent", mediaProgressPercent);
! });
! });
! } else {
! logInfo('[updateDevice] Device not controllable: ' + deviceDpName);
! }
! }else {
! logInfo('[updateDevice] Device unknown: ' + deviceDpName);
! }
! }
! /*
! * Inkrementiert "mediaProgress" alle 2 Sekunden um 2. So wird ein permanentes https-get überflüssig
! * ruft sich nach 2 Sekunden erneut selbst auf, wenn "currentState" noch auf "PLAYING" steht.
! * ist "mediaProgress" größer als "mediaLength", so ist der Song zu Ende und "updateDevice" wird aufgerufen.
! *
! * @param string deviceDpName
! /
! function updateMediaProgress(deviceDpName) {
! var playerPath = deviceObjectPath + deviceDpName + ".player";
! var currentState = getState(playerPath + ".currentState").val;
! var mediaProgress = getState(playerPath + ".mediaProgress").val;
! var mediaLength = getState(playerPath + ".mediaLength").val;
! if ((currentState == 'PLAYING') ) {
! mediaProgressNew = mediaProgress + 2;
! // Am Ende des Titels soll neu geladen werden. Ist es Radio (länge = 0) dann alle 200 sekunden
! if ((mediaProgressNew > mediaLength) && ((mediaLength > 0) || (mediaProgressNew % 200 < 2))){
! setTimeout( function() { updateDevice(deviceDpName); }, 2000 );
! }
! // Nun mediaProgress und mediaProgressPercent neu berechnen
! if (mediaLength > 0) {
! mediaProgressPercent = Math.round((((mediaProgressNew) * 100) / mediaLength));
! } else {
! mediaProgressPercent = 0;
! }
! setState(playerPath + ".mediaProgressPercent", mediaProgressPercent);
! setState(playerPath + ".mediaProgress", mediaProgressNew);
! setState(playerPath + ".mediaProgressStr", sekToHMS(mediaProgressNew));
! setTimeout( function() { updateMediaProgress(deviceDpName); }, 2000 );
! }
! }
! /*
! * Ruft den aktuellen State eines Devices per Seriennummer und Type von Amazon ab.
! * Gibt die Antwort an "callback(result)" weiter
! *
! * @param string serialNumber
! * @param string deviceType
! * @param function callback
! /
! function getDeviceStateBySerialAndType(serialNumber, deviceType, callback) {
! httpsReqGet(
! '/api/media/state?deviceSerialNumber=' + serialNumber + '&deviceType=' + deviceType,
! function(result) {
! // Es kommt vor, dass Geräte nicht antworten, weil sie nicht aktiv sind. Dann greift hier der Dummy-Wert
! if (result == '{"message":null}') {
! result = JSON.stringify({
! "clientId":null,
! "contentId":null,
! "contentType":null,
! "currentState":"IDLE",
! "imageURL":null,
! "isDisliked":false,
! "isLiked":false,
! "looping":false,
! "mediaOwnerCustomerId":null,
! "muted":false,
! "programId":null,
! "progressSeconds":0,
! "providerId":null,
! "queue":null,
! "queueId":null,
! "queueSize":0,
! "radioStationId":null,
! "radioVariety":0,
! "referenceId":null,
! "service":null,
! "shuffling":false,
! "timeLastShuffled":0,
! "volume":0
! });
! }
! if(callback !== undefined && typeof callback === 'function') callback(JSON.parse(result));
! }
! );
! }
! /*
! * Ruft den aktuellen State eines Devices per DatenpunktNamen von Amazon ab.
! * Gibt die Antwort an "callback(result)" weiter
! *
! * @param string deviceDpName
! * @param function callback
! /
! function getDeviceState(deviceDpName, callback) {
! getDeviceStateBySerialAndType(devices[deviceDpName].serialNumber, devices[deviceDpName].deviceType, callback);
! }
! /*
! * Ruft die aktuelle PlayerInfo eines Devices per Seriennummer und Type von Amazon ab.
! * Gibt die Antwort an "callback(result)" weiter
! *
! * @param string serialNumber
! * @param string deviceType
! * @param function callback
! /
! function getDevicePlayerBySerialAndType(serialNumber, deviceType, callback) {
! httpsReqGet(
! '/api/np/player?deviceSerialNumber=' + serialNumber + '&deviceType=' + deviceType,
! function(result) {
! // Es kommt vor, dass Geräte nicht antworten, weil sie nicht aktiv sind. Dann greift hier der Dummy-Wert
! if (result == '{"message":null}') {
! result = JSON.stringify({
! "playerInfo":{
! "hint":null,
! "infoText":null,
! "isPlayingInLemur":false,
! "lemurVolume":null,
! "lyrics":null,
! "mainArt":null,
! "mediaId":null,
! "miniArt":null,
! "miniInfoText":null,
! "playbackSource":null,
! "playingInLemurId":null,
! "progress":null,
! "provider":null,
! "queueId":null,
! "state":null,
! "template":null,
! "transport":null,
! "volume":null
! }
! });
! }
! if(callback !== undefined && typeof callback === 'function') callback(JSON.parse(result).playerInfo);
! }
! );
! }
! /*
! * Ruft die aktuelle PlayerInfo eines Devices per DatenpunktNamen von Amazon ab.
! * Gibt die Antwort an "callback(result)" weiter
! *
! * @param string deviceDpName
! * @param function callback
! /
! function getDevicePlayer(deviceDpName, callback) {
! getDevicePlayerBySerialAndType(devices[deviceDpName].serialNumber, devices[deviceDpName].deviceType, callback);
! }
! /*
! * liest per https-GET alle Alexa-fähigen Geräte neu ein und updated bei allen
! * bereits bekannten Geräten die Infos, wie z.B. Onlinestatus, WLAN, etc.
! /
! function updateAlexa(){
! logInfo('[updateAlexa]');
! httpsReqGet('/api/devices/device', function(result) {
! // Falls Result leer ist, soll nichts weiter gemacht werden
! if(!result) return logWarn("Es konnten keine Daten ermittelt werden! Cookie richtig?");
! logDebug(result);
! var alexaDeviceObj = JSON.parse(result);
! var numberOfDevices = alexaDeviceObj.devices.length;
! logInfo("Anzahl vorhandener Geräte mit Alexa Unterstützung: " + numberOfDevices);
! if (numberOfDevices < 1) {
! return logWarn("Error: Skript konnte keine Geräte abfragen");
! }
! // Kundenindiviuelle Customer ID aus dem ersten Gerät entnehmen -> in vorbereitete globale Variable schreiben
! mediaOwnerCustomerId = getStringOrEmpty(alexaDeviceObj.devices[0].deviceOwnerCustomerId);
! // Devices
! for(var i = 0; i < numberOfDevices; i++) {
! // Nur bekannte Geraete updaten
! if(typeof(devices[clearName(alexaDeviceObj.devices_[i].accountName)]) != "undefined") {
! // Pruefen, ob das Geraet noch das selbe ist
! if (devices[clearName(alexaDeviceObj.devices_[i].accountName)].serialNumber != alexaDeviceObj.devices__.serialNumber){
! logError('Das Geraet "' + clearName(alexaDeviceObj.devices__.accountName) + '" hat nach update eine andere Seriennummer!');
! } else {
! var devicePath = deviceObjectPath + clearName(alexaDeviceObj.devices__.accountName) + ".device";
! httpsReqGet(
! '/api/device-wifi-details?deviceSerialNumber=' + alexaDeviceObj.devices__.serialNumber + '&deviceType=' + alexaDeviceObj.devices_.deviceType,
! function(result) {
! setState(devicePath + ".essid", getStringOrEmpty(JSON.parse(result).essid));
! setState(devicePath + ".macAddress", getStringOrEmpty(JSON.parse(result).macAddress));
! }
! );
! setState(devicePath + ".language", getStringOrEmpty(alexaDeviceObj.devices_.language));
! setState(devicePath + ".online", alexaDeviceObj.devices_.online);
! setState(devicePath + ".parentClusters", getStringOrEmpty(alexaDeviceObj.devices_.parentClusters));
! setState(devicePath + ".softwareVersion", getStringOrEmpty(alexaDeviceObj.devices_.softwareVersion));
! // Device updaten
! updateDevice(clearName(alexaDeviceObj.devices_.accountName));
! }
! }
! }
! });
! }
! // –-----------------------------------------------------------------------------------------------------
! // Objekte Anlegen
! // -------------------------------------------------------------------------------------------------------
! /*
! * liest per https-GET alle Alexa-fähigen Geräte ein und legt die Objekte an
! /
! function initAlexa() {
! httpsReqGet('/api/devices/device', function(result) {
! // Falls Result leer ist, soll nichts weiter gemacht werden
! if(!result) return logWarn("Es konnten keine Daten ermittelt werden! Cookie richtig?");
! logDebug(result);
! var alexaDeviceObj = JSON.parse(result);
! var numberOfDevices = alexaDeviceObj.devices.length;
! logInfo("Anzahl vorhandener Geräte mit Alexa Unterstützung: " + numberOfDevices);
! if (numberOfDevices < 1) {
! return logWarn("Error: Skript konnte keine Geräte abfragen");
! }
! // Kundenindiviuelle Customer ID aus dem ersten Gerät entnehmen -> in vorbereitete globale Variable schreiben
! mediaOwnerCustomerId = alexaDeviceObj.devices[0].deviceOwnerCustomerId;
! createDeviceState(pfad + ".mediaOwnerCustomerId", mediaOwnerCustomerId, forceCreation, {name:"Individuelle Kunden ID", type:"string", role:"value"});
! // Devices
! for(var i = 0; i < numberOfDevices; i++) {
! if (listNonCotrollable || deviceIsControllable(alexaDeviceObj.devices_.capabilities)) {
! devices[clearName(alexaDeviceObj.devices[i].accountName)] = createDevice(alexaDeviceObj.devices_, forceCreation);
! }
! }
! // Update
! createState(
! pfad + ".update",
! false,
! forceCreation,
! {name:"Update Devices", type:"boolean", role:"button"},
! null,
! function () {
! setTimeout(
! function() {
! logInfo("CreateON: " + pfad + ".update");
! on({id: "javascript." + instance + "." + pfad + ".update", change: "any"},
! function (obj){
! unsetButtonFirst(obj, function (obj) {updateAlexa();});
! })
! }
! ,
! 3000
! );
! }
! );
! // Playlists
! createDeviceState(pfad + ".Playlists.JSON", null, forceCreation, {name:"Playlists als JSON", type:"string", role:"state"});
! createDeviceState(pfad + ".Playlists.Titles", null, forceCreation, {name:"Playlist Titel als Liste fuer Dropdown", type:"string", role:"state"});
! createDeviceState(pfad + ".Playlists.IDs", null, forceCreation, {name:"Playlist IDs als Liste fuer Dropdown", type:"string", role:"state"});
! createState(
! pfad + ".Playlists.update",
! false,
! forceCreation,
! {name:"Update Playlists", type:"boolean", role:"button"},
! null,
! function () {
! setTimeout(
! function() {
! logInfo("CreateON: " + pfad + ".Playlists.update");
! on({id: "javascript." + instance + "." + pfad + ".Playlists.update", change: "any"},
! function (obj){
! unsetButtonFirst(obj, function (obj) {updatePlaylists();});
! })
! }
! ,
! 3000
! );
! }
! );
! // Einmalig die Playlists abfragen
! updatePlaylists();
! // History
! createState(pfad + ".History.creationTime", null, forceCreation, {name:"Timestamp", type:"number", role:"state"});
! createState(pfad + ".History.deviceName", null, forceCreation, {name:"deviceName", type:"string", role:"state"});
! createState(pfad + ".History.summary", null, forceCreation, {name:"summary", type:"string", role:"state"});
! createState(
! pfad + ".History.update",
! false,
! forceCreation,
! {name:"Update History", type:"boolean", role:"button"},
! null,
! function () {
! setTimeout(
! function() {
! logInfo("CreateON: " + pfad + ".History.update");
! on({id: "javascript." + instance + "." + pfad + ".History.update", change: "any"},
! function (obj){
! unsetButtonFirst(obj, function (obj) {rescanHistory();});
! })
! }
! ,
! 3000
! );
! }
! );
! // Erstmalig die History abgragen
! rescanHistory();
! });
! }
! /*
! * Erzeugt alle States zu einem übergebenen Device-Objekt. Anhand der "capabilities"
! * des Devices, werden, ggf. "control" und "player" States erstellt.
! *
! * @param object amazonDeviceObject
! * @param boolean forceCreation
! /
! function createDevice(amazonDeviceObject, forceCreation) {
! logInfo('createDevice: '+ amazonDeviceObject.accountName);
! var devicePath = deviceObjectPath + clearName(amazonDeviceObject.accountName) + ".device";
! // device
! createDeviceState(devicePath + ".accountName", getStringOrEmpty(amazonDeviceObject.accountName), forceCreation, {name:"Name", type:"string", role:"value"});
! createDeviceState(devicePath + ".capabilities", getStringOrEmpty(JSON.stringify(amazonDeviceObject.capabilities)), forceCreation, {name:"Fähigkeiten", type:"string", role:"value"});
! createDeviceState(devicePath + ".clusterMembers", getStringOrEmpty(JSON.stringify(amazonDeviceObject.clusterMembers)), forceCreation, {name:"GruppenMitglieder", type:"string", role:"value"});
! createDeviceState(devicePath + ".deviceAccountId", getStringOrEmpty(amazonDeviceObject.deviceAccountId), forceCreation, {name:"AccountId", type:"string", role:"value"});
! createDeviceState(devicePath + ".deviceFamily", getStringOrEmpty(amazonDeviceObject.deviceFamily), forceCreation, {name:"DeviceFamily", type:"string", role:"value"});
! createDeviceState(devicePath + ".deviceOwnerCustomerId", getStringOrEmpty(amazonDeviceObject.deviceOwnerCustomerId), forceCreation, {name:"deviceOwnerCustomerId", type:"string", role:"value"});
! createDeviceState(devicePath + ".deviceType", getStringOrEmpty(amazonDeviceObject.deviceType), forceCreation, {name:"deviceType", type:"string", role:"value"});
! createDeviceState(devicePath + ".deviceTypeString", getStringOrEmpty(deviceTypeStr(amazonDeviceObject.deviceType)), forceCreation, {name:"deviceType als String", type:"string", role:"value"});
! createDeviceState(devicePath + ".deviceTypeFriendlyName", getStringOrEmpty(amazonDeviceObject.deviceTypeFriendlyName), forceCreation, {name:"deviceTypeFriendlyName", type:"string", role:"value"});
! httpsReqGet(
! '/api/device-wifi-details?deviceSerialNumber=' + amazonDeviceObject.serialNumber + '&deviceType=' + amazonDeviceObject.deviceType,
! function(result) {
! createDeviceState(devicePath + ".essid", getStringOrEmpty(JSON.parse(result).essid), forceCreation, {name:"essid", type:"string", role:"value"});
! createDeviceState(devicePath + ".macAddress", getStringOrEmpty(JSON.parse(result).macAddress), forceCreation, {name:"macAddress", type:"string", role:"value"});
! }
! );
! createDeviceState(devicePath + ".language", getStringOrEmpty(amazonDeviceObject.language), forceCreation, {name:"language", type:"string", role:"value"});
! createDeviceState(devicePath + ".online", amazonDeviceObject.online, forceCreation, {name:"online (Klappt nur bei ECHOs)", type:"boolean", role:"value"});
! createDeviceState(devicePath + ".parentClusters", getStringOrEmpty(amazonDeviceObject.parentClusters), forceCreation, {name:"Mitglied in dieser Gruppe", type:"string", role:"value"});
! createDeviceState(devicePath + ".serialNumber", getStringOrEmpty(amazonDeviceObject.serialNumber), forceCreation, {name:"serialNumber", type:"string", role:"value"});
! createDeviceState(devicePath + ".softwareVersion", getStringOrEmpty(amazonDeviceObject.softwareVersion), forceCreation, {name:"softwareVersion", type:"string", role:"value"});
! if (deviceIsControllable(amazonDeviceObject.capabilities)) {
! createDeviceControl(amazonDeviceObject, forceCreation);
! }
! return {
! 'serialNumber' : amazonDeviceObject.serialNumber,
! 'deviceType' : amazonDeviceObject.deviceType,
! 'capabilities' : amazonDeviceObject.capabilities
! };
! }
! /*
! * Erzeugt alle "control" und "player" States zu einem übergebenen Device-Objekt.
! * Für Initial-Werte wird das Device bei Amazon zunächst abgefragt
! *
! * @param object amazonDeviceObject
! * @param boolean forceCreation
! /
! function createDeviceControl(amazonDeviceObject, forceCreation) {
! logInfo('createDeviceControl: '+ amazonDeviceObject.accountName);
! var controlPath = deviceObjectPath + clearName(amazonDeviceObject.accountName) + ".control";
! // control
! createDeviceState(controlPath + ".LastStatus", 'INIT', forceCreation, {name:"Letzter Status", type:"string", role:"value"});
! createDeviceControlState(controlPath + ".updateDevice", false, forceCreation, {name:"Device abfragen", type:"boolean", role:"button"});
! // deviceObjectPath + clearName(amazonDeviceObject.accountName) + ".control.lastState"
! getDeviceStateBySerialAndType(amazonDeviceObject.serialNumber, amazonDeviceObject.deviceType, function(deviceState){
! createDeviceControlState(controlPath + ".volume", parseInt(deviceState.volume), forceCreation, {name:"Volume in Prozent(0-100)", type:"number", role:"level.volume"});
! createDeviceControlState(controlPath + ".pause", false, forceCreation, {name:"Pause", type:"boolean", role:"button"});
! createDeviceControlState(controlPath + ".play", false, forceCreation, {name:"Play", type:"boolean", role:"button"});
! if(deviceHasMusicPlayer(amazonDeviceObject.capabilities)){
! createDeviceControlState(controlPath + ".next", false, forceCreation, {name:"Next (nächster Titel)", type:"boolean", role:"button"});
! createDeviceControlState(controlPath + ".previous", false, forceCreation, {name:"Previous (vorheriger Titel)", type:"boolean", role:"button"});
! createDeviceControlState(controlPath + ".forward", false, forceCreation, {name:"Forward (Hörbuch 30 Sekunden vor)", type:"boolean", role:"button"});
! createDeviceControlState(controlPath + ".rewind", false, forceCreation, {name:"Rewind (Hörbuch 30 Sekunden zurück)", type:"boolean", role:"button"});
! createDeviceControlState(controlPath + ".previous", false, forceCreation, {name:"Previous (vorheriger Titel)", type:"boolean", role:"button"});
! createDeviceControlState(controlPath + ".shuffle", deviceState.shuffling, forceCreation, {name:"Shuffel an/aus", type:"boolean", role:"switch"});
! createDeviceControlState(controlPath + ".repeat", deviceState.looping, forceCreation, {name:"Repeat an/aus)", type:"boolean", role:"switch"});
! createDeviceControlState(controlPath + ".playlistId", false, forceCreation, {name:"spiele Playlist", type:"string", role:"control.value"});
! }
! if(deviceHasTuneIn(amazonDeviceObject.capabilities)){
! createDeviceControlState(controlPath + ".radio", false, forceCreation, {name:"Letzte Radiostation an/aus", type:"boolean", role:"switch"});
! createDeviceControlState(controlPath + ".tunein", defaultRadiostation, forceCreation, {name:"tunein Radiosenderkennung", type:"string", role:"control.value"});
! }
! getDevicePlayerBySerialAndType(amazonDeviceObject.serialNumber, amazonDeviceObject.deviceType, function(devicePlayer){
! // player
! var playerPath = deviceObjectPath + clearName(amazonDeviceObject.accountName) + ".player";
! createDeviceState(playerPath + ".contentType", getStringOrEmpty(deviceState.contentType), forceCreation, {name:"contentType", type:"string", role:"value"}); // "LIVE_STATION" | "TRACKS" | "CUSTOM_STATION"
! createDeviceControlState(playerPath + ".currentState", getStringOrEmpty(deviceState.currentState), forceCreation, {name:"currentState", type:"string", role:"value"}); // "PAUSED" | "PLAYING"
! createDeviceState(playerPath + ".imageURL", getStringOrEmpty(deviceState.imageURL), forceCreation, {name:"Grosses Bild", type:"string", role:"value"});
! createDeviceState(playerPath + ".muted", deviceState.muted, forceCreation, {name:"muted", type:"boolean", role:"value"});
! createDeviceState(playerPath + ".providerId", getStringOrEmpty(deviceState.providerId), forceCreation, {name:"providerId", type:"string", role:"value"}); // "TUNE_IN" | "CLOUD_PLAYER" | "ROBIN"
! createDeviceState(playerPath + ".radioStationId", getStringOrEmpty(deviceState.radioStationId), forceCreation, {name:"radioStationId", type:"string", role:"value"}); // "s24885" | null
! createDeviceState(playerPath + ".service", getStringOrEmpty(deviceState.service), forceCreation, {name:"service", type:"string", role:"value"}); // "TUNE_IN" | "CLOUD_PLAYER" | "PRIME_STATION"
! var providerName = null;
! if ((devicePlayer !== undefined) &&("provider" in devicePlayer) && (devicePlayer.provider !== null)){
! providerName = getStringOrEmpty(devicePlayer.provider.providerName);
! }
! createDeviceState(playerPath + ".providerName", providerName, forceCreation, {name:"active providerName", type:"string", role:"value"}); // "Amazon Music" | "TuneIn Live-Radio"
! var title = '';
! var interpreter = '';
! var album = '';
! if ((devicePlayer !== undefined) &&("infoText" in devicePlayer) && (devicePlayer.infoText !== null)){
! title = getStringOrEmpty(devicePlayer.infoText.title);
! interpreter = getStringOrEmpty(devicePlayer.infoText.subText1);
! album = getStringOrEmpty(devicePlayer.infoText.subText2);
! }
! createDeviceState(playerPath + ".title", title, forceCreation, {name:"active title", type:"string", role:"value"});
! createDeviceState(playerPath + ".interpreter", interpreter, forceCreation, {name:"active interpreter", type:"string", role:"value"});
! createDeviceState(playerPath + ".album", album, forceCreation, {name:"active album", type:"string", role:"value"});
! var mainArtUrl = '';
! if ((devicePlayer !== undefined) &&("mainArt" in devicePlayer) && (devicePlayer.mainArt !== null)){
! mainArtUrl = getStringOrEmpty(devicePlayer.mainArt.url);
! }
! createDeviceState(playerPath + ".mainArtUrl", mainArtUrl, forceCreation, {name:"active mainArtUrl", type:"string", role:"value"});
! var miniArtUrl = '';
! if ((devicePlayer !== undefined) &&("miniArt" in devicePlayer) && (devicePlayer.miniArt !== null)){
! miniArtUrl = getStringOrEmpty(devicePlayer.miniArt.url);
! }
! createDeviceState(playerPath + ".miniArtUrl", miniArtUrl, forceCreation, {name:"active miniArtUrl", type:"string", role:"value"});
! var mediaLength = 0;
! var mediaProgress = 0;
! var mediaProgressPercent = 0;
! if ((devicePlayer !== undefined) &&("progress" in devicePlayer) && (devicePlayer.progress !== null)) {
! mediaLength = parseInt(devicePlayer.progress.mediaLength);
! mediaProgress = parseInt(devicePlayer.progress.mediaProgress);
! if (mediaLength > 0) {
! mediaProgressPercent = Math.round(((mediaProgress * 100) / mediaLength));
! }
! }
! createDeviceState(playerPath + ".mediaLength", mediaLength, forceCreation, {name:"active mediaLength", type:"number", role:"value"});
! createDeviceState(playerPath + ".mediaLengthStr", sekToHMS(mediaLength), forceCreation, {name:"active mediaLength als (HH:)MM:SS", type:"string", role:"value"});
! createDeviceState(playerPath + ".mediaProgress", mediaProgress, forceCreation, {name:"active mediaProgress", type:"number", role:"value"});
! createDeviceState(playerPath + ".mediaProgressStr", sekToHMS(mediaProgress), forceCreation, {name:"active mediaProgress als (HH:)MM:SS", type:"string", role:"value"});
! createDeviceState(playerPath + ".mediaProgressPercent", mediaProgressPercent, forceCreation, {name:"active mediaProgressPercent", type:"number", role:"value"});
! });
! });
! }
! /*
! * Erzeugt einen State und macht danach einen Logeintrag
! *
! * @param string objectdevicePath
! * @param mixed initialValue
! * @param boolean forceCreation
! * @param object common
! /
! function createDeviceState(objectdevicePath, initialValue, forceCreation, common) {
! createState(objectdevicePath, initialValue, forceCreation, common, null, function(){logInfo('createState: ' + objectdevicePath)});
! }
! /*
! * Erzeugt einen State und macht danach einen Logeintrag
! * Dann wird für den State eine "on()-Funktion" erzeugt, die die gewünschte Funktion ausfürht
! *
! * @param string objectdevicePath
! * @param mixed initialValue
! * @param boolean forceCreation
! * @param object common
! /
! function createDeviceControlState(objectdevicePath, initialValue, forceCreation, common) {
! createState(
! objectdevicePath,
! initialValue,
! forceCreation,
! common,
! null,
! function () {
! logInfo('createState: ' + objectdevicePath);
! setTimeout(
! function() {
! logInfo("CreateON: " + objectdevicePath);
! on({id: "javascript." + instance + "." + objectdevicePath, change: "any"},
! function (obj){
! var objArr = obj.id.match(/(^.+).(.+).(.+).(.+)$/, ""); //Aufteilung in devicePath + deviceDpName + CMD
! var deviceDpName = objArr[2];
! var cmd = objArr[4];
! logDebug("Device: " + deviceDpName+", Kommando: " + cmd);
! parameter = obj.state.val;
! var reloadCallback = function() {setTimeout(function() {updateDevice(deviceDpName);}, 3000);};
! switch (cmd) {
! // Buttons, werden immer wieder auf false gesetzt
! case "updateDevice":
! unsetButtonFirst(obj, function (obj) {updateDevice(deviceDpName);});
! break;
! case "pause":
! unsetButtonFirst(obj, function (obj) {setPause(deviceDpName, reloadCallback);});
! break;
! case "play":
! unsetButtonFirst(obj, function (obj) {setPlay(deviceDpName, reloadCallback);});
! break;
! case "next":
! unsetButtonFirst(obj, function (obj) {setNext(deviceDpName, reloadCallback);});
! break;
! case "previous":
! unsetButtonFirst(obj, function (obj) {setPrevious(deviceDpName, reloadCallback);});
! break;
! case "forward":
! unsetButtonFirst(obj, function (obj) {setForward(deviceDpName, reloadCallback);});
! break;
! case "rewind":
! unsetButtonFirst(obj, function (obj) {setRewind(deviceDpName, reloadCallback);});
! break;
! //Switch
! case "shuffle":
! if(parameter === null){
! logWarn("Alexa Shuffle: kein true/false angegeben. Auf true gesetzt.");
! parameter = true;
! }
! setShuffle(deviceDpName, parameter);
! break;
! case "repeat":
! if(parameter === null){
! logWarn("Alexa Repeat: kein true/false angegeben. Auf true gesetzt.");
! parameter = true;
! }
! setRepeat(deviceDpName, parameter);
! break;
! case "radio":
! if(obj.state.val) {
! // Letzte Radiostation einschlaten
! var stationId = getState(deviceObjectPath + deviceDpName + ".control.tunein").val;
! setTuneIn(deviceDpName,stationId, reloadCallback);
! } else {
! // Musik auf Pause.
! setPause(deviceDpName, reloadCallback);
! }
! break;
! case "volume":
! if(!parameter ||parameter === null){
! logWarn("Alexa Volume: keine Lautstärke angegeben. Parameter fehlt.");
! break;
! }
! parameter = parseInt(parameter);
! if(parameter < 0) {
! parameter = 0;
! logWarn("Alexa Volume: ungültige Lautsträke angegeben (<0). Auf 0 gesetzt.");
! }
! if(parameter > 100) {
! parameter = 100;
! logWarn("Alexa Volume: ungültige Lautsträke angegeben (>100). Auf 100 gesetzt.");
! }
! setVolume(deviceDpName, parameter);
! break;
! case "playlistId":
! setPlaylistId(deviceDpName, parameter, reloadCallback);
! break;
! case "tunein":
! setTuneIn(deviceDpName,parameter, reloadCallback);
! break;
! case "currentState":
! // den aktuellen "mediaProgress" berechnen, statt ihn immer neu runterzuladen
! if ((obj.oldState.val == 'PAUSED') && (obj.state.val == 'PLAYING')) {
! // Wechsel von Pause zu Playing
! updateMediaProgress(deviceDpName);
! } else if (obj.state.val == 'PLAYING') {
! // war vorher nicht Pause, nun aber Playing, dann überprüfen, ob sich "mediaProgress"
! // innerhalb einer gewissen Zeit verändert (dann wurde die Funktion bereits ausgeführt)
! var playerPath = deviceObjectPath + deviceDpName + ".player";
! setTimeout( function() {
! var mediaProgress = getState(playerPath + ".mediaProgress").val;
! setTimeout( function() {
! var mediaProgressNew = getState(playerPath + ".mediaProgress").val;
! // Wurde mediaProgress in der Zeit trotz PLAYING nicht verändert, dann trotzdem ausführen
! if (mediaProgressNew == mediaProgress){
! setState(playerPath + ".mediaProgress", mediaProgressNew + 7);
! updateMediaProgress(deviceDpName);
! }
! }, 5000 );
! }, 3000 );
! }
! break;
! default:
! logWarn("Kommando << "+cmd+" >> im Skript nicht behandelt");
! break;
! }
! })
! }
! ,
! 3000
! );
! }
! );
! }
! // –-----------------------------------------------------------------------------------------------------
! // HTTPS-GET/POST-Funktionen
! // -------------------------------------------------------------------------------------------------------
! /*
! * Setzt die Options für den https Request
! *
! * @param string path
! * @param string method - Should be GET oder POST
! /
! function setOptions(path,method) {
! var options = {
! "host": 'layla.amazon.de',
! "path": path,
! "method": method,
! "timeout":10000,
! "headers": {
! 'User-Agent' : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36',
! 'Content-Type': 'text/plain',
! 'csrf' : csrf,
! 'Cookie' : cookie
! }
! };
! return options;
! }
! /*
! * Erzeugt eine GET Anfrage
! * @param string path
! * @param function callback
! /
! function httpsReqGet(path,callback) {
! logDebug("Abfrage " + path + " an Alexa gesendet");
! var options = setOptions(path,"GET");
! var req = https.get(options, function getDevices(res) {
! logDebug('STATUS: ' + res.statusCode) + ": " + statusCode(res.statusCode); // Statuscode
! logDebug('HEADERS: ' + JSON.stringify(res.headers)); // Header (Rückmeldung vom Webserver)
! // Buffer the body entirely for processing as a whole.
! var bodyChunks = [];
! var chunkLine = 0;
! res.on('data', function(chunk) {
! chunkLine = chunkLine + 1;
! // Hier können die einzelnen Zeilen verarbeitet werden...
! logDebug("Zeilennummer: " + chunkLine+ " ,Inhalt: " + chunk);
! bodyChunks.push(chunk);
! }).on('end', function() {
! logDebug("ARRAY mit den einzelnen Zeilen: " + bodyChunks);
! logDebug("ARRAY Länge: " + bodyChunks.length);
! var body = Buffer.concat(bodyChunks);
! // ...und/oder das Gesamtergebnis (body).
! if(!body) log("keine Daten erhalten","warn");
! logDebug('BODY: ' + body);
! if(callback !== undefined && typeof callback === 'function') return callback(body);
! });
! });
! req.on('error', function(e) { // Fehler abfangen
! log('ERROR: ' + e.message,"warn");
! log("keinen gültigen Callback gefunden","warn");
! ok = false;
! });
! req.end();
! }
! /*
! * Setzt das Device auf die Lautstärke
! *
! * @param string deviceDpName
! * @param integer volumeLevel
! * @param function callback
! /
! function setVolume(deviceDpName, volumeLevel, callback) {httpsPostCmd(deviceDpName, '{"type":"VolumeLevelCommand","volumeLevel":' + volumeLevel + '}' , callback);}
! /*
! * Setzt das Device auf PLAY
! *
! * @param string deviceDpName
! * @param function callback
! /
! function setPlay(deviceDpName, callback) {httpsPostCmd(deviceDpName, '{"type":"PlayCommand"}', callback);}
! /*
! * Setzt das Device auf PAUSE
! *
! * @param string deviceDpName
! * @param function callback
! /
! function setPause(deviceDpName, callback) {httpsPostCmd(deviceDpName, '{"type":"PauseCommand"}', callback);}
! /*
! * Setzt das Device auf NEXT
! *
! * @param string deviceDpName
! * @param function callback
! /
! function setNext(deviceDpName, callback) {httpsPostCmd(deviceDpName, '{"type":"NextCommand"}', callback);}
! /*
! * Setzt das Device auf PREVIOUS
! *
! * @param string deviceDpName
! * @param function callback
! /
! function setPrevious(deviceDpName, callback) {httpsPostCmd(deviceDpName, '{"type":"PreviousCommand"}', callback);}
! /*
! * Setzt das Device auf FORWARD
! *
! * @param string deviceDpName
! * @param function callback
! /
! function setForward(deviceDpName, callback) {httpsPostCmd(deviceDpName, '{"type":"ForwardCommand"}', callback);}
! /*
! * Setzt das Device auf REWIND
! *
! * @param string deviceDpName
! * @param function callback
! /
! function setRewind(deviceDpName, callback) {httpsPostCmd(deviceDpName, '{"type":"RewindCommand"}', callback);}
! /*
! * Setzt für das Device SHUFFLE auf den gewünschten zustand
! *
! * @param string deviceDpName
! * @param boolean state
! * @param function callback
! /
! function setShuffle(deviceDpName, state, callback) {httpsPostCmd(deviceDpName, '{"type":"ShuffleCommand","shuffle":' + state + '}', callback);}
! /*
! * Setzt für das Device REPEAT auf den gewünschten zustand
! *
! * @param string deviceDpName
! * @param boolean state
! * @param function callback
! /
! function setRepeat(deviceDpName, state, callback) {httpsPostCmd(deviceDpName, '{"type":"RepeatCommand","repeat":' + state + '}', callback);}
! /*
! * Schickt ein Kommando an Alexa
! *
! * @param string deviceDpName
! * @param string postData
! * @param function callback
! /
! function httpsPostCmd(deviceDpName, postData, callback) {
! logInfo("[httpsPostCmd] Device: " + deviceDpName + " - Kommando: " + postData);
! var path = '/api/np/command?'
! + 'deviceSerialNumber=' + devices[deviceDpName].serialNumber
! + '&deviceType=' + devices[deviceDpName].deviceType ;
! httpsPost(deviceDpName, path, postData, callback);
! }
! /*
! * Startet auf dem Device den Radiosender
! *
! * @param string deviceDpName
! * @param string stationId
! * @param function callback
! /
! function setTuneIn(deviceDpName,stationId, callback) {
! logInfo("[setTuneIn] Device: " + deviceDpName + " - TuneIn-StationId: " + stationId);
! var path = '/api/tunein/queue-and-play?'
! + 'deviceSerialNumber=' + devices[deviceDpName].serialNumber
! + '&deviceType=' + devices[deviceDpName].deviceType
! + '&guideId=' + stationId
! + '&contentType=station&callSign=&mediaOwnerCustomerId=' + mediaOwnerCustomerId;
! httpsPost(deviceDpName, path, '', callback);
! }
! /*
! * Startet auf dem Device die Playlist
! *
! * @param string deviceDpName
! * @param string playlistId
! * @param function callback
! /
! function setPlaylistId(deviceDpName, playlistId, callback) {
! logInfo("[setPlaylistId] Device: " + deviceDpName + " - PlaylistId: " + playlistId);
! var path = '/api/cloudplayer/queue-and-play?'
! + 'deviceSerialNumber=' + devices[deviceDpName].serialNumber
! + '&deviceType=' + devices[deviceDpName].deviceType
! + '&shuffle=false'
! + '&contentType=station&callSign=&mediaOwnerCustomerId=' + mediaOwnerCustomerId;
! httpsPost(deviceDpName, path, '{"playlistId":"' + playlistId + '"}', callback);
! }
! /*
! * Erzeugt eine POST Anfrage und setzt den Status-Code
! * der Anfrage in das 'control.LastStatus' Feld
! *
! * @param string deviceDpName
! * @param string path
! * @param string postData
! * @param function callback
! /
! function httpsPost(deviceDpName, path, postData, callback) {
! logDebug("[httpsPost] Device: " + deviceDpName + " Path: " + path + " postData: " + postData);
! var options = setOptions(path,"POST");
! // request object
! var req = https.request(options, function (res) {
! var result = '';
! res.on('data', function (chunk) {
! result += chunk;
! });
! res.on('end', function () {
! logDebug(result);
! setState(deviceObjectPath + deviceDpName +".control.LastStatus",res.statusCode.toString()+" " + statusCode(res.statusCode));
! if(res.statusCode != 200) {
! logWarn("Negative Rückmeldung von Alexa: " + res.statusCode + ": " + statusCode(res.statusCode));
! logWarn("Gesendetes Kommando: " + postData);
! } else {
! logDebug('STATUS: ' + res.statusCode + ": " + statusCode(res.statusCode)); // Statuscode
! }
! if(res.statusCode != 200){
! logWarn('HEADERS: ' + JSON.stringify(res.headers)); // Header (Rückmeldung vom Webserver)
! }
! if(callback !== undefined && typeof callback === 'function') callback(result);
! });
! res.on('error', function (err) {
! logWarn('ERROR: ' + err.message);
! })
! });
! // req error
! req.on('error', function (err) {
! logWarn('ERROR: ' + err.message);
! });
! //send request witht the postData form
! req.write(postData);
! req.end();
! }
! // –-----------------------------------------------------------------------------------------------------
! // Hilfs-Funktionen
! // -------------------------------------------------------------------------------------------------------
! /*
! * Setzt das gewünschte Loglevel
! *
! * @param string level
! /
! function setLoglevel(level) {
! switch(level.toLowerCase()) {
! case 'debug':
! logLevelInt = 0;
! break;
! case 'info':
! logLevelInt = 1;
! break;
! case 'warn':
! logLevelInt = 2;
! break;
! case 'error':
! logLevelInt = 3;
! break;
! case 'none':
! logLevelInt = 4;
! break;
! default:
! logLevelInt = 2;
! break;
! }
! }
! /*
! * Logt eine DEBUG Message
! * (wird als info geloggt, da Debug nicht angezeigt wird)
! *
! * @param string msg
! /
! function logDebug(msg) {
! if (logLevelInt <= 0) {
! log(msg, "info");
! }
! }
! /*
! * Logt eine INFO Message
! *
! * @param string msg
! /
! function logInfo(msg) {
! if (logLevelInt <= 1) {
! log(msg, "info");
! }
! }
! /*
! * Logt eine WARN Message
! *
! * @param string msg
! /
! function logWarn(msg) {
! if (logLevelInt <= 2) {
! log(msg, "warn");
! }
! }
! /*
! * Logt eine ERROR Message
! *
! * @param string msg
! /
! function logError(msg) {
! if (logLevelInt <= 3) {
! log(msg, "error");
! }
! }
! /*
! * Durchsucht ein Array nach needle und
! * liefert bei Erfolg TRUE
! *
! * @param string needle
! * @param array haystack
! * @return boolean
! /
! function inArray(needle, haystack) {
! var length = haystack.length;
! for(var i = 0; i < length; i++) {
! if(haystack == needle) return true;
! }
! return false;
! }
! /*
! * Gibt zurück, ob die capabilities ein Steuern zulassen
! *
! * @param array capabilities
! * @return boolean
! /
! function deviceIsControllable(capabilities) {
! return (inArray('AUDIO_PLAYER', capabilities)
! || inArray('AMAZON_MUSIC', capabilities)
! || inArray('TUNE_IN', capabilities));
! }
! /*
! * Gibt zurück, ob die capabilities eine Audiowiedergabe zulassen
! *
! * @param array capabilities
! * @return boolean
! /
! function deviceHasMusicPlayer(capabilities) {
! return (inArray('AUDIO_PLAYER', capabilities)
! || inArray('AMAZON_MUSIC', capabilities));
! }
! /*
! * Gibt zurück, ob die capabilities TuneIn und somit Radio zulassen
! *
! * @param array capabilities
! * @return boolean
! /
! function deviceHasTuneIn(capabilities) {
! return (inArray('TUNE_IN', capabilities));
! }
! /*
! * Button wieder auf false zurücksetzen, wenn er true war, danach callback
! *
! * @param object obj
! * @param function callback
! /
! function unsetButtonFirst(obj, callback) {
! if(getState(obj.id).val) {
! setState(obj.id,false);
! if(callback !== undefined && typeof callback === 'function') callback(obj);
! }
! }
! /*
! * Liefert str als String zurück, '' anstelle von null, false, …
! *
! * @param mixed str
! * @return string
! /
! function getStringOrEmpty(str){
! return (String(str) !== 'undefined') ? String(str) : '';
! }
! /*
! * Liefert das Device anhand der seriennummer
! *
! * @param string serialNumber
! * @param object
! /
! function getDeviceNameBySerialNumber(serialNumber) {
! for (device in devices) {
! if (devices[device].serialNumber == serialNumber) {
! return device;
! }
! }
! return null;
! }
! /*
! * Liefert das erste Device das einen MusicPlayer hat,
! * oder null, wenn es keines gibt
! *
! * @return object|null
! /
! function getEchoWithMusicPlayerFromDevices() {
! for (device in devices) {
! if (deviceHasMusicPlayer(devices[device].capabilities)) {
! return devices[device];
! }
! }
! return null;
! }
! /*
! * Liefert einen bereinigten Namen um daraus einen State-Pfad zu erzeugen
! *
! * @param string name
! * @return string
! */
! function clearName(name){
! name = umlaut(name);
! name = name.replace(/\W/g,"");
! return name;
! }
! /**
! * Ersetzt Umlaufe/Sonderzeichen
! *
! * @param string str
! * @return string
! /
! function umlaut(str) {
! return str
! .replace(/Â|À|Å|Ã/g, "A")
! .replace(/â|à|å|ã/g, "a")
! .replace(/Ä/g, "AE")
! .replace(/ä/g, "ae")
! .replace(/Ç/g, "C")
! .replace(/ç/g, "c")
! .replace(/É|Ê|È|Ë/g, "E")
! .replace(/é|ê|è|ë/g, "e")
! .replace(/Ó|Ô|Ò|Õ|Ø/g, "O")
! .replace(/ó|ô|ò|õ/g, "o")
! .replace(/Ö/g, "OE")
! .replace(/ö/g, "oe")
! .replace(/Š/g, "S")
! .replace(/š/g, "s")
! .replace(/ß/g, "ss")
! .replace(/Ú|Û|Ù/g, "U")
! .replace(/ú|û|ù/g, "u")
! .replace(/Ü/g, "UE")
! .replace(/ü/g, "ue")
! .replace(/Ý|Ÿ/g, "Y")
! .replace(/ý|ÿ/g, "y")
! .replace(/Ž/g, "Z")
! .replace(/ž/, "z");
! }
! /*
! * Liefert einen String zum http-Status
! *
! * @param integer status
! * @return string
! /
! function statusCode(status) {
! if(status === 0) return "* Daten unvollständig ** (csrf fehlt/falsch? Cookie falsch?)";
! if(status == 200) return "** OK ";
! if(status == 302) return " Found (Moved Temporarily) ** (Cookie abgelaufen?)";
! if(status == 401) return "** Unauthorized ** (Cookie nicht richtig gesetzt?)";
! if(status == 403) return "** Forbidden ** (Kombination Cookie, deviceType, Seriennummer richtig?)";
! if(status == 404) return "** Not Found ** (Kommando im Kontext des Geräts sinnvoll?)";
! if(status == 500) return "** Internal Server Error** (ggf. Kommando im falschen Kontext verwendet?)";
! return "Fehler";
! }
! /**
! * Liefert einen String zum deviceType
! *
! * @param integer deviceType
! * @return string
! /
! function deviceTypeStr(deviceType){
! if(!knownDeviceType[deviceType] || knownDeviceType[deviceType] === undefined) return "Gerät unbekannt";
! return knownDeviceType[deviceType];
! }
! /*
! * Konvertiert eine Sekundenzahl in einen String im Format (HH:)MM:SS
! *
! * @param integer sek
! * @return string
! */
! function sekToHMS(sek) {
! if (sek === 0) {
! return '0';
! }
! var sec_num = parseInt(sek, 10);
! var hours = Math.floor(sec_num / 3600);
! var minutes = Math.floor((sec_num - (hours * 3600)) / 60);
! var seconds = sec_num - (hours * 3600) - (minutes * 60);
! if (minutes < 10) {minutes = "0"+minutes;}
! if (seconds < 10) {seconds = "0"+seconds;}
! if (hours === 0) {
! return minutes+':'+seconds;
! }
! if (hours < 10) {hours = "0"+hours;}
! return hours+':'+minutes+':'+seconds;
! }___________________________ _____________z.Beispiel was bedeuten die Zahlen am Ende von dem Fehler. Ist die Zeile von der Error im Script auftritt ?
y controller[0]: at IncomingMessage. <anonymous>(script.js.Alexa_Device_Command:214:81)
Caught 2018-06-12 20:38:20.461 error by controller[0]: at dpAbfrageAlexaAnlegen (script.js.Alexa_Device_Command:245:32)
Caught 2018-06-12 20:38:20.461 error by controller[0]: SyntaxError: Unexpected end of JSON input</anonymous>_____________