3 # © Copyright 2021-2022, Scott Gasch
5 """Location/site dependent data."""
9 from dataclasses import dataclass
10 from typing import Callable, Optional
12 # Note: this module is fairly early loaded. Be aware of dependencies.
14 from type.locations import Location
16 logger = logging.getLogger(__name__)
18 args = config.add_commandline_args(
19 f'Global Site Config ({__file__})',
20 'Args related to global site-specific configuration',
23 '--site_config_override_location',
27 choices=['HOUSE', 'CABIN', 'NONE'],
28 help='Where are we, HOUSE, CABIN? Overrides standard detection code.',
33 class SiteConfig(object):
34 """The set of information specific to where the program is running."""
37 """Either "HOUSE" or "CABIN" depending on where we're running"""
40 """Same as above but as an enum value instead of a string"""
43 """The local network specification, e.g. 192.168.0.0/24."""
46 """The netmask of the local network, e.g. 255.255.255.0."""
48 network_router_ip: str
49 """The IP address of the local router, e.g. 192.168.0.1."""
51 presence_location: Location
52 """Same as location, above."""
54 is_anyone_present: Callable
55 """Returns a callable which, when invoked, will tell you if it detects
56 any person in your location by auditing network device MAC addresses."""
58 arper_minimum_device_count: int
59 """How many MAC addresses do we need to see for it to be considered a
63 """The location of the persisted IP-MAC address mappings."""
66 def get_location_name() -> str:
70 >>> location = get_location_name()
71 >>> location == 'HOUSE' or location == 'CABIN'
75 return get_config().location_name
78 def get_location() -> Location:
80 Returns location as an enum instead of a string.
82 >>> from type.locations import Location
83 >>> location = get_location()
84 >>> location == Location.HOUSE or location == Location.CABIN
88 return get_config().location
91 def _is_anyone_present_wrapper(location: Location):
94 p = base_presence.PresenceDetection()
95 return p.is_anyone_in_location_now(location)
98 def other_location() -> str:
100 Returns the location where this program is _NOT_ running.
102 >>> x = other_location()
103 >>> x in set(['HOUSE', 'CABIN'])
106 >>> y = this_location()
111 this = this_location()
114 elif this == 'CABIN':
117 raise Exception(f"{this} doesn't tell me where I'm running?!")
120 def this_location() -> str:
122 Returns the location where this program _IS_ running.
124 >>> x = this_location()
125 >>> x in set(['HOUSE', 'CABIN'])
129 hostname = platform.node()
130 if '.house' in hostname:
132 elif '.cabin' in hostname:
134 elif '.local' in hostname:
137 raise Exception(f"{hostname} doesn't help me know where I'm running?!")
141 def effective_location(location_override: Optional[str] = None) -> str:
142 """Detects and returns a location taking into account two override
145 >>> x = effective_location()
146 >>> x in set(['HOUSE', 'CABIN'])
149 >>> effective_location('HOUSE')
153 if location_override is None:
155 location_override = config.config['site_config_override_location']
157 location_override = None
159 if location_override is None or location_override == 'NONE':
160 location = this_location()
162 logger.debug('site_config\'s location_override was set to: %s', location_override)
163 location = location_override
167 def get_config(location_override: Optional[str] = None):
169 Get a configuration dataclass with information that is
170 site-specific including the current running location.
172 >>> cfg = get_config()
173 >>> cfg.location_name == 'HOUSE' or cfg.location_name == 'CABIN'
177 location = effective_location(location_override)
178 if location == 'HOUSE':
180 location_name='HOUSE',
181 location=Location.HOUSE,
182 network='10.0.0.0/24',
183 network_netmask='255.255.255.0',
184 network_router_ip='10.0.0.1',
185 presence_location=Location.HOUSE,
186 is_anyone_present=lambda x=Location.HOUSE: _is_anyone_present_wrapper(x),
187 arper_minimum_device_count=50,
188 arper_cache_file='/home/scott/cache/.arp_table_cache_house',
190 elif location == 'CABIN':
192 location_name='CABIN',
193 location=Location.CABIN,
194 network='192.168.0.0/24',
195 network_netmask='255.255.255.0',
196 network_router_ip='192.168.0.1',
197 presence_location=Location.CABIN,
198 is_anyone_present=lambda x=Location.CABIN: _is_anyone_present_wrapper(x),
199 arper_minimum_device_count=15,
200 arper_cache_file='/home/scott/cache/.arp_table_cache_cabin',
203 raise Exception(f'Unknown site location: {location}')
206 if __name__ == '__main__':