Page 1 of 1

Barking Sonos doorbell using GPIO & 8v AC doorbell

Posted: Sunday 07 June 2015 23:13
by Tommertom
Hi

As one of my first domoticz project I today completed my Sonos barking doorbell. And I am so happy with it, my kids now call me "Doorbell" for the rest of my life.

I used http://www.dannyvanmaanen.nl/?p=1546 info to create a parallel connection to my existing doorbell, running ac 8v by creating a "equalizing bridge" (proper word for 4 diodes?) and elco which drives a relay.

Image

This relay switches the GPIO (pin 17) using a pull up/down schema as presented on https://www.cl.cam.ac.uk/projects/raspb ... _switches/

Image
(has two button detection points, for future use. ps.how can I resize images on this BB?)

Domoticz fires a small php script which kicks the sonos as well as a telegram message. On Action: script:///home/pi/domoticz/scripts/doorbell.php

The sonos.class.php is taken from https://github.com/DjMomo/sonos/blob/ma ... .class.php. I included a small function to find the IP of the Sonos using the name. Maybe not most efficient for the Pi CPU, but easier for me now.

The script tests for repeated doorbell pressing by the person in front or because of the relay clicking too often. The script runs a few seconds. Maybe too long, but for now it works for me.

The barking sound is taken from youtube (keepvid and then use formatfactory to transcode to mp3).

Simple stuff, but so happy my first project is now completed!

doorbell.php

Code: Select all

#!/usr/bin/php
<?php

require_once '/var/www/homealarm/sonos.class.php';
function find_ip_sonos($room_name)
{
        $temp_stuff = new SonosPHPController('192.168.178.33');
        $devices = $temp_stuff->detect();

        foreach ($devices as $device) {

        if (strtoupper($device->device_info()['roomName']) == strtoupper($room_name)) {
                $raw_ip=explode("-",$device->device_info()['friendlyName']);
                        return str_replace(" ","", $raw_ip[0]);
                }
        }
}

// get the time and compare with last doorbelpresstime
$now=time();
if (file_exists("/tmp/doorbell.time") ) {
        // read the session date if that exists
        $lastchangedate=intval(file_get_contents("/tmp/doorbell.time"));
}
else
	$lastchangedate = 0;
	
// only fire up when there was a press 10 minutes ago
if (($now-$lastchangedate)>10*60) {
        // Write the last press time
		file_put_contents("/tmp/doorbell.time", $now, LOCK_EX);
		
		
		//Fire up the Sonos
		$sonos_1 = new SonosPHPController(find_ip_sonos("keuken"));
		$sonos_1->SetMute(0);
		$sonos_1->RemoveAllTracksFromQueue();
		$sonos_1->SetVolume(50);
		$sonos_1->SetQueue('http://192.168.178.33/homealarm/dog.mp3');
		$sonos_1->Play();	
		
		$last_line = system('/home/pi/tg/bin/telegram-cli -U pi -k /home/pi/tg/tg-server.pub -W -e "msg My_Name Deurbel gaat!"', $retval);
}		
else
{
        // otherwise: do nothing (maybe later some implementation)
};


?>
Need to build a resume-playback-after-barking for the Sonos. For later concern.

Regards

Tom

Re: Barking Sonos doorbell using GPIO & 8v AC doorbell

Posted: Monday 08 June 2015 9:22
by ThinkPad
Nice! Although your soldering is a bit sloppy hehe.... but if it works :) .....

And please resize images before uploading. Good size is around 500pixels width. You can resize it with Paint or something.

Re: Barking Sonos doorbell using GPIO & 8v AC doorbell

Posted: Monday 08 June 2015 9:37
by Tommertom
ThinkPad wrote:Nice! Although your soldering is a bit sloppy hehe.... but if it works :) .....

And please resize images before uploading. Good size is around 500pixels width. You can resize it with Paint or something.
Very true!!
Tom

Re: Barking Sonos doorbell using GPIO & 8v AC doorbell

Posted: Tuesday 09 June 2015 20:39
by Tommertom
Hi

just a quick update. I changed the PHP script. It now supports using multiple Sonos zones (and lets them play at the same time) and also resumes playback of the original queue/radio station once the doorbell has finished.

It has some lines to use to obtain the IP adresses. Of course, there are other ways to find the IP adresses of the Sonos.

Rgdz

Tom

(don't forget to set permissions to 777)

Code: Select all

#!/usr/bin/php
<?php

// script:///home/pi/domoticz/scripts/doorbell.php

require_once '/var/www/homealarm/sonos.class.php';
function find_ip_sonos($room_name)
{
        $temp_stuff = new SonosPHPController('192.168.178.33');
        $devices = $temp_stuff->detect();

        foreach ($devices as $device) {

        if (strtoupper($device->device_info()['roomName']) == strtoupper($room_name)) {
                $raw_ip=explode("-",$device->device_info()['friendlyName']);
                        return str_replace(" ","", $raw_ip[0]);
                }
        }
}

function do_notification() {
// put here code for other notification steps like a telegram message or pushover
}

// settings for the doorbell
$volume = 35;
$unmute= 0;
$file = 'http://192.168.178.33/homealarm/doorbell.mp3';

// nice doorbell: https://www.youtube.com/watch?v=TX7jlxtu7Rk
$potential_devices=array("192.168.178.20","192.168.178.12","192.168.178.30","192.168.178.29","192.168.178.15");
$devices=array();

// get the time and compare with last doorbelpresstime
$now=time();
if (file_exists("/tmp/doorbell.time") ) {
        // read the session date if that exists
        $lastchangedate=intval(file_get_contents("/tmp/doorbell.time"));
}
else
	$lastchangedate = 0;
	
// only fire up when there was a press 10 minutes ago
if (($now-$lastchangedate)>10*60) {
        // Write the last press time
		file_put_contents("/tmp/doorbell.time", $now, LOCK_EX);

		// we need to check if the devices are up and running, and build the array of devices to use
		$temp_stuff = new SonosPHPController('192.168.178.33');
        $present_devices = $temp_stuff->detect();
        foreach ($present_devices as $present_device) {
					$raw_ip=explode("-",$present_device->device_info()['friendlyName']);
					$clean_ip=str_replace(" ","", $raw_ip[0]);
					
					// is the device in the potential devices to use for the doorbell?
					if (in_array($clean_ip, $potential_devices)) array_push( $devices, $clean_ip);
	    }
	
		// create the instances and read the current status, initiate for final play
		foreach ($devices as $a_device) {
			
			// instantiate (devices must be on at all time
			$sonos_1[$a_device] = new SonosPHPController($a_device);
			
			// retrieve settings
			$actual[$a_device]['track'] = $sonos_1[$a_device]->GetPositionInfo(); // this gives a notice if the radio is actually playing
			$actual[$a_device]['volume'] = $sonos_1[$a_device]->GetVolume();
			$actual[$a_device]['mute'] = $sonos_1[$a_device]->GetMute();
			$actual[$a_device]['status'] = $sonos_1[$a_device]->GetTransportInfo();
			$sonos_1[$a_device]->Pause();

			// mute settings
			if ($unmute == 1)
				$sonos_1[$a_device]->SetMute(0);
			if ($volume != 0)
				$sonos_1[$a_device]->SetVolume($volume);
				
			// check the type of sound playing
			if (((stripos($actual[$a_device]['track']["TrackURI"],"x-file-cifs://")) != false) or ((stripos($actual[$a_device]['track']["TrackURI"],".mp3")) != false))
			{
				$actual[$a_device]['is_mp3']=true;
				$TrackNumber[$a_device] = $sonos_1[$a_device]->AddURIToQueue($file);
				$sonos_1[$a_device]->ChangeTrack($TrackNumber[$a_device]);
			}
			else 
			{
				$actual[$a_device]['is_mp3']=false;
				$sonos_1[$a_device]->SetQueue($file);
			}
		}
		
		// lets play at the same time
		foreach ($devices as $a_device) {
			$sonos_1[$a_device]->Play();
		}
		sleep(2);

		// do the other notification steps
		do_notification();

		// wait until all devices have finished
		foreach ($devices as $a_device) 
			while ($sonos_1[$a_device]->GetTransportInfo() == "PLAYING") {}
		
		// and revert to old playlist
		foreach ($devices as $a_device) {
		
			if ($actual[$a_device]['is_mp3'])
			{
				$sonos_1[$a_device]->Pause();
				$sonos_1[$a_device]->SetVolume($actual[$a_device]['volume']);
				$sonos_1[$a_device]->SetMute($actual[$a_device]['mute']);
				$sonos_1[$a_device]->ChangeTrack($actual[$a_device]['track']["TrackNumberInQueue"]);
				$sonos_1[$a_device]->SeekTime($actual[$a_device]['track']["RelTime"]);
				$sonos_1[$a_device]->RemoveTrackFromQueue($TrackNumber[$a_device]);
			}
			else
			{
				$sonos_1[$a_device]->Pause();
				$sonos_1[$a_device]->SetVolume($actual[$a_device]['volume']);
				$sonos_1[$a_device]->SetMute($actual[$a_device]['mute']);
				$sonos_1[$a_device]->SetQueue($actual[$a_device]['track']["TrackURI"]);
			}
		}
		
		// final step to continue playing
		foreach ($devices as $a_device) 
			if (strcmp($actual[$a_device]['status'],"PLAYING") == 0)
				$sonos_1[$a_device]->Play();
}		
		
else
{
        // otherwise: do nothing
};


?>

Re: Barking Sonos doorbell using GPIO & 8v AC doorbell

Posted: Friday 20 May 2016 0:56
by wisheh
Nice script, i have a working Sonos doorbell now. Thank you :) Only a little problem if internet radio is playing. Then the doorbell sound is not being played but the actual radio station with the volume of the doorbell setting. Know any fix for this?

Re: Barking Sonos doorbell using GPIO & 8v AC doorbell

Posted: Friday 20 May 2016 14:23
by TheBod
Great idea. How authentic is the barking mp3?

Re: Barking Sonos doorbell using GPIO & 8v AC doorbell

Posted: Sunday 04 December 2016 14:25
by josimd
Works great! thanks!

Re: Barking Sonos doorbell using GPIO & 8v AC doorbell

Posted: Monday 05 December 2016 1:14
by andreo
Nice doorbell. The proper word for a equalizing bridge build on 4 diodes = Greatz rectifier.

Re: Barking Sonos doorbell using GPIO & 8v AC doorbell

Posted: Tuesday 09 May 2017 21:44
by marmachine
Tommertom wrote:...creating a "equalizing bridge" (proper word for 4 diodes?) and elco which drives a relay....
That'll be: 2A 1000V 2W10 4Pin Single Phases Bridge Diode Rectifier
Nice work though!