From ae9d73659a8cde01a3a85749cef4f9102702e462 Mon Sep 17 00:00:00 2001
From: clerie <git@clerie.de>
Date: Sat, 25 Jun 2022 17:03:13 +0200
Subject: [PATCH] Add interactive control interface

---
 fieldpoc/config.py     | 11 +++++++++
 fieldpoc/controller.py | 51 ++++++++++++++++++++++++++++++++++++++++++
 fieldpoc/fieldpoc.py   |  7 ++++++
 fieldpoc_config.json   |  4 ++++
 4 files changed, 73 insertions(+)
 create mode 100644 fieldpoc/controller.py

diff --git a/fieldpoc/config.py b/fieldpoc/config.py
index 02d0278..68ea8e4 100644
--- a/fieldpoc/config.py
+++ b/fieldpoc/config.py
@@ -1,5 +1,15 @@
 #!/usr/bin/env python3
 
+class ControllerConfig:
+    def __init__(self, c):
+        self._c = c
+
+    def __getattr__(self, name):
+            if name in self._c.keys():
+                return self._c.get(name)
+            else:
+                raise AttributeError()
+
 class DectConfig:
     def __init__(self, c):
         self._c = c
@@ -17,6 +27,7 @@ class DectConfig:
 class Config:
     def __init__(self, c):
         self._c = c
+        self.controller = ControllerConfig(c.get("controller", {}))
         self.dect = DectConfig(c.get("dect", {}))
 
     def check(self):
diff --git a/fieldpoc/controller.py b/fieldpoc/controller.py
new file mode 100644
index 0000000..a1ed9fc
--- /dev/null
+++ b/fieldpoc/controller.py
@@ -0,0 +1,51 @@
+#!/usr/bin/env python3
+
+import socketserver
+import time
+import threading
+
+class Controller:
+    def __init__(self, fp):
+        self.fp = fp
+
+    def get_handler(self):
+        class HandleRequest(socketserver.BaseRequestHandler):
+            fp = self.fp
+
+            def handle(self):
+                self.request.sendall("FieldPOC interactive controller\n".encode("utf-8"))
+                while True:
+                    self.request.sendall("> ".encode("utf-8"))
+                    data = self.request.recv(1024).decode("utf-8").strip()
+
+                    if data == "help":
+                        self.request.sendall("""Availiable commands:
+help    Show this info
+stop    Shutdown FieldPOC
+exit    Disconnect
+""".encode("utf-8"))
+                    elif data == "quit" or data == "exit":
+                        break
+                    elif data == "stop":
+                        self.fp.stop.set()
+                        break
+                    else:
+                        self.request.sendall("Unknown command, type 'help'\n".encode("utf-8"))
+
+                self.request.sendall("disconnecting\n".encode("utf-8"))
+
+        return HandleRequest
+
+
+    def run(self):
+        with socketserver.ThreadingTCPServer((self.fp.config.controller.host, self.fp.config.controller.port), self.get_handler()) as server:
+
+            threading.Thread(target=server.serve_forever).start()
+
+            self.fp.stop.wait()
+
+            print("stopping interactive controller")
+
+            server.shutdown()
+
+            print("stopped interactive controller")
diff --git a/fieldpoc/fieldpoc.py b/fieldpoc/fieldpoc.py
index 0392d4a..11a7307 100644
--- a/fieldpoc/fieldpoc.py
+++ b/fieldpoc/fieldpoc.py
@@ -5,6 +5,7 @@ import pathlib
 import threading
 
 from . import config
+from . import controller
 from . import dect
 
 class FieldPOC:
@@ -17,9 +18,15 @@ class FieldPOC:
         self.extensions_file_path = pathlib.Path(extensions_file_path)
         self._load_extensions()
 
+        self.stop = threading.Event()
+
+        self._controller = controller.Controller(self)
         self._dect = dect.Dect(self)
 
     def run(self):
+        self._controller_thread = threading.Thread(target=self._controller.run)
+        self._controller_thread.start()
+
         self._dect_thread = threading.Thread(target=self._dect.run)
         self._dect_thread.start()
 
diff --git a/fieldpoc_config.json b/fieldpoc_config.json
index e8f4ce3..85747b0 100644
--- a/fieldpoc_config.json
+++ b/fieldpoc_config.json
@@ -1,4 +1,8 @@
 {
+  "controller": {
+    "host": "127.0.0.1",
+    "port": 9437
+  },
   "dect": {
     "host": "192.168.0.100",
     "username": "omm",