DEV Community

loading...
Cover image for Broadcast Google Home alarms & timers

Broadcast Google Home alarms & timers

MHA
Home Automation
・2 min read

Using Home Assistant and Node-RED I broadcast ringing Google Home alarms and timers to other media players.

Goal

  • When a Google Home alarm or timer rings broadcast it to other devices
  • Have a choice between TTS or playing a MP3 file

The subflow

Alt Text

The function node finds ringing alarms or timers and creates the data for the service call, it will send a message for each defined media player.

Code
const defaults = {
    timer: {
        items: 'timers',
        name: 'timer'
    },
    alarm: {
        items: 'alarms',
        name: 'alarms'
    }
}
const mediaPlayers = env.get('media_players');
const mode = env.get('mode');
let type = '';
let callService = {}

if(!msg.data || !mediaPlayers || !mode) {
    return null;
}

if(mode === 'tts') {
    callService = {
        domain: 'tts',
        service: 'google_translate_say',
        data: {
            entity_id: '',
            message: '',    
        }
    }
} else if (mode === 'mp3') {
    if(!env.get('file')) {
        return null;
    }
    callService = {
        domain: 'media_player',
        service: 'play_media',
        data: {
            entity_id: '',            
            media_content_id: env.get('file'),
            media_content_type: 'music',
        }
    }
}


// Determine type: alarm or timer
if(typeof msg.data.new_state.attributes.timers !== 'undefined' || typeof msg.data.old_state.attributes.timers !== 'undefined' ) {
    type = 'timer';
} else if (typeof msg.data.new_state.attributes.alarms !== 'undefined' || typeof msg.data.old_state.attributes.alarms !== 'undefined') {
    type = 'alarm';
} else {
    return null;
}

const typeValues = defaults[type];
const activeItem = (msg.data.new_state.attributes[typeValues.items] || []).find(item => item.status === 'ringing');
if (!activeItem) {
    return null;
}


mediaPlayers.trim().split(/,\s*/).forEach(player => {
    if(!player) return;
    callService.data.entity_id = player;
    if(mode === 'tts') {
        const deviceName = env.get('name') || msg.data.new_state.attributes.friendly_name;
        const ttsMsg = `${activeItem.label || ''} ${typeValues.name} RINGING on ${deviceName}`;
        callService.data.message = ttsMsg;
    }

    const message = {
        payload: callService
    };
    node.send(message);
});

// All done
node.done();

Enter fullscreen mode Exit fullscreen mode
Then the current state node checks if the media player is currently playing, if so we won't send anything to it.

How to use

  1. Import the subflow in NR:
  2. Add the subflow and connect alarm and/or timer sensors from the same device as events_state nodes. Alt Text
  3. Set the properties for the subflow: Alt Text
Property Description Example
Media player ids Comma separated list of media_player entities media_player.mini, media_player.hub
Mode TTS or MP3 TTS
Device name (TTS) Overwrite name for TTS Hub
File path (MP3) Path to MP3 file /local/audio/bell.mp3

Related flow

Make sure to check out my other flow as well:

Discussion (0)