openlp-core team mailing list archive
-
openlp-core team
-
Mailing list archive
-
Message #32092
[Merge] lp:~alisonken1/openlp/pjlink2-k into lp:openlp
Ken Roberts has proposed merging lp:~alisonken1/openlp/pjlink2-k into lp:openlp.
Commit message:
PJLink2 update K
Requested reviews:
OpenLP Core (openlp-core)
For more details, see:
https://code.launchpad.net/~alisonken1/openlp/pjlink2-k/+merge/331191
PJlink2 update K
- Update notes in PJLink-Notes.odt/update PDF
- Add PJLink.get_socket() (process socket data)
- Add PJLink.get_buffer() (process non-socket data)
- Update PJLink.get_data() to work with get_socket/get_buffer
- Cleanup ProjectorManager code
- Fix incorrect note reference to song db in test_projector_db
- Fix projector tests for change to PJLink() creation
- Start PJLinkUDP class
- Remove unused pjlink2.py module
- Code oops cleanups
[SUCCESS] https://ci.openlp.io/job/Branch-01-Pull/2199/
[SUCCESS] https://ci.openlp.io/job/Branch-02-Functional-Tests/2102/
[SUCCESS] https://ci.openlp.io/job/Branch-03-Interface-Tests/1989/
[SUCCESS] https://ci.openlp.io/job/Branch-04a-Code_Analysis/1359/
[SUCCESS] https://ci.openlp.io/job/Branch-04b-Test_Coverage/1192/
[SUCCESS] https://ci.openlp.io/job/Branch-04c-Code_Analysis2/322/
[FAILURE] https://ci.openlp.io/job/Branch-05-AppVeyor-Tests/162/
--
Your team OpenLP Core is requested to review the proposed merge of lp:~alisonken1/openlp/pjlink2-k into lp:openlp.
=== modified file 'documentation/PJLink_Notes.odt'
Binary files documentation/PJLink_Notes.odt 2017-09-09 06:57:21 +0000 and documentation/PJLink_Notes.odt 2017-09-22 12:12:22 +0000 differ
=== modified file 'documentation/PJLink_Notes.pdf'
Binary files documentation/PJLink_Notes.pdf 2017-09-09 06:57:21 +0000 and documentation/PJLink_Notes.pdf 2017-09-22 12:12:22 +0000 differ
=== modified file 'openlp/core/lib/projector/db.py'
--- openlp/core/lib/projector/db.py 2017-06-25 02:21:07 +0000
+++ openlp/core/lib/projector/db.py 2017-09-22 12:12:22 +0000
@@ -341,9 +341,9 @@
"""
old_projector = self.get_object_filtered(Projector, Projector.ip == projector.ip)
if old_projector is not None:
- log.warning('add_new() skipping entry ip="{ip}" (Already saved)'.format(ip=old_projector.ip))
+ log.warning('add_projector() skipping entry ip="{ip}" (Already saved)'.format(ip=old_projector.ip))
return False
- log.debug('add_new() saving new entry')
+ log.debug('add_projector() saving new entry')
log.debug('ip="{ip}", name="{name}", location="{location}"'.format(ip=projector.ip,
name=projector.name,
location=projector.location))
=== modified file 'openlp/core/lib/projector/pjlink.py'
--- openlp/core/lib/projector/pjlink.py 2017-08-23 19:46:30 +0000
+++ openlp/core/lib/projector/pjlink.py 2017-09-22 12:12:22 +0000
@@ -72,6 +72,28 @@
PJLINK_SUFFIX = CR
+class PJLinkUDP(QtNetwork.QUdpSocket):
+ """
+ Socket service for PJLink UDP socket.
+ """
+ # New commands available in PJLink Class 2
+ pjlink_udp_commands = [
+ 'ACKN', # Class 2 (cmd is SRCH)
+ 'ERST', # Class 1/2
+ 'INPT', # Class 1/2
+ 'LKUP', # Class 2 (reply only - no cmd)
+ 'POWR', # Class 1/2
+ 'SRCH' # Class 2 (reply is ACKN)
+ ]
+
+ def __init__(self, port=PJLINK_PORT):
+ """
+ Initialize socket
+ """
+
+ self.port = port
+
+
class PJLinkCommands(object):
"""
Process replies from PJLink projector.
@@ -488,7 +510,7 @@
class PJLink(PJLinkCommands, QtNetwork.QTcpSocket):
"""
- Socket service for connecting to a PJLink-capable projector.
+ Socket service for PJLink TCP socket.
"""
# Signals sent by this module
changeStatus = QtCore.pyqtSignal(str, int, str)
@@ -499,43 +521,29 @@
projectorReceivedData = QtCore.pyqtSignal() # Notify when received data finished processing
projectorUpdateIcons = QtCore.pyqtSignal() # Update the status icons on toolbar
- # New commands available in PJLink Class 2
- pjlink_udp_commands = [
- 'ACKN', # Class 2
- 'ERST', # Class 1 or 2
- 'INPT', # Class 1 or 2
- 'LKUP', # Class 2
- 'POWR', # Class 1 or 2
- 'SRCH' # Class 2
- ]
-
- def __init__(self, port=PJLINK_PORT, *args, **kwargs):
+ def __init__(self, projector, *args, **kwargs):
"""
Setup for instance.
Options should be in kwargs except for port which does have a default.
- :param name: Display name
- :param ip: IP address to connect to
- :param port: Port to use. Default to PJLINK_PORT
- :param pin: Access pin (if needed)
+ :param projector: Database record of projector
Optional parameters
- :param dbid: Database ID number
- :param location: Location where projector is physically located
- :param notes: Extra notes about the projector
:param poll_time: Time (in seconds) to poll connected projector
:param socket_timeout: Time (in seconds) to abort the connection if no response
"""
- log.debug('PJlink(args={args} kwargs={kwargs})'.format(args=args, kwargs=kwargs))
+ log.debug('PJlink(projector={projector}, args={args} kwargs={kwargs})'.format(projector=projector,
+ args=args,
+ kwargs=kwargs))
super().__init__()
- self.dbid = kwargs.get('dbid')
- self.ip = kwargs.get('ip')
- self.location = kwargs.get('location')
- self.mac_adx = kwargs.get('mac_adx')
- self.name = kwargs.get('name')
- self.notes = kwargs.get('notes')
- self.pin = kwargs.get('pin')
- self.port = port
+ self.entry = projector
+ self.ip = self.entry.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 = self.entry.port
self.db_update = False # Use to check if db needs to be updated prior to exiting
# Poll time 20 seconds unless called with something else
self.poll_time = 20000 if 'poll_time' not in kwargs else kwargs['poll_time'] * 1000
@@ -751,7 +759,7 @@
self.change_status(E_AUTHENTICATION)
log.debug('({ip}) emitting projectorAuthentication() signal'.format(ip=self.ip))
return
- elif data_check[1] == '0' and self.pin is not None:
+ elif (data_check[1] == '0') and (self.pin):
# Pin set and no authentication needed
log.warning('({ip}) Regular connection but PIN set'.format(ip=self.name))
self.disconnect_from_host()
@@ -761,7 +769,7 @@
return
elif data_check[1] == '1':
# Authenticated login with salt
- if self.pin is None:
+ if not self.pin:
log.warning('({ip}) Authenticated connection but no pin set'.format(ip=self.ip))
self.disconnect_from_host()
self.change_status(E_AUTHENTICATION)
@@ -776,7 +784,7 @@
else:
data_hash = None
# We're connected at this point, so go ahead and setup regular I/O
- self.readyRead.connect(self.get_data)
+ self.readyRead.connect(self.get_socket)
self.projectorReceivedData.connect(self._send_command)
# Initial data we should know about
self.send_command(cmd='CLSS', salt=data_hash)
@@ -800,27 +808,51 @@
count=trash_count))
return
+ @QtCore.pyqtSlot(str, str)
+ def get_buffer(self, data, ip):
+ """
+ Get data from somewhere other than TCP socket
+
+ :param data: Data to process. buffer must be formatted as a proper PJLink packet.
+ :param ip: Destination IP for buffer.
+ """
+ log.debug("({ip}) get_buffer(data='{buff}' ip='{ip_in}'".format(ip=self.ip, buff=data, ip_in=ip))
+ if ip is None:
+ log.debug("({ip}) get_buffer() Don't know who data is for - exiting".format(ip=self.ip))
+ return
+ return self.get_data(buff=data, ip=ip)
+
@QtCore.pyqtSlot()
- def get_data(self):
- """
- Socket interface to retrieve data.
- """
- log.debug('({ip}) get_data(): Reading data'.format(ip=self.ip))
+ def get_socket(self):
+ """
+ Get data from TCP socket.
+ """
+ log.debug('({ip}) get_socket(): Reading data'.format(ip=self.ip))
if self.state() != self.ConnectedState:
- log.debug('({ip}) get_data(): Not connected - returning'.format(ip=self.ip))
+ log.debug('({ip}) get_socket(): Not connected - returning'.format(ip=self.ip))
self.send_busy = False
return
# Although we have a packet length limit, go ahead and use a larger buffer
read = self.readLine(1024)
- log.debug("({ip}) get_data(): '{buff}'".format(ip=self.ip, buff=read))
+ log.debug("({ip}) get_socket(): '{buff}'".format(ip=self.ip, buff=read))
if read == -1:
# No data available
- log.debug('({ip}) get_data(): No data available (-1)'.format(ip=self.ip))
+ log.debug('({ip}) get_socket(): No data available (-1)'.format(ip=self.ip))
return self.receive_data_signal()
self.socket_timer.stop()
self.projectorNetwork.emit(S_NETWORK_RECEIVED)
+ return self.get_data(buff=read, ip=self.ip)
+
+ def get_data(self, buff, ip):
+ """
+ Process received data
+
+ :param buff: Data to process.
+ :param ip: (optional) Destination IP.
+ """
+ log.debug("({ip}) get_data(ip='{ip_in}' buffer='{buff}'".format(ip=self.ip, ip_in=ip, buff=buff))
# NOTE: Class2 has changed to some values being UTF-8
- data_in = decode(read, 'utf-8')
+ data_in = decode(buff, 'utf-8')
data = data_in.strip()
if (len(data) < 7) or (not data.startswith(PJLINK_PREFIX)):
return self._trash_buffer(msg='get_data(): Invalid packet - length or prefix')
@@ -990,7 +1022,7 @@
self.reset_information()
self.disconnectFromHost()
try:
- self.readyRead.disconnect(self.get_data)
+ self.readyRead.disconnect(self.get_socket)
except TypeError:
pass
if abort:
=== removed file 'openlp/core/lib/projector/pjlink2.py'
--- openlp/core/lib/projector/pjlink2.py 2017-07-07 23:43:50 +0000
+++ openlp/core/lib/projector/pjlink2.py 1970-01-01 00:00:00 +0000
@@ -1,85 +0,0 @@
-# -*- coding: utf-8 -*-
-# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
-
-###############################################################################
-# OpenLP - Open Source Lyrics Projection #
-# --------------------------------------------------------------------------- #
-# Copyright (c) 2008-2017 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; version 2 of the License. #
-# #
-# 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, write to the Free Software Foundation, Inc., 59 #
-# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
-###############################################################################
-"""
- :mod:`openlp.core.lib.projector.pjlink2` module provides the PJLink Class 2
- updates from PJLink Class 1.
-
- This module only handles the UDP socket functionality. Command/query/status
- change messages will still be processed by the PJLink 1 module.
-
- Currently, the only variance is the addition of a UDP "search" command to
- query the local network for Class 2 capable projectors,
- and UDP "notify" messages from projectors to connected software of status
- changes (i.e., power change, input change, error changes).
-
- Differences between Class 1 and Class 2 PJLink specifications are as follows.
-
- New Functionality:
- * Search - UDP Query local network for Class 2 capabable projector(s).
- * Status - UDP Status change with connected projector(s). Status change
- messages consist of:
- * Initial projector power up when network communication becomes available
- * Lamp off/standby to warmup or on
- * Lamp on to cooldown or off/standby
- * Input source select change completed
- * Error status change (i.e., fan/lamp/temp/cover open/filter/other error(s))
-
- New Commands:
- * Query serial number of projector
- * Query version number of projector software
- * Query model number of replacement lamp
- * Query model number of replacement air filter
- * Query current projector screen resolution
- * Query recommended screen resolution
- * Query name of specific input terminal (video source)
- * Adjust projector microphone in 1-step increments
- * Adjust projector speacker in 1-step increments
-
- Extended Commands:
- * Addition of INTERNAL terminal (video source) for a total of 6 types of terminals.
- * Number of terminals (video source) has been expanded from [1-9]
- to [1-9a-z] (Addition of 26 terminals for each type of input).
-
- See PJLink Class 2 Specifications for details.
- http://pjlink.jbmia.or.jp/english/dl_class2.html
-
- Section 5-1 PJLink Specifications
-
- Section 5-5 Guidelines for Input Terminals
-"""
-import logging
-log = logging.getLogger(__name__)
-
-log.debug('pjlink2 loaded')
-
-from PyQt5 import QtNetwork
-
-
-class PJLinkUDP(QtNetwork.QUdpSocket):
- """
- Socket service for handling datagram (UDP) sockets.
- """
- log.debug('PJLinkUDP loaded')
- # Class varialbe for projector list. Should be replaced by ProjectorManager's
- # projector list after being loaded there.
- projector_list = None
- projectors_found = None # UDP search found list
=== modified file 'openlp/core/ui/projector/manager.py'
--- openlp/core/ui/projector/manager.py 2017-08-06 07:23:26 +0000
+++ openlp/core/ui/projector/manager.py 2017-09-22 12:12:22 +0000
@@ -38,8 +38,7 @@
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.pjlink import PJLink
-from openlp.core.lib.projector.pjlink2 import PJLinkUDP
+from openlp.core.lib.projector.pjlink import PJLink, PJLinkUDP
from openlp.core.ui.projector.editform import ProjectorEditForm
from openlp.core.ui.projector.sourceselectform import SourceSelectTabs, SourceSelectSingle
@@ -700,16 +699,9 @@
:returns: PJLink() instance
"""
log.debug('_add_projector()')
- 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,
+ return PJLink(projector=projector,
poll_time=self.poll_time,
- socket_timeout=self.socket_timeout
- )
+ socket_timeout=self.socket_timeout)
def add_projector(self, projector, start=False):
"""
=== modified file 'tests/functional/openlp_core_lib/test_projector_db.py'
--- tests/functional/openlp_core_lib/test_projector_db.py 2017-08-06 07:23:26 +0000
+++ tests/functional/openlp_core_lib/test_projector_db.py 2017-09-22 12:12:22 +0000
@@ -111,7 +111,7 @@
"""
Test that we can upgrade an old song db to the current schema
"""
- # GIVEN: An old song db
+ # GIVEN: An old prjector db
old_db = os.path.join(TEST_RESOURCES_PATH, "projector", TEST_DB_PJLINK1)
tmp_db = os.path.join(self.tmp_folder, TEST_DB)
shutil.copyfile(old_db, tmp_db)
=== modified file 'tests/functional/openlp_core_lib/test_projector_pjlink_base.py'
--- tests/functional/openlp_core_lib/test_projector_pjlink_base.py 2017-08-06 07:23:26 +0000
+++ tests/functional/openlp_core_lib/test_projector_pjlink_base.py 2017-09-22 12:12:22 +0000
@@ -25,12 +25,13 @@
from unittest import TestCase
from unittest.mock import call, patch, MagicMock
+from openlp.core.lib.projector.db import Projector
from openlp.core.lib.projector.pjlink import PJLink
from openlp.core.lib.projector.constants import E_PARAMETER, ERROR_STRING, S_ON, S_CONNECTED
-from tests.resources.projector.data import TEST_PIN, TEST_SALT, TEST_CONNECT_AUTHENTICATE, TEST_HASH
+from tests.resources.projector.data import TEST_PIN, TEST_SALT, TEST_CONNECT_AUTHENTICATE, TEST_HASH, TEST1_DATA
-pjlink_test = PJLink(name='test', ip='127.0.0.1', pin=TEST_PIN, no_poll=True)
+pjlink_test = PJLink(Projector(**TEST1_DATA), no_poll=True)
class TestPJLinkBase(TestCase):
=== modified file 'tests/functional/openlp_core_lib/test_projector_pjlink_cmd_routing.py'
--- tests/functional/openlp_core_lib/test_projector_pjlink_cmd_routing.py 2017-08-12 20:38:50 +0000
+++ tests/functional/openlp_core_lib/test_projector_pjlink_cmd_routing.py 2017-09-22 12:12:22 +0000
@@ -27,6 +27,7 @@
from unittest.mock import patch, MagicMock
import openlp.core.lib.projector.pjlink
+from openlp.core.lib.projector.db import Projector
from openlp.core.lib.projector.pjlink import PJLink
from openlp.core.lib.projector.constants import PJLINK_ERRORS, \
E_AUTHENTICATION, E_PARAMETER, E_PROJECTOR, E_UNAVAILABLE, E_UNDEFINED
@@ -35,9 +36,10 @@
from openlp.core.lib.projector.constants import ERROR_STRING, PJLINK_ERST_DATA, PJLINK_ERST_STATUS, \
PJLINK_POWR_STATUS, PJLINK_VALID_CMD, E_WARN, E_ERROR, S_OFF, S_STANDBY, S_ON
'''
-from tests.resources.projector.data import TEST_PIN
+from tests.resources.projector.data import TEST_PIN, TEST1_DATA
-pjlink_test = PJLink(name='test', ip='127.0.0.1', pin=TEST_PIN, no_poll=True)
+pjlink_test = PJLink(Projector(**TEST1_DATA), pin=TEST_PIN, no_poll=True)
+pjlink_test.ip = '127.0.0.1'
class TestPJLinkRouting(TestCase):
=== modified file 'tests/functional/openlp_core_lib/test_projector_pjlink_commands.py'
--- tests/functional/openlp_core_lib/test_projector_pjlink_commands.py 2017-08-12 20:38:50 +0000
+++ tests/functional/openlp_core_lib/test_projector_pjlink_commands.py 2017-09-22 12:12:22 +0000
@@ -26,15 +26,17 @@
from unittest.mock import patch
import openlp.core.lib.projector.pjlink
+from openlp.core.lib.projector.db import Projector
from openlp.core.lib.projector.pjlink import PJLink
from openlp.core.lib.projector.constants import ERROR_STRING, PJLINK_ERST_DATA, PJLINK_ERST_STATUS, \
PJLINK_POWR_STATUS, \
E_ERROR, E_NOT_CONNECTED, E_SOCKET_ADDRESS_NOT_AVAILABLE, E_UNKNOWN_SOCKET_ERROR, E_WARN, \
S_CONNECTED, S_OFF, S_ON, S_NOT_CONNECTED, S_CONNECTING, S_STANDBY
-from tests.resources.projector.data import TEST_PIN
+from tests.resources.projector.data import TEST_PIN, TEST1_DATA
-pjlink_test = PJLink(name='test', ip='127.0.0.1', pin=TEST_PIN, no_poll=True)
+pjlink_test = PJLink(Projector(**TEST1_DATA), pin=TEST_PIN, no_poll=True)
+pjlink_test.ip = '127.0.0.1'
# Create a list of ERST positional data so we don't have to redo the same buildup multiple times
PJLINK_ERST_POSITIONS = []
Follow ups