Skip to content

Commit

Permalink
update docs and release a stable build
Browse files Browse the repository at this point in the history
  • Loading branch information
pergolafabio committed Aug 30, 2023
1 parent d9b3b4f commit 2ceea8b
Show file tree
Hide file tree
Showing 90 changed files with 1,694 additions and 1,668 deletions.
13 changes: 10 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,20 @@
This repository can be added to an Home Assistant OS installation.
It provides the following add-ons:

## [Hikvision Doorbell](hikvision-sdk/README.md)
## [Hikvision Doorbell](doorbell/README.md)

Connect to you Hikvision IP doorbells to receive events (motion detection, incoming call, etc..) and relay back commands (reject call, open doors, etc...).

To quickly get started, click the following button:
[![Open your Home Assistant instance and show the dashboard of a Supervisor add-on.](https://my.home-assistant.io/badges/supervisor_addon.svg)](https://my.home-assistant.io/redirect/supervisor_addon/?addon=aff2db71_hikvision_sdk&repository_url=https%3A%2F%2Fgithub.com%2Fpergolafabio%2FHikvision-Addons)


## [Running as a standalone container](docs/docker.md)

This program can run as a standalone Docker container, for all other type of installations. (Openhab, Home Assistant, ...)
[Consult the docs for more info](docs/docker.md)


## [Hikvision Doorbell (Beta)](doorbell_beta/README.md)

Pre-release version, containing new features and additions that are being actively developed and tested, to be released in the next stable version.
Expand All @@ -37,11 +44,11 @@ __NOTE__: This version is not recommended for general use, but may be of interes
To quickly get started, click the following button:
[![Open your Home Assistant instance and show the dashboard of a Supervisor add-on.](https://my.home-assistant.io/badges/supervisor_addon.svg)](https://my.home-assistant.io/redirect/supervisor_addon/?addon=aff2db71_hikvision_doorbell_beta&repository_url=https%3A%2F%2Fgithub.com%2Fpergolafabio%2FHikvision-Addons)

## [Use Asterisk as Indoor extension](https://github.com/pergolafabio/Hikvision-Addons/blob/dev/asterisk/asterisk.as.indoor.md)
## [Use Asterisk as Indoor extension](asterisk/asterisk.as.indoor.md)

__NOTE__: This is not an add-on, just an alternate way to setup Asterisk without setting up SIP on the devices!

## [Use Frigate with Two Audio Support and a Lovelace Hass Card](https://github.com/pergolafabio/Hikvision-Addons/blob/dev/frigate/twowayaudio.with.frigate.md)
## [Use Frigate with Two Audio Support and a Lovelace Hass Card](frigate/twowayaudio.with.frigate.md)

__NOTE__: This is not an add-on, just an alternate way to answers calls using Home Assistant with Two Way Audio ISAPI support!

Expand Down
335 changes: 335 additions & 0 deletions asterisk/asterisk.as.indoor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,335 @@
# Setup Asterisk as inbound trunk like an Hikvision indoor extension


## Background info:

Hikvision intercom devices have the ability to register on a PBX, but the disadvantages of using the SIP setting on the device:

- When PBX is down => you miss the call :-)
- When connected to a PBX , Hikconnect cloud doesnt work anymore
- No video before pickup anymore on the indoor panels, so you dont see who is calling, quite annoying!!

There is another way!!!

In asterisk you can define an TRUNK, to register on the primary indoor station, Asterisk will act then as an indoor extension just like a real indoor device... so the call comes in, your first indoor stations starts ringing, and will forward the call to Asterisk.
For some reason the video is not forwarded... no idea why ... that's why I created this workaround to have video in the call on the softphones...

Advantages:

- Hikconnect cloud, still works!
- Still video on your indoor panels! Most important one
- If Asterisk is down, the intercom + indoor station still works as we register it as an extension
- You dont need access to the outdoor station, usefull for people living in appartment with no access to outdoor station.
- You dont need to use the Hikconnect app anymore, you can use your own softphone of choice
- All local!
- Verry nice intergations possible, you can even pickup/answer the call with a Lovelace SIP card!! Freaking nice! :-) https://github.com/TECH7Fox/sip-hass-card
- Opening door also works by sending '#' during call with a softphone (enable "dtmf sip-info" on your softphone client), or use feature codes, see more below

## Get started:

Setup an asterisk PBX, i use the one from Techfox, it already includes the RTSP App, that we need in this approach. https://github.com/TECH7Fox/asterisk-hass-addons
If you want to compile your onw Asterisk, make sure to include this app: https://github.com/tommyjlong/app_rtsp_sip

## Asterisk configuration

As I told before, you can use Asterisk to register as a trunk on your primary indoor panel...

#### Option 1 based on newer indoor panels (ONLY works with 9310-9510 rev B)
On same indoor panels you can already the extension with a SN.. for serial use: Q12345678, for No: 5, enter a password, the the IP is your Asterisk instance running the addon...
In below example, 192.168.0.71 is my primary indoor panel, 10000000005 is actually the number 5 you entered in IVMS, 192.168.0.17 is HA running Asterisk
Some indoor panels dont have the option to add extensions, then try without it, just use the trunk setup below... if you receive an 404 or 401 error when debugging sip, proceed to option 2, and skip this trunk setup... I always use the tool "sngrep", you can install it in the SSH addon with the command "apk add sngrep"


![Ivms](ivms.png)

Below is the trunk you need to define in Asterisk, make sure the password matches, now restart Asterisk, and see if if the Asterisk can succesfull register

```
#### Setup this in pjsip_custom.conf:
[mytrunk-auth]
type=auth
auth_type=userpass
password=XXXX
username=10000000005
[mytrunk-aor]
type=aor
contact=sip:192.168.0.71:5065
[mytrunk-registration]
type=registration
outbound_auth=mytrunk-auth
server_uri=sip:192.168.0.71:5065
client_uri=sip:10000000005@192.168.0.71:5065
retry_interval=10
contact_user=10000000005
expiration=600
[mytrunk]
type=endpoint
context=default
disallow=all
allow=ulaw,alaw
allow=h264,vp8
outbound_auth=mytrunk-auth
aors=mytrunk-aor
rewrite_contact=yes
from_domain=mydomain.com
[mytrunk]
type=identify
endpoint=mytrunk
match=192.168.0.71
```
#### Option 2 based on older indoor panels

On some indoor panels you are not able to add the SN with ivms, when registering the trunk you get an 404/401 error... the SN is mandatory, and Asterisk is not able to send the XML.. Use below script instead...it will send the regXML part, it runs on port 5061, but the invite on indoor panel is always hardcoded, so it goes back to port 5060, where yo u have asterisk running.
The script needs to be running the whole time, so start it with an automation upon boot HA, and use this shell_command below.. its doing an reregister every 900 sec.


[hikvision_register.py](hikvision_register.py)

Try it fist from a putty console, to see it it works, afterwards you can use below shellcommand with an automation.


```
## Test first this command:
python3 /config/hikvision_register.py --ip 192.168.0.17 --domain 192.168.0.71 --username 10000000005 --extension 10000000005 --name Asterisk --password XXX
```
Use this below in HA
```
# Shell command:
hikvision_sip: nohup python3 /config/hikvision_register.py --ip 192.168.0.17 --domain 192.168.0.71 --username 10000000005 --extension 10000000005 --name Asterisk --password XXX $1 > /dev/null 2>&1 &
# Automation:
- alias: Register hikvision
initial_state: 'on'
trigger:
- platform: homeassistant
event: start
action:
- service: shell_command.hikvision_sip
```

Example regXML that is needed in the register packet, its part of the script in the register header...

```
<regXML>
<version>V2.0.0</version>
<regDevName>Asterisk</regDevName>
<regDevSerial>Q12345678</regDevSerial>
<regDevMacAddr>00:0c:29:12:12:12</regDevMacAddr>
</regXML>
```

Use the trunk below, based on IP auth, this one is different, there is no need for user/pass authentication now, since the script is doing the auth

```
#### Setup this in pjsip_custom.conf:
[hikvision]
type=aor
contact=sip:10000000005@192.168.0.71:5060
[hikvision]
type=endpoint
context=default
disallow=all
allow=ulaw,alaw
allow=h264,vp8
aors=hikvision
direct_media=no
[hikvision]
type=identify
endpoint=hikvision
match=192.168.0.71
```

## Simple Dialplan for Asterisk

#### Example 1:
Using Linphone as a free service, the call comes in on '10000000005' and is forwarded to USER1@sip.linphone.com, the 'outgoing' is needed to specify the endpoint and codecs.

```
#### Setup this in pjsip_custom.conf:
[outgoing]
type=endpoint
disallow=all
allow=ulaw,alaw
allow=h264
from_domain=YOURDOMAIN.com
```

```
#### Setup this in extensions.conf in the [default] section
exten => 10000000005,1,NoOp()
same => n,Progress()
same => n,Set(CALLERID(num)=Doorbell)
same => n,Set(CALLERID(name)=Doorbell)
same => n,Set(DIALGROUP(mygroup,add)=PJSIP/outgoing/sip:USER1@sip.linphone.org)
same => n,Set(DIALGROUP(mygroup,add)=PJSIP/outgoing/sip:USER2@sip.linphone.org)
same => n,Dial(${DIALGROUP(mygroup)},40)
same => n,Hangup()
```

#### Example 2:
The problem was "no video", so i created a workaround using the "RTSP-APP". I now use the AMI (agi.php script) from Asterisk to make an originate from "RTSP-APP" to Linphone... In this example 2, the call comes in, then i send a command to AMI using php, to make the "RTSP-APP" call me... this provides early-video (as RTSP Stream) to Linphone... When i answer a Confbridge will be started, '10000000005' checks when the bridge is started and will join the bridge too.
The clue is here to use the AMI script, this is the only way an originate can work with early media, there is also an Originate app in Asterisk itself, but is has no option to turn on early media!!

```
#### Setup this in extensions.conf in the [default] section, make sure to change the rtsp url below, and also the USER1@sip.linphone.com.
You see i make use of local channels 9000 and 9001 , this is to make it possible to todo a hangup (finishcall) on all incoming/outcgoing calls. So whoever leaves
the bridge, all parties will be hungup. In channel 9001 i also make use of a while loop to retry for 60 sec... When USER1@sip.linphone.com is unreachable for whatever reason, the trunk call gets an hangup, but also the Hikvision indoor panels stop ringing, thats something we dont want to happen, otherwise they dont ring at all!
exten => 10000000005,1,NoOp()
same => n,Progress()
same => n,Set(CHANNEL(hangup_handler_push)=default,finishcall,1(args))
same => n,Set(GLOBAL(CHANNEL-IN)=${CHANNEL})
same => n,System(/usr/bin/php "/config/asterisk/agi.php")
same => n,Set(i=1)
same => n,While($[${i} < 60])
same => n,NoOp(Confbridge number of participants : ${CONFBRIDGE_INFO(parties,1)})
same => n,GotoIf($["${CONFBRIDGE_INFO(parties,1)}" >= "1"]?startconf)
same => n,Wait(1)
same => n,Set(i=$[${i} + 1]
same => n,EndWhile()
same => n(startconf),ConfBridge(1,myconferenceroom,default_user)
same => n,Hangup()
exten = rtsp,1,Answer()
same => n,RTSP-SIP(rtsp://admin:XXX@192.168.0.70:554/Streaming/Channels/102,0,asterisk,5060)
same => n,Hangup()
exten => 9000,1,NoOp()
same => n,Progress()
same => n,Set(CHANNEL(hangup_handler_push)=default,finishcall,1(args))
same => n,Set(GLOBAL(CHANNEL-9000)=${CHANNEL})
same => n,Dial(Local/9001@default,,G(join_caller))
same => n(join_caller),ConfBridge(1,myconferenceroom,marked_user)
same => n,ConfBridge(1,myconferenceroom,admin_user)
same => n,Hangup()
exten => 9001,1,NoOp()
same => n,Progress()
same => n,Set(CHANNEL(hangup_handler_push)=default,finishcall,1(args))
same => n,Set(GLOBAL(CHANNEL-9001)=${CHANNEL})
same => n,Set(__DYNAMIC_FEATURES=door)
same => n,Set(CALLERID(num)=Doorbell)
same => n,Set(CALLERID(name)=Doorbell)
same => n,Set(COUNT=1)
same => n,While($[ ${COUNT} < 60 ])
same => n,Dial(PJSIP/outgoing/sip:USER1@sip.linphone.org)
same => n,Set(HANGUPCAUSEKEYS=${HANGUPCAUSE_KEYS()})
same => n,Set(HANGUP_CAUSE=${HANGUPCAUSE})
same => n,Verbose(2, HANGUP_CAUSE=${HANGUPCAUSE})
same => n,GotoIf($["${HANGUP_CAUSE}" == "21"]?exitdialplan)
same => n,Wait(3)
same => n,SET(COUNT=$[${COUNT} + 1])
same => n,EndWhile()
same => n(exitdialplan),NoOp(Exiting dialplan: HANGUP_CAUSE=${HANGUPCAUSE})
same => n,Hangup()
exten => finishcall,1,NoOp()
same => n,System(/usr/sbin/asterisk -rx "confbridge kick 1 all")
same => n,System(/usr/sbin/asterisk -rx "hangup request ${CHANNEL-IN}")
same => n,System(/usr/sbin/asterisk -rx "hangup request ${CHANNEL-9000}")
same => n,System(/usr/sbin/asterisk -rx "hangup request ${CHANNEL-9001}")
same => n,Return()
```

```
#### Create an agi.php in your config folder, this script is launched in the '10000000005' dialplan, make sure to change the username/secret,
this is the AMI password thats being setup during the Asterisk Addon. The AMI script is doing the originate from extension 'rtsp' to a
local channel '9000', and it can be defined as early media
<?php
$socket = fsockopen("127.0.0.1","5038", $errno, $errstr);
fputs($socket, "Action: Login\r\n");
fputs($socket, "UserName: admin\r\n");
fputs($socket, "Secret: XXXX\r\n\r\n");
$wrets=fgets($socket,128);
echo $wrets;
fputs($socket, "Action: Originate\r\n" );
fputs($socket, "Channel: Local/9000@default\r\n" );
fputs($socket, "Exten: rtsp\r\n" );
fputs($socket, "Context: default\r\n" );
fputs($socket, "Priority: 1\r\n" );
fputs($socket, "Async: yes\r\n" );
fputs($socket, "EarlyMedia: true\r\n" );
fputs($socket, "Codecs: ulaw,h264\r\n\r\n");
$wrets=fgets($socket,128);
?>
```

```
#### Setup this in pjsip_custom.conf:
[outgoing]
type=endpoint
disallow=all
allow=ulaw,alaw
allow=h264
from_domain=YOURDOMAIN.com
```
```
#### Setup this in confbridge.conf, the "RTSP-APP" is joining the confbridge as marked user, with video_mode=first_marked, but also as muted, to
prevent echo, cause there is also sound coming from RTSP stream.
[admin_user]
type=user
marked=no
wait_marked=no
end_marked=yes
admin=yes
music_on_hold_when_empty=no
quiet=yes
dtmf_passthrough=yes
[default_user]
type=user
marked=no
wait_marked=yes
end_marked=yes
admin=no
music_on_hold_when_empty=no
quiet=yes
dtmf_passthrough=yes
[marked_user]
type=user
marked=yes
wait_marked=no
end_marked=yes
admin=no
music_on_hold_when_empty=no
quiet=yes
dtmf_passthrough=yes
startmuted=yes
[myconferenceroom]
type=bridge
max_members=10
video_mode=first_marked
```
```
#### Setup this in features.conf, Here you can define dtmf buttons, like turning on a light using CURL command, or open a door. You see i use this
feature code in local channel 9001, where i actually call the Linphone user. So when pressing 9 during the call, i can open the door.
[applicationmap]
door => 9,self,Set,CURL_RESULT=${SHELL(curl -i --digest -u admin:XXX -X PUT -d '<RemoteControlDoor><cmd>open</cmd></RemoteControlDoor>' http://192.168.0.70/ISAPI/AccessControl/RemoteControl/door/1)}
```

NOTE: If you have multiple outdoor stations, registered to same indoor, you can use this dialplan, to capture the door who is calling and change the RTSP with an attribiute, thnx for sharing!
https://github.com/pergolafabio/Hikvision-Addons/issues/114#issuecomment-1591179075

## Donations
Like my work? You can always [send me a donation](https://paypal.me/pergolafabio).
Loading

0 comments on commit 2ceea8b

Please sign in to comment.