Ejemplo n.º 1
0
class NetworkSettingsWindow(CarPiBaseSettingsWindow):
    def __init__(self, parent, redis):
        self._redis = redis
        self._fetcher = RedisBackgroundFetcher(redis, [
            NetworkInfoRedisKeys.KEY_ETH0_IP,
            NetworkInfoRedisKeys.KEY_WLAN0_STRENGTH,
            NetworkInfoRedisKeys.KEY_WLAN0_SSID,
            NetworkInfoRedisKeys.KEY_WLAN0_IP,
            NetworkInfoRedisKeys.KEY_WLAN1_STRENGTH,
            NetworkInfoRedisKeys.KEY_WLAN1_SSID,
            NetworkInfoRedisKeys.KEY_WLAN1_IP
        ],
                                               fetch_interval=5)

        self._ethernet_ip = None  # type: Text
        self._wifi0_ip = None  # type: Text
        self._wifi1_ip = None  # type: Text

        CarPiBaseSettingsWindow.__init__(self, parent, 'Network Settings')

    def _init_controls(self):
        style = {TEXT_FONT: (DEFAULT_STYLE[TEXT_FONT][0], 14)}

        Text(self, ((10, 10), (300, 25)), 'Ethernet IP:', style=style).pack()
        Text(self, ((10, 35), (300, 25)), 'Hotspot IP:', style=style).pack()
        Text(self, ((10, 60), (300, 25)), 'External IP:', style=style).pack()

        self._ethernet_ip = Text(self, ((100, 10), (190, 25)),
                                 '...',
                                 style=style).pack()
        self._wifi0_ip = Text(self, ((100, 35), (190, 25)), '...',
                              style=style).pack()
        self._wifi1_ip = Text(self, ((100, 60), (190, 25)), '...',
                              style=style).pack()

        self._init_options(self, [
            None, None, None, None, None, None, None, None,
            ('< Back', self._back_callback), None
        ])

        self._fetcher.start()

    def update(self):
        new_data = self._fetcher.get_current_data()
        self._ethernet_ip.settext(
            new_data.get(NetworkInfoRedisKeys.KEY_ETH0_IP, '-'))
        self._wifi0_ip.settext(
            new_data.get(NetworkInfoRedisKeys.KEY_WLAN0_IP, '-'))
        self._wifi1_ip.settext(
            new_data.get(NetworkInfoRedisKeys.KEY_WLAN1_IP, '-'))

    def destroy(self):
        self._fetcher.stop()
        super(NetworkSettingsWindow, self).destroy()
Ejemplo n.º 2
0
    def __init__(self, parent, temp_redis, persist_redis):
        self._temp_redis = temp_redis
        self._persist_redis = persist_redis

        self._fetcher = RedisBackgroundFetcher(persist_redis, [
            PersistentGpsRedisKeys.KEY_TRIP_A,
            PersistentGpsRedisKeys.KEY_TRIP_B, PersistentGpsRedisKeys.KEY_ODO
        ],
                                               fetch_interval=1)

        self._trip_a_text = None  # type: Text
        self._trip_b_text = None  # type: Text
        self._odo_text = None  # type: Text

        CarPiBaseSettingsWindow.__init__(self, parent, 'GPS & Trip Settings')
Ejemplo n.º 3
0
    def _load(self):
        self.load_image(IMG_ETHERNET_OFF)
        self.load_image(IMG_ETHERNET)
        self.load_image(IMG_WIFI_OFF)
        self.load_image(IMG_WIFI0)
        self.load_image(IMG_WIFI1)
        self.load_image(IMG_WIFI2)
        self.load_image(IMG_WIFI3)
        self.load_image(IMG_GPS_OFF)
        self.load_image(IMG_GPS_ON)
        self.load_image(IMG_GPS_WARN)
        self.load_image(IMG_GPS_ERROR)
        self.load_image(IMG_OBD_OFF)
        self.load_image(IMG_OBD_ON)
        self.load_image(IMG_OBD_ERROR)

        self._fetcher = RedisBackgroundFetcher(self._redis, [])
        self._predis_fetcher = RedisBackgroundFetcher(self._pers_redis, [])
Ejemplo n.º 4
0
    def __init__(self, parent, redis):
        self._redis = redis
        self._fetcher = RedisBackgroundFetcher(redis, [
            NetworkInfoRedisKeys.KEY_ETH0_IP,
            NetworkInfoRedisKeys.KEY_WLAN0_STRENGTH,
            NetworkInfoRedisKeys.KEY_WLAN0_SSID,
            NetworkInfoRedisKeys.KEY_WLAN0_IP,
            NetworkInfoRedisKeys.KEY_WLAN1_STRENGTH,
            NetworkInfoRedisKeys.KEY_WLAN1_SSID,
            NetworkInfoRedisKeys.KEY_WLAN1_IP
        ],
                                               fetch_interval=5)

        self._ethernet_ip = None  # type: Text
        self._wifi0_ip = None  # type: Text
        self._wifi1_ip = None  # type: Text

        CarPiBaseSettingsWindow.__init__(self, parent, 'Network Settings')
Ejemplo n.º 5
0
    def _closeButton_Click(self, e):
        self.exit()

    def _menuButton_Click(self, e):
        self._popup.show((self._menuButton.x, self._menuButton.y - self._popup.height))


if __name__ == '__main__':
    CONFIG = init_config_env('CARPI_UI_CONFIG', ['ui.conf', '/etc/carpi/ui.conf'])
    boot_print(APP_NAME)

    log("Connecting to Redis ...")
    R = get_redis(CONFIG)

    log("Starting Background Data Fetcher ...")
    R_FETCH = RedisBackgroundFetcher(R, RNAME_FETCH_KEYS)
    R_FETCH.start()

    init_pygame()

    log("Loading Assets ...")
    for image in AUTOLOAD_IMAGES:
        IMAGES[image] = load_image(image)

    log("Initializing UI App ...")
    app = GpsApp(rect=(320, 219),
                 title='CarPi GPS',
                 fullscreen=('NO_FULLSCREEN' not in os.environ))
    app.R_FETCH = R_FETCH
    try:
        log("Starting UI App ...")
Ejemplo n.º 6
0
class CarPiUIApp(pqApp):
    PAGE_GPS = 'GPS'
    PAGE_MUSIC = 'Clock'
    PAGE_SETTINGS = 'Settings'

    def __init__(self,
                 rect,
                 redis,
                 pers_redis,
                 title='CarPi',
                 fullscreen=False):
        log("Initializing CarPiUIApp ...")
        pqApp.__init__(self, rect=rect, title=title, fullscreen=fullscreen)

        # Internal Data Storage & Processing
        self.image_store = {}
        self._pages = {}
        self._redis_pages = {}
        self._predis_pages = {}
        self._current_page = None  # type: str
        self._fetcher = None  # type: RedisBackgroundFetcher
        self._predis_fetcher = None  # type: RedisBackgroundFetcher
        self._redis = redis  # type: Redis
        self._pers_redis = pers_redis  # type: Redis

        # Tabs
        self._gps_tab_button = None  # type: Button
        self._music_tab_button = None  # type: Button
        self._settings_tab_button = None  # type: Button

        # Status Icons
        self._gps_status_icon = None  # type: Image
        self._obd_status_icon = None  # type: Image

        # GPS Data
        self._speed_label = None  # type: Text
        self._speed_unit = None  # type: Text
        self._speed_graph = None  # type: Graph
        self._location_label = None  # type: Text

        self._gps_status_icon = None  # type: Image
        self._car_status_icon = None  # type: Image

        # Trip Data
        self._trip_meter = None  # type: Text
        self._odo_meter = None  # type: Text
        self._trip_odo_unit = None  # type: Text

        # Status Bar
        self._ethernet_status_icon = None  # type: Image
        self._wlan0_status_icon = None  # type: Image
        self._time_label = None  # type: Text

        # Music Display
        self._current_title = None  # type: Text
        self._current_artist = None  # type: Text
        self._current_album = None  # type: Text

        # Music Status
        self._current_song_time = None  # type: Text
        self._current_song_time_bar = None  # type: ProgressBar

        # Music Controls
        self._next_song_button = None  # type: Button
        self._prev_song_button = None  # type: Button
        self._play_song_button = None  # type: Button

        # Load Resources
        self._load()

        # Init Controls
        self._init_controls()

        # Define UI Pages
        gps_page = [
            self._speed_label, self._speed_graph, self._speed_unit,
            self._odo_meter, self._trip_meter, self._trip_odo_unit,
            self._location_label
        ]
        music_page = [
            self._current_title, self._current_artist, self._current_album,
            self._current_song_time, self._current_song_time_bar,
            self._next_song_button, self._prev_song_button,
            self._play_song_button
        ]
        settings_page = []

        self._pages[CarPiUIApp.PAGE_GPS] = gps_page
        self._pages[CarPiUIApp.PAGE_MUSIC] = music_page
        self._pages[CarPiUIApp.PAGE_SETTINGS] = settings_page

        # Define Redis Pages
        gps_r_page = [
            # Alive Keys
            GpsRedisKeys.KEY_ALIVE,
            NetworkInfoRedisKeys.KEY_ALIVE,
            MpdDataRedisKeys.KEY_ALIVE,

            # Always present keys
            NetworkInfoRedisKeys.KEY_ETH0_IP,
            NetworkInfoRedisKeys.KEY_WLAN0_STRENGTH,
            NetworkInfoRedisKeys.KEY_WLAN0_SSID,
            NetworkInfoRedisKeys.KEY_WLAN1_STRENGTH,
            NetworkInfoRedisKeys.KEY_WLAN1_SSID,
            GpsRedisKeys.KEY_SPEED,
            GpsRedisKeys.KEY_SPEED_KMH,
            MpdDataRedisKeys.KEY_STATE,

            # OBD & Fuel Consumption
            ObdRedisKeys.KEY_ALIVE,
            ObdRedisKeys.KEY_ENGINE_RPM,
            ObdRedisKeys.KEY_INTAKE_TEMP,
            ObdRedisKeys.KEY_INTAKE_MAP,
            ObdRedisKeys.KEY_VEHICLE_SPEED,

            # Specific Keys
            GpsRedisKeys.KEY_EPX,
            GpsRedisKeys.KEY_EPY
        ]
        music_r_page = [
            # Alive Keys
            GpsRedisKeys.KEY_ALIVE,
            NetworkInfoRedisKeys.KEY_ALIVE,
            MpdDataRedisKeys.KEY_ALIVE,

            # Always present keys
            NetworkInfoRedisKeys.KEY_ETH0_IP,
            NetworkInfoRedisKeys.KEY_WLAN0_STRENGTH,
            NetworkInfoRedisKeys.KEY_WLAN0_SSID,
            NetworkInfoRedisKeys.KEY_WLAN1_STRENGTH,
            NetworkInfoRedisKeys.KEY_WLAN1_SSID,
            GpsRedisKeys.KEY_SPEED,
            GpsRedisKeys.KEY_SPEED_KMH,
            MpdDataRedisKeys.KEY_STATE,

            # OBD & Fuel Consumption
            ObdRedisKeys.KEY_ALIVE,
            ObdRedisKeys.KEY_ENGINE_RPM,
            ObdRedisKeys.KEY_INTAKE_TEMP,
            ObdRedisKeys.KEY_INTAKE_MAP,
            ObdRedisKeys.KEY_VEHICLE_SPEED,

            # Specific Keys
            MpdDataRedisKeys.KEY_SONG_TITLE,
            MpdDataRedisKeys.KEY_SONG_ARTIST,
            MpdDataRedisKeys.KEY_SONG_ALBUM,
            MpdDataRedisKeys.KEY_CURRENT_TIME,
            MpdDataRedisKeys.KEY_CURRENT_TIME_FORMATTED
        ]
        settings_r_page = [
            # Alive Keys
            GpsRedisKeys.KEY_ALIVE,
            NetworkInfoRedisKeys.KEY_ALIVE,
            MpdDataRedisKeys.KEY_ALIVE,

            # Always present keys
            NetworkInfoRedisKeys.KEY_ETH0_IP,
            NetworkInfoRedisKeys.KEY_WLAN0_STRENGTH,
            NetworkInfoRedisKeys.KEY_WLAN0_SSID,
            NetworkInfoRedisKeys.KEY_WLAN1_STRENGTH,
            NetworkInfoRedisKeys.KEY_WLAN1_SSID,
            GpsRedisKeys.KEY_SPEED_KMH,
            MpdDataRedisKeys.KEY_STATE,

            # OBD & Fuel Consumption
            ObdRedisKeys.KEY_ALIVE,
            ObdRedisKeys.KEY_ENGINE_RPM,
            ObdRedisKeys.KEY_INTAKE_TEMP,
            ObdRedisKeys.KEY_INTAKE_MAP,
            ObdRedisKeys.KEY_VEHICLE_SPEED,

            # Specific Keys
        ]

        self._redis_pages[CarPiUIApp.PAGE_GPS] = gps_r_page
        self._redis_pages[CarPiUIApp.PAGE_MUSIC] = music_r_page
        self._redis_pages[CarPiUIApp.PAGE_SETTINGS] = settings_r_page

        # Define Persistent Redis Pages
        self._predis_pages[CarPiUIApp.PAGE_GPS] = PersistentGpsRedisKeys.KEYS
        self._predis_pages[CarPiUIApp.PAGE_MUSIC] = []
        self._predis_pages[CarPiUIApp.PAGE_SETTINGS] = []

    def _load(self):
        self.load_image(IMG_ETHERNET_OFF)
        self.load_image(IMG_ETHERNET)
        self.load_image(IMG_WIFI_OFF)
        self.load_image(IMG_WIFI0)
        self.load_image(IMG_WIFI1)
        self.load_image(IMG_WIFI2)
        self.load_image(IMG_WIFI3)
        self.load_image(IMG_GPS_OFF)
        self.load_image(IMG_GPS_ON)
        self.load_image(IMG_GPS_WARN)
        self.load_image(IMG_GPS_ERROR)
        self.load_image(IMG_OBD_OFF)
        self.load_image(IMG_OBD_ON)
        self.load_image(IMG_OBD_ERROR)

        self._fetcher = RedisBackgroundFetcher(self._redis, [])
        self._predis_fetcher = RedisBackgroundFetcher(self._pers_redis, [])

    def load_image(self, image_path):
        if image_path not in self.image_store:
            self.image_store[image_path] = load_image(image_path)
        else:
            log("Image \"{}\" already loaded".format(image_path))

    def get_image(self, image_path):
        if image_path not in self.image_store:
            log("Image \"{}\" not loaded! Load image before use!".format(
                image_path))
            return None
        else:
            return self.image_store[image_path]

    def _init_controls(self):
        # GPS Data
        self._speed_label = Text(self, ((5, -5), (260, 195)),
                                 '---',
                                 style={
                                     TEXT_FONT: (PATH_FONT_7SEGM, 150)
                                 }).pack()
        self._speed_unit = Text(self, ((255, 5), (260, 195)),
                                'km/h',
                                style={
                                    TEXT_FONT: (PATH_FONT_VCR, 20)
                                }).pack()
        self._speed_graph = Graph(self, ((5, 130), (200, 52)),
                                  data_gap_ms=500,
                                  style={
                                      TEXT_COLOR: (150, 150, 150)
                                  }).pack()
        self._speed_graph.prefill_data()

        self._location_label = Text(self, ((5, 182), (200, 26)),
                                    '---',
                                    style={
                                        TEXT_FONT: (PATH_FONT_VCR, 20)
                                    }).pack()

        # Trip Data
        self._trip_meter = Text(self, ((227, 130), (94, 33)),
                                '----.-',
                                style={
                                    TEXT_FONT: (PATH_FONT_7SEGM, 30)
                                }).pack()

        self._odo_meter = Text(self, ((215, 175), (106, 33)),
                               '------',
                               style={
                                   TEXT_FONT: (PATH_FONT_7SEGM, 30)
                               }).pack()

        self._trip_odo_unit = Text(self, ((297, 158), (28, 19)),
                                   'km',
                                   style={
                                       TEXT_FONT: (PATH_FONT_VCR, 15)
                                   }).pack()

        # Tab Button
        self._gps_tab_button = Button(self, ((5, 205), (50, 30)),
                                      'GPS',
                                      style=STYLE_TAB_BUTTON,
                                      command=self._gps_tab_button_command,
                                      state=0).pack()
        self._music_tab_button = Button(
            self, ((60, 205), (50, 30)),
            'Music',
            style=STYLE_TAB_BUTTON,
            command=self._clock_tab_button_command).pack()
        self._settings_tab_button = Button(
            self, ((115, 205), (50, 30)),
            'Settings',
            style=STYLE_TAB_BUTTON,
            command=self._settings_tab_button_command).pack()

        # Status Bar Icons
        self._ethernet_status_icon = Image(
            self, ((205, 205), (32, 32)),
            self.get_image(IMG_ETHERNET_OFF)).pack()
        self._wlan0_status_icon = Image(self, ((235, 205), (32, 32)),
                                        self.get_image(IMG_WIFI_OFF)).pack()

        # Time Label
        self._time_label = Text(self, ((260, 212), (95, 34)),
                                '--:--',
                                style={
                                    TEXT_FONT: (PATH_FONT_VCR, 20)
                                }).pack()

        # Music Display
        self._current_title = Text(self, ((5, 5), (310, 30)),
                                   '{Title}',
                                   style={
                                       TEXT_FONT: (PATH_FONT_NORA_MEDIUM, 18)
                                   }).pack()
        self._current_artist = Text(self, ((5, 40), (310, 30)),
                                    '{Artist}',
                                    style={
                                        TEXT_FONT: (PATH_FONT_NORA_MEDIUM, 15)
                                    }).pack()
        self._current_album = Text(self, ((5, 60), (310, 30)),
                                   '{Album}',
                                   style={
                                       TEXT_FONT: (PATH_FONT_NORA_MEDIUM, 15)
                                   }).pack()

        # Music Status
        self._current_song_time = Text(self, ((5, 160), (170, 36)),
                                       '--:--/--:--',
                                       style={
                                           TEXT_FONT: (PATH_FONT_VCR, 20)
                                       }).pack()
        self._current_song_time_bar = ProgressBar(self,
                                                  ((5, 190), (310, 5))).pack()

        # Status Icons
        self._gps_status_icon = Image(self, ((255, 90), (32, 32)),
                                      self.get_image(IMG_GPS_OFF)).pack()
        self._obd_status_icon = Image(self, ((287, 90), (32, 32)),
                                      self.get_image(IMG_OBD_OFF)).pack()

        # Music Controls
        music_control_style = {
            TEXT_FONT: (PATH_FONT_DEFAULT, 25),
            TEXT_COLOR: (200, 200, 200)
        }
        self._prev_song_button = Button(self, ((5, 100), (98, 45)),
                                        '<<',
                                        command=self._prev_song_button_command,
                                        style=music_control_style).pack()
        self._play_song_button = Button(self, ((107, 100), (106, 45)),
                                        '> / ||',
                                        command=self._play_song_button_command,
                                        style=music_control_style).pack()
        self._next_song_button = Button(self, ((217, 100), (98, 45)),
                                        '>>',
                                        command=self._next_song_button_command,
                                        style=music_control_style).pack()

    def main(self):
        """
        Runs at startup
        """
        self.show_page(CarPiUIApp.PAGE_GPS)
        self._fetcher.start()
        self._predis_fetcher.start()
        # self._settings_tab_button_command(None)

    def update(self):
        """
        Runs every frame
        """
        self._time_label.settext(
            strftime('%H:%M'))  # Time is the most important thing!

        new_data = self._fetcher.get_current_data()
        new_pers_data = self._predis_fetcher.get_current_data()

        self._update_status(new_data)
        self._set_speed_metrical(
            new_data
        )  # We keep the speed updated at all times so the graph does not lag behind
        self._set_networking_data(
            new_data)  # Networking is kept alive all the time
        self._set_music_player_info(new_data)

        self._set_trip_odo(new_pers_data)

    def shutdown(self):
        try:
            if self.active_window:
                try:
                    self.active_window.destroy()
                finally:
                    pass

            self._fetcher.stop_safe()
            self._predis_fetcher.stop_safe()
            log("Shutting down CarPiUIApp ...")
            self.destroy()
        finally:
            return

    def show_page(self, page_name):
        for name, page in self._pages.iteritems():
            for control in page:  # type: Widget
                if control:
                    control.setvisible(name == page_name)

        self._fetcher.keys_to_fetch = self._redis_pages[page_name]
        self._predis_fetcher.keys_to_fetch = self._predis_pages[page_name]
        self._current_page = page_name

    def _gps_tab_button_command(self, e):
        self._gps_tab_button.setstate(0)
        self._music_tab_button.setstate(1)
        self._settings_tab_button.setstate(1)

        self.show_page(CarPiUIApp.PAGE_GPS)

    def _clock_tab_button_command(self, e):
        self._gps_tab_button.setstate(1)
        self._music_tab_button.setstate(0)
        self._settings_tab_button.setstate(1)

        self.show_page(CarPiUIApp.PAGE_MUSIC)

    def _settings_tab_button_command(self, e):
        # self._gps_tab_button.setstate(1)
        # self._music_tab_button.setstate(1)
        # self._settings_tab_button.setstate(0)
        # self.show_page(CarPiUIApp.PAGE_SETTINGS)
        MainSettingsWindow(self, self._redis, self._pers_redis).show()

    def _prev_song_button_command(self, e):
        send_command_request(self._redis, MpdCommandRedisKeys.COMMAND_PREV)

    def _play_song_button_command(self, e):
        send_command_request(self._redis, MpdCommandRedisKeys.COMMAND_PAUSE)

    def _next_song_button_command(self, e):
        send_command_request(self._redis, MpdCommandRedisKeys.COMMAND_NEXT)

    def _set_gps_status(self, status):
        self._gps_status_icon.setimage(self.get_image(status))

    def _set_obd_status(self, status):
        self._obd_status_icon.setimage(self.get_image(status))

    def _update_status(self, data):
        """
        :param dict of str, str data:
        """
        if GpsRedisKeys.KEY_ALIVE in data:
            if GpsRedisKeys.KEY_SPEED in data and data[GpsRedisKeys.KEY_SPEED]:
                self._set_gps_status(IMG_GPS_ON)
            else:
                self._set_gps_status(IMG_GPS_ERROR)
        else:
            self._set_gps_status(IMG_GPS_OFF)

        if ObdRedisKeys.KEY_ALIVE in data:
            alive_state = data[ObdRedisKeys.KEY_ALIVE]
            if alive_state and alive_state == '1':
                self._set_obd_status(IMG_OBD_ON)
            elif alive_state and alive_state == '0':
                self._set_obd_status(IMG_OBD_ERROR)
            else:
                self._set_obd_status(IMG_OBD_OFF)
        else:
            self._set_obd_status(IMG_OBD_OFF)

    def _set_speed_metrical(self, data):
        """
        :param dict of str, str data:
        """
        speed_str = ''
        if GpsRedisKeys.KEY_SPEED in data and GpsRedisKeys.KEY_SPEED_KMH in data \
                and data[GpsRedisKeys.KEY_SPEED_KMH]:
            speed_str = data[GpsRedisKeys.KEY_SPEED_KMH]
        elif ObdRedisKeys.KEY_VEHICLE_SPEED in data and data[
                ObdRedisKeys.KEY_VEHICLE_SPEED]:
            speed_str = data[ObdRedisKeys.KEY_VEHICLE_SPEED]
        else:
            speed_str = '-1'

        speed = -1
        try:
            speed = float(speed_str)
        except TypeError:
            speed = -1
        self._set_speed(speed)

        if ObdRedisKeys.KEY_ALIVE in data \
                and data[ObdRedisKeys.KEY_ALIVE] == '1' \
                and (ObdRedisKeys.KEY_ENGINE_RPM in data and data[ObdRedisKeys.KEY_ENGINE_RPM]) \
                and (ObdRedisKeys.KEY_INTAKE_MAP in data and data[ObdRedisKeys.KEY_INTAKE_MAP]) \
                and (ObdRedisKeys.KEY_INTAKE_TEMP in data and data[ObdRedisKeys.KEY_INTAKE_TEMP]):
            try:
                fuel_cons = CarPiUIApp._calc_fuel_consumption(
                    float(data[ObdRedisKeys.KEY_INTAKE_TEMP]),
                    float(data[ObdRedisKeys.KEY_ENGINE_RPM]),
                    float(data[ObdRedisKeys.KEY_INTAKE_MAP]), speed)
                if fuel_cons[0] and isnan(fuel_cons[0]):
                    self._set_fuel_consumption(None)
                elif not speed or speed < 20:
                    self._set_fuel_consumption(fuel_cons[0])
                else:
                    self._set_fuel_consumption(fuel_cons[1], True)

                if fuel_cons[0]:
                    self._speed_graph.add_data_point(fuel_cons[0])
            except TypeError:
                self._set_obd_status(IMG_OBD_ERROR)
                self._set_fuel_consumption(None)
                self._speed_graph.add_data_point(0)
        elif GpsRedisKeys.KEY_EPX in data and GpsRedisKeys.KEY_EPY in data\
                and data[GpsRedisKeys.KEY_EPX] and data[GpsRedisKeys.KEY_EPY]:
            self._set_accuracy(float(data.get(GpsRedisKeys.KEY_EPX, '0')),
                               float(data.get(GpsRedisKeys.KEY_EPY, '0')))
        else:
            self._set_accuracy(None, None)

    def _set_fuel_consumption(self, val, in_lp100k=False):
        if not val or val is str:
            self._location_label.settext('{:>6} l/h'.format('--.--'))
        elif in_lp100k:
            self._location_label.settext('{:>6.2f} l/100km'.format(val))
        else:
            self._location_label.settext('{:>6.2f} l/h'.format(val))

    def _set_accuracy(self, epx, epy):
        if not epx or isnan(epx) or not epy or isnan(epy):
            self._location_label.settext('{0:^15}'.format('NO GPS'))
        else:
            self._location_label.settext('{:>4.0f}m / {:>4.0f}m'.format(
                epx, epy).center(15))

    def _set_speed(self, speed):
        """
        :param float speed:
        """
        if isnan(speed) or speed < 0:
            self._speed_label.settext('---')
            #self._speed_graph.add_data_point(0)
        else:
            self._speed_label.settext('{:>3.0f}'.format(speed))
            #self._speed_graph.add_data_point(speed)

    def _set_networking_data(self, data):
        """
        :param dict of str, str data:
        """
        if NetworkInfoRedisKeys.KEY_ETH0_IP in data:
            eth_ip = data[NetworkInfoRedisKeys.KEY_ETH0_IP]
            self._set_ethernet_data(eth_ip is not None
                                    and eth_ip != '127.0.0.1'
                                    and eth_ip != '::1')
        else:
            self._set_ethernet_data(False)

        if NetworkInfoRedisKeys.KEY_WLAN0_STRENGTH in data \
                and NetworkInfoRedisKeys.KEY_WLAN0_SSID in data:
            strength_str = data[NetworkInfoRedisKeys.KEY_WLAN0_STRENGTH]
            ssid = data[NetworkInfoRedisKeys.KEY_WLAN0_SSID]

            strength = -2
            if ssid is not None:
                strength = int(strength_str) if strength_str else 0

            self._set_wlan_data(self._wlan0_status_icon, strength)
        else:
            self._set_wlan_data(self._wlan0_status_icon, -2)

    def _set_ethernet_data(self, connected):
        """
        :param bool connected:
        """
        self._ethernet_status_icon.setimage(
            self.get_image(IMG_ETHERNET if connected else IMG_ETHERNET_OFF))

    def _set_wlan_data(self, wlan_status_image, strength):
        """
        :param Image wlan_status_image:
        :param int strength: -2 for disconnected, -1 for unknown
        """
        image = IMG_WIFI_OFF
        if strength < -1:
            pass  # already set for OFF
        elif strength < 25:
            image = IMG_WIFI0
        elif strength < 50:
            image = IMG_WIFI1
        elif strength < 75:
            image = IMG_WIFI2
        else:
            image = IMG_WIFI3
        wlan_status_image.setimage(self.get_image(image))

    def _set_music_player_info(self, data):
        """
        :param dict data:
        """
        if data.get(MpdDataRedisKeys.KEY_ALIVE, None):
            self._set_current_song_tags(
                unicode(data.get(MpdDataRedisKeys.KEY_SONG_TITLE, ''),
                        'utf-8'),
                unicode(data.get(MpdDataRedisKeys.KEY_SONG_ARTIST, ''),
                        'utf-8'),
                unicode(data.get(MpdDataRedisKeys.KEY_SONG_ALBUM, ''),
                        'utf-8'))
            self._set_current_song_time(
                data.get(MpdDataRedisKeys.KEY_CURRENT_TIME, '0:0'),
                data.get(MpdDataRedisKeys.KEY_CURRENT_TIME_FORMATTED,
                         '--:--/--:--'))
        else:
            self._set_current_song_tags('[Music Player not running]',
                                        'Check MPD or Daemon', None)
            self._set_current_song_time('0:0', '--:--/--:--')

        self._set_player_status(data.get(MpdDataRedisKeys.KEY_STATE, None))

    def _set_current_song_tags(self, title, artist, album):
        self._current_title.settext(title if title else '')
        self._current_artist.settext(artist if artist else '')
        self._current_album.settext(album if album else '')

    def _set_current_song_time(self, num_time, format_time):
        self._current_song_time.settext(format_time)

        cur_time, max_time = get_mpd_status_time(num_time)
        self._current_song_time_bar.set_max_value(max_time)
        self._current_song_time_bar.set_value(cur_time)

    def _set_player_status(self, state):
        play_button_icon = ''
        if state and state == 'play':
            play_button_icon = '||'
        else:
            play_button_icon = '>'
        self._play_song_button.settext(play_button_icon)

    def _set_trip_odo(self, data):
        """
        :param dict data:
        """
        trip_a_str = data.get(PersistentGpsRedisKeys.KEY_TRIP_A, -1)
        try:
            self._set_trip(float(trip_a_str))
        except TypeError:
            self._set_trip(float(-1))

        odo_str = data.get(PersistentGpsRedisKeys.KEY_ODO, -1)
        try:
            self._set_odo(float(odo_str))
        except TypeError:
            self._set_odo(float(-1))

    def _set_trip(self, value):
        if isnan(value) or value < 0:
            self._trip_meter.settext('----.-')
        else:
            self._trip_meter.settext('{:>6.1f}'.format(
                floor(value / 100) / 10))

    def _set_odo(self, value):
        if isnan(value) or value < 0:
            self._odo_meter.settext('------')
        else:
            self._odo_meter.settext('{:>6.0f}'.format(floor(value / 1000)))

    def _network_settings_button_command(self, e):
        CarPiNetworkSettingsWindow(self, self._redis).show()

    def _gps_settings_button_command(self, e):
        pass

    def _music_settings_button_command(self, e):
        pass

    def _power_settings_button_command(self, e):
        CarPiPowerSettingsWindow(self).show()

    @staticmethod
    def _calc_fuel_consumption(intake_temp,
                               rpm,
                               map,
                               speed=None,
                               ve=0.85,
                               vh=1.390,
                               ma=28.9644,
                               r=8.3144598,
                               pf=745):
        """
        Calculates Fuel consumption with the given variables and constants.
        The result is a tuple of ([l/h], [l/100km]).
        Note that if the speed is not given (None) or <1 km/h, fuel efficiency [l/100km]
        will be returned as "None".
        Parameters marked with * are optional
        :param float intake_temp: Intake Air Temperature in [Degrees Celsius]
        :param float rpm: Engine RPM in [RPM]
        :param float map: Intake Manifold Absolute Pressure in [kPa]
        :param float speed: *Speed in [km/h] (or 0 or None to remove fuel efficiency)
        :param float ve: *Volumetric Efficiency (defined as a percentage value, 0 - 1 (100%)), default: 85%
        :param float vh: *Engine Capacity in [l] ([m^3] / 1000), default: 1.39 l
        :param float ma: *avg. molecular mass of air [g/mol], default 28.9644 g/mol
        :param float r: *Gas constant, default 8.3144598 J/(mol.K)
        :param float pf: *Fuel density in [g/l], default 745 g/l (after Super E10, to be adjusted based on fuel type)
        :return tuple of float, float:
        """
        intake_temp_k = intake_temp + 273.15
        imap = rpm * map / intake_temp_k
        maf = (imap / 120) * ve * vh * ma / r

        cons_p_s = (maf / 14.7) / pf
        cons_p_h = cons_p_s * 3600

        if speed and speed >= 1:
            return cons_p_h, cons_p_h / speed * 100
        else:
            return cons_p_h, None
Ejemplo n.º 7
0
class GpsTripSettingsWindow(CarPiBaseSettingsWindow):
    def __init__(self, parent, temp_redis, persist_redis):
        self._temp_redis = temp_redis
        self._persist_redis = persist_redis

        self._fetcher = RedisBackgroundFetcher(persist_redis, [
            PersistentGpsRedisKeys.KEY_TRIP_A,
            PersistentGpsRedisKeys.KEY_TRIP_B, PersistentGpsRedisKeys.KEY_ODO
        ],
                                               fetch_interval=1)

        self._trip_a_text = None  # type: Text
        self._trip_b_text = None  # type: Text
        self._odo_text = None  # type: Text

        CarPiBaseSettingsWindow.__init__(self, parent, 'GPS & Trip Settings')

    def _init_controls(self):
        rec_trip = get_piped(self._persist_redis,
                             [PersistentGpsRedisKeys.KEY_TRIP_A_RECORDING])

        self._init_options(
            self, [('Reset Trip A', self._reset_trip_a_callback), None,
                   ('Reset Trip B', self._reset_trip_b_callback), None,
                   ('ODO Correction', self._correct_odo_callback), None,
                   ('Start New Trip', self._new_trip_callback),
                   ('Stop Recording', self._stop_recording_callback)
                   if PersistentGpsRedisKeys in rec_trip else None,
                   ('< Back', self._back_callback), None])

        self._trip_a_text = Text(self, ((165, 10), (152, 32)),
                                 '',
                                 style={
                                     TEXT_FONT: (PATH_FONT_VCR, 20)
                                 }).pack()
        self._trip_b_text = Text(self, ((165, 50), (152, 32)),
                                 '',
                                 style={
                                     TEXT_FONT: (PATH_FONT_VCR, 20)
                                 }).pack()
        self._odo_text = Text(self, ((165, 90), (152, 32)),
                              '',
                              style={
                                  TEXT_FONT: (PATH_FONT_VCR, 20)
                              }).pack()

        self._set_distance(self._trip_a_text, 0)
        self._set_distance(self._trip_b_text, 0)
        self._set_distance(self._odo_text, 0)

        self._fetcher.start()

    def _empty_callback(self, e):
        pass

    def update(self):
        new_data = self._fetcher.get_current_data()

        self._set_distance(
            self._trip_a_text,
            float(new_data.get(PersistentGpsRedisKeys.KEY_TRIP_A, '0')))
        self._set_distance(
            self._trip_b_text,
            float(new_data.get(PersistentGpsRedisKeys.KEY_TRIP_B, '0')))
        self._set_distance(
            self._odo_text,
            float(new_data.get(PersistentGpsRedisKeys.KEY_ODO, '0')))

    def _set_distance(self, label, value):
        label.settext('{:>9.2f} km'.format(value / 1000))

    def destroy(self):
        self._fetcher.stop_safe()
        super(GpsTripSettingsWindow, self).destroy()

    def _reset_trip_a_callback(self, e):
        set_piped(self._persist_redis, {PersistentGpsRedisKeys.KEY_TRIP_A: 0})

    def _reset_trip_b_callback(self, e):
        set_piped(self._persist_redis, {PersistentGpsRedisKeys.KEY_TRIP_B: 0})

    def _correct_odo_callback(self, e):
        OdoCorrectionWindow(self, self._persist_redis).show()

    def _new_trip_callback(self, e):
        save_synced_value(self._temp_redis, self._persist_redis,
                          PersistentGpsRedisKeys.KEY_TRIP_A_RECORDING,
                          '999999')
        self._reset_trip_a_callback(e)

    def _stop_recording_callback(self, e):
        save_synced_value(self._temp_redis, self._persist_redis,
                          PersistentGpsRedisKeys.KEY_TRIP_A_RECORDING, None)