diff --git a/Ccs/ccs_function_lib.py b/Ccs/ccs_function_lib.py index dc787ffa0bec2564f203c9ea6db1dd5df4764bd2..4f00ecc77ed3963e681a10a52eafbcadf71636f2 100644 --- a/Ccs/ccs_function_lib.py +++ b/Ccs/ccs_function_lib.py @@ -1503,7 +1503,7 @@ def get_pool_rows(pool_name, dbcon=None): return rows # get values of parameter from HK packets -def get_param_values(tmlist=None, hk=None, param=None, last=0, numerical=False, dbcon=None): +def get_param_values(tmlist=None, hk=None, param=None, last=0, numerical=False): # with self.poolmgr.lock: dbcon = scoped_session_idb if hk is None: diff --git a/Ccs/poolview_sql.py b/Ccs/poolview_sql.py index bf6d80db1dc0f795c7430af95e48e7aa471cc3b6..d2988fab1187e76a232c1ee402d9314dcffba033 100644 --- a/Ccs/poolview_sql.py +++ b/Ccs/poolview_sql.py @@ -140,6 +140,7 @@ class TMPoolView(Gtk.Window): #if not pool_name: # self.active_pool_info = ActivePoolInfo(None,None,None,None) + self.refresh_treeview_active = False self.cnt = 0 self.active_pool_info = ActivePoolInfo(None, None, None, None) self.set_border_width(2) @@ -589,7 +590,7 @@ class TMPoolView(Gtk.Window): self.treeview = Gtk.TreeView() self.treeview.set_model(self.pool_liststore) - self.treeview.set_rubber_banding(True) + self.treeview.set_rubber_banding(False) self.treeview.set_activate_on_single_click(True) # self.treeview.set_fixed_height_mode(True) @@ -682,9 +683,9 @@ class TMPoolView(Gtk.Window): def set_number_of_treeview_rows(self, widget=None, allocation=None): # alloc = widget.get_allocation() height = self.treeview.get_allocated_height() - cell = self.treeview.get_columns()[0].cell_get_size()[-1] + 2 + cell = 25 #self.treeview.get_columns()[0].cell_get_size()[-1] + 2 nlines = height // cell - self.adj.set_page_size(nlines-4) + self.adj.set_page_size(nlines - 1) # self._scroll_treeview() self.reselect_rows() @@ -1357,7 +1358,6 @@ class TMPoolView(Gtk.Window): self.shown_lock.release() - ''' running = True self.shown_lock.acquire() @@ -1502,7 +1502,7 @@ class TMPoolView(Gtk.Window): # print(event.direction.value_name, event.delta_x, event.delta_y) self.only_scroll = True if event.direction.value_name == 'GDK_SCROLL_SMOOTH': - scroll_lines = 3 * event.delta_y + scroll_lines = 3 * max(-1, event.delta_y) if scroll_lines < 0: self.autoscroll = 0 elif scroll_lines > 3: @@ -1546,28 +1546,32 @@ class TMPoolView(Gtk.Window): if scroll_lines == -int(self.adj.get_page_size()): self.offset -= int(self.adj.get_page_size()) else: - self.offset = self.shown_all_rows[int(position + scroll_lines)][0] if (position + scroll_lines) > 0 else 0 + self.offset = self.shown_all_rows[int(position + scroll_lines)][0] if (position + scroll_lines) >= 0 else 0 else: if len(self.shown_all_rows) < (self.shown_limit): - self.offset = self.shown_all_rows[-self.adj.get_page_size()][0] + self.offset = self.shown_all_rows[-int(self.adj.get_page_size())][0] else: - self.offset = self.shown_all_rows[int(position + scroll_lines)][0] if (position + scroll_lines) > 0 else 0 - except: - upper_limit = self.adj.get_upper() - self.adj.get_page_size() + self.offset = self.shown_all_rows[int(position + scroll_lines)][0] if (position + scroll_lines) >= 0 else 0 + except IndexError: + upper_limit = max(0, self.adj.get_upper() - self.adj.get_page_size()) self.offset = int(min(upper_limit, self.adj.get_value() + scroll_lines)) + if self.offset < 0: + return + self.limit = int(self.adj.get_page_size()) - #self.feed_lines_to_view( - # self.fetch_lines_from_db(self.offset, self.limit, sort=sort, order=order, rows=rows, force_import=force_db_import)) self.fetch_lines_from_db(self.offset, self.limit, sort=sort, order=order, rows=rows, scrolled=True, force_import=force_db_import) self.adj.set_value(self.offset) def key_pressed(self, widget=None, event=None): - def unselect_rows(): + def unselect_rows(clear=False): # selection = widget.get_selection() # self.selection.disconnect_by_func(self.tree_selection_changed) - model, paths = self.selection.get_selected_rows() - self.currently_selected = {model[path][0] for path in paths} + if clear: + self.currently_selected = set() + else: + model, paths = self.selection.get_selected_rows() + self.currently_selected = {model[path][0] for path in paths} self.reselect_rows() # self.selection.connect('changed', self.tree_selection_changed) @@ -1610,17 +1614,19 @@ class TMPoolView(Gtk.Window): self.autoscroll = True self.autoselect = True self.scroll_to_bottom() - unselect_rows() + unselect_rows(clear=True) elif event.keyval == Gdk.KEY_Page_Up: # cursor_path = self.treeview.get_cursor()[0] self._scroll_treeview(-self.limit) - self.treeview.set_cursor(cursor_path) + if cursor_path is not None: + self.treeview.set_cursor(cursor_path) self.autoscroll = False unselect_rows() elif event.keyval == Gdk.KEY_Page_Down: # cursor_path = self.treeview.get_cursor()[0] self._scroll_treeview(self.limit) - self.treeview.set_cursor(cursor_path) + if cursor_path is not None: + self.treeview.set_cursor(cursor_path) self.autoscroll = False unselect_rows() # else: @@ -1669,9 +1675,9 @@ class TMPoolView(Gtk.Window): try: self.selection.select_path(model.get_path(model.get_iter(row[0] - self.offset - 1))) except ValueError: - pass + print('valerr') except TypeError: - pass + print('typerr') def unselect_bottom(self, widget=None): if widget.count_selected_rows() > 1: @@ -1916,41 +1922,41 @@ class TMPoolView(Gtk.Window): #self._on_scrollbar_changed() pass - def resize_scrollbar(self): - - if self.first_run or self.resize_thread.is_alive(): - self.first_run = False - self.resize_thread = threading.Thread(target=self.small_refresh_function) - return - - self.resize_thread = threading.Thread(target=self.scrollbar_size_worker) - self.resize_thread.setDaemon(True) - self.resize_thread.start() - - def scrollbar_size_worker(self): - #print(1) - new_session = self.session_factory_storage - rows = new_session.query( - Telemetry[self.decoding_type] - ).join( - DbTelemetryPool, - Telemetry[self.decoding_type].pool_id == DbTelemetryPool.iid - ).filter( - DbTelemetryPool.pool_name == self.active_pool_info.filename - ) - #new_session.close() - cnt = rows.count() - #print(cnt) - rows = self._filter_rows(rows) - cnt = rows.count() - #count_q = que.statement.with_only_columns([func.count()]).order_by(None) - #cnt = new_session.execute(count_q).scalar() - #cnt = new_session.query(que).count() - #print(2) - #print(cnt) - GLib.idle_add(self.adj.set_upper, cnt,) - #print(3) - new_session.close() + # def resize_scrollbar(self): + # + # if self.first_run or self.resize_thread.is_alive(): + # self.first_run = False + # self.resize_thread = threading.Thread(target=self.small_refresh_function) + # return + # + # self.resize_thread = threading.Thread(target=self.scrollbar_size_worker) + # self.resize_thread.setDaemon(True) + # self.resize_thread.start() + # + # def scrollbar_size_worker(self): + # #print(1) + # new_session = self.session_factory_storage + # rows = new_session.query( + # Telemetry[self.decoding_type] + # ).join( + # DbTelemetryPool, + # Telemetry[self.decoding_type].pool_id == DbTelemetryPool.iid + # ).filter( + # DbTelemetryPool.pool_name == self.active_pool_info.filename + # ) + # #new_session.close() + # cnt = rows.count() + # #print(cnt) + # rows = self._filter_rows(rows) + # cnt = rows.count() + # #count_q = que.statement.with_only_columns([func.count()]).order_by(None) + # #cnt = new_session.execute(count_q).scalar() + # #cnt = new_session.query(que).count() + # #print(2) + # #print(cnt) + # GLib.idle_add(self.adj.set_upper, cnt,) + # #print(3) + # new_session.close() def _toggle_rule(self, widget=None, data=None): self.filter_rules_active = widget.get_active() @@ -2166,26 +2172,11 @@ class TMPoolView(Gtk.Window): if pool_name is None: return - #self.pool._clear_pool(pool_name) - #self.active_pool_info = self.pool.loaded_pools[pool_name] poolmgr.Functions('_clear_pool', pool_name) # self.active_pool_info = poolmgr.Dictionaries('loaded_pools', pool_name) self.Active_Pool_Info_append(poolmgr.Dictionaries('loaded_pools', pool_name)) + self.offset = 0 - # new_session = self.dbcon - # new_session.execute( - # 'UPDATE tm_pool SET pool_name="---TO-BE-DELETED---" WHERE tm_pool.pool_name="{}"'.format( - # self.get_active_pool_name())) - # new_session.commit() - # - # # new_session.execute( - # # 'delete tm from tm inner join tm_pool on tm.pool_id=tm_pool.iid where tm_pool.pool_name="{}"'.format( - # # self.active_pool_info.filename)) - # # new_session.execute('delete tm_pool from tm_pool where tm_pool.pool_name="{}"'.format( - # # self.active_pool_info.filename)) - # # # new_session.flush() - # # new_session.commit() - # new_session.close() self.adj.set_upper(self.count_current_pool_rows()) self._on_scrollbar_changed() widget.set_sensitive(True) @@ -2587,6 +2578,9 @@ class TMPoolView(Gtk.Window): datamodel.clear() return + if selection is None: + return + model, treepath = selection.get_selected_rows() if len(treepath) == 0: @@ -3233,9 +3227,10 @@ class TMPoolView(Gtk.Window): return def refresh_treeview(self, pool_name): - # thread = threading.Thread(target=self.refresh_treeview_worker, args=[pool_name]) - # thread.daemon = True - # thread.start() + if self.refresh_treeview_active: + return + + self.refresh_treeview_active = True self.n_pool_rows = 0 GLib.timeout_add(self.pool_refresh_rate * 1000, self.refresh_treeview_worker2, pool_name) # , priority=GLib.PRIORITY_HIGH) @@ -3257,36 +3252,23 @@ class TMPoolView(Gtk.Window): def refresh_treeview_worker2(self, pool_name): if pool_name != self.active_pool_info.pool_name: + self.refresh_treeview_active = False return False - #if not self.active_pool_info.live: - # return False - #if cfl.is_open('poolmanager', cfl.communication['poolmanager']): - # poolmgr = cfl.dbus_connection('poolmanager', cfl.communication['poolmanager']) - #else: - # return False - - # Get value of dict connections, with key self.active... and key recording, True to get - #pool_connection_recording = poolmgr.Dictionaries('connections', self.active_pool_info.pool_name, 'recording', - # True) - #pool_connection = poolmgr.Dictionaries('connections', self.active_pool_info.pool_name) if self.active_pool_info.live: - #if self.pool.connections[self.active_pool_info.pool_name]['recording']: rows = self.get_current_pool_rows() if rows.first() is None: cnt = 0 else: cnt = rows.order_by(Telemetry[self.decoding_type].idx.desc()).first().idx if cnt != self.n_pool_rows: - # self.selection.disconnect_by_func(self.tree_selection_changed) self.scroll_to_bottom(n_pool_rows=cnt, rows=rows) - # self.selection.connect('changed', self.tree_selection_changed) self.n_pool_rows = cnt return True else: return True else: - #self.stop_recording() + self.refresh_treeview_active = False return False def dbtest(self, pool_name, sleep=0.1): @@ -3353,7 +3335,7 @@ class TMPoolView(Gtk.Window): trashbytes = 0 ''' if not self.active_pool_info.live: - return + return False if not instance: instance = 1 diff --git a/Ccs/pus_datapool.py b/Ccs/pus_datapool.py index 0346e7ceb7f5f5fe6f6122c54f4c0b66f1e70935..9790fe42fb5d6e8aaf4060388aee39de0097bef6 100644 --- a/Ccs/pus_datapool.py +++ b/Ccs/pus_datapool.py @@ -1,24 +1,21 @@ -import datetime +# import datetime import io -import signal -import socket -import struct +# import signal +# import socket +# import struct import sys import time import os import datetime import socket -import select +# import select import crcmod import struct -# from bitstring import BitArray, BitStream, Bits, ConstBitStream, ReadError -import traceback +# import traceback import DBus_Basic import dbus import dbus.service from dbus.mainloop.glib import DBusGMainLoop -#cfl.Tcsend_DB('SASW ModHkPeriodCmd', 1, 8, pool_name='new_tmtc_pool') -import configparser import confignator import gi @@ -321,14 +318,14 @@ class DatapoolManager: finally: new_session.close() - def _clear_pool(self, pool_name): # TODO: not working + def _clear_pool(self, pool_name): + if pool_name not in self.connections: self.logger.warning('Cannot clear static pool "{}".'.format(pool_name)) return + new_session = self.session_factory_storage - # get protocol type - pkttype = self.loaded_pools[pool_name].packet_type - if self.connections[pool_name]['socket'].fileno() < 0: + if self.connections[pool_name]['socket'].fileno() < 0: # if true, socket is closed, just "delete" pool n_del_pools, = new_session.execute( 'SELECT COUNT(*) FROM tm_pool WHERE pool_name LIKE "---TO-BE-DELETED%"').fetchall()[0] new_session.execute( @@ -338,12 +335,25 @@ class DatapoolManager: new_session.close() self.logger.info('Content of pool "{}" deleted!'.format(pool_name)) return + self.connections[pool_name]['paused'] = True while self.connections[pool_name]['recv-thread'].is_alive(): time.sleep(0.1) sockfd = self.connections[pool_name]['socket'] - self.tm_recv_start(sockfd, pool_name, try_delete=False) + protocol = self.connections[pool_name]['protocol'] + + if protocol == 'SPW': + self.spw_recv_start(sockfd, pool_name, try_delete=False, force_clean=True) + elif protocol in ['PUS', 'PLMSIM']: + self.tm_recv_start(sockfd, pool_name, protocol=protocol, try_delete=False, force_clean=True) + else: + self.logger.warning('"{}" is not a supported protocol, aborting.'.format(protocol)) + return + + # self.tm_recv_start(sockfd, pool_name, try_delete=False) + self.logger.info('Content of pool "{}" deleted!'.format(pool_name)) + while True: dbrow = new_session.query(DbTelemetryPool).filter(DbTelemetryPool.pool_name == pool_name).first() if dbrow is None: @@ -354,6 +364,7 @@ class DatapoolManager: timestamp = dbrow.modification_time new_session.close() break + self.loaded_pools[pool_name] = ActivePoolInfo(pool_name, timestamp, pool_name, True) self.logger.info('Resuming recording from {}:{}'.format(*sockfd.getpeername())) @@ -391,7 +402,7 @@ class DatapoolManager: try: sockfd.connect((host, port)) except ConnectionRefusedError: - self.logger.error("Connection to {}:{} refused".format(host, port)) + self.logger.warning("Connection to {}:{} refused".format(host, port)) return self.connections[pool_name] = {'socket': sockfd, 'recording': True, 'protocol': protocol} @@ -568,7 +579,7 @@ class DatapoolManager: if self.own_gui: self.own_gui.disconnect_incoming_via_code(param=[pool_name, None, None]) # Updates the gui - #Tell the Poolviewer to stop updating + # Tell the Poolviewer to stop updating if cfl.is_open('poolviewer', cfl.communication['poolviewer']): pv = cfl.dbus_connection('poolviewer', cfl.communication['poolviewer']) cfl.Functions(pv, 'stop_recording_info', str(pool_name)) @@ -588,7 +599,7 @@ class DatapoolManager: self.tc_connections[pool_name]['socket'].close() del self.tc_connections[pool_name] - #Tell the Poolviewer to stop updating + # Tell the Poolviewer to stop updating if cfl.is_open('poolviewer', cfl.communication['poolviewer']): pv = cfl.dbus_connection('poolviewer', cfl.communication['poolviewer']) cfl.Functions(pv, 'stop_recording_info', str(pool_name)) @@ -599,9 +610,14 @@ class DatapoolManager: return datetime.datetime.utcnow().strftime("%Y-%m-%d %T UTC: ") def tm_recv_start(self, sockfd, pool_name, protocol='PUS', drop_rx=False, drop_tx=False, - delete_abandoned=False, try_delete=True, pckt_filter=None): + delete_abandoned=False, try_delete=True, pckt_filter=None, force_clean=False): - self.tm_receiver_del_old_pool(pool_name, delete_abandoned=delete_abandoned, try_delete=try_delete) + if pool_name in self.loaded_pools and self.loaded_pools[pool_name].live and not force_clean and pool_name in self.state: + self.logger.info('Pool "{}" is live. Skipping deletion of previous data.') + start_new = False + else: + self.tm_receiver_del_old_pool(pool_name, delete_abandoned=delete_abandoned, try_delete=try_delete) + start_new = True self.connections[pool_name]['paused'] = False @@ -612,7 +628,9 @@ class DatapoolManager: 'protocol': protocol, 'drop_rx': drop_rx, 'drop_tx': drop_tx, - 'pckt_filter': pckt_filter}) + 'pckt_filter': pckt_filter, + 'start_new': start_new}) + thread.daemon = True thread.name = '{}-tm_recv_worker'.format(pool_name) # thread.stopRecording = False @@ -621,21 +639,21 @@ class DatapoolManager: thread.start() return thread - def tm_recv_worker(self, sockfd, pool_name, protocol='PUS', drop_rx=False, drop_tx=False, pckt_filter=None): + def tm_recv_worker(self, sockfd, pool_name, protocol='PUS', drop_rx=False, drop_tx=False, pckt_filter=None, start_new=True): host, port = sockfd.getpeername() # Check if a Pool has already been started with only TC - start_new = True - if pool_name in self.loaded_pools: - if self.loaded_pools[pool_name].live: - start_new = False - if not pool_name in self.state: - start_new = True + # start_new = True + # if pool_name in self.loaded_pools: + # if self.loaded_pools[pool_name].live: + # start_new = False + # if not pool_name in self.state: + # start_new = True new_session = self.session_factory_storage + # If no TC Pool has been started start new one if start_new: - pool_row = DbTelemetryPool( pool_name=pool_name, modification_time=time.time(), @@ -810,7 +828,7 @@ class DatapoolManager: self.logger.warning('Disconnected from ' + str(host) + ':' + str(port)) sockfd.close() - def tm_receiver_del_old_pool(self, pool_name, delete_abandoned=False, try_delete=True): + def tm_receiver_del_old_pool(self, pool_name, delete_abandoned=False, try_delete=True, force=False): new_session = self.session_factory_storage pool_row = new_session.query(DbTelemetryPool).filter(DbTelemetryPool.pool_name == pool_name).first() if pool_row: @@ -824,10 +842,10 @@ class DatapoolManager: if pool_name in self.state: del self.state[pool_name] - # If the pool is started by TC do not delete - elif pool_name in self.loaded_pools: - if self.loaded_pools[pool_name].live: - return + # If the pool is started by TC do not delete //MM: this is taken care of outside this function + # elif pool_name in self.loaded_pools: + # if self.loaded_pools[pool_name].live: + # return if rows_in_pool < 1000 and try_delete: new_session.execute( @@ -1596,7 +1614,7 @@ class DatapoolManager: delete_thread.start() new_session.close() - def spw_recv_start(self, sockfd, pool_name, drop_rx=False, delete_abandoned=False, try_delete=True): + def spw_recv_start(self, sockfd, pool_name, drop_rx=False, delete_abandoned=False, try_delete=True, force_clean=False): # delete existing pool rows self.spw_receiver_del_old_pool(pool_name, delete_abandoned=delete_abandoned, try_delete=try_delete)