def on_state_streaming_auto(self, e): log.info('Entering state StreamingAuto.') self._streaming = True self.handle_player_auto() log.info('Exiting state StreamingAuto.') self._async_transition( TRANSITION_INFO) # [StreamingAuto] ==show_info==> [SysInfo]
def upload(self): """ Send the copied text to SERVER """ clip = self.copy() clip_encrypted = self.crypto.encrypt(clip) payload = {"text": clip_encrypted, "device": f"{Config.DEVICE_ID}"} try: res = requests.post( self.SERVER + Config.API_COPY_PASTE, data=payload, auth=(self.USER, self.HASH_LOGIN), timeout=Config.CONN_TIMEOUT, verify=Config.VERIFY_SSL_CERT, headers=Config.HEADERS, ) except requests.exceptions.RequestException as e: log.exception("Error in upload request") raise ApiException(e) else: if res.status_code == 201: log.info("Success! Copied to Cloud-Clipboard.") return clip else: log.error(f"Error cannot upload clip: {res.text}") raise ApiException(res.text[0:Config.MAX_RESPONSE_LEN])
def __init__(self, name, server): """A client class Args: name (str): name of the client server (tuple): (ip, port) of a chat server to connect Attributes: id (int): ID of the client s (socket obj): socket of the client rT (Thread obj): receiving thread """ assert isinstance(name, str), 'Name must be string' assert all( (isinstance(server, tuple), len(server) == 2)), 'Address must be tuple' assert all((isinstance(server[0], str), isinstance(server[1], int))), 'Wrong address' self.name = name self.server = server self.id = random.randint(100, 999) self.s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.rT = threading.Thread(target=self.receiving, name='ReceiveThread') log.info('Client successfully initialize')
def download(self): """ Download last or all clips from SERVER and updates the local clipboard """ log.info("downloading clips") url = self.SERVER + Config.API_COPY_PASTE try: res = requests.get( url=url, auth=(self.USER, self.HASH_LOGIN), timeout=Config.CONN_TIMEOUT, verify=Config.VERIFY_SSL_CERT, headers=Config.HEADERS, ) except requests.exceptions.RequestException as e: log.exception("Error in download request") raise ApiException(e) else: if res.status_code == 200: clips_decrypted = self.parse_and_decrypt_response(res) log.info(f"Got new clips from SERVER:\n{clips_decrypted}") self.paste(clips_decrypted[-1]) return clips_decrypted else: log.error( f"Cannot download clips: {res.status_code} - {res.text}") raise ApiException(res.text[0:Config.MAX_RESPONSE_LEN])
def play(self): self._stop() # e.g. (no auth): omxplayer -o hdmi --blank --live --fps 24 -r rtsp://172.16.1.195 # e.g. (auth) : sudo omxplayer -o hdmi --blank --live "rtsp://172.16.1.195/av0_0&user=admin&password=admin" command = [ 'omxplayer', '--adev', 'hdmi', '--aidx', "-1", # disable audio '--timeout', '5', '--blank', '--live' if self.live else '--no-osd', '--aspect-mode', 'fill', '--avdict', 'rtsp_transport:tcp', '--subtitles', '/home/haso/camviewer/sub%d.srt' % self.id, self.uri ] log.info('Starting Player[single]... (%s)' % repr(command)) self.process = Popen(command, stdin=PIPE, stdout=DEV_NULL, stderr=STDOUT, close_fds=True, bufsize=0) # async. execution, instant exit log.info('Player[single] started.')
def store_as_script_on_disk(i, content, script_path): f = open(script_path, 'w+') f.write(BASH_SHEBANG) f.write(content + '\n') f.truncate() f.close() log.info(' - Player[stream-%d] - start script stored on disk: (%s).' % (i, script_path))
def run(self): try: log.info('Entering EventHandlerThread...') self.event_consumer = ZmqConsumer(self.handle_button) log.info('Exiting EventHandlerThread...') except KeyboardInterrupt: self.stop() exit(0)
def run(self): try: log.info('Entering StatusReaderThread...') fetch_serial_number() self.update_model() log.info('Exiting StatusReaderThread...') except KeyboardInterrupt: self.stop() exit(0)
def kill_single_omx_window(i, win_coords_filter): screen_name_filter = SCREEN_NAME_PATTERN % i kill_single_command = [ 'bash', SCRIPT_OMX_KILL_SINGLE, win_coords_filter, screen_name_filter ] log.info( ' --- Player[stream-%d] stopping players for single window, cmd=(%s)' % (i, kill_single_command)) kill_result = check_output(kill_single_command) log.info(' --- Player[stream-%d] kill single window result: (\n%s)', i, kill_result)
def handle_player_split(self): self._cam_stop_user_request = False cams_configs = self._info_collector_thread.cams_configs self._player_split = PlayerSplit(cams_configs) self._player_split.play() if self._cam_stop_user_request: log.info("Player[split] stopped manually. Done.") else: log.info("Player[split] exited by itself.") kill_all_omx_processes()
def is_any_cam(self): for i in range(0, MAX_CAM_AMOUNT): cam_address = self.cams_configs[i].address if cam_address: cam_status = self.cams_statuses[i] available = cam_status == CAM_STATUS_OK log.info("Cam[%d] status=(%s)" % (i, available)) if available: return True return False
def wait_for_tray_event(mygui, server, username, hash_login, hash_msg): """ Check for config modification while waiting for action in systray """ log.debug("Main Loop\n") log.debug(f"{server} - {username} - {hash_login} - {hash_msg}") api = Api(server, username, hash_login, hash_msg) while True: if Config.was_configfile_modified(): log.info("Configfile was modified.") self_restart() event = mygui.tray.read() deal_with_tray_event(mygui, api, event)
def _change_mode(self): log.info('Current mode: (%s).' % self._mode) if self._mode == MODE_SINGLE: log.info('\tChanging mode to SPLIT.') self._set_mode(MODE_SPLIT) elif self._mode == MODE_SPLIT: log.info('\tChanging mode to AUTO.') self._set_mode(MODE_AUTO) elif self._mode == MODE_AUTO: log.info('\tChanging mode to SINGLE.') self._set_mode(MODE_SINGLE) else: log.info('Invalid mode detected. Skipping <DOWN> btn.')
def deal_with_tray_event(mygui, api, event): """ React to menu actions in tray """ log.info(event) if event == "Get last Clip": get_clip(mygui, api, False) if event == "Get all Clips": get_clip(mygui, api, True) elif event == "Share Clip": set_clip(mygui, api) elif event == "Edit Credentials": get_cred(mygui) elif event == "Exit": sys.exit(0)
def run(self): """Begins the main loop establishing connection with the server and waiting for the user's input (there two threads: first for sending, second for receiving) """ self.shutdown = False self.s.connect(('localhost', 0)) self.sendjson('enter', None, self.server) self.rT.start() log.info('Client have been start communicate') while not self.shutdown: try: message = input('') #распознаем команды if re.match(r'/pm \d\d\d', message) is not None: self.sendjson('pmmsg', message[4:], self.server) elif re.match(r'/exit', message) is not None: self.sendjson('exit', None, self.server) print('\n///exit///') self.shutdown = True break elif re.match(r'/help', message) is not None: self.sendjson('help', None, self.server) elif re.match(r'/getonline', message) is not None: self.sendjson('getonline', None, self.server) elif re.match(r'/\w', message) is not None: #неизвестная команда print( 'Unknown command. Type "/help" for redeem a list of all commands' ) elif message != '': #если сообщение не пустое и не явлсяется командой self.sendjson('msg', message, self.server) except Exception as ex: print('Error in sending:\t', ex) log.error(ex) self.shutdown = True break self.rT.join() self.s.close() log.info('Client died')
def start_player(self, i): player_start_command = self.start_commands[i] Popen(player_start_command, stdin=PIPE, stdout=DEV_NULL, stderr=STDOUT, close_fds=True, bufsize=0) # async. execution, instant exit self.check_counters[i] = 0 self.restart_counters[i] += 1 if self.stream_position[i] > 0: self.stream_position[i] = 0 log.info(' --- Player[stream-%d] started with command: (%s)' % (i, repr(player_start_command)))
def fetch_cams_config(self): cam_config_entries = parse_cam_config(CFG_CAM_IP_FILENAME) for i in range(0, MAX_CAM_AMOUNT): cam_config_entry = cam_config_entries[i] cam_address = cam_config_entry.address if not cam_address: cam_status = CAM_STATUS_UNDEFINED else: cam_status = ping(cam_address) self.cams_configs[i] = cam_config_entry self.cams_statuses[i] = cam_status log.info('Camera[%d]: IP=(%s), STATUS=(%s)' % (i + 1, cam_address, cam_status))
def function_test(debug): loglevelset(debug) com = serial_setup() p = [i for i in ports.values()] p.sort() log.debug(str(p)) for k, v in enumerate(p): log.info('Switching to port: {0}'.format(k + 1)) log.info('Using hex code: {0}'.format(v.encode('hex'))) com.write(v) log.info(com.in_waiting) log.info(com.read(com.in_waiting).encode('hex')) log.info(com.read(com.in_waiting).encode('hex')) time.sleep(2) com.close()
def update_model(self): log.info('Entering Ping method...') self.is_enabled = True while self.is_enabled: self.cfg_version = fetch_version() self.cfg_address_mon, self.cfg_netmask_mon = fetch_cfg_mon() self.cfg_serial = fetch_serial_number() self.fetch_cams_config() # wait a while before next data read time.sleep(PING_DELAY) # finish refreshing only after stop invoked... return
def _stop(self): if self.process is not None: try: self.process.stdin.write( KEY_OMXPLAYER_QUIT ) # send quit command 'q' (player must not use '--no-keys' option) self.process.terminate() self.process.wait() log.info('Player[single] gracefully terminated (%s)' % self.process.returncode) return self.process.returncode except EnvironmentError as e: logger.error("Can't stop player[single] %s: %s", self.uri, e) self.process = None return None
def handle_player_single(self): while self._streaming: cams_configs = self._info_collector_thread.cams_configs # not all cams might have been found on startup self._cam_stop_user_request = False any_stream = False for i in range(0, len(cams_configs)): cam_config = cams_configs[i] if cam_config.address: status = self._info_collector_thread.cams_statuses[i] if status == CAM_STATUS_OK: any_stream = True log.info('Starting Player[single] on address: (%s)' % cam_config.main_stream_url()) player_single = Player(i, cam_config.main_stream_url(), WIN_SINGLE) player_single.play() player_single.wait_to_finish( ) # if closed switch automatically to another if not self._streaming: # streaming mode exit was requested break else: log.info( 'Skipping Player[single] camera address: (%s). Not accessible.' % cam_config.main_stream_url()) player_single = Player( i, '/home/haso/camviewer/no_signal.mp4', WIN_SINGLE, False) player_single.play() player_single.wait_to_finish() continue else: log.info( 'Skipping Player[single] camera address: (%s). Not configured.' % cam_config.main_stream_url()) continue # After full cycle if self._cam_stop_user_request and any_stream: log.info("Player[single] stopped manually. Continuing...") continue # cycle again through all cams else: log.info("Player[single] stopped by itself. Exiting...") break # stream was closed (show info screen)
def hdmi_input_switch(port, debug): loglevelset(debug) com = serial_setup() com.reset_input_buffer() com.reset_output_buffer() code = ports['p0{0}'.format(int(port))] com.write(code) log.info('Activated port {0}'.format(int(port))) log.debug(com.in_waiting) log.debug(com.read(com.in_waiting).encode('hex')) log.debug(com.read(com.in_waiting).encode('hex')) # com.flush() com.write(code) log.debug(com.in_waiting) log.debug(com.read(com.in_waiting).encode('hex')) log.debug(com.read(com.in_waiting).encode('hex')) com.close()
def prepare_player_start_command(self, i): # prepare starting script for omxplayer in proper window log.info('Setting up Players[stream-%d]...' % i) cam_config = self.cam_configs[i] address = cam_config.address win_coords = WIN_COORDS[i] screen_name = SCREEN_NAME_PATTERN % i dbus_name = "org.mpris.MediaPlayer2.omxplayer.%s" % screen_name if not address: url = HOME_DIR + VIDEO_NOT_CONFIGURED cmd = "omxplayer --adev hdmi --aidx -1 --timeout 5 --blank --no-keys --no-osd --loop --win %s --dbus_name %s %s" % ( win_coords, dbus_name, url) # NOTE: allowed options are either --live or --no-osd and not both self.stream_position.append(-1) else: url = cam_config.sub_stream_url() cmd = "omxplayer --adev hdmi --aidx -1 --timeout 5 --blank --no-keys --live --aspect-mode fill --avdict rtsp_transport:tcp --win %s --dbus_name %s \"%s\"" % ( win_coords, dbus_name, url ) # quotes around stream are required in some cases self.stream_position.append(0) self.total_stream_count += 1 log.info(' - Player[stream-%d] - omx command: (%s).' % (i, cmd)) script_path = HOME_DIR + ('start%d.sh' % i) store_as_script_on_disk(i, cmd, script_path) # prepare starting commands for current script start_cmd = ['screen', '-dmS', screen_name, "sh", script_path] log.info(' - Player[stream-%d] - start command: (%s).' % (i, start_cmd)) return start_cmd
def main_control_loop(self): fsm.onSysInfo = self.on_state_sys_info fsm.onStreamingSingle = self.on_state_streaming_single fsm.onStreamingSplit = self.on_state_streaming_split fsm.onStreamingAuto = self.on_state_streaming_auto self._async_transition(TRANSITION_INIT) # [NONE] ==init==> [SysInfo] while True: log.info('Waiting for transition...') transition_name = self._transitions_queue.get(block=True) # execute transition - using 'Hollywood principle' in flow control if fsm.can(transition_name): log.info('Executing transition: %s' % transition_name) fsm.trigger(transition_name) else: log.warn( 'Transition (%s) not allowed in state (%s). Skipping...' % (transition_name, fsm.current)) self._transitions_queue.task_done() log.info("Camviewer app stopped.") self._event_handler_thread.stop() self._info_collector_thread.stop() return
def on_state_sys_info(self, e): log.info("Showing sysinfo screen.") if self._auto_close_timer is not None: self._auto_close_timer.cancel() self._auto_close_timer = Timer(AUTO_CLOSE_TIME, self.auto_sysinfo_close) self._auto_close_timer.start() info_window.show() # halts here until window is closed... log.info("Cancelling auto_close_timer...") self._auto_close_timer.cancel() log.info("Exiting sysinfo screen.") if self._mode == MODE_SINGLE: self._async_transition( TRANSITION_CAM_SINGLE ) # [SysInfo] ==view_cam_single==> [StreamingSingle] elif self._mode == MODE_SPLIT: self._async_transition( TRANSITION_CAM_SPLIT ) # [SysInfo] ==view_cam_split==> [StreamingSplit] elif self._mode == MODE_AUTO: self._async_transition( TRANSITION_CAM_AUTO ) # [SysInfo] ==view_cam_auto==> [StreamingAuto] else: log.error("Unknown mode: (%s)" % self._mode)
def action_button_down(self): log.info('Handle DOWN - begin.') if fsm.current == STATE_SYSINFO: self._change_mode() else: log.info('\tHandle DOWN - skipped in state (%s).' % fsm.current) log.info('Handle DOWN - end.')
def action_handle_up(self): log.info('Handle UP - begin.') log.info( ' - Simulating ESC button to stop whatever is currently streamed...' ) self.action_button_esc() full_reboot() log.info('Handle UP - end.')
def login(server, user, pw): """ authenticate user using hash generated from pw """ crypto = Crypt(user, pw) login_hash = crypto.pw_hash_login try: res = requests.get( server + Config.API_LOGIN, auth=(user, login_hash), timeout=Config.CONN_TIMEOUT, verify=Config.VERIFY_SSL_CERT, headers=Config.HEADERS, ) except requests.exceptions.RequestException as e: log.exception("Error in login request") raise LoginException(e) if res.status_code >= 200 and res.status_code < 400: log.info("Login successful") return True else: log.error(f"Login failed: {res.status_code} - {res.text}") raise LoginException(res.text[0:Config.MAX_RESPONSE_LEN])
def full_reboot(): kill_all_omx_processes() command = [ 'sudo', '/usr/bin/fbi', '-T', '1', '--noverbose', '-a', '/home/haso/camviewer/rebooting.jpg' ] Popen(command, stdin=PIPE, stdout=DEV_NULL, stderr=STDOUT, close_fds=True, bufsize=0) time.sleep(3) command = ['sudo', 'reboot'] log.info("Rebooting device with cmd=(%s)" % command) Popen(command, stdin=PIPE, stdout=DEV_NULL, stderr=STDOUT, close_fds=True, bufsize=0)
def action_handle_enter(self): log.info('Handle ENTER - begin.') if fsm.current == STATE_STREAMING_SINGLE: self._next_stream_single() elif fsm.current == STATE_SYSINFO: self._exit_sysinfo() else: log.info('\tHandle ENTER - skipped in state (%s).' % fsm.current) log.info('Handle ENTER - end.')