Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .env_sample
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,10 @@ SLEEP_DATA_PATH=/path/to/sleep/data
DEBUG=False
OWL=False
VIDEO_PATH=/path/to/video
HATCH_IP=192.168.HATCH.IP
HATCH_IP=192.168.HATCH.IP
MQTT=True
MQTT_Broker_IP=IP_OF_MQTT_BROKER
MQTT_Broker_Port=1883
MQTT_Client_ID=babysleepcoach
MQTT_Broker_Username=
MQTT_Broker_Password=
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,13 @@ And you'll probably get a warning about the app trying to boot on port `80`. You
You'll need to update some paths and IPs in the code.
<br/><br/>
## Someone send me proof you got it all running.

<br/><br/>
### Home automation / MQTT
Baby Sleep Coach can also be integrated into home automations like OpenHAB, Home Assistant or ioBroker. For this purpose, there is an MQTT topic

`homeassistant/binary_sensor/baby_sleep_coach/is_awake/state`

which can be used to query the awake status of the baby. This can then be used, for example, to turn off the doorbell when the baby is asleep.

MQTT auto discovery from OpenHAB and Home Assistant is also supported.
53 changes: 53 additions & 0 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,18 @@
# from cast_service import CastSoundService
from http.server import HTTPServer, SimpleHTTPRequestHandler
from helpers import check_eyes_open, set_hatch, check_mouth_open, maintain_aspect_ratio_resize, gamma_correction
from paho.mqtt import client as mqtt_client
import json

load_dotenv()


broker = str(os.getenv("MQTT_Broker_IP"))
port = int(os.getenv("MQTT_Broker_Port"))
client_id = str(os.getenv("MQTT_Client_ID"))
username = str(os.getenv("MQTT_Broker_Username", default=""))
password = str(os.getenv("MQTT_Broker_Password", default=""))

# Uncomment if want phone notifications during daytime wakings.
# Configuration of telegram API key in this dir also needed.
# import telegram_send
Expand Down Expand Up @@ -64,6 +73,7 @@ def __init__(self):

self.multi_face_landmarks = []
self.is_awake = False
self.is_awake_before = not self.is_awake
self.ser = None # serial connection to arduino for controlling demon owl

# If demon owl mode, setup connection to arduino and cast service for playing audio
Expand Down Expand Up @@ -519,6 +529,9 @@ def live(self, consumer_q):
except Exception as e:
print("Something went wrong: ", e)

if os.getenv("MQTT", 'False').lower() in ('true', '1'):
publish(client, self.is_awake, self.is_awake_before)
self.is_awake_before = self.is_awake

####################################
# TODO: move out of this file, break it up
Expand Down Expand Up @@ -561,6 +574,46 @@ def receive(producer_q):
producer_q.append(img)


def connect_mqtt():
def on_connect(client, userdata, flags, rc):
if rc == 0:
print("Connected to MQTT Broker!")
else:
print("Failed to connect, return code %d\n", rc)

client = mqtt_client.Client(client_id)
if username != "" and password != "":
client.username_pw_set(username, password)
client.on_connect = on_connect
client.connect(broker, port)
return client

def publish(client, is_awake, is_awake_before):
if is_awake_before != is_awake:
if is_awake:
msg = "ON"
else:
msg = "OFF"
stateTopic = "homeassistant/binary_sensor/baby_sleep_coach/is_awake/state"
discoveryTopic = "homeassistant/binary_sensor/baby_sleep_coach/is_awake/config"
discoveryPayload = {"unique_id": "baby_sleep_coach_awake", "name":"Baby Sleep Coach: Baby awake", "state_topic": stateTopic, "state_on": "ON", "state_off": "OFF"}

result = client.publish(discoveryTopic, payload=json.dumps(discoveryPayload), retain=True)

result = client.publish(stateTopic, payload=msg, retain=True)
# result: [0, 1]
status = result[0]
if status == 0:
print(f"Send `{msg}` to topic `{stateTopic}`")
else:
print(f"Failed to send message to topic {stateTopic}")



if os.getenv("MQTT", 'False').lower() in ('true', '1'):
client = connect_mqtt()
client.loop_start()

# Had to split frame receive and processing into different threads due to underlying FFMPEG issue. Read more here:
# https://stackoverflow.com/questions/49233433/opencv-read-errorh264-0x8f915e0-error-while-decoding-mb-53-20-bytestream
# Current solution is to insert into deque on the thread receiving images, and process on the other
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ python-dotenv==0.21.1
scikit_learn==1.2.1
statsmodels==0.13.5
tbats==1.1.2
paho-mqtt==1.6.1