Этот код интегрируется с dweet и надводный борт для отображения на приборной панели того, кто из жильцов дома, вероятно, находится дома, на основании наличия или отсутствия MAC-адресов их телефонов в локальной сети.
Важное различие для meke — это между текущий и отмечен присутствие. Например, с 15-минутным льготным периодом, установленным в файле конфигурации, пользователи, отмеченные как В настоящее время присутствовать в любое время в течение последних 15 минут будет отмечен присутствуют, даже если они не В настоящее время присутствует прямо сейчас. Другими словами, текущий присутствие достоверно известно во время выполнения строки кода, тогда как отмечен присутствие «вероятно, точное» и учитывает более длительный период времени.
Программа также читает файл конфигурации в формате YAML, который по умолчанию хранится в /etc/homepresenced/homepresenced.yaml
. Ниже показан пример файла конфигурации.
from time import sleep
import subprocess
import datetime
import yaml
import dweepy
CONFIG_FILE_PATH = '/etc/homepresenced/homepresenced.yaml'
class Occupant:
def __init__(self, name, mac):
self.name = name
self.mac = mac
self.lastPresent = None
def registerPresence(self):
self.lastPresent = datetime.datetime.now()
with open(CONFIG_FILE_PATH) as f:
# load configuration into conf dictionary
conf = yaml.safe_load(f)
# replace yaml-style occupant listings with instances of Occupant object
for i, occupant in enumerate(conf['occupants']):
conf['occupants'][i] = Occupant(occupant['name'], occupant['mac'])
try:
while True:
occupancy_report = {} # data sent to dweepy about occupant presence
# perform network scan. this takes time so it's more efficient to do it once per loop, rather than once per occupant per loop
arp_scan = str(subprocess.check_output("sudo arp-scan -l", shell=True))
for occupant in conf['occupants']:
if occupant.mac in arp_scan:
occupant.registerPresence() # register occupant as CURRENTLY present if mac is in scan
# should the occupant be MARKED as present (taking into account the 'grace period')?
presence = datetime.datetime.now() - occupant.lastPresent < datetime.timedelta(minutes=conf['presence_grace_period']) if occupant.lastPresent else None
# format time of last CURRENT presence. if not set (==None) then use "never"
lastPresent = occupant.lastPresent.strftime(conf['time_format']) if occupant.lastPresent else "never"
print(f"Occupant {occupant.name}'s device is {'PRESENT' if presence else 'ABSENT' if presence == False else 'UNSEEN'} (last present: {lastPresent})")
# add to dictionary that will be sent to dweepy
occupancy_report[occupant.name] = {
'presence': presence,
'lastPresent': lastPresent
}
dweepy.dweet_for(conf['dweet_thing'], occupancy_report)
# catch keyboard ctrl+c interrupt signals and exit cleanly
except KeyboardInterrupt:
exit()
presence_grace_period: 15
dweet_thing: identifier_for_dweet_io
time_format: "%Y/%m/%d at %HL%M:%S"
occupants:
- name: User One
mac: 11:aa:11:aa:11:aa
- name: User Two
mac: 22:bb:22:bb:22:bb
- name: User Three
mac: 33:cc:33:cc:33:9cc