Attempting an intercom

My wife has wanted an intercom in our house for years. Recently I switched from Indigo to HA for multiple reasons, but a bit one was the quality of the UI I could present to her. I was playing around with some frontend things and ran across browser_mod. After realizing it registered a media_player entity I started wondering if I could use that to give her her intercom using wall tablets I had already planned on putting in place.

I started playing with SIP to do this and make calls between browsers, but I wasn’t overly excited about the user interface (probably fixable) and didn’t want to add another thing I had to make sure was always running to keep the WAF high, so I tried to go back to simple.

Disclosure that I am not a developer, but I can copy/paste with the best of them. The below code seems to work (obviously needs a massive amount of cleanup/UI improvements to be at all useful), but curious if anyone sees an issue with what I am doing. My biggest concern is just the size of the audio recording being sent between the browsers, but I’m not really sure a way around that with this approach.

If nobody says this is the worst idea they’ve ever seen I’ll probably try to take this to the finish line and make it usable to everyone besides just me.

class IntercomCard extends HTMLElement {

    constructor() {
        super();
        this.attachShadow({ mode: 'open' });
    }

    set hass(hass) {
        if (!this._hass) {
            console.log("haSs")
            this._hass = hass;
            this.initRecordings()
        };
    }

    setConfig(config) {
        this.config = config;
        const root = this.shadowRoot;
        if (root.lastChild) root.removeChild(root.lastChild);

        const card = document.createElement('ha-card');
        const content = document.createElement('div');
        const style = document.createElement('style');
        style.textContent = `
            ha-card {
                /* sample css */
            }
            .button {
                overflow: auto;
                padding: 16px;
                text-align: right;
            }
            mwc-button {
                margin-right: 16px;
            }
            `;
        // list of buttons needs to be configurable
        content.innerHTML = `
        <div id='cameraview'>
            <p style="padding: 16px">Destinations should be registered here</p>
            <audio id='audio-player'></audio>
        </div>
        <div class='button'>
            <mwc-button raised id='art_room'>` + 'Art Room' + `</mwc-button>
            <mwc-button style='display:none' raised id='stop'>` + 'Stop' + `</mwc-button>
        </div>
        `;
        card.appendChild(content);
        card.appendChild(style);
        root.appendChild(card);
    }

    initRecordings() {
        if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
            navigator.mediaDevices.getUserMedia({ audio: true, video: false })
                .then(stream => { handlerFunction(stream, this) })
                .catch(function(err) {
                    console.log("The following error occurred initializing intercom (getUserMedia)" + err);
                })
        } else {
            console.log("Intercom is not supported by this browser (lacking getUserMedia)")
        }
  
        function handlerFunction(stream, intercomCard) {
            const options = {mimeType: 'audio/mp4'};
            const mediaRecorder = new MediaRecorder(stream, options);
            let chunks = [];

            let artRoomBtn = intercomCard.getElementById('art_room');
            let stopBtn = intercomCard.getElementById('stop');
    
            artRoomBtn.onclick = function() {
                mediaRecorder.start();
                artRoomBtn.style.display = 'none';
                stopBtn.style.display = 'inline-flex';
            }

            stopBtn.onclick = function() {
                mediaRecorder.stop();
                artRoomBtn.style.display = 'inline-flex';
                stopBtn.style.display = 'none';        
            }

            mediaRecorder.ondataavailable = function(e) {
                chunks.push(e.data);
            }

            mediaRecorder.onstop = function(e) {
                const blob = new Blob(chunks, { 'type' : 'audio/ogg; codecs=opus' });
                chunks = [];

                var reader = new FileReader();
                reader.readAsDataURL(blob); 
                reader.onloadend = function() {
                    intercomCard.playAudio(reader.result);             
                }
  
            }
        }
    }

    playAudio(content) {
        // Destination needs to be dynamic
        // need to have some sort of popup/ui with browser_mod to make it easy to reply
        // play doesn't support anything other than media_content_id https://github.com/thomasloven/hass-browser_mod/blob/f13ac064cabc8f48da04f85cedff9c3936b47642/js/main.js#L166
        this._hass.callService('media_player', 'play_media', {
            entity_id: 'media_player.575b8ffa_9b18fb9d',
            media_content_type: 'music',
            media_content_id: content
        });

    }
  
    // The height of your card. Home Assistant uses this to automatically
    // distribute all cards over the available columns.
    getCardSize() {
        return 1;
    }

    getElementById(id) {
        return this.shadowRoot.querySelector(`#${id}`);
    }
}

customElements.define('intercom-card', IntercomCard);

4 Likes

I think this is a good idea. I’m a while from looking at installing my front door intercom and like the idea of not having to install another panel on the wall but using an integrated HA interface.

My very brief look into it was that the camera side was easy but the SIP side was not there then that project got put on the back burner.

But yeah, most of the intercom solutions I looked at used SIP. By the looks of it, the expensive “hub” part of an intercom system can be replaced with a FreePBX type solution.

Hey, im in a similar position, we could use Google speakers as well but Google doesn’t like my wife’s voice for some reason so she prefers a button to press. Funny though, Google works with my 5 year old daughter LOL.
Anyway, how are you getting on with your solution?

It’s pretty much working, just needs cleanup and a couple small features I want to add, but haven’t had any time in a month to work on it.

Hi Justin,

Any update to your project? I’m trying to figure out a way to add intercom stations throughout my house without having to add an obsolete looking intercom next to the tablet I plan on installing as a wall panel.

Thanks!

5 Likes

Hello,

can you show your config files please or something that help us?

Thanks

Check out this project if you haven’t already. They even created an add-on for asterisk within HA if you would prefer that route.

1 Like

Its not that simple as is seems.
I have hikvision intercom, installed by myself. Its poe intercom. I made automation when someone rings a bell turn on tv and show me a picture of a person ringing and announce this on alexa. What I want to do is two way communication ie. someone rings a bell I can speak to him over my mob, comp or even tv remote control.
I’m experimenting with asteriks. I can call mob phones connected to my network but I can’t call intercom when I’m on my local network. Don’t know why.

did you setup your extension to your hikvision in asterisk to auto-answer? I have a Dahua intercom for my front door and use freePBX. If I use an app, such as grandstream, I can call the intercom directly from my app and it will auto-answer with 2-way audio and phone receiving video. If I use the companion app (android) and the SIP cared I linked to, I can call the intercom directly, but no video (apparently it’s a known limitation to the android companion app right now), so I would double-check that your asterisk extension for your intercom is actually set to intercom with auto-answer.

I would like to learn more about your automation. I just recently received an alexa echo dot gen 3 and set it up using the AWS and custom skill method. I have set up an automation so that Alexa will say “Ding Dong” if the doorbell rings, but would love to know how you cast the video to your TV. I can cast to my TV using google cast options, but haven’t played with it much.

I don’t know much about asteriks. To set it up I followed this guide

Asteriks guide

I managed to call my home assistant from my mobile and make calls from mobile to mobile while they are connected on my local wifi network. But I never was able to call my intercom from my mobile or mobile from intercom.
This is my pjsip_custom.conf basically copy/paste from tutorial

; Place your own extensions here.
[8000]
type = endpoint
context = default
direct_media_method=invite
dtmf_mode=info
callerid="Doorbell" <8000>
force_rport=no
aors= 8000
auth = auth8000

[8000]
type = aor
max_contacts = 1

[auth8000]
type=auth
auth_type=userpass
password=8000         ; Set your password here
username=8000

This is what I have on my hikvision settings

I don’t know where the problem is but I can’t make a call.

As for television automation goes first of all you have to figure out how to turn on your tv on from home assistant. I have xiaomi smart tv with build on chromecast. Tv has option to turn it on using either wake on lan or wake on wifi. First I tried wake on wifi. It worked but was very unstable as tv turned on randomly.
I bought two powerline adapters to try wake on lan. I connected one adapter to tv and other to my local router. It worked but I found out that my tv wont wake up once its turn off. So I got an idea. I use binary_sensor.yaml to ping my network devices for avability.
I added to binary_sensor.yaml

# android tv
- platform: ping
  host: 192.168.31.5
  name: Android TV
  count: 1
  scan_interval: 15

And that done the trick. When I turn my tv off red led is blinking on it. Opposite to when you turn it off with remote your red led is dimmed or its completely off. For tv I use android tv integration. if you can turn tv on/off from home assistant than automation is very easy.
As for alexa goes I use home assistant cloud and announcement on alexa is also very easy thing to do. I can post my automation yaml code but its pointless without fully function tv.

Edit:
This is the error I get when I try to call my intercom

Called PJSIP/8000/sip:[email protected]:5060
[Sep 27 16:56:18]   == Everyone is busy/congested at this time (1:0/0/1)

and service is unavailable.

Edit:
One key thing I forgot to write on android tv. I installed android remote app from apps store on my tv. Without it the whole thing will not work as described.