Revize 474551ae
Přidáno uživatelem Jakub Šilhavý před asi 3 roky(ů)
client/api_client.py | ||
---|---|---|
5 | 5 |
from diskcache import Deque |
6 | 6 |
from requests import HTTPError, ConnectionError |
7 | 7 |
|
8 |
from config_manager import server_url, server_port, server_endpoint, cache_dir, \ |
|
9 |
cache_retry_period_seconds, cache_max_retries, cache_max_entries |
|
10 | 8 |
|
9 |
_uri = None |
|
10 |
_cache = None |
|
11 |
_config = None |
|
11 | 12 |
|
12 |
_cache = Deque(directory=cache_dir) |
|
13 |
_uri = server_url + ":" + server_port + server_endpoint |
|
13 |
|
|
14 |
def api_client_set_config(config): |
|
15 |
global _config, _cache, _uri |
|
16 |
_config = config |
|
17 |
_cache = Deque(directory=_config.cache_dir) |
|
18 |
_uri = config.server_url + ":" + config.server_port + config.server_endpoint |
|
14 | 19 |
|
15 | 20 |
|
16 | 21 |
def send_data(payload: dict): |
... | ... | |
27 | 32 |
|
28 | 33 |
|
29 | 34 |
def _cache_failed_payload(payload: dict): |
30 |
if len(_cache) >= cache_max_entries: |
|
35 |
if len(_cache) >= _config.cache_max_entries:
|
|
31 | 36 |
oldest_payload = _cache.pop() |
32 | 37 |
logging.warning(f"cache is full - discarding payload = {oldest_payload}") |
33 | 38 |
|
... | ... | |
35 | 40 |
_cache.append(payload) |
36 | 41 |
|
37 | 42 |
|
43 |
def _resend_cached_payloads(): |
|
44 |
retries = min(_config.cache_max_retries, len(_cache)) |
|
45 |
logging.info(f"emptying the cache ({retries} records)") |
|
46 |
for _ in range(0, retries): |
|
47 |
payload = _cache.pop() |
|
48 |
send_data(payload) |
|
49 |
|
|
50 |
|
|
38 | 51 |
def api_client_run(): |
39 | 52 |
while True: |
40 |
retries = min(cache_max_retries, len(_cache)) |
|
41 |
logging.info(f"emptying the cache ({retries} records)") |
|
42 |
for _ in range(0, retries): |
|
43 |
payload = _cache.pop() |
|
44 |
send_data(payload) |
|
45 |
sleep(cache_retry_period_seconds) |
|
53 |
_resend_cached_payloads() |
|
54 |
sleep(_config.cache_retry_period_seconds) |
client/config_manager.py | ||
---|---|---|
1 |
from sys import exit |
|
1 | 2 |
from configparser import RawConfigParser |
2 | 3 |
|
3 | 4 |
|
4 |
CONFIG_FILE = "config.ini" |
|
5 |
|
|
6 |
usb_detector_section = "usb_detector" |
|
7 |
server_section = "server" |
|
8 |
logger_section = "logger" |
|
9 |
cache_section = "cache" |
|
10 |
|
|
11 |
config = RawConfigParser() |
|
12 |
config.read(CONFIG_FILE) |
|
13 |
|
|
14 |
scan_period_seconds = float(config[usb_detector_section]["scan_period_seconds"]) |
|
15 |
connected_devices_filename = config[usb_detector_section]["connected_devices_filename"] |
|
16 |
|
|
17 |
server_url = config[server_section]["url"] |
|
18 |
server_port = config[server_section]["port"] |
|
19 |
server_endpoint = config[server_section]["end_point"] |
|
20 |
|
|
21 |
logger_config = config[logger_section]["file"] |
|
22 |
logger_format = config[logger_section]["format"] |
|
23 |
logger_level_str = config[logger_section]["level"] |
|
24 |
logger_level = 0 |
|
25 |
|
|
26 |
if logger_level_str == "DEBUG": |
|
27 |
logger_level = 10 |
|
28 |
elif logger_level_str == "INFO": |
|
29 |
logger_level = 20 |
|
30 |
elif logger_level_str == "WARNING": |
|
31 |
logger_level = 30 |
|
32 |
elif logger_level_str == "ERROR": |
|
33 |
logger_level = 40 |
|
34 |
elif logger_level_str == "CRITICAL": |
|
35 |
logger_level = 50 |
|
36 |
|
|
37 |
cache_dir = config[cache_section]["directory"] |
|
38 |
cache_max_entries = int(config[cache_section]["max_entries"]) |
|
39 |
cache_max_retries = int(config[cache_section]["max_retries"]) |
|
40 |
cache_retry_period_seconds = float(config[cache_section]["retry_period_seconds"]) |
|
5 |
class Config: |
|
6 |
|
|
7 |
def __init__(self, filepath): |
|
8 |
self.config = RawConfigParser() |
|
9 |
if not self.config.read(filepath): |
|
10 |
print(f"Failed to parse the config file {filepath}. Make sure you entered a valid path.") |
|
11 |
exit(1) |
|
12 |
|
|
13 |
self._parse_usb_detector_section() |
|
14 |
self._parse_server_section() |
|
15 |
self._parse_logger_section() |
|
16 |
self._parse_cache_section() |
|
17 |
|
|
18 |
def _parse_usb_detector_section(self): |
|
19 |
section_name = "usb_detector" |
|
20 |
self.scan_period_seconds = float(self.config[section_name]["scan_period_seconds"]) |
|
21 |
self.connected_devices_filename = self.config[section_name]["connected_devices_filename"] |
|
22 |
|
|
23 |
def _parse_server_section(self): |
|
24 |
section_name = "server" |
|
25 |
self.server_url = self.config[section_name]["url"] |
|
26 |
self.server_port = self.config[section_name]["port"] |
|
27 |
self.server_endpoint = self.config[section_name]["end_point"] |
|
28 |
|
|
29 |
def _parse_logger_section(self): |
|
30 |
section_name = "logger" |
|
31 |
self.logger_config_file = self.config[section_name]["config_file"] |
|
32 |
|
|
33 |
def _parse_cache_section(self): |
|
34 |
section_name = "cache" |
|
35 |
self.cache_dir = self.config[section_name]["directory"] |
|
36 |
self.cache_max_entries = int(self.config[section_name]["max_entries"]) |
|
37 |
self.cache_max_retries = int(self.config[section_name]["max_retries"]) |
|
38 |
self.cache_retry_period_seconds = float(self.config[section_name]["retry_period_seconds"]) |
client/main.py | ||
---|---|---|
5 | 5 |
from tendo import singleton |
6 | 6 |
from sys import exit |
7 | 7 |
|
8 |
from config_manager import logger_config
|
|
9 |
from usb_detector.detector import register_listener, usb_detector_run |
|
8 |
from config_manager import Config
|
|
9 |
from usb_detector.detector import register_listener, usb_detector_run, usb_detector_set_config
|
|
10 | 10 |
from usb_detector.event_listener import usb_connected_callback, usb_disconnected_callback |
11 |
from api_client import api_client_run |
|
11 |
from api_client import api_client_run, api_client_set_config
|
|
12 | 12 |
|
13 | 13 |
|
14 |
def init_logging(): |
|
15 |
if exists(logger_config): |
|
16 |
logging.config.fileConfig(fname=logger_config) |
|
14 |
def init_logging(app_config: Config): |
|
15 |
if exists(app_config.logger_config_file): |
|
16 |
logging.config.fileConfig(fname=app_config.logger_config_file) |
|
17 |
api_client_set_config(app_config) |
|
18 |
usb_detector_set_config(app_config) |
|
17 | 19 |
else: |
18 |
print(f"Cant find logger configuration \"{logger_config}\"! Please specify valid path or define new.")
|
|
20 |
print(f"Cannot find logger configuration \"{app_config.logger_config_file}\"! Please specify valid a path or define a new one.")
|
|
19 | 21 |
exit(1) |
20 | 22 |
|
21 | 23 |
|
... | ... | |
25 | 27 |
except singleton.SingleInstanceException: |
26 | 28 |
exit(1) |
27 | 29 |
|
28 |
init_logging() |
|
30 |
config = Config("config.ini") |
|
31 |
init_logging(config) |
|
29 | 32 |
|
30 | 33 |
register_listener(callback=usb_connected_callback, connected=True) |
31 | 34 |
register_listener(callback=usb_disconnected_callback, connected=False) |
... | ... | |
36 | 39 |
api_thread = Thread(target=api_client_run) |
37 | 40 |
api_thread.setDaemon(True) |
38 | 41 |
|
39 |
logging.info('starting USB detector.')
|
|
42 |
logging.info("Starting USB detector.")
|
|
40 | 43 |
usb_detector_thread.start() |
41 | 44 |
|
42 |
logging.info('starting API communication manager.')
|
|
45 |
logging.info("Starting API communication manager.")
|
|
43 | 46 |
api_thread.start() |
44 | 47 |
|
45 | 48 |
usb_detector_thread.join() |
46 | 49 |
api_thread.join() |
47 |
|
|
48 |
logging.info('application exit.') |
client/usb_detector/detector.py | ||
---|---|---|
3 | 3 |
from time import sleep |
4 | 4 |
|
5 | 5 |
from .usb_reader import read_connected_devices |
6 |
from config_manager import scan_period_seconds, connected_devices_filename |
|
7 | 6 |
|
8 | 7 |
|
9 | 8 |
_listeners_connected = [] |
10 | 9 |
_listeners_disconnected = [] |
11 | 10 |
_last_connected_devices = [] |
11 |
_config = None |
|
12 | 12 |
|
13 | 13 |
|
14 |
def register_listener(callback, connected: bool = True): |
|
15 |
logging.info(f'Registering callback: {callback}.') |
|
14 |
def usb_detector_set_config(config): |
|
15 |
global _config |
|
16 |
_config = config |
|
17 |
|
|
16 | 18 |
|
19 |
def register_listener(callback, connected: bool = True): |
|
20 |
logging.info(f"Registering callback: {callback}.") |
|
17 | 21 |
if connected is True: |
18 | 22 |
_listeners_connected.append(callback) |
19 | 23 |
else: |
... | ... | |
21 | 25 |
|
22 | 26 |
|
23 | 27 |
def _notify_listeners(listeners: list, devices: list): |
28 |
if listeners is None or devices is None: |
|
29 |
return |
|
24 | 30 |
for callback in listeners: |
25 | 31 |
for device in devices: |
26 | 32 |
callback(device) |
27 | 33 |
|
28 | 34 |
|
29 | 35 |
def _store_connected_devices(devices: list): |
30 |
logging.debug('storing newly connected devices')
|
|
31 |
with open(connected_devices_filename, "w") as file: |
|
36 |
logging.debug("storing newly connected devices")
|
|
37 |
with open(_config.connected_devices_filename, "w") as file:
|
|
32 | 38 |
json.dump(devices, file) |
33 | 39 |
|
34 | 40 |
|
35 | 41 |
def _load_last_connected_devices() -> list: |
36 |
logging.debug('loading last connected devices')
|
|
42 |
logging.debug("loading last connected devices")
|
|
37 | 43 |
try: |
38 |
with open(connected_devices_filename, "r") as file: |
|
44 |
with open(_config.connected_devices_filename, "r") as file:
|
|
39 | 45 |
return json.loads(file.read()) |
40 | 46 |
except IOError: |
41 |
logging.error('loading of last connected devices failed')
|
|
47 |
logging.error("loading of last connected devices failed")
|
|
42 | 48 |
return [] |
43 | 49 |
|
44 | 50 |
|
... | ... | |
73 | 79 |
|
74 | 80 |
while True: |
75 | 81 |
_update() |
76 |
sleep(scan_period_seconds) |
|
82 |
sleep(_config.scan_period_seconds) |
client/usb_detector/event_listener.py | ||
---|---|---|
7 | 7 |
|
8 | 8 |
|
9 | 9 |
def _get_metadata() -> dict: |
10 |
logging.debug('getting computer metadata')
|
|
10 |
logging.debug("getting computer metadata")
|
|
11 | 11 |
return { |
12 | 12 |
"username": getpass.getuser(), |
13 | 13 |
"hostname": platform.uname().node, |
... | ... | |
16 | 16 |
|
17 | 17 |
|
18 | 18 |
def _send_payload_to_server(device: dict, status: str): |
19 |
logging.debug('payload send preparation')
|
|
19 |
logging.debug("payload send preparation")
|
|
20 | 20 |
payload = _get_metadata() |
21 | 21 |
payload["device"] = device |
22 | 22 |
payload["status"] = status |
Také k dispozici: Unified diff
re #9419 Moved the config manager into a class (better modularity)