├── .gitignore
├── .idea
├── codeStyles
│ ├── Project.xml
│ └── codeStyleConfig.xml
├── encodings.xml
├── gradle.xml
├── misc.xml
├── runConfigurations.xml
└── vcs.xml
├── HomeAssistant
└── config
│ └── www
│ └── doordroid
│ ├── doordroid-card.js
│ └── jssip-3.3.6.min.js
├── Readme.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── be
│ │ └── rosoco
│ │ └── doordroid
│ │ └── ExampleInstrumentedTest.kt
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ ├── be
│ │ │ └── rosoco
│ │ │ │ └── doordroid
│ │ │ │ ├── AbstractPreference.kt
│ │ │ │ ├── MainActivity.kt
│ │ │ │ ├── OnBoardingActivity1.kt
│ │ │ │ ├── OnBoardingActivity2.kt
│ │ │ │ ├── OnBoardingActivity3.kt
│ │ │ │ ├── SplashActivity.kt
│ │ │ │ ├── fotoapparat
│ │ │ │ ├── Camera.kt
│ │ │ │ └── CameraStreamListener.kt
│ │ │ │ ├── httpd
│ │ │ │ ├── CallHttpRequestHandler.kt
│ │ │ │ ├── CameraStillImageHttpRequestHandler.kt
│ │ │ │ ├── CameraStreamImageHttpRequestHandler.kt
│ │ │ │ ├── HelloWorldHttpRequestHandler.kt
│ │ │ │ ├── HttpRequestHandler.kt
│ │ │ │ ├── Httpd.kt
│ │ │ │ └── StatusHttpRequestHandler.kt
│ │ │ │ └── sip
│ │ │ │ └── DoorSip.kt
│ │ └── fi
│ │ │ └── iki
│ │ │ └── elonen
│ │ │ └── NanoHTTPD.java
│ └── res
│ │ ├── drawable-v24
│ │ └── ic_launcher_foreground.xml
│ │ ├── drawable
│ │ └── ic_launcher_background.xml
│ │ ├── layout
│ │ ├── activity_main.xml
│ │ ├── activity_onboarding_1.xml
│ │ ├── activity_onboarding_2.xml
│ │ └── activity_onboarding_3.xml
│ │ ├── menu
│ │ └── main_menu.xml
│ │ ├── mipmap-anydpi-v26
│ │ ├── ic_launcher.xml
│ │ └── ic_launcher_round.xml
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── values
│ │ ├── colors.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ │ └── xml
│ │ ├── settings_homeassistant.xml
│ │ └── settings_sip.xml
│ └── test
│ └── java
│ └── be
│ └── rosoco
│ └── doordroid
│ └── ExampleUnitTest.kt
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/caches
5 | /.idea/libraries
6 | /.idea/modules.xml
7 | /.idea/workspace.xml
8 | /.idea/navEditor.xml
9 | /.idea/assetWizardSettings.xml
10 | .DS_Store
11 | /build
12 | /captures
13 | .externalNativeBuild
14 |
--------------------------------------------------------------------------------
/.idea/codeStyles/Project.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/codeStyles/codeStyleConfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
17 |
18 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/HomeAssistant/config/www/doordroid/doordroid-card.js:
--------------------------------------------------------------------------------
1 | class DoorPiCard extends HTMLElement {
2 | constructor() {
3 | super();
4 | this.attachShadow({ mode: 'open' });
5 | }
6 |
7 | set hass(hass) {
8 | if(this.notYetInitialized()) {
9 | this.initJsSIPIfNecessary(hass);
10 | this.initCameraView(hass);
11 | } else if(this.cameraEntityHasNewAccessToken(hass)) {
12 | this.updateCameraView(hass);
13 | }
14 | this.initDoorbellRinging(hass)
15 | }
16 |
17 | setConfig(config) {
18 | if (!config.camera_entity) {
19 | throw new Error('You need to define a camera entity');
20 | }
21 | if(!config.sip_settings) {
22 | throw new Error('You need to define the SIP settings');
23 | } else {
24 | if(!config.sip_settings.sip_wss_url) throw new Error('You need to define the SIP Secure Webservice url');
25 | if(!config.sip_settings.sip_server) throw new Error('You need to define the SIP Server (ip or hostname)');
26 | if(!config.sip_settings.sip_username) throw new Error('You need to define the SIP username');
27 | if(!config.sip_settings.sip_password) throw new Error('You need to define the SIP password');
28 | }
29 | this.config = config;
30 |
31 | const root = this.shadowRoot;
32 | if (root.lastChild) root.removeChild(root.lastChild);
33 |
34 |
35 | const card = document.createElement('ha-card');
36 | const content = document.createElement('div');
37 | const style = document.createElement('style');
38 | style.textContent = `
39 | ha-card {
40 | /* sample css */
41 | }
42 | .buttons {
43 | overflow: auto;
44 | padding: 16px;
45 | text-align: right;
46 | }
47 | .ring-buttons {
48 | float: left;
49 | background: var(--paper-dialog-background-color, var(--primary-background-color));
50 | color: var(--paper-dialog-color, var(--primary-text-color));
51 | }
52 | #cameraview img{
53 | object-fit: cover;
54 | height: 400px;
55 | }
56 | mwc-button {
57 | margin-right: 16px;
58 | }
59 | `;
60 | content.innerHTML = `
61 |
62 |
Initializing SIP connection and webcam view
63 |
64 |
65 |
76 | `;
77 | card.header = ''
78 | card.appendChild(content);
79 | card.appendChild(style);
80 | root.appendChild(card);
81 | }
82 |
83 | // The height of your card. Home Assistant uses this to automatically
84 | // distribute all cards over the available columns.
85 | getCardSize() {
86 | return 3;
87 | }
88 |
89 | notYetInitialized() {
90 | return window.JsSIP && !this.sipPhone && this.config;
91 | }
92 |
93 | initJsSIPIfNecessary(hass) {
94 | console.log('Loading SIPPhone');
95 |
96 | let socket = new JsSIP.WebSocketInterface(this.config.sip_settings.sip_wss_url);
97 | let configuration = {
98 | sockets : [ socket ],
99 | uri : `sip:${this.config.sip_settings.sip_username}@${this.config.sip_settings.sip_server}`,
100 | password : this.config.sip_settings.sip_password
101 | };
102 | this.sipPhone = new JsSIP.UA(configuration);
103 | this.sipPhone.start()
104 |
105 |
106 | let callOptions = { mediaConstraints: { audio: true, video: false } };// only audio calls
107 |
108 | this.sipPhone.on("registered", () => console.log('SIPPhone registered with SIP Server'));
109 |
110 | let droidCard = this;
111 | this.sipPhone.on("newRTCSession", function(data){
112 | let session = data.session;
113 |
114 |
115 | if (session.direction === "incoming") {
116 | let acceptCallBtn = droidCard.getElementById('btn-accept-call');
117 | let rejectCallBtn = droidCard.getElementById('btn-reject-call');
118 | let endCallBtn = droidCard.getElementById('btn-end-call');
119 |
120 | session.on("accepted", () => {
121 | console.log('call accepted')
122 | acceptCallBtn.style.display = 'none';
123 | rejectCallBtn.style.display = 'none';
124 | endCallBtn.style.display = 'inline-flex';
125 |
126 | });
127 | session.on("confirmed", () => console.log('call confirmed'));
128 | session.on("ended", () => {console.log('call ended'); droidCard.cleanup(hass)});
129 | session.on("failed", () =>{console.log('call failed'); droidCard.cleanup(hass)});
130 | session.on("peerconnection", () => {
131 | session.connection.addEventListener("addstream", (e) => {
132 | console.log('adding audiostream')
133 | // set remote audio stream (to listen to remote audio)
134 | // remoteAudio is