Using mic on rpi to open my front door

mic
rules
Tags: #<Tag:0x00007f2135764230> #<Tag:0x00007f213576fa40>

(Kim Skatun) #1

Hi all,
I have a front door which opens through an intercom system, this system has a button for opening the door, which I have simply connected to a relay which I then can control with GPIO on RPI through OH. This works perfect and I am happy with the solution.

However it is a bit tidious to get out the phone to open the door, so what I want to do instead is to detect if the internal doorbell in the intercom goes off. So my idea is to take out the cables going to the small speaker and solder on some resistor like shown here and then feed it into the mic line of the rpi. The question is will this work? And how can I detect noise(someone ringing the door bell) in a rule in OH?


(Oliver Stenzel) #2

Uh…but wouldn’t that mean anyone ringing the doorbell can open your door?
Kinda creepy thought…


(Rich Koshak) #3

You can’t as far as I am aware. You would have to implement this outside of OH and report the result to OH using the REST API, MQTT, etc. or have OH call an external program using Exec.


(Kim Skatun) #4

Well @rlkoshak , sorry for not being clear about this, I was thinking about using the inbuilt line in on rpi and then a python (or similar) script which then notify OH when sound is detected(maybe REST API is the easiest?), but I am unsure how to do this. I have never worked with python or sounds thats why I was asking here:)


(Rich Koshak) #5

I can’t help with the sound part but the nice thing about Python is there are libraries for everything.

You can have the Python communicate with OH over the REST API or by passing MQTT messages. You can see my sensorReporter script as an example of how I’ve done it.

The openHAB REST API is documented as a separate addon you can install through PaperUI under the Misc tab. It is an interactive document so you can test out REST calls in the document before coding it to figure out how to structure your HTTP calls.


(Kim Skatun) #6

@rlkoshak and @Oli I got the hardware to work by desoldering a mic from arduino mic board and soldering the speaker cables from my intercom in instead!

Now my second issue I am running out of GPIO on my rpi, which GPIO can i use with GPIO binding in OH? can I use the SPI pins? Or can I only use these pin numbers?

# GPIO numbers should be from this list
# 0, 1, 4, 7, 8, 9, 10, 11, 14, 15, 17, 18, 21, 22, 23, 24, 25

Then it is to my rule, I want some kind of code to secure that a random ring on my door bell does not open it…
So if the ring is between 2.5s and 3.5s then a pause of 1.5s to 2.5s then followed by ring 2.5s to 3.5 s then open the door. However I am unsure how to implement this in a rule:

when doorBellcontact changed from OPEN to CLOSED and secondRing = false{
     startedTime= now()
}

when doorBellcontact changed from CLOSED to OPEN and secondRing = false{
    if now() - startedTime >2.5 and now() - startedTime <3.5{
       secondRing = true
       pausedTime = now()
    }
}

when doorBellcontact changed from OPEN to CLOSED and secondRing = true{
    if now() - pausedTime >1.5 and now() - pausedTime <2.5{
    startedTime =now
    }
}

when doorBellcontact changed from CLOSED to OPEN and secondRing = true{
    if now() - startedTime>2.5 and now() - startedTime<3.5{
    secondRing = false
    div_DoorOpener.sendCommand(ON)
    }
}

I am sure this will work though! Just a rough thought of my idea… I will take some photos tonight to show my setup:)


(Rossko57) #7

Rules are event-triggered, it doesn’t work like that. Recent post


(Rich Koshak) #8

See these two state machine tutorials.


(Kim Skatun) #9

So folks,
I got the hardware hooked up yesterday, (found a free gpio on my RPI, by disconnecting a relay that’s not in use anymore). It all works ok, and might be useful for others as well. I will upload some pictures of the setup here as soon as I get my phone to work again .

In Software I am still not quite there yet, I am experimenting with the debounce interval to get it to detect it correctly, currently I am using 300ms which seems ok, but more test needs to be done to validate this. Can I somehow log just one item (contact item) to make validation easier?

Secondly I found out when you press the doorbell buttons, it automatically rings 3 times, even if you keep pressing button, so in that 3 time ringing period(more testing need to be found to figure out the time it takes, hence log will be useful) you need to release the ringing button and then after a given time you can press it again.

So any idea how the rule can look like to achieve this?

the contact item changes from OPEN to CLOSED 3 times in a row with a fixed interval,
then you ring again after x second from first ring, (this will be the secret code interval)
the contact item changes from OPEN to CLOSED 3 times in a row with a fixed interval,

So basically if the 4th OPEN to CLOSED event happens lets say between 6-7s after the first then DoorOpener.sendCommand(ON)


(Rich Koshak) #10
tail -f /var/log/openhab2/events.log | grep ItemName

What you want is a state machine, hence my links above.


(Kim Skatun) #11

I am not sure if a doorbell has state, but here is my state sketch:

So in my rule I somehow need to keep track of time and changes, I added questions as comments in the code. Also by using state i need two rules and two items instead of just 1 rule and 1 item. Maybe I am missing something here?

val Number MODE_NO_ACTIVITY = 0
val Number MODE_NOICE = 1
val Number MODE_CORRECT_CODE = 2
val Number changes = 0
val time timeFirstChange //how to define a time variable?

rule "Doorbell ringed"
when
    Item DoorBell changed from OPEN to CLOSED
then
    if (changes =0) {
		changes = changes +1
		timeFirstChange = now() // whats the correct syntax?
	    DoorBell_State.postUpdate(MODE_NOICE)
    else if (changes = 3) and (now- timeFirstChange)>5 and (now- timeFirstChange)<6 { //does the time use seconds or ms?
		DoorBell_State.postUpdate(MODE_CORRECT_CODE)
		changes = changes +1
	}
    else if (changes=6) {
		changes = 6
		DoorBell_State.postUpdate(MODE_NO_ACTIVITY)
    }
	else{
		changes = changes +1
	    DoorBell_State.postUpdate(MODE_NOICE)
	}
end

rule "Doorbell state changed"
when
    Item DoorBell_State changed to MODE_CORRECT_CODE //is this correct syntax?
then
	DoorOpener.sendCommand(ON)
end

Tutorial - Use a 5V Relay to Disable You Doorbell
(Rich Koshak) #12

The states are each step through your code. The state transitions are the doorbell presses and time periods.

val DateTime timeFirstChange
timeFirstChange = now

The answer is neither and both. You probably want to get the seconds (i.e. now.millis - timeFirstChange.millis > 5). I don’t have access to Designer right now so am not certain the method to get milliseconds is millis. Type in the following into designer and it will tell you all the methods you can call).

now.<ctrl><space>

Hold ctrl and space at the same time.

A dialog will pop up with a list of all the methods on now.

All that being said, there is an easier way:

else if ( changes == 3 && now.minusSeconds(5).isAfter(timeFirstChange) && now.minusSeconds(6).isBefore(timeFirstChange))

No. You cannot use a var or val in a Rule trigger.


(Kim Skatun) #13

So I got rid of the whole state thing and just made a rule:

val Number changes = 0
val DateTime timeFirstChange

rule "Doorbell ringed"
when
    Item DoorBell changed from OPEN to CLOSED
then
    if (changes =0) {
		changes = changes +1
		timeFirstChange = now
    else if ( changes == 3 && now.minusSeconds(5).isAfter(timeFirstChange) && now.minusSeconds(6).isBefore(timeFirstChange))
		DoorOpener.sendCommand(ON)
		changes = changes +1
	}
    else if (changes=6) {
		changes = 0
    }
	else if (now.minusSeconds(10).isAfter(timeFirstChange)){
		changes = 0
	}
	else{
		changes = changes +1
	}
end

I will test it out on Saturday when I get my flat back.[quote=“rlkoshak, post:12, topic:28790”]
Item DoorBell_State changed to MODE_CORRECT_CODE
[/quote]

I might move back to state if more things should happen when correct code happens;

Item DoorBell_State changed to 2 //Number DoorBell_State


(Kim Skatun) #14

So here is my evaluation of the system:

1: Solder wires to both sides of the open button on your door phone.
2: If your phone requires that the phone earpiece to be lifted off you can either tape a magnet to it to emulate this or solder wire over the magnetic switch inside the phone
3: Solder wires to earpiece connector, locate which two wires that goes to the speaker(ring the door bell, and you should read mV signals)
4: Connect the two wires going to the door open button to a relay that can be controlled by openhab/alexa and so on
5: Solder the speaker wire to a mic board with gain adjuster Mic board , this was my problem in the beginning, it picked up all background noice(whenever a relay triggered) so set the gain as low as you can.
6: Now you can actually get push notifications, have secret code on your door bell to open your door etc…
7: Happy hacking and thank @rlkoshak for helping out with the code

I still get uneven number of changes on doorbell ring, due to the debounce interval set on the GPIO, so my secret code is just to push the button rapidly untill it opens:

val Number changes = 0
val DateTime timeFirstChange

rule "Doorbell ringed"
when
    Item DoorBell changed from OPEN to CLOSED
then
    if (changes =0) {
		changes = changes +1
		timeFirstChange = now
    else if ( changes == 5 && now.minusSeconds(3).isAfter(timeFirstChange) && now.minusSeconds(8).isBefore(timeFirstChange))
		DoorOpener.sendCommand(ON)
		changes = 0
	}
	else if (now.minusSeconds(10).isAfter(timeFirstChange)){
		changes = 0
	}
	else{
		changes = changes +1
	}
end

What would be cool is to hook it up to a phone and make it call you when someone rings your door and you are not home…