From 8ed8e5f2556ce346579fa68f290636e2481c313d Mon Sep 17 00:00:00 2001 From: Dmytro Bogovych Date: Tue, 19 Sep 2023 09:01:41 +0300 Subject: [PATCH] - initial implementation of standalone hotspot --- setup/setup_agent_gsm.sh | 4 +-- src/agent_gsm.py | 14 +++++++++-- src/agent_point.py | 54 ++++++++++++++++++++++++++++++++++++++++ src/utils_qualtest.py | 14 +++++++++-- 4 files changed, 80 insertions(+), 6 deletions(-) create mode 100644 src/agent_point.py diff --git a/setup/setup_agent_gsm.sh b/setup/setup_agent_gsm.sh index 9936379..a6aef55 100755 --- a/setup/setup_agent_gsm.sh +++ b/setup/setup_agent_gsm.sh @@ -10,8 +10,8 @@ INSTALL_DIR=agent_gsm GIT_SOURCE=https://git.sevana.biz/public/agent_gsm # Install prerequisites -sudo apt install --assume-yes git mc python3 sox vim libffi-dev screen python3-pip python3-numpy -sudo pip3 install pyyaml sox pyrabbit soundfile dbus_python pexpect pydub requests rabbitpy pydub +sudo apt install --assume-yes git mc python3 sox vim libffi-dev screen python3-pip python3-numpy dnsmasq hostapd +sudo pip3 install pyyaml sox pyrabbit soundfile dbus_python pexpect pydub requests rabbitpy pydub reachability bottle if [ -f "$INSTALL_DIR" ]; then rm -rf "$INSTALL_DIR" diff --git a/src/agent_gsm.py b/src/agent_gsm.py index f92873f..911d668 100644 --- a/src/agent_gsm.py +++ b/src/agent_gsm.py @@ -24,6 +24,7 @@ from bt_signal import SignalBoundaries from bt_call_controller import INTERRUPT_SIGNAL import bt_call_controller +import agent_point CONFIG = AgentConfig() @@ -436,6 +437,9 @@ def receive_signal(signal_number, frame): # Delete PID file remove_pid_on_exit() + # Stop optional access point + agent_point.stop() + # Debugging info print(f'Got signal {signal_number} from {frame}') @@ -447,7 +451,6 @@ def receive_signal(signal_number, frame): return - # Check if Python version is ok assert sys.version_info >= (3, 6) @@ -529,7 +532,11 @@ if __name__ == '__main__': if BACKEND.phone is None: utils.log_error(f'Failed to obtain information about {BACKEND.instance}. Exiting.') exit(EXIT_ERROR) - + + if not BACKEND.online: + # Start own hotspot and API server + agent_point.start() + # Cache phone information CACHE.put_phone(BACKEND.phone) @@ -570,4 +577,7 @@ if __name__ == '__main__': # Close log file utils.close_log_file() + # Stop optional access point + agent_point.stop() + sys.exit(EXIT_OK) diff --git a/src/agent_point.py b/src/agent_point.py new file mode 100644 index 0000000..efe6996 --- /dev/null +++ b/src/agent_point.py @@ -0,0 +1,54 @@ +#!/usr/bin/python3 +import PyAccessPoint +import bottle +import multiprocessing +from PyAccessPoint import pyaccesspoint +class AccessPoint: + active: bool = False + ap: pyaccesspoint.AccessPoint = None + + def __init__(self) -> None: + pass + + + def start(self): + if self.ap is not None: + return + + self.ap = pyaccesspoint.AccessPoint(ssid='agent_gsm', password='qwerty') + if not self.ap.start(): + raise RuntimeError(f'Failed to start WiFi access point.') + + def stop(self): + if self.ap is None: + return + + if not self.ap.stop(): + raise RuntimeError(f'Failed to stop Wifi access point') + self.ap = None + +ACCESS_POINT = AccessPoint() +SERVER_PROCESS = None + +@bottle.route('/status') +def web_status(): + return "OK" + +def web_process(): + bottle.run(host='0.0.0.0', port=8080) + +def start(): + global SERVER_PROCESS + + ACCESS_POINT.start() + SERVER_PROCESS = multiprocessing.Process(target=web_process) + +def stop(): + ACCESS_POINT.stop() + SERVER_PROCESS.kill() + + +if __name__ == '__main__': + start() + # Wait 120 seconds for tests + stop() diff --git a/src/utils_qualtest.py b/src/utils_qualtest.py index 03fce30..db6d9d5 100644 --- a/src/utils_qualtest.py +++ b/src/utils_qualtest.py @@ -66,12 +66,13 @@ def trace_function(frame, event, arg): class QualtestBackend: address: str instance: str + online: bool def __init__(self): - self.address = "" + self.address = "" self.instance = "" self.__phone = None - + self.online = False @property def phone(self) -> Phone: @@ -190,8 +191,17 @@ class QualtestBackend: response = urllib.request.urlopen(url, timeout=utils.NETWORK_TIMEOUT) if response.getcode() != 200: raise RuntimeError(f'Failed to load phone definition from server. Error code: {response.getcode()}') + + # Consider backend as working one + self.online = True + except Exception as e: utils.log_error(f'Problem when loading the phone definition from backend. Error: {str(e)}') + + # Consider backend as non-working + self.online = False + + # Try to get data from the cache r = cache.get_phone(self.instance) if r is None: raise RuntimeError(f'No cached phone definition.')