]> www.average.org Git - loctrkd.git/blob - gps303/__main__.py
Work with cell location data; use opencellid
[loctrkd.git] / gps303 / __main__.py
1 from getopt import getopt
2 from logging import getLogger, StreamHandler, DEBUG, INFO
3 from logging.handlers import SysLogHandler
4 from select import poll, POLLIN, POLLERR, POLLHUP, POLLPRI
5 from socket import socket, AF_INET, SOCK_STREAM, SOL_SOCKET, SO_REUSEADDR
6 import sys
7 from time import time
8
9 from .config import readconfig
10 from .GT06mod import handle_packet, make_response, LOGIN, set_config
11 from .evstore import initdb, stow
12
13 CONF = "/etc/gps303.conf"
14
15 log = getLogger("gps303")
16
17 if __name__.endswith("__main__"):
18     opts, _ = getopt(sys.argv[1:], "c:d")
19     opts = dict(opts)
20     conf = readconfig(opts["-c"] if "-c" in opts else CONF)
21
22     if sys.stdout.isatty():
23         log.addHandler(StreamHandler(sys.stderr))
24     else:
25         log.addHandler(SysLogHandler(address="/dev/log"))
26     log.setLevel(DEBUG if "-d" in opts else INFO)
27     log.info("starting with options: %s", opts)
28
29     initdb(conf.get("daemon", "dbfn"))
30     set_config(conf)
31
32     ctlsock = socket(AF_INET, SOCK_STREAM)
33     ctlsock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
34     ctlsock.bind(("", conf.getint("daemon", "port")))
35     ctlsock.listen(5)
36     ctlfd = ctlsock.fileno()
37     pollset = poll()
38     pollset.register(ctlfd, POLLIN | POLLERR | POLLHUP | POLLPRI)
39     clnt_dict = {}
40     while True:
41         try:
42             events = pollset.poll(1000)
43         except KeyboardInterrupt:
44             log.info("Exiting")
45             sys.exit(0)
46         for fd, ev in events:
47             if fd == ctlfd:
48                 if ev & POLLIN:
49                     clntsock, clntaddr = ctlsock.accept()
50                     clntfd = clntsock.fileno()
51                     clnt_dict[clntfd] = (clntsock, clntaddr, None)
52                     pollset.register(
53                         clntfd, POLLIN | POLLERR | POLLHUP | POLLPRI
54                     )
55                     log.debug(
56                         "accepted connection from %s as fd %d",
57                         clntaddr,
58                         clntfd,
59                     )
60                 if ev & ~POLLIN:
61                     log.debug("unexpected event on ctlfd: %s", ev)
62             else:
63                 try:
64                     clntsock, clntaddr, imei = clnt_dict[fd]
65                 except KeyError:  # this socket closed already
66                     continue
67                 if ev & POLLIN:
68                     packet = clntsock.recv(4096)
69                     when = time()
70                     if packet:
71                         msg = handle_packet(packet, clntaddr, when)
72                         log.debug("%s from %s fd %d", msg, clntaddr, fd)
73                         if isinstance(msg, LOGIN):
74                             imei = msg.imei
75                             clnt_dict[fd] = (clntsock, clntaddr, imei)
76                         stow(
77                             clntaddr,
78                             when,
79                             imei,
80                             msg.length,
81                             msg.proto,
82                             msg.payload,
83                         )
84                         response = make_response(msg)
85                         if response:
86                             try:
87                                 # Ignore possibility of blocking
88                                 clntsock.send(make_response(msg))
89                             except OSError as e:
90                                 log.debug("sending to fd %d error %s", fd, e)
91                     else:
92                         log.info("disconnect fd %d imei %s", fd, imei)
93                         pollset.unregister(fd)
94                         clntsock.close()
95                         del clnt_dict[fd]
96                 if ev & ~POLLIN:
97                     log.warning("unexpected event", ev, "on fd", fd)