def __init__(self, parent):

        # Basic Construction stuff
        super().__init__(parent)
        self.app_data = AppData()
        self._output_garbage_collector = 0
        self._input_matrix_enabled = False

        # Create modbus instance, to have access to its props
        instance = ModbusConnectionThreadSingleton()
        self.modbus = instance.thread_instance_get()

        # Create content for
        self.input_matrix = InputArray(parent=self, title='Associated inputs:',
                                       dimension=(3, 5),
                                       col_titles=['1', '2', '3', '4', '5'],
                                       row_titles=['X1', 'X2', 'X3'])

        self.inner_panel_sizer = wx.BoxSizer(wx.VERTICAL)
        self.inner_panel_sizer.Add(self.input_matrix, 0, wx.ALL | wx.ALIGN_CENTER, 10)
        self.SetSizer(self.inner_panel_sizer)

        self.input_matrix.disable()
        self.app_data.iface_output_handler_register(self._matrix_visibility_update)
        for instance in self.input_matrix.instance_array:
            self.Bind(wx.EVT_CHECKBOX, self._checkbox_pressed_handle, instance.cell_instance.checkbox)
Пример #2
0
class TopRightPanel(wx.Panel):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.app_data = AppData()

        self.modbus = ModbusConnectionThreadSingleton()
        self.modbus = self.modbus.thread_instance_get()

        self.input_matrix = InputArray(parent=self,
                                       title='Inputs state:',
                                       interface=DISPLAY_INTERFACE,
                                       dimension=(3, 5),
                                       col_titles=['1', '2', '3', '4', '5'],
                                       row_titles=['X1', 'X2', 'X3'])

        inner_panel_sizer = wx.BoxSizer(wx.VERTICAL)
        inner_panel_sizer.Add(self.input_matrix, 0, wx.ALL | wx.CENTER, 15)

        self.app_data.iface_output_handler_register(self._inputs_state_update)

        self.SetSizer(inner_panel_sizer)

    def _inputs_state_update(self):
        for i in range(15):
            self.input_matrix.value_set_by_index(
                i, self.app_data.input_state_get(i))
    def __init__(self, parent=None):
        super().__init__(parent)
        self.app_data = AppData()
        self._input_matrix_enabled = False
        self._in_matrix_update_stage = 0

        self.modbus = ModbusConnectionThreadSingleton()
        self.modbus = self.modbus.thread_instance_get()

        self.input_matrix = InputArray(parent=self,
                                       title='Inputs mode toggle:',
                                       interface=INPUT_INTERFACE,
                                       dimension=(3, 5),
                                       col_titles=['1', '2', '3', '4', '5'],
                                       row_titles=['X1', 'X2', 'X3'])

        inner_panel_sizer = wx.BoxSizer(wx.VERTICAL)
        inner_panel_sizer.Add(self.input_matrix, 0, wx.ALL | wx.CENTER, 15)

        self.input_matrix.disable()
        self.app_data.iface_conn_handler_register(
            self._matrix_initial_data_setup)
        self.app_data.iface_output_handler_register(
            self._matrix_visibility_update)
        self.app_data.iface_input_handler_register(self._in_matrix_data_gather)

        self.SetSizer(inner_panel_sizer)

        for instance in self.input_matrix.instance_array:
            self.Bind(wx.EVT_CHECKBOX, self._checkbox_pressed_handle,
                      instance.cell_instance.checkbox)
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.main_sizer = wx.BoxSizer(wx.VERTICAL)
        inner_sizer = wx.BoxSizer(wx.HORIZONTAL)

        self.modbus_label = ' '
        self.conn_static_text = wx.StaticText(parent=self,
                                              label='Connection status')
        self.modbus_status_text = wx.StaticText(parent=self, label='')

        inner_sizer.Add(self.conn_static_text, 2, wx.LEFT | wx.ALIGN_LEFT, 10)
        inner_sizer.Add(self.modbus_status_text, 4, wx.LEFT | wx.ALIGN_LEFT,
                        120)

        self.main_sizer.Add(inner_sizer, 1, wx.ALL | wx.EXPAND, 2)

        self.appdata = AppData()
        self.modbus = ModbusConnectionThreadSingleton().modbus_comm_instance
        self.SetSizer(self.main_sizer)

        self.appdata.iface_output_handler_register(self._conn_status_update)
        self.appdata.iface_output_handler_register(self._modbus_data_update)

        self.status = 1
        self.conn_static_text.SetLabel(self.STATUSES[self.status])
Пример #5
0
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # Define two singletones, containing data to share across application
        self.app_settings = Settings()
        self.app_settings.settings_load()
        self.app_data = AppData()
        self.modbus_singleton = None

        # Create a gui application with main frame
        self.gui = GuiApp(size=(439, 550), title="Light Controller")

        # Create threads
        self.modbus_singleton = ModbusConnectionThreadSingleton()
        self.modbus_connection = self.modbus_singleton.modbus_comm_instance
        self.modbus_connection.daemon = True

        self.poll_thread = threading.Thread(target=self._app_settings_poll)
        self.poll_thread.daemon = True

        self.main_logic_thread = threading.Thread(
            target=self._main_logic_handler)
        self.main_logic_thread.daemon = True

        self.data_thread = threading.Thread(target=self._modbus_data_handler)
        self.data_thread.daemon = True

        self.conn_state_prev = None
        self.app_stage = 0
class StatusPanel(wx.Panel):

    STATUSES = {0: 'Connected', 1: 'Disconnected', 2: 'Connection timeout'}

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.main_sizer = wx.BoxSizer(wx.VERTICAL)
        inner_sizer = wx.BoxSizer(wx.HORIZONTAL)

        self.modbus_label = ' '
        self.conn_static_text = wx.StaticText(parent=self,
                                              label='Connection status')
        self.modbus_status_text = wx.StaticText(parent=self, label='')

        inner_sizer.Add(self.conn_static_text, 2, wx.LEFT | wx.ALIGN_LEFT, 10)
        inner_sizer.Add(self.modbus_status_text, 4, wx.LEFT | wx.ALIGN_LEFT,
                        120)

        self.main_sizer.Add(inner_sizer, 1, wx.ALL | wx.EXPAND, 2)

        self.appdata = AppData()
        self.modbus = ModbusConnectionThreadSingleton().modbus_comm_instance
        self.SetSizer(self.main_sizer)

        self.appdata.iface_output_handler_register(self._conn_status_update)
        self.appdata.iface_output_handler_register(self._modbus_data_update)

        self.status = 1
        self.conn_static_text.SetLabel(self.STATUSES[self.status])

    def _conn_status_update(self):
        if self.modbus.is_connected:
            status = 0
            if self.modbus.exception_state_get():
                status = 2
        else:
            status = 1
        if status != self.status:
            self.status = status
            try:
                self.conn_static_text.SetLabel(self.STATUSES[self.status])
            except RuntimeError:
                pass

    def _modbus_data_update(self):
        label = 'Port: ' + str(self.modbus.port) + '; ' + str(self.modbus.baudrate) + '-' + \
                str(self.modbus.bytesize) + '-' + str(self.modbus.parity) + '-' + \
                str(self.modbus.stopbits)
        if label != self.modbus_label:
            self.modbus_label = label
            try:
                self.modbus_status_text.SetLabel(self.modbus_label)
            except RuntimeError:
                pass
class TopLeftPanel(wx.Panel):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.app_data = AppData()
        self._input_matrix_enabled = False
        self._in_matrix_update_stage = 0

        self.modbus = ModbusConnectionThreadSingleton()
        self.modbus = self.modbus.thread_instance_get()

        self.input_matrix = InputArray(parent=self,
                                       title='Inputs mode toggle:',
                                       interface=INPUT_INTERFACE,
                                       dimension=(3, 5),
                                       col_titles=['1', '2', '3', '4', '5'],
                                       row_titles=['X1', 'X2', 'X3'])

        inner_panel_sizer = wx.BoxSizer(wx.VERTICAL)
        inner_panel_sizer.Add(self.input_matrix, 0, wx.ALL | wx.CENTER, 15)

        self.input_matrix.disable()
        self.app_data.iface_conn_handler_register(
            self._matrix_initial_data_setup)
        self.app_data.iface_output_handler_register(
            self._matrix_visibility_update)
        self.app_data.iface_input_handler_register(self._in_matrix_data_gather)

        self.SetSizer(inner_panel_sizer)

        for instance in self.input_matrix.instance_array:
            self.Bind(wx.EVT_CHECKBOX, self._checkbox_pressed_handle,
                      instance.cell_instance.checkbox)

    def _checkbox_pressed_handle(self, event):
        self.app_data.user_interaction = True

    def _matrix_initial_data_setup(self):
        for i in range(15):
            toggle = self.app_data.input_trigger_type_is_toggle_get(i)
            self.input_matrix.value_set_by_index(i, toggle)

    def _matrix_visibility_update(self):
        if self.modbus.is_connected:
            if self._input_matrix_enabled is False:
                self.input_matrix.enable()
                self._input_matrix_enabled = True
        else:
            if self._input_matrix_enabled is True:
                self.input_matrix.disable()
                self._input_matrix_enabled = False

    def _in_matrix_data_gather(self):
        val_list = []
        for in_id in range(15):
            value = self.input_matrix.value_get_by_index(in_id)
            val_list.append(value)

        self.app_data.input_trigger_type_is_toggle_set_mask(val_list)
 def __init__(self):
     # API ENDPOINT
     self.app_data = AppData()
     self.app_data.read_data()
     self.current_bets = []
     self.mother = BetAccount(self.app_data.account_mother_name, self.app_data.account_mother_pass)
     self.sons = []
     for son_data in self.app_data.accounts_son:
         son = BetAccount(son_data['name'], son_data['pass'])
         self.sons.append(son)
     # self.monitor_process = multiprocessing.Process(target=self.monitor)
     self.monitor_thread = None
Пример #9
0
    def __init__(self, parent=None):

        super().__init__(parent=parent)

        self.app_data = AppData()

        self.modbus = ModbusConnectionThreadSingleton()
        self.modbus = self.modbus.thread_instance_get()

        self.btm_page_sizer = wx.BoxSizer(wx.HORIZONTAL)
        self.notebook_sizer = wx.BoxSizer(wx.HORIZONTAL)

        self.notebook = wx.Notebook(self)
        self.sub_canvases = list()
        for i in range(8):
            self.sub_canvases.append(_BtmSubPanel(parent=self.notebook))
            self.notebook.AddPage(self.sub_canvases[i], "Relay " + str(1 + i))
        '''
            Here goes a very important line of a code, setting notebook
            item's color to default window color instead of white color,
            chosen by default, when creating widget
        '''
        self.notebook.SetOwnBackgroundColour(self.GetBackgroundColour())
        self.notebook_sizer.Add(self.notebook, 0, wx.EXPAND)

        self.btm_page_sizer.Add(self.notebook_sizer, 0, wx.EXPAND)
        self.SetSizer(self.btm_page_sizer)

        # Apply data on connection
        self.app_data.iface_conn_handler_register(
            self._input_left_matrix_update_on_conn)
        self.app_data.iface_conn_handler_register(
            self._input_radio_data_set_on_conn)

        # Interface handlers, always called to update data on screen
        self.app_data.iface_output_handler_register(self._out_led_update)
        self.app_data.iface_output_handler_register(
            self._matrix_visibility_update)
        self.app_data.iface_output_handler_register(
            self._input_right_matrix_update)

        # Gather input data handlers
        self.app_data.iface_input_handler_register(
            self._input_left_matrix_data_gather)
        self.app_data.iface_input_handler_register(
            self._input_radio_data_gather)

        self._input_matrix_enabled = 0

        self.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.on_page_change)
Пример #10
0
    def __init__(
        self,
        conn_method='rtu',
        port='COM2',
        baudrate=19200,
        parity='E',
        timeout=1,
        bytesize=8,
        stopbits=1,
        slave_id=32,
        *args,
        **kwargs,
    ):
        super().__init__(*args, **kwargs)
        self.daemon = True

        self.app_data = AppData()

        self.queue_income = queue.Queue()
        self.queue_outcome = queue.Queue()
        self.queue_cmd = queue.Queue()
        self.queue_new_data = queue.Queue()

        self.method = conn_method
        self.port = port
        self.baudrate = baudrate
        self.parity = parity
        self.timeout = timeout
        self.slave_id = slave_id
        self.bytesize = bytesize
        self.stopbits = stopbits

        self.stopped = False
        self._inner_modbus_is_conn = self.Cmd.DISCONNECT
        self.client = None

        self.port_lock = threading.Lock()
        self.queue_lock = threading.Lock()
        self.blink_lock = threading.Lock()
        self.reconnect_lock = threading.Lock()
        self.state_lock = threading.Lock()

        self._rr = None
        self._wr = None

        self.state_machine_state = self.State.IDLE

        self.exception_state = False
        self.data_exchange_in_process = False
        self.connection_cmd_sent = False
        self.state_read = True

        self.cmd_current = None
        self.data_renewed = False
        self.slave_changed = False
        self.reconnect_requested = False
Пример #11
0
    def __init__(self, pos=(0, 0), size=(400, 300), title=""):
        self.size = size
        self.pos = pos

        # FIXME: Why this self.super_sizer is still present
        # self.super_sizer = wx.BoxSizer(wx.VERTICAL)

        self.app_data = AppData()
        self.settings = Settings()

        style = wx.DEFAULT_FRAME_STYLE  # Create a Frame style
        style ^= wx.RESIZE_BORDER       # Restrict resizing actions
        style ^= wx.MAXIMIZE_BOX        # Disable Maximize Button

        # Create Centered application frame
        wx.Frame.__init__(self, None, title=title, style=style,
                          size=self.size, pos=self.pos)
        self.Center()

        # Create Menu Bar
        self.menu_bar = MenuBarSequence(parent=self)

        main_panel = wx.Panel(parent=self, size=self.size)
        main_sizer = wx.BoxSizer(wx.VERTICAL)

        # Top of the page sequence
        self.top_canvas = TopPanel(parent=main_panel)

        # # Mid of the page sequence
        self.mid_canvas = MidPanel(parent=main_panel)

        # Bottom of the page sequence
        self.btm_canvas = BtmPanel(parent=main_panel)

        # Under bottom of the page sequence
        self.status_bottom_panel = StatusPanel(parent=main_panel)

        main_sizer.Add(self.top_canvas, 0,  wx.EXPAND)
        main_sizer.Add(self.mid_canvas, 0, wx.EXPAND | wx.BOTTOM, 10)
        main_sizer.Add(self.btm_canvas, 0, wx.EXPAND)
        main_sizer.Add(self.status_bottom_panel, 0, wx.EXPAND)

        main_panel.SetSizer(main_sizer)
        main_panel.Layout()

        '''
            Must be called after all items are set, according to doc files. 
            If not, any items, initialized after calling SetMenuBar method
            won't be rendered
        '''
        self.SetMenuBar(self.menu_bar)
    def __init__(self, parent):
        super().__init__(parent)
        self.app_data = AppData()
        self._output_garbage_collector = 0

        # Create modbus instance, to have access to its props
        instance = ModbusConnectionThreadSingleton()
        self.modbus = instance.thread_instance_get()

        # Create content for
        self.input_matrix = InputArray(parent=self,
                                       title='Corresponding inputs state:',
                                       dimension=(3, 5),
                                       interface=DISPLAY_INTERFACE,
                                       col_titles=['1', '2', '3', '4', '5'],
                                       row_titles=['X1', 'X2', 'X3'])

        self.inner_panel_sizer = wx.BoxSizer(wx.VERTICAL)
        self.inner_panel_sizer.Add(self.input_matrix, 0,
                                   wx.ALL | wx.ALIGN_CENTER, 10)
        self.SetSizer(self.inner_panel_sizer)
class BetManager:
    def __init__(self):
        # API ENDPOINT
        self.app_data = AppData()
        self.app_data.read_data()
        self.current_bets = []
        self.mother = BetAccount(self.app_data.account_mother_name, self.app_data.account_mother_pass)
        self.sons = []
        for son_data in self.app_data.accounts_son:
            son = BetAccount(son_data['name'], son_data['pass'])
            self.sons.append(son)
        # self.monitor_process = multiprocessing.Process(target=self.monitor)
        self.monitor_thread = None

    class OddsFormat(Enum):
        AMERICAN = 'AMERICAN'
        DECIMAL = 'DECIMAL'
        HONGKONG = 'HONGKONG'
        INDONESIAN = 'INDONESIAN'
        MALAY = 'MALAY'

    class BOOLEAN(Enum):
        FALSE = 'FALSE'
        TRUE = 'TRUE'

    class WinRiskType(Enum):
        RISK = 'RISK'
        WIN = 'WIN'

    class BetType(Enum):
        MONEYLINE = 'MONEYLINE'
        TEAM_TOTAL_POINTS = 'TEAM_TOTAL_POINTS'
        SPREAD = 'SPREAD'
        TOTAL_POINTS = 'TOTAL_POINTS'
        SPECIAL = 'SPECIAL'

    class BetStatus(Enum):
        ACCEPTED = 'ACCEPTED'
        CANCELLED = 'CANCELLED'
        LOSE = 'LOSE'
        PENDING_ACCEPTANCE = 'PENDING_ACCEPTANCE'
        REFUNDED = 'REFUNDED'
        REJECTED = 'REJECTED'
        WON = 'WON'

    def get_mother_bets(self):
        return self.mother.get_bets(days=29)

    def monitor(self):
        while True:
            if self.app_data.status_is_running == 0:
                print(datetime.now(), " -> ", "monitor thread stopped")
                return

            bets_response = self.get_mother_bets()
            print(datetime.now(), " -> ", bets_response)
            self.current_bets = bets_response['straightBets']
            for bet_response in bets_response['straightBets']:
                print(bet_response)
                # TODO: check bet status
                if bet_response['betStatus'] != self.BetStatus.ACCEPTED.value:
                    continue

                if self.app_data.check_if_exists_or_duplicated(bet_id=bet_response['betId']):
                    continue

                self.app_data.add_bet(bet_id=bet_response['betId'])

                bet_uuid = '{}'.format(uuid.uuid1())
                win_risk_stake = self.WinRiskType.RISK.value
                stake = bet_response['risk'] * self.app_data.status_percentage / 100
                if stake < 5.00:
                    stake = 5.00
                bet_team = "0"
                if bet_response['teamName'] == bet_response['team1']:
                    bet_team = '0'
                if bet_response['teamName'] == bet_response['team2']:
                    bet_team = '1'

                # line = self.mother.get_line(
                #     sport_id=bet_response['sportId'],
                #     league_id=bet_response['leagueId'],
                #     event_id=bet_response['eventId'],
                #     period_number=bet_response['periodNumber'],
                #     bet_type=bet_response['betType'],
                #     handicap=bet_response['handicap'],
                #     team=bet_response['teamName']
                # )
                # print(line)
                # line['lineId']
                bet_line_id = 1

                bet_request = {}
                # bet_request.update({
                #     'uniqueRequestId': bet_uuid,
                #     'acceptBetterLine': self.BOOLEAN.TRUE.value,
                #     'oddsFormat': bet_response['oddsFormat'],
                #     'betId': bet_response['betId'],
                #     'stake': stake,
                #     'winRiskStake': win_risk_stake,
                #     'sportId': bet_response['sportId'],
                #     'eventId': bet_response['eventId'],
                #     'periodNumber': bet_response['periodNumber'],
                #     'betType': bet_response['betType'],
                #     'lineId': bet_line_id,
                #     'team': 'TEAM1',
                # })

                bet_request.update({
                    'betId': bet_response['betId'],
                    'stake': stake,
                    'sportId': bet_response['sportId'],
                    'eventId': bet_response['eventId'],
                    'betType': bet_response['betType'],
                    'teamType': bet_team
                })
                res = self.duplicate_bets(json.dumps(bet_request))
                print(res)
            time.sleep(self.app_data.status_delay_in_seconds)

    def start(self):
        self.app_data.status_is_running = 1
        self.monitor_thread = threading.Thread(target=self.monitor)
        self.monitor_thread.start()

    def stop(self):
        self.app_data.status_is_running = 0
        # self.monitor_process.terminate()
        # self.app_data.write_data()

    def duplicate_bets(self, bet_request: dict):
        headers = {}
        headers.update({'Accept': 'application/json'})
        headers.update({'Content-Type': 'application/json'})

        res = requests.post(
            url="http://127.0.0.1:3000",
            data=bet_request,
            headers=headers
        )
        print(res.json())
        return res.json()
Пример #14
0
class WxWidgetCustomApp:
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # Define two singletones, containing data to share across application
        self.app_settings = Settings()
        self.app_settings.settings_load()
        self.app_data = AppData()
        self.modbus_singleton = None

        # Create a gui application with main frame
        self.gui = GuiApp(size=(439, 550), title="Light Controller")

        # Create threads
        self.modbus_singleton = ModbusConnectionThreadSingleton()
        self.modbus_connection = self.modbus_singleton.modbus_comm_instance
        self.modbus_connection.daemon = True

        self.poll_thread = threading.Thread(target=self._app_settings_poll)
        self.poll_thread.daemon = True

        self.main_logic_thread = threading.Thread(
            target=self._main_logic_handler)
        self.main_logic_thread.daemon = True

        self.data_thread = threading.Thread(target=self._modbus_data_handler)
        self.data_thread.daemon = True

        self.conn_state_prev = None
        self.app_stage = 0

    def _poll_close_event(self):
        # TODO: Resolve access violation
        closed = False
        if self.gui.is_closing:
            self.modbus_connection.disconnect()
            self.modbus_connection.stop()
            self.modbus_connection.join()
            self.poll_thread.join()
            self.data_thread.join(0.5)
            closed = True
            # self.gui.application.Destroy()
            # self.gui.application.Close()

        return closed

    def _modbus_data_get(self):
        data = self.modbus_connection.queue_data_get()
        if data is not None:
            self.app_data.modbus_data = data

    def _modbus_data_put(self):
        if self.modbus_connection.is_connected:
            if self.app_data.modbus_send_data:
                self.modbus_connection.queue_data_set(
                    self.app_data.modbus_send_data)

    # Thread handler list
    def _app_settings_poll(self):
        while True:
            if self.gui.is_closing:
                print('poll thread closing')
                break
            self.app_settings.settings_save()
            time.sleep(0.1)

    def _main_logic_handler(self):
        while True:
            if self._poll_close_event():
                break
            time.sleep(.2)

        try:
            self.gui.main_frame.Destroy()
        except Exception as e:
            print(e)

    def _modbus_data_handler(self):
        while True:
            if self.gui.is_closing:
                print('data handler closing')
                break

            with self.modbus_connection.reconnect_lock:
                if self.modbus_connection.reconnect_requested:
                    self.modbus_connection.reconnect_requested = False
                    self.app_stage = 0

                if self.app_stage == 0:
                    if self.modbus_connection.is_connected and self.modbus_connection.data_renewed:
                        self.app_data.conn_data_apply()
                        self.app_stage = 1
                    else:
                        self.app_data.output_data_update()

                elif self.app_stage == 1:
                    if self.modbus_connection.is_connected:
                        self._modbus_data_get()
                        self.app_data.output_data_update()

                        self.app_data.input_data_gather()
                        if self.app_data.user_interaction:
                            self.app_data.user_interaction = False
                            self._modbus_data_put()
                    else:
                        self.app_stage = 0

                elif self.app_stage == 3:
                    pass

            time.sleep(.1)

    def run(self):
        """
            Manually launch every thread defined in __init__()
            GUI.start() should always be the last one**
            __________________________________________________
              **blocks every call after itself, until finished
        """
        self.poll_thread.start()
        self.main_logic_thread.start()
        self.modbus_connection.start()
        self.data_thread.start()

        # GUI.start() Called at the end, as mentioned everywhere
        self.gui.start()
Пример #15
0
class _MidPanelContent(wx.Panel):
    def __init__(self, parent=None):
        super().__init__(parent=parent)
        self.conn_blink_state = 0
        self.settings = Settings()
        self.app_data = AppData()
        self.sizer = wx.BoxSizer(wx.HORIZONTAL)
        self._output_garbage_collector = 0
        self.act_indicator_wrapper = wx.BoxSizer(wx.VERTICAL)
        self.slave_id_sequence_wrapper = wx.BoxSizer(wx.VERTICAL)

        # Create display matrix for Relays
        self.output_matrix = InputArray(
            parent=self,
            title='Outputs state:',
            dimension=(1, 8),
            col_titles=['K1', 'K2', 'K3', 'K4', 'K5', 'K6', 'K7', 'K8'],
            interface=DISPLAY_INTERFACE,
            secret_ids=[1, 2, 3, 4, 5, 6, 7, 8],
            is_input_indication=False)
        self.output_matrix_wrapper = wx.BoxSizer(wx.VERTICAL)
        self.output_matrix_wrapper.Add(self.output_matrix, 0,
                                       wx.RIGHT | wx.ALIGN_RIGHT, 18)

        # Assign instance of modbus singleton, to have access to its props
        instance = ModbusConnectionThreadSingleton()
        self.modbus = instance.thread_instance_get()

        # Create an activity Led
        self.act_label = wx.StaticText(parent=self, label='Activity')
        self.activity_led = InputArray(parent=self,
                                       dimension=(1, 1),
                                       is_conn=True,
                                       interface=DISPLAY_INTERFACE,
                                       outlined=False)

        # Create Slave id sequence
        self.slave_id_label = wx.StaticText(parent=self, label='Slave ID')
        self.slave_id_control = wx.SpinCtrl(parent=self,
                                            size=(60, -1),
                                            style=wx.TE_LEFT,
                                            max=999)

        # Wrap indicator
        act_label_wrapper = wx.BoxSizer(wx.HORIZONTAL)
        led_activity_wrapper = wx.BoxSizer(wx.HORIZONTAL)
        act_label_wrapper.Add(self.act_label, 1, wx.LEFT, 8)
        led_activity_wrapper.Add(self.activity_led, 1, wx.LEFT, 21)
        self.act_indicator_wrapper.Add(act_label_wrapper, 2, wx.TOP, 12)
        self.act_indicator_wrapper.Add(led_activity_wrapper, 2, wx.TOP, 14)

        # Wrap slave id
        slave_id_label_wrapper = wx.BoxSizer(wx.HORIZONTAL)
        slave_id_control_wrapper = wx.BoxSizer(wx.HORIZONTAL)
        slave_id_label_wrapper.Add(self.slave_id_label, 1, wx.LEFT, 3)
        slave_id_control_wrapper.Add(self.slave_id_control, 1, wx.LEFT, 8)
        self.slave_id_sequence_wrapper.Add(slave_id_label_wrapper, 3, wx.TOP,
                                           18)
        self.slave_id_sequence_wrapper.Add(slave_id_control_wrapper, 2, wx.TOP,
                                           4)

        # Bind events
        self.Bind(wx.EVT_SPINCTRL, self.slave_id_update, self.slave_id_control)
        self.app_data.iface_output_handler_register(self._slave_id_update)

        # Assemble panel sizer
        self.sizer.Add(self.act_indicator_wrapper, 1,
                       wx.LEFT | wx.ALIGN_CENTER_VERTICAL, 20)
        self.sizer.Add(self.slave_id_sequence_wrapper, 1,
                       wx.LEFT | wx.ALIGN_CENTER_VERTICAL, 20)
        self.sizer.Add(self.output_matrix_wrapper, 6, wx.EXPAND, 0)

        # Apply panel sizer
        self.SetSizer(self.sizer)

        # Register handler to update output state
        self.app_data.iface_output_handler_register(
            self._output_indication_update)

        # Insert a certain delay for refresh button
        self.timer = wx.Timer()
        self.timer_evt_handler = wx.EvtHandler()
        self.timer.SetOwner(self.timer_evt_handler, id=228)
        self.timer_evt_handler.Bind(wx.EVT_TIMER,
                                    self._refresh_conn_activity,
                                    self.timer,
                                    id=228)

        self.timer.Start(100, True)

    def _slave_id_update(self):
        self.value = self.settings.slave_id

    def slave_id_update(self, event):
        self._output_garbage_collector = event
        self.settings.slave_id = self.value
        self.modbus.slave_id_update(self.settings.slave_id)

    def _output_indication_update(self):
        for i in range(8):
            self.output_matrix.value_set_by_index(
                i, self.app_data.output_state_get(i))

    # Refresh callback, which is called every 100
    def _refresh_conn_activity(self, event):
        self._garbage_evt_collector = event
        self.timer.Start(100, True)
        self._can_be_refreshed = 1
        self._conn_indication()

    def _conn_indication(self):
        modbus_conn_state = self.modbus.is_connected
        self.activity_led.visible_instances = (modbus_conn_state, )
        if modbus_conn_state:
            if self._can_be_refreshed == 1:
                self._can_be_refreshed = 0
                self.conn_blink_state = not self.conn_blink_state
                self.activity_led.values = (self.conn_blink_state, )
            else:
                self.activity_led.values = (0, )
                self.conn_blink_state = 0

    @property
    def value(self):
        if self.slave_id_control:
            try:
                value = self.slave_id_control.GetValue()
            except Exception as e:
                print(e)
                value = None
            return value

    @value.setter
    def value(self, new_value):
        if self.slave_id_control:
            self.slave_id_control.SetValue(new_value)
Пример #16
0
    def __init__(self, parent=None):
        super().__init__(parent=parent)
        self.conn_blink_state = 0
        self.settings = Settings()
        self.app_data = AppData()
        self.sizer = wx.BoxSizer(wx.HORIZONTAL)
        self._output_garbage_collector = 0
        self.act_indicator_wrapper = wx.BoxSizer(wx.VERTICAL)
        self.slave_id_sequence_wrapper = wx.BoxSizer(wx.VERTICAL)

        # Create display matrix for Relays
        self.output_matrix = InputArray(
            parent=self,
            title='Outputs state:',
            dimension=(1, 8),
            col_titles=['K1', 'K2', 'K3', 'K4', 'K5', 'K6', 'K7', 'K8'],
            interface=DISPLAY_INTERFACE,
            secret_ids=[1, 2, 3, 4, 5, 6, 7, 8],
            is_input_indication=False)
        self.output_matrix_wrapper = wx.BoxSizer(wx.VERTICAL)
        self.output_matrix_wrapper.Add(self.output_matrix, 0,
                                       wx.RIGHT | wx.ALIGN_RIGHT, 18)

        # Assign instance of modbus singleton, to have access to its props
        instance = ModbusConnectionThreadSingleton()
        self.modbus = instance.thread_instance_get()

        # Create an activity Led
        self.act_label = wx.StaticText(parent=self, label='Activity')
        self.activity_led = InputArray(parent=self,
                                       dimension=(1, 1),
                                       is_conn=True,
                                       interface=DISPLAY_INTERFACE,
                                       outlined=False)

        # Create Slave id sequence
        self.slave_id_label = wx.StaticText(parent=self, label='Slave ID')
        self.slave_id_control = wx.SpinCtrl(parent=self,
                                            size=(60, -1),
                                            style=wx.TE_LEFT,
                                            max=999)

        # Wrap indicator
        act_label_wrapper = wx.BoxSizer(wx.HORIZONTAL)
        led_activity_wrapper = wx.BoxSizer(wx.HORIZONTAL)
        act_label_wrapper.Add(self.act_label, 1, wx.LEFT, 8)
        led_activity_wrapper.Add(self.activity_led, 1, wx.LEFT, 21)
        self.act_indicator_wrapper.Add(act_label_wrapper, 2, wx.TOP, 12)
        self.act_indicator_wrapper.Add(led_activity_wrapper, 2, wx.TOP, 14)

        # Wrap slave id
        slave_id_label_wrapper = wx.BoxSizer(wx.HORIZONTAL)
        slave_id_control_wrapper = wx.BoxSizer(wx.HORIZONTAL)
        slave_id_label_wrapper.Add(self.slave_id_label, 1, wx.LEFT, 3)
        slave_id_control_wrapper.Add(self.slave_id_control, 1, wx.LEFT, 8)
        self.slave_id_sequence_wrapper.Add(slave_id_label_wrapper, 3, wx.TOP,
                                           18)
        self.slave_id_sequence_wrapper.Add(slave_id_control_wrapper, 2, wx.TOP,
                                           4)

        # Bind events
        self.Bind(wx.EVT_SPINCTRL, self.slave_id_update, self.slave_id_control)
        self.app_data.iface_output_handler_register(self._slave_id_update)

        # Assemble panel sizer
        self.sizer.Add(self.act_indicator_wrapper, 1,
                       wx.LEFT | wx.ALIGN_CENTER_VERTICAL, 20)
        self.sizer.Add(self.slave_id_sequence_wrapper, 1,
                       wx.LEFT | wx.ALIGN_CENTER_VERTICAL, 20)
        self.sizer.Add(self.output_matrix_wrapper, 6, wx.EXPAND, 0)

        # Apply panel sizer
        self.SetSizer(self.sizer)

        # Register handler to update output state
        self.app_data.iface_output_handler_register(
            self._output_indication_update)

        # Insert a certain delay for refresh button
        self.timer = wx.Timer()
        self.timer_evt_handler = wx.EvtHandler()
        self.timer.SetOwner(self.timer_evt_handler, id=228)
        self.timer_evt_handler.Bind(wx.EVT_TIMER,
                                    self._refresh_conn_activity,
                                    self.timer,
                                    id=228)

        self.timer.Start(100, True)
Пример #17
0
    def __init__(self,
                 parent,
                 *args,
                 aydi=None,
                 with_size=True,
                 with_indicator=False,
                 with_radio_panel=False,
                 **kwargs):
        self.id = aydi

        style = None
        if 'style' in kwargs:
            style = kwargs['style']
        if style is not None:
            super().__init__(parent, style=style)
        else:
            super().__init__(parent)

        self.inner_title = None
        self.setup_button = None
        self._configuration = None

        self.inner_title = wx.StaticText(parent=self,
                                         label=kwargs['inner_title'])

        modbus_singleton = ModbusConnectionThreadSingleton()
        self.modbus = modbus_singleton.modbus_comm_instance

        self.app_data = AppData()

        intermediate_sizer = wx.BoxSizer(wx.HORIZONTAL)
        self.inter_title = wx.StaticText(parent=self, label='Output State')
        self.inter_instance = InputArray(parent=self,
                                         dimension=(1, 1),
                                         outlined=False,
                                         interface=DISPLAY_INTERFACE)
        intermediate_sizer.Add(self.inter_title, 0, wx.LEFT, 15)
        intermediate_sizer.Add(self.inter_instance, 0, wx.LEFT, 30)

        if 'interface' in kwargs:
            if kwargs['interface'] == DISPLAY_INTERFACE:
                self.interface = DISPLAY_INTERFACE
        else:
            self.interface = INPUT_INTERFACE

        title = 'Inputs state:'
        self.inner_matrix = InputArray(parent=self,
                                       title=title,
                                       dimension=(3, 5),
                                       col_titles=['1', '2', '3', '4', '5'],
                                       row_titles=['X1', 'X2', 'X3'])

        self.inner_panel_sizer = wx.BoxSizer(wx.VERTICAL)
        self.inner_panel_sizer.Add(self.inner_title, 0, wx.ALL, 5)
        if with_indicator or with_radio_panel:
            self.inner_panel_sizer.Add(intermediate_sizer, 0,
                                       wx.RIGHT | wx.ALIGN_RIGHT, 18)
        self.inner_panel_sizer.Add(self.inner_matrix, 0, wx.ALL | wx.CENTER,
                                   10)

        if with_size:
            self.SetSizer(self.inner_panel_sizer)
Пример #18
0
class _BtmSubPanel(wx.Panel):
    def __init__(self, parent):
        # Basic Construction procedure
        super().__init__(parent)
        self.left_panel = None
        self.right_panel = None
        self.app_data = AppData()
        self.rb_value = 0

        # Create modbus instance, to have access to its props
        instance = ModbusConnectionThreadSingleton()
        self.modbus = instance.thread_instance_get()

        # Create sizers
        self.panel_sizer = wx.BoxSizer(wx.VERTICAL)
        self.upper_sizer = wx.BoxSizer(wx.HORIZONTAL)
        self.bottom_sizer = wx.BoxSizer(wx.HORIZONTAL)

        # Create upper sequence items
        self.output_mode_label = wx.StaticText(parent=self, label='Mode:')
        self.output_mode_rb_auto = wx.RadioButton(parent=self,
                                                  id=0,
                                                  label='Auto',
                                                  style=wx.RB_GROUP)
        self.output_mode_rb_off = wx.RadioButton(parent=self,
                                                 id=1,
                                                 label='Off')
        self.output_mode_rb_on = wx.RadioButton(parent=self, id=2, label='On')
        # self.output_mode_rb_change = wx.RadioButton(parent=self, id=3, label='Change')

        self.output_state_label = wx.StaticText(parent=self, label='State:')
        self.output_led = InputArray(parent=self,
                                     dimension=(1, 1),
                                     interface=DISPLAY_INTERFACE,
                                     outlined=False,
                                     is_input_indication=False)

        # Create both panels
        self._left_panel_create(self)
        self._right_panel_create(self)

        # Prepare led state sizer
        self.led_state_sizer = wx.BoxSizer(wx.HORIZONTAL)
        led_inter_sizer = wx.BoxSizer(wx.VERTICAL)
        led_inter_sizer.Add(self.output_led, 1, wx.RIGHT | wx.ALIGN_RIGHT, 20)
        label_inter_sizer = wx.BoxSizer(wx.VERTICAL)
        label_inter_sizer.Add(self.output_state_label, 1, wx.LEFT, 85)
        self.led_state_sizer.Add(label_inter_sizer, 1, wx.ALL)
        self.led_state_sizer.Add(led_inter_sizer, 1, wx.ALL)

        # Wrap data into upper sizer
        self.upper_radio_sizer = wx.BoxSizer(wx.HORIZONTAL)

        self.upper_radio_sizer.Add(self.output_mode_label, 0, wx.LEFT, 15)
        self.upper_radio_sizer.Add(self.output_mode_rb_auto, 0, wx.LEFT, 5)
        self.upper_radio_sizer.Add(self.output_mode_rb_off, 0, wx.LEFT, 5)
        self.upper_radio_sizer.Add(self.output_mode_rb_on, 0, wx.LEFT, 5)
        # self.upper_radio_sizer.Add(self.output_mode_rb_change, 0, wx.LEFT, 5)

        self.upper_sizer.Add(self.upper_radio_sizer, 1, wx.TOP | wx.BOTTOM, 15)
        self.upper_sizer.Add(self.led_state_sizer, 5, wx.ALL, 15)

        # Wrap data into bottom sizer
        self.bottom_sizer.Add(self.left_panel, 1, wx.EXPAND | wx.LEFT, 2)
        self.bottom_sizer.Add(self.right_panel, 1, wx.EXPAND | wx.RIGHT, 2)

        # Wrap data into self sizer
        self.panel_sizer.Add(self.upper_sizer, 1, wx.EXPAND | wx.TOP, 5)
        self.panel_sizer.Add(self.bottom_sizer, 3, wx.EXPAND)

        # Apply self sizer
        self.SetSizer(self.panel_sizer)

        # Beautify
        self.output_mode_rb_auto.Disable()
        self.output_mode_rb_off.Disable()
        self.output_mode_rb_on.Disable()
        # self.output_mode_rb_change.Disable()

        # Bind Callbacks
        self.Bind(wx.EVT_RADIOBUTTON, self._radio_button_callback,
                  self.output_mode_rb_auto)
        self.Bind(wx.EVT_RADIOBUTTON, self._radio_button_callback,
                  self.output_mode_rb_off)
        self.Bind(wx.EVT_RADIOBUTTON, self._radio_button_callback,
                  self.output_mode_rb_on)
        # self.Bind(wx.EVT_RADIOBUTTON, self._radio_button_callback, self.output_mode_rb_change)

        self.app_data.iface_output_handler_register(
            self.radio_buttons_visibility_handler)

    def radio_buttons_visibility_handler(self):
        if self.modbus.is_connected:
            try:
                if self.output_mode_rb_auto:
                    self.output_mode_rb_auto.Enable()
                if self.output_mode_rb_off:
                    self.output_mode_rb_off.Enable()
                if self.output_mode_rb_on:
                    self.output_mode_rb_on.Enable()
                # if self.output_mode_rb_change:
                #     self.output_mode_rb_change.Enable()
            except Exception as e:
                print(e)
        else:
            try:
                if self.output_mode_rb_auto:
                    self.output_mode_rb_auto.Disable()
                if self.output_mode_rb_off:
                    self.output_mode_rb_off.Disable()
                if self.output_mode_rb_on:
                    self.output_mode_rb_on.Disable()
                # if self.output_mode_rb_change:
                #     self.output_mode_rb_change.Disable()
            except Exception as e:
                print(e)
            self.rb_value = -1

    def rb_layout(self):
        if self.rb_value == 0:
            if self.output_mode_rb_auto:
                self.output_mode_rb_auto.SetValue(True)
                self.output_mode_rb_auto.Layout()
        elif self.rb_value == 1:
            if self.output_mode_rb_off:
                self.output_mode_rb_off.SetValue(True)
                self.output_mode_rb_off.Layout()
        elif self.rb_value == 2:
            if self.output_mode_rb_on:
                self.output_mode_rb_on.SetValue(True)
                self.output_mode_rb_on.Layout()
        # elif self.rb_value == 3:
        #     if self.output_mode_rb_change:
        #         self.output_mode_rb_change.SetValue(True)
        #         self.output_mode_rb_change.Layout()

    def _left_panel_create(self, parent):
        self.left_panel = BtmLeftPanel(parent)

    def _right_panel_create(self, parent):
        self.right_panel = BtmRightPanel(parent)

    def _radio_button_callback(self, event):
        self.app_data.user_interaction = True
        if self.modbus.is_connected and self.app_data.modbus_data is not None:
            self.rb_value = event.GetId()
Пример #19
0
class _BtmPanel(wx.Panel):
    def __init__(self, parent=None):

        super().__init__(parent=parent)

        self.app_data = AppData()

        self.modbus = ModbusConnectionThreadSingleton()
        self.modbus = self.modbus.thread_instance_get()

        self.btm_page_sizer = wx.BoxSizer(wx.HORIZONTAL)
        self.notebook_sizer = wx.BoxSizer(wx.HORIZONTAL)

        self.notebook = wx.Notebook(self)
        self.sub_canvases = list()
        for i in range(8):
            self.sub_canvases.append(_BtmSubPanel(parent=self.notebook))
            self.notebook.AddPage(self.sub_canvases[i], "Relay " + str(1 + i))
        '''
            Here goes a very important line of a code, setting notebook
            item's color to default window color instead of white color,
            chosen by default, when creating widget
        '''
        self.notebook.SetOwnBackgroundColour(self.GetBackgroundColour())
        self.notebook_sizer.Add(self.notebook, 0, wx.EXPAND)

        self.btm_page_sizer.Add(self.notebook_sizer, 0, wx.EXPAND)
        self.SetSizer(self.btm_page_sizer)

        # Apply data on connection
        self.app_data.iface_conn_handler_register(
            self._input_left_matrix_update_on_conn)
        self.app_data.iface_conn_handler_register(
            self._input_radio_data_set_on_conn)

        # Interface handlers, always called to update data on screen
        self.app_data.iface_output_handler_register(self._out_led_update)
        self.app_data.iface_output_handler_register(
            self._matrix_visibility_update)
        self.app_data.iface_output_handler_register(
            self._input_right_matrix_update)

        # Gather input data handlers
        self.app_data.iface_input_handler_register(
            self._input_left_matrix_data_gather)
        self.app_data.iface_input_handler_register(
            self._input_radio_data_gather)

        self._input_matrix_enabled = 0

        self.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.on_page_change)

    def on_page_change(self, event):
        page = event.GetSelection()
        if self.modbus.is_connected:
            self.sub_canvases[page].rb_value = self.app_data.output_mode_get(
                page)
            self.sub_canvases[page].rb_layout()

    def _input_left_matrix_data_gather(self):
        for out_id in range(8):
            val_list = []
            left_panel = self.sub_canvases[out_id].left_panel
            for in_id in range(15):
                value = left_panel.input_matrix.value_get_by_index(in_id)
                val_list.append(value)

            self.app_data.output_associated_input_set_mask(out_id, val_list)

    def _input_left_matrix_update_on_conn(self):
        # Update left matrix when we acquire connection
        for out_id in range(8):
            left_panel = self.sub_canvases[out_id].left_panel

            for in_id in range(15):
                value = self.app_data.output_associated_input_get(
                    out_id, in_id)
                left_panel.input_matrix.value_set_by_index(in_id, value)

    def _input_right_matrix_update(self):
        # Update right matrix when we acquire connection
        for out_id in range(8):
            right_panel = self.sub_canvases[out_id].right_panel

            for in_id in range(15):
                is_visible = self.app_data.output_associated_input_get(
                    out_id, in_id)
                right_panel.input_matrix.visibility_set_by_index(
                    in_id, is_visible)

                value = self.app_data.input_state_get(in_id)
                right_panel.input_matrix.value_set_by_index(in_id, value)

    def _input_radio_data_set_on_conn(self):
        val_list = list()
        for out_id, sub_cvs in enumerate(self.sub_canvases):
            sub_cvs.rb_value = self.app_data.output_mode_get(out_id)
            val_list.append(sub_cvs.rb_value)
            sub_cvs.rb_layout()

    def _input_radio_data_gather(self):
        val_list = list()
        for out_id, sub_cvs in enumerate(self.sub_canvases):
            val_list.append(sub_cvs.rb_value)
            self.app_data.output_mode_set(out_id, sub_cvs.rb_value)

    def _matrix_visibility_update(self):
        if self.modbus.is_connected:
            for out_id in range(8):
                left_panel = self.sub_canvases[out_id].left_panel
                if self._input_matrix_enabled is False:
                    left_panel.input_matrix.enable()
                    self._input_matrix_enabled = True
        else:
            for out_id in range(8):
                left_panel = self.sub_canvases[out_id].left_panel
                if self._input_matrix_enabled is True:
                    left_panel.input_matrix.disable()
                    self._input_matrix_enabled = False

    def _out_led_update(self):
        for i in range(8):
            self.sub_canvases[i].output_led.values = [
                self.app_data.output_state_get(i),
            ]
Пример #20
0
    def __init__(self, parent):
        # Basic Construction procedure
        super().__init__(parent)
        self.left_panel = None
        self.right_panel = None
        self.app_data = AppData()
        self.rb_value = 0

        # Create modbus instance, to have access to its props
        instance = ModbusConnectionThreadSingleton()
        self.modbus = instance.thread_instance_get()

        # Create sizers
        self.panel_sizer = wx.BoxSizer(wx.VERTICAL)
        self.upper_sizer = wx.BoxSizer(wx.HORIZONTAL)
        self.bottom_sizer = wx.BoxSizer(wx.HORIZONTAL)

        # Create upper sequence items
        self.output_mode_label = wx.StaticText(parent=self, label='Mode:')
        self.output_mode_rb_auto = wx.RadioButton(parent=self,
                                                  id=0,
                                                  label='Auto',
                                                  style=wx.RB_GROUP)
        self.output_mode_rb_off = wx.RadioButton(parent=self,
                                                 id=1,
                                                 label='Off')
        self.output_mode_rb_on = wx.RadioButton(parent=self, id=2, label='On')
        # self.output_mode_rb_change = wx.RadioButton(parent=self, id=3, label='Change')

        self.output_state_label = wx.StaticText(parent=self, label='State:')
        self.output_led = InputArray(parent=self,
                                     dimension=(1, 1),
                                     interface=DISPLAY_INTERFACE,
                                     outlined=False,
                                     is_input_indication=False)

        # Create both panels
        self._left_panel_create(self)
        self._right_panel_create(self)

        # Prepare led state sizer
        self.led_state_sizer = wx.BoxSizer(wx.HORIZONTAL)
        led_inter_sizer = wx.BoxSizer(wx.VERTICAL)
        led_inter_sizer.Add(self.output_led, 1, wx.RIGHT | wx.ALIGN_RIGHT, 20)
        label_inter_sizer = wx.BoxSizer(wx.VERTICAL)
        label_inter_sizer.Add(self.output_state_label, 1, wx.LEFT, 85)
        self.led_state_sizer.Add(label_inter_sizer, 1, wx.ALL)
        self.led_state_sizer.Add(led_inter_sizer, 1, wx.ALL)

        # Wrap data into upper sizer
        self.upper_radio_sizer = wx.BoxSizer(wx.HORIZONTAL)

        self.upper_radio_sizer.Add(self.output_mode_label, 0, wx.LEFT, 15)
        self.upper_radio_sizer.Add(self.output_mode_rb_auto, 0, wx.LEFT, 5)
        self.upper_radio_sizer.Add(self.output_mode_rb_off, 0, wx.LEFT, 5)
        self.upper_radio_sizer.Add(self.output_mode_rb_on, 0, wx.LEFT, 5)
        # self.upper_radio_sizer.Add(self.output_mode_rb_change, 0, wx.LEFT, 5)

        self.upper_sizer.Add(self.upper_radio_sizer, 1, wx.TOP | wx.BOTTOM, 15)
        self.upper_sizer.Add(self.led_state_sizer, 5, wx.ALL, 15)

        # Wrap data into bottom sizer
        self.bottom_sizer.Add(self.left_panel, 1, wx.EXPAND | wx.LEFT, 2)
        self.bottom_sizer.Add(self.right_panel, 1, wx.EXPAND | wx.RIGHT, 2)

        # Wrap data into self sizer
        self.panel_sizer.Add(self.upper_sizer, 1, wx.EXPAND | wx.TOP, 5)
        self.panel_sizer.Add(self.bottom_sizer, 3, wx.EXPAND)

        # Apply self sizer
        self.SetSizer(self.panel_sizer)

        # Beautify
        self.output_mode_rb_auto.Disable()
        self.output_mode_rb_off.Disable()
        self.output_mode_rb_on.Disable()
        # self.output_mode_rb_change.Disable()

        # Bind Callbacks
        self.Bind(wx.EVT_RADIOBUTTON, self._radio_button_callback,
                  self.output_mode_rb_auto)
        self.Bind(wx.EVT_RADIOBUTTON, self._radio_button_callback,
                  self.output_mode_rb_off)
        self.Bind(wx.EVT_RADIOBUTTON, self._radio_button_callback,
                  self.output_mode_rb_on)
        # self.Bind(wx.EVT_RADIOBUTTON, self._radio_button_callback, self.output_mode_rb_change)

        self.app_data.iface_output_handler_register(
            self.radio_buttons_visibility_handler)