Merge lp:~alisonken1/openlp/pjlink2-n into lp:openlp

Proposed by Ken Roberts
Status: Superseded
Proposed branch: lp:~alisonken1/openlp/pjlink2-n
Merge into: lp:openlp
Diff against target: 3646 lines (+1547/-1299)
7 files modified
openlp/core/projectors/constants.py (+300/-224)
openlp/core/projectors/manager.py (+37/-33)
openlp/core/projectors/pjlink.py (+114/-97)
tests/functional/openlp_core/projectors/test_projector_constants.py (+39/-0)
tests/functional/openlp_core/projectors/test_projector_pjlink_base.py (+3/-4)
tests/functional/openlp_core/projectors/test_projector_pjlink_cmd_routing.py (+183/-170)
tests/functional/openlp_core/projectors/test_projector_pjlink_commands_01.py (+871/-771)
To merge this branch: bzr merge lp:~alisonken1/openlp/pjlink2-n
Reviewer Review Type Date Requested Status
OpenLP Core Pending
Review via email: mp+335587@code.launchpad.net

This proposal has been superseded by a proposal from 2017-12-25.

Commit message

PJLink 2 update N

Description of the change

Jenkins cli at home dies at '02b-macOS-tests' [waiting], then timesout.

Passes local tests (pytest, nose2, pep8) with exception of
test_bible_gateway_extract_books_support_redirect

Large diff fixing test_projector_pjlink_commands_01 file

- Update some comments
- Some PJLink code fixes/restructuring
- Restructure some projector tests for proper mocking
- Fix manager.py and pjlink.py for changes to constants.py
- Fix test_projector_pjlink_routing.py for proper mocking and restructuring
- Renamed test_process_command_invalid to test_get_data_unknown_command
- Added test to verify assigned E_*/S_* codes are in STATUS_CODE and STATUS_MSG
- Added missing status/error codes to STATUS_MSG
- Added error checks to process_inpt
- Deleted unneeded test(s)

Updates to constants.py include:
    - Reordered dictionaries and lists into alphabetical order
    - Added PJLINK_ERST_LIST
    - Added S_NETWORK_IDLE code (for future)
    - Added PJLINK_STATUS list
    - Move S_QSOCKET_STATUS to QSOCKET_STATE
    - Move STATUS_STRING to STATUS_CODE
    - Move PJLINK_CLASS, PJLINK_SUFFIX, and PJLINK_PREFIX from pjlink.py to constants.py
    - Change CONNECTION_ERRORS from a dictionary to a list
    - Change QSOCKET_STATE to map QAbstractSocket.state() to local status codes
    - Merge ERROR_MSG with STATUS_MSG
    - Merge ERROR_STRING into STATUS_CODE
    - Clean out unused portion of PJLINK_ERST_STATUS
    - Clean out unused portion of PJLINK_POWR_STATUS
    - Clean out unused portion of QSOCKET_STATUS

To post a comment you must log in.
lp:~alisonken1/openlp/pjlink2-n updated
2805. By Ken Roberts

Cleanups and assert updates

2806. By Ken Roberts

Merge trunk

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'openlp/core/projectors/constants.py'
2--- openlp/core/projectors/constants.py 2017-12-09 11:17:05 +0000
3+++ openlp/core/projectors/constants.py 2017-12-25 08:57:51 +0000
4@@ -32,9 +32,128 @@
5 # Set common constants.
6 CR = chr(0x0D) # \r
7 LF = chr(0x0A) # \n
8+PJLINK_CLASS = '1' # Default to class 1 until we query the projector
9+PJLINK_MAX_PACKET = 136
10+PJLINK_PREFIX = '%'
11 PJLINK_PORT = 4352
12-TIMEOUT = 30.0
13-PJLINK_MAX_PACKET = 136
14+PJLINK_SUFFIX = CR
15+PJLINK_TIMEOUT = 30.0
16+
17+# Error and status codes
18+S_OK = E_OK = 0 # E_OK included since I sometimes forget
19+
20+# Error codes. Start at 200 so we don't duplicate system error codes.
21+E_GENERAL = 200 # Unknown error
22+E_NOT_CONNECTED = 201
23+E_UNDEFINED = 202 # PJLink ERR1
24+E_PARAMETER = 203 # PJLink ERR2
25+E_UNAVAILABLE = 204 # PJLink ERR3
26+E_PROJECTOR = 205 # PJLink ERR4
27+E_AUTHENTICATION = 206 # PJLink ERRA
28+E_NO_AUTHENTICATION = 207 # PJLink authentication mismatch between projector and program
29+E_PREFIX = 208 # PJLink invalid prefix for packet
30+E_CLASS = 209 # PJLink class version mismatch
31+E_INVALID_DATA = 210
32+E_WARN = 211
33+E_ERROR = 212
34+E_FAN = 213
35+E_LAMP = 214
36+E_TEMP = 215
37+E_COVER = 216
38+E_FILTER = 217
39+E_UNKNOWN = 218
40+
41+# Remap Qt socket error codes to local error codes
42+E_CONNECTION_REFUSED = 230
43+E_REMOTE_HOST_CLOSED_CONNECTION = 231
44+E_HOST_NOT_FOUND = 232
45+E_SOCKET_ACCESS = 233
46+E_SOCKET_RESOURCE = 234
47+E_SOCKET_TIMEOUT = 235
48+E_DATAGRAM_TOO_LARGE = 236
49+E_NETWORK = 237
50+E_ADDRESS_IN_USE = 238
51+E_SOCKET_ADDRESS_NOT_AVAILABLE = 239
52+E_UNSUPPORTED_SOCKET_OPERATION = 240
53+E_PROXY_AUTHENTICATION_REQUIRED = 241
54+E_SLS_HANDSHAKE_FAILED = 242
55+E_UNFINISHED_SOCKET_OPERATION = 243
56+E_PROXY_CONNECTION_REFUSED = 244
57+E_PROXY_CONNECTION_CLOSED = 245
58+E_PROXY_CONNECTION_TIMEOUT = 246
59+E_PROXY_NOT_FOUND = 247
60+E_PROXY_PROTOCOL = 248
61+E_UNKNOWN_SOCKET_ERROR = 249
62+
63+# Status codes start at 300
64+
65+# Remap Qt socket states to local status codes
66+S_NOT_CONNECTED = 300
67+S_HOST_LOOKUP = 301
68+S_CONNECTING = 302
69+S_CONNECTED = 303
70+S_BOUND = 304
71+S_LISTENING = 305 # Listed as internal use only in QAbstractSocket
72+S_CLOSING = 306
73+
74+# Projector states
75+S_INITIALIZE = 310
76+S_STATUS = 311
77+S_OFF = 312
78+S_STANDBY = 313
79+S_WARMUP = 314
80+S_ON = 315
81+S_COOLDOWN = 316
82+S_INFO = 317
83+
84+# Information that does not affect status
85+S_NETWORK_IDLE = 400
86+S_NETWORK_SENDING = 401
87+S_NETWORK_RECEIVING = 402
88+
89+# Map PJlink errors to local status
90+PJLINK_ERRORS = {
91+ 'ERRA': E_AUTHENTICATION, # Authentication error
92+ 'ERR1': E_UNDEFINED, # Undefined command error
93+ 'ERR2': E_PARAMETER, # Invalid parameter error
94+ 'ERR3': E_UNAVAILABLE, # Projector busy
95+ 'ERR4': E_PROJECTOR, # Projector or display failure
96+ E_AUTHENTICATION: 'ERRA',
97+ E_UNDEFINED: 'ERR1',
98+ E_PARAMETER: 'ERR2',
99+ E_UNAVAILABLE: 'ERR3',
100+ E_PROJECTOR: 'ERR4'
101+}
102+
103+# Map QAbstractSocketState enums to local status
104+QSOCKET_STATE = {
105+ 0: S_NOT_CONNECTED, # 'UnconnectedState',
106+ 1: S_HOST_LOOKUP, # 'HostLookupState',
107+ 2: S_CONNECTING, # 'ConnectingState',
108+ 3: S_CONNECTED, # 'ConnectedState',
109+ 4: S_BOUND, # 'BoundState',
110+ 5: S_LISTENING, # 'ListeningState' - Noted as "Internal Use Only" on Qt website
111+ 6: S_CLOSING, # 'ClosingState',
112+ S_NOT_CONNECTED: 0,
113+ S_HOST_LOOKUP: 1,
114+ S_CONNECTING: 2,
115+ S_CONNECTED: 3,
116+ S_BOUND: 4,
117+ S_LISTENING: 5,
118+ S_CLOSING: 6
119+}
120+
121+PROJECTOR_STATE = [
122+ S_INITIALIZE,
123+ S_STATUS,
124+ S_OFF,
125+ S_STANDBY,
126+ S_WARMUP,
127+ S_ON,
128+ S_COOLDOWN,
129+ S_INFO
130+]
131+
132 # NOTE: Changed format to account for some commands are both class 1 and 2
133 PJLINK_VALID_CMD = {
134 'ACKN': {'version': ['2', ],
135@@ -144,227 +263,140 @@
136 }
137 }
138
139-# QAbstractSocketState enums converted to string
140-S_QSOCKET_STATE = {
141- 0: 'QSocketState - UnconnectedState',
142- 1: 'QSocketState - HostLookupState',
143- 2: 'QSocketState - ConnectingState',
144- 3: 'QSocketState - ConnectedState',
145- 4: 'QSocketState - BoundState',
146- 5: 'QSocketState - ListeningState (internal use only)',
147- 6: 'QSocketState - ClosingState',
148- 'UnconnectedState': 0,
149- 'HostLookupState': 1,
150- 'ConnectingState': 2,
151- 'ConnectedState': 3,
152- 'BoundState': 4,
153- 'ListeningState': 5,
154- 'ClosingState': 6
155-}
156-
157-# Error and status codes
158-S_OK = E_OK = 0 # E_OK included since I sometimes forget
159-# Error codes. Start at 200 so we don't duplicate system error codes.
160-E_GENERAL = 200 # Unknown error
161-E_NOT_CONNECTED = 201
162-E_FAN = 202
163-E_LAMP = 203
164-E_TEMP = 204
165-E_COVER = 205
166-E_FILTER = 206
167-E_NO_AUTHENTICATION = 207 # PIN set and no authentication set on projector
168-E_UNDEFINED = 208 # ERR1
169-E_PARAMETER = 209 # ERR2
170-E_UNAVAILABLE = 210 # ERR3
171-E_PROJECTOR = 211 # ERR4
172-E_INVALID_DATA = 212
173-E_WARN = 213
174-E_ERROR = 214
175-E_AUTHENTICATION = 215 # ERRA
176-E_CLASS = 216
177-E_PREFIX = 217
178-
179-# Remap Qt socket error codes to projector error codes
180-E_CONNECTION_REFUSED = 230
181-E_REMOTE_HOST_CLOSED_CONNECTION = 231
182-E_HOST_NOT_FOUND = 232
183-E_SOCKET_ACCESS = 233
184-E_SOCKET_RESOURCE = 234
185-E_SOCKET_TIMEOUT = 235
186-E_DATAGRAM_TOO_LARGE = 236
187-E_NETWORK = 237
188-E_ADDRESS_IN_USE = 238
189-E_SOCKET_ADDRESS_NOT_AVAILABLE = 239
190-E_UNSUPPORTED_SOCKET_OPERATION = 240
191-E_PROXY_AUTHENTICATION_REQUIRED = 241
192-E_SLS_HANDSHAKE_FAILED = 242
193-E_UNFINISHED_SOCKET_OPERATION = 243
194-E_PROXY_CONNECTION_REFUSED = 244
195-E_PROXY_CONNECTION_CLOSED = 245
196-E_PROXY_CONNECTION_TIMEOUT = 246
197-E_PROXY_NOT_FOUND = 247
198-E_PROXY_PROTOCOL = 248
199-E_UNKNOWN_SOCKET_ERROR = -1
200-
201-# Status codes start at 300
202-S_NOT_CONNECTED = 300
203-S_CONNECTING = 301
204-S_CONNECTED = 302
205-S_INITIALIZE = 303
206-S_STATUS = 304
207-S_OFF = 305
208-S_STANDBY = 306
209-S_WARMUP = 307
210-S_ON = 308
211-S_COOLDOWN = 309
212-S_INFO = 310
213-
214-# Information that does not affect status
215-S_NETWORK_SENDING = 400
216-S_NETWORK_RECEIVED = 401
217-
218-CONNECTION_ERRORS = {
219- E_NOT_CONNECTED, E_NO_AUTHENTICATION, E_AUTHENTICATION, E_CLASS,
220- E_PREFIX, E_CONNECTION_REFUSED, E_REMOTE_HOST_CLOSED_CONNECTION,
221- E_HOST_NOT_FOUND, E_SOCKET_ACCESS, E_SOCKET_RESOURCE, E_SOCKET_TIMEOUT,
222- E_DATAGRAM_TOO_LARGE, E_NETWORK, E_ADDRESS_IN_USE, E_SOCKET_ADDRESS_NOT_AVAILABLE,
223- E_UNSUPPORTED_SOCKET_OPERATION, E_PROXY_AUTHENTICATION_REQUIRED,
224- E_SLS_HANDSHAKE_FAILED, E_UNFINISHED_SOCKET_OPERATION, E_PROXY_CONNECTION_REFUSED,
225- E_PROXY_CONNECTION_CLOSED, E_PROXY_CONNECTION_TIMEOUT, E_PROXY_NOT_FOUND,
226- E_PROXY_PROTOCOL, E_UNKNOWN_SOCKET_ERROR
227-}
228-
229-PJLINK_ERRORS = {
230- 'ERRA': E_AUTHENTICATION, # Authentication error
231- 'ERR1': E_UNDEFINED, # Undefined command error
232- 'ERR2': E_PARAMETER, # Invalid parameter error
233- 'ERR3': E_UNAVAILABLE, # Projector busy
234- 'ERR4': E_PROJECTOR, # Projector or display failure
235- E_AUTHENTICATION: 'ERRA',
236- E_UNDEFINED: 'ERR1',
237- E_PARAMETER: 'ERR2',
238- E_UNAVAILABLE: 'ERR3',
239- E_PROJECTOR: 'ERR4'
240-}
241-
242-# Map error/status codes to string
243-ERROR_STRING = {
244- 0: 'S_OK',
245+CONNECTION_ERRORS = [
246+ E_ADDRESS_IN_USE,
247+ E_CONNECTION_REFUSED,
248+ E_DATAGRAM_TOO_LARGE,
249+ E_HOST_NOT_FOUND,
250+ E_NETWORK,
251+ E_NOT_CONNECTED,
252+ E_PROXY_AUTHENTICATION_REQUIRED,
253+ E_PROXY_CONNECTION_CLOSED,
254+ E_PROXY_CONNECTION_REFUSED,
255+ E_PROXY_CONNECTION_TIMEOUT,
256+ E_PROXY_NOT_FOUND,
257+ E_PROXY_PROTOCOL,
258+ E_REMOTE_HOST_CLOSED_CONNECTION,
259+ E_SLS_HANDSHAKE_FAILED,
260+ E_SOCKET_ACCESS,
261+ E_SOCKET_ADDRESS_NOT_AVAILABLE,
262+ E_SOCKET_RESOURCE,
263+ E_SOCKET_TIMEOUT,
264+ E_UNFINISHED_SOCKET_OPERATION,
265+ E_UNKNOWN_SOCKET_ERROR,
266+ E_UNSUPPORTED_SOCKET_OPERATION
267+]
268+
269+PROJECTOR_ERRORS = [
270+ E_AUTHENTICATION,
271+ E_CLASS,
272+ E_INVALID_DATA,
273+ E_NO_AUTHENTICATION,
274+ E_PARAMETER,
275+ E_PREFIX,
276+ E_PROJECTOR,
277+ E_UNAVAILABLE,
278+ E_UNDEFINED,
279+ E_UNKNOWN
280+]
281+
282+# Show status code as string
283+STATUS_CODE = {
284+ E_ADDRESS_IN_USE: 'E_ADDRESS_IN_USE',
285+ E_AUTHENTICATION: 'E_AUTHENTICATION',
286+ E_CLASS: 'E_CLASS',
287+ E_CONNECTION_REFUSED: 'E_CONNECTION_REFUSED',
288+ E_COVER: 'E_COVER',
289+ E_DATAGRAM_TOO_LARGE: 'E_DATAGRAM_TOO_LARGE',
290+ E_ERROR: 'E_ERROR',
291+ E_FAN: 'E_FAN',
292+ E_FILTER: 'E_FILTER',
293 E_GENERAL: 'E_GENERAL',
294- E_NOT_CONNECTED: 'E_NOT_CONNECTED',
295- E_FAN: 'E_FAN',
296+ E_HOST_NOT_FOUND: 'E_HOST_NOT_FOUND',
297+ E_INVALID_DATA: 'E_INVALID_DATA',
298 E_LAMP: 'E_LAMP',
299- E_TEMP: 'E_TEMP',
300- E_COVER: 'E_COVER',
301- E_FILTER: 'E_FILTER',
302- E_AUTHENTICATION: 'E_AUTHENTICATION',
303+ E_NETWORK: 'E_NETWORK',
304 E_NO_AUTHENTICATION: 'E_NO_AUTHENTICATION',
305- E_UNDEFINED: 'E_UNDEFINED',
306+ E_NOT_CONNECTED: 'E_NOT_CONNECTED',
307 E_PARAMETER: 'E_PARAMETER',
308- E_UNAVAILABLE: 'E_UNAVAILABLE',
309+ E_PREFIX: 'E_PREFIX',
310 E_PROJECTOR: 'E_PROJECTOR',
311- E_INVALID_DATA: 'E_INVALID_DATA',
312- E_WARN: 'E_WARN',
313- E_ERROR: 'E_ERROR',
314- E_CLASS: 'E_CLASS',
315- E_PREFIX: 'E_PREFIX', # Last projector error
316- E_CONNECTION_REFUSED: 'E_CONNECTION_REFUSED', # First QtSocket error
317+ E_PROXY_AUTHENTICATION_REQUIRED: 'E_PROXY_AUTHENTICATION_REQUIRED',
318+ E_PROXY_CONNECTION_CLOSED: 'E_PROXY_CONNECTION_CLOSED',
319+ E_PROXY_CONNECTION_REFUSED: 'E_PROXY_CONNECTION_REFUSED',
320+ E_PROXY_CONNECTION_TIMEOUT: 'E_PROXY_CONNECTION_TIMEOUT',
321+ E_PROXY_NOT_FOUND: 'E_PROXY_NOT_FOUND',
322+ E_PROXY_PROTOCOL: 'E_PROXY_PROTOCOL',
323 E_REMOTE_HOST_CLOSED_CONNECTION: 'E_REMOTE_HOST_CLOSED_CONNECTION',
324- E_HOST_NOT_FOUND: 'E_HOST_NOT_FOUND',
325+ E_SLS_HANDSHAKE_FAILED: 'E_SLS_HANDSHAKE_FAILED',
326 E_SOCKET_ACCESS: 'E_SOCKET_ACCESS',
327+ E_SOCKET_ADDRESS_NOT_AVAILABLE: 'E_SOCKET_ADDRESS_NOT_AVAILABLE',
328 E_SOCKET_RESOURCE: 'E_SOCKET_RESOURCE',
329 E_SOCKET_TIMEOUT: 'E_SOCKET_TIMEOUT',
330- E_DATAGRAM_TOO_LARGE: 'E_DATAGRAM_TOO_LARGE',
331- E_NETWORK: 'E_NETWORK',
332- E_ADDRESS_IN_USE: 'E_ADDRESS_IN_USE',
333- E_SOCKET_ADDRESS_NOT_AVAILABLE: 'E_SOCKET_ADDRESS_NOT_AVAILABLE',
334+ E_TEMP: 'E_TEMP',
335+ E_UNAVAILABLE: 'E_UNAVAILABLE',
336+ E_UNDEFINED: 'E_UNDEFINED',
337+ E_UNFINISHED_SOCKET_OPERATION: 'E_UNFINISHED_SOCKET_OPERATION',
338+ E_UNKNOWN: 'E_UNKNOWN',
339+ E_UNKNOWN_SOCKET_ERROR: 'E_UNKNOWN_SOCKET_ERROR',
340 E_UNSUPPORTED_SOCKET_OPERATION: 'E_UNSUPPORTED_SOCKET_OPERATION',
341- E_PROXY_AUTHENTICATION_REQUIRED: 'E_PROXY_AUTHENTICATION_REQUIRED',
342- E_SLS_HANDSHAKE_FAILED: 'E_SLS_HANDSHAKE_FAILED',
343- E_UNFINISHED_SOCKET_OPERATION: 'E_UNFINISHED_SOCKET_OPERATION',
344- E_PROXY_CONNECTION_REFUSED: 'E_PROXY_CONNECTION_REFUSED',
345- E_PROXY_CONNECTION_CLOSED: 'E_PROXY_CONNECTION_CLOSED',
346- E_PROXY_CONNECTION_TIMEOUT: 'E_PROXY_CONNECTION_TIMEOUT',
347- E_PROXY_NOT_FOUND: 'E_PROXY_NOT_FOUND',
348- E_PROXY_PROTOCOL: 'E_PROXY_PROTOCOL',
349- E_UNKNOWN_SOCKET_ERROR: 'E_UNKNOWN_SOCKET_ERROR'
350-}
351-
352-STATUS_STRING = {
353+ E_WARN: 'E_WARN',
354+ S_BOUND: 'S_BOUND',
355+ S_COOLDOWN: 'S_COOLDOWN',
356+ S_CLOSING: 'S_CLOSING',
357+ S_CONNECTED: 'S_CONNECTED',
358+ S_CONNECTING: 'S_CONNECTING',
359+ S_HOST_LOOKUP: 'S_HOST_LOOKUP',
360+ S_INFO: 'S_INFO',
361+ S_INITIALIZE: 'S_INITIALIZE',
362+ S_LISTENING: 'S_LISTENING',
363+ S_NETWORK_RECEIVING: 'S_NETWORK_RECEIVING',
364+ S_NETWORK_SENDING: 'S_NETWORK_SENDING',
365+ S_NETWORK_IDLE: 'S_NETWORK_IDLE',
366 S_NOT_CONNECTED: 'S_NOT_CONNECTED',
367- S_CONNECTING: 'S_CONNECTING',
368- S_CONNECTED: 'S_CONNECTED',
369- S_STATUS: 'S_STATUS',
370 S_OFF: 'S_OFF',
371- S_INITIALIZE: 'S_INITIALIZE',
372+ S_OK: 'S_OK', # S_OK or E_OK
373+ S_ON: 'S_ON',
374 S_STANDBY: 'S_STANDBY',
375+ S_STATUS: 'S_STATUS',
376 S_WARMUP: 'S_WARMUP',
377- S_ON: 'S_ON',
378- S_COOLDOWN: 'S_COOLDOWN',
379- S_INFO: 'S_INFO',
380- S_NETWORK_SENDING: 'S_NETWORK_SENDING',
381- S_NETWORK_RECEIVED: 'S_NETWORK_RECEIVED'
382 }
383
384-# Map error/status codes to message strings
385-ERROR_MSG = {
386- E_OK: translate('OpenLP.ProjectorConstants', 'OK'), # E_OK | S_OK
387- E_GENERAL: translate('OpenLP.ProjectorConstants', 'General projector error'),
388- E_NOT_CONNECTED: translate('OpenLP.ProjectorConstants', 'Not connected error'),
389- E_LAMP: translate('OpenLP.ProjectorConstants', 'Lamp error'),
390- E_FAN: translate('OpenLP.ProjectorConstants', 'Fan error'),
391- E_TEMP: translate('OpenLP.ProjectorConstants', 'High temperature detected'),
392- E_COVER: translate('OpenLP.ProjectorConstants', 'Cover open detected'),
393- E_FILTER: translate('OpenLP.ProjectorConstants', 'Check filter'),
394- E_AUTHENTICATION: translate('OpenLP.ProjectorConstants', 'Authentication Error'),
395- E_UNDEFINED: translate('OpenLP.ProjectorConstants', 'Undefined Command'),
396- E_PARAMETER: translate('OpenLP.ProjectorConstants', 'Invalid Parameter'),
397- E_UNAVAILABLE: translate('OpenLP.ProjectorConstants', 'Projector Busy'),
398- E_PROJECTOR: translate('OpenLP.ProjectorConstants', 'Projector/Display Error'),
399- E_INVALID_DATA: translate('OpenLP.ProjectorConstants', 'Invalid packet received'),
400- E_WARN: translate('OpenLP.ProjectorConstants', 'Warning condition detected'),
401- E_ERROR: translate('OpenLP.ProjectorConstants', 'Error condition detected'),
402- E_CLASS: translate('OpenLP.ProjectorConstants', 'PJLink class not supported'),
403- E_PREFIX: translate('OpenLP.ProjectorConstants', 'Invalid prefix character'),
404+# Map status codes to message strings
405+STATUS_MSG = {
406+ E_ADDRESS_IN_USE: translate('OpenLP.ProjectorConstants',
407+ 'The address specified with socket.bind() '
408+ 'is already in use and was set to be exclusive'),
409+ E_AUTHENTICATION: translate('OpenLP.ProjectorConstants', 'PJLink returned "ERRA: Authentication Error"'),
410 E_CONNECTION_REFUSED: translate('OpenLP.ProjectorConstants',
411 'The connection was refused by the peer (or timed out)'),
412- E_REMOTE_HOST_CLOSED_CONNECTION: translate('OpenLP.ProjectorConstants',
413- 'The remote host closed the connection'),
414+ E_COVER: translate('OpenLP.ProjectorConstants', 'Projector cover open detected'),
415+ E_CLASS: translate('OpenLP.ProjectorConstants', 'PJLink class not supported'),
416+ E_DATAGRAM_TOO_LARGE: translate('OpenLP.ProjectorConstants',
417+ "The datagram was larger than the operating system's limit"),
418+ E_ERROR: translate('OpenLP.ProjectorConstants', 'Error condition detected'),
419+ E_FAN: translate('OpenLP.ProjectorConstants', 'Projector fan error'),
420+ E_FILTER: translate('OpenLP.ProjectorConstants', 'Projector check filter'),
421+ E_GENERAL: translate('OpenLP.ProjectorConstants', 'General projector error'),
422 E_HOST_NOT_FOUND: translate('OpenLP.ProjectorConstants', 'The host address was not found'),
423- E_SOCKET_ACCESS: translate('OpenLP.ProjectorConstants',
424- 'The socket operation failed because the application '
425- 'lacked the required privileges'),
426- E_SOCKET_RESOURCE: translate('OpenLP.ProjectorConstants',
427- 'The local system ran out of resources (e.g., too many sockets)'),
428- E_SOCKET_TIMEOUT: translate('OpenLP.ProjectorConstants',
429- 'The socket operation timed out'),
430- E_DATAGRAM_TOO_LARGE: translate('OpenLP.ProjectorConstants',
431- 'The datagram was larger than the operating system\'s limit'),
432+ E_INVALID_DATA: translate('OpenLP.ProjectorConstants', 'PJLink invalid packet received'),
433+ E_LAMP: translate('OpenLP.ProjectorConstants', 'Projector lamp error'),
434 E_NETWORK: translate('OpenLP.ProjectorConstants',
435 'An error occurred with the network (Possibly someone pulled the plug?)'),
436- E_ADDRESS_IN_USE: translate('OpenLP.ProjectorConstants',
437- 'The address specified with socket.bind() '
438- 'is already in use and was set to be exclusive'),
439- E_SOCKET_ADDRESS_NOT_AVAILABLE: translate('OpenLP.ProjectorConstants',
440- 'The address specified to socket.bind() '
441- 'does not belong to the host'),
442- E_UNSUPPORTED_SOCKET_OPERATION: translate('OpenLP.ProjectorConstants',
443- 'The requested socket operation is not supported by the local '
444- 'operating system (e.g., lack of IPv6 support)'),
445+ E_NO_AUTHENTICATION: translate('OpenLP.ProjectorConstants', 'PJlink authentication Mismatch Error'),
446+ E_NOT_CONNECTED: translate('OpenLP.ProjectorConstants', 'Projector not connected error'),
447+ E_PARAMETER: translate('OpenLP.ProjectorConstants', 'PJLink returned "ERR2: Invalid Parameter"'),
448+ E_PREFIX: translate('OpenLP.ProjectorConstants', 'PJLink Invalid prefix character'),
449+ E_PROJECTOR: translate('OpenLP.ProjectorConstants', 'PJLink returned "ERR4: Projector/Display Error"'),
450 E_PROXY_AUTHENTICATION_REQUIRED: translate('OpenLP.ProjectorConstants',
451 'The socket is using a proxy, '
452 'and the proxy requires authentication'),
453- E_SLS_HANDSHAKE_FAILED: translate('OpenLP.ProjectorConstants',
454- 'The SSL/TLS handshake failed'),
455- E_UNFINISHED_SOCKET_OPERATION: translate('OpenLP.ProjectorConstants',
456- 'The last operation attempted has not finished yet '
457- '(still in progress in the background)'),
458+ E_PROXY_CONNECTION_CLOSED: translate('OpenLP.ProjectorConstants',
459+ 'The connection to the proxy server was closed unexpectedly '
460+ '(before the connection to the final peer was established)'),
461 E_PROXY_CONNECTION_REFUSED: translate('OpenLP.ProjectorConstants',
462 'Could not contact the proxy server because the connection '
463 'to that server was denied'),
464- E_PROXY_CONNECTION_CLOSED: translate('OpenLP.ProjectorConstants',
465- 'The connection to the proxy server was closed unexpectedly '
466- '(before the connection to the final peer was established)'),
467 E_PROXY_CONNECTION_TIMEOUT: translate('OpenLP.ProjectorConstants',
468 'The connection to the proxy server timed out or the proxy '
469 'server stopped responding in the authentication phase.'),
470@@ -373,51 +405,91 @@
471 E_PROXY_PROTOCOL: translate('OpenLP.ProjectorConstants',
472 'The connection negotiation with the proxy server failed because the '
473 'response from the proxy server could not be understood'),
474- E_UNKNOWN_SOCKET_ERROR: translate('OpenLP.ProjectorConstants', 'An unidentified error occurred'),
475- S_NOT_CONNECTED: translate('OpenLP.ProjectorConstants', 'Not connected'),
476+ E_REMOTE_HOST_CLOSED_CONNECTION: translate('OpenLP.ProjectorConstants',
477+ 'The remote host closed the connection'),
478+ E_SLS_HANDSHAKE_FAILED: translate('OpenLP.ProjectorConstants',
479+ 'The SSL/TLS handshake failed'),
480+ E_SOCKET_ADDRESS_NOT_AVAILABLE: translate('OpenLP.ProjectorConstants',
481+ 'The address specified to socket.bind() '
482+ 'does not belong to the host'),
483+ E_SOCKET_ACCESS: translate('OpenLP.ProjectorConstants',
484+ 'The socket operation failed because the application '
485+ 'lacked the required privileges'),
486+ E_SOCKET_RESOURCE: translate('OpenLP.ProjectorConstants',
487+ 'The local system ran out of resources (e.g., too many sockets)'),
488+ E_SOCKET_TIMEOUT: translate('OpenLP.ProjectorConstants',
489+ 'The socket operation timed out'),
490+ E_TEMP: translate('OpenLP.ProjectorConstants', 'Projector high temperature detected'),
491+ E_UNAVAILABLE: translate('OpenLP.ProjectorConstants', 'PJLink returned "ERR3: Busy"'),
492+ E_UNDEFINED: translate('OpenLP.ProjectorConstants', 'PJLink returned "ERR1: Undefined Command"'),
493+ E_UNFINISHED_SOCKET_OPERATION: translate('OpenLP.ProjectorConstants',
494+ 'The last operation attempted has not finished yet '
495+ '(still in progress in the background)'),
496+ E_UNKNOWN: translate('OpenLP.ProjectorConstants', 'Unknown condiction detected'),
497+ E_UNKNOWN_SOCKET_ERROR: translate('OpenLP.ProjectorConstants', 'An unidentified socket error occurred'),
498+ E_UNSUPPORTED_SOCKET_OPERATION: translate('OpenLP.ProjectorConstants',
499+ 'The requested socket operation is not supported by the local '
500+ 'operating system (e.g., lack of IPv6 support)'),
501+ E_WARN: translate('OpenLP.ProjectorConstants', 'Warning condition detected'),
502+ S_BOUND: translate('OpenLP.ProjectorConstants', 'Socket is bount to an address or port'),
503+ S_CLOSING: translate('OpenLP.ProjectorConstants', 'Socket is about to close'),
504+ S_CONNECTED: translate('OpenLP.ProjectorConstants', 'Connected'),
505 S_CONNECTING: translate('OpenLP.ProjectorConstants', 'Connecting'),
506- S_CONNECTED: translate('OpenLP.ProjectorConstants', 'Connected'),
507- S_STATUS: translate('OpenLP.ProjectorConstants', 'Getting status'),
508+ S_COOLDOWN: translate('OpenLP.ProjectorConstants', 'Cooldown in progress'),
509+ S_HOST_LOOKUP: translate('OpenLP.ProjectorConstants', 'Performing a host name lookup'),
510+ S_INFO: translate('OpenLP.ProjectorConstants', 'Projector Information available'),
511+ S_INITIALIZE: translate('OpenLP.ProjectorConstants', 'Initialize in progress'),
512+ S_LISTENING: translate('OpenLP.ProjectorConstants', 'Socket it listening (internal use only)'),
513+ S_NETWORK_IDLE: translate('OpenLP.ProjectorConstants', 'No network activity at this time'),
514+ S_NETWORK_RECEIVING: translate('OpenLP.ProjectorConstants', 'Received data'),
515+ S_NETWORK_SENDING: translate('OpenLP.ProjectorConstants', 'Sending data'),
516+ S_NOT_CONNECTED: translate('OpenLP.ProjectorConstants', 'Not Connected'),
517 S_OFF: translate('OpenLP.ProjectorConstants', 'Off'),
518- S_INITIALIZE: translate('OpenLP.ProjectorConstants', 'Initialize in progress'),
519+ S_OK: translate('OpenLP.ProjectorConstants', 'OK'),
520+ S_ON: translate('OpenLP.ProjectorConstants', 'Power is on'),
521 S_STANDBY: translate('OpenLP.ProjectorConstants', 'Power in standby'),
522+ S_STATUS: translate('OpenLP.ProjectorConstants', 'Getting status'),
523 S_WARMUP: translate('OpenLP.ProjectorConstants', 'Warmup in progress'),
524- S_ON: translate('OpenLP.ProjectorConstants', 'Power is on'),
525- S_COOLDOWN: translate('OpenLP.ProjectorConstants', 'Cooldown in progress'),
526- S_INFO: translate('OpenLP.ProjectorConstants', 'Projector Information available'),
527- S_NETWORK_SENDING: translate('OpenLP.ProjectorConstants', 'Sending data'),
528- S_NETWORK_RECEIVED: translate('OpenLP.ProjectorConstants', 'Received data')
529-}
530-
531-# Map ERST return code positions to equipment
532+}
533+
534+# Map ERST reply positions to equipment
535+PJLINK_ERST_LIST = {
536+ "FAN": translate('OpenLP.PJLink', 'Fan'),
537+ "LAMP": translate('OpenLP.PJLink', 'Lamp'),
538+ "TEMP": translate('OpenLP.PJLink', 'Temperature'),
539+ "COVER": translate('OpenLP.PJLink', 'Cover'),
540+ "FILTER": translate('OpenLP.PJLink', 'Filter'),
541+ "OTHER": translate('OpenPL.PJLink', 'Other')
542+}
543+
544+# Map projector item to ERST data position
545 PJLINK_ERST_DATA = {
546- 'DATA_LENGTH': 6,
547+ 'DATA_LENGTH': 6, # Zero based so enums are 0-5
548+ 'FAN': 0,
549+ 'LAMP': 1,
550+ 'TEMP': 2,
551+ 'COVER': 3,
552+ 'FILTER': 4,
553+ 'OTHER': 5,
554 0: 'FAN',
555 1: 'LAMP',
556 2: 'TEMP',
557 3: 'COVER',
558 4: 'FILTER',
559- 5: 'OTHER',
560- 'FAN': 0,
561- 'LAMP': 1,
562- 'TEMP': 2,
563- 'COVER': 3,
564- 'FILTER': 4,
565- 'OTHER': 5
566+ 5: 'OTHER'
567 }
568
569-# Map for ERST return codes to string
570+# Map ERST reply codes to string
571 PJLINK_ERST_STATUS = {
572- '0': 'OK',
573- '1': ERROR_STRING[E_WARN],
574- '2': ERROR_STRING[E_ERROR],
575- 'OK': '0',
576- E_OK: '0',
577+ '0': S_OK,
578+ '1': E_WARN,
579+ '2': E_ERROR,
580+ S_OK: '0',
581 E_WARN: '1',
582 E_ERROR: '2'
583 }
584
585-# Map for POWR return codes to status code
586+# Map POWR return codes to status code
587 PJLINK_POWR_STATUS = {
588 '0': S_STANDBY,
589 '1': S_ON,
590@@ -485,3 +557,7 @@
591 label = "{source}{item}".format(source=source, item=item)
592 PJLINK_DEFAULT_CODES[label] = "{source} {item}".format(source=PJLINK_DEFAULT_SOURCES[source],
593 item=PJLINK_DEFAULT_ITEMS[item])
594+# Remove temp variables so they don't become part of the module dict
595+del(source)
596+del(item)
597+del(label)
598
599=== modified file 'openlp/core/projectors/manager.py'
600--- openlp/core/projectors/manager.py 2017-11-24 19:08:23 +0000
601+++ openlp/core/projectors/manager.py 2017-12-25 08:57:51 +0000
602@@ -35,9 +35,25 @@
603 from openlp.core.common.settings import Settings
604 from openlp.core.lib.ui import create_widget_action
605 from openlp.core.projectors import DialogSourceStyle
606-from openlp.core.projectors.constants import ERROR_MSG, ERROR_STRING, E_AUTHENTICATION, E_ERROR, \
607- E_NETWORK, E_NOT_CONNECTED, E_UNKNOWN_SOCKET_ERROR, STATUS_STRING, S_CONNECTED, S_CONNECTING, S_COOLDOWN, \
608- S_INITIALIZE, S_NOT_CONNECTED, S_OFF, S_ON, S_STANDBY, S_WARMUP
609+from openlp.core.projectors.constants import \
610+ E_AUTHENTICATION, \
611+ E_ERROR, \
612+ E_NETWORK, \
613+ E_NOT_CONNECTED, \
614+ E_UNKNOWN_SOCKET_ERROR, \
615+ S_CONNECTED, \
616+ S_CONNECTING, \
617+ S_COOLDOWN, \
618+ S_INITIALIZE, \
619+ S_NOT_CONNECTED, \
620+ S_OFF, \
621+ S_ON, \
622+ S_STANDBY, \
623+ S_WARMUP, \
624+ STATUS_CODE, \
625+ STATUS_MSG, \
626+ QSOCKET_STATE
627+
628 from openlp.core.projectors.db import ProjectorDB
629 from openlp.core.projectors.pjlink import PJLink, PJLinkUDP
630 from openlp.core.projectors.editform import ProjectorEditForm
631@@ -440,11 +456,12 @@
632 :param opt: Needed by PyQt5
633 """
634 projector = item.data(QtCore.Qt.UserRole)
635- if projector.link.state() != projector.link.ConnectedState:
636+ if QSOCKET_STATE[projector.link.state()] != S_CONNECTED:
637 try:
638+ log.debug('ProjectorManager: Calling connect_to_host() on "{ip}"'.format(ip=projector.link.ip))
639 projector.link.connect_to_host()
640 except:
641- pass
642+ log.debug('ProjectorManager: "{ip}" already connected - skipping'.format(ip=projector.link.ip))
643 return
644
645 def on_connect_projector(self, opt=None):
646@@ -647,7 +664,7 @@
647 'Other info'),
648 data=projector.link.other_info)
649 message += '<b>{title}</b>: {data}<br />'.format(title=translate('OpenLP.ProjectorManager', 'Power status'),
650- data=ERROR_MSG[projector.link.power])
651+ data=STATUS_MSG[projector.link.power])
652 message += '<b>{title}</b>: {data}<br />'.format(title=translate('OpenLP.ProjectorManager', 'Shutter is'),
653 data=translate('OpenLP.ProjectorManager', 'Closed')
654 if projector.link.shutter
655@@ -692,7 +709,7 @@
656 else:
657 message += '<b>{data}</b>'.format(data=translate('OpenLP.ProjectorManager', 'Current errors/warnings'))
658 for (key, val) in projector.link.projector_errors.items():
659- message += '<b>{key}</b>: {data}<br />'.format(key=key, data=ERROR_MSG[val])
660+ message += '<b>{key}</b>: {data}<br />'.format(key=key, data=STATUS_MSG[val])
661 QtWidgets.QMessageBox.information(self, translate('OpenLP.ProjectorManager', 'Projector Information'), message)
662
663 def _add_projector(self, projector):
664@@ -817,31 +834,18 @@
665 if ip == list_item.link.ip:
666 item = list_item
667 break
668- message = translate('OpenLP.ProjectorManager', 'No message') if msg is None else msg
669- if status in STATUS_STRING:
670- status_code = STATUS_STRING[status]
671- message = ERROR_MSG[status] if msg is None else msg
672- elif status in ERROR_STRING:
673- status_code = ERROR_STRING[status]
674- message = ERROR_MSG[status] if msg is None else msg
675- else:
676- status_code = status
677- message = ERROR_MSG[status] if msg is None else msg
678- log.debug('({name}) updateStatus(status={status}) message: "{message}"'.format(name=item.link.name,
679- status=status_code,
680- message=message))
681- if status in STATUS_ICONS:
682- if item.status == status:
683- return
684- item.status = status
685- item.icon = QtGui.QIcon(QtGui.QPixmap(STATUS_ICONS[status]))
686- if status in ERROR_STRING:
687- status_code = ERROR_STRING[status]
688- elif status in STATUS_STRING:
689- status_code = STATUS_STRING[status]
690- log.debug('({name}) Updating icon with {code}'.format(name=item.link.name, code=status_code))
691- item.widget.setIcon(item.icon)
692- self.update_icons()
693+ if item is None:
694+ log.error('ProjectorManager: Unknown item "{ip}" - not updating status'.format(ip=ip))
695+ return
696+ elif item.status == status:
697+ log.debug('ProjectorManager: No status change for "{ip}" - not updating status'.format(ip=ip))
698+ return
699+
700+ item.status = status
701+ item.icon = QtGui.QIcon(QtGui.QPixmap(STATUS_ICONS[status]))
702+ log.debug('({name}) Updating icon with {code}'.format(name=item.link.name, code=STATUS_CODE[status]))
703+ item.widget.setIcon(item.icon)
704+ return self.update_icons()
705
706 def get_toolbar_item(self, name, enabled=False, hidden=False):
707 item = self.one_toolbar.findChild(QtWidgets.QAction, name)
708@@ -877,7 +881,7 @@
709 self.get_toolbar_item('show_projector_multiple', hidden=True)
710 elif count == 1:
711 projector = self.projector_list_widget.selectedItems()[0].data(QtCore.Qt.UserRole)
712- connected = projector.link.state() == projector.link.ConnectedState
713+ connected = QSOCKET_STATE[projector.link.state()] == S_CONNECTED
714 power = projector.link.power == S_ON
715 self.get_toolbar_item('connect_projector_multiple', hidden=True)
716 self.get_toolbar_item('disconnect_projector_multiple', hidden=True)
717
718=== modified file 'openlp/core/projectors/pjlink.py'
719--- openlp/core/projectors/pjlink.py 2017-12-09 11:17:05 +0000
720+++ openlp/core/projectors/pjlink.py 2017-12-25 08:57:51 +0000
721@@ -54,11 +54,12 @@
722
723 from openlp.core.common import qmd5_hash
724 from openlp.core.common.i18n import translate
725-from openlp.core.projectors.constants import CONNECTION_ERRORS, CR, ERROR_MSG, ERROR_STRING, \
726- E_AUTHENTICATION, E_CONNECTION_REFUSED, E_GENERAL, E_INVALID_DATA, E_NETWORK, E_NOT_CONNECTED, E_OK, \
727- E_PARAMETER, E_PROJECTOR, E_SOCKET_TIMEOUT, E_UNAVAILABLE, E_UNDEFINED, PJLINK_ERRORS, PJLINK_ERST_DATA, \
728- PJLINK_ERST_STATUS, PJLINK_MAX_PACKET, PJLINK_PORT, PJLINK_POWR_STATUS, PJLINK_VALID_CMD, \
729- STATUS_STRING, S_CONNECTED, S_CONNECTING, S_INFO, S_NOT_CONNECTED, S_OFF, S_OK, S_ON, S_QSOCKET_STATE, S_STATUS
730+from openlp.core.projectors.constants import CONNECTION_ERRORS, PJLINK_CLASS, PJLINK_DEFAULT_CODES, PJLINK_ERRORS, \
731+ PJLINK_ERST_DATA, PJLINK_ERST_STATUS, PJLINK_MAX_PACKET, PJLINK_PREFIX, PJLINK_PORT, PJLINK_POWR_STATUS, \
732+ PJLINK_SUFFIX, PJLINK_VALID_CMD, PROJECTOR_STATE, STATUS_CODE, STATUS_MSG, QSOCKET_STATE, \
733+ E_AUTHENTICATION, E_CONNECTION_REFUSED, E_GENERAL, E_INVALID_DATA, E_NETWORK, E_NOT_CONNECTED, \
734+ E_OK, E_SOCKET_TIMEOUT, \
735+ S_CONNECTED, S_CONNECTING, S_INFO, S_NOT_CONNECTED, S_OFF, S_OK, S_ON, S_STATUS
736
737 log = logging.getLogger(__name__)
738 log.debug('pjlink loaded')
739@@ -69,12 +70,9 @@
740 SocketError = QtNetwork.QAbstractSocket.SocketError
741 SocketSTate = QtNetwork.QAbstractSocket.SocketState
742
743-PJLINK_PREFIX = '%'
744-PJLINK_CLASS = '1' # Default to class 1 until we query the projector
745 # Add prefix here, but defer linkclass expansion until later when we have the actual
746 # PJLink class for the command
747 PJLINK_HEADER = '{prefix}{{linkclass}}'.format(prefix=PJLINK_PREFIX)
748-PJLINK_SUFFIX = CR
749
750
751 class PJLinkUDP(QtNetwork.QUdpSocket):
752@@ -136,8 +134,9 @@
753 """
754 Initialize instance variables. Also used to reset projector-specific information to default.
755 """
756+ conn_state = STATUS_CODE[QSOCKET_STATE[self.state()]]
757 log.debug('({ip}) reset_information() connect status is {state}'.format(ip=self.ip,
758- state=S_QSOCKET_STATE[self.state()]))
759+ state=conn_state))
760 self.fan = None # ERST
761 self.filter_time = None # FILT
762 self.lamp = None # LAMP
763@@ -183,42 +182,25 @@
764 # Due to some replies should stay as mixed-case, validate using separate uppercase check
765 _data = data.upper()
766 # Check if we have a future command not available yet
767- if cmd not in PJLINK_VALID_CMD:
768- log.error('({ip}) Ignoring command="{cmd}" (Invalid/Unknown)'.format(ip=self.ip, cmd=cmd))
769+ if cmd not in self.pjlink_functions:
770+ log.warning('({ip}) Unable to process command="{cmd}" (Future option?)'.format(ip=self.ip, cmd=cmd))
771 return
772 elif _data == 'OK':
773 log.debug('({ip}) Command "{cmd}" returned OK'.format(ip=self.ip, cmd=cmd))
774 # A command returned successfully, so do a query on command to verify status
775 return self.send_command(cmd=cmd)
776- elif cmd not in self.pjlink_functions:
777- log.warning('({ip}) Unable to process command="{cmd}" (Future option?)'.format(ip=self.ip, cmd=cmd))
778- return
779 elif _data in PJLINK_ERRORS:
780 # Oops - projector error
781- log.error('({ip}) Projector returned error "{data}"'.format(ip=self.ip, data=data))
782- if _data == PJLINK_ERRORS[E_AUTHENTICATION]:
783- # Authentication error
784+ log.error('({ip}) {cmd}: {err}'.format(ip=self.ip,
785+ cmd=cmd,
786+ err=STATUS_MSG[PJLINK_ERRORS[_data]]))
787+ if PJLINK_ERRORS[_data] == E_AUTHENTICATION:
788 self.disconnect_from_host()
789- self.change_status(E_AUTHENTICATION)
790- log.debug('({ip}) emitting projectorAuthentication() signal'.format(ip=self.ip))
791 self.projectorAuthentication.emit(self.name)
792- elif _data == PJLINK_ERRORS[E_UNDEFINED]:
793- # Projector does not recognize command
794- self.change_status(E_UNDEFINED, '{error}: "{data}"'.format(error=ERROR_MSG[E_UNDEFINED],
795- data=cmd))
796- elif _data == PJLINK_ERRORS[E_PARAMETER]:
797- # Invalid parameter
798- self.change_status(E_PARAMETER)
799- elif _data == PJLINK_ERRORS[E_UNAVAILABLE]:
800- # Projector busy
801- self.change_status(E_UNAVAILABLE)
802- elif _data == PJLINK_ERRORS[E_PROJECTOR]:
803- # Projector/display error
804- self.change_status(E_PROJECTOR)
805- return
806+ return self.change_status(status=E_AUTHENTICATION)
807 # Command checks already passed
808 log.debug('({ip}) Calling function for {cmd}'.format(ip=self.ip, cmd=cmd))
809- self.pjlink_functions[cmd](data)
810+ self.pjlink_functions[cmd](data=data)
811
812 def process_avmt(self, data):
813 """
814@@ -313,22 +295,22 @@
815 data[PJLINK_ERST_DATA['COVER']],
816 data[PJLINK_ERST_DATA['FILTER']],
817 data[PJLINK_ERST_DATA['OTHER']])
818- if fan != PJLINK_ERST_STATUS[E_OK]:
819+ if fan != PJLINK_ERST_STATUS[S_OK]:
820 self.projector_errors[translate('OpenLP.ProjectorPJLink', 'Fan')] = \
821 PJLINK_ERST_STATUS[fan]
822- if lamp != PJLINK_ERST_STATUS[E_OK]:
823+ if lamp != PJLINK_ERST_STATUS[S_OK]:
824 self.projector_errors[translate('OpenLP.ProjectorPJLink', 'Lamp')] = \
825 PJLINK_ERST_STATUS[lamp]
826- if temp != PJLINK_ERST_STATUS[E_OK]:
827+ if temp != PJLINK_ERST_STATUS[S_OK]:
828 self.projector_errors[translate('OpenLP.ProjectorPJLink', 'Temperature')] = \
829 PJLINK_ERST_STATUS[temp]
830- if cover != PJLINK_ERST_STATUS[E_OK]:
831+ if cover != PJLINK_ERST_STATUS[S_OK]:
832 self.projector_errors[translate('OpenLP.ProjectorPJLink', 'Cover')] = \
833 PJLINK_ERST_STATUS[cover]
834- if filt != PJLINK_ERST_STATUS[E_OK]:
835+ if filt != PJLINK_ERST_STATUS[S_OK]:
836 self.projector_errors[translate('OpenLP.ProjectorPJLink', 'Filter')] = \
837 PJLINK_ERST_STATUS[filt]
838- if other != PJLINK_ERST_STATUS[E_OK]:
839+ if other != PJLINK_ERST_STATUS[S_OK]:
840 self.projector_errors[translate('OpenLP.ProjectorPJLink', 'Other')] = \
841 PJLINK_ERST_STATUS[other]
842 return
843@@ -373,8 +355,18 @@
844
845 :param data: Currently selected source
846 """
847+ # First, see if we have a valid input based on what is installed (if available)
848+ if self.source_available is not None:
849+ # We have available inputs, so verify it's in the list
850+ if data not in self.source_available:
851+ log.warn('({ip}) Input source not listed in available sources - ignoring'.format(ip=self.ip))
852+ return
853+ elif data not in PJLINK_DEFAULT_CODES:
854+ # Hmm - no sources available yet, so check with PJLink defaults
855+ log.warn('({ip}) Input source not listed as a PJLink available source - ignoring'.format(ip=self.ip))
856+ return
857 self.source = data
858- log.info('({ip}) Setting data source to "{data}"'.format(ip=self.ip, data=self.source))
859+ log.debug('({ip}) Setting data source to "{data}"'.format(ip=self.ip, data=self.source))
860 return
861
862 def process_inst(self, data):
863@@ -390,7 +382,6 @@
864 sources.append(source)
865 sources.sort()
866 self.source_available = sources
867- self.projectorUpdateIcons.emit()
868 log.debug('({ip}) Setting projector sources_available to "{data}"'.format(ip=self.ip,
869 data=self.source_available))
870 return
871@@ -551,17 +542,15 @@
872 return
873 elif self.sw_version is None:
874 log.debug('({ip}) Setting projector software version to "{data}"'.format(ip=self.ip, data=data))
875- self.sw_version = data
876- self.db_update = True
877 else:
878- # Compare software version and see if we got the same projector
879- if self.serial_no != data:
880+ if self.sw_version != data:
881 log.warning('({ip}) Projector software version does not match saved '
882 'software version'.format(ip=self.ip))
883 log.warning('({ip}) Saved: "{old}"'.format(ip=self.ip, old=self.sw_version))
884 log.warning('({ip}) Received: "{new}"'.format(ip=self.ip, new=data))
885- log.warning('({ip}) Saving new serial number as sw_version_received'.format(ip=self.ip))
886- self.sw_version_received = data
887+ log.warning('({ip}) Updating software version'.format(ip=self.ip))
888+ self.sw_version = data
889+ self.db_update = True
890
891
892 class PJLink(QtNetwork.QTcpSocket, PJLinkCommands):
893@@ -678,7 +667,7 @@
894 Retrieve information from projector that changes.
895 Normally called by timer().
896 """
897- if self.state() != S_QSOCKET_STATE['ConnectedState']:
898+ if QSOCKET_STATE[self.state()] != S_CONNECTED:
899 log.warning('({ip}) poll_loop(): Not connected - returning'.format(ip=self.ip))
900 return
901 log.debug('({ip}) poll_loop(): Updating projector status'.format(ip=self.ip))
902@@ -688,13 +677,8 @@
903 self.timer.setInterval(self.poll_time)
904 # Restart timer
905 self.timer.start()
906- # These commands may change during connection
907- check_list = ['POWR', 'ERST', 'LAMP', 'AVMT', 'INPT']
908- if self.pjlink_class == '2':
909- check_list.extend(['FILT', 'FREZ'])
910- for command in check_list:
911- self.send_command(command)
912 # The following commands do not change, so only check them once
913+ # Call them first in case other functions rely on something here
914 if self.power == S_ON and self.source_available is None:
915 self.send_command('INST')
916 if self.other_info is None:
917@@ -715,22 +699,28 @@
918 self.send_command('RFIL')
919 if self.model_lamp is None:
920 self.send_command('RLMP')
921+ # These commands may change during connection
922+ check_list = ['POWR', 'ERST', 'LAMP', 'AVMT', 'INPT']
923+ if self.pjlink_class == '2':
924+ check_list.extend(['FILT', 'FREZ'])
925+ for command in check_list:
926+ self.send_command(command)
927
928 def _get_status(self, status):
929 """
930 Helper to retrieve status/error codes and convert to strings.
931
932 :param status: Status/Error code
933- :returns: (Status/Error code, String)
934+ :returns: tuple (-1 if code not INT, None)
935+ :returns: tuple (string: code as string, None if no description)
936+ :returns: tuple (string: code as string, string: Status/Error description)
937 """
938 if not isinstance(status, int):
939- return -1, 'Invalid status code'
940- elif status in ERROR_STRING:
941- return ERROR_STRING[status], ERROR_MSG[status]
942- elif status in STATUS_STRING:
943- return STATUS_STRING[status], ERROR_MSG[status]
944+ return -1, None
945+ elif status not in STATUS_MSG:
946+ return None, None
947 else:
948- return status, translate('OpenLP.PJLink', 'Unknown status')
949+ return STATUS_CODE[status], STATUS_MSG[status]
950
951 def change_status(self, status, msg=None):
952 """
953@@ -740,19 +730,27 @@
954 :param status: Status code
955 :param msg: Optional message
956 """
957- message = translate('OpenLP.PJLink', 'No message') if msg is None else msg
958- (code, message) = self._get_status(status)
959- if msg is not None:
960- message = msg
961+ if status in STATUS_CODE:
962+ log.debug('({ip}) Changing status to {status} '
963+ '"{msg}"'.format(ip=self.ip,
964+ status=STATUS_CODE[status],
965+ msg=msg if msg is not None else STATUS_MSG[status]))
966+ else:
967+ log.warning('({ip}) Unknown status change code: {code}'.format(ip=self.ip,
968+ code=status))
969+ return
970 if status in CONNECTION_ERRORS:
971- # Projector, connection state
972- self.projector_status = self.error_status = self.status_connect = E_NOT_CONNECTED
973- elif status >= S_NOT_CONNECTED and status < S_STATUS:
974+ # Connection state error affects both socket and projector
975+ self.error_status = status
976+ self.status_connect = E_NOT_CONNECTED
977+ elif status >= S_NOT_CONNECTED and status in QSOCKET_STATE:
978+ # Socket connection status update
979 self.status_connect = status
980- self.projector_status = S_NOT_CONNECTED
981- elif status <= S_INFO:
982- self.status_connect = S_CONNECTED
983+ elif status >= S_NOT_CONNECTED and status in PROJECTOR_STATE:
984+ # Only affects the projector status
985 self.projector_status = status
986+
987+ # These log entries are for troubleshooting only
988 (status_code, status_message) = self._get_status(self.status_connect)
989 log.debug('({ip}) status_connect: {code}: "{message}"'.format(ip=self.ip,
990 code=status_code,
991@@ -765,6 +763,15 @@
992 log.debug('({ip}) error_status: {code}: "{message}"'.format(ip=self.ip,
993 code=status_code,
994 message=status_message if msg is None else msg))
995+
996+ # Now that we logged extra information for debugging, broadcast the original change/message
997+ (code, message) = self._get_status(status)
998+ if msg is not None:
999+ message = msg
1000+ elif message is None:
1001+ # No message for status code
1002+ message = translate('OpenLP.PJLink', 'No message') if msg is None else msg
1003+
1004 self.changeStatus.emit(self.ip, status, message)
1005 self.projectorUpdateIcons.emit()
1006
1007@@ -794,7 +801,7 @@
1008 data = decode(read, 'utf-8')
1009 # Possibility of extraneous data on input when reading.
1010 # Clean out extraneous characters in buffer.
1011- self.readLine(self.max_size)
1012+ self.read(2048)
1013 log.debug('({ip}) check_login() read "{data}"'.format(ip=self.ip, data=data.strip()))
1014 # At this point, we should only have the initial login prompt with
1015 # possible authentication
1016@@ -805,6 +812,7 @@
1017 # Invalid initial packet - close socket
1018 log.error('({ip}) Invalid initial packet received - closing socket'.format(ip=self.ip))
1019 return self.disconnect_from_host()
1020+ # Convert the initial login prompt with the expected PJLink normal command format for processing
1021 log.debug('({ip}) check_login(): Formatting initial connection prompt to PJLink packet'.format(ip=self.ip))
1022 return self.get_data('{start}{clss}{data}'.format(start=PJLINK_PREFIX,
1023 clss='1',
1024@@ -895,7 +903,7 @@
1025 Get data from TCP socket.
1026 """
1027 log.debug('({ip}) get_socket(): Reading data'.format(ip=self.ip))
1028- if self.state() != self.ConnectedState:
1029+ if QSOCKET_STATE[self.state()] != S_CONNECTED:
1030 log.debug('({ip}) get_socket(): Not connected - returning'.format(ip=self.ip))
1031 self.send_busy = False
1032 return
1033@@ -907,8 +915,7 @@
1034 log.debug('({ip}) get_socket(): No data available (-1)'.format(ip=self.ip))
1035 return self.receive_data_signal()
1036 self.socket_timer.stop()
1037- self.get_data(buff=read, ip=self.ip)
1038- return self.receive_data_signal()
1039+ return self.get_data(buff=read, ip=self.ip)
1040
1041 def get_data(self, buff, ip=None):
1042 """
1043@@ -927,13 +934,17 @@
1044 data = data_in.strip()
1045 # Initial packet checks
1046 if (len(data) < 7):
1047- return self._trash_buffer(msg='get_data(): Invalid packet - length')
1048+ self._trash_buffer(msg='get_data(): Invalid packet - length')
1049+ return self.receive_data_signal()
1050 elif len(data) > self.max_size:
1051- return self._trash_buffer(msg='get_data(): Invalid packet - too long')
1052+ self._trash_buffer(msg='get_data(): Invalid packet - too long')
1053+ return self.receive_data_signal()
1054 elif not data.startswith(PJLINK_PREFIX):
1055- return self._trash_buffer(msg='get_data(): Invalid packet - PJLink prefix missing')
1056+ self._trash_buffer(msg='get_data(): Invalid packet - PJLink prefix missing')
1057+ return self.receive_data_signal()
1058 elif '=' not in data:
1059- return self._trash_buffer(msg='get_data(): Invalid reply - Does not have "="')
1060+ self._trash_buffer(msg='get_data(): Invalid reply - Does not have "="')
1061+ return self.receive_data_signal()
1062 log.debug('({ip}) get_data(): Checking new data "{data}"'.format(ip=self.ip, data=data))
1063 header, data = data.split('=')
1064 # At this point, the header should contain:
1065@@ -947,15 +958,17 @@
1066 except ValueError as e:
1067 self.change_status(E_INVALID_DATA)
1068 log.warning('({ip}) get_data(): Received data: "{data}"'.format(ip=self.ip, data=data_in))
1069- return self._trash_buffer('get_data(): Expected header + command + data')
1070+ self._trash_buffer('get_data(): Expected header + command + data')
1071+ return self.receive_data_signal()
1072 if cmd not in PJLINK_VALID_CMD:
1073 log.warning('({ip}) get_data(): Invalid packet - unknown command "{data}"'.format(ip=self.ip, data=cmd))
1074- return self._trash_buffer(msg='get_data(): Unknown command "{data}"'.format(data=cmd))
1075+ self._trash_buffer(msg='get_data(): Unknown command "{data}"'.format(data=cmd))
1076+ return self.receive_data_signal()
1077 if int(self.pjlink_class) < int(version):
1078 log.warning('({ip}) get_data(): Projector returned class reply higher '
1079 'than projector stated class'.format(ip=self.ip))
1080- self.send_busy = False
1081- return self.process_command(cmd, data)
1082+ self.process_command(cmd, data)
1083+ return self.receive_data_signal()
1084
1085 @QtCore.pyqtSlot(QtNetwork.QAbstractSocket.SocketError)
1086 def get_error(self, err):
1087@@ -993,7 +1006,7 @@
1088 :param salt: Optional salt for md5 hash initial authentication
1089 :param priority: Option to send packet now rather than queue it up
1090 """
1091- if self.state() != self.ConnectedState:
1092+ if QSOCKET_STATE[self.state()] != S_CONNECTED:
1093 log.warning('({ip}) send_command(): Not connected - returning'.format(ip=self.ip))
1094 return self.reset_information()
1095 if cmd not in PJLINK_VALID_CMD:
1096@@ -1018,7 +1031,7 @@
1097 header=header,
1098 command=cmd,
1099 options=opts,
1100- suffix=CR)
1101+ suffix=PJLINK_SUFFIX)
1102 if out in self.priority_queue:
1103 log.debug('({ip}) send_command(): Already in priority queue - skipping'.format(ip=self.ip))
1104 elif out in self.send_queue:
1105@@ -1044,9 +1057,10 @@
1106 """
1107 # Funny looking data check, but it's a quick check for data=None
1108 log.debug('({ip}) _send_command(data="{data}")'.format(ip=self.ip, data=data.strip() if data else data))
1109+ conn_state = STATUS_CODE[QSOCKET_STATE[self.state()]]
1110 log.debug('({ip}) _send_command(): Connection status: {data}'.format(ip=self.ip,
1111- data=S_QSOCKET_STATE[self.state()]))
1112- if self.state() != self.ConnectedState:
1113+ data=conn_state))
1114+ if QSOCKET_STATE[self.state()] != S_CONNECTED:
1115 log.debug('({ip}) _send_command() Not connected - abort'.format(ip=self.ip))
1116 self.send_busy = False
1117 return self.disconnect_from_host()
1118@@ -1088,10 +1102,11 @@
1119 """
1120 Initiate connection to projector.
1121 """
1122- log.debug('{ip}) connect_to_host(): Starting connection'.format(ip=self.ip))
1123- if self.state() == self.ConnectedState:
1124+ log.debug('({ip}) connect_to_host(): Starting connection'.format(ip=self.ip))
1125+ if QSOCKET_STATE[self.state()] == S_CONNECTED:
1126 log.warning('({ip}) connect_to_host(): Already connected - returning'.format(ip=self.ip))
1127 return
1128+ self.error_status = S_OK
1129 self.change_status(S_CONNECTING)
1130 self.connectToHost(self.ip, self.port if isinstance(self.port, int) else int(self.port))
1131
1132@@ -1100,12 +1115,13 @@
1133 """
1134 Close socket and cleanup.
1135 """
1136- if abort or self.state() != self.ConnectedState:
1137+ if abort or QSOCKET_STATE[self.state()] != S_NOT_CONNECTED:
1138 if abort:
1139 log.warning('({ip}) disconnect_from_host(): Aborting connection'.format(ip=self.ip))
1140+ self.abort()
1141 else:
1142 log.warning('({ip}) disconnect_from_host(): Not connected'.format(ip=self.ip))
1143- self.disconnectFromHost()
1144+ self.disconnectFromHost()
1145 try:
1146 self.readyRead.disconnect(self.get_socket)
1147 except TypeError:
1148@@ -1201,7 +1217,7 @@
1149 elif src not in self.source_available:
1150 return
1151 log.debug('({ip}) Setting input source to "{data}"'.format(ip=self.ip, data=src))
1152- self.send_command(cmd='INPT', opts=src)
1153+ self.send_command(cmd='INPT', opts=src, priority=True)
1154 self.poll_loop()
1155
1156 def set_power_on(self):
1157@@ -1209,7 +1225,7 @@
1158 Send command to turn power to on.
1159 """
1160 log.debug('({ip}) Setting POWR to 1 (on)'.format(ip=self.ip))
1161- self.send_command(cmd='POWR', opts='1')
1162+ self.send_command(cmd='POWR', opts='1', priority=True)
1163 self.poll_loop()
1164
1165 def set_power_off(self):
1166@@ -1217,7 +1233,7 @@
1167 Send command to turn power to standby.
1168 """
1169 log.debug('({ip}) Setting POWR to 0 (standby)'.format(ip=self.ip))
1170- self.send_command(cmd='POWR', opts='0')
1171+ self.send_command(cmd='POWR', opts='0', priority=True)
1172 self.poll_loop()
1173
1174 def set_shutter_closed(self):
1175@@ -1225,7 +1241,7 @@
1176 Send command to set shutter to closed position.
1177 """
1178 log.debug('({ip}) Setting AVMT to 11 (shutter closed)'.format(ip=self.ip))
1179- self.send_command(cmd='AVMT', opts='11')
1180+ self.send_command(cmd='AVMT', opts='11', priority=True)
1181 self.poll_loop()
1182
1183 def set_shutter_open(self):
1184@@ -1233,8 +1249,9 @@
1185 Send command to set shutter to open position.
1186 """
1187 log.debug('({ip}) Setting AVMT to "10" (shutter open)'.format(ip=self.ip))
1188- self.send_command(cmd='AVMT', opts='10')
1189+ self.send_command(cmd='AVMT', opts='10', priority=True)
1190 self.poll_loop()
1191+ self.projectorUpdateIcons.emit()
1192
1193 def receive_data_signal(self):
1194 """
1195
1196=== modified file 'tests/functional/openlp_core/projectors/test_projector_constants.py'
1197--- tests/functional/openlp_core/projectors/test_projector_constants.py 2017-11-10 11:59:38 +0000
1198+++ tests/functional/openlp_core/projectors/test_projector_constants.py 2017-12-25 08:57:51 +0000
1199@@ -23,12 +23,51 @@
1200 Package to test the openlp.core.projectors.constants module.
1201 """
1202 from unittest import TestCase
1203+from openlp.core.projectors import constants
1204+from openlp.core.projectors.constants import STATUS_CODE, STATUS_MSG
1205
1206
1207 class TestProjectorConstants(TestCase):
1208 """
1209 Test specific functions in the projector constants module.
1210 """
1211+ def test_defined_codes_in_status_code(self):
1212+ """
1213+ Test defined status/error codes have equivalent strings
1214+ """
1215+ check = []
1216+ missing_str = []
1217+
1218+ # GIVEN: List of defined E_* and S_* items defined in constants
1219+ for item in constants.__dict__:
1220+ if item.startswith('E_') or item.startswith('S_'):
1221+ check.append(item)
1222+
1223+ # WHEN: Verify defined list against STATUS_STR
1224+ for item in check:
1225+ if constants.__dict__[item] not in STATUS_CODE:
1226+ missing_str.append(item)
1227+
1228+ # THEN: There should be no missing items
1229+ assert 0 == len(missing_str), 'Status string missing: {msg}'.format(msg=missing_str)
1230+
1231+ def test_status_code_in_status_message(self):
1232+ """
1233+ Test if entries in STATUS_CODE have equivalent descriptions in STATUS_MSG
1234+ """
1235+ missing_msg = []
1236+
1237+ # GIVEN: Test items
1238+ check = STATUS_CODE
1239+
1240+ # WHEN: Verify each entry in STATUS_MSG against STATUS_CODE
1241+ for item in check:
1242+ if item not in STATUS_MSG:
1243+ missing_msg.append(item)
1244+
1245+ # THEN: There should be no missing items
1246+ assert 0 == len(missing_msg), 'Status message missing: {msg}'.format(msg=missing_msg)
1247+
1248 def test_build_pjlink_video_label(self):
1249 """
1250 Test building PJLINK_DEFAULT_CODES dictionary
1251
1252=== modified file 'tests/functional/openlp_core/projectors/test_projector_pjlink_base.py'
1253--- tests/functional/openlp_core/projectors/test_projector_pjlink_base.py 2017-12-04 00:24:47 +0000
1254+++ tests/functional/openlp_core/projectors/test_projector_pjlink_base.py 2017-12-25 08:57:51 +0000
1255@@ -25,7 +25,7 @@
1256 from unittest import TestCase
1257 from unittest.mock import call, patch, MagicMock
1258
1259-from openlp.core.projectors.constants import E_PARAMETER, ERROR_STRING, S_ON, S_CONNECTED, S_QSOCKET_STATE
1260+from openlp.core.projectors.constants import E_PARAMETER, STATUS_CODE, S_ON, S_CONNECTED, QSOCKET_STATE
1261 from openlp.core.projectors.db import Projector
1262 from openlp.core.projectors.pjlink import PJLink
1263
1264@@ -65,7 +65,7 @@
1265 # as first parameter
1266 mock_change_status.called_with(E_PARAMETER,
1267 'change_status should have been called with "{}"'.format(
1268- ERROR_STRING[E_PARAMETER]))
1269+ STATUS_CODE[E_PARAMETER]))
1270
1271 @patch.object(pjlink_test, 'disconnect_from_host')
1272 def test_socket_abort(self, mock_disconnect):
1273@@ -104,7 +104,7 @@
1274 """
1275 # GIVEN: Mocks and test data
1276 mock_state = patch.object(self.pjlink_test, 'state').start()
1277- mock_state.return_value = S_QSOCKET_STATE['ConnectedState']
1278+ mock_state.return_value = QSOCKET_STATE[S_CONNECTED]
1279 mock_timer = patch.object(self.pjlink_test, 'timer').start()
1280 mock_timer.interval.return_value = 10
1281 mock_send_command = patch.object(self.pjlink_test, 'send_command').start()
1282@@ -117,7 +117,6 @@
1283 pjlink.manufacturer = None
1284 pjlink.model = None
1285 pjlink.pjlink_name = None
1286- pjlink.ConnectedState = S_CONNECTED
1287 call_list = [
1288 call('POWR'),
1289 call('ERST'),
1290
1291=== modified file 'tests/functional/openlp_core/projectors/test_projector_pjlink_cmd_routing.py'
1292--- tests/functional/openlp_core/projectors/test_projector_pjlink_cmd_routing.py 2017-12-09 11:17:05 +0000
1293+++ tests/functional/openlp_core/projectors/test_projector_pjlink_cmd_routing.py 2017-12-25 08:57:51 +0000
1294@@ -24,209 +24,222 @@
1295 """
1296
1297 from unittest import TestCase
1298-from unittest.mock import patch, MagicMock
1299+from unittest.mock import MagicMock, call, patch
1300
1301 import openlp.core.projectors.pjlink
1302-from openlp.core.projectors.constants import PJLINK_ERRORS, \
1303+from openlp.core.projectors.constants import PJLINK_ERRORS, PJLINK_PREFIX, STATUS_MSG, \
1304 E_AUTHENTICATION, E_PARAMETER, E_PROJECTOR, E_UNAVAILABLE, E_UNDEFINED
1305 from openlp.core.projectors.db import Projector
1306 from openlp.core.projectors.pjlink import PJLink
1307
1308-'''
1309-from openlp.core.projectors.constants import ERROR_STRING, PJLINK_ERST_DATA, PJLINK_ERST_STATUS, \
1310- PJLINK_POWR_STATUS, PJLINK_VALID_CMD, E_WARN, E_ERROR, S_OFF, S_STANDBY, S_ON
1311-'''
1312-from tests.resources.projector.data import TEST_PIN, TEST1_DATA
1313-
1314-pjlink_test = PJLink(Projector(**TEST1_DATA), pin=TEST_PIN, no_poll=True)
1315-pjlink_test.ip = '127.0.0.1'
1316+from tests.resources.projector.data import TEST1_DATA
1317
1318
1319 class TestPJLinkRouting(TestCase):
1320 """
1321 Tests for the PJLink module command routing
1322 """
1323- def setUp(self):
1324- '''
1325- TestPJLinkCommands part 2 initialization
1326- '''
1327- self.pjlink_test = PJLink(Projector(**TEST1_DATA), no_poll=True)
1328-
1329- def tearDown(self):
1330- '''
1331- TestPJLinkCommands part 2 cleanups
1332- '''
1333- self.pjlink_test = None
1334-
1335- @patch.object(openlp.core.projectors.pjlink, 'log')
1336- def test_process_command_call_clss(self, mock_log):
1337+ def test_get_data_unknown_command(self):
1338+ """
1339+ Test not a valid command
1340+ """
1341+ # GIVEN: Test object
1342+ log_warning_text = [call('(111.111.111.111) get_data(): Invalid packet - unknown command "UNK"')]
1343+ log_debug_text = [call('(111.111.111.111) get_data(ip="111.111.111.111" buffer="b\'%1UNK=Huh?\'"'),
1344+ call('(111.111.111.111) get_data(): Checking new data "%1UNK=Huh?"')]
1345+
1346+ with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
1347+ patch.object(openlp.core.projectors.pjlink.PJLink, '_trash_buffer') as mock_buffer:
1348+
1349+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
1350+ pjlink.pjlink_functions = MagicMock()
1351+
1352+ # WHEN: get_data called with an unknown command
1353+ pjlink.get_data(buff='{prefix}1UNK=Huh?'.format(prefix=PJLINK_PREFIX).encode('utf-8'))
1354+
1355+ # THEN: Appropriate log entries should have been made and methods called/not called
1356+ mock_log.debug.assert_has_calls(log_debug_text)
1357+ mock_log.warning.assert_has_calls(log_warning_text)
1358+ self.assertFalse(pjlink.pjlink_functions.called, 'Should not have accessed pjlink_functions')
1359+ self.assertTrue(mock_buffer.called, 'Should have called _trash_buffer')
1360+
1361+ def test_process_command_call_clss(self):
1362 """
1363 Test process_command calls proper function
1364 """
1365+ # GIVEN: Test object and mocks
1366+ log_debug_calls = [call('(111.111.111.111) Processing command "CLSS" with data "1"'),
1367+ call('(111.111.111.111) Calling function for CLSS')]
1368+
1369+ with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
1370+ patch.object(openlp.core.projectors.pjlink.PJLink, 'process_clss') as mock_process_clss:
1371+
1372+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
1373+
1374+ # WHEN: process_command is called with valid function and data
1375+ pjlink.process_command(cmd='CLSS', data='1')
1376+
1377+ # THEN: Appropriate log entries should have been made and methods called
1378+ mock_log.debug.assert_has_calls(log_debug_calls)
1379+ mock_process_clss.assert_called_once_with(data='1')
1380+
1381+ def test_process_command_erra(self):
1382+ """
1383+ Test ERRA - Authentication Error
1384+ """
1385 # GIVEN: Test object
1386- pjlink = pjlink_test
1387- log_text = '(127.0.0.1) Calling function for CLSS'
1388- mock_log.reset_mock()
1389- mock_process_clss = MagicMock()
1390- pjlink.pjlink_functions['CLSS'] = mock_process_clss
1391-
1392- # WHEN: process_command is called with valid function and data
1393- pjlink.process_command(cmd='CLSS', data='1')
1394-
1395- # THEN: Process method should have been called properly
1396- mock_log.debug.assert_called_with(log_text)
1397- mock_process_clss.assert_called_with('1')
1398-
1399- @patch.object(pjlink_test, 'change_status')
1400- @patch.object(openlp.core.projectors.pjlink, 'log')
1401- def test_process_command_err1(self, mock_log, mock_change_status):
1402+ log_error_calls = [call('(111.111.111.111) PJLINK: {msg}'.format(msg=STATUS_MSG[E_AUTHENTICATION]))]
1403+ log_debug_calls = [call('(111.111.111.111) Processing command "PJLINK" with data "ERRA"')]
1404+
1405+ with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
1406+ patch.object(openlp.core.projectors.pjlink.PJLink, 'process_pjlink') as mock_process_pjlink, \
1407+ patch.object(openlp.core.projectors.pjlink.PJLink, 'change_status') as mock_change_status, \
1408+ patch.object(openlp.core.projectors.pjlink.PJLink, 'disconnect_from_host') as mock_disconnect, \
1409+ patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorAuthentication') as mock_authentication:
1410+
1411+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
1412+
1413+ # WHEN: process_command called with ERRA
1414+ pjlink.process_command(cmd='PJLINK', data=PJLINK_ERRORS[E_AUTHENTICATION])
1415+
1416+ # THEN: Appropriate log entries should have been made and methods called/not called
1417+ mock_log.error.assert_has_calls(log_error_calls)
1418+ mock_log.debug.assert_has_calls(log_debug_calls)
1419+ self.assertTrue(mock_disconnect.called, 'disconnect_from_host should have been called')
1420+ mock_change_status.assert_called_once_with(status=E_AUTHENTICATION)
1421+ mock_authentication.emit.assert_called_once_with(pjlink.name)
1422+ mock_process_pjlink.assert_not_called()
1423+
1424+ def test_process_command_err1(self):
1425 """
1426 Test ERR1 - Undefined projector function
1427 """
1428 # GIVEN: Test object
1429- pjlink = pjlink_test
1430- log_text = '(127.0.0.1) Projector returned error "ERR1"'
1431- mock_change_status.reset_mock()
1432- mock_log.reset_mock()
1433-
1434- # WHEN: process_command called with ERR1
1435- pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_UNDEFINED])
1436-
1437- # THEN: Error should be logged and status_change should be called
1438- mock_change_status.assert_called_once_with(E_UNDEFINED, 'Undefined Command: "CLSS"')
1439- mock_log.error.assert_called_with(log_text)
1440-
1441- @patch.object(pjlink_test, 'change_status')
1442- @patch.object(openlp.core.projectors.pjlink, 'log')
1443- def test_process_command_err2(self, mock_log, mock_change_status):
1444+ log_error_text = [call('(111.111.111.111) CLSS: {msg}'.format(msg=STATUS_MSG[E_UNDEFINED]))]
1445+ log_debug_text = [call('(111.111.111.111) Processing command "CLSS" with data "ERR1"'),
1446+ call('(111.111.111.111) Calling function for CLSS')]
1447+
1448+ with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
1449+ patch.object(openlp.core.projectors.pjlink.PJLink, 'process_clss') as mock_process_clss:
1450+
1451+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
1452+
1453+ # WHEN: process_command called with ERR1
1454+ pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_UNDEFINED])
1455+
1456+ # THEN: Appropriate log entries should have been made and methods called
1457+ mock_log.error.assert_has_calls(log_error_text)
1458+ mock_log.debug.assert_has_calls(log_debug_text)
1459+ mock_process_clss.assert_called_once_with(data=PJLINK_ERRORS[E_UNDEFINED])
1460+
1461+ def test_process_command_err2(self):
1462 """
1463 Test ERR2 - Parameter Error
1464 """
1465 # GIVEN: Test object
1466- pjlink = pjlink_test
1467- log_text = '(127.0.0.1) Projector returned error "ERR2"'
1468- mock_change_status.reset_mock()
1469- mock_log.reset_mock()
1470-
1471- # WHEN: process_command called with ERR2
1472- pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_PARAMETER])
1473-
1474- # THEN: Error should be logged and status_change should be called
1475- mock_change_status.assert_called_once_with(E_PARAMETER)
1476- mock_log.error.assert_called_with(log_text)
1477-
1478- @patch.object(pjlink_test, 'change_status')
1479- @patch.object(openlp.core.projectors.pjlink, 'log')
1480- def test_process_command_err3(self, mock_log, mock_change_status):
1481- """
1482- Test ERR3 - Unavailable error
1483- """
1484- # GIVEN: Test object
1485- pjlink = pjlink_test
1486- log_text = '(127.0.0.1) Projector returned error "ERR3"'
1487- mock_change_status.reset_mock()
1488- mock_log.reset_mock()
1489-
1490- # WHEN: process_command called with ERR3
1491- pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_UNAVAILABLE])
1492-
1493- # THEN: Error should be logged and status_change should be called
1494- mock_change_status.assert_called_once_with(E_UNAVAILABLE)
1495- mock_log.error.assert_called_with(log_text)
1496-
1497- @patch.object(pjlink_test, 'change_status')
1498- @patch.object(openlp.core.projectors.pjlink, 'log')
1499- def test_process_command_err4(self, mock_log, mock_change_status):
1500- """
1501- Test ERR3 - Unavailable error
1502- """
1503- # GIVEN: Test object
1504- pjlink = pjlink_test
1505- log_text = '(127.0.0.1) Projector returned error "ERR4"'
1506- mock_change_status.reset_mock()
1507- mock_log.reset_mock()
1508-
1509- # WHEN: process_command called with ERR3
1510- pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_PROJECTOR])
1511-
1512- # THEN: Error should be logged and status_change should be called
1513- mock_change_status.assert_called_once_with(E_PROJECTOR)
1514- mock_log.error.assert_called_with(log_text)
1515-
1516- @patch.object(pjlink_test, 'projectorAuthentication')
1517- @patch.object(pjlink_test, 'change_status')
1518- @patch.object(pjlink_test, 'disconnect_from_host')
1519- @patch.object(openlp.core.projectors.pjlink, 'log')
1520- def test_process_command_erra(self, mock_log, mock_disconnect, mock_change_status, mock_err_authenticate):
1521- """
1522- Test ERRA - Authentication Error
1523- """
1524- # GIVEN: Test object
1525- pjlink = pjlink_test
1526- log_text = '(127.0.0.1) Projector returned error "ERRA"'
1527- mock_change_status.reset_mock()
1528- mock_log.reset_mock()
1529-
1530- # WHEN: process_command called with ERRA
1531- pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_AUTHENTICATION])
1532-
1533- # THEN: Error should be logged and several methods should be called
1534- self.assertTrue(mock_disconnect.called, 'disconnect_from_host should have been called')
1535- mock_change_status.assert_called_once_with(E_AUTHENTICATION)
1536- mock_log.error.assert_called_with(log_text)
1537+ log_error_text = [call('(111.111.111.111) CLSS: {msg}'.format(msg=STATUS_MSG[E_PARAMETER]))]
1538+ log_debug_text = [call('(111.111.111.111) Processing command "CLSS" with data "ERR2"'),
1539+ call('(111.111.111.111) Calling function for CLSS')]
1540+
1541+ with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
1542+ patch.object(openlp.core.projectors.pjlink.PJLink, 'process_clss') as mock_process_clss:
1543+
1544+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
1545+
1546+ # WHEN: process_command called with ERR2
1547+ pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_PARAMETER])
1548+
1549+ # THEN: Appropriate log entries should have been made and methods called/not called
1550+ mock_log.error.assert_has_calls(log_error_text)
1551+ mock_log.debug.assert_has_calls(log_debug_text)
1552+ mock_process_clss.assert_called_once_with(data=PJLINK_ERRORS[E_PARAMETER])
1553+
1554+ def test_process_command_err3(self):
1555+ """
1556+ Test ERR3 - Unavailable error
1557+ """
1558+ # GIVEN: Test object
1559+ log_error_text = [call('(111.111.111.111) CLSS: {msg}'.format(msg=STATUS_MSG[E_UNAVAILABLE]))]
1560+ log_debug_text = [call('(111.111.111.111) Processing command "CLSS" with data "ERR3"'),
1561+ call('(111.111.111.111) Calling function for CLSS')]
1562+
1563+ with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
1564+ patch.object(openlp.core.projectors.pjlink.PJLink, 'process_clss') as mock_process_clss:
1565+
1566+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
1567+
1568+ # WHEN: process_command called with ERR3
1569+ pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_UNAVAILABLE])
1570+
1571+ # THEN: Appropriate log entries should have been made and methods called
1572+ mock_log.error.assert_has_calls(log_error_text)
1573+ mock_log.debug.assert_has_calls(log_debug_text)
1574+ mock_process_clss.assert_called_once_with(data=PJLINK_ERRORS[E_UNAVAILABLE])
1575+
1576+ def test_process_command_err4(self):
1577+ """
1578+ Test ERR3 - Unavailable error
1579+ """
1580+ # GIVEN: Test object
1581+ log_error_text = [call('(111.111.111.111) CLSS: {msg}'.format(msg=STATUS_MSG[E_PROJECTOR]))]
1582+ log_debug_text = [call('(111.111.111.111) Processing command "CLSS" with data "ERR4"'),
1583+ call('(111.111.111.111) Calling function for CLSS')]
1584+
1585+ with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
1586+ patch.object(openlp.core.projectors.pjlink.PJLink, 'process_clss') as mock_process_clss:
1587+
1588+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
1589+
1590+ # WHEN: process_command called with ERR4
1591+ pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_PROJECTOR])
1592+
1593+ # THEN: Appropriate log entries should have been made and methods called
1594+ mock_log.error.assert_has_calls(log_error_text)
1595+ mock_log.debug.assert_has_calls(log_debug_text)
1596+ mock_process_clss.assert_called_once_with(data=PJLINK_ERRORS[E_PROJECTOR])
1597
1598 def test_process_command_future(self):
1599 """
1600 Test command valid but no method to process yet
1601 """
1602- # GIVEN: Initial mocks and data
1603- mock_log = patch.object(openlp.core.projectors.pjlink, 'log').start()
1604- mock_functions = patch.object(self.pjlink_test, 'pjlink_functions').start()
1605- mock_functions.return_value = []
1606-
1607- pjlink = self.pjlink_test
1608- log_text = '(111.111.111.111) Unable to process command="CLSS" (Future option?)'
1609-
1610- # WHEN: process_command called with an unknown command
1611- pjlink.process_command(cmd='CLSS', data='DONT CARE')
1612-
1613- # THEN: Error should be logged and no command called
1614- self.assertFalse(mock_functions.called, 'Should not have gotten to the end of the method')
1615- mock_log.warning.assert_called_once_with(log_text)
1616-
1617- @patch.object(pjlink_test, 'pjlink_functions')
1618- @patch.object(openlp.core.projectors.pjlink, 'log')
1619- def test_process_command_invalid(self, mock_log, mock_functions):
1620- """
1621- Test not a valid command
1622- """
1623 # GIVEN: Test object
1624- pjlink = pjlink_test
1625- mock_functions.reset_mock()
1626- mock_log.reset_mock()
1627-
1628- # WHEN: process_command called with an unknown command
1629- pjlink.process_command(cmd='Unknown', data='Dont Care')
1630- log_text = '(127.0.0.1) Ignoring command="Unknown" (Invalid/Unknown)'
1631-
1632- # THEN: Error should be logged and no command called
1633- self.assertFalse(mock_functions.called, 'Should not have gotten to the end of the method')
1634- mock_log.error.assert_called_once_with(log_text)
1635+ log_warning_text = [call('(111.111.111.111) Unable to process command="CLSS" (Future option?)')]
1636+ log_debug_text = [call('(111.111.111.111) Processing command "CLSS" with data "Huh?"')]
1637+
1638+ with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
1639+ patch.object(openlp.core.projectors.pjlink.PJLink, 'process_clss') as mock_process_clss:
1640+
1641+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
1642+ pjlink.pjlink_functions = MagicMock()
1643+
1644+ # WHEN: Processing a possible future command
1645+ pjlink.process_command(cmd='CLSS', data="Huh?")
1646+
1647+ # THEN: Appropriate log entries should have been made and methods called/not called
1648+ mock_log.debug.assert_has_calls(log_debug_text)
1649+ mock_log.warning.assert_has_calls(log_warning_text)
1650+ self.assertFalse(pjlink.pjlink_functions.called, 'Should not have accessed pjlink_functions')
1651+ self.assertFalse(mock_process_clss.called, 'Should not have called process_clss')
1652
1653 def test_process_command_ok(self):
1654 """
1655 Test command returned success
1656 """
1657 # GIVEN: Initial mocks and data
1658- mock_log = patch.object(openlp.core.projectors.pjlink, 'log').start()
1659- mock_send_command = patch.object(self.pjlink_test, 'send_command').start()
1660-
1661- pjlink = self.pjlink_test
1662- log_text = '(111.111.111.111) Command "POWR" returned OK'
1663-
1664- # WHEN: process_command called with a command that returns OK
1665- pjlink.process_command(cmd='POWR', data='OK')
1666-
1667- # THEN: Appropriate calls should have been made
1668- mock_log.debug.assert_called_with(log_text)
1669- mock_send_command.assert_called_once_with(cmd='POWR')
1670+ # GIVEN: Test object and mocks
1671+ log_debug_calls = [call('(111.111.111.111) Processing command "CLSS" with data "OK"'),
1672+ call('(111.111.111.111) Command "CLSS" returned OK')]
1673+
1674+ with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
1675+ patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command, \
1676+ patch.object(openlp.core.projectors.pjlink.PJLink, 'process_clss') as mock_process_clss:
1677+
1678+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
1679+
1680+ # WHEN: process_command is called with valid function and data
1681+ pjlink.process_command(cmd='CLSS', data='OK')
1682+
1683+ # THEN: Appropriate log entries should have been made and methods called
1684+ mock_log.debug.assert_has_calls(log_debug_calls)
1685+ mock_send_command.assert_called_once_with(cmd='CLSS')
1686+ mock_process_clss.assert_not_called()
1687
1688=== modified file 'tests/functional/openlp_core/projectors/test_projector_pjlink_commands_01.py'
1689--- tests/functional/openlp_core/projectors/test_projector_pjlink_commands_01.py 2017-12-09 11:17:05 +0000
1690+++ tests/functional/openlp_core/projectors/test_projector_pjlink_commands_01.py 2017-12-25 08:57:51 +0000
1691@@ -23,372 +23,402 @@
1692 Package to test the openlp.core.projectors.pjlink commands package.
1693 """
1694 from unittest import TestCase
1695-from unittest.mock import patch
1696+from unittest.mock import call, patch
1697
1698 import openlp.core.projectors.pjlink
1699-from openlp.core.projectors.constants import ERROR_STRING, PJLINK_ERST_DATA, PJLINK_ERST_STATUS, \
1700- PJLINK_POWR_STATUS, \
1701- E_ERROR, E_NOT_CONNECTED, E_SOCKET_ADDRESS_NOT_AVAILABLE, E_UNKNOWN_SOCKET_ERROR, E_WARN, \
1702- S_CONNECTED, S_OFF, S_ON, S_NOT_CONNECTED, S_CONNECTING, S_STANDBY
1703+from openlp.core.projectors.constants import PJLINK_ERST_DATA, PJLINK_ERST_STATUS, PJLINK_POWR_STATUS, \
1704+ STATUS_CODE, STATUS_MSG, E_ERROR, E_NOT_CONNECTED, E_UNKNOWN_SOCKET_ERROR, E_WARN, \
1705+ S_CONNECTED, S_CONNECTING, S_OFF, S_OK, S_ON, S_NOT_CONNECTED, S_STANDBY
1706 from openlp.core.projectors.db import Projector
1707 from openlp.core.projectors.pjlink import PJLink
1708
1709-from tests.resources.projector.data import TEST_PIN, TEST1_DATA
1710-
1711-pjlink_test = PJLink(Projector(**TEST1_DATA), pin=TEST_PIN, no_poll=True)
1712-pjlink_test.ip = '127.0.0.1'
1713-
1714-# Create a list of ERST positional data so we don't have to redo the same buildup multiple times
1715-PJLINK_ERST_POSITIONS = []
1716-for pos in range(0, len(PJLINK_ERST_DATA)):
1717- if pos in PJLINK_ERST_DATA:
1718- PJLINK_ERST_POSITIONS.append(PJLINK_ERST_DATA[pos])
1719+from tests.resources.projector.data import TEST1_DATA
1720
1721
1722 class TestPJLinkCommands(TestCase):
1723 """
1724 Tests for the PJLinkCommands class part 1
1725 """
1726- @patch.object(pjlink_test, 'changeStatus')
1727- @patch.object(openlp.core.projectors.pjlink, 'log')
1728- def test_projector_change_status_connection_error(self, mock_log, mock_change_status):
1729+ def test_projector_change_status_unknown_socket_error(self):
1730 """
1731 Test change_status with connection error
1732 """
1733- # GIVEN: Test object
1734- pjlink = pjlink_test
1735- pjlink.projector_status = 0
1736- pjlink.status_connect = 0
1737- test_code = E_UNKNOWN_SOCKET_ERROR
1738- mock_change_status.reset_mock()
1739- mock_log.reset_mock()
1740-
1741- # WHEN: change_status called with unknown socket error
1742- pjlink.change_status(status=test_code, msg=None)
1743-
1744- # THEN: Proper settings should change and signals sent
1745- self.assertEqual(pjlink.projector_status, E_NOT_CONNECTED, 'Projector status should be NOT CONNECTED')
1746- self.assertEqual(pjlink.status_connect, E_NOT_CONNECTED, 'Status connect should be NOT CONNECTED')
1747- mock_change_status.emit.assert_called_once_with(pjlink.ip, E_UNKNOWN_SOCKET_ERROR,
1748- 'An unidentified error occurred')
1749- self.assertEqual(mock_log.debug.call_count, 3, 'Debug log should have been called 3 times')
1750-
1751- @patch.object(pjlink_test, 'changeStatus')
1752- @patch.object(openlp.core.projectors.pjlink, 'log')
1753- def test_projector_change_status_connection_status_connecting(self, mock_log, mock_change_status):
1754- """
1755- Test change_status with connection status
1756- """
1757- # GIVEN: Test object
1758- pjlink = pjlink_test
1759- pjlink.projector_status = 0
1760- pjlink.status_connect = 0
1761- test_code = S_CONNECTING
1762- mock_change_status.reset_mock()
1763- mock_log.reset_mock()
1764-
1765- # WHEN: change_status called with unknown socket error
1766- pjlink.change_status(status=test_code, msg=None)
1767-
1768- # THEN: Proper settings should change and signals sent
1769- self.assertEqual(pjlink.projector_status, S_NOT_CONNECTED, 'Projector status should be NOT CONNECTED')
1770- self.assertEqual(pjlink.status_connect, S_CONNECTING, 'Status connect should be CONNECTING')
1771- mock_change_status.emit.assert_called_once_with(pjlink.ip, S_CONNECTING, 'Connecting')
1772- self.assertEqual(mock_log.debug.call_count, 3, 'Debug log should have been called 3 times')
1773-
1774- @patch.object(pjlink_test, 'changeStatus')
1775- @patch.object(openlp.core.projectors.pjlink, 'log')
1776- def test_projector_change_status_connection_status_connected(self, mock_log, mock_change_status):
1777- """
1778- Test change_status with connection status
1779- """
1780- # GIVEN: Test object
1781- pjlink = pjlink_test
1782- pjlink.projector_status = 0
1783- pjlink.status_connect = 0
1784- test_code = S_ON
1785- mock_change_status.reset_mock()
1786- mock_log.reset_mock()
1787-
1788- # WHEN: change_status called with unknown socket error
1789- pjlink.change_status(status=test_code, msg=None)
1790-
1791- # THEN: Proper settings should change and signals sent
1792- self.assertEqual(pjlink.projector_status, S_ON, 'Projector status should be ON')
1793- self.assertEqual(pjlink.status_connect, S_CONNECTED, 'Status connect should be CONNECTED')
1794- mock_change_status.emit.assert_called_once_with(pjlink.ip, S_ON, 'Power is on')
1795- self.assertEqual(mock_log.debug.call_count, 3, 'Debug log should have been called 3 times')
1796-
1797- @patch.object(pjlink_test, 'changeStatus')
1798- @patch.object(openlp.core.projectors.pjlink, 'log')
1799- def test_projector_change_status_connection_status_with_message(self, mock_log, mock_change_status):
1800- """
1801- Test change_status with connection status
1802- """
1803- # GIVEN: Test object
1804- pjlink = pjlink_test
1805- pjlink.projector_status = 0
1806- pjlink.status_connect = 0
1807+ log_debug_calls = [
1808+ call('(111.111.111.111) Changing status to '
1809+ '{status} "{msg}"'.format(status=STATUS_CODE[E_UNKNOWN_SOCKET_ERROR],
1810+ msg=STATUS_MSG[E_UNKNOWN_SOCKET_ERROR])),
1811+ call('(111.111.111.111) status_connect: '
1812+ '{code}: "{msg}"'.format(code=STATUS_CODE[E_NOT_CONNECTED],
1813+ msg=STATUS_MSG[E_NOT_CONNECTED])),
1814+ call('(111.111.111.111) projector_status: '
1815+ '{code}: "{msg}"'.format(code=STATUS_CODE[S_OK],
1816+ msg=STATUS_MSG[S_OK])),
1817+ call('(111.111.111.111) error_status: '
1818+ '{code}: "{msg}"'.format(code=STATUS_CODE[E_UNKNOWN_SOCKET_ERROR],
1819+ msg=STATUS_MSG[E_UNKNOWN_SOCKET_ERROR]))]
1820+
1821+ # GIVEN: Test object and mocks
1822+ with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
1823+ patch.object(openlp.core.projectors.pjlink.PJLink, 'changeStatus') as mock_changeStatus, \
1824+ patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons:
1825+
1826+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
1827+ pjlink.projector_status = 0
1828+ pjlink.status_connect = 0
1829+
1830+ # WHEN: change_status called with unknown socket error
1831+ pjlink.change_status(status=E_UNKNOWN_SOCKET_ERROR)
1832+
1833+ # THEN: Proper settings should change and signals sent
1834+ mock_log.debug.assert_has_calls(log_debug_calls)
1835+ self.assertEqual(pjlink.projector_status, S_OK, 'Projector status should not have changed')
1836+ self.assertEqual(pjlink.status_connect, E_NOT_CONNECTED,
1837+ 'Status connect should be NOT CONNECTED')
1838+ self.assertTrue(mock_UpdateIcons.emit.called, 'Should have called UpdateIcons')
1839+ mock_changeStatus.emit.assert_called_once_with(pjlink.ip, E_UNKNOWN_SOCKET_ERROR,
1840+ STATUS_MSG[E_UNKNOWN_SOCKET_ERROR])
1841+
1842+ def test_projector_change_status_connection_status_connecting(self):
1843+ """
1844+ Test change_status with connecting status
1845+ """
1846+ log_debug_calls = [
1847+ call('(111.111.111.111) Changing status to '
1848+ '{status} "{msg}"'.format(status=STATUS_CODE[S_CONNECTING],
1849+ msg=STATUS_MSG[S_CONNECTING])),
1850+ call('(111.111.111.111) status_connect: '
1851+ '{code}: "{msg}"'.format(code=STATUS_CODE[S_CONNECTING],
1852+ msg=STATUS_MSG[S_CONNECTING])),
1853+ call('(111.111.111.111) projector_status: '
1854+ '{code}: "{msg}"'.format(code=STATUS_CODE[S_OK],
1855+ msg=STATUS_MSG[S_OK])),
1856+ call('(111.111.111.111) error_status: '
1857+ '{code}: "{msg}"'.format(code=STATUS_CODE[S_OK],
1858+ msg=STATUS_MSG[S_OK]))]
1859+
1860+ # GIVEN: Test object and mocks
1861+ with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
1862+ patch.object(openlp.core.projectors.pjlink.PJLink, 'changeStatus') as mock_changeStatus, \
1863+ patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons:
1864+
1865+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
1866+ pjlink.projector_status = 0
1867+ pjlink.status_connect = 0
1868+
1869+ # WHEN: change_status called with CONNECTING
1870+ pjlink.change_status(status=S_CONNECTING)
1871+
1872+ # THEN: Proper settings should change and signals sent
1873+ mock_log.debug.assert_has_calls(log_debug_calls)
1874+ self.assertEqual(pjlink.projector_status, S_OK, 'Projector status should not have changed')
1875+ self.assertEqual(pjlink.status_connect, S_CONNECTING, 'Status connect should be CONNECTING')
1876+ self.assertTrue(mock_UpdateIcons.emit.called, 'Should have called UpdateIcons')
1877+ mock_changeStatus.emit.assert_called_once_with(pjlink.ip, S_CONNECTING, STATUS_MSG[S_CONNECTING])
1878+
1879+ def test_projector_change_status_connection_status_connected(self):
1880+ """
1881+ Test change_status with connected status
1882+ """
1883+ log_debug_calls = [
1884+ call('(111.111.111.111) Changing status to '
1885+ '{status} "{msg}"'.format(status=STATUS_CODE[S_CONNECTED],
1886+ msg=STATUS_MSG[S_CONNECTED])),
1887+ call('(111.111.111.111) status_connect: '
1888+ '{code}: "{msg}"'.format(code=STATUS_CODE[S_CONNECTED],
1889+ msg=STATUS_MSG[S_CONNECTED])),
1890+ call('(111.111.111.111) projector_status: '
1891+ '{code}: "{msg}"'.format(code=STATUS_CODE[S_OK],
1892+ msg=STATUS_MSG[S_OK])),
1893+ call('(111.111.111.111) error_status: '
1894+ '{code}: "{msg}"'.format(code=STATUS_CODE[S_OK],
1895+ msg=STATUS_MSG[S_OK]))]
1896+
1897+ # GIVEN: Test object and mocks
1898+ with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
1899+ patch.object(openlp.core.projectors.pjlink.PJLink, 'changeStatus') as mock_changeStatus:
1900+
1901+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
1902+ pjlink.projector_status = 0
1903+ pjlink.status_connect = 0
1904+
1905+ # WHEN: change_status called with CONNECTED
1906+ pjlink.change_status(status=S_CONNECTED)
1907+
1908+ # THEN: Proper settings should change and signals sent
1909+ mock_log.debug.assert_has_calls(log_debug_calls)
1910+ self.assertEqual(pjlink.projector_status, S_OK, 'Projector status should not have changed')
1911+ self.assertEqual(pjlink.status_connect, S_CONNECTED, 'Status connect should be CONNECTED')
1912+ mock_changeStatus.emit.assert_called_once_with(pjlink.ip, S_CONNECTED, 'Connected')
1913+
1914+ def test_projector_change_status_connection_status_with_message(self):
1915+ """
1916+ Test change_status with connection status
1917+ """
1918 test_message = 'Different Status Message than default'
1919- test_code = S_ON
1920- mock_change_status.reset_mock()
1921- mock_log.reset_mock()
1922-
1923- # WHEN: change_status called with unknown socket error
1924- pjlink.change_status(status=test_code, msg=test_message)
1925-
1926- # THEN: Proper settings should change and signals sent
1927- self.assertEqual(pjlink.projector_status, S_ON, 'Projector status should be ON')
1928- self.assertEqual(pjlink.status_connect, S_CONNECTED, 'Status connect should be CONNECTED')
1929- mock_change_status.emit.assert_called_once_with(pjlink.ip, S_ON, test_message)
1930- self.assertEqual(mock_log.debug.call_count, 3, 'Debug log should have been called 3 times')
1931-
1932- @patch.object(pjlink_test, 'send_command')
1933- @patch.object(openlp.core.projectors.pjlink, 'log')
1934- def test_projector_get_av_mute_status(self, mock_log, mock_send_command):
1935+ log_debug_calls = [
1936+ call('(111.111.111.111) Changing status to {status} "{msg}"'.format(status=STATUS_CODE[S_ON],
1937+ msg=test_message)),
1938+ call('(111.111.111.111) status_connect: {code}: "{msg}"'.format(code=STATUS_CODE[S_OK],
1939+ msg=test_message)),
1940+ call('(111.111.111.111) projector_status: {code}: "{msg}"'.format(code=STATUS_CODE[S_ON],
1941+ msg=test_message)),
1942+ call('(111.111.111.111) error_status: {code}: "{msg}"'.format(code=STATUS_CODE[S_OK],
1943+ msg=test_message))]
1944+
1945+ # GIVEN: Test object and mocks
1946+ with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
1947+ patch.object(openlp.core.projectors.pjlink.PJLink, 'changeStatus') as mock_changeStatus:
1948+
1949+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
1950+ pjlink.projector_status = 0
1951+ pjlink.status_connect = 0
1952+
1953+ # WHEN: change_status called with projector ON status
1954+ pjlink.change_status(status=S_ON, msg=test_message)
1955+
1956+ # THEN: Proper settings should change and signals sent
1957+ mock_log.debug.assert_has_calls(log_debug_calls)
1958+ self.assertEqual(pjlink.projector_status, S_ON, 'Projector status should be ON')
1959+ self.assertEqual(pjlink.status_connect, S_OK, 'Status connect should not have changed')
1960+ mock_changeStatus.emit.assert_called_once_with(pjlink.ip, S_ON, test_message)
1961+
1962+ def test_projector_get_av_mute_status(self):
1963 """
1964 Test sending command to retrieve shutter/audio state
1965 """
1966- # GIVEN: Test object
1967- pjlink = pjlink_test
1968- mock_log.reset_mock()
1969- mock_send_command.reset_mock()
1970 test_data = 'AVMT'
1971- test_log = '(127.0.0.1) Sending AVMT command'
1972-
1973- # WHEN: get_av_mute_status is called
1974- pjlink.get_av_mute_status()
1975-
1976- # THEN: log data and send_command should have been called
1977- mock_log.debug.assert_called_once_with(test_log)
1978- mock_send_command.assert_called_once_with(cmd=test_data)
1979-
1980- @patch.object(pjlink_test, 'send_command')
1981- @patch.object(openlp.core.projectors.pjlink, 'log')
1982- def test_projector_get_available_inputs(self, mock_log, mock_send_command):
1983+ log_debug_calls = [call('(111.111.111.111) reset_information() connect status is '
1984+ '{state}'.format(state=STATUS_CODE[S_NOT_CONNECTED])),
1985+ call('(111.111.111.111) Sending {cmd} command'.format(cmd=test_data))]
1986+
1987+ # GIVEN: Test object and mocks
1988+ with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
1989+ patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command:
1990+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
1991+
1992+ # WHEN: get_av_mute_status is called
1993+ pjlink.get_av_mute_status()
1994+
1995+ # THEN: log data and send_command should have been called
1996+ mock_log.debug.assert_has_calls(log_debug_calls)
1997+ mock_send_command.assert_called_once_with(cmd=test_data)
1998+
1999+ def test_projector_get_available_inputs(self):
2000 """
2001 Test sending command to retrieve avaliable inputs
2002 """
2003- # GIVEN: Test object
2004- pjlink = pjlink_test
2005- mock_log.reset_mock()
2006- mock_send_command.reset_mock()
2007 test_data = 'INST'
2008- test_log = '(127.0.0.1) Sending INST command'
2009-
2010- # WHEN: get_available_inputs is called
2011- pjlink.get_available_inputs()
2012-
2013- # THEN: log data and send_command should have been called
2014- mock_log.debug.assert_called_once_with(test_log)
2015- mock_send_command.assert_called_once_with(cmd=test_data)
2016-
2017- @patch.object(pjlink_test, 'send_command')
2018- @patch.object(openlp.core.projectors.pjlink, 'log')
2019- def test_projector_get_error_status(self, mock_log, mock_send_command):
2020+ log_debug_calls = [call('(111.111.111.111) reset_information() connect status is '
2021+ '{state}'.format(state=STATUS_CODE[S_NOT_CONNECTED])),
2022+ call('(111.111.111.111) Sending {cmd} command'.format(cmd=test_data))]
2023+
2024+ # GIVEN: Test object and mocks
2025+ with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
2026+ patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command:
2027+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
2028+
2029+ # WHEN: get_available_inputs is called
2030+ pjlink.get_available_inputs()
2031+
2032+ # THEN: log data and send_command should have been called
2033+ mock_log.debug.assert_has_calls(log_debug_calls)
2034+ mock_send_command.assert_called_once_with(cmd=test_data)
2035+
2036+ def test_projector_get_error_status(self):
2037 """
2038 Test sending command to retrieve projector error status
2039 """
2040- # GIVEN: Test object
2041- pjlink = pjlink_test
2042- mock_log.reset_mock()
2043- mock_send_command.reset_mock()
2044 test_data = 'ERST'
2045- test_log = '(127.0.0.1) Sending ERST command'
2046-
2047- # WHEN: get_error_status is called
2048- pjlink.get_error_status()
2049-
2050- # THEN: log data and send_command should have been called
2051- mock_log.debug.assert_called_once_with(test_log)
2052- mock_send_command.assert_called_once_with(cmd=test_data)
2053-
2054- @patch.object(pjlink_test, 'send_command')
2055- @patch.object(openlp.core.projectors.pjlink, 'log')
2056- def test_projector_get_input_source(self, mock_log, mock_send_command):
2057+ log_debug_calls = [call('(111.111.111.111) reset_information() connect status is '
2058+ '{state}'.format(state=STATUS_CODE[S_NOT_CONNECTED])),
2059+ call('(111.111.111.111) Sending {cmd} command'.format(cmd=test_data))]
2060+ # GIVEN: Test object and mocks
2061+ with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
2062+ patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command:
2063+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
2064+
2065+ # WHEN: get_error_status is called
2066+ pjlink.get_error_status()
2067+
2068+ # THEN: log data and send_command should have been called
2069+ mock_log.debug.assert_has_calls(log_debug_calls)
2070+ mock_send_command.assert_called_once_with(cmd=test_data)
2071+
2072+ def test_projector_get_input_source(self):
2073 """
2074 Test sending command to retrieve current input
2075 """
2076- # GIVEN: Test object
2077- pjlink = pjlink_test
2078- mock_log.reset_mock()
2079- mock_send_command.reset_mock()
2080 test_data = 'INPT'
2081- test_log = '(127.0.0.1) Sending INPT command'
2082-
2083- # WHEN: get_input_source is called
2084- pjlink.get_input_source()
2085-
2086- # THEN: log data and send_command should have been called
2087- mock_log.debug.assert_called_once_with(test_log)
2088- mock_send_command.assert_called_once_with(cmd=test_data)
2089-
2090- @patch.object(pjlink_test, 'send_command')
2091- @patch.object(openlp.core.projectors.pjlink, 'log')
2092- def test_projector_get_lamp_status(self, mock_log, mock_send_command):
2093+ log_debug_calls = [call('(111.111.111.111) reset_information() connect status is '
2094+ '{state}'.format(state=STATUS_CODE[S_NOT_CONNECTED])),
2095+ call('(111.111.111.111) Sending {cmd} command'.format(cmd=test_data))]
2096+
2097+ # GIVEN: Test object and mocks
2098+ with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
2099+ patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command:
2100+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
2101+
2102+ # WHEN: get_input_source is called
2103+ pjlink.get_input_source()
2104+
2105+ # THEN: log data and send_command should have been called
2106+ mock_log.debug.assert_has_calls(log_debug_calls)
2107+ mock_send_command.assert_called_once_with(cmd=test_data)
2108+
2109+ def test_projector_get_lamp_status(self):
2110 """
2111 Test sending command to retrieve lamp(s) status
2112 """
2113- # GIVEN: Test object
2114- pjlink = pjlink_test
2115- mock_log.reset_mock()
2116- mock_send_command.reset_mock()
2117 test_data = 'LAMP'
2118- test_log = '(127.0.0.1) Sending LAMP command'
2119-
2120- # WHEN: get_lamp_status is called
2121- pjlink.get_lamp_status()
2122-
2123- # THEN: log data and send_command should have been called
2124- mock_log.debug.assert_called_once_with(test_log)
2125- mock_send_command.assert_called_once_with(cmd=test_data)
2126-
2127- @patch.object(pjlink_test, 'send_command')
2128- @patch.object(openlp.core.projectors.pjlink, 'log')
2129- def test_projector_get_manufacturer(self, mock_log, mock_send_command):
2130+ log_debug_calls = [call('(111.111.111.111) reset_information() connect status is '
2131+ '{state}'.format(state=STATUS_CODE[S_NOT_CONNECTED])),
2132+ call('(111.111.111.111) Sending {cmd} command'.format(cmd=test_data))]
2133+
2134+ # GIVEN: Test object and mocks
2135+ with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
2136+ patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command:
2137+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
2138+
2139+ # WHEN: get_input_source is called
2140+ pjlink.get_lamp_status()
2141+
2142+ # THEN: log data and send_command should have been called
2143+ mock_log.debug.assert_has_calls(log_debug_calls)
2144+ mock_send_command.assert_called_once_with(cmd=test_data)
2145+
2146+ def test_projector_get_manufacturer(self):
2147 """
2148 Test sending command to retrieve manufacturer name
2149 """
2150- # GIVEN: Test object
2151- pjlink = pjlink_test
2152- mock_log.reset_mock()
2153- mock_send_command.reset_mock()
2154 test_data = 'INF1'
2155- test_log = '(127.0.0.1) Sending INF1 command'
2156-
2157- # WHEN: get_manufacturer is called
2158- pjlink.get_manufacturer()
2159-
2160- # THEN: log data and send_command should have been called
2161- mock_log.debug.assert_called_once_with(test_log)
2162- mock_send_command.assert_called_once_with(cmd=test_data)
2163-
2164- @patch.object(pjlink_test, 'send_command')
2165- @patch.object(openlp.core.projectors.pjlink, 'log')
2166- def test_projector_get_model(self, mock_log, mock_send_command):
2167+ log_debug_calls = [call('(111.111.111.111) reset_information() connect status is '
2168+ '{state}'.format(state=STATUS_CODE[S_NOT_CONNECTED])),
2169+ call('(111.111.111.111) Sending {cmd} command'.format(cmd=test_data))]
2170+
2171+ # GIVEN: Test object and mocks
2172+ with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
2173+ patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command:
2174+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
2175+
2176+ # WHEN: get_input_source is called
2177+ pjlink.get_manufacturer()
2178+
2179+ # THEN: log data and send_command should have been called
2180+ mock_log.debug.assert_has_calls(log_debug_calls)
2181+ mock_send_command.assert_called_once_with(cmd=test_data)
2182+
2183+ def test_projector_get_model(self):
2184 """
2185 Test sending command to get model information
2186 """
2187- # GIVEN: Test object
2188- pjlink = pjlink_test
2189- mock_log.reset_mock()
2190- mock_send_command.reset_mock()
2191 test_data = 'INF2'
2192- test_log = '(127.0.0.1) Sending INF2 command'
2193-
2194- # WHEN: get_model is called
2195- pjlink.get_model()
2196-
2197- # THEN: log data and send_command should have been called
2198- mock_log.debug.assert_called_once_with(test_log)
2199- mock_send_command.assert_called_once_with(cmd=test_data)
2200-
2201- @patch.object(pjlink_test, 'send_command')
2202- @patch.object(openlp.core.projectors.pjlink, 'log')
2203- def test_projector_get_name(self, mock_log, mock_send_command):
2204+ log_debug_calls = [call('(111.111.111.111) reset_information() connect status is '
2205+ '{state}'.format(state=STATUS_CODE[S_NOT_CONNECTED])),
2206+ call('(111.111.111.111) Sending {cmd} command'.format(cmd=test_data))]
2207+
2208+ # GIVEN: Test object and mocks
2209+ with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
2210+ patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command:
2211+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
2212+
2213+ # WHEN: get_input_source is called
2214+ pjlink.get_model()
2215+
2216+ # THEN: log data and send_command should have been called
2217+ mock_log.debug.assert_has_calls(log_debug_calls)
2218+ mock_send_command.assert_called_once_with(cmd=test_data)
2219+
2220+ def test_projector_get_name(self):
2221 """
2222 Test sending command to get user-assigned name
2223 """
2224- # GIVEN: Test object
2225- pjlink = pjlink_test
2226- mock_log.reset_mock()
2227- mock_send_command.reset_mock()
2228 test_data = 'NAME'
2229- test_log = '(127.0.0.1) Sending NAME command'
2230-
2231- # WHEN: get_name is called
2232- pjlink.get_name()
2233-
2234- # THEN: log data and send_command should have been called
2235- mock_log.debug.assert_called_once_with(test_log)
2236- mock_send_command.assert_called_once_with(cmd=test_data)
2237-
2238- @patch.object(pjlink_test, 'send_command')
2239- @patch.object(openlp.core.projectors.pjlink, 'log')
2240- def test_projector_get_other_info(self, mock_log, mock_send_command):
2241+ log_debug_calls = [call('(111.111.111.111) reset_information() connect status is '
2242+ '{state}'.format(state=STATUS_CODE[S_NOT_CONNECTED])),
2243+ call('(111.111.111.111) Sending {cmd} command'.format(cmd=test_data))]
2244+
2245+ # GIVEN: Test object and mocks
2246+ with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
2247+ patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command:
2248+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
2249+
2250+ # WHEN: get_input_source is called
2251+ pjlink.get_name()
2252+
2253+ # THEN: log data and send_command should have been called
2254+ mock_log.debug.assert_has_calls(log_debug_calls)
2255+ mock_send_command.assert_called_once_with(cmd=test_data)
2256+
2257+ def test_projector_get_other_info(self):
2258 """
2259 Test sending command to retrieve other information
2260 """
2261- # GIVEN: Test object
2262- pjlink = pjlink_test
2263- mock_log.reset_mock()
2264- mock_send_command.reset_mock()
2265 test_data = 'INFO'
2266- test_log = '(127.0.0.1) Sending INFO command'
2267-
2268- # WHEN: get_other_info is called
2269- pjlink.get_other_info()
2270-
2271- # THEN: log data and send_command should have been called
2272- mock_log.debug.assert_called_once_with(test_log)
2273- mock_send_command.assert_called_once_with(cmd=test_data)
2274-
2275- @patch.object(pjlink_test, 'send_command')
2276- @patch.object(openlp.core.projectors.pjlink, 'log')
2277- def test_projector_get_power_status(self, mock_log, mock_send_command):
2278+ log_debug_calls = [call('(111.111.111.111) reset_information() connect status is '
2279+ '{state}'.format(state=STATUS_CODE[S_NOT_CONNECTED])),
2280+ call('(111.111.111.111) Sending {cmd} command'.format(cmd=test_data))]
2281+
2282+ # GIVEN: Test object and mocks
2283+ with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
2284+ patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command:
2285+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
2286+
2287+ # WHEN: get_input_source is called
2288+ pjlink.get_other_info()
2289+
2290+ # THEN: log data and send_command should have been called
2291+ mock_log.debug.assert_has_calls(log_debug_calls)
2292+ mock_send_command.assert_called_once_with(cmd=test_data)
2293+
2294+ def test_projector_get_power_status(self):
2295 """
2296 Test sending command to retrieve current power state
2297 """
2298- # GIVEN: Test object
2299- pjlink = pjlink_test
2300- mock_log.reset_mock()
2301- mock_send_command.reset_mock()
2302 test_data = 'POWR'
2303- test_log = '(127.0.0.1) Sending POWR command'
2304-
2305- # WHEN: get_power_status called
2306- pjlink.get_power_status()
2307-
2308- # THEN: log data and send_command should have been called
2309- mock_log.debug.assert_called_once_with(test_log)
2310- mock_send_command.assert_called_once_with(cmd=test_data)
2311-
2312- def test_projector_get_status_error(self):
2313- """
2314- Test to check returned information for error code
2315- """
2316- # GIVEN: Test object
2317- pjlink = pjlink_test
2318- test_string = 'E_SOCKET_ADDRESS_NOT_AVAILABLE'
2319- test_message = 'The address specified to socket.bind() does not belong to the host'
2320-
2321- # WHEN: get_status called
2322- string, message = pjlink._get_status(status=E_SOCKET_ADDRESS_NOT_AVAILABLE)
2323-
2324- # THEN: Proper strings should have been returned
2325- self.assertEqual(string, test_string, 'Code as string should have been returned')
2326- self.assertEqual(message, test_message, 'Description of code should have been returned')
2327+ log_debug_calls = [call('(111.111.111.111) reset_information() connect status is '
2328+ '{state}'.format(state=STATUS_CODE[S_NOT_CONNECTED])),
2329+ call('(111.111.111.111) Sending {cmd} command'.format(cmd=test_data))]
2330+
2331+ # GIVEN: Test object and mocks
2332+ with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
2333+ patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command:
2334+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
2335+
2336+ # WHEN: get_input_source is called
2337+ pjlink.get_power_status()
2338+
2339+ # THEN: log data and send_command should have been called
2340+ mock_log.debug.assert_has_calls(log_debug_calls)
2341+ mock_send_command.assert_called_once_with(cmd=test_data)
2342
2343 def test_projector_get_status_invalid(self):
2344 """
2345 Test to check returned information for error code
2346 """
2347 # GIVEN: Test object
2348- pjlink = pjlink_test
2349- test_string = 'Test string since get_status will only work with int'
2350- test_message = 'Invalid status code'
2351+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
2352+ test_string = 'NaN test'
2353
2354 # WHEN: get_status called
2355- string, message = pjlink._get_status(status=test_string)
2356-
2357- # THEN: Proper strings should have been returned
2358- self.assertEqual(string, -1, 'Should have returned -1 as a bad status check')
2359- self.assertEqual(message, test_message, 'Error message should have been returned')
2360-
2361- def test_projector_get_status_status(self):
2362+ code, message = pjlink._get_status(status=test_string)
2363+
2364+ # THEN: Proper data should have been returned
2365+ self.assertEqual(code, -1, 'Should have returned -1 as a bad status check')
2366+ self.assertIsNone(message, 'Invalid code type should have returned None for message')
2367+
2368+ def test_projector_get_status_valid(self):
2369 """
2370 Test to check returned information for status codes
2371 """
2372 # GIVEN: Test object
2373- pjlink = pjlink_test
2374- test_string = 'S_NOT_CONNECTED'
2375- test_message = 'Not connected'
2376+ test_message = 'Not Connected'
2377+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
2378
2379 # WHEN: get_status called
2380- string, message = pjlink._get_status(status=S_NOT_CONNECTED)
2381+ code, message = pjlink._get_status(status=S_NOT_CONNECTED)
2382
2383 # THEN: Proper strings should have been returned
2384- self.assertEqual(string, test_string, 'Code as string should have been returned')
2385+ self.assertEqual(code, 'S_NOT_CONNECTED', 'Code returned should have been the same code that was sent')
2386 self.assertEqual(message, test_message, 'Description of code should have been returned')
2387
2388 def test_projector_get_status_unknown(self):
2389@@ -396,25 +426,24 @@
2390 Test to check returned information for unknown code
2391 """
2392 # GIVEN: Test object
2393- pjlink = pjlink_test
2394- test_string = 999999
2395- test_message = 'Unknown status'
2396+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
2397
2398 # WHEN: get_status called
2399- string, message = pjlink._get_status(status=test_string)
2400+ code, message = pjlink._get_status(status=9999)
2401
2402 # THEN: Proper strings should have been returned
2403- self.assertEqual(string, test_string, 'Received code should have been returned')
2404- self.assertEqual(message, test_message, 'Unknown status string should have been returned')
2405+ self.assertIsNone(code, 'Code returned should have been the same code that was sent')
2406+ self.assertIsNone(message, 'Should have returned None as message')
2407
2408 def test_projector_process_inf1(self):
2409 """
2410 Test saving INF1 data (manufacturer)
2411 """
2412+ test_data = 'TEst INformation MultiCase'
2413+
2414 # GIVEN: Test object
2415- pjlink = pjlink_test
2416+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
2417 pjlink.manufacturer = None
2418- test_data = 'TEst INformation MultiCase'
2419
2420 # WHEN: process_inf called with test data
2421 pjlink.process_inf1(data=test_data)
2422@@ -426,10 +455,11 @@
2423 """
2424 Test saving INF2 data (model)
2425 """
2426+ test_data = 'TEst moDEl MultiCase'
2427+
2428 # GIVEN: Test object
2429- pjlink = pjlink_test
2430+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
2431 pjlink.model = None
2432- test_data = 'TEst moDEl MultiCase'
2433
2434 # WHEN: process_inf called with test data
2435 pjlink.process_inf2(data=test_data)
2436@@ -441,10 +471,11 @@
2437 """
2438 Test saving INFO data (other information)
2439 """
2440+ test_data = 'TEst ExtrANEous MultiCase INformatoin that MFGR might Set'
2441+
2442 # GIVEN: Test object
2443- pjlink = pjlink_test
2444+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
2445 pjlink.other_info = None
2446- test_data = 'TEst ExtrANEous MultiCase INformatoin that MFGR might Set'
2447
2448 # WHEN: process_inf called with test data
2449 pjlink.process_info(data=test_data)
2450@@ -452,509 +483,558 @@
2451 # THEN: Data should be saved
2452 self.assertEqual(pjlink.other_info, test_data, 'Test data should have been saved')
2453
2454- @patch.object(pjlink_test, 'projectorUpdateIcons')
2455- def test_projector_process_avmt_bad_data(self, mock_UpdateIcons):
2456+ def test_projector_process_avmt_bad_data(self):
2457 """
2458 Test avmt bad data fail
2459 """
2460 # GIVEN: Test object
2461- pjlink = pjlink_test
2462- pjlink.shutter = True
2463- pjlink.mute = True
2464-
2465- # WHEN: Called with an invalid setting
2466- pjlink.process_avmt('36')
2467-
2468- # THEN: Shutter should be closed and mute should be True
2469- self.assertTrue(pjlink.shutter, 'Shutter should changed')
2470- self.assertTrue(pjlink.mute, 'Audio should not have changed')
2471- self.assertFalse(mock_UpdateIcons.emit.called, 'Update icons should NOT have been called')
2472-
2473- @patch.object(pjlink_test, 'projectorUpdateIcons')
2474- def test_projector_process_avmt_closed_muted(self, mock_UpdateIcons):
2475+ with patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons:
2476+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
2477+ pjlink.shutter = True
2478+ pjlink.mute = True
2479+
2480+ # WHEN: Called with an invalid setting
2481+ pjlink.process_avmt('36')
2482+
2483+ # THEN: Shutter should be closed and mute should be True
2484+ self.assertTrue(pjlink.shutter, 'Shutter should changed')
2485+ self.assertTrue(pjlink.mute, 'Audio should not have changed')
2486+ self.assertFalse(mock_UpdateIcons.emit.called, 'Update icons should NOT have been called')
2487+
2488+ def test_projector_process_avmt_closed_muted(self):
2489 """
2490 Test avmt status shutter closed and mute off
2491 """
2492 # GIVEN: Test object
2493- pjlink = pjlink_test
2494- pjlink.shutter = False
2495- pjlink.mute = False
2496-
2497- # WHEN: Called with setting shutter to closed and mute on
2498- pjlink.process_avmt('31')
2499-
2500- # THEN: Shutter should be closed and mute should be True
2501- self.assertTrue(pjlink.shutter, 'Shutter should have been set to closed')
2502- self.assertTrue(pjlink.mute, 'Audio should be muted')
2503- self.assertTrue(mock_UpdateIcons.emit.called, 'Update icons should have been called')
2504-
2505- @patch.object(pjlink_test, 'projectorUpdateIcons')
2506- def test_projector_process_avmt_shutter_closed(self, mock_UpdateIcons):
2507+ with patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons:
2508+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
2509+ pjlink.shutter = False
2510+ pjlink.mute = False
2511+
2512+ # WHEN: Called with setting shutter to closed and mute on
2513+ pjlink.process_avmt('31')
2514+
2515+ # THEN: Shutter should be closed and mute should be True
2516+ self.assertTrue(pjlink.shutter, 'Shutter should have been set to closed')
2517+ self.assertTrue(pjlink.mute, 'Audio should be muted')
2518+ self.assertTrue(mock_UpdateIcons.emit.called, 'Update icons should have been called')
2519+
2520+ def test_projector_process_avmt_shutter_closed(self):
2521 """
2522 Test avmt status shutter closed and audio unchanged
2523 """
2524 # GIVEN: Test object
2525- pjlink = pjlink_test
2526- pjlink.shutter = False
2527- pjlink.mute = True
2528-
2529- # WHEN: Called with setting shutter closed and mute off
2530- pjlink.process_avmt('11')
2531-
2532- # THEN: Shutter should be True and mute should be False
2533- self.assertTrue(pjlink.shutter, 'Shutter should have been set to closed')
2534- self.assertTrue(pjlink.mute, 'Audio should not have changed')
2535- self.assertTrue(mock_UpdateIcons.emit.called, 'Update icons should have been called')
2536-
2537- @patch.object(pjlink_test, 'projectorUpdateIcons')
2538- def test_projector_process_avmt_audio_muted(self, mock_UpdateIcons):
2539+ with patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons:
2540+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
2541+ pjlink.shutter = False
2542+ pjlink.mute = True
2543+
2544+ # WHEN: Called with setting shutter closed and mute off
2545+ pjlink.process_avmt('11')
2546+
2547+ # THEN: Shutter should be True and mute should be False
2548+ self.assertTrue(pjlink.shutter, 'Shutter should have been set to closed')
2549+ self.assertTrue(pjlink.mute, 'Audio should not have changed')
2550+ self.assertTrue(mock_UpdateIcons.emit.called, 'Update icons should have been called')
2551+
2552+ def test_projector_process_avmt_audio_muted(self):
2553 """
2554 Test avmt status shutter unchanged and mute on
2555 """
2556 # GIVEN: Test object
2557- pjlink = pjlink_test
2558- pjlink.shutter = True
2559- pjlink.mute = False
2560-
2561- # WHEN: Called with setting shutter closed and mute on
2562- pjlink.process_avmt('21')
2563-
2564- # THEN: Shutter should be closed and mute should be True
2565- self.assertTrue(pjlink.shutter, 'Shutter should not have changed')
2566- self.assertTrue(pjlink.mute, 'Audio should be off')
2567- self.assertTrue(mock_UpdateIcons.emit.called, 'Update icons should have been called')
2568-
2569- @patch.object(pjlink_test, 'projectorUpdateIcons')
2570- def test_projector_process_avmt_open_unmuted(self, mock_UpdateIcons):
2571+ with patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons:
2572+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
2573+ pjlink.shutter = True
2574+ pjlink.mute = False
2575+
2576+ # WHEN: Called with setting shutter closed and mute on
2577+ pjlink.process_avmt('21')
2578+
2579+ # THEN: Shutter should be closed and mute should be True
2580+ self.assertTrue(pjlink.shutter, 'Shutter should not have changed')
2581+ self.assertTrue(pjlink.mute, 'Audio should be off')
2582+ self.assertTrue(mock_UpdateIcons.emit.called, 'Update icons should have been called')
2583+
2584+ def test_projector_process_avmt_open_unmuted(self):
2585 """
2586 Test avmt status shutter open and mute off
2587 """
2588 # GIVEN: Test object
2589- pjlink = pjlink_test
2590- pjlink.shutter = True
2591- pjlink.mute = True
2592-
2593- # WHEN: Called with setting shutter to closed and mute on
2594- pjlink.process_avmt('30')
2595-
2596- # THEN: Shutter should be closed and mute should be True
2597- self.assertFalse(pjlink.shutter, 'Shutter should have been set to open')
2598- self.assertFalse(pjlink.mute, 'Audio should be on')
2599- self.assertTrue(mock_UpdateIcons.emit.called, 'Update icons should have been called')
2600+ with patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons:
2601+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
2602+ pjlink.shutter = True
2603+ pjlink.mute = True
2604+
2605+ # WHEN: Called with setting shutter to closed and mute on
2606+ pjlink.process_avmt('30')
2607+
2608+ # THEN: Shutter should be closed and mute should be True
2609+ self.assertFalse(pjlink.shutter, 'Shutter should have been set to open')
2610+ self.assertFalse(pjlink.mute, 'Audio should be on')
2611+ self.assertTrue(mock_UpdateIcons.emit.called, 'Update icons should have been called')
2612
2613 def test_projector_process_clss_one(self):
2614 """
2615 Test class 1 sent from projector
2616 """
2617 # GIVEN: Test object
2618- pjlink = pjlink_test
2619+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
2620
2621 # WHEN: Process class response
2622 pjlink.process_clss('1')
2623
2624 # THEN: Projector class should be set to 1
2625- self.assertEqual(pjlink.pjlink_class, '1',
2626- 'Projector should have set class=1')
2627+ self.assertEqual(pjlink.pjlink_class, '1', 'Projector should have set class=1')
2628
2629 def test_projector_process_clss_two(self):
2630 """
2631 Test class 2 sent from projector
2632 """
2633 # GIVEN: Test object
2634- pjlink = pjlink_test
2635+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
2636
2637 # WHEN: Process class response
2638 pjlink.process_clss('2')
2639
2640 # THEN: Projector class should be set to 1
2641- self.assertEqual(pjlink.pjlink_class, '2',
2642- 'Projector should have set class=2')
2643-
2644- @patch.object(openlp.core.projectors.pjlink, 'log')
2645- def test_projector_process_clss_invalid_nan(self, mock_log):
2646- """
2647- Test CLSS reply has no class number
2648- """
2649- # GIVEN: Test object
2650- pjlink = pjlink_test
2651-
2652- # WHEN: Process invalid reply
2653- pjlink.process_clss('Z')
2654- log_text = '(127.0.0.1) NAN CLSS version reply "Z" - defaulting to class "1"'
2655-
2656- # THEN: Projector class should be set with default value
2657- self.assertEqual(pjlink.pjlink_class, '1',
2658- 'Non-standard class reply should have set class=1')
2659- mock_log.error.assert_called_once_with(log_text)
2660-
2661- @patch.object(openlp.core.projectors.pjlink, 'log')
2662- def test_projector_process_clss_invalid_no_version(self, mock_log):
2663- """
2664- Test CLSS reply has no class number
2665- """
2666- # GIVEN: Test object
2667- pjlink = pjlink_test
2668-
2669- # WHEN: Process invalid reply
2670- pjlink.process_clss('Invalid')
2671- log_text = '(127.0.0.1) No numbers found in class version reply "Invalid" - defaulting to class "1"'
2672-
2673- # THEN: Projector class should be set with default value
2674- self.assertEqual(pjlink.pjlink_class, '1',
2675- 'Non-standard class reply should have set class=1')
2676- mock_log.error.assert_called_once_with(log_text)
2677+ self.assertEqual(pjlink.pjlink_class, '2', 'Projector should have set class=2')
2678+
2679+ def test_projector_process_clss_invalid_nan(self):
2680+ """
2681+ Test CLSS reply has no class number
2682+ """
2683+ log_debug_calls = [call('(111.111.111.111) reset_information() connect status is '
2684+ '{state}'.format(state=STATUS_CODE[S_NOT_CONNECTED])),
2685+ call('(111.111.111.111) Setting pjlink_class for this projector to "1"')]
2686+ log_error_calls = [call('(111.111.111.111) NAN CLSS version reply "Z" - defaulting to class "1"')]
2687+
2688+ # GIVEN: Test object
2689+ with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
2690+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
2691+
2692+ # WHEN: Process invalid reply
2693+ pjlink.process_clss('Z')
2694+
2695+ # THEN: Projector class should be set with default value
2696+ self.assertEqual(pjlink.pjlink_class, '1', 'Invalid NaN class reply should have set class=1')
2697+ mock_log.error.assert_has_calls(log_error_calls)
2698+ mock_log.debug.assert_has_calls(log_debug_calls)
2699+
2700+ def test_projector_process_clss_invalid_no_version(self):
2701+ """
2702+ Test CLSS reply has no class number
2703+ """
2704+ log_debug_calls = [call('(111.111.111.111) reset_information() connect status is '
2705+ '{state}'.format(state=STATUS_CODE[S_NOT_CONNECTED])),
2706+ call('(111.111.111.111) Setting pjlink_class for this projector to "1"')]
2707+ log_error_calls = [call('(111.111.111.111) No numbers found in class version reply "Invalid" '
2708+ '- defaulting to class "1"')]
2709+
2710+ # GIVEN: Test object
2711+ with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
2712+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
2713+
2714+ # WHEN: Process invalid reply
2715+ pjlink.process_clss('Invalid')
2716+
2717+ # THEN: Projector class should be set with default value
2718+ self.assertEqual(pjlink.pjlink_class, '1', 'Invalid class reply should have set class=1')
2719+ mock_log.error.assert_has_calls(log_error_calls)
2720+ mock_log.debug.assert_has_calls(log_debug_calls)
2721
2722 def test_projector_process_erst_all_ok(self):
2723 """
2724- Test test_projector_process_erst_all_ok
2725+ Test to verify pjlink.projector_errors is set to None when no errors
2726 """
2727+ chk_data = '0' * PJLINK_ERST_DATA['DATA_LENGTH']
2728+
2729 # GIVEN: Test object
2730- pjlink = pjlink_test
2731- chk_test = PJLINK_ERST_STATUS['OK']
2732- chk_param = chk_test * len(PJLINK_ERST_POSITIONS)
2733+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
2734
2735 # WHEN: process_erst with no errors
2736- pjlink.process_erst(chk_param)
2737+ pjlink.process_erst(chk_data)
2738
2739 # THEN: PJLink instance errors should be None
2740 self.assertIsNone(pjlink.projector_errors, 'projector_errors should have been set to None')
2741
2742- @patch.object(openlp.core.projectors.pjlink, 'log')
2743- def test_projector_process_erst_data_invalid_length(self, mock_log):
2744+ def test_projector_process_erst_data_invalid_length(self):
2745 """
2746 Test test_projector_process_erst_data_invalid_length
2747 """
2748+ chk_data = '0' * (PJLINK_ERST_DATA['DATA_LENGTH'] + 1)
2749+ log_debug_calls = [call('(111.111.111.111) reset_information() connect status is '
2750+ '{state}'.format(state=STATUS_CODE[S_NOT_CONNECTED]))]
2751+ log_warn_calls = [call('111.111.111.111) Invalid error status response "0000000": '
2752+ 'length != {chk}'.format(chk=PJLINK_ERST_DATA['DATA_LENGTH']))]
2753+
2754 # GIVEN: Test object
2755- pjlink = pjlink_test
2756- pjlink.projector_errors = None
2757- log_text = '127.0.0.1) Invalid error status response "11111111": length != 6'
2758-
2759- # WHEN: process_erst called with invalid data (too many values
2760- pjlink.process_erst('11111111')
2761-
2762- # THEN: pjlink.projector_errors should be empty and warning logged
2763- self.assertIsNone(pjlink.projector_errors, 'There should be no errors')
2764- self.assertTrue(mock_log.warning.called, 'Warning should have been logged')
2765- mock_log.warning.assert_called_once_with(log_text)
2766-
2767- @patch.object(openlp.core.projectors.pjlink, 'log')
2768- def test_projector_process_erst_data_invalid_nan(self, mock_log):
2769+ with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
2770+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
2771+ pjlink.projector_errors = None
2772+
2773+ # WHEN: process_erst called with invalid data (too many values
2774+ pjlink.process_erst(chk_data)
2775+
2776+ # THEN: pjlink.projector_errors should be empty and warning logged
2777+ self.assertIsNone(pjlink.projector_errors, 'There should be no errors')
2778+ mock_log.debug.assert_has_calls(log_debug_calls)
2779+ mock_log.warning.assert_has_calls(log_warn_calls)
2780+
2781+ def test_projector_process_erst_data_invalid_nan(self):
2782 """
2783 Test test_projector_process_erst_data_invalid_nan
2784 """
2785+ chk_data = 'Z' + ('0' * (PJLINK_ERST_DATA['DATA_LENGTH'] - 1))
2786+ log_debug_calls = [call('(111.111.111.111) reset_information() connect status is '
2787+ '{state}'.format(state=STATUS_CODE[S_NOT_CONNECTED]))]
2788+ log_warn_calls = [call('(111.111.111.111) Invalid error status response "Z00000"')]
2789+
2790 # GIVEN: Test object
2791- pjlink = pjlink_test
2792- pjlink.projector_errors = None
2793- log_text = '(127.0.0.1) Invalid error status response "1111Z1"'
2794-
2795- # WHEN: process_erst called with invalid data (too many values
2796- pjlink.process_erst('1111Z1')
2797-
2798- # THEN: pjlink.projector_errors should be empty and warning logged
2799- self.assertIsNone(pjlink.projector_errors, 'There should be no errors')
2800- self.assertTrue(mock_log.warning.called, 'Warning should have been logged')
2801- mock_log.warning.assert_called_once_with(log_text)
2802+ with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
2803+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
2804+ pjlink.projector_errors = None
2805+
2806+ # WHEN: process_erst called with invalid data (too many values
2807+ pjlink.process_erst(chk_data)
2808+
2809+ # THEN: pjlink.projector_errors should be empty and warning logged
2810+ self.assertIsNone(pjlink.projector_errors, 'There should be no errors')
2811+ mock_log.debug.assert_has_calls(log_debug_calls)
2812+ mock_log.warning.assert_has_calls(log_warn_calls)
2813
2814 def test_projector_process_erst_all_warn(self):
2815 """
2816 Test test_projector_process_erst_all_warn
2817 """
2818+ chk_data = '{fan}{lamp}{temp}{cover}{filt}{other}'.format(fan=PJLINK_ERST_STATUS[E_WARN],
2819+ lamp=PJLINK_ERST_STATUS[E_WARN],
2820+ temp=PJLINK_ERST_STATUS[E_WARN],
2821+ cover=PJLINK_ERST_STATUS[E_WARN],
2822+ filt=PJLINK_ERST_STATUS[E_WARN],
2823+ other=PJLINK_ERST_STATUS[E_WARN])
2824+ chk_test = {'Fan': E_WARN,
2825+ 'Lamp': E_WARN,
2826+ 'Temperature': E_WARN,
2827+ 'Cover': E_WARN,
2828+ 'Filter': E_WARN,
2829+ 'Other': E_WARN}
2830+
2831 # GIVEN: Test object
2832- pjlink = pjlink_test
2833- chk_test = PJLINK_ERST_STATUS[E_WARN]
2834- chk_string = ERROR_STRING[E_WARN]
2835- chk_param = chk_test * len(PJLINK_ERST_POSITIONS)
2836+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
2837+ pjlink.projector_errors = None
2838
2839 # WHEN: process_erst with status set to WARN
2840- pjlink.process_erst(chk_param)
2841+ pjlink.process_erst(chk_data)
2842
2843 # THEN: PJLink instance errors should match chk_value
2844- for chk in pjlink.projector_errors:
2845- self.assertEqual(pjlink.projector_errors[chk], chk_string,
2846- 'projector_errors["{chk}"] should have been set to "{err}"'.format(chk=chk,
2847- err=chk_string))
2848+ self.assertEqual(pjlink.projector_errors, chk_test, 'Projector errors should be all E_WARN')
2849
2850 def test_projector_process_erst_all_error(self):
2851 """
2852 Test test_projector_process_erst_all_error
2853 """
2854+ chk_data = '{fan}{lamp}{temp}{cover}{filt}{other}'.format(fan=PJLINK_ERST_STATUS[E_ERROR],
2855+ lamp=PJLINK_ERST_STATUS[E_ERROR],
2856+ temp=PJLINK_ERST_STATUS[E_ERROR],
2857+ cover=PJLINK_ERST_STATUS[E_ERROR],
2858+ filt=PJLINK_ERST_STATUS[E_ERROR],
2859+ other=PJLINK_ERST_STATUS[E_ERROR])
2860+ chk_test = {'Fan': E_ERROR,
2861+ 'Lamp': E_ERROR,
2862+ 'Temperature': E_ERROR,
2863+ 'Cover': E_ERROR,
2864+ 'Filter': E_ERROR,
2865+ 'Other': E_ERROR}
2866+
2867 # GIVEN: Test object
2868- pjlink = pjlink_test
2869- chk_test = PJLINK_ERST_STATUS[E_ERROR]
2870- chk_string = ERROR_STRING[E_ERROR]
2871- chk_param = chk_test * len(PJLINK_ERST_POSITIONS)
2872+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
2873+ pjlink.projector_errors = None
2874
2875 # WHEN: process_erst with status set to WARN
2876- pjlink.process_erst(chk_param)
2877+ pjlink.process_erst(chk_data)
2878
2879 # THEN: PJLink instance errors should match chk_value
2880- for chk in pjlink.projector_errors:
2881- self.assertEqual(pjlink.projector_errors[chk], chk_string,
2882- 'projector_errors["{chk}"] should have been set to "{err}"'.format(chk=chk,
2883- err=chk_string))
2884+ self.assertEqual(pjlink.projector_errors, chk_test, 'Projector errors should be all E_ERROR')
2885
2886 def test_projector_process_erst_warn_cover_only(self):
2887 """
2888 Test test_projector_process_erst_warn_cover_only
2889 """
2890+ chk_data = '{fan}{lamp}{temp}{cover}{filt}{other}'.format(fan=PJLINK_ERST_STATUS[S_OK],
2891+ lamp=PJLINK_ERST_STATUS[S_OK],
2892+ temp=PJLINK_ERST_STATUS[S_OK],
2893+ cover=PJLINK_ERST_STATUS[E_WARN],
2894+ filt=PJLINK_ERST_STATUS[S_OK],
2895+ other=PJLINK_ERST_STATUS[S_OK])
2896+ chk_test = {'Cover': E_WARN}
2897+
2898 # GIVEN: Test object
2899- pjlink = pjlink_test
2900- chk_test = PJLINK_ERST_STATUS[E_WARN]
2901- chk_string = ERROR_STRING[E_WARN]
2902- pos = PJLINK_ERST_DATA['COVER']
2903- build_chk = []
2904- for check in range(0, len(PJLINK_ERST_POSITIONS)):
2905- if check == pos:
2906- build_chk.append(chk_test)
2907- else:
2908- build_chk.append(PJLINK_ERST_STATUS['OK'])
2909- chk_param = ''.join(build_chk)
2910-
2911- # WHEN: process_erst with cover only set to WARN and all others set to OK
2912- pjlink.process_erst(chk_param)
2913-
2914- # THEN: Only COVER should have an error
2915- self.assertEqual(len(pjlink.projector_errors), 1, 'projector_errors should only have 1 error')
2916- self.assertTrue(('Cover' in pjlink.projector_errors), 'projector_errors should have an error for "Cover"')
2917- self.assertEqual(pjlink.projector_errors['Cover'],
2918- chk_string,
2919- 'projector_errors["Cover"] should have error "{err}"'.format(err=chk_string))
2920-
2921- def test_projector_process_inpt(self):
2922+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
2923+ pjlink.projector_errors = None
2924+
2925+ # WHEN: process_erst with status set to WARN
2926+ pjlink.process_erst(chk_data)
2927+
2928+ # THEN: PJLink instance errors should match only cover warning
2929+ assert 1 == len(pjlink.projector_errors), 'There should only be 1 error listed in projector_errors'
2930+ assert 'Cover' in pjlink.projector_errors, '"Cover" should be the only error listed'
2931+ assert pjlink.projector_errors['Cover'] == E_WARN, '"Cover" should have E_WARN listed as error'
2932+ assert chk_test == pjlink.projector_errors, 'projector_errors should match test errors'
2933+
2934+ def test_projector_process_inpt_valid(self):
2935 """
2936 Test input source status shows current input
2937 """
2938+ log_debug_calls = [call('(111.111.111.111) reset_information() connect status is S_NOT_CONNECTED')]
2939+ chk_source_available = ['11', '12', '21', '22', '31', '32']
2940+
2941 # GIVEN: Test object
2942- pjlink = pjlink_test
2943- pjlink.source = '0'
2944-
2945- # WHEN: Called with input source
2946- pjlink.process_inpt('1')
2947-
2948- # THEN: Input selected should reflect current input
2949- self.assertEqual(pjlink.source, '1', 'Input source should be set to "1"')
2950-
2951- @patch.object(pjlink_test, 'projectorUpdateIcons')
2952- @patch.object(openlp.core.projectors.pjlink, 'log')
2953- def test_projector_process_inst(self, mock_log, mock_UpdateIcons):
2954+ with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
2955+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
2956+ pjlink.source_available = chk_source_available
2957+ pjlink.source = '11'
2958+
2959+ # WHEN: Called with input source
2960+ pjlink.process_inpt('21')
2961+
2962+ # THEN: Input selected should reflect current input
2963+ assert pjlink.source == '21', 'Input source should be set to "21"'
2964+ mock_log.debug.assert_has_calls(log_debug_calls)
2965+
2966+ def test_projector_process_input_not_in_list(self):
2967+ """
2968+ Test setting input outside of available inputs
2969+
2970+ TODO: Future test
2971+ """
2972+ pass
2973+
2974+ def test_projector_process_input_not_in_default(self):
2975+ """
2976+ Test setting input with no sources available
2977+ TODO: Future test
2978+ """
2979+ pass
2980+
2981+ def test_projector_process_input_invalid(self):
2982+ """
2983+ Test setting input with an invalid value
2984+
2985+ TODO: Future test
2986+ """
2987+
2988+ def test_projector_process_inst_class_1(self):
2989 """
2990 Test saving video source available information
2991 """
2992+ log_debug_calls = [call('(111.111.111.111) Setting projector sources_available to '
2993+ '"[\'11\', \'12\', \'21\', \'22\', \'31\', \'32\']"')]
2994+ chk_data = '21 12 11 22 32 31' # Although they should already be sorted, use unsorted to verify method
2995+ chk_test = ['11', '12', '21', '22', '31', '32']
2996+
2997 # GIVEN: Test object
2998- pjlink = pjlink_test
2999- pjlink.source_available = []
3000- test_data = '21 10 30 31 11 20'
3001- test_saved = ["10", "11", "20", "21", "30", "31"]
3002- log_data = "(127.0.0.1) Setting projector sources_available to " \
3003- "\"['10', '11', '20', '21', '30', '31']\""
3004- mock_UpdateIcons.reset_mock()
3005- mock_log.reset_mock()
3006-
3007- # WHEN: process_inst called with test data
3008- pjlink.process_inst(data=test_data)
3009-
3010- # THEN: Data should have been sorted and saved properly
3011- self.assertEqual(pjlink.source_available, test_saved, "Sources should have been sorted and saved")
3012- mock_log.debug.assert_called_once_with(log_data)
3013- self.assertTrue(mock_UpdateIcons.emit.called, 'Update Icons should have been called')
3014-
3015- @patch.object(openlp.core.projectors.pjlink, 'log')
3016- def test_projector_process_lamp_invalid(self, mock_log):
3017+ with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
3018+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
3019+ pjlink.source_available = []
3020+
3021+ # WHEN: process_inst called with test data
3022+ pjlink.process_inst(data=chk_data)
3023+
3024+ # THEN: Data should have been sorted and saved properly
3025+ assert pjlink.source_available == chk_test, "Sources should have been sorted and saved"
3026+ mock_log.debug.assert_has_calls(log_debug_calls)
3027+
3028+ def test_projector_process_lamp_invalid(self):
3029 """
3030 Test status multiple lamp on/off and hours
3031 """
3032+ log_data = [call('(111.111.111.111) process_lamp(): Invalid data "11111 1 22222 0 333A3 1"')]
3033+
3034 # GIVEN: Test object
3035- pjlink = pjlink_test
3036- pjlink.lamp = [{'Hours': 00000, 'On': True},
3037- {'Hours': 11111, 'On': False}]
3038- log_data = '(127.0.0.1) process_lamp(): Invalid data "11111 1 22222 0 333A3 1"'
3039-
3040- # WHEN: Call process_command with invalid lamp data
3041- pjlink.process_lamp('11111 1 22222 0 333A3 1')
3042-
3043- # THEN: lamps should not have changed
3044- self.assertEqual(len(pjlink.lamp), 2,
3045- 'Projector should have kept 2 lamps specified')
3046- self.assertEqual(pjlink.lamp[0]['On'], True,
3047- 'Lamp 1 power status should have been set to TRUE')
3048- self.assertEqual(pjlink.lamp[0]['Hours'], 00000,
3049- 'Lamp 1 hours should have been left at 00000')
3050- self.assertEqual(pjlink.lamp[1]['On'], False,
3051- 'Lamp 2 power status should have been set to FALSE')
3052- self.assertEqual(pjlink.lamp[1]['Hours'], 11111,
3053- 'Lamp 2 hours should have been left at 11111')
3054- mock_log.warning.assert_called_once_with(log_data)
3055+ with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
3056+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
3057+ pjlink.lamp = [{'Hours': 00000, 'On': True},
3058+ {'Hours': 11111, 'On': False}]
3059+
3060+ # WHEN: Call process_command with invalid lamp data
3061+ pjlink.process_lamp('11111 1 22222 0 333A3 1')
3062+
3063+ # THEN: lamps should not have changed
3064+ assert 2 == len(pjlink.lamp), 'Projector should have kept 2 lamps specified'
3065+ assert pjlink.lamp[0]['On'] is True, 'Lamp 1 power status should have stayed TRUE'
3066+ assert 00000 == pjlink.lamp[0]['Hours'], 'Lamp 1 hours should have been left at 00000'
3067+ assert pjlink.lamp[1]['On'] is False, 'Lamp 2 power status should have stayed FALSE'
3068+ assert 11111 == pjlink.lamp[1]['Hours'], 'Lamp 2 hours should have been left at 11111'
3069+ mock_log.warning.assert_has_calls(log_data)
3070
3071 def test_projector_process_lamp_multiple(self):
3072 """
3073 Test status multiple lamp on/off and hours
3074 """
3075 # GIVEN: Test object
3076- pjlink = pjlink_test
3077- pjlink.lamps = []
3078+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
3079+ pjlink.lamp = []
3080
3081- # WHEN: Call process_command with lamp data
3082+ # WHEN: Call process_command with invalid lamp data
3083 pjlink.process_lamp('11111 1 22222 0 33333 1')
3084
3085 # THEN: Lamp should have been set with proper lamp status
3086- self.assertEqual(len(pjlink.lamp), 3,
3087- 'Projector should have 3 lamps specified')
3088- self.assertEqual(pjlink.lamp[0]['On'], True,
3089- 'Lamp 1 power status should have been set to TRUE')
3090- self.assertEqual(pjlink.lamp[0]['Hours'], 11111,
3091- 'Lamp 1 hours should have been set to 11111')
3092- self.assertEqual(pjlink.lamp[1]['On'], False,
3093- 'Lamp 2 power status should have been set to FALSE')
3094- self.assertEqual(pjlink.lamp[1]['Hours'], 22222,
3095- 'Lamp 2 hours should have been set to 22222')
3096- self.assertEqual(pjlink.lamp[2]['On'], True,
3097- 'Lamp 3 power status should have been set to TRUE')
3098- self.assertEqual(pjlink.lamp[2]['Hours'], 33333,
3099- 'Lamp 3 hours should have been set to 33333')
3100+ assert 3 == len(pjlink.lamp), 'Projector should have 3 lamps specified'
3101+ assert pjlink.lamp[0]['On'] is True, 'Lamp 1 power status should have been set to TRUE'
3102+ assert 11111 == pjlink.lamp[0]['Hours'], 'Lamp 1 hours should have been set to 11111'
3103+ assert pjlink.lamp[1]['On'] is False, 'Lamp 2 power status should have been set to FALSE'
3104+ assert 22222 == pjlink.lamp[1]['Hours'], 'Lamp 2 hours should have been set to 22222'
3105+ assert pjlink.lamp[2]['On'] is True, 'Lamp 3 power status should have been set to TRUE'
3106+ assert 33333 == pjlink.lamp[2]['Hours'], 'Lamp 3 hours should have been set to 33333'
3107
3108 def test_projector_process_lamp_single(self):
3109 """
3110 Test status lamp on/off and hours
3111 """
3112+
3113 # GIVEN: Test object
3114- pjlink = pjlink_test
3115- pjlink.lamps = []
3116+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
3117+ pjlink.lamp = []
3118
3119- # WHEN: Call process_command with lamp data
3120+ # WHEN: Call process_command with invalid lamp data
3121 pjlink.process_lamp('22222 1')
3122
3123 # THEN: Lamp should have been set with status=ON and hours=22222
3124- self.assertEqual(pjlink.lamp[0]['On'], True,
3125- 'Lamp power status should have been set to TRUE')
3126- self.assertEqual(pjlink.lamp[0]['Hours'], 22222,
3127- 'Lamp hours should have been set to 22222')
3128+ assert 1 == len(pjlink.lamp), 'Projector should have only 1 lamp'
3129+ assert pjlink.lamp[0]['On'] is True, 'Lamp power status should have been set to TRUE'
3130+ assert 22222 == pjlink.lamp[0]['Hours'], 'Lamp hours should have been set to 22222'
3131
3132- @patch.object(openlp.core.projectors.pjlink, 'log')
3133- def test_projector_process_name(self, mock_log):
3134+ def test_projector_process_name(self):
3135 """
3136 Test saving NAME data from projector
3137 """
3138- # GIVEN: Test data
3139- pjlink = pjlink_test
3140- test_data = "Some Name the End-User Set IN Projector"
3141- test_log = '(127.0.0.1) Setting projector PJLink name to "Some Name the End-User Set IN Projector"'
3142- mock_log.reset_mock()
3143-
3144- # WHEN: process_name called with test data
3145- pjlink.process_name(data=test_data)
3146-
3147- # THEN: name should be set and logged
3148- self.assertEqual(pjlink.pjlink_name, test_data, 'Name test data should have been saved')
3149- mock_log.debug.assert_called_once_with(test_log)
3150-
3151- @patch.object(pjlink_test, 'projectorUpdateIcons')
3152- @patch.object(pjlink_test, 'send_command')
3153- @patch.object(pjlink_test, 'change_status')
3154- def test_projector_process_powr_on(self,
3155- mock_change_status,
3156- mock_send_command,
3157- mock_UpdateIcons):
3158+ chk_data = "Some Name the End-User Set IN Projector"
3159+ log_debug_calls = [call('(111.111.111.111) Setting projector PJLink name to '
3160+ '"Some Name the End-User Set IN Projector"')]
3161+
3162+ # GIVEN: Test object
3163+ with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
3164+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
3165+
3166+ # WHEN: process_name called with test data
3167+ pjlink.process_name(data=chk_data)
3168+
3169+ # THEN: name should be set and logged
3170+ assert pjlink.pjlink_name == chk_data, 'Name test data should have been saved'
3171+ mock_log.debug.assert_has_calls(log_debug_calls)
3172+
3173+ def test_projector_process_powr_on(self):
3174 """
3175 Test status power to ON
3176 """
3177- # GIVEN: Test object and preset
3178- pjlink = pjlink_test
3179- pjlink.power = S_STANDBY
3180- test_data = PJLINK_POWR_STATUS[S_ON]
3181-
3182- # WHEN: Call process_command with turn power on command
3183- pjlink.process_command(cmd='POWR', data=test_data)
3184-
3185- # THEN: Power should be set to ON
3186- self.assertEqual(pjlink.power, S_ON, 'Power should have been set to ON')
3187- mock_send_command.assert_called_once_with('INST')
3188- mock_change_status.assert_called_once_with(PJLINK_POWR_STATUS[test_data])
3189- self.assertEqual(mock_UpdateIcons.emit.called, True, 'projectorUpdateIcons should have been called')
3190-
3191- @patch.object(pjlink_test, 'projectorUpdateIcons')
3192- @patch.object(pjlink_test, 'send_command')
3193- @patch.object(pjlink_test, 'change_status')
3194- def test_projector_process_powr_invalid(self,
3195- mock_change_status,
3196- mock_send_command,
3197- mock_UpdateIcons):
3198+ # GIVEN: Test object
3199+ with patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command, \
3200+ patch.object(openlp.core.projectors.pjlink.PJLink, 'change_status') as mock_change_status, \
3201+ patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons:
3202+
3203+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
3204+ pjlink.power = S_STANDBY
3205+
3206+ # WHEN: process_name called with test data
3207+ pjlink.process_powr(data=PJLINK_POWR_STATUS[S_ON])
3208+
3209+ # THEN: Power should be set to ON
3210+ assert pjlink.power == S_ON, 'Power should have been set to ON'
3211+ assert mock_UpdateIcons.emit.called is True, 'projectorUpdateIcons should have been called'
3212+ mock_send_command.assert_called_once_with('INST')
3213+ mock_change_status.assert_called_once_with(S_ON)
3214+
3215+ def test_projector_process_powr_invalid(self):
3216 """
3217 Test process_powr invalid call
3218 """
3219- # GIVEN: Test object and preset
3220- pjlink = pjlink_test
3221- pjlink.power = S_STANDBY
3222- test_data = '99'
3223-
3224- # WHEN: Call process_command with turn power on command
3225- pjlink.process_command(cmd='POWR', data=test_data)
3226-
3227- # THEN: Power should be set to ON
3228- self.assertEqual(pjlink.power, S_STANDBY, 'Power should not have changed')
3229- self.assertFalse(mock_change_status.called, 'Change status should not have been called')
3230- self.assertFalse(mock_send_command.called, 'send_command("INST") should not have been called')
3231- self.assertFalse(mock_UpdateIcons.emit.called, 'projectorUpdateIcons should not have been called')
3232-
3233- @patch.object(pjlink_test, 'projectorUpdateIcons')
3234- @patch.object(pjlink_test, 'send_command')
3235- @patch.object(pjlink_test, 'change_status')
3236- def test_projector_process_powr_off(self,
3237- mock_change_status,
3238- mock_send_command,
3239- mock_UpdateIcons):
3240+ log_warn_calls = [call('(111.111.111.111) Unknown power response: "99"')]
3241+
3242+ # GIVEN: Test object
3243+ with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
3244+ patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command, \
3245+ patch.object(openlp.core.projectors.pjlink.PJLink, 'change_status') as mock_change_status, \
3246+ patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons:
3247+
3248+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
3249+ pjlink.power = S_STANDBY
3250+
3251+ # WHEN: process_name called with test data
3252+ pjlink.process_powr(data='99')
3253+
3254+ # THEN: Power should be set to ON
3255+ assert pjlink.power == S_STANDBY, 'Power should not have changed'
3256+ assert mock_UpdateIcons.emit.called is False, 'projectorUpdateIcons() should not have been called'
3257+ mock_change_status.called is False, 'change_status() should not have been called'
3258+ mock_send_command.called is False, 'send_command() should not have been called'
3259+ mock_log.warning.assert_has_calls(log_warn_calls)
3260+
3261+ def test_projector_process_powr_off(self):
3262 """
3263 Test status power to STANDBY
3264 """
3265- # GIVEN: Test object and preset
3266- pjlink = pjlink_test
3267- pjlink.power = S_ON
3268- test_data = PJLINK_POWR_STATUS[S_STANDBY]
3269-
3270- # WHEN: Call process_command with turn power on command
3271- pjlink.process_command(cmd='POWR', data=test_data)
3272-
3273- # THEN: Power should be set to STANDBY
3274- self.assertEqual(pjlink.power, S_STANDBY, 'Power should have been set to STANDBY')
3275- self.assertEqual(mock_UpdateIcons.emit.called, True, 'projectorUpdateIcons should have been called')
3276- mock_change_status.assert_called_once_with(PJLINK_POWR_STATUS[test_data])
3277- self.assertFalse(mock_send_command.called, "send_command['INST'] should not have been called")
3278+ # GIVEN: Test object
3279+ with patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command, \
3280+ patch.object(openlp.core.projectors.pjlink.PJLink, 'change_status') as mock_change_status, \
3281+ patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons:
3282+
3283+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
3284+ pjlink.power = S_ON
3285+
3286+ # WHEN: process_name called with test data
3287+ pjlink.process_powr(data=PJLINK_POWR_STATUS[S_STANDBY])
3288+
3289+ # THEN: Power should be set to ON
3290+ assert pjlink.power == S_STANDBY, 'Power should have changed to S_STANDBY'
3291+ assert mock_UpdateIcons.emit.called is True, 'projectorUpdateIcons should have been called'
3292+ mock_change_status.called is True, 'change_status should have been called'
3293+ mock_send_command.called is False, 'send_command should not have been called'
3294
3295 def test_projector_process_rfil_save(self):
3296 """
3297 Test saving filter type
3298 """
3299+ filter_model = 'Filter Type Test'
3300+
3301 # GIVEN: Test object
3302- pjlink = pjlink_test
3303+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
3304 pjlink.model_filter = None
3305- filter_model = 'Filter Type Test'
3306
3307 # WHEN: Filter model is received
3308 pjlink.process_rfil(data=filter_model)
3309
3310 # THEN: Filter model number should be saved
3311- self.assertEqual(pjlink.model_filter, filter_model, 'Filter type should have been saved')
3312+ assert pjlink.model_filter == filter_model, 'Filter type should have been saved'
3313
3314 def test_projector_process_rfil_nosave(self):
3315 """
3316 Test saving filter type previously saved
3317 """
3318+ filter_model = 'Filter Type Test'
3319+ log_warn_calls = [call('(111.111.111.111) Filter model already set'),
3320+ call('(111.111.111.111) Saved model: "Old filter type"'),
3321+ call('(111.111.111.111) New model: "Filter Type Test"')]
3322+
3323 # GIVEN: Test object
3324- pjlink = pjlink_test
3325- pjlink.model_filter = 'Old filter type'
3326- filter_model = 'Filter Type Test'
3327-
3328- # WHEN: Filter model is received
3329- pjlink.process_rfil(data=filter_model)
3330-
3331- # THEN: Filter model number should be saved
3332- self.assertNotEquals(pjlink.model_filter, filter_model, 'Filter type should NOT have been saved')
3333+ with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
3334+
3335+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
3336+ pjlink.model_filter = 'Old filter type'
3337+
3338+ # WHEN: Filter model is received
3339+ pjlink.process_rfil(data=filter_model)
3340+
3341+ # THEN: Filter model number should be saved
3342+ assert pjlink.model_filter != filter_model, 'Filter type should NOT have been saved'
3343+ mock_log.warning.assert_has_calls(log_warn_calls)
3344
3345 def test_projector_process_rlmp_save(self):
3346 """
3347 Test saving lamp type
3348 """
3349 # GIVEN: Test object
3350- pjlink = pjlink_test
3351+ # GIVEN: Test object
3352+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
3353 pjlink.model_lamp = None
3354 lamp_model = 'Lamp Type Test'
3355
3356@@ -968,153 +1048,173 @@
3357 """
3358 Test saving lamp type previously saved
3359 """
3360+ lamp_model = 'Lamp Type Test'
3361+ log_warn_calls = [call('(111.111.111.111) Lamp model already set'),
3362+ call('(111.111.111.111) Saved lamp: "Old lamp type"'),
3363+ call('(111.111.111.111) New lamp: "Lamp Type Test"')]
3364+
3365 # GIVEN: Test object
3366- pjlink = pjlink_test
3367- pjlink.model_lamp = 'Old lamp type'
3368- lamp_model = 'Filter Type Test'
3369-
3370- # WHEN: Filter model is received
3371- pjlink.process_rlmp(data=lamp_model)
3372-
3373- # THEN: Filter model number should be saved
3374- self.assertNotEquals(pjlink.model_lamp, lamp_model, 'Lamp type should NOT have been saved')
3375+ with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
3376+
3377+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
3378+ pjlink.model_lamp = 'Old lamp type'
3379+
3380+ # WHEN: Filter model is received
3381+ pjlink.process_rlmp(data=lamp_model)
3382+
3383+ # THEN: Filter model number should be saved
3384+ assert pjlink.model_lamp != lamp_model, 'Lamp type should NOT have been saved'
3385+ mock_log.warning.assert_has_calls(log_warn_calls)
3386
3387 def test_projector_process_snum_set(self):
3388 """
3389 Test saving serial number from projector
3390 """
3391+ log_debug_calls = [call('(111.111.111.111) Setting projector serial number to "Test Serial Number"')]
3392+ test_number = 'Test Serial Number'
3393+
3394 # GIVEN: Test object
3395- pjlink = pjlink_test
3396- pjlink.serial_no = None
3397- test_number = 'Test Serial Number'
3398-
3399- # WHEN: No serial number is set and we receive serial number command
3400- pjlink.process_snum(data=test_number)
3401-
3402- # THEN: Serial number should be set
3403- self.assertEqual(pjlink.serial_no, test_number,
3404- 'Projector serial number should have been set')
3405+ with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
3406+
3407+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
3408+ pjlink.serial_no = None
3409+
3410+ # WHEN: No serial number is set and we receive serial number command
3411+ pjlink.process_snum(data=test_number)
3412+
3413+ # THEN: Serial number should be set
3414+ assert pjlink.serial_no == test_number, 'Projector serial number should have been set'
3415+ mock_log.debug.assert_has_calls(log_debug_calls)
3416
3417 def test_projector_process_snum_different(self):
3418 """
3419 Test projector serial number different than saved serial number
3420 """
3421- # GIVEN: Test object
3422- pjlink = pjlink_test
3423- pjlink.serial_no = 'Previous serial number'
3424+ log_warn_calls = [call('(111.111.111.111) Projector serial number does not match saved serial number'),
3425+ call('(111.111.111.111) Saved: "Previous serial number"'),
3426+ call('(111.111.111.111) Received: "Test Serial Number"'),
3427+ call('(111.111.111.111) NOT saving serial number')]
3428 test_number = 'Test Serial Number'
3429
3430- # WHEN: No serial number is set and we receive serial number command
3431- pjlink.process_snum(data=test_number)
3432-
3433- # THEN: Serial number should be set
3434- self.assertNotEquals(pjlink.serial_no, test_number,
3435- 'Projector serial number should NOT have been set')
3436-
3437- @patch.object(openlp.core.projectors.pjlink, 'log')
3438- def test_projector_process_sver(self, mock_log):
3439+ # GIVEN: Test object
3440+ with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
3441+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
3442+ pjlink.serial_no = 'Previous serial number'
3443+
3444+ # WHEN: No serial number is set and we receive serial number command
3445+ pjlink.process_snum(data=test_number)
3446+
3447+ # THEN: Serial number should be set
3448+ assert pjlink.serial_no != test_number, 'Projector serial number should NOT have been set'
3449+ mock_log.warning.assert_has_calls(log_warn_calls)
3450+
3451+ def test_projector_process_sver(self):
3452 """
3453 Test invalid software version information - too long
3454 """
3455- # GIVEN: Test object
3456- pjlink = pjlink_test
3457- pjlink.sw_version = None
3458- pjlink.sw_version_received = None
3459 test_data = 'Test 1 Subtest 1'
3460- test_log = '(127.0.0.1) Setting projector software version to "Test 1 Subtest 1"'
3461- mock_log.reset_mock()
3462-
3463- # WHEN: process_sver called with invalid data
3464- pjlink.process_sver(data=test_data)
3465-
3466- # THEN: Version information should not change
3467- self.assertEqual(pjlink.sw_version, test_data, 'Software version should have been updated')
3468- self.assertIsNone(pjlink.sw_version_received, 'Received software version should not have changed')
3469- mock_log.debug.assert_called_once_with(test_log)
3470-
3471- @patch.object(openlp.core.projectors.pjlink, 'log')
3472- def test_projector_process_sver_changed(self, mock_log):
3473+ log_debug_calls = [call('(111.111.111.111) Setting projector software version to "Test 1 Subtest 1"')]
3474+
3475+ # GIVEN: Test object
3476+ with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
3477+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
3478+ pjlink.sw_version = None
3479+ pjlink.sw_version_received = None
3480+
3481+ # WHEN: process_sver called with invalid data
3482+ pjlink.process_sver(data=test_data)
3483+
3484+ # THEN: Version information should not change
3485+ assert pjlink.sw_version == test_data, 'Software version should have been updated'
3486+ mock_log.debug.assert_has_calls(log_debug_calls)
3487+
3488+ def test_projector_process_sver_changed(self):
3489 """
3490 Test invalid software version information - Received different than saved
3491 """
3492- # GIVEN: Test object
3493- pjlink = pjlink_test
3494+ test_data_old = 'Test 1 Subtest 1'
3495 test_data_new = 'Test 1 Subtest 2'
3496- test_data_old = 'Test 1 Subtest 1'
3497- pjlink.sw_version = test_data_old
3498- pjlink.sw_version_received = None
3499- test_log = '(127.0.0.1) Saving new serial number as sw_version_received'
3500- mock_log.reset_mock()
3501-
3502- # WHEN: process_sver called with invalid data
3503- pjlink.process_sver(data=test_data_new)
3504-
3505- # THEN: Version information should not change
3506- self.assertEqual(pjlink.sw_version, test_data_old, 'Software version should not have been updated')
3507- self.assertEqual(pjlink.sw_version_received, test_data_new,
3508- 'Received software version should have been changed')
3509- self.assertEqual(mock_log.warning.call_count, 4, 'log.warn should have been called 4 times')
3510- # There was 4 calls, but only the last one is checked with this method
3511- mock_log.warning.assert_called_with(test_log)
3512-
3513- @patch.object(openlp.core.projectors.pjlink, 'log')
3514- def test_projector_process_sver_invalid(self, mock_log):
3515+ log_warn_calls = [call('(111.111.111.111) Projector software version does not match saved software version'),
3516+ call('(111.111.111.111) Saved: "Test 1 Subtest 1"'),
3517+ call('(111.111.111.111) Received: "Test 1 Subtest 2"'),
3518+ call('(111.111.111.111) Updating software version')]
3519+
3520+ # GIVEN: Test object
3521+ with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
3522+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
3523+ pjlink.sw_version = test_data_old
3524+
3525+ # WHEN: process_sver called with invalid data
3526+ pjlink.process_sver(data=test_data_new)
3527+
3528+ # THEN: Version information should not change
3529+ assert pjlink.sw_version == test_data_new, 'Software version should have changed'
3530+ mock_log.warning.assert_has_calls(log_warn_calls)
3531+
3532+ def test_projector_process_sver_invalid(self):
3533 """
3534 Test invalid software version information - too long
3535 """
3536- # GIVEN: Test object
3537- pjlink = pjlink_test
3538- pjlink.sw_version = None
3539- pjlink.sw_version_received = None
3540 test_data = 'This is a test software version line that is too long based on PJLink version 2 specs'
3541- test_log = "Invalid software version - too long"
3542- mock_log.reset_mock()
3543-
3544- # WHEN: process_sver called with invalid data
3545- pjlink.process_sver(data=test_data)
3546-
3547- # THEN: Version information should not change
3548- self.assertIsNone(pjlink.sw_version, 'Software version should not have changed')
3549- self.assertIsNone(pjlink.sw_version_received, 'Received software version should not have changed')
3550- mock_log.warning.assert_called_once_with(test_log)
3551+ log_warn_calls = [call('Invalid software version - too long')]
3552+
3553+ # GIVEN: Test object
3554+ with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
3555+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
3556+ pjlink.sw_version = None
3557+
3558+ # WHEN: process_sver called with invalid data
3559+ pjlink.process_sver(data=test_data)
3560+
3561+ # THEN: Version information should not change
3562+ assert pjlink.sw_version is None, 'Software version should not have changed'
3563+ assert pjlink.sw_version_received is None, 'Received software version should not have changed'
3564+ mock_log.warning.assert_has_calls(log_warn_calls)
3565
3566 def test_projector_reset_information(self):
3567 """
3568 Test reset_information() resets all information and stops timers
3569 """
3570- # GIVEN: Test object and test data
3571- pjlink = pjlink_test
3572- pjlink.power = S_ON
3573- pjlink.pjlink_name = 'OPENLPTEST'
3574- pjlink.manufacturer = 'PJLINK'
3575- pjlink.model = '1'
3576- pjlink.shutter = True
3577- pjlink.mute = True
3578- pjlink.lamp = True
3579- pjlink.fan = True
3580- pjlink.source_available = True
3581- pjlink.other_info = 'ANOTHER TEST'
3582- pjlink.send_queue = True
3583- pjlink.send_busy = True
3584-
3585- # WHEN: reset_information() is called
3586- with patch.object(pjlink, 'timer') as mock_timer:
3587- with patch.object(pjlink, 'socket_timer') as mock_socket_timer:
3588+ log_debug_calls = [call('(111.111.111.111): Calling timer.stop()'),
3589+ call('(111.111.111.111): Calling socket_timer.stop()')]
3590+
3591+ # GIVEN: Test object
3592+ with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
3593+ pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
3594+ # timer and socket_timer not available until instantiation, so mock here
3595+ with patch.object(pjlink, 'socket_timer') as mock_socket_timer, \
3596+ patch.object(pjlink, 'timer') as mock_timer:
3597+
3598+ pjlink.power = S_ON
3599+ pjlink.pjlink_name = 'OPENLPTEST'
3600+ pjlink.manufacturer = 'PJLINK'
3601+ pjlink.model = '1'
3602+ pjlink.shutter = True
3603+ pjlink.mute = True
3604+ pjlink.lamp = True
3605+ pjlink.fan = True
3606+ pjlink.source_available = True
3607+ pjlink.other_info = 'ANOTHER TEST'
3608+ pjlink.send_queue = True
3609+ pjlink.send_busy = True
3610+
3611+ # WHEN: reset_information() is called
3612 pjlink.reset_information()
3613
3614- # THEN: All information should be reset and timers stopped
3615- self.assertEqual(pjlink.power, S_OFF, 'Projector power should be OFF')
3616- self.assertIsNone(pjlink.pjlink_name, 'Projector pjlink_name should be None')
3617- self.assertIsNone(pjlink.manufacturer, 'Projector manufacturer should be None')
3618- self.assertIsNone(pjlink.model, 'Projector model should be None')
3619- self.assertIsNone(pjlink.shutter, 'Projector shutter should be None')
3620- self.assertIsNone(pjlink.mute, 'Projector shuttter should be None')
3621- self.assertIsNone(pjlink.lamp, 'Projector lamp should be None')
3622- self.assertIsNone(pjlink.fan, 'Projector fan should be None')
3623- self.assertIsNone(pjlink.source_available, 'Projector source_available should be None')
3624- self.assertIsNone(pjlink.source, 'Projector source should be None')
3625- self.assertIsNone(pjlink.other_info, 'Projector other_info should be None')
3626- self.assertEqual(pjlink.send_queue, [], 'Projector send_queue should be an empty list')
3627- self.assertFalse(pjlink.send_busy, 'Projector send_busy should be False')
3628- self.assertTrue(mock_timer.stop.called, 'Projector timer.stop() should have been called')
3629- self.assertTrue(mock_socket_timer.stop.called, 'Projector socket_timer.stop() should have been called')
3630+ # THEN: All information should be reset and timers stopped
3631+ assert pjlink.power == S_OFF, 'Projector power should be OFF'
3632+ assert pjlink.pjlink_name is None, 'Projector pjlink_name should be None'
3633+ assert pjlink.manufacturer is None, 'Projector manufacturer should be None'
3634+ assert pjlink.model is None, 'Projector model should be None'
3635+ assert pjlink.shutter is None, 'Projector shutter should be None'
3636+ assert pjlink.mute is None, 'Projector shuttter should be None'
3637+ assert pjlink.lamp is None, 'Projector lamp should be None'
3638+ assert pjlink.fan is None, 'Projector fan should be None'
3639+ assert pjlink.source_available is None, 'Projector source_available should be None'
3640+ assert pjlink.source is None, 'Projector source should be None'
3641+ assert pjlink.other_info is None, 'Projector other_info should be None'
3642+ assert pjlink.send_queue == [], 'Projector send_queue should be an empty list'
3643+ assert pjlink.send_busy is False, 'Projector send_busy should be False'
3644+ assert mock_timer.stop.called is True, 'Projector timer.stop() should have been called'
3645+ assert mock_socket_timer.stop.called is True, 'Projector socket_timer.stop() should have been called'
3646+ mock_log.debug.assert_has_calls(log_debug_calls)