Preston Holmes
Published © Apache-2.0

Google Hangouts "on-air" light and lock

No more accidentally getting disturbed during your next Hangouts meeting. Auto-lock the door and enable an "on-air" do not disturb light.

IntermediateFull instructions provided2,992
Google Hangouts "on-air" light and lock

Things used in this project

Hardware components

ESP8266 ESP-01
Espressif ESP8266 ESP-01
×1
Automotive Door Lock
×1

Software apps and online services

Google Chrome
Google Hangouts

Story

Read more

Schematics

Prototyping schematic

Code

door-lock.ino

C/C++
This is the Arduino Sketch for the ESP8266 module
#include <ESP8266WiFi.h>



const char* ssid = "****";
const char* password = "****";

int lockpin = 2;
int unlockpin = 0;
int statuspin = 3;
int relay_delay = 600;

// Create an instance of the server
// specify the port to listen on as an argument
WiFiServer server(80);

void setup() {
  PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_GPIO3);
  Serial.begin(115200);
  delay(10);

  // prepare GPIO
  pinMode(lockpin, OUTPUT);
  digitalWrite(lockpin, 0);
  pinMode(unlockpin, OUTPUT);
  
  pinMode(statuspin, OUTPUT);
  digitalWrite(statuspin, 0);
  
  // unlock the door
  digitalWrite(unlockpin, 1);
  delay(relay_delay);
  digitalWrite(unlockpin, 0);
  
  
  
  // Connect to WiFi network
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  
  WiFi.begin(ssid, password);
  
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  
  // Start the server
  server.begin();
  Serial.println("Server started");

  // Print the IP address
  Serial.println(WiFi.localIP());
}

void loop() {
  // Check if a client has connected
  WiFiClient client = server.available();
  if (!client) {
    return;
  }
  
  // Wait until the client sends some data
  Serial.println("new client");
  while(!client.available()){
    delay(1);
  }
  
  // Read the first line of the request
  String req = client.readStringUntil('\r');
  Serial.println(req);
  client.flush();
  
  // Match the request
  int val;
  if (req.indexOf("/lock/0") != -1) {
    digitalWrite(statuspin, 0);
    digitalWrite(unlockpin, 1);
    delay(relay_delay);
    digitalWrite(unlockpin, 0);
  } else if (req.indexOf("/lock/1") != -1) {

    digitalWrite(lockpin, 1);
    delay(relay_delay);
    digitalWrite(lockpin, 0);
    digitalWrite(statuspin, 1);
  } else {
    Serial.println("invalid request");
    client.stop();
    return;
  }

  // Set GPIO2 according to the request
  
  
  client.flush();

  // Prepare the response
  String s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>request processed ";
  s += "</html>\n";

  // Send the response to the client
  client.print(s);
  delay(1);
  Serial.println("Client disonnected");

  // The client will actually be disconnected 
  // when the function returns and 'client' object is detroyed
}

check_hangouts.py

Python
Run on the machine where you will be having Hangouts
#! /Users/ptone/Projects/Python/virtualenvs/appscript/bin/python
# -*- coding: utf-8 -*-


# Copyright 2015 Preston Holmes

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

    # http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


import re
from appscript import app
import time
import os

import requests

# regex to check against tab URLs
active_hangout_re = re.compile("https://plus.google.com/hangouts/_/.*/.*$")


BROWSER='Google Chrome'

# set this to the IP address of the ESP8266
controller_ip = '192.168.1.59'

# global lock state
locked = False

# our appscript based browser object
browser = app(BROWSER)

def get_tabs():
    """
    gets a list of the current tabs in the browser
    """
    tabs = []
    try:
        windows = browser.windows.get()
        for w in windows:
            w_tabs = w.tabs.get()
            for i, t in enumerate(w_tabs):
                t.window = w
                if 'Chrome' in BROWSER:
                    t.index = i + 1
            tabs.extend(w_tabs)
    except Exception as e:
        print "oops: %s" % e

    return tabs


def in_hangout(tabs=None):
    """
    checks an array of tags to see if any of them contain an active hangout
    """
    if tabs is None:
        tabs = get_tabs()
    tabs = get_tabs()
    # for i, t in enumerate(tabs):
        # print i, t.URL.get()
    hangout_tabs = [active_hangout_re.match(t.URL.get()) for t in tabs]
    if any(hangout_tabs):
        return True
    else:
        return False


def lock():
    global locked
    if not locked:
        print "locking"
        requests.get('http://{ip}/lock/1'.format(ip=controller_ip))
        locked = True


def unlock(force=False):
    global locked
    if locked or force:
        print "unlocking"
        requests.get('http://{ip}/lock/0'.format(ip=controller_ip))
        locked = False


def main():
    unlock(force=True)
    ct = 0
    while True:
        if os.path.exists('/tmp/unlock'):
            # an override mechanism to unlock the door during a hangout
            unlock()
        elif (ct % 5):
            # only check the browser every 5 seconds
            if in_hangout():
                lock()
            else:
                unlock()
        # else wait

        if ct > 10000:
            # roll the counter
            ct = 0
        ct += 1
        time.sleep(1)

if __name__ == "__main__":
    main()
    try:
        main()
    except KeyboardInterrupt:
        print 'quiting'
        try:
            unlock(force=True)
            sys.exit(0)
        except SystemExit:
            os._exit(0)

Credits

Preston Holmes

Preston Holmes

1 project • 2 followers
Building IoT and cloud connections

Comments