#!/usr/bin/env python
# Automatically lock the screen when bluetooth beacon moves out of range

import time
from beacontools import BeaconScanner, IBeaconFilter, IBeaconAdvertisement
import signal
import dbus
from gi.repository import Gio

global isHere, beaconTimeout
global screenSaverSetActive, screenSaverGetActive, sessionIdleTime

def handler(signum, frame):
    scanner.stop()
    exit(0)

def callback(bt_addr, rssi, packet, additional_info):
    global isHere
    isHere = True

sessionBus = dbus.SessionBus()

screenSaver = sessionBus.get_object("org.gnome.ScreenSaver", "/org/gnome/ScreenSaver")
screenSaverIface = dbus.Interface(screenSaver, 'org.gnome.ScreenSaver')
screenSaverSetActive = screenSaverIface.get_dbus_method("SetActive")
screenSaverGetActive = screenSaverIface.get_dbus_method("GetActive")

mutter = sessionBus.get_object('org.gnome.Mutter.IdleMonitor', '/org/gnome/Mutter/IdleMonitor/Core')
mutterIface = dbus.Interface(mutter, 'org.gnome.Mutter.IdleMonitor')
sessionIdleTime = mutterIface.get_dbus_method("GetIdletime")

# scan for all iBeacon advertisements regardless from which beacon
#scanner = BeaconScanner(callback,
#    packet_filter=IBeaconAdvertisement
#)

signal.signal(signal.SIGINT, handler)

beaconTimeout=0

while True:
    isHere = False
    scanner = BeaconScanner(callback,
        device_filter=IBeaconFilter(uuid="INSERT BEACON UUID HERE")
    )
    scanner.start()
    time.sleep(10)
    scanner.stop()
    idleTime = sessionIdleTime() / 1000

    if isHere:
        #print("Beacon observed")
        beaconTimeout = 0
    else:
        beaconTimeout += 10
        #print("Beacon not observed,", idleTime, "seconds since last activity,", beaconTimeout, "seconds since beacon seen")
        if idleTime >= 60 and beaconTimeout >= 60:
            if not screenSaverGetActive():
                print("No activity and not seen for at least 60 seconds, locking screen")
                screenSaverSetActive(True)
