diff --git a/openlp/core/projectors/constants.py b/openlp/core/projectors/constants.py index 5350c1206..3648a9d42 100644 --- a/openlp/core/projectors/constants.py +++ b/openlp/core/projectors/constants.py @@ -37,6 +37,7 @@ PJLINK_MAX_PACKET = 136 PJLINK_PREFIX = '%' PJLINK_PORT = 4352 PJLINK_SUFFIX = CR +PJLINK_SVER_MAX_LEN = 32 PJLINK_TIMEOUT = 30.0 PJLINK_TOKEN_SIZE = 8 # PJLINK 1 : where is 8 characters diff --git a/openlp/core/projectors/manager.py b/openlp/core/projectors/manager.py index da1ff4dee..04ece3c9e 100644 --- a/openlp/core/projectors/manager.py +++ b/openlp/core/projectors/manager.py @@ -497,7 +497,7 @@ class ProjectorManager(QtWidgets.QWidget, RegistryBase, UiProjectorManager, LogM if ans == msg.Cancel: return try: - projector.link.changeStatus.disconnect(self.update_status) + projector.link.projectorChangeStatus.disconnect(self.update_status) except (AttributeError, TypeError): pass try: @@ -717,7 +717,7 @@ class ProjectorManager(QtWidgets.QWidget, RegistryBase, UiProjectorManager, LogM widget.setData(QtCore.Qt.UserRole, item) item.pjlink.db_item = item.db_item item.widget = widget - item.pjlink.changeStatus.connect(self.update_status) + item.pjlink.projectorChangeStatus.connect(self.update_status) item.pjlink.projectorAuthentication.connect(self.authentication_error) item.pjlink.projectorNoAuthentication.connect(self.no_authentication_error) item.pjlink.projectorUpdateIcons.connect(self.update_icons) diff --git a/openlp/core/projectors/pjlink.py b/openlp/core/projectors/pjlink.py index 9acb8c0a9..779722194 100644 --- a/openlp/core/projectors/pjlink.py +++ b/openlp/core/projectors/pjlink.py @@ -186,12 +186,14 @@ class PJLink(QtNetwork.QTcpSocket): Socket services for PJLink TCP packets. """ # Signals sent by this module - changeStatus = QtCore.pyqtSignal(str, int, str) + projectorChangeStatus = QtCore.pyqtSignal(str, int, str) projectorStatus = QtCore.pyqtSignal(int) # Status update projectorAuthentication = QtCore.pyqtSignal(str) # Authentication error projectorNoAuthentication = QtCore.pyqtSignal(str) # PIN set and no authentication needed projectorReceivedData = QtCore.pyqtSignal() # Notify when received data finished processing projectorUpdateIcons = QtCore.pyqtSignal() # Update the status icons on toolbar + # Deprecated + changeStatus = projectorChangeStatus # Use projectorChangeStatus def __init__(self, projector, *args, **kwargs): """ @@ -207,7 +209,8 @@ class PJLink(QtNetwork.QTcpSocket): log.debug(f'PJLink(projector="{projector}", args="{args}" kwargs="{kwargs}")') super().__init__() self.settings_section = 'projector' - self.entry = projector + self.db = projector + self.entry = self.db # Deprecated use self.db self.ip = self.entry.ip self.qhost = QtNetwork.QHostAddress(self.ip) self.location = self.entry.location diff --git a/openlp/core/projectors/pjlinkcommands.py b/openlp/core/projectors/pjlinkcommands.py index 554ad5b05..5cc0e9564 100644 --- a/openlp/core/projectors/pjlinkcommands.py +++ b/openlp/core/projectors/pjlinkcommands.py @@ -49,14 +49,19 @@ import string from openlp.core.common.registry import Registry from openlp.core.projectors.constants import E_AUTHENTICATION, PJLINK_DEFAULT_CODES, PJLINK_ERRORS, \ - PJLINK_ERST_DATA, PJLINK_ERST_LIST, PJLINK_ERST_STATUS, PJLINK_POWR_STATUS, PJLINK_TOKEN_SIZE, \ - E_NO_AUTHENTICATION, S_AUTHENTICATE, S_CONNECT, S_DATA_OK, S_OFF, S_OK, S_ON, S_STANDBY, STATUS_MSG + PJLINK_ERST_DATA, PJLINK_ERST_LIST, PJLINK_ERST_STATUS, PJLINK_POWR_STATUS, PJLINK_SVER_MAX_LEN, \ + PJLINK_TOKEN_SIZE, E_NO_AUTHENTICATION, S_AUTHENTICATE, S_CONNECT, S_DATA_OK, S_OFF, S_OK, S_ON, \ + S_STANDBY, STATUS_MSG log = logging.getLogger(__name__) log.debug('Loading pjlinkcommands') __all__ = ['process_command'] +_pjlink_functions = {} +# Helper until I update the rest of the tests +pjlink_functions = _pjlink_functions + # This should be the only function that's imported. def process_command(projector, cmd, data): @@ -103,16 +108,34 @@ def process_ackn(projector, data): pass -def process_avmt(projector, data): +_pjlink_functions['ACKN'] = process_ackn + + +def _process_avmt_mute(projector, data): + """ + Helper to set projector.mute + """ + projector.mute = data + + +def _process_avmt_shutter(projector, data): + """ + Helper to set projector.shutter + """ + projector.shutter = data + + +def _process_avmt(projector, data): """ Process shutter and speaker status. See PJLink specification for format. - Update projector.mute (audio) and projector.shutter (video shutter). + + Update projector.mute (audio mute) and projector.shutter (video mute). 10 = Shutter open, audio unchanged 11 = Shutter closed, audio unchanged - 20 = Shutter unchanged, Audio normal - 21 = Shutter unchanged, Audio muted - 30 = Shutter open, audio muted - 31 = Shutter closed, audio normal + 20 = Shutter unchanged, audio normal + 21 = Shutter unchanged, audio mute + 30 = Shutter open, audio normal + 31 = Shutter closed, audio mute :param projector: Projector instance :param data: Shutter and audio status @@ -125,25 +148,26 @@ def process_avmt(projector, data): '31': {'shutter': True, 'mute': True} } if data not in settings: - log.warning('({ip}) Invalid av mute response: {data}'.format(ip=projector.entry.name, data=data)) + log.warning(f'({projector.entry.name}) Invalid av mute response: {data}') return shutter = settings[data]['shutter'] mute = settings[data]['mute'] - # Check if we need to update the icons - update_icons = (shutter != projector.shutter) or (mute != projector.mute) + update_icons = False + if projector.shutter != shutter: + _process_avmt_shutter(projector=projector, data=shutter) + update_icons = True + log.debug(f'({projector.entry.name}) Setting shutter to {"closed" if shutter else "open"}') + if projector.mute != mute: + _process_avmt_mute(projector=projector, data=mute) + projector.mute = mute + update_icons = True + log.debug(f'({projector.entry.name}) Setting speaker to {"muted" if mute else "normal"}') if update_icons: - if projector.shutter != shutter: - projector.shutter = shutter - log.debug('({ip}) Setting shutter to {chk}'.format(ip=projector.entry.name, - chk='closed' if shutter else 'open')) - if projector.mute != mute: - projector.mute = mute - log.debug('({ip}) Setting speaker to {chk}'.format(ip=projector.entry.name, - chk='muted' if shutter else 'normal')) - if 'AVMT' in projector.status_timer_checks: - projector.status_timer_delete('AVMT') projector.projectorUpdateIcons.emit() - return + projector.status_timer_delete('AVMT') + + +_pjlink_functions['AVMT'] = _process_avmt def process_clss(projector, data): @@ -178,14 +202,14 @@ def process_clss(projector, data): clss = data projector.pjlink_class = clss log.debug(f'({projector.entry.name}) Setting pjlink_class for this projector to "{projector.pjlink_class}"') - if projector.no_poll: - return + if not projector.no_poll: + # Since we call this one on first connect, setup polling from here + log.debug(f'({projector.entry.name}) process_pjlink(): Starting timer') + projector.poll_timer.setInterval(1000) # Set 1 second for initial information + projector.poll_timer.start() - # Since we call this one on first connect, setup polling from here - log.debug(f'({projector.entry.name}) process_pjlink(): Starting timer') - projector.poll_timer.setInterval(1000) # Set 1 second for initial information - projector.poll_timer.start() - return + +_pjlink_functions['CLSS'] = process_clss def process_erst(projector, data): @@ -198,13 +222,11 @@ def process_erst(projector, data): """ if len(data) != PJLINK_ERST_DATA['DATA_LENGTH']: count = PJLINK_ERST_DATA['DATA_LENGTH'] - log.warning('({ip}) Invalid error status response "{data}": length != {count}'.format(ip=projector.entry.name, - data=data, - count=count)) + log.warning(f'({projector.entry.name}) Invalid error status response "{data}": length != {count}') return if not data.isnumeric(): # Bad data - ignore - log.warning('({ip}) Invalid error status response "{data}"'.format(ip=projector.entry.name, data=data)) + log.warning(f'({projector.entry.name}) Invalid error status response "{data}"') return if int(data) == 0: projector.projector_errors = None @@ -233,6 +255,9 @@ def process_erst(projector, data): return +_pjlink_functions['ERST'] = process_erst + + def process_inf1(projector, data): """ Manufacturer name set in projector. @@ -242,11 +267,13 @@ def process_inf1(projector, data): :param data: Projector manufacturer """ projector.manufacturer = data - log.debug('({ip}) Setting projector manufacturer data to "{data}"'.format(ip=projector.entry.name, - data=projector.manufacturer)) + log.debug(f'({projector.entry.name}) Setting projector manufacturer data to "{projector.manufacturer}"') return +_pjlink_functions['INF1'] = process_inf1 + + def process_inf2(projector, data): """ Projector Model set in projector. @@ -256,10 +283,13 @@ def process_inf2(projector, data): :param data: Model name """ projector.model = data - log.debug('({ip}) Setting projector model to "{data}"'.format(ip=projector.entry.name, data=projector.model)) + log.debug(f'({projector.entry.name}) Setting projector model to "{projector.model}"') return +_pjlink_functions['INF2'] = process_inf2 + + def process_info(projector, data): """ Any extra info set in projector. @@ -269,11 +299,13 @@ def process_info(projector, data): :param data: Projector other info """ projector.other_info = data - log.debug('({ip}) Setting projector other_info to "{data}"'.format(ip=projector.entry.name, - data=projector.other_info)) + log.debug(f'({projector.entry.name}) Setting projector other_info to "{projector.other_info}"') return +_pjlink_functions['INFO'] = process_info + + def process_inpt(projector, data): """ Current source input selected. See PJLink specification for format. @@ -286,19 +318,20 @@ def process_inpt(projector, data): if projector.source_available is not None: # We have available inputs, so verify it's in the list if data not in projector.source_available: - log.warning('({ip}) Input source not listed in available sources - ' - 'ignoring'.format(ip=projector.entry.name)) + log.warning(f'({projector.entry.name}) Input source not listed in available sources - ignoring') return elif data not in PJLINK_DEFAULT_CODES: # Hmm - no sources available yet, so check with PJLink defaults - log.warning('({ip}) Input source not listed as a PJLink valid source ' - '- ignoring'.format(ip=projector.entry.name)) + log.warning(f'({projector.entry.name}) Input source not listed as a PJLink valid source - ignoring') return projector.source = data - log.debug('({ip}) Setting current source to "{data}"'.format(ip=projector.entry.name, data=projector.source)) + log.debug(f'({projector.entry.name}) Setting current source to "{projector.source}"') return +_pjlink_functions['INPT'] = process_inpt + + def process_inst(projector, data): """ Available source inputs. See PJLink specification for format. @@ -313,12 +346,14 @@ def process_inst(projector, data): sources.append(source) sources.sort() projector.source_available = sources - log.debug('({ip}) Setting projector source_available to "{data}"'.format(ip=projector.entry.name, - data=projector.source_available)) + log.debug(f'({projector.entry.name}) Setting projector source_available to "{projector.source_available}"') projector.projectorUpdateIcons.emit() return +_pjlink_functions['INST'] = process_inst + + def process_lamp(projector, data): """ Lamp(s) status. See PJLink Specifications for format. @@ -332,14 +367,13 @@ def process_lamp(projector, data): lamp_list = data.split() if len(lamp_list) < 2: # Invalid data - not enough information - log.warning('({ip}) process_lamp(): Invalid data "{data}" - ' - 'Missing data'.format(ip=projector.entry.name, data=data)) + log.warning(f'({projector.entry.name}) process_lamp(): Invalid data "{data}" - Missing data') return else: while lamp_list: if not lamp_list[0].isnumeric() or not lamp_list[1].isnumeric(): # Invalid data - we'll ignore the rest for now - log.warning('({ip}) process_lamp(): Invalid data "{data}"'.format(ip=projector.entry.name, data=data)) + log.warning(f'({projector.entry.name}) process_lamp(): Invalid data "{data}"') return fill = {'Hours': int(lamp_list[0]), 'On': False if lamp_list[1] == '0' else True} lamps.append(fill) @@ -349,18 +383,24 @@ def process_lamp(projector, data): return -def process_lkup(projector, data): +_pjlink_functions['LAMP'] = process_lamp + + +def _process_lkup(projector, data): """ Process UDP request indicating remote is available for connection :param projector: Projector instance :param data: Data packet from remote """ - log.debug('({ip}) Processing LKUP command'.format(ip=projector.entry.name)) + log.debug(f'({projector.entry.name}) Processing LKUP command') if Registry().get('settings').value('projector/connect when LKUP received'): projector.connect_to_host() +_pjlink_functions['LKUP'] = _process_lkup + + def process_name(projector, data): """ Projector name set in projector. @@ -370,11 +410,13 @@ def process_name(projector, data): :param data: Projector name """ projector.pjlink_name = data - log.debug('({ip}) Setting projector PJLink name to "{data}"'.format(ip=projector.entry.name, - data=projector.pjlink_name)) + log.debug(f'({projector.entry.name}) Setting projector PJLink name to "{projector.pjlink_name}"') return +_pjlink_functions['NAME'] = process_name + + def process_pjlink(projector, data): """ Process initial socket connection to terminal. @@ -419,6 +461,9 @@ def process_pjlink(projector, data): return S_AUTHENTICATE +_pjlink_functions['PJLINK'] = process_pjlink + + def process_powr(projector, data): """ Power status. See PJLink specification for format. @@ -427,15 +472,14 @@ def process_powr(projector, data): :param projector: Projector instance :param data: Power status """ - log.debug('({ip}) Processing POWR command'.format(ip=projector.entry.name)) + log.debug(f'({projector.entry.name}) Processing POWR command') if data not in PJLINK_POWR_STATUS: # Log unknown status response - log.warning('({ip}) Unknown power response: "{data}"'.format(ip=projector.entry.name, data=data)) + log.warning(f'({projector.entry.name}) Unknown power response: "{data}"') return power = PJLINK_POWR_STATUS[data] - update_icons = projector.power != power - if update_icons: + if projector.power != power: projector.power = power projector.change_status(PJLINK_POWR_STATUS[data]) projector.projectorUpdateIcons.emit() @@ -443,11 +487,14 @@ def process_powr(projector, data): # Input sources list should only be available after power on, so update here projector.send_command('INST') - if projector.power in [S_ON, S_STANDBY, S_OFF] and 'POWR' in projector.status_timer_checks: + if projector.power in [S_ON, S_STANDBY, S_OFF]: projector.status_timer_delete(cmd='POWR') return +_pjlink_functions['POWR'] = process_powr + + def process_rfil(projector, data): """ Process replacement filter type @@ -458,9 +505,12 @@ def process_rfil(projector, data): if projector.model_filter is None: projector.model_filter = data else: - log.warning('({ip}) Filter model already set'.format(ip=projector.entry.name)) - log.warning('({ip}) Saved model: "{old}"'.format(ip=projector.entry.name, old=projector.model_filter)) - log.warning('({ip}) New model: "{new}"'.format(ip=projector.entry.name, new=data)) + log.warning(f'({projector.entry.name}) Filter model already set') + log.warning(f'({projector.entry.name}) Saved model: "{projector.model_filter}"') + log.warning(f'({projector.entry.name}) New model: "{data}"') + + +_pjlink_functions['RFIL'] = process_rfil def process_rlmp(projector, data): @@ -473,9 +523,12 @@ def process_rlmp(projector, data): if projector.model_lamp is None: projector.model_lamp = data else: - log.warning('({ip}) Lamp model already set'.format(ip=projector.entry.name)) - log.warning('({ip}) Saved lamp: "{old}"'.format(ip=projector.entry.name, old=projector.model_lamp)) - log.warning('({ip}) New lamp: "{new}"'.format(ip=projector.entry.name, new=data)) + log.warning(f'({projector.entry.name}) Lamp model already set') + log.warning(f'({projector.entry.name}) Saved lamp: "{projector.model_lamp}"') + log.warning(f'({projector.entry.name}) New lamp: "{data}"') + + +_pjlink_functions['RLMP'] = process_rlmp def process_snum(projector, data): @@ -486,22 +539,24 @@ def process_snum(projector, data): :param data: Serial number from projector. """ if projector.serial_no is None: - log.debug('({ip}) Setting projector serial number to "{data}"'.format(ip=projector.entry.name, data=data)) + log.debug(f'({projector.entry.name}) Setting projector serial number to "{data}"') projector.serial_no = data projector.db_update = False return # Compare serial numbers and see if we got the same projector if projector.serial_no != data: - log.warning('({ip}) Projector serial number does not match saved serial ' - 'number'.format(ip=projector.entry.name)) - log.warning('({ip}) Saved: "{old}"'.format(ip=projector.entry.name, old=projector.serial_no)) - log.warning('({ip}) Received: "{new}"'.format(ip=projector.entry.name, new=data)) - log.warning('({ip}) NOT saving serial number'.format(ip=projector.entry.name)) + log.warning(f'({projector.entry.name}) Projector serial number does not match saved serial number') + log.warning(f'({projector.entry.name}) Saved: "{projector.serial_no}"') + log.warning(f'({projector.entry.name}) Received: "{data}"') + log.warning(f'({projector.entry.name}) NOT saving serial number') projector.serial_no_received = data -def process_srch(projector=None, data=None): +_pjlink_functions['SNUM'] = process_snum + + +def _process_srch(projector=None, data=None): """ Process the SRCH command. @@ -512,58 +567,38 @@ def process_srch(projector=None, data=None): :param projector: Projector instance (actually ignored for this command) :param data: Data in packet """ - if projector is None: - log.warning('SRCH packet detected - ignoring') - else: - log.warning(f'({projector.entry.name}) SRCH packet detected - ignoring') - return + msg = 'SRCH packet detected - ignoring' + name = '' + if projector is not None: + name = f'({projector.entry.name}) ' + log.warning(f'{name}{msg}') -def process_sver(projector, data): +_pjlink_functions['SRCH'] = _process_srch + + +def _process_sver(projector, data): """ Software version of projector :param projector: Projector instance :param data: Software version of projector """ - if len(data) > 32: - # Defined in specs max version is 32 characters - log.warning('Invalid software version - too long') + if len(data) > PJLINK_SVER_MAX_LEN: + # Defined in specs 0-32 characters max + log.warning(f'({projector.name}) Invalid software version - too long') return - if projector.sw_version is not None: - if projector.sw_version == data: - log.debug('({ip}) Software version same as saved version - returning'.format(ip=projector.entry.name)) - return - log.warning('({ip}) Projector software version does not match saved ' - 'software version'.format(ip=projector.entry.name)) - log.warning('({ip}) Saved: "{old}"'.format(ip=projector.entry.name, old=projector.sw_version)) - log.warning('({ip}) Received: "{new}"'.format(ip=projector.entry.name, new=data)) - log.warning('({ip}) Updating software version'.format(ip=projector.entry.name)) + elif projector.sw_version == data: + log.debug(f'({projector.name}) Software version unchanged - returning') + return + elif projector.sw_version is not None: + log.debug(f'({projector.name}) Old software version "{projector.sw_version}"') + log.debug(f'({projector.name}) New software version "{data}"') - log.debug('({ip}) Setting projector software version to "{data}"'.format(ip=projector.entry.name, data=data)) + # Software version changed - save + log.debug(f'({projector.entry.name}) Setting projector software version to "{data}"') projector.sw_version = data projector.db_update = True -# Map command to function. -pjlink_functions = { - 'ACKN': process_ackn, # Class 2 (command is SRCH) - 'AVMT': process_avmt, - 'CLSS': process_clss, - 'ERST': process_erst, - 'INFO': process_info, - 'INF1': process_inf1, - 'INF2': process_inf2, - 'INPT': process_inpt, - 'INST': process_inst, - 'LAMP': process_lamp, - 'LKUP': process_lkup, # Class 2 (terminal request only - no cmd) - 'NAME': process_name, - 'PJLINK': process_pjlink, - 'POWR': process_powr, - 'SNUM': process_snum, - 'SRCH': process_srch, # Class 2 (reply is ACKN) - 'SVER': process_sver, - 'RFIL': process_rfil, - 'RLMP': process_rlmp -} +_pjlink_functions['SVER'] = _process_sver diff --git a/tests/helpers/projector.py b/tests/helpers/projector.py index 58319739d..271512312 100644 --- a/tests/helpers/projector.py +++ b/tests/helpers/projector.py @@ -25,7 +25,7 @@ Help classes/functions for PJLink Projector tests from unittest.mock import MagicMock from PyQt5 import QtNetwork -from openlp.core.projectors.constants import S_OK, S_NOT_CONNECTED +from openlp.core.projectors.constants import S_NOT_CONNECTED, S_OFF, S_OK from openlp.core.projectors.db import Projector from tests.resources.projector.data import TEST1_DATA @@ -57,8 +57,10 @@ class FakePJLink(object): """ Helper class with signals and methods mocked """ - def __init__(self, projector=None, *args, **kwargs): + def __init__(self, projector=Projector(**TEST1_DATA), *args, **kwargs): # Signal mocks + self.changeStatus = MagicMock() # Deprecated use projectorChangeStatus + self.projectorChangeStatus = MagicMock() self.projectorStatus = MagicMock() self.projectorAuthentication = MagicMock() self.projectorNoAuthentication = MagicMock() @@ -66,7 +68,7 @@ class FakePJLink(object): self.projectorUpdateIcons = MagicMock() # Method mocks - self.changeStatus = MagicMock() + self.change_status = MagicMock() self.connect_to_host = MagicMock() self.disconnect_from_host = MagicMock() self.poll_timer = MagicMock() @@ -75,8 +77,10 @@ class FakePJLink(object): self.set_shutter_closed = MagicMock() self.set_shutter_open = MagicMock() self.socket_timer = MagicMock() - self.status_timer = MagicMock() self.state = MagicMock() + self.status_timer = MagicMock() + self.status_timer_add = MagicMock() + self.status_timer_delete = MagicMock() # Some tests that may include what it thinks are ProjectorItem() # If ProjectorItem() is called, will probably overwrite these - OK @@ -84,19 +88,20 @@ class FakePJLink(object): self.pjlink = self # Normal entries from PJLink - self.entry = Projector(**TEST1_DATA) if projector is None else projector - self.ip = self.entry.ip + self.db = projector + self.entry = self.db # Deprecated use self.db + self.ip = self.db.ip self.qhost = QtNetwork.QHostAddress(self.ip) - self.location = self.entry.location - self.mac_adx = self.entry.mac_adx - self.name = self.entry.name - self.notes = self.entry.notes - self.pin = self.entry.pin - self.port = int(self.entry.port) - self.pjlink_class = "1" if self.entry.pjlink_class is None else self.entry.pjlink_class - self.poll_time = 20000 if 'poll_time' not in kwargs else kwargs['poll_time'] * 1000 - self.socket_timeout = 5000 if 'socket_timeout' not in kwargs else kwargs['socket_timeout'] * 1000 - self.no_poll = 'no_poll' in kwargs + self.location = self.db.location + self.mac_adx = self.db.mac_adx + self.name = self.db.name + self.notes = self.db.notes + self.pin = self.db.pin + self.port = int(self.db.port) + self.pjlink_class = "1" if self.db.pjlink_class is None else self.db.pjlink_class + self.poll_time = 20000 + self.socket_timeout = 5000 + self.no_poll = True self.status_connect = S_NOT_CONNECTED self.last_command = '' self.projector_status = S_NOT_CONNECTED @@ -105,4 +110,25 @@ class FakePJLink(object): self.priority_queue = [] self.send_busy = False self.status_timer_checks = {} # Keep track of events for the status timer - # Default mock return values + + # reset_information attributes + self.fan = None # ERST + self.filter_time = None # FILT + self.lamp = None # LAMP + self.mac_adx_received = None # ACKN + self.manufacturer = None # INF1 + self.model = None # INF2 + self.model_filter = None # RFIL + self.model_lamp = None # RLMP + self.mute = None # AVMT + self.other_info = None # INFO + self.pjlink_name = None # NAME + self.power = S_OFF # POWR + self.projector_errors = {} # Full ERST errors + self.serial_no = None # SNUM + self.serial_no_received = None + self.sw_version = None # SVER + self.sw_version_received = None + self.shutter = None # AVMT + self.source_available = None # INST + self.source = None # INPT diff --git a/tests/openlp_core/projectors/commands/test_avmt.py b/tests/openlp_core/projectors/commands/test_avmt.py new file mode 100644 index 000000000..f3aa35176 --- /dev/null +++ b/tests/openlp_core/projectors/commands/test_avmt.py @@ -0,0 +1,222 @@ +# -*- coding: utf-8 -*- + +########################################################################## +# OpenLP - Open Source Lyrics Projection # +# ---------------------------------------------------------------------- # +# Copyright (c) 2008-2022 OpenLP Developers # +# ---------------------------------------------------------------------- # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see . # +########################################################################## + +""" +Test _process_avmt +""" + +import logging + +import openlp.core.projectors.pjlinkcommands + +from unittest.mock import patch + +test_module = openlp.core.projectors.pjlinkcommands.__name__ +_process_avmt = openlp.core.projectors.pjlinkcommands._process_avmt + + +def test_avmt_mute(fake_pjlink): + """ + Test _proces_avmt_mute helper + """ + # GIVEN: Test setup + fake_pjlink.mute = False + + # WHEN: Called + openlp.core.projectors.pjlinkcommands._process_avmt_mute(projector=fake_pjlink, data=True) + + # THEN: mute should have been changed + assert fake_pjlink.mute is True, 'Mute did not change' + + +def test_avmt_shutter(fake_pjlink): + """ + Test _proces_avmt_shutter helper + """ + # GIVEN: Test setup + fake_pjlink.shutter = False + + # WHEN: Called + openlp.core.projectors.pjlinkcommands._process_avmt_shutter(projector=fake_pjlink, data=True) + + # THEN: mute should have been changed + assert fake_pjlink.shutter is True, 'Mute did not change' + + +@patch.object(openlp.core.projectors.pjlinkcommands, '_process_avmt_mute') +@patch.object(openlp.core.projectors.pjlinkcommands, '_process_avmt_shutter') +def test_avmt_bad_data(mock_shutter, mock_mute, fake_pjlink, caplog): + """ + Test avmt bad data fail + """ + # GIVEN: Test setup + t_data = '36' + caplog.set_level(logging.DEBUG) + logs = [(test_module, logging.WARNING, f'({fake_pjlink.name}) Invalid av mute response: {t_data}')] + + # WHEN: Called with an invalid setting + caplog.clear() + _process_avmt(projector=fake_pjlink, data=t_data) + + # THEN: No other calls made + assert caplog.record_tuples == logs, 'Invalid log entries' + mock_mute.assert_not_called() + mock_shutter.assert_not_called() + fake_pjlink.projectorUpdateIcons.assert_not_called() + fake_pjlink.status_timer_delete.assert_not_called() + + +@patch.object(openlp.core.projectors.pjlinkcommands, '_process_avmt_mute') +@patch.object(openlp.core.projectors.pjlinkcommands, '_process_avmt_shutter') +def test_avmt_10(mock_shutter, mock_mute, fake_pjlink, caplog): + """ + Test 10 = Shutter open, audio unchanged + """ + # GIVEN: Test setup + t_data = '10' + + caplog.set_level(logging.DEBUG) + logs = [(test_module, logging.DEBUG, f'({fake_pjlink.name}) Setting shutter to open')] + + # WHEN: Called + _process_avmt(projector=fake_pjlink, data=t_data) + + # THEN: Shutter and mute should be set correctly + assert caplog.record_tuples == logs, 'Invalid log entries' + mock_mute.assert_not_called() + mock_shutter.assert_called_with(projector=fake_pjlink, data=False) + fake_pjlink.projectorUpdateIcons.emit.assert_called_once() + fake_pjlink.status_timer_delete.assert_called_once_with('AVMT') + + +@patch.object(openlp.core.projectors.pjlinkcommands, '_process_avmt_mute') +@patch.object(openlp.core.projectors.pjlinkcommands, '_process_avmt_shutter') +def test_avmt_11(mock_shutter, mock_mute, fake_pjlink, caplog): + """ + Test 11 = Shutter closed, audio unchanged + """ + # GIVEN: Test setup + t_data = '11' + caplog.set_level(logging.DEBUG) + logs = [(test_module, logging.DEBUG, f'({fake_pjlink.name}) Setting shutter to closed')] + + # WHEN: Called with setting shutter closed and mute on + _process_avmt(projector=fake_pjlink, data=t_data) + + # THEN: Shutter and mute should be set correctly + assert caplog.record_tuples == logs, 'Invalid log entries' + mock_mute.assert_not_called() + mock_shutter.assert_called_once_with(projector=fake_pjlink, data=True) + fake_pjlink.projectorUpdateIcons.emit.assert_called_once() + fake_pjlink.status_timer_delete.assert_called_once_with('AVMT') + + +@patch.object(openlp.core.projectors.pjlinkcommands, '_process_avmt_mute') +@patch.object(openlp.core.projectors.pjlinkcommands, '_process_avmt_shutter') +def test_avmt_20(mock_shutter, mock_mute, fake_pjlink, caplog): + """ + Test 20 = Shutter unchanged, audio normal + """ + # GIVEN: Test setup + t_data = '20' + caplog.set_level(logging.DEBUG) + logs = [(test_module, logging.DEBUG, f'({fake_pjlink.name}) Setting speaker to normal')] + + # WHEN: Called with setting shutter closed and mute on + _process_avmt(projector=fake_pjlink, data=t_data) + + # THEN: Shutter and mute should be set correctly + assert caplog.record_tuples == logs, 'Invalid log entries' + mock_mute.assert_called_once_with(projector=fake_pjlink, data=False) + mock_shutter.assert_not_called() + fake_pjlink.projectorUpdateIcons.emit.assert_called_once() + fake_pjlink.status_timer_delete.assert_called_once_with('AVMT') + + +@patch.object(openlp.core.projectors.pjlinkcommands, '_process_avmt_mute') +@patch.object(openlp.core.projectors.pjlinkcommands, '_process_avmt_shutter') +def test_avmt_21(mock_shutter, mock_mute, fake_pjlink, caplog): + """ + Test 21 = Shutter unchanged, audio mute + """ + # GIVEN: Test setup + t_data = '21' + caplog.set_level(logging.DEBUG) + logs = [(test_module, logging.DEBUG, f'({fake_pjlink.name}) Setting speaker to muted')] + + # WHEN: Called with setting shutter closed and mute on + _process_avmt(projector=fake_pjlink, data=t_data) + + # THEN: Shutter and mute should be set correctly + assert caplog.record_tuples == logs, 'Invalid log entries' + mock_mute.assert_called_once_with(projector=fake_pjlink, data=True) + mock_shutter.assert_not_called() + fake_pjlink.projectorUpdateIcons.emit.assert_called_once() + fake_pjlink.status_timer_delete.assert_called_once_with('AVMT') + + +@patch.object(openlp.core.projectors.pjlinkcommands, '_process_avmt_mute') +@patch.object(openlp.core.projectors.pjlinkcommands, '_process_avmt_shutter') +def test_avmt_30(mock_shutter, mock_mute, fake_pjlink, caplog): + """ + Test 30 = Shutter open, audio normal + """ + # GIVEN: Test setup + t_data = '30' + + caplog.set_level(logging.DEBUG) + logs = [(test_module, logging.DEBUG, f'({fake_pjlink.name}) Setting shutter to open'), + (test_module, logging.DEBUG, f'({fake_pjlink.name}) Setting speaker to normal') + ] + + # WHEN: Called + _process_avmt(projector=fake_pjlink, data=t_data) + + # THEN: Shutter and mute should be set correctly + assert caplog.record_tuples == logs, 'Invalid log entries' + mock_mute.assert_called_once_with(projector=fake_pjlink, data=False) + mock_shutter.assert_called_once_with(projector=fake_pjlink, data=False) + fake_pjlink.projectorUpdateIcons.emit.assert_called_once() + fake_pjlink.status_timer_delete.assert_called_once_with('AVMT') + + +@patch.object(openlp.core.projectors.pjlinkcommands, '_process_avmt_mute') +@patch.object(openlp.core.projectors.pjlinkcommands, '_process_avmt_shutter') +def test_avmt_31(mock_shutter, mock_mute, fake_pjlink, caplog): + """ + Test 31 = Shutter closed, audio mute + """ + # GIVEN: Test object + t_data = '31' + + caplog.set_level(logging.DEBUG) + logs = [(test_module, logging.DEBUG, f'({fake_pjlink.name}) Setting shutter to closed'), + (test_module, logging.DEBUG, f'({fake_pjlink.name}) Setting speaker to muted') + ] + # WHEN: Called + _process_avmt(projector=fake_pjlink, data=t_data) + + # THEN: Shutter and mute should be set correctly + assert caplog.record_tuples == logs, 'Invalid log entries' + mock_mute.assert_called_once_with(projector=fake_pjlink, data=True) + mock_shutter.assert_called_once_with(projector=fake_pjlink, data=True) + fake_pjlink.projectorUpdateIcons.emit.assert_called_once() + fake_pjlink.status_timer_delete.assert_called_once_with('AVMT') diff --git a/tests/openlp_core/projectors/commands/test_misc_commands.py b/tests/openlp_core/projectors/commands/test_misc.py similarity index 64% rename from tests/openlp_core/projectors/commands/test_misc_commands.py rename to tests/openlp_core/projectors/commands/test_misc.py index dd2f50c56..e2765b8a5 100644 --- a/tests/openlp_core/projectors/commands/test_misc_commands.py +++ b/tests/openlp_core/projectors/commands/test_misc.py @@ -26,9 +26,43 @@ Tests for commands that do not need much testing import logging import openlp.core.projectors.pjlinkcommands -from openlp.core.projectors.pjlinkcommands import process_srch - test_module = openlp.core.projectors.pjlinkcommands.__name__ +_process_lkup = openlp.core.projectors.pjlinkcommands._process_lkup +_process_srch = openlp.core.projectors.pjlinkcommands._process_srch + + +def test_lkup_connect(fake_pjlink, settings, caplog): + """ + Test LKUP when settings indicate connect + """ + # GIVEN: Test setup + caplog.set_level(logging.DEBUG) + logs = [(test_module, logging.DEBUG, f'({fake_pjlink.name}) Processing LKUP command')] + settings.setValue('projector/connect when LKUP received', True) + + # WHEN: Called + _process_lkup(projector=fake_pjlink, data=None) + + # THEN: Only log entry made + assert caplog.record_tuples == logs, 'Invalid log entries' + fake_pjlink.connect_to_host.assert_called_once() + + +def test_lkup_no_connect(fake_pjlink, settings, caplog): + """ + Test LKUP when settings indicate no connect + """ + # GIVEN: Test setup + caplog.set_level(logging.DEBUG) + logs = [(test_module, logging.DEBUG, f'({fake_pjlink.name}) Processing LKUP command')] + settings.setValue('projector/connect when LKUP received', False) + + # WHEN: Called + _process_lkup(projector=fake_pjlink, data=None) + + # THEN: Only log entry made + assert caplog.record_tuples == logs, 'Invalid log entries' + fake_pjlink.connect_to_host.assert_not_called() def test_srch_no_projector(caplog): @@ -40,7 +74,7 @@ def test_srch_no_projector(caplog): logs = [(f'{test_module}', logging.WARNING, 'SRCH packet detected - ignoring')] # WHEN: Called - t_chk = process_srch() + t_chk = _process_srch() # THEN: Appropriate return code and log entries assert t_chk is None, 'Invalid return code' @@ -57,7 +91,7 @@ def test_srch_with_projector(pjlink, caplog): f'({pjlink.entry.name}) SRCH packet detected - ignoring')] # WHEN: Called - t_chk = process_srch(projector=pjlink) + t_chk = _process_srch(projector=pjlink) # THEN: Appropriate return code and log entries assert t_chk is None, 'Invalid return code' diff --git a/tests/openlp_core/projectors/commands/test_pjlink.py b/tests/openlp_core/projectors/commands/test_pjlink.py index e3496bc43..82cd32033 100644 --- a/tests/openlp_core/projectors/commands/test_pjlink.py +++ b/tests/openlp_core/projectors/commands/test_pjlink.py @@ -24,28 +24,16 @@ Test process_pjlink method import logging import openlp.core.projectors.pjlinkcommands -import pytest from openlp.core.projectors.pjlinkcommands import process_pjlink from openlp.core.projectors.constants import E_AUTHENTICATION, E_NO_AUTHENTICATION, \ S_AUTHENTICATE, S_CONNECT -from tests.helpers.projector import FakeProjector from tests.resources.projector.data import TEST_PIN, TEST_SALT test_module = openlp.core.projectors.pjlinkcommands.__name__ -@pytest.fixture -def fake_pjlink(): - """ - Helper since we don't need a full-blown PJLink() instance - """ - dumb_projector = FakeProjector() - yield dumb_projector - del(dumb_projector) - - def test_normal_no_authentication_type(fake_pjlink, caplog): """ Test login prompt with not enough parameters @@ -147,6 +135,7 @@ def test_normal_login(fake_pjlink, caplog): (f'{test_module}', logging.DEBUG, f'({fake_pjlink.entry.name}) PJLINK: Returning S_CONNECT') ] + fake_pjlink.pin = None # WHEN: Calling function caplog.clear() @@ -230,7 +219,6 @@ def test_authenticate_invalid_salt(fake_pjlink, caplog): # GIVEN: Test setup caplog.set_level(logging.DEBUG) t_data = '1 1a2b3c4g' - print(t_data) logs = [(f'{test_module}', logging.DEBUG, f'({fake_pjlink.entry.name}) Processing PJLINK command'), (f'{test_module}', logging.ERROR, @@ -253,12 +241,12 @@ def test_authenticate_no_pin(fake_pjlink, caplog): # GIVEN: Test setup caplog.set_level(logging.DEBUG) t_data = f'1 {TEST_SALT}' - print(t_data) logs = [(f'{test_module}', logging.DEBUG, f'({fake_pjlink.entry.name}) Processing PJLINK command'), (f'{test_module}', logging.ERROR, f'({fake_pjlink.entry.name}) Authenticate connection but no PIN - aborting') ] + fake_pjlink.pin = None # WHEN: Calling function caplog.clear() @@ -276,7 +264,6 @@ def test_authenticate_login(fake_pjlink, caplog): # GIVEN: Test setup caplog.set_level(logging.DEBUG) t_data = f'1 {TEST_SALT}' - print(t_data) logs = [(f'{test_module}', logging.DEBUG, f'({fake_pjlink.entry.name}) Processing PJLINK command'), (f'{test_module}', logging.DEBUG, diff --git a/tests/openlp_core/projectors/commands/test_sver.py b/tests/openlp_core/projectors/commands/test_sver.py new file mode 100644 index 000000000..48ec35b04 --- /dev/null +++ b/tests/openlp_core/projectors/commands/test_sver.py @@ -0,0 +1,120 @@ +# -*- coding: utf-8 -*- + +########################################################################## +# OpenLP - Open Source Lyrics Projection # +# ---------------------------------------------------------------------- # +# Copyright (c) 2008-2022 OpenLP Developers # +# ---------------------------------------------------------------------- # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see . # +########################################################################## + +""" +Tests for commands that do not need much testing +""" + +import logging +import openlp.core.projectors.pjlinkcommands + +from copy import deepcopy + +from openlp.core.projectors.constants import PJLINK_SVER_MAX_LEN + +from tests.resources.projector.data import TEST1_DATA, TEST2_DATA + +test_module = openlp.core.projectors.pjlinkcommands.__name__ +_process_sver = openlp.core.projectors.pjlinkcommands._process_sver + + +def test_sver_none(fake_pjlink, caplog): + """ + Test SVER update when saved version is None + """ + # GIVEN: Test setup + fake_pjlink.sw_version = None + fake_pjlink.db_update = False + t_data = deepcopy(TEST1_DATA['sw_version']) + caplog.set_level(logging.DEBUG) + logs = [(test_module, logging.DEBUG, f'({fake_pjlink.name}) Setting projector software version to "{t_data}"')] + + # WHEN: Called + _process_sver(projector=fake_pjlink, data=t_data) + + # THEN: Only log entry made + assert caplog.record_tuples == logs, 'Invalid log entries' + assert fake_pjlink.sw_version == t_data, 'sw_version should have updated' + assert fake_pjlink.db_update is True, 'db_update should be set' + + +def test_sver_same(fake_pjlink, caplog): + """ + Test SVER same as saved version + """ + # GIVEN: Test setup + fake_pjlink.sw_version = deepcopy(TEST1_DATA['sw_version']) + fake_pjlink.db_update = False + t_data = fake_pjlink.sw_version + caplog.set_level(logging.DEBUG) + logs = [(test_module, logging.DEBUG, f'({fake_pjlink.name}) Software version unchanged - returning')] + + # WHEN: Called + _process_sver(projector=fake_pjlink, data=t_data) + + # THEN: Only log entry made + assert caplog.record_tuples == logs, 'Invalid log entries' + assert fake_pjlink.sw_version == t_data, 'sw_version should not have changed' + assert fake_pjlink.db_update is False, 'db_update should not have changed' + + +def test_sver_too_long(fake_pjlink, caplog): + """ + Test SVER too long + """ + # GIVEN: Test setup + fake_pjlink.sw_version = None + fake_pjlink.db_update = False + t_data = '1' * PJLINK_SVER_MAX_LEN + t_data += 'z' # One longer than max length + caplog.set_level(logging.DEBUG) + logs = [(test_module, logging.WARNING, f'({fake_pjlink.name}) Invalid software version - too long')] + + # WHEN: Called + caplog.clear() + _process_sver(projector=fake_pjlink, data=t_data) + + # THEN: Only log entry made + assert caplog.record_tuples == logs, 'Invalid log entries' + assert fake_pjlink.sw_version is None, 'sw_version should not have changed' + assert fake_pjlink.db_update is False, 'db_update should not have changed' + + +def test_sver_update(fake_pjlink, caplog): + """ + Test SVER update when saved version is different than received version + """ + # GIVEN: Test setup + fake_pjlink.sw_version = deepcopy(TEST1_DATA['sw_version']) + fake_pjlink.db_update = False + t_data = deepcopy(TEST2_DATA['sw_version']) + caplog.set_level(logging.DEBUG) + logs = [(test_module, logging.DEBUG, f'({fake_pjlink.name}) Old software version "{fake_pjlink.sw_version}"'), + (test_module, logging.DEBUG, f'({fake_pjlink.name}) New software version "{t_data}"'), + (test_module, logging.DEBUG, f'({fake_pjlink.name}) Setting projector software version to "{t_data}"')] + + # WHEN: Called + _process_sver(projector=fake_pjlink, data=t_data) + + # THEN: Only log entry made + assert caplog.record_tuples == logs, 'Invalid log entries' + assert fake_pjlink.sw_version == t_data, 'sw_version should have updated' + assert fake_pjlink.db_update is True, 'db_update should be set' diff --git a/tests/openlp_core/projectors/conftest.py b/tests/openlp_core/projectors/conftest.py index f06c706e8..fb8a5ae0f 100644 --- a/tests/openlp_core/projectors/conftest.py +++ b/tests/openlp_core/projectors/conftest.py @@ -28,6 +28,7 @@ from unittest.mock import patch from openlp.core.projectors.db import Projector, ProjectorDB from openlp.core.projectors.manager import ProjectorManager from openlp.core.projectors.pjlink import PJLink +from tests.helpers.projector import FakePJLink from tests.resources.projector.data import TEST_DB, TEST1_DATA ''' @@ -78,6 +79,13 @@ def projector_manager_mtdb(settings): del t_manager +@pytest.fixture +def fake_pjlink(): + faker = FakePJLink() + yield faker + del(faker) + + @pytest.fixture() def pjlink(): pj_link = PJLink(Projector(**TEST1_DATA), no_poll=True) diff --git a/tests/openlp_core/projectors/test_projector_commands_01.py b/tests/openlp_core/projectors/test_projector_commands_01.py index 56c802e9a..e81d71b4c 100644 --- a/tests/openlp_core/projectors/test_projector_commands_01.py +++ b/tests/openlp_core/projectors/test_projector_commands_01.py @@ -44,161 +44,6 @@ def test_projector_ackn(mock_log, pjlink): mock_log.debug.assert_has_calls(log_debug_text) -@patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') -@patch.object(openlp.core.projectors.pjlinkcommands, 'log') -def test_projector_avmt_audio_muted(mock_log, mock_UpdateIcons, pjlink): - """ - Test avmt status shutter unchanged and mute on - """ - # GIVEN: Test setup - log_warning_text = [] - log_debug_text = [call('({ip}) Processing command "AVMT" with data "21"'.format(ip=pjlink.name)), - call('({ip}) Calling function for AVMT'.format(ip=pjlink.name)), - call('({ip}) Setting speaker to muted'.format(ip=pjlink.name))] - pjlink.shutter = True - pjlink.mute = False - - # WHEN: Called with setting shutter closed and mute on - process_command(projector=pjlink, cmd='AVMT', data='21') - - # THEN: Shutter should be closed and mute should be True - assert pjlink.shutter, 'Shutter should not have changed' - assert pjlink.mute, 'Audio should be off' - assert mock_UpdateIcons.emit.called, 'Update icons should have been called' - mock_log.warning.assert_has_calls(log_warning_text) - mock_log.debug.assert_has_calls(log_debug_text) - - -@patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') -@patch.object(openlp.core.projectors.pjlinkcommands, 'log') -def test_projector_avmt_bad_data(mock_log, mock_UpdateIcons, pjlink): - """ - Test avmt bad data fail - """ - # GIVEN: Test object - log_warning_text = [call('({ip}) Invalid av mute response: 36'.format(ip=pjlink.name))] - log_debug_text = [call('({ip}) Processing command "AVMT" with data "36"'.format(ip=pjlink.name)), - call('({ip}) Calling function for AVMT'.format(ip=pjlink.name))] - pjlink.shutter = True - pjlink.mute = True - - # WHEN: Called with an invalid setting - process_command(projector=pjlink, cmd='AVMT', data='36') - - # THEN: Shutter should be closed and mute should be True - assert pjlink.shutter, 'Shutter should changed' - assert pjlink.mute, 'Audio should not have changed' - assert not mock_UpdateIcons.emit.called, 'Update icons should NOT have been called' - mock_log.warning.assert_has_calls(log_warning_text) - mock_log.debug.assert_has_calls(log_debug_text) - - -@patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') -@patch.object(openlp.core.projectors.pjlinkcommands, 'log') -def test_projector_avmt_closed_muted(mock_log, mock_UpdateIcons, pjlink): - """ - Test avmt status shutter closed and mute off - """ - # GIVEN: Test object - log_warning_text = [] - log_debug_text = [call('({ip}) Processing command "AVMT" with data "31"'.format(ip=pjlink.name)), - call('({ip}) Calling function for AVMT'.format(ip=pjlink.name)), - call('({ip}) Setting shutter to closed'.format(ip=pjlink.name)), - call('({ip}) Setting speaker to muted'.format(ip=pjlink.name))] - pjlink.shutter = False - pjlink.mute = False - - # WHEN: Called with setting shutter to closed and mute on - process_command(projector=pjlink, cmd='AVMT', data='31') - - # THEN: Shutter should be closed and mute should be True - assert pjlink.shutter, 'Shutter should have been set to closed' - assert pjlink.mute, 'Audio should be muted' - assert mock_UpdateIcons.emit.called, 'Update icons should have been called' - mock_log.warning.assert_has_calls(log_warning_text) - mock_log.debug.assert_has_calls(log_debug_text) - - -@patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') -@patch.object(openlp.core.projectors.pjlinkcommands, 'log') -def test_projector_avmt_open_unmuted(mock_log, mock_UpdateIcons, pjlink): - """ - Test avmt status shutter open and mute off - """ - # GIVEN: Test object - log_warning_text = [] - log_debug_text = [call('({ip}) Processing command "AVMT" with data "30"'.format(ip=pjlink.name)), - call('({ip}) Calling function for AVMT'.format(ip=pjlink.name)), - call('({ip}) Setting shutter to open'.format(ip=pjlink.name)), - call('({ip}) Setting speaker to normal'.format(ip=pjlink.name))] - pjlink.shutter = True - pjlink.mute = True - - # WHEN: Called with setting shutter to closed and mute on - process_command(projector=pjlink, cmd='AVMT', data='30') - - # THEN: Shutter should be closed and mute should be True - assert not pjlink.shutter, 'Shutter should have been set to off' - assert not pjlink.mute, 'Audio should be on' - assert mock_UpdateIcons.emit.called, 'Update icons should have been called' - mock_log.warning.assert_has_calls(log_warning_text) - mock_log.debug.assert_has_calls(log_debug_text) - - -@patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') -@patch.object(openlp.core.projectors.pjlinkcommands, 'log') -def test_projector_avmt_shutter_closed(mock_log, mock_UpdateIcons, pjlink): - """ - Test avmt status shutter closed and audio unchanged - """ - # GIVEN: Test object - log_warning_text = [] - log_debug_text = [call('({ip}) Processing command "AVMT" with data "11"'.format(ip=pjlink.name)), - call('({ip}) Calling function for AVMT'.format(ip=pjlink.name)), - call('({ip}) Setting shutter to closed'.format(ip=pjlink.name))] - pjlink.shutter = False - pjlink.mute = True - - # WHEN: Called with setting shutter closed and mute off - process_command(projector=pjlink, cmd='AVMT', data='11') - - # THEN: Shutter should be True and mute should be False - assert pjlink.shutter, 'Shutter should have been set to closed' - assert pjlink.mute, 'Audio should not have changed' - assert mock_UpdateIcons.emit.called, 'Update icons should have been called' - mock_log.warning.assert_has_calls(log_warning_text) - mock_log.debug.assert_has_calls(log_debug_text) - - -@patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') -@patch.object(openlp.core.projectors.pjlinkcommands, 'log') -def test_projector_avmt_status_timer_check_delete(mock_log, mock_UpdateIcons, pjlink): - """ - Test avmt deletes callback in projector.status_timer_check - """ - # GIVEN: Test object - log_warning_text = [] - log_debug_text = [call('({ip}) Processing command "AVMT" with data "11"'.format(ip=pjlink.name)), - call('({ip}) Calling function for AVMT'.format(ip=pjlink.name)), - call('({ip}) Setting shutter to closed'.format(ip=pjlink.name))] - pjlink.shutter = False - pjlink.mute = True - pjlink.status_timer_checks = {'AVMT': pjlink.get_av_mute_status} - - # WHEN: Called with setting shutter closed and mute off - with patch.object(pjlink, 'status_timer') as mock_status_timer: - process_command(projector=pjlink, cmd='AVMT', data='11') - - # THEN: Shutter should be True and mute should be False - assert pjlink.shutter, 'Shutter should have been set to closed' - assert pjlink.mute, 'Audio should not have changed' - assert mock_UpdateIcons.emit.called, 'Update icons should have been called' - assert 'AVMT' not in pjlink.status_timer_checks, 'Status timer list should not have AVMT callback' - assert mock_status_timer.stop.called, 'Projector status_timer.stop() should have been called' - mock_log.warning.assert_has_calls(log_warning_text) - mock_log.debug.assert_has_calls(log_debug_text) - - @patch.object(openlp.core.projectors.pjlinkcommands, 'log') def test_projector_erst_all_error(mock_log, pjlink): """ diff --git a/tests/openlp_core/projectors/test_projector_commands_02.py b/tests/openlp_core/projectors/test_projector_commands_02.py index 7d23f4058..d2dac46dd 100644 --- a/tests/openlp_core/projectors/test_projector_commands_02.py +++ b/tests/openlp_core/projectors/test_projector_commands_02.py @@ -468,82 +468,3 @@ def test_projector_snum_set(mock_log, pjlink): assert pjlink.serial_no == new_data, 'Projector serial number should have been set' mock_log.warning.assert_has_calls(log_warning_calls) mock_log.debug.assert_has_calls(log_debug_calls) - - -@patch.object(openlp.core.projectors.pjlinkcommands, 'log') -def test_projector_sver_changed(mock_log, pjlink): - """ - Test invalid software version information - Received different than saved - """ - # GIVEN: Test object - old_data = 'Test 1 Subtest 1' - new_data = 'Test 1 Subtest 2' - log_warning_calls = [call('({ip}) Projector software version does not match ' - 'saved software version'.format(ip=pjlink.name)), - call('({ip}) Saved: "{data}"'.format(ip=pjlink.name, data=old_data)), - call('({ip}) Received: "{data}"'.format(ip=pjlink.name, data=new_data)), - call('({ip}) Updating software version'.format(ip=pjlink.name))] - log_debug_calls = [call('({ip}) Processing command "SVER" with data ' - '"{data}"'.format(ip=pjlink.name, data=new_data)), - call('({ip}) Calling function for SVER'.format(ip=pjlink.name)), - call('({ip}) Setting projector software version to ' - '"{data}"'.format(ip=pjlink.name, data=new_data))] - pjlink.sw_version = old_data - - # WHEN: process_sver called with invalid data - process_command(pjlink, cmd='SVER', data=new_data) - - # THEN: Version information should change - assert pjlink.sw_version == new_data, 'Software version should have changed' - mock_log.warning.assert_has_calls(log_warning_calls) - mock_log.debug.assert_has_calls(log_debug_calls) - - -@patch.object(openlp.core.projectors.pjlinkcommands, 'log') -def test_projector_sver_invalid(mock_log, pjlink): - """ - Test invalid software version information - too long - """ - # GIVEN: Test object - new_data = 'This is a test software version line that is too long based on PJLink version 2 specs' - log_warning_calls = [call('Invalid software version - too long')] - log_debug_calls = [call('({ip}) Processing command "SVER" with data "{data}"'.format(ip=pjlink.name, - data=new_data)), - call('({ip}) Calling function for SVER'.format(ip=pjlink.name))] - pjlink.sw_version = None - pjlink.sw_version_received = None - - # WHEN: process_sver called with invalid data - process_command(projector=pjlink, cmd='SVER', data=new_data) - - # THEN: Version information should not change - assert not pjlink.sw_version, 'Software version should not have changed' - assert not pjlink.sw_version_received, 'Received software version should not have changed' - mock_log.warning.assert_has_calls(log_warning_calls) - mock_log.debug.assert_has_calls(log_debug_calls) - - -@patch.object(openlp.core.projectors.pjlinkcommands, 'log') -def test_projector_sver_save(mock_log, pjlink): - """ - Test invalid software version information - too long - """ - # GIVEN: Test object - new_data = 'Test 1 Subtest 1' - log_warning_calls = [] - log_debug_calls = [call('({ip}) Processing command "SVER" with data ' - '"{data}"'.format(ip=pjlink.name, data=new_data)), - call('({ip}) Calling function for SVER'.format(ip=pjlink.name)), - call('({ip}) Setting projector software version to ' - '"{data}"'.format(ip=pjlink.name, data=new_data))] - pjlink.sw_version = None - pjlink.sw_version_received = None - - # WHEN: process_sver called with invalid data - process_command(projector=pjlink, cmd='SVER', data=new_data) - - # THEN: Version information should not change - assert pjlink.sw_version == new_data, 'Software version should have been updated' - assert not pjlink.sw_version_received, 'Received version field should not have changed' - mock_log.warning.assert_has_calls(log_warning_calls) - mock_log.debug.assert_has_calls(log_debug_calls)