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