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
=== modified file 'openlp/core/projectors/constants.py'
--- openlp/core/projectors/constants.py 2017-12-09 11:17:05 +0000
+++ openlp/core/projectors/constants.py 2017-12-25 08:57:51 +0000
@@ -32,9 +32,128 @@
32# Set common constants.32# Set common constants.
33CR = chr(0x0D) # \r33CR = chr(0x0D) # \r
34LF = chr(0x0A) # \n34LF = chr(0x0A) # \n
35PJLINK_CLASS = '1' # Default to class 1 until we query the projector
36PJLINK_MAX_PACKET = 136
37PJLINK_PREFIX = '%'
35PJLINK_PORT = 435238PJLINK_PORT = 4352
36TIMEOUT = 30.039PJLINK_SUFFIX = CR
37PJLINK_MAX_PACKET = 13640PJLINK_TIMEOUT = 30.0
41
42# Error and status codes
43S_OK = E_OK = 0 # E_OK included since I sometimes forget
44
45# Error codes. Start at 200 so we don't duplicate system error codes.
46E_GENERAL = 200 # Unknown error
47E_NOT_CONNECTED = 201
48E_UNDEFINED = 202 # PJLink ERR1
49E_PARAMETER = 203 # PJLink ERR2
50E_UNAVAILABLE = 204 # PJLink ERR3
51E_PROJECTOR = 205 # PJLink ERR4
52E_AUTHENTICATION = 206 # PJLink ERRA
53E_NO_AUTHENTICATION = 207 # PJLink authentication mismatch between projector and program
54E_PREFIX = 208 # PJLink invalid prefix for packet
55E_CLASS = 209 # PJLink class version mismatch
56E_INVALID_DATA = 210
57E_WARN = 211
58E_ERROR = 212
59E_FAN = 213
60E_LAMP = 214
61E_TEMP = 215
62E_COVER = 216
63E_FILTER = 217
64E_UNKNOWN = 218
65
66# Remap Qt socket error codes to local error codes
67E_CONNECTION_REFUSED = 230
68E_REMOTE_HOST_CLOSED_CONNECTION = 231
69E_HOST_NOT_FOUND = 232
70E_SOCKET_ACCESS = 233
71E_SOCKET_RESOURCE = 234
72E_SOCKET_TIMEOUT = 235
73E_DATAGRAM_TOO_LARGE = 236
74E_NETWORK = 237
75E_ADDRESS_IN_USE = 238
76E_SOCKET_ADDRESS_NOT_AVAILABLE = 239
77E_UNSUPPORTED_SOCKET_OPERATION = 240
78E_PROXY_AUTHENTICATION_REQUIRED = 241
79E_SLS_HANDSHAKE_FAILED = 242
80E_UNFINISHED_SOCKET_OPERATION = 243
81E_PROXY_CONNECTION_REFUSED = 244
82E_PROXY_CONNECTION_CLOSED = 245
83E_PROXY_CONNECTION_TIMEOUT = 246
84E_PROXY_NOT_FOUND = 247
85E_PROXY_PROTOCOL = 248
86E_UNKNOWN_SOCKET_ERROR = 249
87
88# Status codes start at 300
89
90# Remap Qt socket states to local status codes
91S_NOT_CONNECTED = 300
92S_HOST_LOOKUP = 301
93S_CONNECTING = 302
94S_CONNECTED = 303
95S_BOUND = 304
96S_LISTENING = 305 # Listed as internal use only in QAbstractSocket
97S_CLOSING = 306
98
99# Projector states
100S_INITIALIZE = 310
101S_STATUS = 311
102S_OFF = 312
103S_STANDBY = 313
104S_WARMUP = 314
105S_ON = 315
106S_COOLDOWN = 316
107S_INFO = 317
108
109# Information that does not affect status
110S_NETWORK_IDLE = 400
111S_NETWORK_SENDING = 401
112S_NETWORK_RECEIVING = 402
113
114# Map PJlink errors to local status
115PJLINK_ERRORS = {
116 'ERRA': E_AUTHENTICATION, # Authentication error
117 'ERR1': E_UNDEFINED, # Undefined command error
118 'ERR2': E_PARAMETER, # Invalid parameter error
119 'ERR3': E_UNAVAILABLE, # Projector busy
120 'ERR4': E_PROJECTOR, # Projector or display failure
121 E_AUTHENTICATION: 'ERRA',
122 E_UNDEFINED: 'ERR1',
123 E_PARAMETER: 'ERR2',
124 E_UNAVAILABLE: 'ERR3',
125 E_PROJECTOR: 'ERR4'
126}
127
128# Map QAbstractSocketState enums to local status
129QSOCKET_STATE = {
130 0: S_NOT_CONNECTED, # 'UnconnectedState',
131 1: S_HOST_LOOKUP, # 'HostLookupState',
132 2: S_CONNECTING, # 'ConnectingState',
133 3: S_CONNECTED, # 'ConnectedState',
134 4: S_BOUND, # 'BoundState',
135 5: S_LISTENING, # 'ListeningState' - Noted as "Internal Use Only" on Qt website
136 6: S_CLOSING, # 'ClosingState',
137 S_NOT_CONNECTED: 0,
138 S_HOST_LOOKUP: 1,
139 S_CONNECTING: 2,
140 S_CONNECTED: 3,
141 S_BOUND: 4,
142 S_LISTENING: 5,
143 S_CLOSING: 6
144}
145
146PROJECTOR_STATE = [
147 S_INITIALIZE,
148 S_STATUS,
149 S_OFF,
150 S_STANDBY,
151 S_WARMUP,
152 S_ON,
153 S_COOLDOWN,
154 S_INFO
155]
156
38# NOTE: Changed format to account for some commands are both class 1 and 2157# NOTE: Changed format to account for some commands are both class 1 and 2
39PJLINK_VALID_CMD = {158PJLINK_VALID_CMD = {
40 'ACKN': {'version': ['2', ],159 'ACKN': {'version': ['2', ],
@@ -144,227 +263,140 @@
144 }263 }
145}264}
146265
147# QAbstractSocketState enums converted to string266CONNECTION_ERRORS = [
148S_QSOCKET_STATE = {267 E_ADDRESS_IN_USE,
149 0: 'QSocketState - UnconnectedState',268 E_CONNECTION_REFUSED,
150 1: 'QSocketState - HostLookupState',269 E_DATAGRAM_TOO_LARGE,
151 2: 'QSocketState - ConnectingState',270 E_HOST_NOT_FOUND,
152 3: 'QSocketState - ConnectedState',271 E_NETWORK,
153 4: 'QSocketState - BoundState',272 E_NOT_CONNECTED,
154 5: 'QSocketState - ListeningState (internal use only)',273 E_PROXY_AUTHENTICATION_REQUIRED,
155 6: 'QSocketState - ClosingState',274 E_PROXY_CONNECTION_CLOSED,
156 'UnconnectedState': 0,275 E_PROXY_CONNECTION_REFUSED,
157 'HostLookupState': 1,276 E_PROXY_CONNECTION_TIMEOUT,
158 'ConnectingState': 2,277 E_PROXY_NOT_FOUND,
159 'ConnectedState': 3,278 E_PROXY_PROTOCOL,
160 'BoundState': 4,279 E_REMOTE_HOST_CLOSED_CONNECTION,
161 'ListeningState': 5,280 E_SLS_HANDSHAKE_FAILED,
162 'ClosingState': 6281 E_SOCKET_ACCESS,
163}282 E_SOCKET_ADDRESS_NOT_AVAILABLE,
164283 E_SOCKET_RESOURCE,
165# Error and status codes284 E_SOCKET_TIMEOUT,
166S_OK = E_OK = 0 # E_OK included since I sometimes forget285 E_UNFINISHED_SOCKET_OPERATION,
167# Error codes. Start at 200 so we don't duplicate system error codes.286 E_UNKNOWN_SOCKET_ERROR,
168E_GENERAL = 200 # Unknown error287 E_UNSUPPORTED_SOCKET_OPERATION
169E_NOT_CONNECTED = 201288]
170E_FAN = 202289
171E_LAMP = 203290PROJECTOR_ERRORS = [
172E_TEMP = 204291 E_AUTHENTICATION,
173E_COVER = 205292 E_CLASS,
174E_FILTER = 206293 E_INVALID_DATA,
175E_NO_AUTHENTICATION = 207 # PIN set and no authentication set on projector294 E_NO_AUTHENTICATION,
176E_UNDEFINED = 208 # ERR1295 E_PARAMETER,
177E_PARAMETER = 209 # ERR2296 E_PREFIX,
178E_UNAVAILABLE = 210 # ERR3297 E_PROJECTOR,
179E_PROJECTOR = 211 # ERR4298 E_UNAVAILABLE,
180E_INVALID_DATA = 212299 E_UNDEFINED,
181E_WARN = 213300 E_UNKNOWN
182E_ERROR = 214301]
183E_AUTHENTICATION = 215 # ERRA302
184E_CLASS = 216303# Show status code as string
185E_PREFIX = 217304STATUS_CODE = {
186305 E_ADDRESS_IN_USE: 'E_ADDRESS_IN_USE',
187# Remap Qt socket error codes to projector error codes306 E_AUTHENTICATION: 'E_AUTHENTICATION',
188E_CONNECTION_REFUSED = 230307 E_CLASS: 'E_CLASS',
189E_REMOTE_HOST_CLOSED_CONNECTION = 231308 E_CONNECTION_REFUSED: 'E_CONNECTION_REFUSED',
190E_HOST_NOT_FOUND = 232309 E_COVER: 'E_COVER',
191E_SOCKET_ACCESS = 233310 E_DATAGRAM_TOO_LARGE: 'E_DATAGRAM_TOO_LARGE',
192E_SOCKET_RESOURCE = 234311 E_ERROR: 'E_ERROR',
193E_SOCKET_TIMEOUT = 235312 E_FAN: 'E_FAN',
194E_DATAGRAM_TOO_LARGE = 236313 E_FILTER: 'E_FILTER',
195E_NETWORK = 237
196E_ADDRESS_IN_USE = 238
197E_SOCKET_ADDRESS_NOT_AVAILABLE = 239
198E_UNSUPPORTED_SOCKET_OPERATION = 240
199E_PROXY_AUTHENTICATION_REQUIRED = 241
200E_SLS_HANDSHAKE_FAILED = 242
201E_UNFINISHED_SOCKET_OPERATION = 243
202E_PROXY_CONNECTION_REFUSED = 244
203E_PROXY_CONNECTION_CLOSED = 245
204E_PROXY_CONNECTION_TIMEOUT = 246
205E_PROXY_NOT_FOUND = 247
206E_PROXY_PROTOCOL = 248
207E_UNKNOWN_SOCKET_ERROR = -1
208
209# Status codes start at 300
210S_NOT_CONNECTED = 300
211S_CONNECTING = 301
212S_CONNECTED = 302
213S_INITIALIZE = 303
214S_STATUS = 304
215S_OFF = 305
216S_STANDBY = 306
217S_WARMUP = 307
218S_ON = 308
219S_COOLDOWN = 309
220S_INFO = 310
221
222# Information that does not affect status
223S_NETWORK_SENDING = 400
224S_NETWORK_RECEIVED = 401
225
226CONNECTION_ERRORS = {
227 E_NOT_CONNECTED, E_NO_AUTHENTICATION, E_AUTHENTICATION, E_CLASS,
228 E_PREFIX, E_CONNECTION_REFUSED, E_REMOTE_HOST_CLOSED_CONNECTION,
229 E_HOST_NOT_FOUND, E_SOCKET_ACCESS, E_SOCKET_RESOURCE, E_SOCKET_TIMEOUT,
230 E_DATAGRAM_TOO_LARGE, E_NETWORK, E_ADDRESS_IN_USE, E_SOCKET_ADDRESS_NOT_AVAILABLE,
231 E_UNSUPPORTED_SOCKET_OPERATION, E_PROXY_AUTHENTICATION_REQUIRED,
232 E_SLS_HANDSHAKE_FAILED, E_UNFINISHED_SOCKET_OPERATION, E_PROXY_CONNECTION_REFUSED,
233 E_PROXY_CONNECTION_CLOSED, E_PROXY_CONNECTION_TIMEOUT, E_PROXY_NOT_FOUND,
234 E_PROXY_PROTOCOL, E_UNKNOWN_SOCKET_ERROR
235}
236
237PJLINK_ERRORS = {
238 'ERRA': E_AUTHENTICATION, # Authentication error
239 'ERR1': E_UNDEFINED, # Undefined command error
240 'ERR2': E_PARAMETER, # Invalid parameter error
241 'ERR3': E_UNAVAILABLE, # Projector busy
242 'ERR4': E_PROJECTOR, # Projector or display failure
243 E_AUTHENTICATION: 'ERRA',
244 E_UNDEFINED: 'ERR1',
245 E_PARAMETER: 'ERR2',
246 E_UNAVAILABLE: 'ERR3',
247 E_PROJECTOR: 'ERR4'
248}
249
250# Map error/status codes to string
251ERROR_STRING = {
252 0: 'S_OK',
253 E_GENERAL: 'E_GENERAL',314 E_GENERAL: 'E_GENERAL',
254 E_NOT_CONNECTED: 'E_NOT_CONNECTED',315 E_HOST_NOT_FOUND: 'E_HOST_NOT_FOUND',
255 E_FAN: 'E_FAN',316 E_INVALID_DATA: 'E_INVALID_DATA',
256 E_LAMP: 'E_LAMP',317 E_LAMP: 'E_LAMP',
257 E_TEMP: 'E_TEMP',318 E_NETWORK: 'E_NETWORK',
258 E_COVER: 'E_COVER',
259 E_FILTER: 'E_FILTER',
260 E_AUTHENTICATION: 'E_AUTHENTICATION',
261 E_NO_AUTHENTICATION: 'E_NO_AUTHENTICATION',319 E_NO_AUTHENTICATION: 'E_NO_AUTHENTICATION',
262 E_UNDEFINED: 'E_UNDEFINED',320 E_NOT_CONNECTED: 'E_NOT_CONNECTED',
263 E_PARAMETER: 'E_PARAMETER',321 E_PARAMETER: 'E_PARAMETER',
264 E_UNAVAILABLE: 'E_UNAVAILABLE',322 E_PREFIX: 'E_PREFIX',
265 E_PROJECTOR: 'E_PROJECTOR',323 E_PROJECTOR: 'E_PROJECTOR',
266 E_INVALID_DATA: 'E_INVALID_DATA',324 E_PROXY_AUTHENTICATION_REQUIRED: 'E_PROXY_AUTHENTICATION_REQUIRED',
267 E_WARN: 'E_WARN',325 E_PROXY_CONNECTION_CLOSED: 'E_PROXY_CONNECTION_CLOSED',
268 E_ERROR: 'E_ERROR',326 E_PROXY_CONNECTION_REFUSED: 'E_PROXY_CONNECTION_REFUSED',
269 E_CLASS: 'E_CLASS',327 E_PROXY_CONNECTION_TIMEOUT: 'E_PROXY_CONNECTION_TIMEOUT',
270 E_PREFIX: 'E_PREFIX', # Last projector error328 E_PROXY_NOT_FOUND: 'E_PROXY_NOT_FOUND',
271 E_CONNECTION_REFUSED: 'E_CONNECTION_REFUSED', # First QtSocket error329 E_PROXY_PROTOCOL: 'E_PROXY_PROTOCOL',
272 E_REMOTE_HOST_CLOSED_CONNECTION: 'E_REMOTE_HOST_CLOSED_CONNECTION',330 E_REMOTE_HOST_CLOSED_CONNECTION: 'E_REMOTE_HOST_CLOSED_CONNECTION',
273 E_HOST_NOT_FOUND: 'E_HOST_NOT_FOUND',331 E_SLS_HANDSHAKE_FAILED: 'E_SLS_HANDSHAKE_FAILED',
274 E_SOCKET_ACCESS: 'E_SOCKET_ACCESS',332 E_SOCKET_ACCESS: 'E_SOCKET_ACCESS',
333 E_SOCKET_ADDRESS_NOT_AVAILABLE: 'E_SOCKET_ADDRESS_NOT_AVAILABLE',
275 E_SOCKET_RESOURCE: 'E_SOCKET_RESOURCE',334 E_SOCKET_RESOURCE: 'E_SOCKET_RESOURCE',
276 E_SOCKET_TIMEOUT: 'E_SOCKET_TIMEOUT',335 E_SOCKET_TIMEOUT: 'E_SOCKET_TIMEOUT',
277 E_DATAGRAM_TOO_LARGE: 'E_DATAGRAM_TOO_LARGE',336 E_TEMP: 'E_TEMP',
278 E_NETWORK: 'E_NETWORK',337 E_UNAVAILABLE: 'E_UNAVAILABLE',
279 E_ADDRESS_IN_USE: 'E_ADDRESS_IN_USE',338 E_UNDEFINED: 'E_UNDEFINED',
280 E_SOCKET_ADDRESS_NOT_AVAILABLE: 'E_SOCKET_ADDRESS_NOT_AVAILABLE',339 E_UNFINISHED_SOCKET_OPERATION: 'E_UNFINISHED_SOCKET_OPERATION',
340 E_UNKNOWN: 'E_UNKNOWN',
341 E_UNKNOWN_SOCKET_ERROR: 'E_UNKNOWN_SOCKET_ERROR',
281 E_UNSUPPORTED_SOCKET_OPERATION: 'E_UNSUPPORTED_SOCKET_OPERATION',342 E_UNSUPPORTED_SOCKET_OPERATION: 'E_UNSUPPORTED_SOCKET_OPERATION',
282 E_PROXY_AUTHENTICATION_REQUIRED: 'E_PROXY_AUTHENTICATION_REQUIRED',343 E_WARN: 'E_WARN',
283 E_SLS_HANDSHAKE_FAILED: 'E_SLS_HANDSHAKE_FAILED',344 S_BOUND: 'S_BOUND',
284 E_UNFINISHED_SOCKET_OPERATION: 'E_UNFINISHED_SOCKET_OPERATION',345 S_COOLDOWN: 'S_COOLDOWN',
285 E_PROXY_CONNECTION_REFUSED: 'E_PROXY_CONNECTION_REFUSED',346 S_CLOSING: 'S_CLOSING',
286 E_PROXY_CONNECTION_CLOSED: 'E_PROXY_CONNECTION_CLOSED',347 S_CONNECTED: 'S_CONNECTED',
287 E_PROXY_CONNECTION_TIMEOUT: 'E_PROXY_CONNECTION_TIMEOUT',348 S_CONNECTING: 'S_CONNECTING',
288 E_PROXY_NOT_FOUND: 'E_PROXY_NOT_FOUND',349 S_HOST_LOOKUP: 'S_HOST_LOOKUP',
289 E_PROXY_PROTOCOL: 'E_PROXY_PROTOCOL',350 S_INFO: 'S_INFO',
290 E_UNKNOWN_SOCKET_ERROR: 'E_UNKNOWN_SOCKET_ERROR'351 S_INITIALIZE: 'S_INITIALIZE',
291}352 S_LISTENING: 'S_LISTENING',
292353 S_NETWORK_RECEIVING: 'S_NETWORK_RECEIVING',
293STATUS_STRING = {354 S_NETWORK_SENDING: 'S_NETWORK_SENDING',
355 S_NETWORK_IDLE: 'S_NETWORK_IDLE',
294 S_NOT_CONNECTED: 'S_NOT_CONNECTED',356 S_NOT_CONNECTED: 'S_NOT_CONNECTED',
295 S_CONNECTING: 'S_CONNECTING',
296 S_CONNECTED: 'S_CONNECTED',
297 S_STATUS: 'S_STATUS',
298 S_OFF: 'S_OFF',357 S_OFF: 'S_OFF',
299 S_INITIALIZE: 'S_INITIALIZE',358 S_OK: 'S_OK', # S_OK or E_OK
359 S_ON: 'S_ON',
300 S_STANDBY: 'S_STANDBY',360 S_STANDBY: 'S_STANDBY',
361 S_STATUS: 'S_STATUS',
301 S_WARMUP: 'S_WARMUP',362 S_WARMUP: 'S_WARMUP',
302 S_ON: 'S_ON',
303 S_COOLDOWN: 'S_COOLDOWN',
304 S_INFO: 'S_INFO',
305 S_NETWORK_SENDING: 'S_NETWORK_SENDING',
306 S_NETWORK_RECEIVED: 'S_NETWORK_RECEIVED'
307}363}
308364
309# Map error/status codes to message strings365# Map status codes to message strings
310ERROR_MSG = {366STATUS_MSG = {
311 E_OK: translate('OpenLP.ProjectorConstants', 'OK'), # E_OK | S_OK367 E_ADDRESS_IN_USE: translate('OpenLP.ProjectorConstants',
312 E_GENERAL: translate('OpenLP.ProjectorConstants', 'General projector error'),368 'The address specified with socket.bind() '
313 E_NOT_CONNECTED: translate('OpenLP.ProjectorConstants', 'Not connected error'),369 'is already in use and was set to be exclusive'),
314 E_LAMP: translate('OpenLP.ProjectorConstants', 'Lamp error'),370 E_AUTHENTICATION: translate('OpenLP.ProjectorConstants', 'PJLink returned "ERRA: Authentication Error"'),
315 E_FAN: translate('OpenLP.ProjectorConstants', 'Fan error'),
316 E_TEMP: translate('OpenLP.ProjectorConstants', 'High temperature detected'),
317 E_COVER: translate('OpenLP.ProjectorConstants', 'Cover open detected'),
318 E_FILTER: translate('OpenLP.ProjectorConstants', 'Check filter'),
319 E_AUTHENTICATION: translate('OpenLP.ProjectorConstants', 'Authentication Error'),
320 E_UNDEFINED: translate('OpenLP.ProjectorConstants', 'Undefined Command'),
321 E_PARAMETER: translate('OpenLP.ProjectorConstants', 'Invalid Parameter'),
322 E_UNAVAILABLE: translate('OpenLP.ProjectorConstants', 'Projector Busy'),
323 E_PROJECTOR: translate('OpenLP.ProjectorConstants', 'Projector/Display Error'),
324 E_INVALID_DATA: translate('OpenLP.ProjectorConstants', 'Invalid packet received'),
325 E_WARN: translate('OpenLP.ProjectorConstants', 'Warning condition detected'),
326 E_ERROR: translate('OpenLP.ProjectorConstants', 'Error condition detected'),
327 E_CLASS: translate('OpenLP.ProjectorConstants', 'PJLink class not supported'),
328 E_PREFIX: translate('OpenLP.ProjectorConstants', 'Invalid prefix character'),
329 E_CONNECTION_REFUSED: translate('OpenLP.ProjectorConstants',371 E_CONNECTION_REFUSED: translate('OpenLP.ProjectorConstants',
330 'The connection was refused by the peer (or timed out)'),372 'The connection was refused by the peer (or timed out)'),
331 E_REMOTE_HOST_CLOSED_CONNECTION: translate('OpenLP.ProjectorConstants',373 E_COVER: translate('OpenLP.ProjectorConstants', 'Projector cover open detected'),
332 'The remote host closed the connection'),374 E_CLASS: translate('OpenLP.ProjectorConstants', 'PJLink class not supported'),
375 E_DATAGRAM_TOO_LARGE: translate('OpenLP.ProjectorConstants',
376 "The datagram was larger than the operating system's limit"),
377 E_ERROR: translate('OpenLP.ProjectorConstants', 'Error condition detected'),
378 E_FAN: translate('OpenLP.ProjectorConstants', 'Projector fan error'),
379 E_FILTER: translate('OpenLP.ProjectorConstants', 'Projector check filter'),
380 E_GENERAL: translate('OpenLP.ProjectorConstants', 'General projector error'),
333 E_HOST_NOT_FOUND: translate('OpenLP.ProjectorConstants', 'The host address was not found'),381 E_HOST_NOT_FOUND: translate('OpenLP.ProjectorConstants', 'The host address was not found'),
334 E_SOCKET_ACCESS: translate('OpenLP.ProjectorConstants',382 E_INVALID_DATA: translate('OpenLP.ProjectorConstants', 'PJLink invalid packet received'),
335 'The socket operation failed because the application '383 E_LAMP: translate('OpenLP.ProjectorConstants', 'Projector lamp error'),
336 'lacked the required privileges'),
337 E_SOCKET_RESOURCE: translate('OpenLP.ProjectorConstants',
338 'The local system ran out of resources (e.g., too many sockets)'),
339 E_SOCKET_TIMEOUT: translate('OpenLP.ProjectorConstants',
340 'The socket operation timed out'),
341 E_DATAGRAM_TOO_LARGE: translate('OpenLP.ProjectorConstants',
342 'The datagram was larger than the operating system\'s limit'),
343 E_NETWORK: translate('OpenLP.ProjectorConstants',384 E_NETWORK: translate('OpenLP.ProjectorConstants',
344 'An error occurred with the network (Possibly someone pulled the plug?)'),385 'An error occurred with the network (Possibly someone pulled the plug?)'),
345 E_ADDRESS_IN_USE: translate('OpenLP.ProjectorConstants',386 E_NO_AUTHENTICATION: translate('OpenLP.ProjectorConstants', 'PJlink authentication Mismatch Error'),
346 'The address specified with socket.bind() '387 E_NOT_CONNECTED: translate('OpenLP.ProjectorConstants', 'Projector not connected error'),
347 'is already in use and was set to be exclusive'),388 E_PARAMETER: translate('OpenLP.ProjectorConstants', 'PJLink returned "ERR2: Invalid Parameter"'),
348 E_SOCKET_ADDRESS_NOT_AVAILABLE: translate('OpenLP.ProjectorConstants',389 E_PREFIX: translate('OpenLP.ProjectorConstants', 'PJLink Invalid prefix character'),
349 'The address specified to socket.bind() '390 E_PROJECTOR: translate('OpenLP.ProjectorConstants', 'PJLink returned "ERR4: Projector/Display Error"'),
350 'does not belong to the host'),
351 E_UNSUPPORTED_SOCKET_OPERATION: translate('OpenLP.ProjectorConstants',
352 'The requested socket operation is not supported by the local '
353 'operating system (e.g., lack of IPv6 support)'),
354 E_PROXY_AUTHENTICATION_REQUIRED: translate('OpenLP.ProjectorConstants',391 E_PROXY_AUTHENTICATION_REQUIRED: translate('OpenLP.ProjectorConstants',
355 'The socket is using a proxy, '392 'The socket is using a proxy, '
356 'and the proxy requires authentication'),393 'and the proxy requires authentication'),
357 E_SLS_HANDSHAKE_FAILED: translate('OpenLP.ProjectorConstants',394 E_PROXY_CONNECTION_CLOSED: translate('OpenLP.ProjectorConstants',
358 'The SSL/TLS handshake failed'),395 'The connection to the proxy server was closed unexpectedly '
359 E_UNFINISHED_SOCKET_OPERATION: translate('OpenLP.ProjectorConstants',396 '(before the connection to the final peer was established)'),
360 'The last operation attempted has not finished yet '
361 '(still in progress in the background)'),
362 E_PROXY_CONNECTION_REFUSED: translate('OpenLP.ProjectorConstants',397 E_PROXY_CONNECTION_REFUSED: translate('OpenLP.ProjectorConstants',
363 'Could not contact the proxy server because the connection '398 'Could not contact the proxy server because the connection '
364 'to that server was denied'),399 'to that server was denied'),
365 E_PROXY_CONNECTION_CLOSED: translate('OpenLP.ProjectorConstants',
366 'The connection to the proxy server was closed unexpectedly '
367 '(before the connection to the final peer was established)'),
368 E_PROXY_CONNECTION_TIMEOUT: translate('OpenLP.ProjectorConstants',400 E_PROXY_CONNECTION_TIMEOUT: translate('OpenLP.ProjectorConstants',
369 'The connection to the proxy server timed out or the proxy '401 'The connection to the proxy server timed out or the proxy '
370 'server stopped responding in the authentication phase.'),402 'server stopped responding in the authentication phase.'),
@@ -373,51 +405,91 @@
373 E_PROXY_PROTOCOL: translate('OpenLP.ProjectorConstants',405 E_PROXY_PROTOCOL: translate('OpenLP.ProjectorConstants',
374 'The connection negotiation with the proxy server failed because the '406 'The connection negotiation with the proxy server failed because the '
375 'response from the proxy server could not be understood'),407 'response from the proxy server could not be understood'),
376 E_UNKNOWN_SOCKET_ERROR: translate('OpenLP.ProjectorConstants', 'An unidentified error occurred'),408 E_REMOTE_HOST_CLOSED_CONNECTION: translate('OpenLP.ProjectorConstants',
377 S_NOT_CONNECTED: translate('OpenLP.ProjectorConstants', 'Not connected'),409 'The remote host closed the connection'),
410 E_SLS_HANDSHAKE_FAILED: translate('OpenLP.ProjectorConstants',
411 'The SSL/TLS handshake failed'),
412 E_SOCKET_ADDRESS_NOT_AVAILABLE: translate('OpenLP.ProjectorConstants',
413 'The address specified to socket.bind() '
414 'does not belong to the host'),
415 E_SOCKET_ACCESS: translate('OpenLP.ProjectorConstants',
416 'The socket operation failed because the application '
417 'lacked the required privileges'),
418 E_SOCKET_RESOURCE: translate('OpenLP.ProjectorConstants',
419 'The local system ran out of resources (e.g., too many sockets)'),
420 E_SOCKET_TIMEOUT: translate('OpenLP.ProjectorConstants',
421 'The socket operation timed out'),
422 E_TEMP: translate('OpenLP.ProjectorConstants', 'Projector high temperature detected'),
423 E_UNAVAILABLE: translate('OpenLP.ProjectorConstants', 'PJLink returned "ERR3: Busy"'),
424 E_UNDEFINED: translate('OpenLP.ProjectorConstants', 'PJLink returned "ERR1: Undefined Command"'),
425 E_UNFINISHED_SOCKET_OPERATION: translate('OpenLP.ProjectorConstants',
426 'The last operation attempted has not finished yet '
427 '(still in progress in the background)'),
428 E_UNKNOWN: translate('OpenLP.ProjectorConstants', 'Unknown condiction detected'),
429 E_UNKNOWN_SOCKET_ERROR: translate('OpenLP.ProjectorConstants', 'An unidentified socket error occurred'),
430 E_UNSUPPORTED_SOCKET_OPERATION: translate('OpenLP.ProjectorConstants',
431 'The requested socket operation is not supported by the local '
432 'operating system (e.g., lack of IPv6 support)'),
433 E_WARN: translate('OpenLP.ProjectorConstants', 'Warning condition detected'),
434 S_BOUND: translate('OpenLP.ProjectorConstants', 'Socket is bount to an address or port'),
435 S_CLOSING: translate('OpenLP.ProjectorConstants', 'Socket is about to close'),
436 S_CONNECTED: translate('OpenLP.ProjectorConstants', 'Connected'),
378 S_CONNECTING: translate('OpenLP.ProjectorConstants', 'Connecting'),437 S_CONNECTING: translate('OpenLP.ProjectorConstants', 'Connecting'),
379 S_CONNECTED: translate('OpenLP.ProjectorConstants', 'Connected'),438 S_COOLDOWN: translate('OpenLP.ProjectorConstants', 'Cooldown in progress'),
380 S_STATUS: translate('OpenLP.ProjectorConstants', 'Getting status'),439 S_HOST_LOOKUP: translate('OpenLP.ProjectorConstants', 'Performing a host name lookup'),
440 S_INFO: translate('OpenLP.ProjectorConstants', 'Projector Information available'),
441 S_INITIALIZE: translate('OpenLP.ProjectorConstants', 'Initialize in progress'),
442 S_LISTENING: translate('OpenLP.ProjectorConstants', 'Socket it listening (internal use only)'),
443 S_NETWORK_IDLE: translate('OpenLP.ProjectorConstants', 'No network activity at this time'),
444 S_NETWORK_RECEIVING: translate('OpenLP.ProjectorConstants', 'Received data'),
445 S_NETWORK_SENDING: translate('OpenLP.ProjectorConstants', 'Sending data'),
446 S_NOT_CONNECTED: translate('OpenLP.ProjectorConstants', 'Not Connected'),
381 S_OFF: translate('OpenLP.ProjectorConstants', 'Off'),447 S_OFF: translate('OpenLP.ProjectorConstants', 'Off'),
382 S_INITIALIZE: translate('OpenLP.ProjectorConstants', 'Initialize in progress'),448 S_OK: translate('OpenLP.ProjectorConstants', 'OK'),
449 S_ON: translate('OpenLP.ProjectorConstants', 'Power is on'),
383 S_STANDBY: translate('OpenLP.ProjectorConstants', 'Power in standby'),450 S_STANDBY: translate('OpenLP.ProjectorConstants', 'Power in standby'),
451 S_STATUS: translate('OpenLP.ProjectorConstants', 'Getting status'),
384 S_WARMUP: translate('OpenLP.ProjectorConstants', 'Warmup in progress'),452 S_WARMUP: translate('OpenLP.ProjectorConstants', 'Warmup in progress'),
385 S_ON: translate('OpenLP.ProjectorConstants', 'Power is on'),453}
386 S_COOLDOWN: translate('OpenLP.ProjectorConstants', 'Cooldown in progress'),454
387 S_INFO: translate('OpenLP.ProjectorConstants', 'Projector Information available'),455# Map ERST reply positions to equipment
388 S_NETWORK_SENDING: translate('OpenLP.ProjectorConstants', 'Sending data'),456PJLINK_ERST_LIST = {
389 S_NETWORK_RECEIVED: translate('OpenLP.ProjectorConstants', 'Received data')457 "FAN": translate('OpenLP.PJLink', 'Fan'),
390}458 "LAMP": translate('OpenLP.PJLink', 'Lamp'),
391459 "TEMP": translate('OpenLP.PJLink', 'Temperature'),
392# Map ERST return code positions to equipment460 "COVER": translate('OpenLP.PJLink', 'Cover'),
461 "FILTER": translate('OpenLP.PJLink', 'Filter'),
462 "OTHER": translate('OpenPL.PJLink', 'Other')
463}
464
465# Map projector item to ERST data position
393PJLINK_ERST_DATA = {466PJLINK_ERST_DATA = {
394 'DATA_LENGTH': 6,467 'DATA_LENGTH': 6, # Zero based so enums are 0-5
468 'FAN': 0,
469 'LAMP': 1,
470 'TEMP': 2,
471 'COVER': 3,
472 'FILTER': 4,
473 'OTHER': 5,
395 0: 'FAN',474 0: 'FAN',
396 1: 'LAMP',475 1: 'LAMP',
397 2: 'TEMP',476 2: 'TEMP',
398 3: 'COVER',477 3: 'COVER',
399 4: 'FILTER',478 4: 'FILTER',
400 5: 'OTHER',479 5: 'OTHER'
401 'FAN': 0,
402 'LAMP': 1,
403 'TEMP': 2,
404 'COVER': 3,
405 'FILTER': 4,
406 'OTHER': 5
407}480}
408481
409# Map for ERST return codes to string482# Map ERST reply codes to string
410PJLINK_ERST_STATUS = {483PJLINK_ERST_STATUS = {
411 '0': 'OK',484 '0': S_OK,
412 '1': ERROR_STRING[E_WARN],485 '1': E_WARN,
413 '2': ERROR_STRING[E_ERROR],486 '2': E_ERROR,
414 'OK': '0',487 S_OK: '0',
415 E_OK: '0',
416 E_WARN: '1',488 E_WARN: '1',
417 E_ERROR: '2'489 E_ERROR: '2'
418}490}
419491
420# Map for POWR return codes to status code492# Map POWR return codes to status code
421PJLINK_POWR_STATUS = {493PJLINK_POWR_STATUS = {
422 '0': S_STANDBY,494 '0': S_STANDBY,
423 '1': S_ON,495 '1': S_ON,
@@ -485,3 +557,7 @@
485 label = "{source}{item}".format(source=source, item=item)557 label = "{source}{item}".format(source=source, item=item)
486 PJLINK_DEFAULT_CODES[label] = "{source} {item}".format(source=PJLINK_DEFAULT_SOURCES[source],558 PJLINK_DEFAULT_CODES[label] = "{source} {item}".format(source=PJLINK_DEFAULT_SOURCES[source],
487 item=PJLINK_DEFAULT_ITEMS[item])559 item=PJLINK_DEFAULT_ITEMS[item])
560# Remove temp variables so they don't become part of the module dict
561del(source)
562del(item)
563del(label)
488564
=== modified file 'openlp/core/projectors/manager.py'
--- openlp/core/projectors/manager.py 2017-11-24 19:08:23 +0000
+++ openlp/core/projectors/manager.py 2017-12-25 08:57:51 +0000
@@ -35,9 +35,25 @@
35from openlp.core.common.settings import Settings35from openlp.core.common.settings import Settings
36from openlp.core.lib.ui import create_widget_action36from openlp.core.lib.ui import create_widget_action
37from openlp.core.projectors import DialogSourceStyle37from openlp.core.projectors import DialogSourceStyle
38from openlp.core.projectors.constants import ERROR_MSG, ERROR_STRING, E_AUTHENTICATION, E_ERROR, \38from openlp.core.projectors.constants import \
39 E_NETWORK, E_NOT_CONNECTED, E_UNKNOWN_SOCKET_ERROR, STATUS_STRING, S_CONNECTED, S_CONNECTING, S_COOLDOWN, \39 E_AUTHENTICATION, \
40 S_INITIALIZE, S_NOT_CONNECTED, S_OFF, S_ON, S_STANDBY, S_WARMUP40 E_ERROR, \
41 E_NETWORK, \
42 E_NOT_CONNECTED, \
43 E_UNKNOWN_SOCKET_ERROR, \
44 S_CONNECTED, \
45 S_CONNECTING, \
46 S_COOLDOWN, \
47 S_INITIALIZE, \
48 S_NOT_CONNECTED, \
49 S_OFF, \
50 S_ON, \
51 S_STANDBY, \
52 S_WARMUP, \
53 STATUS_CODE, \
54 STATUS_MSG, \
55 QSOCKET_STATE
56
41from openlp.core.projectors.db import ProjectorDB57from openlp.core.projectors.db import ProjectorDB
42from openlp.core.projectors.pjlink import PJLink, PJLinkUDP58from openlp.core.projectors.pjlink import PJLink, PJLinkUDP
43from openlp.core.projectors.editform import ProjectorEditForm59from openlp.core.projectors.editform import ProjectorEditForm
@@ -440,11 +456,12 @@
440 :param opt: Needed by PyQt5456 :param opt: Needed by PyQt5
441 """457 """
442 projector = item.data(QtCore.Qt.UserRole)458 projector = item.data(QtCore.Qt.UserRole)
443 if projector.link.state() != projector.link.ConnectedState:459 if QSOCKET_STATE[projector.link.state()] != S_CONNECTED:
444 try:460 try:
461 log.debug('ProjectorManager: Calling connect_to_host() on "{ip}"'.format(ip=projector.link.ip))
445 projector.link.connect_to_host()462 projector.link.connect_to_host()
446 except:463 except:
447 pass464 log.debug('ProjectorManager: "{ip}" already connected - skipping'.format(ip=projector.link.ip))
448 return465 return
449466
450 def on_connect_projector(self, opt=None):467 def on_connect_projector(self, opt=None):
@@ -647,7 +664,7 @@
647 'Other info'),664 'Other info'),
648 data=projector.link.other_info)665 data=projector.link.other_info)
649 message += '<b>{title}</b>: {data}<br />'.format(title=translate('OpenLP.ProjectorManager', 'Power status'),666 message += '<b>{title}</b>: {data}<br />'.format(title=translate('OpenLP.ProjectorManager', 'Power status'),
650 data=ERROR_MSG[projector.link.power])667 data=STATUS_MSG[projector.link.power])
651 message += '<b>{title}</b>: {data}<br />'.format(title=translate('OpenLP.ProjectorManager', 'Shutter is'),668 message += '<b>{title}</b>: {data}<br />'.format(title=translate('OpenLP.ProjectorManager', 'Shutter is'),
652 data=translate('OpenLP.ProjectorManager', 'Closed')669 data=translate('OpenLP.ProjectorManager', 'Closed')
653 if projector.link.shutter670 if projector.link.shutter
@@ -692,7 +709,7 @@
692 else:709 else:
693 message += '<b>{data}</b>'.format(data=translate('OpenLP.ProjectorManager', 'Current errors/warnings'))710 message += '<b>{data}</b>'.format(data=translate('OpenLP.ProjectorManager', 'Current errors/warnings'))
694 for (key, val) in projector.link.projector_errors.items():711 for (key, val) in projector.link.projector_errors.items():
695 message += '<b>{key}</b>: {data}<br />'.format(key=key, data=ERROR_MSG[val])712 message += '<b>{key}</b>: {data}<br />'.format(key=key, data=STATUS_MSG[val])
696 QtWidgets.QMessageBox.information(self, translate('OpenLP.ProjectorManager', 'Projector Information'), message)713 QtWidgets.QMessageBox.information(self, translate('OpenLP.ProjectorManager', 'Projector Information'), message)
697714
698 def _add_projector(self, projector):715 def _add_projector(self, projector):
@@ -817,31 +834,18 @@
817 if ip == list_item.link.ip:834 if ip == list_item.link.ip:
818 item = list_item835 item = list_item
819 break836 break
820 message = translate('OpenLP.ProjectorManager', 'No message') if msg is None else msg837 if item is None:
821 if status in STATUS_STRING:838 log.error('ProjectorManager: Unknown item "{ip}" - not updating status'.format(ip=ip))
822 status_code = STATUS_STRING[status]839 return
823 message = ERROR_MSG[status] if msg is None else msg840 elif item.status == status:
824 elif status in ERROR_STRING:841 log.debug('ProjectorManager: No status change for "{ip}" - not updating status'.format(ip=ip))
825 status_code = ERROR_STRING[status]842 return
826 message = ERROR_MSG[status] if msg is None else msg843
827 else:844 item.status = status
828 status_code = status845 item.icon = QtGui.QIcon(QtGui.QPixmap(STATUS_ICONS[status]))
829 message = ERROR_MSG[status] if msg is None else msg846 log.debug('({name}) Updating icon with {code}'.format(name=item.link.name, code=STATUS_CODE[status]))
830 log.debug('({name}) updateStatus(status={status}) message: "{message}"'.format(name=item.link.name,847 item.widget.setIcon(item.icon)
831 status=status_code,848 return self.update_icons()
832 message=message))
833 if status in STATUS_ICONS:
834 if item.status == status:
835 return
836 item.status = status
837 item.icon = QtGui.QIcon(QtGui.QPixmap(STATUS_ICONS[status]))
838 if status in ERROR_STRING:
839 status_code = ERROR_STRING[status]
840 elif status in STATUS_STRING:
841 status_code = STATUS_STRING[status]
842 log.debug('({name}) Updating icon with {code}'.format(name=item.link.name, code=status_code))
843 item.widget.setIcon(item.icon)
844 self.update_icons()
845849
846 def get_toolbar_item(self, name, enabled=False, hidden=False):850 def get_toolbar_item(self, name, enabled=False, hidden=False):
847 item = self.one_toolbar.findChild(QtWidgets.QAction, name)851 item = self.one_toolbar.findChild(QtWidgets.QAction, name)
@@ -877,7 +881,7 @@
877 self.get_toolbar_item('show_projector_multiple', hidden=True)881 self.get_toolbar_item('show_projector_multiple', hidden=True)
878 elif count == 1:882 elif count == 1:
879 projector = self.projector_list_widget.selectedItems()[0].data(QtCore.Qt.UserRole)883 projector = self.projector_list_widget.selectedItems()[0].data(QtCore.Qt.UserRole)
880 connected = projector.link.state() == projector.link.ConnectedState884 connected = QSOCKET_STATE[projector.link.state()] == S_CONNECTED
881 power = projector.link.power == S_ON885 power = projector.link.power == S_ON
882 self.get_toolbar_item('connect_projector_multiple', hidden=True)886 self.get_toolbar_item('connect_projector_multiple', hidden=True)
883 self.get_toolbar_item('disconnect_projector_multiple', hidden=True)887 self.get_toolbar_item('disconnect_projector_multiple', hidden=True)
884888
=== modified file 'openlp/core/projectors/pjlink.py'
--- openlp/core/projectors/pjlink.py 2017-12-09 11:17:05 +0000
+++ openlp/core/projectors/pjlink.py 2017-12-25 08:57:51 +0000
@@ -54,11 +54,12 @@
5454
55from openlp.core.common import qmd5_hash55from openlp.core.common import qmd5_hash
56from openlp.core.common.i18n import translate56from openlp.core.common.i18n import translate
57from openlp.core.projectors.constants import CONNECTION_ERRORS, CR, ERROR_MSG, ERROR_STRING, \57from openlp.core.projectors.constants import CONNECTION_ERRORS, PJLINK_CLASS, PJLINK_DEFAULT_CODES, PJLINK_ERRORS, \
58 E_AUTHENTICATION, E_CONNECTION_REFUSED, E_GENERAL, E_INVALID_DATA, E_NETWORK, E_NOT_CONNECTED, E_OK, \58 PJLINK_ERST_DATA, PJLINK_ERST_STATUS, PJLINK_MAX_PACKET, PJLINK_PREFIX, PJLINK_PORT, PJLINK_POWR_STATUS, \
59 E_PARAMETER, E_PROJECTOR, E_SOCKET_TIMEOUT, E_UNAVAILABLE, E_UNDEFINED, PJLINK_ERRORS, PJLINK_ERST_DATA, \59 PJLINK_SUFFIX, PJLINK_VALID_CMD, PROJECTOR_STATE, STATUS_CODE, STATUS_MSG, QSOCKET_STATE, \
60 PJLINK_ERST_STATUS, PJLINK_MAX_PACKET, PJLINK_PORT, PJLINK_POWR_STATUS, PJLINK_VALID_CMD, \60 E_AUTHENTICATION, E_CONNECTION_REFUSED, E_GENERAL, E_INVALID_DATA, E_NETWORK, E_NOT_CONNECTED, \
61 STATUS_STRING, S_CONNECTED, S_CONNECTING, S_INFO, S_NOT_CONNECTED, S_OFF, S_OK, S_ON, S_QSOCKET_STATE, S_STATUS61 E_OK, E_SOCKET_TIMEOUT, \
62 S_CONNECTED, S_CONNECTING, S_INFO, S_NOT_CONNECTED, S_OFF, S_OK, S_ON, S_STATUS
6263
63log = logging.getLogger(__name__)64log = logging.getLogger(__name__)
64log.debug('pjlink loaded')65log.debug('pjlink loaded')
@@ -69,12 +70,9 @@
69SocketError = QtNetwork.QAbstractSocket.SocketError70SocketError = QtNetwork.QAbstractSocket.SocketError
70SocketSTate = QtNetwork.QAbstractSocket.SocketState71SocketSTate = QtNetwork.QAbstractSocket.SocketState
7172
72PJLINK_PREFIX = '%'
73PJLINK_CLASS = '1' # Default to class 1 until we query the projector
74# Add prefix here, but defer linkclass expansion until later when we have the actual73# Add prefix here, but defer linkclass expansion until later when we have the actual
75# PJLink class for the command74# PJLink class for the command
76PJLINK_HEADER = '{prefix}{{linkclass}}'.format(prefix=PJLINK_PREFIX)75PJLINK_HEADER = '{prefix}{{linkclass}}'.format(prefix=PJLINK_PREFIX)
77PJLINK_SUFFIX = CR
7876
7977
80class PJLinkUDP(QtNetwork.QUdpSocket):78class PJLinkUDP(QtNetwork.QUdpSocket):
@@ -136,8 +134,9 @@
136 """134 """
137 Initialize instance variables. Also used to reset projector-specific information to default.135 Initialize instance variables. Also used to reset projector-specific information to default.
138 """136 """
137 conn_state = STATUS_CODE[QSOCKET_STATE[self.state()]]
139 log.debug('({ip}) reset_information() connect status is {state}'.format(ip=self.ip,138 log.debug('({ip}) reset_information() connect status is {state}'.format(ip=self.ip,
140 state=S_QSOCKET_STATE[self.state()]))139 state=conn_state))
141 self.fan = None # ERST140 self.fan = None # ERST
142 self.filter_time = None # FILT141 self.filter_time = None # FILT
143 self.lamp = None # LAMP142 self.lamp = None # LAMP
@@ -183,42 +182,25 @@
183 # Due to some replies should stay as mixed-case, validate using separate uppercase check182 # Due to some replies should stay as mixed-case, validate using separate uppercase check
184 _data = data.upper()183 _data = data.upper()
185 # Check if we have a future command not available yet184 # Check if we have a future command not available yet
186 if cmd not in PJLINK_VALID_CMD:185 if cmd not in self.pjlink_functions:
187 log.error('({ip}) Ignoring command="{cmd}" (Invalid/Unknown)'.format(ip=self.ip, cmd=cmd))186 log.warning('({ip}) Unable to process command="{cmd}" (Future option?)'.format(ip=self.ip, cmd=cmd))
188 return187 return
189 elif _data == 'OK':188 elif _data == 'OK':
190 log.debug('({ip}) Command "{cmd}" returned OK'.format(ip=self.ip, cmd=cmd))189 log.debug('({ip}) Command "{cmd}" returned OK'.format(ip=self.ip, cmd=cmd))
191 # A command returned successfully, so do a query on command to verify status190 # A command returned successfully, so do a query on command to verify status
192 return self.send_command(cmd=cmd)191 return self.send_command(cmd=cmd)
193 elif cmd not in self.pjlink_functions:
194 log.warning('({ip}) Unable to process command="{cmd}" (Future option?)'.format(ip=self.ip, cmd=cmd))
195 return
196 elif _data in PJLINK_ERRORS:192 elif _data in PJLINK_ERRORS:
197 # Oops - projector error193 # Oops - projector error
198 log.error('({ip}) Projector returned error "{data}"'.format(ip=self.ip, data=data))194 log.error('({ip}) {cmd}: {err}'.format(ip=self.ip,
199 if _data == PJLINK_ERRORS[E_AUTHENTICATION]:195 cmd=cmd,
200 # Authentication error196 err=STATUS_MSG[PJLINK_ERRORS[_data]]))
197 if PJLINK_ERRORS[_data] == E_AUTHENTICATION:
201 self.disconnect_from_host()198 self.disconnect_from_host()
202 self.change_status(E_AUTHENTICATION)
203 log.debug('({ip}) emitting projectorAuthentication() signal'.format(ip=self.ip))
204 self.projectorAuthentication.emit(self.name)199 self.projectorAuthentication.emit(self.name)
205 elif _data == PJLINK_ERRORS[E_UNDEFINED]:200 return self.change_status(status=E_AUTHENTICATION)
206 # Projector does not recognize command
207 self.change_status(E_UNDEFINED, '{error}: "{data}"'.format(error=ERROR_MSG[E_UNDEFINED],
208 data=cmd))
209 elif _data == PJLINK_ERRORS[E_PARAMETER]:
210 # Invalid parameter
211 self.change_status(E_PARAMETER)
212 elif _data == PJLINK_ERRORS[E_UNAVAILABLE]:
213 # Projector busy
214 self.change_status(E_UNAVAILABLE)
215 elif _data == PJLINK_ERRORS[E_PROJECTOR]:
216 # Projector/display error
217 self.change_status(E_PROJECTOR)
218 return
219 # Command checks already passed201 # Command checks already passed
220 log.debug('({ip}) Calling function for {cmd}'.format(ip=self.ip, cmd=cmd))202 log.debug('({ip}) Calling function for {cmd}'.format(ip=self.ip, cmd=cmd))
221 self.pjlink_functions[cmd](data)203 self.pjlink_functions[cmd](data=data)
222204
223 def process_avmt(self, data):205 def process_avmt(self, data):
224 """206 """
@@ -313,22 +295,22 @@
313 data[PJLINK_ERST_DATA['COVER']],295 data[PJLINK_ERST_DATA['COVER']],
314 data[PJLINK_ERST_DATA['FILTER']],296 data[PJLINK_ERST_DATA['FILTER']],
315 data[PJLINK_ERST_DATA['OTHER']])297 data[PJLINK_ERST_DATA['OTHER']])
316 if fan != PJLINK_ERST_STATUS[E_OK]:298 if fan != PJLINK_ERST_STATUS[S_OK]:
317 self.projector_errors[translate('OpenLP.ProjectorPJLink', 'Fan')] = \299 self.projector_errors[translate('OpenLP.ProjectorPJLink', 'Fan')] = \
318 PJLINK_ERST_STATUS[fan]300 PJLINK_ERST_STATUS[fan]
319 if lamp != PJLINK_ERST_STATUS[E_OK]:301 if lamp != PJLINK_ERST_STATUS[S_OK]:
320 self.projector_errors[translate('OpenLP.ProjectorPJLink', 'Lamp')] = \302 self.projector_errors[translate('OpenLP.ProjectorPJLink', 'Lamp')] = \
321 PJLINK_ERST_STATUS[lamp]303 PJLINK_ERST_STATUS[lamp]
322 if temp != PJLINK_ERST_STATUS[E_OK]:304 if temp != PJLINK_ERST_STATUS[S_OK]:
323 self.projector_errors[translate('OpenLP.ProjectorPJLink', 'Temperature')] = \305 self.projector_errors[translate('OpenLP.ProjectorPJLink', 'Temperature')] = \
324 PJLINK_ERST_STATUS[temp]306 PJLINK_ERST_STATUS[temp]
325 if cover != PJLINK_ERST_STATUS[E_OK]:307 if cover != PJLINK_ERST_STATUS[S_OK]:
326 self.projector_errors[translate('OpenLP.ProjectorPJLink', 'Cover')] = \308 self.projector_errors[translate('OpenLP.ProjectorPJLink', 'Cover')] = \
327 PJLINK_ERST_STATUS[cover]309 PJLINK_ERST_STATUS[cover]
328 if filt != PJLINK_ERST_STATUS[E_OK]:310 if filt != PJLINK_ERST_STATUS[S_OK]:
329 self.projector_errors[translate('OpenLP.ProjectorPJLink', 'Filter')] = \311 self.projector_errors[translate('OpenLP.ProjectorPJLink', 'Filter')] = \
330 PJLINK_ERST_STATUS[filt]312 PJLINK_ERST_STATUS[filt]
331 if other != PJLINK_ERST_STATUS[E_OK]:313 if other != PJLINK_ERST_STATUS[S_OK]:
332 self.projector_errors[translate('OpenLP.ProjectorPJLink', 'Other')] = \314 self.projector_errors[translate('OpenLP.ProjectorPJLink', 'Other')] = \
333 PJLINK_ERST_STATUS[other]315 PJLINK_ERST_STATUS[other]
334 return316 return
@@ -373,8 +355,18 @@
373355
374 :param data: Currently selected source356 :param data: Currently selected source
375 """357 """
358 # First, see if we have a valid input based on what is installed (if available)
359 if self.source_available is not None:
360 # We have available inputs, so verify it's in the list
361 if data not in self.source_available:
362 log.warn('({ip}) Input source not listed in available sources - ignoring'.format(ip=self.ip))
363 return
364 elif data not in PJLINK_DEFAULT_CODES:
365 # Hmm - no sources available yet, so check with PJLink defaults
366 log.warn('({ip}) Input source not listed as a PJLink available source - ignoring'.format(ip=self.ip))
367 return
376 self.source = data368 self.source = data
377 log.info('({ip}) Setting data source to "{data}"'.format(ip=self.ip, data=self.source))369 log.debug('({ip}) Setting data source to "{data}"'.format(ip=self.ip, data=self.source))
378 return370 return
379371
380 def process_inst(self, data):372 def process_inst(self, data):
@@ -390,7 +382,6 @@
390 sources.append(source)382 sources.append(source)
391 sources.sort()383 sources.sort()
392 self.source_available = sources384 self.source_available = sources
393 self.projectorUpdateIcons.emit()
394 log.debug('({ip}) Setting projector sources_available to "{data}"'.format(ip=self.ip,385 log.debug('({ip}) Setting projector sources_available to "{data}"'.format(ip=self.ip,
395 data=self.source_available))386 data=self.source_available))
396 return387 return
@@ -551,17 +542,15 @@
551 return542 return
552 elif self.sw_version is None:543 elif self.sw_version is None:
553 log.debug('({ip}) Setting projector software version to "{data}"'.format(ip=self.ip, data=data))544 log.debug('({ip}) Setting projector software version to "{data}"'.format(ip=self.ip, data=data))
554 self.sw_version = data
555 self.db_update = True
556 else:545 else:
557 # Compare software version and see if we got the same projector546 if self.sw_version != data:
558 if self.serial_no != data:
559 log.warning('({ip}) Projector software version does not match saved '547 log.warning('({ip}) Projector software version does not match saved '
560 'software version'.format(ip=self.ip))548 'software version'.format(ip=self.ip))
561 log.warning('({ip}) Saved: "{old}"'.format(ip=self.ip, old=self.sw_version))549 log.warning('({ip}) Saved: "{old}"'.format(ip=self.ip, old=self.sw_version))
562 log.warning('({ip}) Received: "{new}"'.format(ip=self.ip, new=data))550 log.warning('({ip}) Received: "{new}"'.format(ip=self.ip, new=data))
563 log.warning('({ip}) Saving new serial number as sw_version_received'.format(ip=self.ip))551 log.warning('({ip}) Updating software version'.format(ip=self.ip))
564 self.sw_version_received = data552 self.sw_version = data
553 self.db_update = True
565554
566555
567class PJLink(QtNetwork.QTcpSocket, PJLinkCommands):556class PJLink(QtNetwork.QTcpSocket, PJLinkCommands):
@@ -678,7 +667,7 @@
678 Retrieve information from projector that changes.667 Retrieve information from projector that changes.
679 Normally called by timer().668 Normally called by timer().
680 """669 """
681 if self.state() != S_QSOCKET_STATE['ConnectedState']:670 if QSOCKET_STATE[self.state()] != S_CONNECTED:
682 log.warning('({ip}) poll_loop(): Not connected - returning'.format(ip=self.ip))671 log.warning('({ip}) poll_loop(): Not connected - returning'.format(ip=self.ip))
683 return672 return
684 log.debug('({ip}) poll_loop(): Updating projector status'.format(ip=self.ip))673 log.debug('({ip}) poll_loop(): Updating projector status'.format(ip=self.ip))
@@ -688,13 +677,8 @@
688 self.timer.setInterval(self.poll_time)677 self.timer.setInterval(self.poll_time)
689 # Restart timer678 # Restart timer
690 self.timer.start()679 self.timer.start()
691 # These commands may change during connection
692 check_list = ['POWR', 'ERST', 'LAMP', 'AVMT', 'INPT']
693 if self.pjlink_class == '2':
694 check_list.extend(['FILT', 'FREZ'])
695 for command in check_list:
696 self.send_command(command)
697 # The following commands do not change, so only check them once680 # The following commands do not change, so only check them once
681 # Call them first in case other functions rely on something here
698 if self.power == S_ON and self.source_available is None:682 if self.power == S_ON and self.source_available is None:
699 self.send_command('INST')683 self.send_command('INST')
700 if self.other_info is None:684 if self.other_info is None:
@@ -715,22 +699,28 @@
715 self.send_command('RFIL')699 self.send_command('RFIL')
716 if self.model_lamp is None:700 if self.model_lamp is None:
717 self.send_command('RLMP')701 self.send_command('RLMP')
702 # These commands may change during connection
703 check_list = ['POWR', 'ERST', 'LAMP', 'AVMT', 'INPT']
704 if self.pjlink_class == '2':
705 check_list.extend(['FILT', 'FREZ'])
706 for command in check_list:
707 self.send_command(command)
718708
719 def _get_status(self, status):709 def _get_status(self, status):
720 """710 """
721 Helper to retrieve status/error codes and convert to strings.711 Helper to retrieve status/error codes and convert to strings.
722712
723 :param status: Status/Error code713 :param status: Status/Error code
724 :returns: (Status/Error code, String)714 :returns: tuple (-1 if code not INT, None)
715 :returns: tuple (string: code as string, None if no description)
716 :returns: tuple (string: code as string, string: Status/Error description)
725 """717 """
726 if not isinstance(status, int):718 if not isinstance(status, int):
727 return -1, 'Invalid status code'719 return -1, None
728 elif status in ERROR_STRING:720 elif status not in STATUS_MSG:
729 return ERROR_STRING[status], ERROR_MSG[status]721 return None, None
730 elif status in STATUS_STRING:
731 return STATUS_STRING[status], ERROR_MSG[status]
732 else:722 else:
733 return status, translate('OpenLP.PJLink', 'Unknown status')723 return STATUS_CODE[status], STATUS_MSG[status]
734724
735 def change_status(self, status, msg=None):725 def change_status(self, status, msg=None):
736 """726 """
@@ -740,19 +730,27 @@
740 :param status: Status code730 :param status: Status code
741 :param msg: Optional message731 :param msg: Optional message
742 """732 """
743 message = translate('OpenLP.PJLink', 'No message') if msg is None else msg733 if status in STATUS_CODE:
744 (code, message) = self._get_status(status)734 log.debug('({ip}) Changing status to {status} '
745 if msg is not None:735 '"{msg}"'.format(ip=self.ip,
746 message = msg736 status=STATUS_CODE[status],
737 msg=msg if msg is not None else STATUS_MSG[status]))
738 else:
739 log.warning('({ip}) Unknown status change code: {code}'.format(ip=self.ip,
740 code=status))
741 return
747 if status in CONNECTION_ERRORS:742 if status in CONNECTION_ERRORS:
748 # Projector, connection state743 # Connection state error affects both socket and projector
749 self.projector_status = self.error_status = self.status_connect = E_NOT_CONNECTED744 self.error_status = status
750 elif status >= S_NOT_CONNECTED and status < S_STATUS:745 self.status_connect = E_NOT_CONNECTED
746 elif status >= S_NOT_CONNECTED and status in QSOCKET_STATE:
747 # Socket connection status update
751 self.status_connect = status748 self.status_connect = status
752 self.projector_status = S_NOT_CONNECTED749 elif status >= S_NOT_CONNECTED and status in PROJECTOR_STATE:
753 elif status <= S_INFO:750 # Only affects the projector status
754 self.status_connect = S_CONNECTED
755 self.projector_status = status751 self.projector_status = status
752
753 # These log entries are for troubleshooting only
756 (status_code, status_message) = self._get_status(self.status_connect)754 (status_code, status_message) = self._get_status(self.status_connect)
757 log.debug('({ip}) status_connect: {code}: "{message}"'.format(ip=self.ip,755 log.debug('({ip}) status_connect: {code}: "{message}"'.format(ip=self.ip,
758 code=status_code,756 code=status_code,
@@ -765,6 +763,15 @@
765 log.debug('({ip}) error_status: {code}: "{message}"'.format(ip=self.ip,763 log.debug('({ip}) error_status: {code}: "{message}"'.format(ip=self.ip,
766 code=status_code,764 code=status_code,
767 message=status_message if msg is None else msg))765 message=status_message if msg is None else msg))
766
767 # Now that we logged extra information for debugging, broadcast the original change/message
768 (code, message) = self._get_status(status)
769 if msg is not None:
770 message = msg
771 elif message is None:
772 # No message for status code
773 message = translate('OpenLP.PJLink', 'No message') if msg is None else msg
774
768 self.changeStatus.emit(self.ip, status, message)775 self.changeStatus.emit(self.ip, status, message)
769 self.projectorUpdateIcons.emit()776 self.projectorUpdateIcons.emit()
770777
@@ -794,7 +801,7 @@
794 data = decode(read, 'utf-8')801 data = decode(read, 'utf-8')
795 # Possibility of extraneous data on input when reading.802 # Possibility of extraneous data on input when reading.
796 # Clean out extraneous characters in buffer.803 # Clean out extraneous characters in buffer.
797 self.readLine(self.max_size)804 self.read(2048)
798 log.debug('({ip}) check_login() read "{data}"'.format(ip=self.ip, data=data.strip()))805 log.debug('({ip}) check_login() read "{data}"'.format(ip=self.ip, data=data.strip()))
799 # At this point, we should only have the initial login prompt with806 # At this point, we should only have the initial login prompt with
800 # possible authentication807 # possible authentication
@@ -805,6 +812,7 @@
805 # Invalid initial packet - close socket812 # Invalid initial packet - close socket
806 log.error('({ip}) Invalid initial packet received - closing socket'.format(ip=self.ip))813 log.error('({ip}) Invalid initial packet received - closing socket'.format(ip=self.ip))
807 return self.disconnect_from_host()814 return self.disconnect_from_host()
815 # Convert the initial login prompt with the expected PJLink normal command format for processing
808 log.debug('({ip}) check_login(): Formatting initial connection prompt to PJLink packet'.format(ip=self.ip))816 log.debug('({ip}) check_login(): Formatting initial connection prompt to PJLink packet'.format(ip=self.ip))
809 return self.get_data('{start}{clss}{data}'.format(start=PJLINK_PREFIX,817 return self.get_data('{start}{clss}{data}'.format(start=PJLINK_PREFIX,
810 clss='1',818 clss='1',
@@ -895,7 +903,7 @@
895 Get data from TCP socket.903 Get data from TCP socket.
896 """904 """
897 log.debug('({ip}) get_socket(): Reading data'.format(ip=self.ip))905 log.debug('({ip}) get_socket(): Reading data'.format(ip=self.ip))
898 if self.state() != self.ConnectedState:906 if QSOCKET_STATE[self.state()] != S_CONNECTED:
899 log.debug('({ip}) get_socket(): Not connected - returning'.format(ip=self.ip))907 log.debug('({ip}) get_socket(): Not connected - returning'.format(ip=self.ip))
900 self.send_busy = False908 self.send_busy = False
901 return909 return
@@ -907,8 +915,7 @@
907 log.debug('({ip}) get_socket(): No data available (-1)'.format(ip=self.ip))915 log.debug('({ip}) get_socket(): No data available (-1)'.format(ip=self.ip))
908 return self.receive_data_signal()916 return self.receive_data_signal()
909 self.socket_timer.stop()917 self.socket_timer.stop()
910 self.get_data(buff=read, ip=self.ip)918 return self.get_data(buff=read, ip=self.ip)
911 return self.receive_data_signal()
912919
913 def get_data(self, buff, ip=None):920 def get_data(self, buff, ip=None):
914 """921 """
@@ -927,13 +934,17 @@
927 data = data_in.strip()934 data = data_in.strip()
928 # Initial packet checks935 # Initial packet checks
929 if (len(data) < 7):936 if (len(data) < 7):
930 return self._trash_buffer(msg='get_data(): Invalid packet - length')937 self._trash_buffer(msg='get_data(): Invalid packet - length')
938 return self.receive_data_signal()
931 elif len(data) > self.max_size:939 elif len(data) > self.max_size:
932 return self._trash_buffer(msg='get_data(): Invalid packet - too long')940 self._trash_buffer(msg='get_data(): Invalid packet - too long')
941 return self.receive_data_signal()
933 elif not data.startswith(PJLINK_PREFIX):942 elif not data.startswith(PJLINK_PREFIX):
934 return self._trash_buffer(msg='get_data(): Invalid packet - PJLink prefix missing')943 self._trash_buffer(msg='get_data(): Invalid packet - PJLink prefix missing')
944 return self.receive_data_signal()
935 elif '=' not in data:945 elif '=' not in data:
936 return self._trash_buffer(msg='get_data(): Invalid reply - Does not have "="')946 self._trash_buffer(msg='get_data(): Invalid reply - Does not have "="')
947 return self.receive_data_signal()
937 log.debug('({ip}) get_data(): Checking new data "{data}"'.format(ip=self.ip, data=data))948 log.debug('({ip}) get_data(): Checking new data "{data}"'.format(ip=self.ip, data=data))
938 header, data = data.split('=')949 header, data = data.split('=')
939 # At this point, the header should contain:950 # At this point, the header should contain:
@@ -947,15 +958,17 @@
947 except ValueError as e:958 except ValueError as e:
948 self.change_status(E_INVALID_DATA)959 self.change_status(E_INVALID_DATA)
949 log.warning('({ip}) get_data(): Received data: "{data}"'.format(ip=self.ip, data=data_in))960 log.warning('({ip}) get_data(): Received data: "{data}"'.format(ip=self.ip, data=data_in))
950 return self._trash_buffer('get_data(): Expected header + command + data')961 self._trash_buffer('get_data(): Expected header + command + data')
962 return self.receive_data_signal()
951 if cmd not in PJLINK_VALID_CMD:963 if cmd not in PJLINK_VALID_CMD:
952 log.warning('({ip}) get_data(): Invalid packet - unknown command "{data}"'.format(ip=self.ip, data=cmd))964 log.warning('({ip}) get_data(): Invalid packet - unknown command "{data}"'.format(ip=self.ip, data=cmd))
953 return self._trash_buffer(msg='get_data(): Unknown command "{data}"'.format(data=cmd))965 self._trash_buffer(msg='get_data(): Unknown command "{data}"'.format(data=cmd))
966 return self.receive_data_signal()
954 if int(self.pjlink_class) < int(version):967 if int(self.pjlink_class) < int(version):
955 log.warning('({ip}) get_data(): Projector returned class reply higher '968 log.warning('({ip}) get_data(): Projector returned class reply higher '
956 'than projector stated class'.format(ip=self.ip))969 'than projector stated class'.format(ip=self.ip))
957 self.send_busy = False970 self.process_command(cmd, data)
958 return self.process_command(cmd, data)971 return self.receive_data_signal()
959972
960 @QtCore.pyqtSlot(QtNetwork.QAbstractSocket.SocketError)973 @QtCore.pyqtSlot(QtNetwork.QAbstractSocket.SocketError)
961 def get_error(self, err):974 def get_error(self, err):
@@ -993,7 +1006,7 @@
993 :param salt: Optional salt for md5 hash initial authentication1006 :param salt: Optional salt for md5 hash initial authentication
994 :param priority: Option to send packet now rather than queue it up1007 :param priority: Option to send packet now rather than queue it up
995 """1008 """
996 if self.state() != self.ConnectedState:1009 if QSOCKET_STATE[self.state()] != S_CONNECTED:
997 log.warning('({ip}) send_command(): Not connected - returning'.format(ip=self.ip))1010 log.warning('({ip}) send_command(): Not connected - returning'.format(ip=self.ip))
998 return self.reset_information()1011 return self.reset_information()
999 if cmd not in PJLINK_VALID_CMD:1012 if cmd not in PJLINK_VALID_CMD:
@@ -1018,7 +1031,7 @@
1018 header=header,1031 header=header,
1019 command=cmd,1032 command=cmd,
1020 options=opts,1033 options=opts,
1021 suffix=CR)1034 suffix=PJLINK_SUFFIX)
1022 if out in self.priority_queue:1035 if out in self.priority_queue:
1023 log.debug('({ip}) send_command(): Already in priority queue - skipping'.format(ip=self.ip))1036 log.debug('({ip}) send_command(): Already in priority queue - skipping'.format(ip=self.ip))
1024 elif out in self.send_queue:1037 elif out in self.send_queue:
@@ -1044,9 +1057,10 @@
1044 """1057 """
1045 # Funny looking data check, but it's a quick check for data=None1058 # Funny looking data check, but it's a quick check for data=None
1046 log.debug('({ip}) _send_command(data="{data}")'.format(ip=self.ip, data=data.strip() if data else data))1059 log.debug('({ip}) _send_command(data="{data}")'.format(ip=self.ip, data=data.strip() if data else data))
1060 conn_state = STATUS_CODE[QSOCKET_STATE[self.state()]]
1047 log.debug('({ip}) _send_command(): Connection status: {data}'.format(ip=self.ip,1061 log.debug('({ip}) _send_command(): Connection status: {data}'.format(ip=self.ip,
1048 data=S_QSOCKET_STATE[self.state()]))1062 data=conn_state))
1049 if self.state() != self.ConnectedState:1063 if QSOCKET_STATE[self.state()] != S_CONNECTED:
1050 log.debug('({ip}) _send_command() Not connected - abort'.format(ip=self.ip))1064 log.debug('({ip}) _send_command() Not connected - abort'.format(ip=self.ip))
1051 self.send_busy = False1065 self.send_busy = False
1052 return self.disconnect_from_host()1066 return self.disconnect_from_host()
@@ -1088,10 +1102,11 @@
1088 """1102 """
1089 Initiate connection to projector.1103 Initiate connection to projector.
1090 """1104 """
1091 log.debug('{ip}) connect_to_host(): Starting connection'.format(ip=self.ip))1105 log.debug('({ip}) connect_to_host(): Starting connection'.format(ip=self.ip))
1092 if self.state() == self.ConnectedState:1106 if QSOCKET_STATE[self.state()] == S_CONNECTED:
1093 log.warning('({ip}) connect_to_host(): Already connected - returning'.format(ip=self.ip))1107 log.warning('({ip}) connect_to_host(): Already connected - returning'.format(ip=self.ip))
1094 return1108 return
1109 self.error_status = S_OK
1095 self.change_status(S_CONNECTING)1110 self.change_status(S_CONNECTING)
1096 self.connectToHost(self.ip, self.port if isinstance(self.port, int) else int(self.port))1111 self.connectToHost(self.ip, self.port if isinstance(self.port, int) else int(self.port))
10971112
@@ -1100,12 +1115,13 @@
1100 """1115 """
1101 Close socket and cleanup.1116 Close socket and cleanup.
1102 """1117 """
1103 if abort or self.state() != self.ConnectedState:1118 if abort or QSOCKET_STATE[self.state()] != S_NOT_CONNECTED:
1104 if abort:1119 if abort:
1105 log.warning('({ip}) disconnect_from_host(): Aborting connection'.format(ip=self.ip))1120 log.warning('({ip}) disconnect_from_host(): Aborting connection'.format(ip=self.ip))
1121 self.abort()
1106 else:1122 else:
1107 log.warning('({ip}) disconnect_from_host(): Not connected'.format(ip=self.ip))1123 log.warning('({ip}) disconnect_from_host(): Not connected'.format(ip=self.ip))
1108 self.disconnectFromHost()1124 self.disconnectFromHost()
1109 try:1125 try:
1110 self.readyRead.disconnect(self.get_socket)1126 self.readyRead.disconnect(self.get_socket)
1111 except TypeError:1127 except TypeError:
@@ -1201,7 +1217,7 @@
1201 elif src not in self.source_available:1217 elif src not in self.source_available:
1202 return1218 return
1203 log.debug('({ip}) Setting input source to "{data}"'.format(ip=self.ip, data=src))1219 log.debug('({ip}) Setting input source to "{data}"'.format(ip=self.ip, data=src))
1204 self.send_command(cmd='INPT', opts=src)1220 self.send_command(cmd='INPT', opts=src, priority=True)
1205 self.poll_loop()1221 self.poll_loop()
12061222
1207 def set_power_on(self):1223 def set_power_on(self):
@@ -1209,7 +1225,7 @@
1209 Send command to turn power to on.1225 Send command to turn power to on.
1210 """1226 """
1211 log.debug('({ip}) Setting POWR to 1 (on)'.format(ip=self.ip))1227 log.debug('({ip}) Setting POWR to 1 (on)'.format(ip=self.ip))
1212 self.send_command(cmd='POWR', opts='1')1228 self.send_command(cmd='POWR', opts='1', priority=True)
1213 self.poll_loop()1229 self.poll_loop()
12141230
1215 def set_power_off(self):1231 def set_power_off(self):
@@ -1217,7 +1233,7 @@
1217 Send command to turn power to standby.1233 Send command to turn power to standby.
1218 """1234 """
1219 log.debug('({ip}) Setting POWR to 0 (standby)'.format(ip=self.ip))1235 log.debug('({ip}) Setting POWR to 0 (standby)'.format(ip=self.ip))
1220 self.send_command(cmd='POWR', opts='0')1236 self.send_command(cmd='POWR', opts='0', priority=True)
1221 self.poll_loop()1237 self.poll_loop()
12221238
1223 def set_shutter_closed(self):1239 def set_shutter_closed(self):
@@ -1225,7 +1241,7 @@
1225 Send command to set shutter to closed position.1241 Send command to set shutter to closed position.
1226 """1242 """
1227 log.debug('({ip}) Setting AVMT to 11 (shutter closed)'.format(ip=self.ip))1243 log.debug('({ip}) Setting AVMT to 11 (shutter closed)'.format(ip=self.ip))
1228 self.send_command(cmd='AVMT', opts='11')1244 self.send_command(cmd='AVMT', opts='11', priority=True)
1229 self.poll_loop()1245 self.poll_loop()
12301246
1231 def set_shutter_open(self):1247 def set_shutter_open(self):
@@ -1233,8 +1249,9 @@
1233 Send command to set shutter to open position.1249 Send command to set shutter to open position.
1234 """1250 """
1235 log.debug('({ip}) Setting AVMT to "10" (shutter open)'.format(ip=self.ip))1251 log.debug('({ip}) Setting AVMT to "10" (shutter open)'.format(ip=self.ip))
1236 self.send_command(cmd='AVMT', opts='10')1252 self.send_command(cmd='AVMT', opts='10', priority=True)
1237 self.poll_loop()1253 self.poll_loop()
1254 self.projectorUpdateIcons.emit()
12381255
1239 def receive_data_signal(self):1256 def receive_data_signal(self):
1240 """1257 """
12411258
=== modified file 'tests/functional/openlp_core/projectors/test_projector_constants.py'
--- tests/functional/openlp_core/projectors/test_projector_constants.py 2017-11-10 11:59:38 +0000
+++ tests/functional/openlp_core/projectors/test_projector_constants.py 2017-12-25 08:57:51 +0000
@@ -23,12 +23,51 @@
23Package to test the openlp.core.projectors.constants module.23Package to test the openlp.core.projectors.constants module.
24"""24"""
25from unittest import TestCase25from unittest import TestCase
26from openlp.core.projectors import constants
27from openlp.core.projectors.constants import STATUS_CODE, STATUS_MSG
2628
2729
28class TestProjectorConstants(TestCase):30class TestProjectorConstants(TestCase):
29 """31 """
30 Test specific functions in the projector constants module.32 Test specific functions in the projector constants module.
31 """33 """
34 def test_defined_codes_in_status_code(self):
35 """
36 Test defined status/error codes have equivalent strings
37 """
38 check = []
39 missing_str = []
40
41 # GIVEN: List of defined E_* and S_* items defined in constants
42 for item in constants.__dict__:
43 if item.startswith('E_') or item.startswith('S_'):
44 check.append(item)
45
46 # WHEN: Verify defined list against STATUS_STR
47 for item in check:
48 if constants.__dict__[item] not in STATUS_CODE:
49 missing_str.append(item)
50
51 # THEN: There should be no missing items
52 assert 0 == len(missing_str), 'Status string missing: {msg}'.format(msg=missing_str)
53
54 def test_status_code_in_status_message(self):
55 """
56 Test if entries in STATUS_CODE have equivalent descriptions in STATUS_MSG
57 """
58 missing_msg = []
59
60 # GIVEN: Test items
61 check = STATUS_CODE
62
63 # WHEN: Verify each entry in STATUS_MSG against STATUS_CODE
64 for item in check:
65 if item not in STATUS_MSG:
66 missing_msg.append(item)
67
68 # THEN: There should be no missing items
69 assert 0 == len(missing_msg), 'Status message missing: {msg}'.format(msg=missing_msg)
70
32 def test_build_pjlink_video_label(self):71 def test_build_pjlink_video_label(self):
33 """72 """
34 Test building PJLINK_DEFAULT_CODES dictionary73 Test building PJLINK_DEFAULT_CODES dictionary
3574
=== modified file 'tests/functional/openlp_core/projectors/test_projector_pjlink_base.py'
--- tests/functional/openlp_core/projectors/test_projector_pjlink_base.py 2017-12-04 00:24:47 +0000
+++ tests/functional/openlp_core/projectors/test_projector_pjlink_base.py 2017-12-25 08:57:51 +0000
@@ -25,7 +25,7 @@
25from unittest import TestCase25from unittest import TestCase
26from unittest.mock import call, patch, MagicMock26from unittest.mock import call, patch, MagicMock
2727
28from openlp.core.projectors.constants import E_PARAMETER, ERROR_STRING, S_ON, S_CONNECTED, S_QSOCKET_STATE28from openlp.core.projectors.constants import E_PARAMETER, STATUS_CODE, S_ON, S_CONNECTED, QSOCKET_STATE
29from openlp.core.projectors.db import Projector29from openlp.core.projectors.db import Projector
30from openlp.core.projectors.pjlink import PJLink30from openlp.core.projectors.pjlink import PJLink
3131
@@ -65,7 +65,7 @@
65 # as first parameter65 # as first parameter
66 mock_change_status.called_with(E_PARAMETER,66 mock_change_status.called_with(E_PARAMETER,
67 'change_status should have been called with "{}"'.format(67 'change_status should have been called with "{}"'.format(
68 ERROR_STRING[E_PARAMETER]))68 STATUS_CODE[E_PARAMETER]))
6969
70 @patch.object(pjlink_test, 'disconnect_from_host')70 @patch.object(pjlink_test, 'disconnect_from_host')
71 def test_socket_abort(self, mock_disconnect):71 def test_socket_abort(self, mock_disconnect):
@@ -104,7 +104,7 @@
104 """104 """
105 # GIVEN: Mocks and test data105 # GIVEN: Mocks and test data
106 mock_state = patch.object(self.pjlink_test, 'state').start()106 mock_state = patch.object(self.pjlink_test, 'state').start()
107 mock_state.return_value = S_QSOCKET_STATE['ConnectedState']107 mock_state.return_value = QSOCKET_STATE[S_CONNECTED]
108 mock_timer = patch.object(self.pjlink_test, 'timer').start()108 mock_timer = patch.object(self.pjlink_test, 'timer').start()
109 mock_timer.interval.return_value = 10109 mock_timer.interval.return_value = 10
110 mock_send_command = patch.object(self.pjlink_test, 'send_command').start()110 mock_send_command = patch.object(self.pjlink_test, 'send_command').start()
@@ -117,7 +117,6 @@
117 pjlink.manufacturer = None117 pjlink.manufacturer = None
118 pjlink.model = None118 pjlink.model = None
119 pjlink.pjlink_name = None119 pjlink.pjlink_name = None
120 pjlink.ConnectedState = S_CONNECTED
121 call_list = [120 call_list = [
122 call('POWR'),121 call('POWR'),
123 call('ERST'),122 call('ERST'),
124123
=== modified file 'tests/functional/openlp_core/projectors/test_projector_pjlink_cmd_routing.py'
--- tests/functional/openlp_core/projectors/test_projector_pjlink_cmd_routing.py 2017-12-09 11:17:05 +0000
+++ tests/functional/openlp_core/projectors/test_projector_pjlink_cmd_routing.py 2017-12-25 08:57:51 +0000
@@ -24,209 +24,222 @@
24"""24"""
2525
26from unittest import TestCase26from unittest import TestCase
27from unittest.mock import patch, MagicMock27from unittest.mock import MagicMock, call, patch
2828
29import openlp.core.projectors.pjlink29import openlp.core.projectors.pjlink
30from openlp.core.projectors.constants import PJLINK_ERRORS, \30from openlp.core.projectors.constants import PJLINK_ERRORS, PJLINK_PREFIX, STATUS_MSG, \
31 E_AUTHENTICATION, E_PARAMETER, E_PROJECTOR, E_UNAVAILABLE, E_UNDEFINED31 E_AUTHENTICATION, E_PARAMETER, E_PROJECTOR, E_UNAVAILABLE, E_UNDEFINED
32from openlp.core.projectors.db import Projector32from openlp.core.projectors.db import Projector
33from openlp.core.projectors.pjlink import PJLink33from openlp.core.projectors.pjlink import PJLink
3434
35'''35from tests.resources.projector.data import TEST1_DATA
36from openlp.core.projectors.constants import ERROR_STRING, PJLINK_ERST_DATA, PJLINK_ERST_STATUS, \
37 PJLINK_POWR_STATUS, PJLINK_VALID_CMD, E_WARN, E_ERROR, S_OFF, S_STANDBY, S_ON
38'''
39from tests.resources.projector.data import TEST_PIN, TEST1_DATA
40
41pjlink_test = PJLink(Projector(**TEST1_DATA), pin=TEST_PIN, no_poll=True)
42pjlink_test.ip = '127.0.0.1'
4336
4437
45class TestPJLinkRouting(TestCase):38class TestPJLinkRouting(TestCase):
46 """39 """
47 Tests for the PJLink module command routing40 Tests for the PJLink module command routing
48 """41 """
49 def setUp(self):42 def test_get_data_unknown_command(self):
50 '''43 """
51 TestPJLinkCommands part 2 initialization44 Test not a valid command
52 '''45 """
53 self.pjlink_test = PJLink(Projector(**TEST1_DATA), no_poll=True)46 # GIVEN: Test object
5447 log_warning_text = [call('(111.111.111.111) get_data(): Invalid packet - unknown command "UNK"')]
55 def tearDown(self):48 log_debug_text = [call('(111.111.111.111) get_data(ip="111.111.111.111" buffer="b\'%1UNK=Huh?\'"'),
56 '''49 call('(111.111.111.111) get_data(): Checking new data "%1UNK=Huh?"')]
57 TestPJLinkCommands part 2 cleanups50
58 '''51 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
59 self.pjlink_test = None52 patch.object(openlp.core.projectors.pjlink.PJLink, '_trash_buffer') as mock_buffer:
6053
61 @patch.object(openlp.core.projectors.pjlink, 'log')54 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
62 def test_process_command_call_clss(self, mock_log):55 pjlink.pjlink_functions = MagicMock()
56
57 # WHEN: get_data called with an unknown command
58 pjlink.get_data(buff='{prefix}1UNK=Huh?'.format(prefix=PJLINK_PREFIX).encode('utf-8'))
59
60 # THEN: Appropriate log entries should have been made and methods called/not called
61 mock_log.debug.assert_has_calls(log_debug_text)
62 mock_log.warning.assert_has_calls(log_warning_text)
63 self.assertFalse(pjlink.pjlink_functions.called, 'Should not have accessed pjlink_functions')
64 self.assertTrue(mock_buffer.called, 'Should have called _trash_buffer')
65
66 def test_process_command_call_clss(self):
63 """67 """
64 Test process_command calls proper function68 Test process_command calls proper function
65 """69 """
70 # GIVEN: Test object and mocks
71 log_debug_calls = [call('(111.111.111.111) Processing command "CLSS" with data "1"'),
72 call('(111.111.111.111) Calling function for CLSS')]
73
74 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
75 patch.object(openlp.core.projectors.pjlink.PJLink, 'process_clss') as mock_process_clss:
76
77 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
78
79 # WHEN: process_command is called with valid function and data
80 pjlink.process_command(cmd='CLSS', data='1')
81
82 # THEN: Appropriate log entries should have been made and methods called
83 mock_log.debug.assert_has_calls(log_debug_calls)
84 mock_process_clss.assert_called_once_with(data='1')
85
86 def test_process_command_erra(self):
87 """
88 Test ERRA - Authentication Error
89 """
66 # GIVEN: Test object90 # GIVEN: Test object
67 pjlink = pjlink_test91 log_error_calls = [call('(111.111.111.111) PJLINK: {msg}'.format(msg=STATUS_MSG[E_AUTHENTICATION]))]
68 log_text = '(127.0.0.1) Calling function for CLSS'92 log_debug_calls = [call('(111.111.111.111) Processing command "PJLINK" with data "ERRA"')]
69 mock_log.reset_mock()93
70 mock_process_clss = MagicMock()94 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
71 pjlink.pjlink_functions['CLSS'] = mock_process_clss95 patch.object(openlp.core.projectors.pjlink.PJLink, 'process_pjlink') as mock_process_pjlink, \
7296 patch.object(openlp.core.projectors.pjlink.PJLink, 'change_status') as mock_change_status, \
73 # WHEN: process_command is called with valid function and data97 patch.object(openlp.core.projectors.pjlink.PJLink, 'disconnect_from_host') as mock_disconnect, \
74 pjlink.process_command(cmd='CLSS', data='1')98 patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorAuthentication') as mock_authentication:
7599
76 # THEN: Process method should have been called properly100 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
77 mock_log.debug.assert_called_with(log_text)101
78 mock_process_clss.assert_called_with('1')102 # WHEN: process_command called with ERRA
79103 pjlink.process_command(cmd='PJLINK', data=PJLINK_ERRORS[E_AUTHENTICATION])
80 @patch.object(pjlink_test, 'change_status')104
81 @patch.object(openlp.core.projectors.pjlink, 'log')105 # THEN: Appropriate log entries should have been made and methods called/not called
82 def test_process_command_err1(self, mock_log, mock_change_status):106 mock_log.error.assert_has_calls(log_error_calls)
107 mock_log.debug.assert_has_calls(log_debug_calls)
108 self.assertTrue(mock_disconnect.called, 'disconnect_from_host should have been called')
109 mock_change_status.assert_called_once_with(status=E_AUTHENTICATION)
110 mock_authentication.emit.assert_called_once_with(pjlink.name)
111 mock_process_pjlink.assert_not_called()
112
113 def test_process_command_err1(self):
83 """114 """
84 Test ERR1 - Undefined projector function115 Test ERR1 - Undefined projector function
85 """116 """
86 # GIVEN: Test object117 # GIVEN: Test object
87 pjlink = pjlink_test118 log_error_text = [call('(111.111.111.111) CLSS: {msg}'.format(msg=STATUS_MSG[E_UNDEFINED]))]
88 log_text = '(127.0.0.1) Projector returned error "ERR1"'119 log_debug_text = [call('(111.111.111.111) Processing command "CLSS" with data "ERR1"'),
89 mock_change_status.reset_mock()120 call('(111.111.111.111) Calling function for CLSS')]
90 mock_log.reset_mock()121
91122 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
92 # WHEN: process_command called with ERR1123 patch.object(openlp.core.projectors.pjlink.PJLink, 'process_clss') as mock_process_clss:
93 pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_UNDEFINED])124
94125 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
95 # THEN: Error should be logged and status_change should be called126
96 mock_change_status.assert_called_once_with(E_UNDEFINED, 'Undefined Command: "CLSS"')127 # WHEN: process_command called with ERR1
97 mock_log.error.assert_called_with(log_text)128 pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_UNDEFINED])
98129
99 @patch.object(pjlink_test, 'change_status')130 # THEN: Appropriate log entries should have been made and methods called
100 @patch.object(openlp.core.projectors.pjlink, 'log')131 mock_log.error.assert_has_calls(log_error_text)
101 def test_process_command_err2(self, mock_log, mock_change_status):132 mock_log.debug.assert_has_calls(log_debug_text)
133 mock_process_clss.assert_called_once_with(data=PJLINK_ERRORS[E_UNDEFINED])
134
135 def test_process_command_err2(self):
102 """136 """
103 Test ERR2 - Parameter Error137 Test ERR2 - Parameter Error
104 """138 """
105 # GIVEN: Test object139 # GIVEN: Test object
106 pjlink = pjlink_test140 log_error_text = [call('(111.111.111.111) CLSS: {msg}'.format(msg=STATUS_MSG[E_PARAMETER]))]
107 log_text = '(127.0.0.1) Projector returned error "ERR2"'141 log_debug_text = [call('(111.111.111.111) Processing command "CLSS" with data "ERR2"'),
108 mock_change_status.reset_mock()142 call('(111.111.111.111) Calling function for CLSS')]
109 mock_log.reset_mock()143
110144 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
111 # WHEN: process_command called with ERR2145 patch.object(openlp.core.projectors.pjlink.PJLink, 'process_clss') as mock_process_clss:
112 pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_PARAMETER])146
113147 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
114 # THEN: Error should be logged and status_change should be called148
115 mock_change_status.assert_called_once_with(E_PARAMETER)149 # WHEN: process_command called with ERR2
116 mock_log.error.assert_called_with(log_text)150 pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_PARAMETER])
117151
118 @patch.object(pjlink_test, 'change_status')152 # THEN: Appropriate log entries should have been made and methods called/not called
119 @patch.object(openlp.core.projectors.pjlink, 'log')153 mock_log.error.assert_has_calls(log_error_text)
120 def test_process_command_err3(self, mock_log, mock_change_status):154 mock_log.debug.assert_has_calls(log_debug_text)
121 """155 mock_process_clss.assert_called_once_with(data=PJLINK_ERRORS[E_PARAMETER])
122 Test ERR3 - Unavailable error156
123 """157 def test_process_command_err3(self):
124 # GIVEN: Test object158 """
125 pjlink = pjlink_test159 Test ERR3 - Unavailable error
126 log_text = '(127.0.0.1) Projector returned error "ERR3"'160 """
127 mock_change_status.reset_mock()161 # GIVEN: Test object
128 mock_log.reset_mock()162 log_error_text = [call('(111.111.111.111) CLSS: {msg}'.format(msg=STATUS_MSG[E_UNAVAILABLE]))]
129163 log_debug_text = [call('(111.111.111.111) Processing command "CLSS" with data "ERR3"'),
130 # WHEN: process_command called with ERR3164 call('(111.111.111.111) Calling function for CLSS')]
131 pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_UNAVAILABLE])165
132166 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
133 # THEN: Error should be logged and status_change should be called167 patch.object(openlp.core.projectors.pjlink.PJLink, 'process_clss') as mock_process_clss:
134 mock_change_status.assert_called_once_with(E_UNAVAILABLE)168
135 mock_log.error.assert_called_with(log_text)169 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
136170
137 @patch.object(pjlink_test, 'change_status')171 # WHEN: process_command called with ERR3
138 @patch.object(openlp.core.projectors.pjlink, 'log')172 pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_UNAVAILABLE])
139 def test_process_command_err4(self, mock_log, mock_change_status):173
140 """174 # THEN: Appropriate log entries should have been made and methods called
141 Test ERR3 - Unavailable error175 mock_log.error.assert_has_calls(log_error_text)
142 """176 mock_log.debug.assert_has_calls(log_debug_text)
143 # GIVEN: Test object177 mock_process_clss.assert_called_once_with(data=PJLINK_ERRORS[E_UNAVAILABLE])
144 pjlink = pjlink_test178
145 log_text = '(127.0.0.1) Projector returned error "ERR4"'179 def test_process_command_err4(self):
146 mock_change_status.reset_mock()180 """
147 mock_log.reset_mock()181 Test ERR3 - Unavailable error
148182 """
149 # WHEN: process_command called with ERR3183 # GIVEN: Test object
150 pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_PROJECTOR])184 log_error_text = [call('(111.111.111.111) CLSS: {msg}'.format(msg=STATUS_MSG[E_PROJECTOR]))]
151185 log_debug_text = [call('(111.111.111.111) Processing command "CLSS" with data "ERR4"'),
152 # THEN: Error should be logged and status_change should be called186 call('(111.111.111.111) Calling function for CLSS')]
153 mock_change_status.assert_called_once_with(E_PROJECTOR)187
154 mock_log.error.assert_called_with(log_text)188 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
155189 patch.object(openlp.core.projectors.pjlink.PJLink, 'process_clss') as mock_process_clss:
156 @patch.object(pjlink_test, 'projectorAuthentication')190
157 @patch.object(pjlink_test, 'change_status')191 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
158 @patch.object(pjlink_test, 'disconnect_from_host')192
159 @patch.object(openlp.core.projectors.pjlink, 'log')193 # WHEN: process_command called with ERR4
160 def test_process_command_erra(self, mock_log, mock_disconnect, mock_change_status, mock_err_authenticate):194 pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_PROJECTOR])
161 """195
162 Test ERRA - Authentication Error196 # THEN: Appropriate log entries should have been made and methods called
163 """197 mock_log.error.assert_has_calls(log_error_text)
164 # GIVEN: Test object198 mock_log.debug.assert_has_calls(log_debug_text)
165 pjlink = pjlink_test199 mock_process_clss.assert_called_once_with(data=PJLINK_ERRORS[E_PROJECTOR])
166 log_text = '(127.0.0.1) Projector returned error "ERRA"'
167 mock_change_status.reset_mock()
168 mock_log.reset_mock()
169
170 # WHEN: process_command called with ERRA
171 pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_AUTHENTICATION])
172
173 # THEN: Error should be logged and several methods should be called
174 self.assertTrue(mock_disconnect.called, 'disconnect_from_host should have been called')
175 mock_change_status.assert_called_once_with(E_AUTHENTICATION)
176 mock_log.error.assert_called_with(log_text)
177200
178 def test_process_command_future(self):201 def test_process_command_future(self):
179 """202 """
180 Test command valid but no method to process yet203 Test command valid but no method to process yet
181 """204 """
182 # GIVEN: Initial mocks and data
183 mock_log = patch.object(openlp.core.projectors.pjlink, 'log').start()
184 mock_functions = patch.object(self.pjlink_test, 'pjlink_functions').start()
185 mock_functions.return_value = []
186
187 pjlink = self.pjlink_test
188 log_text = '(111.111.111.111) Unable to process command="CLSS" (Future option?)'
189
190 # WHEN: process_command called with an unknown command
191 pjlink.process_command(cmd='CLSS', data='DONT CARE')
192
193 # THEN: Error should be logged and no command called
194 self.assertFalse(mock_functions.called, 'Should not have gotten to the end of the method')
195 mock_log.warning.assert_called_once_with(log_text)
196
197 @patch.object(pjlink_test, 'pjlink_functions')
198 @patch.object(openlp.core.projectors.pjlink, 'log')
199 def test_process_command_invalid(self, mock_log, mock_functions):
200 """
201 Test not a valid command
202 """
203 # GIVEN: Test object205 # GIVEN: Test object
204 pjlink = pjlink_test206 log_warning_text = [call('(111.111.111.111) Unable to process command="CLSS" (Future option?)')]
205 mock_functions.reset_mock()207 log_debug_text = [call('(111.111.111.111) Processing command "CLSS" with data "Huh?"')]
206 mock_log.reset_mock()208
207209 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
208 # WHEN: process_command called with an unknown command210 patch.object(openlp.core.projectors.pjlink.PJLink, 'process_clss') as mock_process_clss:
209 pjlink.process_command(cmd='Unknown', data='Dont Care')211
210 log_text = '(127.0.0.1) Ignoring command="Unknown" (Invalid/Unknown)'212 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
211213 pjlink.pjlink_functions = MagicMock()
212 # THEN: Error should be logged and no command called214
213 self.assertFalse(mock_functions.called, 'Should not have gotten to the end of the method')215 # WHEN: Processing a possible future command
214 mock_log.error.assert_called_once_with(log_text)216 pjlink.process_command(cmd='CLSS', data="Huh?")
217
218 # THEN: Appropriate log entries should have been made and methods called/not called
219 mock_log.debug.assert_has_calls(log_debug_text)
220 mock_log.warning.assert_has_calls(log_warning_text)
221 self.assertFalse(pjlink.pjlink_functions.called, 'Should not have accessed pjlink_functions')
222 self.assertFalse(mock_process_clss.called, 'Should not have called process_clss')
215223
216 def test_process_command_ok(self):224 def test_process_command_ok(self):
217 """225 """
218 Test command returned success226 Test command returned success
219 """227 """
220 # GIVEN: Initial mocks and data228 # GIVEN: Initial mocks and data
221 mock_log = patch.object(openlp.core.projectors.pjlink, 'log').start()229 # GIVEN: Test object and mocks
222 mock_send_command = patch.object(self.pjlink_test, 'send_command').start()230 log_debug_calls = [call('(111.111.111.111) Processing command "CLSS" with data "OK"'),
223231 call('(111.111.111.111) Command "CLSS" returned OK')]
224 pjlink = self.pjlink_test232
225 log_text = '(111.111.111.111) Command "POWR" returned OK'233 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
226234 patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command, \
227 # WHEN: process_command called with a command that returns OK235 patch.object(openlp.core.projectors.pjlink.PJLink, 'process_clss') as mock_process_clss:
228 pjlink.process_command(cmd='POWR', data='OK')236
229237 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
230 # THEN: Appropriate calls should have been made238
231 mock_log.debug.assert_called_with(log_text)239 # WHEN: process_command is called with valid function and data
232 mock_send_command.assert_called_once_with(cmd='POWR')240 pjlink.process_command(cmd='CLSS', data='OK')
241
242 # THEN: Appropriate log entries should have been made and methods called
243 mock_log.debug.assert_has_calls(log_debug_calls)
244 mock_send_command.assert_called_once_with(cmd='CLSS')
245 mock_process_clss.assert_not_called()
233246
=== modified file 'tests/functional/openlp_core/projectors/test_projector_pjlink_commands_01.py'
--- tests/functional/openlp_core/projectors/test_projector_pjlink_commands_01.py 2017-12-09 11:17:05 +0000
+++ tests/functional/openlp_core/projectors/test_projector_pjlink_commands_01.py 2017-12-25 08:57:51 +0000
@@ -23,372 +23,402 @@
23Package to test the openlp.core.projectors.pjlink commands package.23Package to test the openlp.core.projectors.pjlink commands package.
24"""24"""
25from unittest import TestCase25from unittest import TestCase
26from unittest.mock import patch26from unittest.mock import call, patch
2727
28import openlp.core.projectors.pjlink28import openlp.core.projectors.pjlink
29from openlp.core.projectors.constants import ERROR_STRING, PJLINK_ERST_DATA, PJLINK_ERST_STATUS, \29from openlp.core.projectors.constants import PJLINK_ERST_DATA, PJLINK_ERST_STATUS, PJLINK_POWR_STATUS, \
30 PJLINK_POWR_STATUS, \30 STATUS_CODE, STATUS_MSG, E_ERROR, E_NOT_CONNECTED, E_UNKNOWN_SOCKET_ERROR, E_WARN, \
31 E_ERROR, E_NOT_CONNECTED, E_SOCKET_ADDRESS_NOT_AVAILABLE, E_UNKNOWN_SOCKET_ERROR, E_WARN, \31 S_CONNECTED, S_CONNECTING, S_OFF, S_OK, S_ON, S_NOT_CONNECTED, S_STANDBY
32 S_CONNECTED, S_OFF, S_ON, S_NOT_CONNECTED, S_CONNECTING, S_STANDBY
33from openlp.core.projectors.db import Projector32from openlp.core.projectors.db import Projector
34from openlp.core.projectors.pjlink import PJLink33from openlp.core.projectors.pjlink import PJLink
3534
36from tests.resources.projector.data import TEST_PIN, TEST1_DATA35from tests.resources.projector.data import TEST1_DATA
37
38pjlink_test = PJLink(Projector(**TEST1_DATA), pin=TEST_PIN, no_poll=True)
39pjlink_test.ip = '127.0.0.1'
40
41# Create a list of ERST positional data so we don't have to redo the same buildup multiple times
42PJLINK_ERST_POSITIONS = []
43for pos in range(0, len(PJLINK_ERST_DATA)):
44 if pos in PJLINK_ERST_DATA:
45 PJLINK_ERST_POSITIONS.append(PJLINK_ERST_DATA[pos])
4636
4737
48class TestPJLinkCommands(TestCase):38class TestPJLinkCommands(TestCase):
49 """39 """
50 Tests for the PJLinkCommands class part 140 Tests for the PJLinkCommands class part 1
51 """41 """
52 @patch.object(pjlink_test, 'changeStatus')42 def test_projector_change_status_unknown_socket_error(self):
53 @patch.object(openlp.core.projectors.pjlink, 'log')
54 def test_projector_change_status_connection_error(self, mock_log, mock_change_status):
55 """43 """
56 Test change_status with connection error44 Test change_status with connection error
57 """45 """
58 # GIVEN: Test object46 log_debug_calls = [
59 pjlink = pjlink_test47 call('(111.111.111.111) Changing status to '
60 pjlink.projector_status = 048 '{status} "{msg}"'.format(status=STATUS_CODE[E_UNKNOWN_SOCKET_ERROR],
61 pjlink.status_connect = 049 msg=STATUS_MSG[E_UNKNOWN_SOCKET_ERROR])),
62 test_code = E_UNKNOWN_SOCKET_ERROR50 call('(111.111.111.111) status_connect: '
63 mock_change_status.reset_mock()51 '{code}: "{msg}"'.format(code=STATUS_CODE[E_NOT_CONNECTED],
64 mock_log.reset_mock()52 msg=STATUS_MSG[E_NOT_CONNECTED])),
6553 call('(111.111.111.111) projector_status: '
66 # WHEN: change_status called with unknown socket error54 '{code}: "{msg}"'.format(code=STATUS_CODE[S_OK],
67 pjlink.change_status(status=test_code, msg=None)55 msg=STATUS_MSG[S_OK])),
6856 call('(111.111.111.111) error_status: '
69 # THEN: Proper settings should change and signals sent57 '{code}: "{msg}"'.format(code=STATUS_CODE[E_UNKNOWN_SOCKET_ERROR],
70 self.assertEqual(pjlink.projector_status, E_NOT_CONNECTED, 'Projector status should be NOT CONNECTED')58 msg=STATUS_MSG[E_UNKNOWN_SOCKET_ERROR]))]
71 self.assertEqual(pjlink.status_connect, E_NOT_CONNECTED, 'Status connect should be NOT CONNECTED')59
72 mock_change_status.emit.assert_called_once_with(pjlink.ip, E_UNKNOWN_SOCKET_ERROR,60 # GIVEN: Test object and mocks
73 'An unidentified error occurred')61 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
74 self.assertEqual(mock_log.debug.call_count, 3, 'Debug log should have been called 3 times')62 patch.object(openlp.core.projectors.pjlink.PJLink, 'changeStatus') as mock_changeStatus, \
7563 patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons:
76 @patch.object(pjlink_test, 'changeStatus')64
77 @patch.object(openlp.core.projectors.pjlink, 'log')65 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
78 def test_projector_change_status_connection_status_connecting(self, mock_log, mock_change_status):66 pjlink.projector_status = 0
79 """67 pjlink.status_connect = 0
80 Test change_status with connection status68
81 """69 # WHEN: change_status called with unknown socket error
82 # GIVEN: Test object70 pjlink.change_status(status=E_UNKNOWN_SOCKET_ERROR)
83 pjlink = pjlink_test71
84 pjlink.projector_status = 072 # THEN: Proper settings should change and signals sent
85 pjlink.status_connect = 073 mock_log.debug.assert_has_calls(log_debug_calls)
86 test_code = S_CONNECTING74 self.assertEqual(pjlink.projector_status, S_OK, 'Projector status should not have changed')
87 mock_change_status.reset_mock()75 self.assertEqual(pjlink.status_connect, E_NOT_CONNECTED,
88 mock_log.reset_mock()76 'Status connect should be NOT CONNECTED')
8977 self.assertTrue(mock_UpdateIcons.emit.called, 'Should have called UpdateIcons')
90 # WHEN: change_status called with unknown socket error78 mock_changeStatus.emit.assert_called_once_with(pjlink.ip, E_UNKNOWN_SOCKET_ERROR,
91 pjlink.change_status(status=test_code, msg=None)79 STATUS_MSG[E_UNKNOWN_SOCKET_ERROR])
9280
93 # THEN: Proper settings should change and signals sent81 def test_projector_change_status_connection_status_connecting(self):
94 self.assertEqual(pjlink.projector_status, S_NOT_CONNECTED, 'Projector status should be NOT CONNECTED')82 """
95 self.assertEqual(pjlink.status_connect, S_CONNECTING, 'Status connect should be CONNECTING')83 Test change_status with connecting status
96 mock_change_status.emit.assert_called_once_with(pjlink.ip, S_CONNECTING, 'Connecting')84 """
97 self.assertEqual(mock_log.debug.call_count, 3, 'Debug log should have been called 3 times')85 log_debug_calls = [
9886 call('(111.111.111.111) Changing status to '
99 @patch.object(pjlink_test, 'changeStatus')87 '{status} "{msg}"'.format(status=STATUS_CODE[S_CONNECTING],
100 @patch.object(openlp.core.projectors.pjlink, 'log')88 msg=STATUS_MSG[S_CONNECTING])),
101 def test_projector_change_status_connection_status_connected(self, mock_log, mock_change_status):89 call('(111.111.111.111) status_connect: '
102 """90 '{code}: "{msg}"'.format(code=STATUS_CODE[S_CONNECTING],
103 Test change_status with connection status91 msg=STATUS_MSG[S_CONNECTING])),
104 """92 call('(111.111.111.111) projector_status: '
105 # GIVEN: Test object93 '{code}: "{msg}"'.format(code=STATUS_CODE[S_OK],
106 pjlink = pjlink_test94 msg=STATUS_MSG[S_OK])),
107 pjlink.projector_status = 095 call('(111.111.111.111) error_status: '
108 pjlink.status_connect = 096 '{code}: "{msg}"'.format(code=STATUS_CODE[S_OK],
109 test_code = S_ON97 msg=STATUS_MSG[S_OK]))]
110 mock_change_status.reset_mock()98
111 mock_log.reset_mock()99 # GIVEN: Test object and mocks
112100 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
113 # WHEN: change_status called with unknown socket error101 patch.object(openlp.core.projectors.pjlink.PJLink, 'changeStatus') as mock_changeStatus, \
114 pjlink.change_status(status=test_code, msg=None)102 patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons:
115103
116 # THEN: Proper settings should change and signals sent104 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
117 self.assertEqual(pjlink.projector_status, S_ON, 'Projector status should be ON')105 pjlink.projector_status = 0
118 self.assertEqual(pjlink.status_connect, S_CONNECTED, 'Status connect should be CONNECTED')106 pjlink.status_connect = 0
119 mock_change_status.emit.assert_called_once_with(pjlink.ip, S_ON, 'Power is on')107
120 self.assertEqual(mock_log.debug.call_count, 3, 'Debug log should have been called 3 times')108 # WHEN: change_status called with CONNECTING
121109 pjlink.change_status(status=S_CONNECTING)
122 @patch.object(pjlink_test, 'changeStatus')110
123 @patch.object(openlp.core.projectors.pjlink, 'log')111 # THEN: Proper settings should change and signals sent
124 def test_projector_change_status_connection_status_with_message(self, mock_log, mock_change_status):112 mock_log.debug.assert_has_calls(log_debug_calls)
125 """113 self.assertEqual(pjlink.projector_status, S_OK, 'Projector status should not have changed')
126 Test change_status with connection status114 self.assertEqual(pjlink.status_connect, S_CONNECTING, 'Status connect should be CONNECTING')
127 """115 self.assertTrue(mock_UpdateIcons.emit.called, 'Should have called UpdateIcons')
128 # GIVEN: Test object116 mock_changeStatus.emit.assert_called_once_with(pjlink.ip, S_CONNECTING, STATUS_MSG[S_CONNECTING])
129 pjlink = pjlink_test117
130 pjlink.projector_status = 0118 def test_projector_change_status_connection_status_connected(self):
131 pjlink.status_connect = 0119 """
120 Test change_status with connected status
121 """
122 log_debug_calls = [
123 call('(111.111.111.111) Changing status to '
124 '{status} "{msg}"'.format(status=STATUS_CODE[S_CONNECTED],
125 msg=STATUS_MSG[S_CONNECTED])),
126 call('(111.111.111.111) status_connect: '
127 '{code}: "{msg}"'.format(code=STATUS_CODE[S_CONNECTED],
128 msg=STATUS_MSG[S_CONNECTED])),
129 call('(111.111.111.111) projector_status: '
130 '{code}: "{msg}"'.format(code=STATUS_CODE[S_OK],
131 msg=STATUS_MSG[S_OK])),
132 call('(111.111.111.111) error_status: '
133 '{code}: "{msg}"'.format(code=STATUS_CODE[S_OK],
134 msg=STATUS_MSG[S_OK]))]
135
136 # GIVEN: Test object and mocks
137 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
138 patch.object(openlp.core.projectors.pjlink.PJLink, 'changeStatus') as mock_changeStatus:
139
140 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
141 pjlink.projector_status = 0
142 pjlink.status_connect = 0
143
144 # WHEN: change_status called with CONNECTED
145 pjlink.change_status(status=S_CONNECTED)
146
147 # THEN: Proper settings should change and signals sent
148 mock_log.debug.assert_has_calls(log_debug_calls)
149 self.assertEqual(pjlink.projector_status, S_OK, 'Projector status should not have changed')
150 self.assertEqual(pjlink.status_connect, S_CONNECTED, 'Status connect should be CONNECTED')
151 mock_changeStatus.emit.assert_called_once_with(pjlink.ip, S_CONNECTED, 'Connected')
152
153 def test_projector_change_status_connection_status_with_message(self):
154 """
155 Test change_status with connection status
156 """
132 test_message = 'Different Status Message than default'157 test_message = 'Different Status Message than default'
133 test_code = S_ON158 log_debug_calls = [
134 mock_change_status.reset_mock()159 call('(111.111.111.111) Changing status to {status} "{msg}"'.format(status=STATUS_CODE[S_ON],
135 mock_log.reset_mock()160 msg=test_message)),
136161 call('(111.111.111.111) status_connect: {code}: "{msg}"'.format(code=STATUS_CODE[S_OK],
137 # WHEN: change_status called with unknown socket error162 msg=test_message)),
138 pjlink.change_status(status=test_code, msg=test_message)163 call('(111.111.111.111) projector_status: {code}: "{msg}"'.format(code=STATUS_CODE[S_ON],
139164 msg=test_message)),
140 # THEN: Proper settings should change and signals sent165 call('(111.111.111.111) error_status: {code}: "{msg}"'.format(code=STATUS_CODE[S_OK],
141 self.assertEqual(pjlink.projector_status, S_ON, 'Projector status should be ON')166 msg=test_message))]
142 self.assertEqual(pjlink.status_connect, S_CONNECTED, 'Status connect should be CONNECTED')167
143 mock_change_status.emit.assert_called_once_with(pjlink.ip, S_ON, test_message)168 # GIVEN: Test object and mocks
144 self.assertEqual(mock_log.debug.call_count, 3, 'Debug log should have been called 3 times')169 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
145170 patch.object(openlp.core.projectors.pjlink.PJLink, 'changeStatus') as mock_changeStatus:
146 @patch.object(pjlink_test, 'send_command')171
147 @patch.object(openlp.core.projectors.pjlink, 'log')172 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
148 def test_projector_get_av_mute_status(self, mock_log, mock_send_command):173 pjlink.projector_status = 0
174 pjlink.status_connect = 0
175
176 # WHEN: change_status called with projector ON status
177 pjlink.change_status(status=S_ON, msg=test_message)
178
179 # THEN: Proper settings should change and signals sent
180 mock_log.debug.assert_has_calls(log_debug_calls)
181 self.assertEqual(pjlink.projector_status, S_ON, 'Projector status should be ON')
182 self.assertEqual(pjlink.status_connect, S_OK, 'Status connect should not have changed')
183 mock_changeStatus.emit.assert_called_once_with(pjlink.ip, S_ON, test_message)
184
185 def test_projector_get_av_mute_status(self):
149 """186 """
150 Test sending command to retrieve shutter/audio state187 Test sending command to retrieve shutter/audio state
151 """188 """
152 # GIVEN: Test object
153 pjlink = pjlink_test
154 mock_log.reset_mock()
155 mock_send_command.reset_mock()
156 test_data = 'AVMT'189 test_data = 'AVMT'
157 test_log = '(127.0.0.1) Sending AVMT command'190 log_debug_calls = [call('(111.111.111.111) reset_information() connect status is '
158191 '{state}'.format(state=STATUS_CODE[S_NOT_CONNECTED])),
159 # WHEN: get_av_mute_status is called192 call('(111.111.111.111) Sending {cmd} command'.format(cmd=test_data))]
160 pjlink.get_av_mute_status()193
161194 # GIVEN: Test object and mocks
162 # THEN: log data and send_command should have been called195 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
163 mock_log.debug.assert_called_once_with(test_log)196 patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command:
164 mock_send_command.assert_called_once_with(cmd=test_data)197 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
165198
166 @patch.object(pjlink_test, 'send_command')199 # WHEN: get_av_mute_status is called
167 @patch.object(openlp.core.projectors.pjlink, 'log')200 pjlink.get_av_mute_status()
168 def test_projector_get_available_inputs(self, mock_log, mock_send_command):201
202 # THEN: log data and send_command should have been called
203 mock_log.debug.assert_has_calls(log_debug_calls)
204 mock_send_command.assert_called_once_with(cmd=test_data)
205
206 def test_projector_get_available_inputs(self):
169 """207 """
170 Test sending command to retrieve avaliable inputs208 Test sending command to retrieve avaliable inputs
171 """209 """
172 # GIVEN: Test object
173 pjlink = pjlink_test
174 mock_log.reset_mock()
175 mock_send_command.reset_mock()
176 test_data = 'INST'210 test_data = 'INST'
177 test_log = '(127.0.0.1) Sending INST command'211 log_debug_calls = [call('(111.111.111.111) reset_information() connect status is '
178212 '{state}'.format(state=STATUS_CODE[S_NOT_CONNECTED])),
179 # WHEN: get_available_inputs is called213 call('(111.111.111.111) Sending {cmd} command'.format(cmd=test_data))]
180 pjlink.get_available_inputs()214
181215 # GIVEN: Test object and mocks
182 # THEN: log data and send_command should have been called216 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
183 mock_log.debug.assert_called_once_with(test_log)217 patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command:
184 mock_send_command.assert_called_once_with(cmd=test_data)218 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
185219
186 @patch.object(pjlink_test, 'send_command')220 # WHEN: get_available_inputs is called
187 @patch.object(openlp.core.projectors.pjlink, 'log')221 pjlink.get_available_inputs()
188 def test_projector_get_error_status(self, mock_log, mock_send_command):222
223 # THEN: log data and send_command should have been called
224 mock_log.debug.assert_has_calls(log_debug_calls)
225 mock_send_command.assert_called_once_with(cmd=test_data)
226
227 def test_projector_get_error_status(self):
189 """228 """
190 Test sending command to retrieve projector error status229 Test sending command to retrieve projector error status
191 """230 """
192 # GIVEN: Test object
193 pjlink = pjlink_test
194 mock_log.reset_mock()
195 mock_send_command.reset_mock()
196 test_data = 'ERST'231 test_data = 'ERST'
197 test_log = '(127.0.0.1) Sending ERST command'232 log_debug_calls = [call('(111.111.111.111) reset_information() connect status is '
198233 '{state}'.format(state=STATUS_CODE[S_NOT_CONNECTED])),
199 # WHEN: get_error_status is called234 call('(111.111.111.111) Sending {cmd} command'.format(cmd=test_data))]
200 pjlink.get_error_status()235 # GIVEN: Test object and mocks
201236 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
202 # THEN: log data and send_command should have been called237 patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command:
203 mock_log.debug.assert_called_once_with(test_log)238 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
204 mock_send_command.assert_called_once_with(cmd=test_data)239
205240 # WHEN: get_error_status is called
206 @patch.object(pjlink_test, 'send_command')241 pjlink.get_error_status()
207 @patch.object(openlp.core.projectors.pjlink, 'log')242
208 def test_projector_get_input_source(self, mock_log, mock_send_command):243 # THEN: log data and send_command should have been called
244 mock_log.debug.assert_has_calls(log_debug_calls)
245 mock_send_command.assert_called_once_with(cmd=test_data)
246
247 def test_projector_get_input_source(self):
209 """248 """
210 Test sending command to retrieve current input249 Test sending command to retrieve current input
211 """250 """
212 # GIVEN: Test object
213 pjlink = pjlink_test
214 mock_log.reset_mock()
215 mock_send_command.reset_mock()
216 test_data = 'INPT'251 test_data = 'INPT'
217 test_log = '(127.0.0.1) Sending INPT command'252 log_debug_calls = [call('(111.111.111.111) reset_information() connect status is '
218253 '{state}'.format(state=STATUS_CODE[S_NOT_CONNECTED])),
219 # WHEN: get_input_source is called254 call('(111.111.111.111) Sending {cmd} command'.format(cmd=test_data))]
220 pjlink.get_input_source()255
221256 # GIVEN: Test object and mocks
222 # THEN: log data and send_command should have been called257 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
223 mock_log.debug.assert_called_once_with(test_log)258 patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command:
224 mock_send_command.assert_called_once_with(cmd=test_data)259 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
225260
226 @patch.object(pjlink_test, 'send_command')261 # WHEN: get_input_source is called
227 @patch.object(openlp.core.projectors.pjlink, 'log')262 pjlink.get_input_source()
228 def test_projector_get_lamp_status(self, mock_log, mock_send_command):263
264 # THEN: log data and send_command should have been called
265 mock_log.debug.assert_has_calls(log_debug_calls)
266 mock_send_command.assert_called_once_with(cmd=test_data)
267
268 def test_projector_get_lamp_status(self):
229 """269 """
230 Test sending command to retrieve lamp(s) status270 Test sending command to retrieve lamp(s) status
231 """271 """
232 # GIVEN: Test object
233 pjlink = pjlink_test
234 mock_log.reset_mock()
235 mock_send_command.reset_mock()
236 test_data = 'LAMP'272 test_data = 'LAMP'
237 test_log = '(127.0.0.1) Sending LAMP command'273 log_debug_calls = [call('(111.111.111.111) reset_information() connect status is '
238274 '{state}'.format(state=STATUS_CODE[S_NOT_CONNECTED])),
239 # WHEN: get_lamp_status is called275 call('(111.111.111.111) Sending {cmd} command'.format(cmd=test_data))]
240 pjlink.get_lamp_status()276
241277 # GIVEN: Test object and mocks
242 # THEN: log data and send_command should have been called278 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
243 mock_log.debug.assert_called_once_with(test_log)279 patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command:
244 mock_send_command.assert_called_once_with(cmd=test_data)280 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
245281
246 @patch.object(pjlink_test, 'send_command')282 # WHEN: get_input_source is called
247 @patch.object(openlp.core.projectors.pjlink, 'log')283 pjlink.get_lamp_status()
248 def test_projector_get_manufacturer(self, mock_log, mock_send_command):284
285 # THEN: log data and send_command should have been called
286 mock_log.debug.assert_has_calls(log_debug_calls)
287 mock_send_command.assert_called_once_with(cmd=test_data)
288
289 def test_projector_get_manufacturer(self):
249 """290 """
250 Test sending command to retrieve manufacturer name291 Test sending command to retrieve manufacturer name
251 """292 """
252 # GIVEN: Test object
253 pjlink = pjlink_test
254 mock_log.reset_mock()
255 mock_send_command.reset_mock()
256 test_data = 'INF1'293 test_data = 'INF1'
257 test_log = '(127.0.0.1) Sending INF1 command'294 log_debug_calls = [call('(111.111.111.111) reset_information() connect status is '
258295 '{state}'.format(state=STATUS_CODE[S_NOT_CONNECTED])),
259 # WHEN: get_manufacturer is called296 call('(111.111.111.111) Sending {cmd} command'.format(cmd=test_data))]
260 pjlink.get_manufacturer()297
261298 # GIVEN: Test object and mocks
262 # THEN: log data and send_command should have been called299 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
263 mock_log.debug.assert_called_once_with(test_log)300 patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command:
264 mock_send_command.assert_called_once_with(cmd=test_data)301 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
265302
266 @patch.object(pjlink_test, 'send_command')303 # WHEN: get_input_source is called
267 @patch.object(openlp.core.projectors.pjlink, 'log')304 pjlink.get_manufacturer()
268 def test_projector_get_model(self, mock_log, mock_send_command):305
306 # THEN: log data and send_command should have been called
307 mock_log.debug.assert_has_calls(log_debug_calls)
308 mock_send_command.assert_called_once_with(cmd=test_data)
309
310 def test_projector_get_model(self):
269 """311 """
270 Test sending command to get model information312 Test sending command to get model information
271 """313 """
272 # GIVEN: Test object
273 pjlink = pjlink_test
274 mock_log.reset_mock()
275 mock_send_command.reset_mock()
276 test_data = 'INF2'314 test_data = 'INF2'
277 test_log = '(127.0.0.1) Sending INF2 command'315 log_debug_calls = [call('(111.111.111.111) reset_information() connect status is '
278316 '{state}'.format(state=STATUS_CODE[S_NOT_CONNECTED])),
279 # WHEN: get_model is called317 call('(111.111.111.111) Sending {cmd} command'.format(cmd=test_data))]
280 pjlink.get_model()318
281319 # GIVEN: Test object and mocks
282 # THEN: log data and send_command should have been called320 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
283 mock_log.debug.assert_called_once_with(test_log)321 patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command:
284 mock_send_command.assert_called_once_with(cmd=test_data)322 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
285323
286 @patch.object(pjlink_test, 'send_command')324 # WHEN: get_input_source is called
287 @patch.object(openlp.core.projectors.pjlink, 'log')325 pjlink.get_model()
288 def test_projector_get_name(self, mock_log, mock_send_command):326
327 # THEN: log data and send_command should have been called
328 mock_log.debug.assert_has_calls(log_debug_calls)
329 mock_send_command.assert_called_once_with(cmd=test_data)
330
331 def test_projector_get_name(self):
289 """332 """
290 Test sending command to get user-assigned name333 Test sending command to get user-assigned name
291 """334 """
292 # GIVEN: Test object
293 pjlink = pjlink_test
294 mock_log.reset_mock()
295 mock_send_command.reset_mock()
296 test_data = 'NAME'335 test_data = 'NAME'
297 test_log = '(127.0.0.1) Sending NAME command'336 log_debug_calls = [call('(111.111.111.111) reset_information() connect status is '
298337 '{state}'.format(state=STATUS_CODE[S_NOT_CONNECTED])),
299 # WHEN: get_name is called338 call('(111.111.111.111) Sending {cmd} command'.format(cmd=test_data))]
300 pjlink.get_name()339
301340 # GIVEN: Test object and mocks
302 # THEN: log data and send_command should have been called341 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
303 mock_log.debug.assert_called_once_with(test_log)342 patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command:
304 mock_send_command.assert_called_once_with(cmd=test_data)343 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
305344
306 @patch.object(pjlink_test, 'send_command')345 # WHEN: get_input_source is called
307 @patch.object(openlp.core.projectors.pjlink, 'log')346 pjlink.get_name()
308 def test_projector_get_other_info(self, mock_log, mock_send_command):347
348 # THEN: log data and send_command should have been called
349 mock_log.debug.assert_has_calls(log_debug_calls)
350 mock_send_command.assert_called_once_with(cmd=test_data)
351
352 def test_projector_get_other_info(self):
309 """353 """
310 Test sending command to retrieve other information354 Test sending command to retrieve other information
311 """355 """
312 # GIVEN: Test object
313 pjlink = pjlink_test
314 mock_log.reset_mock()
315 mock_send_command.reset_mock()
316 test_data = 'INFO'356 test_data = 'INFO'
317 test_log = '(127.0.0.1) Sending INFO command'357 log_debug_calls = [call('(111.111.111.111) reset_information() connect status is '
318358 '{state}'.format(state=STATUS_CODE[S_NOT_CONNECTED])),
319 # WHEN: get_other_info is called359 call('(111.111.111.111) Sending {cmd} command'.format(cmd=test_data))]
320 pjlink.get_other_info()360
321361 # GIVEN: Test object and mocks
322 # THEN: log data and send_command should have been called362 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
323 mock_log.debug.assert_called_once_with(test_log)363 patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command:
324 mock_send_command.assert_called_once_with(cmd=test_data)364 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
325365
326 @patch.object(pjlink_test, 'send_command')366 # WHEN: get_input_source is called
327 @patch.object(openlp.core.projectors.pjlink, 'log')367 pjlink.get_other_info()
328 def test_projector_get_power_status(self, mock_log, mock_send_command):368
369 # THEN: log data and send_command should have been called
370 mock_log.debug.assert_has_calls(log_debug_calls)
371 mock_send_command.assert_called_once_with(cmd=test_data)
372
373 def test_projector_get_power_status(self):
329 """374 """
330 Test sending command to retrieve current power state375 Test sending command to retrieve current power state
331 """376 """
332 # GIVEN: Test object
333 pjlink = pjlink_test
334 mock_log.reset_mock()
335 mock_send_command.reset_mock()
336 test_data = 'POWR'377 test_data = 'POWR'
337 test_log = '(127.0.0.1) Sending POWR command'378 log_debug_calls = [call('(111.111.111.111) reset_information() connect status is '
338379 '{state}'.format(state=STATUS_CODE[S_NOT_CONNECTED])),
339 # WHEN: get_power_status called380 call('(111.111.111.111) Sending {cmd} command'.format(cmd=test_data))]
340 pjlink.get_power_status()381
341382 # GIVEN: Test object and mocks
342 # THEN: log data and send_command should have been called383 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
343 mock_log.debug.assert_called_once_with(test_log)384 patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command:
344 mock_send_command.assert_called_once_with(cmd=test_data)385 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
345386
346 def test_projector_get_status_error(self):387 # WHEN: get_input_source is called
347 """388 pjlink.get_power_status()
348 Test to check returned information for error code389
349 """390 # THEN: log data and send_command should have been called
350 # GIVEN: Test object391 mock_log.debug.assert_has_calls(log_debug_calls)
351 pjlink = pjlink_test392 mock_send_command.assert_called_once_with(cmd=test_data)
352 test_string = 'E_SOCKET_ADDRESS_NOT_AVAILABLE'
353 test_message = 'The address specified to socket.bind() does not belong to the host'
354
355 # WHEN: get_status called
356 string, message = pjlink._get_status(status=E_SOCKET_ADDRESS_NOT_AVAILABLE)
357
358 # THEN: Proper strings should have been returned
359 self.assertEqual(string, test_string, 'Code as string should have been returned')
360 self.assertEqual(message, test_message, 'Description of code should have been returned')
361393
362 def test_projector_get_status_invalid(self):394 def test_projector_get_status_invalid(self):
363 """395 """
364 Test to check returned information for error code396 Test to check returned information for error code
365 """397 """
366 # GIVEN: Test object398 # GIVEN: Test object
367 pjlink = pjlink_test399 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
368 test_string = 'Test string since get_status will only work with int'400 test_string = 'NaN test'
369 test_message = 'Invalid status code'
370401
371 # WHEN: get_status called402 # WHEN: get_status called
372 string, message = pjlink._get_status(status=test_string)403 code, message = pjlink._get_status(status=test_string)
373404
374 # THEN: Proper strings should have been returned405 # THEN: Proper data should have been returned
375 self.assertEqual(string, -1, 'Should have returned -1 as a bad status check')406 self.assertEqual(code, -1, 'Should have returned -1 as a bad status check')
376 self.assertEqual(message, test_message, 'Error message should have been returned')407 self.assertIsNone(message, 'Invalid code type should have returned None for message')
377408
378 def test_projector_get_status_status(self):409 def test_projector_get_status_valid(self):
379 """410 """
380 Test to check returned information for status codes411 Test to check returned information for status codes
381 """412 """
382 # GIVEN: Test object413 # GIVEN: Test object
383 pjlink = pjlink_test414 test_message = 'Not Connected'
384 test_string = 'S_NOT_CONNECTED'415 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
385 test_message = 'Not connected'
386416
387 # WHEN: get_status called417 # WHEN: get_status called
388 string, message = pjlink._get_status(status=S_NOT_CONNECTED)418 code, message = pjlink._get_status(status=S_NOT_CONNECTED)
389419
390 # THEN: Proper strings should have been returned420 # THEN: Proper strings should have been returned
391 self.assertEqual(string, test_string, 'Code as string should have been returned')421 self.assertEqual(code, 'S_NOT_CONNECTED', 'Code returned should have been the same code that was sent')
392 self.assertEqual(message, test_message, 'Description of code should have been returned')422 self.assertEqual(message, test_message, 'Description of code should have been returned')
393423
394 def test_projector_get_status_unknown(self):424 def test_projector_get_status_unknown(self):
@@ -396,25 +426,24 @@
396 Test to check returned information for unknown code426 Test to check returned information for unknown code
397 """427 """
398 # GIVEN: Test object428 # GIVEN: Test object
399 pjlink = pjlink_test429 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
400 test_string = 999999
401 test_message = 'Unknown status'
402430
403 # WHEN: get_status called431 # WHEN: get_status called
404 string, message = pjlink._get_status(status=test_string)432 code, message = pjlink._get_status(status=9999)
405433
406 # THEN: Proper strings should have been returned434 # THEN: Proper strings should have been returned
407 self.assertEqual(string, test_string, 'Received code should have been returned')435 self.assertIsNone(code, 'Code returned should have been the same code that was sent')
408 self.assertEqual(message, test_message, 'Unknown status string should have been returned')436 self.assertIsNone(message, 'Should have returned None as message')
409437
410 def test_projector_process_inf1(self):438 def test_projector_process_inf1(self):
411 """439 """
412 Test saving INF1 data (manufacturer)440 Test saving INF1 data (manufacturer)
413 """441 """
442 test_data = 'TEst INformation MultiCase'
443
414 # GIVEN: Test object444 # GIVEN: Test object
415 pjlink = pjlink_test445 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
416 pjlink.manufacturer = None446 pjlink.manufacturer = None
417 test_data = 'TEst INformation MultiCase'
418447
419 # WHEN: process_inf called with test data448 # WHEN: process_inf called with test data
420 pjlink.process_inf1(data=test_data)449 pjlink.process_inf1(data=test_data)
@@ -426,10 +455,11 @@
426 """455 """
427 Test saving INF2 data (model)456 Test saving INF2 data (model)
428 """457 """
458 test_data = 'TEst moDEl MultiCase'
459
429 # GIVEN: Test object460 # GIVEN: Test object
430 pjlink = pjlink_test461 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
431 pjlink.model = None462 pjlink.model = None
432 test_data = 'TEst moDEl MultiCase'
433463
434 # WHEN: process_inf called with test data464 # WHEN: process_inf called with test data
435 pjlink.process_inf2(data=test_data)465 pjlink.process_inf2(data=test_data)
@@ -441,10 +471,11 @@
441 """471 """
442 Test saving INFO data (other information)472 Test saving INFO data (other information)
443 """473 """
474 test_data = 'TEst ExtrANEous MultiCase INformatoin that MFGR might Set'
475
444 # GIVEN: Test object476 # GIVEN: Test object
445 pjlink = pjlink_test477 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
446 pjlink.other_info = None478 pjlink.other_info = None
447 test_data = 'TEst ExtrANEous MultiCase INformatoin that MFGR might Set'
448479
449 # WHEN: process_inf called with test data480 # WHEN: process_inf called with test data
450 pjlink.process_info(data=test_data)481 pjlink.process_info(data=test_data)
@@ -452,509 +483,558 @@
452 # THEN: Data should be saved483 # THEN: Data should be saved
453 self.assertEqual(pjlink.other_info, test_data, 'Test data should have been saved')484 self.assertEqual(pjlink.other_info, test_data, 'Test data should have been saved')
454485
455 @patch.object(pjlink_test, 'projectorUpdateIcons')486 def test_projector_process_avmt_bad_data(self):
456 def test_projector_process_avmt_bad_data(self, mock_UpdateIcons):
457 """487 """
458 Test avmt bad data fail488 Test avmt bad data fail
459 """489 """
460 # GIVEN: Test object490 # GIVEN: Test object
461 pjlink = pjlink_test491 with patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons:
462 pjlink.shutter = True492 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
463 pjlink.mute = True493 pjlink.shutter = True
464494 pjlink.mute = True
465 # WHEN: Called with an invalid setting495
466 pjlink.process_avmt('36')496 # WHEN: Called with an invalid setting
467497 pjlink.process_avmt('36')
468 # THEN: Shutter should be closed and mute should be True498
469 self.assertTrue(pjlink.shutter, 'Shutter should changed')499 # THEN: Shutter should be closed and mute should be True
470 self.assertTrue(pjlink.mute, 'Audio should not have changed')500 self.assertTrue(pjlink.shutter, 'Shutter should changed')
471 self.assertFalse(mock_UpdateIcons.emit.called, 'Update icons should NOT have been called')501 self.assertTrue(pjlink.mute, 'Audio should not have changed')
472502 self.assertFalse(mock_UpdateIcons.emit.called, 'Update icons should NOT have been called')
473 @patch.object(pjlink_test, 'projectorUpdateIcons')503
474 def test_projector_process_avmt_closed_muted(self, mock_UpdateIcons):504 def test_projector_process_avmt_closed_muted(self):
475 """505 """
476 Test avmt status shutter closed and mute off506 Test avmt status shutter closed and mute off
477 """507 """
478 # GIVEN: Test object508 # GIVEN: Test object
479 pjlink = pjlink_test509 with patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons:
480 pjlink.shutter = False510 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
481 pjlink.mute = False511 pjlink.shutter = False
482512 pjlink.mute = False
483 # WHEN: Called with setting shutter to closed and mute on513
484 pjlink.process_avmt('31')514 # WHEN: Called with setting shutter to closed and mute on
485515 pjlink.process_avmt('31')
486 # THEN: Shutter should be closed and mute should be True516
487 self.assertTrue(pjlink.shutter, 'Shutter should have been set to closed')517 # THEN: Shutter should be closed and mute should be True
488 self.assertTrue(pjlink.mute, 'Audio should be muted')518 self.assertTrue(pjlink.shutter, 'Shutter should have been set to closed')
489 self.assertTrue(mock_UpdateIcons.emit.called, 'Update icons should have been called')519 self.assertTrue(pjlink.mute, 'Audio should be muted')
490520 self.assertTrue(mock_UpdateIcons.emit.called, 'Update icons should have been called')
491 @patch.object(pjlink_test, 'projectorUpdateIcons')521
492 def test_projector_process_avmt_shutter_closed(self, mock_UpdateIcons):522 def test_projector_process_avmt_shutter_closed(self):
493 """523 """
494 Test avmt status shutter closed and audio unchanged524 Test avmt status shutter closed and audio unchanged
495 """525 """
496 # GIVEN: Test object526 # GIVEN: Test object
497 pjlink = pjlink_test527 with patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons:
498 pjlink.shutter = False528 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
499 pjlink.mute = True529 pjlink.shutter = False
500530 pjlink.mute = True
501 # WHEN: Called with setting shutter closed and mute off531
502 pjlink.process_avmt('11')532 # WHEN: Called with setting shutter closed and mute off
503533 pjlink.process_avmt('11')
504 # THEN: Shutter should be True and mute should be False534
505 self.assertTrue(pjlink.shutter, 'Shutter should have been set to closed')535 # THEN: Shutter should be True and mute should be False
506 self.assertTrue(pjlink.mute, 'Audio should not have changed')536 self.assertTrue(pjlink.shutter, 'Shutter should have been set to closed')
507 self.assertTrue(mock_UpdateIcons.emit.called, 'Update icons should have been called')537 self.assertTrue(pjlink.mute, 'Audio should not have changed')
508538 self.assertTrue(mock_UpdateIcons.emit.called, 'Update icons should have been called')
509 @patch.object(pjlink_test, 'projectorUpdateIcons')539
510 def test_projector_process_avmt_audio_muted(self, mock_UpdateIcons):540 def test_projector_process_avmt_audio_muted(self):
511 """541 """
512 Test avmt status shutter unchanged and mute on542 Test avmt status shutter unchanged and mute on
513 """543 """
514 # GIVEN: Test object544 # GIVEN: Test object
515 pjlink = pjlink_test545 with patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons:
516 pjlink.shutter = True546 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
517 pjlink.mute = False547 pjlink.shutter = True
518548 pjlink.mute = False
519 # WHEN: Called with setting shutter closed and mute on549
520 pjlink.process_avmt('21')550 # WHEN: Called with setting shutter closed and mute on
521551 pjlink.process_avmt('21')
522 # THEN: Shutter should be closed and mute should be True552
523 self.assertTrue(pjlink.shutter, 'Shutter should not have changed')553 # THEN: Shutter should be closed and mute should be True
524 self.assertTrue(pjlink.mute, 'Audio should be off')554 self.assertTrue(pjlink.shutter, 'Shutter should not have changed')
525 self.assertTrue(mock_UpdateIcons.emit.called, 'Update icons should have been called')555 self.assertTrue(pjlink.mute, 'Audio should be off')
526556 self.assertTrue(mock_UpdateIcons.emit.called, 'Update icons should have been called')
527 @patch.object(pjlink_test, 'projectorUpdateIcons')557
528 def test_projector_process_avmt_open_unmuted(self, mock_UpdateIcons):558 def test_projector_process_avmt_open_unmuted(self):
529 """559 """
530 Test avmt status shutter open and mute off560 Test avmt status shutter open and mute off
531 """561 """
532 # GIVEN: Test object562 # GIVEN: Test object
533 pjlink = pjlink_test563 with patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons:
534 pjlink.shutter = True564 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
535 pjlink.mute = True565 pjlink.shutter = True
536566 pjlink.mute = True
537 # WHEN: Called with setting shutter to closed and mute on567
538 pjlink.process_avmt('30')568 # WHEN: Called with setting shutter to closed and mute on
539569 pjlink.process_avmt('30')
540 # THEN: Shutter should be closed and mute should be True570
541 self.assertFalse(pjlink.shutter, 'Shutter should have been set to open')571 # THEN: Shutter should be closed and mute should be True
542 self.assertFalse(pjlink.mute, 'Audio should be on')572 self.assertFalse(pjlink.shutter, 'Shutter should have been set to open')
543 self.assertTrue(mock_UpdateIcons.emit.called, 'Update icons should have been called')573 self.assertFalse(pjlink.mute, 'Audio should be on')
574 self.assertTrue(mock_UpdateIcons.emit.called, 'Update icons should have been called')
544575
545 def test_projector_process_clss_one(self):576 def test_projector_process_clss_one(self):
546 """577 """
547 Test class 1 sent from projector578 Test class 1 sent from projector
548 """579 """
549 # GIVEN: Test object580 # GIVEN: Test object
550 pjlink = pjlink_test581 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
551582
552 # WHEN: Process class response583 # WHEN: Process class response
553 pjlink.process_clss('1')584 pjlink.process_clss('1')
554585
555 # THEN: Projector class should be set to 1586 # THEN: Projector class should be set to 1
556 self.assertEqual(pjlink.pjlink_class, '1',587 self.assertEqual(pjlink.pjlink_class, '1', 'Projector should have set class=1')
557 'Projector should have set class=1')
558588
559 def test_projector_process_clss_two(self):589 def test_projector_process_clss_two(self):
560 """590 """
561 Test class 2 sent from projector591 Test class 2 sent from projector
562 """592 """
563 # GIVEN: Test object593 # GIVEN: Test object
564 pjlink = pjlink_test594 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
565595
566 # WHEN: Process class response596 # WHEN: Process class response
567 pjlink.process_clss('2')597 pjlink.process_clss('2')
568598
569 # THEN: Projector class should be set to 1599 # THEN: Projector class should be set to 1
570 self.assertEqual(pjlink.pjlink_class, '2',600 self.assertEqual(pjlink.pjlink_class, '2', 'Projector should have set class=2')
571 'Projector should have set class=2')601
572602 def test_projector_process_clss_invalid_nan(self):
573 @patch.object(openlp.core.projectors.pjlink, 'log')603 """
574 def test_projector_process_clss_invalid_nan(self, mock_log):604 Test CLSS reply has no class number
575 """605 """
576 Test CLSS reply has no class number606 log_debug_calls = [call('(111.111.111.111) reset_information() connect status is '
577 """607 '{state}'.format(state=STATUS_CODE[S_NOT_CONNECTED])),
578 # GIVEN: Test object608 call('(111.111.111.111) Setting pjlink_class for this projector to "1"')]
579 pjlink = pjlink_test609 log_error_calls = [call('(111.111.111.111) NAN CLSS version reply "Z" - defaulting to class "1"')]
580610
581 # WHEN: Process invalid reply611 # GIVEN: Test object
582 pjlink.process_clss('Z')612 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
583 log_text = '(127.0.0.1) NAN CLSS version reply "Z" - defaulting to class "1"'613 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
584614
585 # THEN: Projector class should be set with default value615 # WHEN: Process invalid reply
586 self.assertEqual(pjlink.pjlink_class, '1',616 pjlink.process_clss('Z')
587 'Non-standard class reply should have set class=1')617
588 mock_log.error.assert_called_once_with(log_text)618 # THEN: Projector class should be set with default value
589619 self.assertEqual(pjlink.pjlink_class, '1', 'Invalid NaN class reply should have set class=1')
590 @patch.object(openlp.core.projectors.pjlink, 'log')620 mock_log.error.assert_has_calls(log_error_calls)
591 def test_projector_process_clss_invalid_no_version(self, mock_log):621 mock_log.debug.assert_has_calls(log_debug_calls)
592 """622
593 Test CLSS reply has no class number623 def test_projector_process_clss_invalid_no_version(self):
594 """624 """
595 # GIVEN: Test object625 Test CLSS reply has no class number
596 pjlink = pjlink_test626 """
597627 log_debug_calls = [call('(111.111.111.111) reset_information() connect status is '
598 # WHEN: Process invalid reply628 '{state}'.format(state=STATUS_CODE[S_NOT_CONNECTED])),
599 pjlink.process_clss('Invalid')629 call('(111.111.111.111) Setting pjlink_class for this projector to "1"')]
600 log_text = '(127.0.0.1) No numbers found in class version reply "Invalid" - defaulting to class "1"'630 log_error_calls = [call('(111.111.111.111) No numbers found in class version reply "Invalid" '
601631 '- defaulting to class "1"')]
602 # THEN: Projector class should be set with default value632
603 self.assertEqual(pjlink.pjlink_class, '1',633 # GIVEN: Test object
604 'Non-standard class reply should have set class=1')634 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
605 mock_log.error.assert_called_once_with(log_text)635 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
636
637 # WHEN: Process invalid reply
638 pjlink.process_clss('Invalid')
639
640 # THEN: Projector class should be set with default value
641 self.assertEqual(pjlink.pjlink_class, '1', 'Invalid class reply should have set class=1')
642 mock_log.error.assert_has_calls(log_error_calls)
643 mock_log.debug.assert_has_calls(log_debug_calls)
606644
607 def test_projector_process_erst_all_ok(self):645 def test_projector_process_erst_all_ok(self):
608 """646 """
609 Test test_projector_process_erst_all_ok647 Test to verify pjlink.projector_errors is set to None when no errors
610 """648 """
649 chk_data = '0' * PJLINK_ERST_DATA['DATA_LENGTH']
650
611 # GIVEN: Test object651 # GIVEN: Test object
612 pjlink = pjlink_test652 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
613 chk_test = PJLINK_ERST_STATUS['OK']
614 chk_param = chk_test * len(PJLINK_ERST_POSITIONS)
615653
616 # WHEN: process_erst with no errors654 # WHEN: process_erst with no errors
617 pjlink.process_erst(chk_param)655 pjlink.process_erst(chk_data)
618656
619 # THEN: PJLink instance errors should be None657 # THEN: PJLink instance errors should be None
620 self.assertIsNone(pjlink.projector_errors, 'projector_errors should have been set to None')658 self.assertIsNone(pjlink.projector_errors, 'projector_errors should have been set to None')
621659
622 @patch.object(openlp.core.projectors.pjlink, 'log')660 def test_projector_process_erst_data_invalid_length(self):
623 def test_projector_process_erst_data_invalid_length(self, mock_log):
624 """661 """
625 Test test_projector_process_erst_data_invalid_length662 Test test_projector_process_erst_data_invalid_length
626 """663 """
664 chk_data = '0' * (PJLINK_ERST_DATA['DATA_LENGTH'] + 1)
665 log_debug_calls = [call('(111.111.111.111) reset_information() connect status is '
666 '{state}'.format(state=STATUS_CODE[S_NOT_CONNECTED]))]
667 log_warn_calls = [call('111.111.111.111) Invalid error status response "0000000": '
668 'length != {chk}'.format(chk=PJLINK_ERST_DATA['DATA_LENGTH']))]
669
627 # GIVEN: Test object670 # GIVEN: Test object
628 pjlink = pjlink_test671 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
629 pjlink.projector_errors = None672 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
630 log_text = '127.0.0.1) Invalid error status response "11111111": length != 6'673 pjlink.projector_errors = None
631674
632 # WHEN: process_erst called with invalid data (too many values675 # WHEN: process_erst called with invalid data (too many values
633 pjlink.process_erst('11111111')676 pjlink.process_erst(chk_data)
634677
635 # THEN: pjlink.projector_errors should be empty and warning logged678 # THEN: pjlink.projector_errors should be empty and warning logged
636 self.assertIsNone(pjlink.projector_errors, 'There should be no errors')679 self.assertIsNone(pjlink.projector_errors, 'There should be no errors')
637 self.assertTrue(mock_log.warning.called, 'Warning should have been logged')680 mock_log.debug.assert_has_calls(log_debug_calls)
638 mock_log.warning.assert_called_once_with(log_text)681 mock_log.warning.assert_has_calls(log_warn_calls)
639682
640 @patch.object(openlp.core.projectors.pjlink, 'log')683 def test_projector_process_erst_data_invalid_nan(self):
641 def test_projector_process_erst_data_invalid_nan(self, mock_log):
642 """684 """
643 Test test_projector_process_erst_data_invalid_nan685 Test test_projector_process_erst_data_invalid_nan
644 """686 """
687 chk_data = 'Z' + ('0' * (PJLINK_ERST_DATA['DATA_LENGTH'] - 1))
688 log_debug_calls = [call('(111.111.111.111) reset_information() connect status is '
689 '{state}'.format(state=STATUS_CODE[S_NOT_CONNECTED]))]
690 log_warn_calls = [call('(111.111.111.111) Invalid error status response "Z00000"')]
691
645 # GIVEN: Test object692 # GIVEN: Test object
646 pjlink = pjlink_test693 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
647 pjlink.projector_errors = None694 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
648 log_text = '(127.0.0.1) Invalid error status response "1111Z1"'695 pjlink.projector_errors = None
649696
650 # WHEN: process_erst called with invalid data (too many values697 # WHEN: process_erst called with invalid data (too many values
651 pjlink.process_erst('1111Z1')698 pjlink.process_erst(chk_data)
652699
653 # THEN: pjlink.projector_errors should be empty and warning logged700 # THEN: pjlink.projector_errors should be empty and warning logged
654 self.assertIsNone(pjlink.projector_errors, 'There should be no errors')701 self.assertIsNone(pjlink.projector_errors, 'There should be no errors')
655 self.assertTrue(mock_log.warning.called, 'Warning should have been logged')702 mock_log.debug.assert_has_calls(log_debug_calls)
656 mock_log.warning.assert_called_once_with(log_text)703 mock_log.warning.assert_has_calls(log_warn_calls)
657704
658 def test_projector_process_erst_all_warn(self):705 def test_projector_process_erst_all_warn(self):
659 """706 """
660 Test test_projector_process_erst_all_warn707 Test test_projector_process_erst_all_warn
661 """708 """
709 chk_data = '{fan}{lamp}{temp}{cover}{filt}{other}'.format(fan=PJLINK_ERST_STATUS[E_WARN],
710 lamp=PJLINK_ERST_STATUS[E_WARN],
711 temp=PJLINK_ERST_STATUS[E_WARN],
712 cover=PJLINK_ERST_STATUS[E_WARN],
713 filt=PJLINK_ERST_STATUS[E_WARN],
714 other=PJLINK_ERST_STATUS[E_WARN])
715 chk_test = {'Fan': E_WARN,
716 'Lamp': E_WARN,
717 'Temperature': E_WARN,
718 'Cover': E_WARN,
719 'Filter': E_WARN,
720 'Other': E_WARN}
721
662 # GIVEN: Test object722 # GIVEN: Test object
663 pjlink = pjlink_test723 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
664 chk_test = PJLINK_ERST_STATUS[E_WARN]724 pjlink.projector_errors = None
665 chk_string = ERROR_STRING[E_WARN]
666 chk_param = chk_test * len(PJLINK_ERST_POSITIONS)
667725
668 # WHEN: process_erst with status set to WARN726 # WHEN: process_erst with status set to WARN
669 pjlink.process_erst(chk_param)727 pjlink.process_erst(chk_data)
670728
671 # THEN: PJLink instance errors should match chk_value729 # THEN: PJLink instance errors should match chk_value
672 for chk in pjlink.projector_errors:730 self.assertEqual(pjlink.projector_errors, chk_test, 'Projector errors should be all E_WARN')
673 self.assertEqual(pjlink.projector_errors[chk], chk_string,
674 'projector_errors["{chk}"] should have been set to "{err}"'.format(chk=chk,
675 err=chk_string))
676731
677 def test_projector_process_erst_all_error(self):732 def test_projector_process_erst_all_error(self):
678 """733 """
679 Test test_projector_process_erst_all_error734 Test test_projector_process_erst_all_error
680 """735 """
736 chk_data = '{fan}{lamp}{temp}{cover}{filt}{other}'.format(fan=PJLINK_ERST_STATUS[E_ERROR],
737 lamp=PJLINK_ERST_STATUS[E_ERROR],
738 temp=PJLINK_ERST_STATUS[E_ERROR],
739 cover=PJLINK_ERST_STATUS[E_ERROR],
740 filt=PJLINK_ERST_STATUS[E_ERROR],
741 other=PJLINK_ERST_STATUS[E_ERROR])
742 chk_test = {'Fan': E_ERROR,
743 'Lamp': E_ERROR,
744 'Temperature': E_ERROR,
745 'Cover': E_ERROR,
746 'Filter': E_ERROR,
747 'Other': E_ERROR}
748
681 # GIVEN: Test object749 # GIVEN: Test object
682 pjlink = pjlink_test750 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
683 chk_test = PJLINK_ERST_STATUS[E_ERROR]751 pjlink.projector_errors = None
684 chk_string = ERROR_STRING[E_ERROR]
685 chk_param = chk_test * len(PJLINK_ERST_POSITIONS)
686752
687 # WHEN: process_erst with status set to WARN753 # WHEN: process_erst with status set to WARN
688 pjlink.process_erst(chk_param)754 pjlink.process_erst(chk_data)
689755
690 # THEN: PJLink instance errors should match chk_value756 # THEN: PJLink instance errors should match chk_value
691 for chk in pjlink.projector_errors:757 self.assertEqual(pjlink.projector_errors, chk_test, 'Projector errors should be all E_ERROR')
692 self.assertEqual(pjlink.projector_errors[chk], chk_string,
693 'projector_errors["{chk}"] should have been set to "{err}"'.format(chk=chk,
694 err=chk_string))
695758
696 def test_projector_process_erst_warn_cover_only(self):759 def test_projector_process_erst_warn_cover_only(self):
697 """760 """
698 Test test_projector_process_erst_warn_cover_only761 Test test_projector_process_erst_warn_cover_only
699 """762 """
763 chk_data = '{fan}{lamp}{temp}{cover}{filt}{other}'.format(fan=PJLINK_ERST_STATUS[S_OK],
764 lamp=PJLINK_ERST_STATUS[S_OK],
765 temp=PJLINK_ERST_STATUS[S_OK],
766 cover=PJLINK_ERST_STATUS[E_WARN],
767 filt=PJLINK_ERST_STATUS[S_OK],
768 other=PJLINK_ERST_STATUS[S_OK])
769 chk_test = {'Cover': E_WARN}
770
700 # GIVEN: Test object771 # GIVEN: Test object
701 pjlink = pjlink_test772 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
702 chk_test = PJLINK_ERST_STATUS[E_WARN]773 pjlink.projector_errors = None
703 chk_string = ERROR_STRING[E_WARN]774
704 pos = PJLINK_ERST_DATA['COVER']775 # WHEN: process_erst with status set to WARN
705 build_chk = []776 pjlink.process_erst(chk_data)
706 for check in range(0, len(PJLINK_ERST_POSITIONS)):777
707 if check == pos:778 # THEN: PJLink instance errors should match only cover warning
708 build_chk.append(chk_test)779 assert 1 == len(pjlink.projector_errors), 'There should only be 1 error listed in projector_errors'
709 else:780 assert 'Cover' in pjlink.projector_errors, '"Cover" should be the only error listed'
710 build_chk.append(PJLINK_ERST_STATUS['OK'])781 assert pjlink.projector_errors['Cover'] == E_WARN, '"Cover" should have E_WARN listed as error'
711 chk_param = ''.join(build_chk)782 assert chk_test == pjlink.projector_errors, 'projector_errors should match test errors'
712783
713 # WHEN: process_erst with cover only set to WARN and all others set to OK784 def test_projector_process_inpt_valid(self):
714 pjlink.process_erst(chk_param)
715
716 # THEN: Only COVER should have an error
717 self.assertEqual(len(pjlink.projector_errors), 1, 'projector_errors should only have 1 error')
718 self.assertTrue(('Cover' in pjlink.projector_errors), 'projector_errors should have an error for "Cover"')
719 self.assertEqual(pjlink.projector_errors['Cover'],
720 chk_string,
721 'projector_errors["Cover"] should have error "{err}"'.format(err=chk_string))
722
723 def test_projector_process_inpt(self):
724 """785 """
725 Test input source status shows current input786 Test input source status shows current input
726 """787 """
788 log_debug_calls = [call('(111.111.111.111) reset_information() connect status is S_NOT_CONNECTED')]
789 chk_source_available = ['11', '12', '21', '22', '31', '32']
790
727 # GIVEN: Test object791 # GIVEN: Test object
728 pjlink = pjlink_test792 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
729 pjlink.source = '0'793 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
730794 pjlink.source_available = chk_source_available
731 # WHEN: Called with input source795 pjlink.source = '11'
732 pjlink.process_inpt('1')796
733797 # WHEN: Called with input source
734 # THEN: Input selected should reflect current input798 pjlink.process_inpt('21')
735 self.assertEqual(pjlink.source, '1', 'Input source should be set to "1"')799
736800 # THEN: Input selected should reflect current input
737 @patch.object(pjlink_test, 'projectorUpdateIcons')801 assert pjlink.source == '21', 'Input source should be set to "21"'
738 @patch.object(openlp.core.projectors.pjlink, 'log')802 mock_log.debug.assert_has_calls(log_debug_calls)
739 def test_projector_process_inst(self, mock_log, mock_UpdateIcons):803
804 def test_projector_process_input_not_in_list(self):
805 """
806 Test setting input outside of available inputs
807
808 TODO: Future test
809 """
810 pass
811
812 def test_projector_process_input_not_in_default(self):
813 """
814 Test setting input with no sources available
815 TODO: Future test
816 """
817 pass
818
819 def test_projector_process_input_invalid(self):
820 """
821 Test setting input with an invalid value
822
823 TODO: Future test
824 """
825
826 def test_projector_process_inst_class_1(self):
740 """827 """
741 Test saving video source available information828 Test saving video source available information
742 """829 """
830 log_debug_calls = [call('(111.111.111.111) Setting projector sources_available to '
831 '"[\'11\', \'12\', \'21\', \'22\', \'31\', \'32\']"')]
832 chk_data = '21 12 11 22 32 31' # Although they should already be sorted, use unsorted to verify method
833 chk_test = ['11', '12', '21', '22', '31', '32']
834
743 # GIVEN: Test object835 # GIVEN: Test object
744 pjlink = pjlink_test836 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
745 pjlink.source_available = []837 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
746 test_data = '21 10 30 31 11 20'838 pjlink.source_available = []
747 test_saved = ["10", "11", "20", "21", "30", "31"]839
748 log_data = "(127.0.0.1) Setting projector sources_available to " \840 # WHEN: process_inst called with test data
749 "\"['10', '11', '20', '21', '30', '31']\""841 pjlink.process_inst(data=chk_data)
750 mock_UpdateIcons.reset_mock()842
751 mock_log.reset_mock()843 # THEN: Data should have been sorted and saved properly
752844 assert pjlink.source_available == chk_test, "Sources should have been sorted and saved"
753 # WHEN: process_inst called with test data845 mock_log.debug.assert_has_calls(log_debug_calls)
754 pjlink.process_inst(data=test_data)846
755847 def test_projector_process_lamp_invalid(self):
756 # THEN: Data should have been sorted and saved properly
757 self.assertEqual(pjlink.source_available, test_saved, "Sources should have been sorted and saved")
758 mock_log.debug.assert_called_once_with(log_data)
759 self.assertTrue(mock_UpdateIcons.emit.called, 'Update Icons should have been called')
760
761 @patch.object(openlp.core.projectors.pjlink, 'log')
762 def test_projector_process_lamp_invalid(self, mock_log):
763 """848 """
764 Test status multiple lamp on/off and hours849 Test status multiple lamp on/off and hours
765 """850 """
851 log_data = [call('(111.111.111.111) process_lamp(): Invalid data "11111 1 22222 0 333A3 1"')]
852
766 # GIVEN: Test object853 # GIVEN: Test object
767 pjlink = pjlink_test854 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
768 pjlink.lamp = [{'Hours': 00000, 'On': True},855 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
769 {'Hours': 11111, 'On': False}]856 pjlink.lamp = [{'Hours': 00000, 'On': True},
770 log_data = '(127.0.0.1) process_lamp(): Invalid data "11111 1 22222 0 333A3 1"'857 {'Hours': 11111, 'On': False}]
771858
772 # WHEN: Call process_command with invalid lamp data859 # WHEN: Call process_command with invalid lamp data
773 pjlink.process_lamp('11111 1 22222 0 333A3 1')860 pjlink.process_lamp('11111 1 22222 0 333A3 1')
774861
775 # THEN: lamps should not have changed862 # THEN: lamps should not have changed
776 self.assertEqual(len(pjlink.lamp), 2,863 assert 2 == len(pjlink.lamp), 'Projector should have kept 2 lamps specified'
777 'Projector should have kept 2 lamps specified')864 assert pjlink.lamp[0]['On'] is True, 'Lamp 1 power status should have stayed TRUE'
778 self.assertEqual(pjlink.lamp[0]['On'], True,865 assert 00000 == pjlink.lamp[0]['Hours'], 'Lamp 1 hours should have been left at 00000'
779 'Lamp 1 power status should have been set to TRUE')866 assert pjlink.lamp[1]['On'] is False, 'Lamp 2 power status should have stayed FALSE'
780 self.assertEqual(pjlink.lamp[0]['Hours'], 00000,867 assert 11111 == pjlink.lamp[1]['Hours'], 'Lamp 2 hours should have been left at 11111'
781 'Lamp 1 hours should have been left at 00000')868 mock_log.warning.assert_has_calls(log_data)
782 self.assertEqual(pjlink.lamp[1]['On'], False,
783 'Lamp 2 power status should have been set to FALSE')
784 self.assertEqual(pjlink.lamp[1]['Hours'], 11111,
785 'Lamp 2 hours should have been left at 11111')
786 mock_log.warning.assert_called_once_with(log_data)
787869
788 def test_projector_process_lamp_multiple(self):870 def test_projector_process_lamp_multiple(self):
789 """871 """
790 Test status multiple lamp on/off and hours872 Test status multiple lamp on/off and hours
791 """873 """
792 # GIVEN: Test object874 # GIVEN: Test object
793 pjlink = pjlink_test875 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
794 pjlink.lamps = []876 pjlink.lamp = []
795877
796 # WHEN: Call process_command with lamp data878 # WHEN: Call process_command with invalid lamp data
797 pjlink.process_lamp('11111 1 22222 0 33333 1')879 pjlink.process_lamp('11111 1 22222 0 33333 1')
798880
799 # THEN: Lamp should have been set with proper lamp status881 # THEN: Lamp should have been set with proper lamp status
800 self.assertEqual(len(pjlink.lamp), 3,882 assert 3 == len(pjlink.lamp), 'Projector should have 3 lamps specified'
801 'Projector should have 3 lamps specified')883 assert pjlink.lamp[0]['On'] is True, 'Lamp 1 power status should have been set to TRUE'
802 self.assertEqual(pjlink.lamp[0]['On'], True,884 assert 11111 == pjlink.lamp[0]['Hours'], 'Lamp 1 hours should have been set to 11111'
803 'Lamp 1 power status should have been set to TRUE')885 assert pjlink.lamp[1]['On'] is False, 'Lamp 2 power status should have been set to FALSE'
804 self.assertEqual(pjlink.lamp[0]['Hours'], 11111,886 assert 22222 == pjlink.lamp[1]['Hours'], 'Lamp 2 hours should have been set to 22222'
805 'Lamp 1 hours should have been set to 11111')887 assert pjlink.lamp[2]['On'] is True, 'Lamp 3 power status should have been set to TRUE'
806 self.assertEqual(pjlink.lamp[1]['On'], False,888 assert 33333 == pjlink.lamp[2]['Hours'], 'Lamp 3 hours should have been set to 33333'
807 'Lamp 2 power status should have been set to FALSE')
808 self.assertEqual(pjlink.lamp[1]['Hours'], 22222,
809 'Lamp 2 hours should have been set to 22222')
810 self.assertEqual(pjlink.lamp[2]['On'], True,
811 'Lamp 3 power status should have been set to TRUE')
812 self.assertEqual(pjlink.lamp[2]['Hours'], 33333,
813 'Lamp 3 hours should have been set to 33333')
814889
815 def test_projector_process_lamp_single(self):890 def test_projector_process_lamp_single(self):
816 """891 """
817 Test status lamp on/off and hours892 Test status lamp on/off and hours
818 """893 """
894
819 # GIVEN: Test object895 # GIVEN: Test object
820 pjlink = pjlink_test896 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
821 pjlink.lamps = []897 pjlink.lamp = []
822898
823 # WHEN: Call process_command with lamp data899 # WHEN: Call process_command with invalid lamp data
824 pjlink.process_lamp('22222 1')900 pjlink.process_lamp('22222 1')
825901
826 # THEN: Lamp should have been set with status=ON and hours=22222902 # THEN: Lamp should have been set with status=ON and hours=22222
827 self.assertEqual(pjlink.lamp[0]['On'], True,903 assert 1 == len(pjlink.lamp), 'Projector should have only 1 lamp'
828 'Lamp power status should have been set to TRUE')904 assert pjlink.lamp[0]['On'] is True, 'Lamp power status should have been set to TRUE'
829 self.assertEqual(pjlink.lamp[0]['Hours'], 22222,905 assert 22222 == pjlink.lamp[0]['Hours'], 'Lamp hours should have been set to 22222'
830 'Lamp hours should have been set to 22222')
831906
832 @patch.object(openlp.core.projectors.pjlink, 'log')907 def test_projector_process_name(self):
833 def test_projector_process_name(self, mock_log):
834 """908 """
835 Test saving NAME data from projector909 Test saving NAME data from projector
836 """910 """
837 # GIVEN: Test data911 chk_data = "Some Name the End-User Set IN Projector"
838 pjlink = pjlink_test912 log_debug_calls = [call('(111.111.111.111) Setting projector PJLink name to '
839 test_data = "Some Name the End-User Set IN Projector"913 '"Some Name the End-User Set IN Projector"')]
840 test_log = '(127.0.0.1) Setting projector PJLink name to "Some Name the End-User Set IN Projector"'914
841 mock_log.reset_mock()915 # GIVEN: Test object
842916 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
843 # WHEN: process_name called with test data917 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
844 pjlink.process_name(data=test_data)918
845919 # WHEN: process_name called with test data
846 # THEN: name should be set and logged920 pjlink.process_name(data=chk_data)
847 self.assertEqual(pjlink.pjlink_name, test_data, 'Name test data should have been saved')921
848 mock_log.debug.assert_called_once_with(test_log)922 # THEN: name should be set and logged
849923 assert pjlink.pjlink_name == chk_data, 'Name test data should have been saved'
850 @patch.object(pjlink_test, 'projectorUpdateIcons')924 mock_log.debug.assert_has_calls(log_debug_calls)
851 @patch.object(pjlink_test, 'send_command')925
852 @patch.object(pjlink_test, 'change_status')926 def test_projector_process_powr_on(self):
853 def test_projector_process_powr_on(self,
854 mock_change_status,
855 mock_send_command,
856 mock_UpdateIcons):
857 """927 """
858 Test status power to ON928 Test status power to ON
859 """929 """
860 # GIVEN: Test object and preset930 # GIVEN: Test object
861 pjlink = pjlink_test931 with patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command, \
862 pjlink.power = S_STANDBY932 patch.object(openlp.core.projectors.pjlink.PJLink, 'change_status') as mock_change_status, \
863 test_data = PJLINK_POWR_STATUS[S_ON]933 patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons:
864934
865 # WHEN: Call process_command with turn power on command935 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
866 pjlink.process_command(cmd='POWR', data=test_data)936 pjlink.power = S_STANDBY
867937
868 # THEN: Power should be set to ON938 # WHEN: process_name called with test data
869 self.assertEqual(pjlink.power, S_ON, 'Power should have been set to ON')939 pjlink.process_powr(data=PJLINK_POWR_STATUS[S_ON])
870 mock_send_command.assert_called_once_with('INST')940
871 mock_change_status.assert_called_once_with(PJLINK_POWR_STATUS[test_data])941 # THEN: Power should be set to ON
872 self.assertEqual(mock_UpdateIcons.emit.called, True, 'projectorUpdateIcons should have been called')942 assert pjlink.power == S_ON, 'Power should have been set to ON'
873943 assert mock_UpdateIcons.emit.called is True, 'projectorUpdateIcons should have been called'
874 @patch.object(pjlink_test, 'projectorUpdateIcons')944 mock_send_command.assert_called_once_with('INST')
875 @patch.object(pjlink_test, 'send_command')945 mock_change_status.assert_called_once_with(S_ON)
876 @patch.object(pjlink_test, 'change_status')946
877 def test_projector_process_powr_invalid(self,947 def test_projector_process_powr_invalid(self):
878 mock_change_status,
879 mock_send_command,
880 mock_UpdateIcons):
881 """948 """
882 Test process_powr invalid call949 Test process_powr invalid call
883 """950 """
884 # GIVEN: Test object and preset951 log_warn_calls = [call('(111.111.111.111) Unknown power response: "99"')]
885 pjlink = pjlink_test952
886 pjlink.power = S_STANDBY953 # GIVEN: Test object
887 test_data = '99'954 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
888955 patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command, \
889 # WHEN: Call process_command with turn power on command956 patch.object(openlp.core.projectors.pjlink.PJLink, 'change_status') as mock_change_status, \
890 pjlink.process_command(cmd='POWR', data=test_data)957 patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons:
891958
892 # THEN: Power should be set to ON959 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
893 self.assertEqual(pjlink.power, S_STANDBY, 'Power should not have changed')960 pjlink.power = S_STANDBY
894 self.assertFalse(mock_change_status.called, 'Change status should not have been called')961
895 self.assertFalse(mock_send_command.called, 'send_command("INST") should not have been called')962 # WHEN: process_name called with test data
896 self.assertFalse(mock_UpdateIcons.emit.called, 'projectorUpdateIcons should not have been called')963 pjlink.process_powr(data='99')
897964
898 @patch.object(pjlink_test, 'projectorUpdateIcons')965 # THEN: Power should be set to ON
899 @patch.object(pjlink_test, 'send_command')966 assert pjlink.power == S_STANDBY, 'Power should not have changed'
900 @patch.object(pjlink_test, 'change_status')967 assert mock_UpdateIcons.emit.called is False, 'projectorUpdateIcons() should not have been called'
901 def test_projector_process_powr_off(self,968 mock_change_status.called is False, 'change_status() should not have been called'
902 mock_change_status,969 mock_send_command.called is False, 'send_command() should not have been called'
903 mock_send_command,970 mock_log.warning.assert_has_calls(log_warn_calls)
904 mock_UpdateIcons):971
972 def test_projector_process_powr_off(self):
905 """973 """
906 Test status power to STANDBY974 Test status power to STANDBY
907 """975 """
908 # GIVEN: Test object and preset976 # GIVEN: Test object
909 pjlink = pjlink_test977 with patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command, \
910 pjlink.power = S_ON978 patch.object(openlp.core.projectors.pjlink.PJLink, 'change_status') as mock_change_status, \
911 test_data = PJLINK_POWR_STATUS[S_STANDBY]979 patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons:
912980
913 # WHEN: Call process_command with turn power on command981 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
914 pjlink.process_command(cmd='POWR', data=test_data)982 pjlink.power = S_ON
915983
916 # THEN: Power should be set to STANDBY984 # WHEN: process_name called with test data
917 self.assertEqual(pjlink.power, S_STANDBY, 'Power should have been set to STANDBY')985 pjlink.process_powr(data=PJLINK_POWR_STATUS[S_STANDBY])
918 self.assertEqual(mock_UpdateIcons.emit.called, True, 'projectorUpdateIcons should have been called')986
919 mock_change_status.assert_called_once_with(PJLINK_POWR_STATUS[test_data])987 # THEN: Power should be set to ON
920 self.assertFalse(mock_send_command.called, "send_command['INST'] should not have been called")988 assert pjlink.power == S_STANDBY, 'Power should have changed to S_STANDBY'
989 assert mock_UpdateIcons.emit.called is True, 'projectorUpdateIcons should have been called'
990 mock_change_status.called is True, 'change_status should have been called'
991 mock_send_command.called is False, 'send_command should not have been called'
921992
922 def test_projector_process_rfil_save(self):993 def test_projector_process_rfil_save(self):
923 """994 """
924 Test saving filter type995 Test saving filter type
925 """996 """
997 filter_model = 'Filter Type Test'
998
926 # GIVEN: Test object999 # GIVEN: Test object
927 pjlink = pjlink_test1000 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
928 pjlink.model_filter = None1001 pjlink.model_filter = None
929 filter_model = 'Filter Type Test'
9301002
931 # WHEN: Filter model is received1003 # WHEN: Filter model is received
932 pjlink.process_rfil(data=filter_model)1004 pjlink.process_rfil(data=filter_model)
9331005
934 # THEN: Filter model number should be saved1006 # THEN: Filter model number should be saved
935 self.assertEqual(pjlink.model_filter, filter_model, 'Filter type should have been saved')1007 assert pjlink.model_filter == filter_model, 'Filter type should have been saved'
9361008
937 def test_projector_process_rfil_nosave(self):1009 def test_projector_process_rfil_nosave(self):
938 """1010 """
939 Test saving filter type previously saved1011 Test saving filter type previously saved
940 """1012 """
1013 filter_model = 'Filter Type Test'
1014 log_warn_calls = [call('(111.111.111.111) Filter model already set'),
1015 call('(111.111.111.111) Saved model: "Old filter type"'),
1016 call('(111.111.111.111) New model: "Filter Type Test"')]
1017
941 # GIVEN: Test object1018 # GIVEN: Test object
942 pjlink = pjlink_test1019 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
943 pjlink.model_filter = 'Old filter type'1020
944 filter_model = 'Filter Type Test'1021 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
9451022 pjlink.model_filter = 'Old filter type'
946 # WHEN: Filter model is received1023
947 pjlink.process_rfil(data=filter_model)1024 # WHEN: Filter model is received
9481025 pjlink.process_rfil(data=filter_model)
949 # THEN: Filter model number should be saved1026
950 self.assertNotEquals(pjlink.model_filter, filter_model, 'Filter type should NOT have been saved')1027 # THEN: Filter model number should be saved
1028 assert pjlink.model_filter != filter_model, 'Filter type should NOT have been saved'
1029 mock_log.warning.assert_has_calls(log_warn_calls)
9511030
952 def test_projector_process_rlmp_save(self):1031 def test_projector_process_rlmp_save(self):
953 """1032 """
954 Test saving lamp type1033 Test saving lamp type
955 """1034 """
956 # GIVEN: Test object1035 # GIVEN: Test object
957 pjlink = pjlink_test1036 # GIVEN: Test object
1037 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
958 pjlink.model_lamp = None1038 pjlink.model_lamp = None
959 lamp_model = 'Lamp Type Test'1039 lamp_model = 'Lamp Type Test'
9601040
@@ -968,153 +1048,173 @@
968 """1048 """
969 Test saving lamp type previously saved1049 Test saving lamp type previously saved
970 """1050 """
1051 lamp_model = 'Lamp Type Test'
1052 log_warn_calls = [call('(111.111.111.111) Lamp model already set'),
1053 call('(111.111.111.111) Saved lamp: "Old lamp type"'),
1054 call('(111.111.111.111) New lamp: "Lamp Type Test"')]
1055
971 # GIVEN: Test object1056 # GIVEN: Test object
972 pjlink = pjlink_test1057 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
973 pjlink.model_lamp = 'Old lamp type'1058
974 lamp_model = 'Filter Type Test'1059 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
9751060 pjlink.model_lamp = 'Old lamp type'
976 # WHEN: Filter model is received1061
977 pjlink.process_rlmp(data=lamp_model)1062 # WHEN: Filter model is received
9781063 pjlink.process_rlmp(data=lamp_model)
979 # THEN: Filter model number should be saved1064
980 self.assertNotEquals(pjlink.model_lamp, lamp_model, 'Lamp type should NOT have been saved')1065 # THEN: Filter model number should be saved
1066 assert pjlink.model_lamp != lamp_model, 'Lamp type should NOT have been saved'
1067 mock_log.warning.assert_has_calls(log_warn_calls)
9811068
982 def test_projector_process_snum_set(self):1069 def test_projector_process_snum_set(self):
983 """1070 """
984 Test saving serial number from projector1071 Test saving serial number from projector
985 """1072 """
1073 log_debug_calls = [call('(111.111.111.111) Setting projector serial number to "Test Serial Number"')]
1074 test_number = 'Test Serial Number'
1075
986 # GIVEN: Test object1076 # GIVEN: Test object
987 pjlink = pjlink_test1077 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
988 pjlink.serial_no = None1078
989 test_number = 'Test Serial Number'1079 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
9901080 pjlink.serial_no = None
991 # WHEN: No serial number is set and we receive serial number command1081
992 pjlink.process_snum(data=test_number)1082 # WHEN: No serial number is set and we receive serial number command
9931083 pjlink.process_snum(data=test_number)
994 # THEN: Serial number should be set1084
995 self.assertEqual(pjlink.serial_no, test_number,1085 # THEN: Serial number should be set
996 'Projector serial number should have been set')1086 assert pjlink.serial_no == test_number, 'Projector serial number should have been set'
1087 mock_log.debug.assert_has_calls(log_debug_calls)
9971088
998 def test_projector_process_snum_different(self):1089 def test_projector_process_snum_different(self):
999 """1090 """
1000 Test projector serial number different than saved serial number1091 Test projector serial number different than saved serial number
1001 """1092 """
1002 # GIVEN: Test object1093 log_warn_calls = [call('(111.111.111.111) Projector serial number does not match saved serial number'),
1003 pjlink = pjlink_test1094 call('(111.111.111.111) Saved: "Previous serial number"'),
1004 pjlink.serial_no = 'Previous serial number'1095 call('(111.111.111.111) Received: "Test Serial Number"'),
1096 call('(111.111.111.111) NOT saving serial number')]
1005 test_number = 'Test Serial Number'1097 test_number = 'Test Serial Number'
10061098
1007 # WHEN: No serial number is set and we receive serial number command1099 # GIVEN: Test object
1008 pjlink.process_snum(data=test_number)1100 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
10091101 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
1010 # THEN: Serial number should be set1102 pjlink.serial_no = 'Previous serial number'
1011 self.assertNotEquals(pjlink.serial_no, test_number,1103
1012 'Projector serial number should NOT have been set')1104 # WHEN: No serial number is set and we receive serial number command
10131105 pjlink.process_snum(data=test_number)
1014 @patch.object(openlp.core.projectors.pjlink, 'log')1106
1015 def test_projector_process_sver(self, mock_log):1107 # THEN: Serial number should be set
1108 assert pjlink.serial_no != test_number, 'Projector serial number should NOT have been set'
1109 mock_log.warning.assert_has_calls(log_warn_calls)
1110
1111 def test_projector_process_sver(self):
1016 """1112 """
1017 Test invalid software version information - too long1113 Test invalid software version information - too long
1018 """1114 """
1019 # GIVEN: Test object
1020 pjlink = pjlink_test
1021 pjlink.sw_version = None
1022 pjlink.sw_version_received = None
1023 test_data = 'Test 1 Subtest 1'1115 test_data = 'Test 1 Subtest 1'
1024 test_log = '(127.0.0.1) Setting projector software version to "Test 1 Subtest 1"'1116 log_debug_calls = [call('(111.111.111.111) Setting projector software version to "Test 1 Subtest 1"')]
1025 mock_log.reset_mock()1117
10261118 # GIVEN: Test object
1027 # WHEN: process_sver called with invalid data1119 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
1028 pjlink.process_sver(data=test_data)1120 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
10291121 pjlink.sw_version = None
1030 # THEN: Version information should not change1122 pjlink.sw_version_received = None
1031 self.assertEqual(pjlink.sw_version, test_data, 'Software version should have been updated')1123
1032 self.assertIsNone(pjlink.sw_version_received, 'Received software version should not have changed')1124 # WHEN: process_sver called with invalid data
1033 mock_log.debug.assert_called_once_with(test_log)1125 pjlink.process_sver(data=test_data)
10341126
1035 @patch.object(openlp.core.projectors.pjlink, 'log')1127 # THEN: Version information should not change
1036 def test_projector_process_sver_changed(self, mock_log):1128 assert pjlink.sw_version == test_data, 'Software version should have been updated'
1129 mock_log.debug.assert_has_calls(log_debug_calls)
1130
1131 def test_projector_process_sver_changed(self):
1037 """1132 """
1038 Test invalid software version information - Received different than saved1133 Test invalid software version information - Received different than saved
1039 """1134 """
1040 # GIVEN: Test object1135 test_data_old = 'Test 1 Subtest 1'
1041 pjlink = pjlink_test
1042 test_data_new = 'Test 1 Subtest 2'1136 test_data_new = 'Test 1 Subtest 2'
1043 test_data_old = 'Test 1 Subtest 1'1137 log_warn_calls = [call('(111.111.111.111) Projector software version does not match saved software version'),
1044 pjlink.sw_version = test_data_old1138 call('(111.111.111.111) Saved: "Test 1 Subtest 1"'),
1045 pjlink.sw_version_received = None1139 call('(111.111.111.111) Received: "Test 1 Subtest 2"'),
1046 test_log = '(127.0.0.1) Saving new serial number as sw_version_received'1140 call('(111.111.111.111) Updating software version')]
1047 mock_log.reset_mock()1141
10481142 # GIVEN: Test object
1049 # WHEN: process_sver called with invalid data1143 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
1050 pjlink.process_sver(data=test_data_new)1144 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
10511145 pjlink.sw_version = test_data_old
1052 # THEN: Version information should not change1146
1053 self.assertEqual(pjlink.sw_version, test_data_old, 'Software version should not have been updated')1147 # WHEN: process_sver called with invalid data
1054 self.assertEqual(pjlink.sw_version_received, test_data_new,1148 pjlink.process_sver(data=test_data_new)
1055 'Received software version should have been changed')1149
1056 self.assertEqual(mock_log.warning.call_count, 4, 'log.warn should have been called 4 times')1150 # THEN: Version information should not change
1057 # There was 4 calls, but only the last one is checked with this method1151 assert pjlink.sw_version == test_data_new, 'Software version should have changed'
1058 mock_log.warning.assert_called_with(test_log)1152 mock_log.warning.assert_has_calls(log_warn_calls)
10591153
1060 @patch.object(openlp.core.projectors.pjlink, 'log')1154 def test_projector_process_sver_invalid(self):
1061 def test_projector_process_sver_invalid(self, mock_log):
1062 """1155 """
1063 Test invalid software version information - too long1156 Test invalid software version information - too long
1064 """1157 """
1065 # GIVEN: Test object
1066 pjlink = pjlink_test
1067 pjlink.sw_version = None
1068 pjlink.sw_version_received = None
1069 test_data = 'This is a test software version line that is too long based on PJLink version 2 specs'1158 test_data = 'This is a test software version line that is too long based on PJLink version 2 specs'
1070 test_log = "Invalid software version - too long"1159 log_warn_calls = [call('Invalid software version - too long')]
1071 mock_log.reset_mock()1160
10721161 # GIVEN: Test object
1073 # WHEN: process_sver called with invalid data1162 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
1074 pjlink.process_sver(data=test_data)1163 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
10751164 pjlink.sw_version = None
1076 # THEN: Version information should not change1165
1077 self.assertIsNone(pjlink.sw_version, 'Software version should not have changed')1166 # WHEN: process_sver called with invalid data
1078 self.assertIsNone(pjlink.sw_version_received, 'Received software version should not have changed')1167 pjlink.process_sver(data=test_data)
1079 mock_log.warning.assert_called_once_with(test_log)1168
1169 # THEN: Version information should not change
1170 assert pjlink.sw_version is None, 'Software version should not have changed'
1171 assert pjlink.sw_version_received is None, 'Received software version should not have changed'
1172 mock_log.warning.assert_has_calls(log_warn_calls)
10801173
1081 def test_projector_reset_information(self):1174 def test_projector_reset_information(self):
1082 """1175 """
1083 Test reset_information() resets all information and stops timers1176 Test reset_information() resets all information and stops timers
1084 """1177 """
1085 # GIVEN: Test object and test data1178 log_debug_calls = [call('(111.111.111.111): Calling timer.stop()'),
1086 pjlink = pjlink_test1179 call('(111.111.111.111): Calling socket_timer.stop()')]
1087 pjlink.power = S_ON1180
1088 pjlink.pjlink_name = 'OPENLPTEST'1181 # GIVEN: Test object
1089 pjlink.manufacturer = 'PJLINK'1182 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
1090 pjlink.model = '1'1183 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
1091 pjlink.shutter = True1184 # timer and socket_timer not available until instantiation, so mock here
1092 pjlink.mute = True1185 with patch.object(pjlink, 'socket_timer') as mock_socket_timer, \
1093 pjlink.lamp = True1186 patch.object(pjlink, 'timer') as mock_timer:
1094 pjlink.fan = True1187
1095 pjlink.source_available = True1188 pjlink.power = S_ON
1096 pjlink.other_info = 'ANOTHER TEST'1189 pjlink.pjlink_name = 'OPENLPTEST'
1097 pjlink.send_queue = True1190 pjlink.manufacturer = 'PJLINK'
1098 pjlink.send_busy = True1191 pjlink.model = '1'
10991192 pjlink.shutter = True
1100 # WHEN: reset_information() is called1193 pjlink.mute = True
1101 with patch.object(pjlink, 'timer') as mock_timer:1194 pjlink.lamp = True
1102 with patch.object(pjlink, 'socket_timer') as mock_socket_timer:1195 pjlink.fan = True
1196 pjlink.source_available = True
1197 pjlink.other_info = 'ANOTHER TEST'
1198 pjlink.send_queue = True
1199 pjlink.send_busy = True
1200
1201 # WHEN: reset_information() is called
1103 pjlink.reset_information()1202 pjlink.reset_information()
11041203
1105 # THEN: All information should be reset and timers stopped1204 # THEN: All information should be reset and timers stopped
1106 self.assertEqual(pjlink.power, S_OFF, 'Projector power should be OFF')1205 assert pjlink.power == S_OFF, 'Projector power should be OFF'
1107 self.assertIsNone(pjlink.pjlink_name, 'Projector pjlink_name should be None')1206 assert pjlink.pjlink_name is None, 'Projector pjlink_name should be None'
1108 self.assertIsNone(pjlink.manufacturer, 'Projector manufacturer should be None')1207 assert pjlink.manufacturer is None, 'Projector manufacturer should be None'
1109 self.assertIsNone(pjlink.model, 'Projector model should be None')1208 assert pjlink.model is None, 'Projector model should be None'
1110 self.assertIsNone(pjlink.shutter, 'Projector shutter should be None')1209 assert pjlink.shutter is None, 'Projector shutter should be None'
1111 self.assertIsNone(pjlink.mute, 'Projector shuttter should be None')1210 assert pjlink.mute is None, 'Projector shuttter should be None'
1112 self.assertIsNone(pjlink.lamp, 'Projector lamp should be None')1211 assert pjlink.lamp is None, 'Projector lamp should be None'
1113 self.assertIsNone(pjlink.fan, 'Projector fan should be None')1212 assert pjlink.fan is None, 'Projector fan should be None'
1114 self.assertIsNone(pjlink.source_available, 'Projector source_available should be None')1213 assert pjlink.source_available is None, 'Projector source_available should be None'
1115 self.assertIsNone(pjlink.source, 'Projector source should be None')1214 assert pjlink.source is None, 'Projector source should be None'
1116 self.assertIsNone(pjlink.other_info, 'Projector other_info should be None')1215 assert pjlink.other_info is None, 'Projector other_info should be None'
1117 self.assertEqual(pjlink.send_queue, [], 'Projector send_queue should be an empty list')1216 assert pjlink.send_queue == [], 'Projector send_queue should be an empty list'
1118 self.assertFalse(pjlink.send_busy, 'Projector send_busy should be False')1217 assert pjlink.send_busy is False, 'Projector send_busy should be False'
1119 self.assertTrue(mock_timer.stop.called, 'Projector timer.stop() should have been called')1218 assert mock_timer.stop.called is True, 'Projector timer.stop() should have been called'
1120 self.assertTrue(mock_socket_timer.stop.called, 'Projector socket_timer.stop() should have been called')1219 assert mock_socket_timer.stop.called is True, 'Projector socket_timer.stop() should have been called'
1220 mock_log.debug.assert_has_calls(log_debug_calls)