Alexa Notifications - Override/Reroute Speech Commands

Posted on
Mon Jun 22, 2020 11:01 am
whmoorejr offline
User avatar
Posts: 762
Joined: Jan 15, 2013
Location: Houston, TX

Re: Alexa Notifications - Override/Reroute Speech Commands

mundmc wrote:
Any progress on this?


sorta/kinda. I never figured out how to do sounds this way, but I can using Node-Red. I have a lot more 2-way control / integration between Alexa and Indigo using node-red. I'm still using these .js script things for basic announcements or announcing variables on the fly.... but with Node-Red I've been able to add more devices and better control of devices through Alexa and able to push out sounds to devices (doorbells, animals.... even fart noises.... because what's an automated house without that?)... https://forums.indigodomo.com/viewtopic.php?f=133&t=23486&hilit=node+red

If you get into it, it's kinda cool. You can do things like add a "dashboard" plugin that lets you create little webpages that run on the node-red server (for me, thats on the same Mac as my indigo server). I can then link to those pages within indigo touch. It can provide things like a dropdown that polls your amazon account and populates it with all the available speakers you want to send a fart noise to. Or you can create a little music page that lets you select your provider (Amazon Music, iHeart, Pandora, etc) and then search for the station you want (compete with cover-art, track progress, etc.... and it's all just drag and drop easy)

Bill
My Plugin: My People

Posted on
Mon Jun 22, 2020 6:54 pm
mundmc offline
User avatar
Posts: 1060
Joined: Sep 14, 2012

Re: Alexa Notifications - Override/Reroute Speech Commands

whmoorejr wrote:
mundmc wrote:
Any progress on this?


sorta/kinda. I never figured out how to do sounds this way, but I can using Node-Red. I have a lot more 2-way control / integration between Alexa and Indigo using node-red. I'm still using these .js script things for basic announcements or announcing variables on the fly.... but with Node-Red I've been able to add more devices and better control of devices through Alexa and able to push out sounds to devices (doorbells, animals.... even fart noises.... because what's an automated house without that?)... https://forums.indigodomo.com/viewtopic.php?f=133&t=23486&hilit=node+red

If you get into it, it's kinda cool. You can do things like add a "dashboard" plugin that lets you create little webpages that run on the node-red server (for me, thats on the same Mac as my indigo server). I can then link to those pages within indigo touch. It can provide things like a dropdown that polls your amazon account and populates it with all the available speakers you want to send a fart noise to. Or you can create a little music page that lets you select your provider (Amazon Music, iHeart, Pandora, etc) and then search for the station you want (compete with cover-art, track progress, etc.... and it's all just drag and drop easy)
If only i had time to take on Node Red- it looks super-flexible but the effort buy-in is too much right now :)

Posted on
Tue Aug 01, 2023 3:45 pm
ckeyes888 offline
Posts: 2417
Joined: Nov 26, 2009
Location: Kalispell, MT

Re: Alexa Notifications - Override/Reroute Speech Commands

Having an issue with the volume of the announcements.
Maybe some way to adjust it within the script?

Thanks,

Carl

Code: Select all
 const fs = require("fs");
let Alexa = require('alexa-remote2');
let alexa = new Alexa();

/***************************************************************/
// Default speech settings for creating SSML
// Amazon's SSML Reference: https://developer.amazon.com/docs/custom-skills/speech-synthesis-markup-language-ssml-reference.html
var defaultVoice = "Amy";
var defaultLang = "en-US";

/***************************************************************/
// see: https://www.gehrig.info/alexa/Alexa.html
// cookie starts with x-amzn-dat and ends with =" csrf=12345780
let cookie = {};

var cookieFile = "/Users/TV/Desktop/Alexa/my-cookie.json";
var deviceFile = "/Users/TV/Desktop/Alexa/my-devices.json";

// Load last cookie from file
if (fs.existsSync(cookieFile)) cookie = JSON.parse(fs.readFileSync(cookieFile));


alexa.init({
        cookie: cookie,  // cookie if already known, else can be generated using email/password
        email: '...',    // optional, amazon email for login to get new cookie
        password: '...', // optional, amazon password for login to get new cookie
        proxyOnly: true,
        proxyOwnIp: 'localhost',
        proxyPort: 3001,
        proxyLogLevel: 'info',
        bluetooth: true,
        logger: console.log, // optional
        alexaServiceHost: 'pitangui.amazon.com', // optional, e.g. "pitangui.amazon.com" for amazon.com, default is "layla.amazon.de"
        //userAgent: '...', // optional, override used user-Agent for all Requests and Cookie determination
        acceptLanguage: 'en-US', // optional, override Accept-Language-Header for cookie determination
        amazonPage: 'amazon.com', // optional, override Amazon-Login-Page for cookie determination and referer for requests
        useWsMqtt: true, // optional, true to use the Websocket/MQTT direct push connection
        cookieRefreshInterval: 7*24*60*1000 // optional, cookie refresh intervall, set to 0 to disable refresh
    },
    function (err) {
        if (err) {
            console.log(err);
            return;
        }

        argCommand = ''
        argDetail = ''
        argDevice = ''

        console.log('>>>>START<<<<<')
        for (let j = 0; j < process.argv.length; j++) {
            if (j == 2) {
                argCommand = process.argv[j]
            }

            if (j == 3) {
                argDetail = process.argv[j]
            }

            if (j == 4) {
                argDevice = process.argv[j]
            }

            console.log(j + ' -> ' + (process.argv[j]));
        }
        console.log('>>>>END<<<<<')



        // Save cookie to file so it can be used next time, as long as it is still valid.
        saveCookie();


        if (argCommand !== '') {
            if (argDetail !== '') {
                if (argDevice !== '') {
                    sendCommand(argCommand, argDetail, [argDevice]);
                } else {
                    sendCommand(argCommand, argDetail)
                }
            }
        }

        // Change the sendCommand call below to send a command to one or more of your Alexa devices.
        //sendCommand("ssml", "This is an english test from Indigo.");

        // Here are a few other example calls.
         
       
        //sendCommand("speak", "This is a test to one device only.", ["Study Echo Dot"]);

        //sendCommand("singasong", "", "SERIALNUMBER");

        //sendCommand("weather", "", "Family Room");

        /*
       
        //Send custom SSML string
        let customSSML = "<speak>" +
            "<lang xml:lang='en-UK'>" +
            "<say-as interpret-as='interjection'>hiya. guess what.</say-as>" +
            "I wanna tell you a secret" +
            "<break time='500ms'/>" +
            "<amazon:effect name='whispered'>I can see your browser history.</amazon:effect>" +
            "<break time='1s'/>" +
            "<say-as interpret-as='interjection'>schwing. oh my.</say-as>" +
            "<break time='1500ms'/>" +
            "<say-as interpret-as='interjection'>ha ha. gotcha.</say-as>." +
            '</lang>' +
            '</speak>';
        sendCommand("ssml", customSSML, ["Study Echo Dot"]);
        /* */

        // Pause so the command has a chance to be sent. Then exit.
        setTimeout(function(){
            process.exit();
        },5000);
    }
);


function saveCookie() {
    // Save cookie (and device data for reference).
    console.log("Saving cookie to file: " + cookieFile);
    try {
        // Save device data
        fs.writeFileSync(deviceFile, JSON.stringify(alexa.serialNumbers, null,4));

        // Save cookie
        if (alexa.cookieData) {
            if (alexa.cookieData.csrf) {
                fs.writeFileSync(cookieFile, JSON.stringify(alexa.cookieData,null,4));
            } else {
                throw new Error("alexa.cookieData is invalid or missing 'csrf' property.");
            }
        } else {
            throw new Error("alexa.cookieData is null or empty.");
        }
    } catch (e) {
        console.log("Error saving cookie and/or list of devices: " + e.message);
    }
}

function sendCommand(command, value, deviceIDs) {
    try {
        // See createSequenceNode function in alexa-remote.js for a list of commands.

        // If no devices are specified, the command will be sent to ALL devices.
        if (!deviceIDs) deviceIDs = getAllDeviceSerialNumbers();
        if (!Array.isArray(deviceIDs)) deviceIDs = [deviceIDs];

        // Build list of commands
        // The 'ssml' and 'announcement' commands support sending to multiple devices at once. The other commands do not.
        let allCommands = [];
        if (['ssml','announcement'].includes(command)) {
            let thisCommand = {};
            thisCommand.command = command;
            thisCommand.value = (command == 'ssml') ? stringToSSML(value) : value;
            allCommands.push(thisCommand);
        } else {
            deviceIDs.forEach(function(name) {
                let thisCommand = {};
                thisCommand.command = command;
                thisCommand.value = value;
                thisCommand.device = name;
                allCommands.push(thisCommand);
            });
        }

        console.log("Sending command(s):\n" + JSON.stringify({
            devices: deviceIDs,
            commands: allCommands,
        },null,4));

        alexa.sendMultiSequenceCommand(deviceIDs, allCommands);

        return;

    } catch (e) {
        console.log("Error sending command: \n" + JSON.stringify(e, null, 4));
    }
}

function stringToSSML(input) {
    if (input.startsWith('<speak>')) {
        // Input is already in SSML format.
        return input;
    } else {
        // Encapsulate string in XML using default voice/lang values, if provided.
        let output;
        output = input;
        if (defaultLang) output = '<lang xml:lang="' + defaultLang + '">' + output + '</lang>';
        if (defaultVoice) output = '<voice name="' + defaultVoice + '">' + output + '</voice>';
        output = '<speak>' + output + '</speak>';
        return output;
    }
}

function getAllDeviceSerialNumbers() {
    let serials = [];
    Object.values(alexa.serialNumbers).forEach(function(dev){
        serials.push(dev.serialNumber);
    });
    return serials;
}

Who is online

Users browsing this forum: No registered users and 4 guests