]> www.average.org Git - loctrkd.git/blobdiff - gps303/__main__.py
fill in `when` in Resp packet
[loctrkd.git] / gps303 / __main__.py
old mode 100755 (executable)
new mode 100644 (file)
index d3d6d1e..1583280
+""" Command line tool for sending requests to the terminal """
+
+from datetime import datetime, timezone
 from getopt import getopt
-from logging import getLogger, StreamHandler, DEBUG, INFO
-from logging.handlers import SysLogHandler
-from select import poll, POLLIN, POLLERR, POLLHUP, POLLPRI
-from socket import socket, AF_INET, SOCK_STREAM, SOL_SOCKET, SO_REUSEADDR
-import sys
+from logging import getLogger
+from sys import argv
 from time import time
+import zmq
 
-from .config import readconfig
-from .gps303proto import handle_packet, make_response, LOGIN, set_config
-from .evstore import initdb, stow
-from .lookaside import prepare_response
-
-CONF = "/etc/gps303.conf"
+from . import common
+from .gps303proto import *
+from .zmsg import Bcast, Resp
 
 log = getLogger("gps303")
 
-if __name__.endswith("__main__"):
-    opts, _ = getopt(sys.argv[1:], "c:d")
-    opts = dict(opts)
-    conf = readconfig(opts["-c"] if "-c" in opts else CONF)
 
-    if sys.stdout.isatty():
-        log.addHandler(StreamHandler(sys.stderr))
-    else:
-        log.addHandler(SysLogHandler(address="/dev/log"))
-    log.setLevel(DEBUG if "-d" in opts else INFO)
-    log.info("starting with options: %s", opts)
+def main(conf, opts, args):
+    zctx = zmq.Context()
+    zpush = zctx.socket(zmq.PUSH)
+    zpush.connect(conf.get("collector", "listenurl"))
 
-    initdb(conf.get("daemon", "dbfn"))
-    set_config(conf)
+    if len(args) < 2:
+        raise ValueError(
+            "Too few args, need IMEI and command min: " + str(args)
+        )
+    imei = args[0]
+    cmd = args[1]
+    args = args[2:]
+    cls = class_by_prefix(cmd)
+    if isinstance(cls, list):
+        raise ValueError("Prefix does not select a single class: " + str(cls))
+    kwargs = dict([arg.split("=") for arg in args])
+    for arg in args:
+        k, v = arg.split("=")
+        kwargs[k] = v
+    resp = Resp(imei=imei, when=time(), packet=cls.Out(**kwargs).packed)
+    log.debug("Response: %s", resp)
+    zpush.send(resp.packed)
 
-    ctlsock = socket(AF_INET, SOCK_STREAM)
-    ctlsock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
-    ctlsock.bind(("", conf.getint("daemon", "port")))
-    ctlsock.listen(5)
-    ctlfd = ctlsock.fileno()
-    pollset = poll()
-    pollset.register(ctlfd, POLLIN | POLLERR | POLLHUP | POLLPRI)
-    clnt_dict = {}
-    while True:
-        try:
-            events = pollset.poll(1000)
-        except KeyboardInterrupt:
-            log.info("Exiting")
-            sys.exit(0)
-        for fd, ev in events:
-            if fd == ctlfd:
-                if ev & POLLIN:
-                    clntsock, clntaddr = ctlsock.accept()
-                    clntfd = clntsock.fileno()
-                    clnt_dict[clntfd] = (clntsock, clntaddr, None)
-                    pollset.register(
-                        clntfd, POLLIN | POLLERR | POLLHUP | POLLPRI
-                    )
-                    log.debug(
-                        "accepted connection from %s as fd %d",
-                        clntaddr,
-                        clntfd,
-                    )
-                if ev & ~POLLIN:
-                    log.debug("unexpected event on ctlfd: %s", ev)
-            else:
-                try:
-                    clntsock, clntaddr, imei = clnt_dict[fd]
-                except KeyError:  # this socket closed already
-                    continue
-                if ev & POLLIN:
-                    packet = clntsock.recv(4096)
-                    when = time()
-                    if packet:
-                        msg = handle_packet(packet, clntaddr, when)
-                        log.debug("%s from %s fd %d", msg, clntaddr, fd)
-                        if isinstance(msg, LOGIN):
-                            imei = msg.imei
-                            clnt_dict[fd] = (clntsock, clntaddr, imei)
-                        stow(
-                            clntaddr,
-                            when,
-                            imei,
-                            msg.length,
-                            msg.proto,
-                            msg.payload,
-                        )
-                        kwargs = prepare_response(conf, msg)
-                        response = make_response(msg, **kwargs)
-                        if response:
-                            try:
-                                # Ignore possibility of blocking
-                                clntsock.send(make_response(msg))
-                            except OSError as e:
-                                log.debug("sending to fd %d error %s", fd, e)
-                    else:
-                        # TODO: Also disconnect on HIBERNATION
-                        log.info("disconnect fd %d imei %s", fd, imei)
-                        pollset.unregister(fd)
-                        clntsock.close()
-                        del clnt_dict[fd]
-                if ev & ~POLLIN:
-                    log.warning("unexpected event", ev, "on fd", fd)
+
+if __name__.endswith("__main__"):
+    opts, args = getopt(argv[1:], "c:d")
+    main(common.init(log, opts=opts), opts, args)