summaryrefslogtreecommitdiff
path: root/smart_home
diff options
context:
space:
mode:
Diffstat (limited to 'smart_home')
-rw-r--r--smart_home/cameras.py8
-rw-r--r--smart_home/chromecasts.py2
-rw-r--r--smart_home/registry.py52
-rw-r--r--smart_home/thermometers.py23
4 files changed, 79 insertions, 6 deletions
diff --git a/smart_home/cameras.py b/smart_home/cameras.py
index 8643611..e8f164b 100644
--- a/smart_home/cameras.py
+++ b/smart_home/cameras.py
@@ -5,6 +5,7 @@
"""Utilities for dealing with the webcams."""
import logging
+from typing import Optional
import scott_secrets
import smart_home.device as dev
@@ -29,9 +30,12 @@ class BaseCamera(dev.Device):
super().__init__(name.strip(), mac.strip(), keywords)
self.camera_name = BaseCamera.camera_mapping.get(name, None)
- def get_stream_url(self) -> str:
+ def get_stream_url(self) -> Optional[str]:
+ """Get the URL for the webcam's live stream. Return None on error."""
+
name = self.camera_name
- assert name is not None
+ if not name:
+ return None
if name == 'driveway':
return f'http://10.0.0.226:8080/{scott_secrets.SHINOBI_KEY1}/mjpeg/{scott_secrets.SHINOBI_KEY2}/driveway'
else:
diff --git a/smart_home/chromecasts.py b/smart_home/chromecasts.py
index 408ccf0..3bd45f1 100644
--- a/smart_home/chromecasts.py
+++ b/smart_home/chromecasts.py
@@ -2,7 +2,7 @@
# © Copyright 2021-2022, Scott Gasch
-"""Utilities for dealing with the webcams."""
+"""Utilities for dealing with the chromecasts."""
import atexit
import datetime
diff --git a/smart_home/registry.py b/smart_home/registry.py
index d63474d..8ca7f3b 100644
--- a/smart_home/registry.py
+++ b/smart_home/registry.py
@@ -83,9 +83,9 @@ class SmartHomeRegistry(object):
self._keywords_by_name[name] = keywords
self._keywords_by_mac[mac] = keywords
self._names_by_mac[mac] = name
- self.index_device(name, keywords, mac)
+ self._index_device(name, keywords, mac)
- def index_device(self, name: str, keywords: str, mac: str) -> None:
+ def _index_device(self, name: str, keywords: str, mac: str) -> None:
properties = [("name", name)]
tags = set()
for kw in keywords.split():
@@ -111,9 +111,30 @@ class SmartHomeRegistry(object):
return s
def get_keywords_by_name(self, name: str) -> Optional[str]:
+ """Given the name of a device, get its keywords.
+
+ >>> reg = SmartHomeRegistry('/home/scott/bin/network_mac_addresses.txt')
+ >>> reg.get_keywords_by_name('near_kitchen_lamp')
+ 'wifi smart light goog meross test'
+
+ >>> reg.get_keywords_by_name('unknown') is None
+ True
+
+ """
return self._keywords_by_name.get(name, None)
def get_macs_by_name(self, name: str) -> Set[str]:
+ """Given the name of a device, get its MAC address(es)
+
+ >>> reg = SmartHomeRegistry('/home/scott/bin/network_mac_addresses.txt')
+ >>> reg.get_macs_by_name('near_kitchen_lamp')
+ {'34:29:8F:12:34:8E'}
+
+ >>> reg.get_macs_by_name('unknown')
+ set()
+
+ """
+
retval = set()
for (mac, lname) in self._names_by_mac.items():
if name in lname:
@@ -121,6 +142,19 @@ class SmartHomeRegistry(object):
return retval
def get_macs_by_keyword(self, keyword: str) -> Set[str]:
+ """Given a keyword, return the set of MAC address(es) that have
+ that keyword.
+
+ >>> reg = SmartHomeRegistry('/home/scott/bin/network_mac_addresses.txt')
+ >>> r = reg.get_macs_by_keyword('test')
+ >>> e = set(['34:29:8F:12:26:74' , '34:29:8F:12:34:8E'])
+ >>> r == e
+ True
+
+ >>> reg.get_macs_by_keyword('unknown')
+ set()
+
+ """
retval = set()
for (mac, keywords) in self._keywords_by_mac.items():
if keyword in keywords:
@@ -128,11 +162,15 @@ class SmartHomeRegistry(object):
return retval
def get_device_by_name(self, name: str) -> Optional[device.Device]:
+ """Given a name, return its Device object."""
+
if name in self._macs_by_name:
return self.get_device_by_mac(self._macs_by_name[name])
return None
def get_all_devices(self) -> List[device.Device]:
+ """Return a list of all known devices."""
+
retval = []
for mac, _ in self._keywords_by_mac.items():
if mac is not None:
@@ -142,6 +180,8 @@ class SmartHomeRegistry(object):
return retval
def get_device_by_mac(self, mac: str) -> Optional[device.Device]:
+ """Given a MAC address, return its Device object."""
+
if mac in self._keywords_by_mac:
name = self._names_by_mac[mac]
kws = self._keywords_by_mac[mac]
@@ -197,7 +237,7 @@ class SmartHomeRegistry(object):
return None
def query(self, query: str) -> List[device.Device]:
- """Evaluates a lighting query expression formed of keywords to search
+ """Evaluates a device query expression formed of keywords to search
for, logical operators (and, or, not), and parenthesis.
Returns a list of matching lights.
"""
@@ -211,3 +251,9 @@ class SmartHomeRegistry(object):
if dev is not None:
retval.append(dev)
return retval
+
+
+if __name__ == '__main__':
+ import doctest
+
+ doctest.testmod()
diff --git a/smart_home/thermometers.py b/smart_home/thermometers.py
index 73117bc..4531c61 100644
--- a/smart_home/thermometers.py
+++ b/smart_home/thermometers.py
@@ -28,6 +28,22 @@ class ThermometerRegistry(object):
}
def read_temperature(self, location: str, *, convert_to_fahrenheit=False) -> Optional[float]:
+ """Read the current value of a thermometer (in celsius unless
+ convert_to_fahrenheit is True) and return it. Return None on
+ error.
+
+ >>> registry = ThermometerRegistry()
+ >>> registry.read_temperature('unknown') is None
+ True
+
+ >>> temp = registry.read_temperature('house_computer_closet')
+ >>> temp is None
+ False
+ >>> temp > 0.0
+ True
+
+ """
+
record = self.thermometers.get(location, None)
if record is None:
logger.error(
@@ -36,6 +52,7 @@ class ThermometerRegistry(object):
self.thermometers.keys(),
)
return None
+
url = f'http://{record[0]}/~pi/{record[1]}'
logger.debug('Constructed URL: %s', url)
try:
@@ -54,3 +71,9 @@ class ThermometerRegistry(object):
if www is not None:
www.close()
return temp
+
+
+if __name__ == '__main__':
+ import doctest
+
+ doctest.testmod()