From cb5c0f82a3086b97d6b6cc332e9c0edd3813bc8b Mon Sep 17 00:00:00 2001 From: Ken Roberts Date: Fri, 19 May 2017 22:51:58 -0700 Subject: [PATCH] PJlink class 2 updates C --- openlp/core/lib/__init__.py | 2 +- openlp/core/lib/projector/db.py | 55 ++++++++++++------- openlp/core/lib/projector/pjlink1.py | 20 ++++--- openlp/core/ui/projector/manager.py | 26 ++++----- .../test_projector_constants.py | 1 - .../openlp_core_lib/test_projector_pjlink1.py | 39 +++++++++---- .../openlp_core_lib/test_projectordb.py | 22 ++++++-- tests/resources/projector/data.py | 20 ++++++- 8 files changed, 122 insertions(+), 63 deletions(-) diff --git a/openlp/core/lib/__init__.py b/openlp/core/lib/__init__.py index 21195096f..a8b5771b6 100644 --- a/openlp/core/lib/__init__.py +++ b/openlp/core/lib/__init__.py @@ -621,5 +621,5 @@ from .imagemanager import ImageManager from .renderer import Renderer from .mediamanageritem import MediaManagerItem from .projector.db import ProjectorDB, Projector -from .projector.pjlink1 import PJLink1 +from .projector.pjlink1 import PJLink from .projector.constants import PJLINK_PORT, ERROR_MSG, ERROR_STRING diff --git a/openlp/core/lib/projector/db.py b/openlp/core/lib/projector/db.py index bff1be00e..11b84b019 100644 --- a/openlp/core/lib/projector/db.py +++ b/openlp/core/lib/projector/db.py @@ -150,11 +150,15 @@ class Projector(CommonBase, Base): name: Column(String(20)) location: Column(String(30)) notes: Column(String(200)) - pjlink_name: Column(String(128)) # From projector (future) - manufacturer: Column(String(128)) # From projector (future) - model: Column(String(128)) # From projector (future) - other: Column(String(128)) # From projector (future) - sources: Column(String(128)) # From projector (future) + pjlink_name: Column(String(128)) # From projector + manufacturer: Column(String(128)) # From projector + model: Column(String(128)) # From projector + other: Column(String(128)) # From projector + sources: Column(String(128)) # From projector + serial_no: Column(String(30)) # From projector (Class 2) + sw_version: Column(String(30)) # From projector (Class 2) + model_filter: Column(String(30)) # From projector (Class 2) + model_lamp: Column(String(30)) # From projector (Class 2) ProjectorSource relates """ @@ -164,20 +168,25 @@ class Projector(CommonBase, Base): """ return '< Projector(id="{data}", ip="{ip}", port="{port}", pin="{pin}", name="{name}", ' \ 'location="{location}", notes="{notes}", pjlink_name="{pjlink_name}", ' \ - 'manufacturer="{manufacturer}", model="{model}", other="{other}", ' \ - 'sources="{sources}", source_list="{source_list}") >'.format(data=self.id, - ip=self.ip, - port=self.port, - pin=self.pin, - name=self.name, - location=self.location, - notes=self.notes, - pjlink_name=self.pjlink_name, - manufacturer=self.manufacturer, - model=self.model, - other=self.other, - sources=self.sources, - source_list=self.source_list) + 'manufacturer="{manufacturer}", model="{model}", serial_no="{serial}", other="{other}", ' \ + 'sources="{sources}", source_list="{source_list}", model_filter="{mfilter}", ' \ + 'model_lamp="{mlamp}", sw_version="{sw_ver}") >'.format(data=self.id, + ip=self.ip, + port=self.port, + pin=self.pin, + name=self.name, + location=self.location, + notes=self.notes, + pjlink_name=self.pjlink_name, + manufacturer=self.manufacturer, + model=self.model, + other=self.other, + sources=self.sources, + source_list=self.source_list, + serial=self.serial_no, + mfilter=self.model_filter, + mlamp=self.model_lamp, + sw_ver=self.sw_version) ip = Column(String(100)) port = Column(String(8)) pin = Column(String(20)) @@ -189,6 +198,10 @@ class Projector(CommonBase, Base): model = Column(String(128)) other = Column(String(128)) sources = Column(String(128)) + serial_no = Column(String(30)) + sw_version = Column(String(30)) + model_filter = Column(String(30)) + model_lamp = Column(String(30)) source_list = relationship('ProjectorSource', order_by='ProjectorSource.code', backref='projector', @@ -359,6 +372,10 @@ class ProjectorDB(Manager): old_projector.model = projector.model old_projector.other = projector.other old_projector.sources = projector.sources + old_projector.serial_no = projector.serial_no + old_projector.sw_version = projector.sw_version + old_projector.model_filter = projector.model_filter + old_projector.model_lamp = projector.model_lamp return self.save_object(old_projector) def delete_projector(self, projector): diff --git a/openlp/core/lib/projector/pjlink1.py b/openlp/core/lib/projector/pjlink1.py index 2af1e9767..2252c566c 100644 --- a/openlp/core/lib/projector/pjlink1.py +++ b/openlp/core/lib/projector/pjlink1.py @@ -42,7 +42,7 @@ log = logging.getLogger(__name__) log.debug('pjlink1 loaded') -__all__ = ['PJLink1'] +__all__ = ['PJLink'] from codecs import decode @@ -68,7 +68,7 @@ PJLINK_HEADER = '{prefix}{{linkclass}}'.format(prefix=PJLINK_PREFIX) PJLINK_SUFFIX = CR -class PJLink1(QtNetwork.QTcpSocket): +class PJLink(QtNetwork.QTcpSocket): """ Socket service for connecting to a PJLink-capable projector. """ @@ -129,7 +129,7 @@ class PJLink1(QtNetwork.QTcpSocket): self.ip = ip self.port = port self.pin = pin - super(PJLink1, self).__init__() + super(PJLink, self).__init__() self.dbid = None self.location = None self.notes = None @@ -162,7 +162,7 @@ class PJLink1(QtNetwork.QTcpSocket): # Socket timer for some possible brain-dead projectors or network cable pulled self.socket_timer = None # Map command to function - self.pjlink1_functions = { + self.pjlink_functions = { 'AVMT': self.process_avmt, 'CLSS': self.process_clss, 'ERST': self.process_erst, @@ -286,7 +286,7 @@ class PJLink1(QtNetwork.QTcpSocket): elif status in STATUS_STRING: return STATUS_STRING[status], ERROR_MSG[status] else: - return status, translate('OpenLP.PJLink1', 'Unknown status') + return status, translate('OpenLP.PJLink', 'Unknown status') def change_status(self, status, msg=None): """ @@ -296,7 +296,7 @@ class PJLink1(QtNetwork.QTcpSocket): :param status: Status code :param msg: Optional message """ - message = translate('OpenLP.PJLink1', 'No message') if msg is None else msg + message = translate('OpenLP.PJLink', 'No message') if msg is None else msg (code, message) = self._get_status(status) if msg is not None: message = msg @@ -576,7 +576,7 @@ class PJLink1(QtNetwork.QTcpSocket): if sent == -1: # Network error? self.change_status(E_NETWORK, - translate('OpenLP.PJLink1', 'Error while sending data to projector')) + translate('OpenLP.PJLink', 'Error while sending data to projector')) def process_command(self, cmd, data): """ @@ -625,8 +625,9 @@ class PJLink1(QtNetwork.QTcpSocket): self.projectorReceivedData.emit() return - if cmd in self.pjlink1_functions: - self.pjlink1_functions[cmd](data) + if cmd in self.pjlink_functions: + log.debug('({ip}) Calling function for {cmd}'.format(ip=self.ip, cmd=cmd)) + self.pjlink_functions[cmd](data) else: log.warning('({ip}) Invalid command {data}'.format(ip=self.ip, data=cmd)) self.send_busy = False @@ -662,6 +663,7 @@ class PJLink1(QtNetwork.QTcpSocket): :param data: Power status """ + log.debug('({ip}: Processing POWR command'.format(ip=self.ip)) if data in PJLINK_POWR_STATUS: power = PJLINK_POWR_STATUS[data] update_icons = self.power != power diff --git a/openlp/core/ui/projector/manager.py b/openlp/core/ui/projector/manager.py index 06ddd9dee..747a63a85 100644 --- a/openlp/core/ui/projector/manager.py +++ b/openlp/core/ui/projector/manager.py @@ -38,7 +38,7 @@ from openlp.core.lib.projector.constants import ERROR_MSG, ERROR_STRING, E_AUTHE E_NETWORK, E_NOT_CONNECTED, E_UNKNOWN_SOCKET_ERROR, STATUS_STRING, S_CONNECTED, S_CONNECTING, S_COOLDOWN, \ S_INITIALIZE, S_NOT_CONNECTED, S_OFF, S_ON, S_STANDBY, S_WARMUP from openlp.core.lib.projector.db import ProjectorDB -from openlp.core.lib.projector.pjlink1 import PJLink1 +from openlp.core.lib.projector.pjlink1 import PJLink from openlp.core.ui.projector.editform import ProjectorEditForm from openlp.core.ui.projector.sourceselectform import SourceSelectTabs, SourceSelectSingle @@ -690,19 +690,19 @@ class ProjectorManager(OpenLPMixin, RegistryMixin, QtWidgets.QWidget, UiProjecto Helper app to build a projector instance :param projector: Dict of projector database information - :returns: PJLink1() instance + :returns: PJLink() instance """ log.debug('_add_projector()') - return PJLink1(dbid=projector.id, - ip=projector.ip, - port=int(projector.port), - name=projector.name, - location=projector.location, - notes=projector.notes, - pin=None if projector.pin == '' else projector.pin, - poll_time=self.poll_time, - socket_timeout=self.socket_timeout - ) + return PJLink(dbid=projector.id, + ip=projector.ip, + port=int(projector.port), + name=projector.name, + location=projector.location, + notes=projector.notes, + pin=None if projector.pin == '' else projector.pin, + poll_time=self.poll_time, + socket_timeout=self.socket_timeout + ) def add_projector(self, projector, start=False): """ @@ -961,7 +961,7 @@ class ProjectorItem(QtCore.QObject): """ Initialization for ProjectorItem instance - :param link: PJLink1 instance for QListWidgetItem + :param link: PJLink instance for QListWidgetItem """ self.link = link self.thread = None diff --git a/tests/functional/openlp_core_lib/test_projector_constants.py b/tests/functional/openlp_core_lib/test_projector_constants.py index 2b6ef948b..4a8e7a9e1 100644 --- a/tests/functional/openlp_core_lib/test_projector_constants.py +++ b/tests/functional/openlp_core_lib/test_projector_constants.py @@ -29,7 +29,6 @@ class TestProjectorConstants(TestCase): """ Test specific functions in the projector constants module. """ - @skip('Waiting for merge of ~alisonken1/openlp/pjlink2-resource-data') def build_pjlink_video_label_test(self): """ Test building PJLINK_DEFAULT_CODES dictionary diff --git a/tests/functional/openlp_core_lib/test_projector_pjlink1.py b/tests/functional/openlp_core_lib/test_projector_pjlink1.py index fadd17bb7..cd62da060 100644 --- a/tests/functional/openlp_core_lib/test_projector_pjlink1.py +++ b/tests/functional/openlp_core_lib/test_projector_pjlink1.py @@ -25,13 +25,13 @@ Package to test the openlp.core.lib.projector.pjlink1 package. from unittest import TestCase from unittest.mock import call, patch, MagicMock -from openlp.core.lib.projector.pjlink1 import PJLink1 +from openlp.core.lib.projector.pjlink1 import PJLink from openlp.core.lib.projector.constants import E_PARAMETER, ERROR_STRING, S_OFF, S_STANDBY, S_ON, \ PJLINK_POWR_STATUS, S_CONNECTED from tests.resources.projector.data import TEST_PIN, TEST_SALT, TEST_CONNECT_AUTHENTICATE, TEST_HASH -pjlink_test = PJLink1(name='test', ip='127.0.0.1', pin=TEST_PIN, no_poll=True) +pjlink_test = PJLink(name='test', ip='127.0.0.1', pin=TEST_PIN, no_poll=True) class TestPJLink(TestCase): @@ -164,23 +164,36 @@ class TestPJLink(TestCase): 'Lamp 3 hours should have been set to 33333') @patch.object(pjlink_test, 'projectorReceivedData') - def test_projector_process_power_on(self, mock_projectorReceivedData): + @patch.object(pjlink_test, 'projectorUpdateIcons') + @patch.object(pjlink_test, 'send_command') + @patch.object(pjlink_test, 'change_status') + def test_projector_process_power_on(self, mock_change_status, + mock_send_command, + mock_UpdateIcons, + mock_ReceivedData): """ Test status power to ON """ # GIVEN: Test object and preset pjlink = pjlink_test pjlink.power = S_STANDBY - pjlink.socket_timer = MagicMock() # WHEN: Call process_command with turn power on command pjlink.process_command('POWR', PJLINK_POWR_STATUS[S_ON]) # THEN: Power should be set to ON self.assertEquals(pjlink.power, S_ON, 'Power should have been set to ON') + mock_send_command.assert_called_once_with('INST') + self.assertEquals(mock_UpdateIcons.emit.called, True, 'projectorUpdateIcons should have been called') @patch.object(pjlink_test, 'projectorReceivedData') - def test_projector_process_power_off(self, mock_projectorReceivedData): + @patch.object(pjlink_test, 'projectorUpdateIcons') + @patch.object(pjlink_test, 'send_command') + @patch.object(pjlink_test, 'change_status') + def test_projector_process_power_off(self, mock_change_status, + mock_send_command, + mock_UpdateIcons, + mock_ReceivedData): """ Test status power to STANDBY """ @@ -193,6 +206,8 @@ class TestPJLink(TestCase): # THEN: Power should be set to STANDBY self.assertEquals(pjlink.power, S_STANDBY, 'Power should have been set to STANDBY') + self.assertEquals(mock_send_command.called, False, 'send_command should not have been called') + self.assertEquals(mock_UpdateIcons.emit.called, True, 'projectorUpdateIcons should have been called') @patch.object(pjlink_test, 'projectorUpdateIcons') def test_projector_process_avmt_closed_unmuted(self, mock_projectorReceivedData): @@ -372,7 +387,7 @@ class TestPJLink(TestCase): @patch.object(pjlink_test, '_not_implemented') def not_implemented_test(self, mock_not_implemented): """ - Test pjlink1._not_implemented method being called + Test PJLink._not_implemented method being called """ # GIVEN: test object pjlink = pjlink_test @@ -381,13 +396,13 @@ class TestPJLink(TestCase): # WHEN: A future command is called that is not implemented yet pjlink.process_command(test_cmd, "Garbage data for test only") - # THEN: pjlink1.__not_implemented should have been called with test_cmd + # THEN: PJLink.__not_implemented should have been called with test_cmd mock_not_implemented.assert_called_with(test_cmd) @patch.object(pjlink_test, 'disconnect_from_host') def socket_abort_test(self, mock_disconnect): """ - Test PJLink1.socket_abort calls disconnect_from_host + Test PJLink.socket_abort calls disconnect_from_host """ # GIVEN: Test object pjlink = pjlink_test @@ -400,7 +415,7 @@ class TestPJLink(TestCase): def poll_loop_not_connected_test(self): """ - Test PJLink1.poll_loop not connected return + Test PJLink.poll_loop not connected return """ # GIVEN: Test object and mocks pjlink = pjlink_test @@ -409,7 +424,7 @@ class TestPJLink(TestCase): pjlink.state.return_value = False pjlink.ConnectedState = True - # WHEN: PJLink1.poll_loop called + # WHEN: PJLink.poll_loop called pjlink.poll_loop() # THEN: poll_loop should exit without calling any other method @@ -418,7 +433,7 @@ class TestPJLink(TestCase): @patch.object(pjlink_test, 'send_command') def poll_loop_start_test(self, mock_send_command): """ - Test PJLink1.poll_loop makes correct calls + Test PJLink.poll_loop makes correct calls """ # GIVEN: test object and test data pjlink = pjlink_test @@ -450,7 +465,7 @@ class TestPJLink(TestCase): call('NAME', queue=True), ] - # WHEN: PJLink1.poll_loop is called + # WHEN: PJLink.poll_loop is called pjlink.poll_loop() # THEN: proper calls were made to retrieve projector data diff --git a/tests/functional/openlp_core_lib/test_projectordb.py b/tests/functional/openlp_core_lib/test_projectordb.py index 52b7f0d2f..6b63ad493 100644 --- a/tests/functional/openlp_core_lib/test_projectordb.py +++ b/tests/functional/openlp_core_lib/test_projectordb.py @@ -26,13 +26,15 @@ record functions. PREREQUISITE: add_record() and get_all() functions validated. """ import os +import shutil from unittest import TestCase from unittest.mock import MagicMock, patch from openlp.core.lib.projector.db import Manufacturer, Model, Projector, ProjectorDB, ProjectorSource, Source from openlp.core.lib.projector.constants import PJLINK_PORT -from tests.resources.projector.data import TEST_DB, TEST1_DATA, TEST2_DATA, TEST3_DATA +from tests.resources.projector.data import TEST_DB_PJLINK1, TEST_DB, TEST1_DATA, TEST2_DATA, TEST3_DATA +from tests.utils.constants import TEST_RESOURCES_PATH def compare_data(one, two): @@ -45,7 +47,11 @@ def compare_data(one, two): one.port == two.port and \ one.name == two.name and \ one.location == two.location and \ - one.notes == two.notes + one.notes == two.notes and \ + one.sw_version == two.sw_version and \ + one.serial_no == two.serial_no and \ + one.model_filter == two.model_filter and \ + one.model_lamp == two.model_lamp def compare_source(one, two): @@ -168,6 +174,10 @@ class TestProjectorDB(TestCase): record.name = TEST3_DATA['name'] record.location = TEST3_DATA['location'] record.notes = TEST3_DATA['notes'] + record.sw_version = TEST3_DATA['sw_version'] + record.serial_no = TEST3_DATA['serial_no'] + record.model_filter = TEST3_DATA['model_filter'] + record.model_lamp = TEST3_DATA['model_lamp'] updated = self.projector.update_projector(record) self.assertTrue(updated, 'Save updated record should have returned True') record = self.projector.get_projector_by_ip(TEST3_DATA['ip']) @@ -246,7 +256,8 @@ class TestProjectorDB(TestCase): projector = Projector() # WHEN: projector() is populated - # NOTE: projector.pin, projector.other, projector.sources should all return None + # NOTE: projector.[pin, other, sources, sw_version, serial_no, sw_version, model_lamp, model_filter] + # should all return None. # projector.source_list should return an empty list projector.id = 0 projector.ip = '127.0.0.1' @@ -262,8 +273,9 @@ class TestProjectorDB(TestCase): self.assertEqual(str(projector), '< Projector(id="0", ip="127.0.0.1", port="4352", pin="None", name="Test One", ' 'location="Somewhere over the rainbow", notes="Not again", pjlink_name="TEST", ' - 'manufacturer="IN YOUR DREAMS", model="OpenLP", other="None", sources="None", ' - 'source_list="[]") >', + 'manufacturer="IN YOUR DREAMS", model="OpenLP", serial_no="None", other="None", ' + 'sources="None", source_list="[]", model_filter="None", model_lamp="None", ' + 'sw_version="None") >', 'Projector.__repr__() should have returned a proper representation string') def test_projectorsource_repr(self): diff --git a/tests/resources/projector/data.py b/tests/resources/projector/data.py index 1c30a87b2..358719015 100644 --- a/tests/resources/projector/data.py +++ b/tests/resources/projector/data.py @@ -27,6 +27,8 @@ import os from tempfile import gettempdir # Test data +TEST_DB_PJLINK1 = 'projector_pjlink1.sqlite' + TEST_DB = os.path.join(gettempdir(), 'openlp-test-projectordb.sql') TEST_SALT = '498e4a67' @@ -44,21 +46,33 @@ TEST1_DATA = dict(ip='111.111.111.111', pin='1111', name='___TEST_ONE___', location='location one', - notes='notes one') + notes='notes one', + serial_no='Serial Number 1', + sw_version='Version 1', + model_filter='Filter type 1', + model_lamp='Lamp type 1') TEST2_DATA = dict(ip='222.222.222.222', port='2222', pin='2222', name='___TEST_TWO___', location='location two', - notes='notes two') + notes='notes one', + serial_no='Serial Number 2', + sw_version='Version 2', + model_filter='Filter type 2', + model_lamp='Lamp type 2') TEST3_DATA = dict(ip='333.333.333.333', port='3333', pin='3333', name='___TEST_THREE___', location='location three', - notes='notes three') + notes='notes one', + serial_no='Serial Number 3', + sw_version='Version 3', + model_filter='Filter type 3', + model_lamp='Lamp type 3') TEST_VIDEO_CODES = { '11': 'RGB 1',