net.py: typo fix + catch the right exception
[breadcrumb.git] / code / breadcrumb / client / tracking.py
blob7ad6234c101f23a16d8c9928380b4fe5732cbb0e
1 # -*- coding: utf8 -*-
2 """Tracking code for Breadcrumb. Mainly glue between other components."""
4 # Copyright (C) 2008 Laurens Van Houtven <lvh at laurensvh.be>
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation, either version 3 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program. If not, see <http://www.gnu.org/licenses/>.
18 import net
19 import logging
20 import collections
22 class Tracker:
23 """The central class for handling GPS tracking."""
24 def __init__(self, host = None, port = None):
25 self.network_interface = net.UDPClient(host = host, port = port)
26 self.gps = None # See connect_to_gps()
27 self.messages = collections.deque()
28 self.last_point = None
30 def start(self):
31 """Starts the main tracking cycle.
33 This iterates over the gps attribute, which produces points.
34 """
35 for new_point in self.gps:
36 if new_point is not None: # new point
37 if self.last_point is None:
38 self.last_point = new_point
40 elif self.last_point < new_point:
41 self.last_point.update(new_point)
43 else:
44 continue
46 self.send_point()
48 logging.debug("No more data from the GPS! Fake device?")
50 def send_point(self):
51 """Sends the tracker's current point.
53 Also tries to send a handler message together with the point, unless
54 that point already has one. In that case, a second crumb is sent
55 immediately afterwards that has nothing but the handler message. This
56 prevents clients that send a handler message with *every* point from
57 blocking all other handler messages permanently.
58 """
59 delayed = False
60 if self.messages:
61 if not has_message(self.last_point):
62 next_message(point)
63 else:
64 delayed = True
66 self.network_interface.send_point(self.last_point)
67 self.last_point.clear_message()
69 if delayed:
70 point = self.next_message()
71 self.networkinterface.sendpoint(point)
73 def next_message(self, point = {}):
74 """Gets the next handler message from the queue and adds it to a point.
76 Uses an empty dict if no point is provided.
78 The point is always returned. This is useful if no point was provided.
79 """
80 if self.messages:
81 id, msg = self.messages.popleft()
82 point.update({'handlerid': id, 'handlermessage': msg})
84 return point
86 def has_message(point):
87 """Returns True if the point has a handler message, False otherwise."""
88 for attr in ('handlerid', 'handlermessage'):
89 if attr not in point:
90 return False
91 return True