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: 3657 lines (+1548/-1305)
7 files modified
openlp/core/projectors/constants.py (+296/-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 (+876/-777)
To merge this branch: bzr merge lp:~alisonken1/openlp/pjlink2-n
Reviewer Review Type Date Requested Status
Tim Bentley Needs Fixing
Review via email: mp+335588@code.launchpad.net

This proposal supersedes a proposal from 2017-12-25.

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

Commit message

PJLink 2 update N

Description of the change

--------------------------------------------------------------------------------
lp:~alisonken1/openlp/pjlink2-n (revision 2804)
https://ci.openlp.io/job/Branch-01-Pull/2394/ [SUCCESS]
https://ci.openlp.io/job/Branch-02a-Linux-Tests/2295/ [SUCCESS]
https://ci.openlp.io/job/Branch-02b-macOS-Tests/90/ [SUCCESS]
https://ci.openlp.io/job/Branch-03a-Build-Source/15/ [SUCCESS]
https://ci.openlp.io/job/Branch-03b-Build-macOS/14/ [SUCCESS]
https://ci.openlp.io/job/Branch-04a-Code-Analysis/1477/ [SUCCESS]
https://ci.openlp.io/job/Branch-04b-Test-Coverage/1290/ [SUCCESS]
https://ci.openlp.io/job/Branch-05-AppVeyor-Tests/247/ [FAILURE]

Large diff fixing projector tests

- 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.
Revision history for this message
Tim Bentley (trb143) wrote :

Some questions and old style asserts remain!

review: Needs Fixing
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-26 04:14:59 +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,
424496
=== 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-26 04:14:59 +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-26 04:14:59 +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(1024)
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-26 04:14:59 +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-26 04:14:59 +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-26 04:14:59 +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 assert pjlink.pjlink_functions.called is False, 'Should not have accessed pjlink_functions'
64 assert mock_buffer.called is True, '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 assert mock_disconnect.called is True, 'disconnect_from_host should have been called'
107 mock_log.error.assert_has_calls(log_error_calls)
108 mock_log.debug.assert_has_calls(log_debug_calls)
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 assert pjlink.pjlink_functions.called is False, 'Should not have accessed pjlink_functions'
222 assert mock_process_clss.called is False, '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-26 04:14:59 +0000
@@ -23,938 +23,1017 @@
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 assert pjlink.projector_status == S_OK, 'Projector status should not have changed'
87 mock_change_status.reset_mock()75 assert pjlink.status_connect == E_NOT_CONNECTED, 'Status connect should be NOT CONNECTED'
88 mock_log.reset_mock()76 assert mock_UpdateIcons.emit.called is True, 'Should have called UpdateIcons'
8977 mock_changeStatus.emit.assert_called_once_with(pjlink.ip, E_UNKNOWN_SOCKET_ERROR,
90 # WHEN: change_status called with unknown socket error78 STATUS_MSG[E_UNKNOWN_SOCKET_ERROR])
91 pjlink.change_status(status=test_code, msg=None)79
9280 def test_projector_change_status_connection_status_connecting(self):
93 # THEN: Proper settings should change and signals sent81 """
94 self.assertEqual(pjlink.projector_status, S_NOT_CONNECTED, 'Projector status should be NOT CONNECTED')82 Test change_status with connecting status
95 self.assertEqual(pjlink.status_connect, S_CONNECTING, 'Status connect should be CONNECTING')83 """
96 mock_change_status.emit.assert_called_once_with(pjlink.ip, S_CONNECTING, 'Connecting')84 log_debug_calls = [
97 self.assertEqual(mock_log.debug.call_count, 3, 'Debug log should have been called 3 times')85 call('(111.111.111.111) Changing status to '
9886 '{status} "{msg}"'.format(status=STATUS_CODE[S_CONNECTING],
99 @patch.object(pjlink_test, 'changeStatus')87 msg=STATUS_MSG[S_CONNECTING])),
100 @patch.object(openlp.core.projectors.pjlink, 'log')88 call('(111.111.111.111) status_connect: '
101 def test_projector_change_status_connection_status_connected(self, mock_log, mock_change_status):89 '{code}: "{msg}"'.format(code=STATUS_CODE[S_CONNECTING],
102 """90 msg=STATUS_MSG[S_CONNECTING])),
103 Test change_status with connection status91 call('(111.111.111.111) projector_status: '
104 """92 '{code}: "{msg}"'.format(code=STATUS_CODE[S_OK],
105 # GIVEN: Test object93 msg=STATUS_MSG[S_OK])),
106 pjlink = pjlink_test94 call('(111.111.111.111) error_status: '
107 pjlink.projector_status = 095 '{code}: "{msg}"'.format(code=STATUS_CODE[S_OK],
108 pjlink.status_connect = 096 msg=STATUS_MSG[S_OK]))]
109 test_code = S_ON97
110 mock_change_status.reset_mock()98 # GIVEN: Test object and mocks
111 mock_log.reset_mock()99 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
112100 patch.object(openlp.core.projectors.pjlink.PJLink, 'changeStatus') as mock_changeStatus, \
113 # WHEN: change_status called with unknown socket error101 patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons:
114 pjlink.change_status(status=test_code, msg=None)102
115103 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
116 # THEN: Proper settings should change and signals sent104 pjlink.projector_status = 0
117 self.assertEqual(pjlink.projector_status, S_ON, 'Projector status should be ON')105 pjlink.status_connect = 0
118 self.assertEqual(pjlink.status_connect, S_CONNECTED, 'Status connect should be CONNECTED')106
119 mock_change_status.emit.assert_called_once_with(pjlink.ip, S_ON, 'Power is on')107 # WHEN: change_status called with CONNECTING
120 self.assertEqual(mock_log.debug.call_count, 3, 'Debug log should have been called 3 times')108 pjlink.change_status(status=S_CONNECTING)
121109
122 @patch.object(pjlink_test, 'changeStatus')110 # THEN: Proper settings should change and signals sent
123 @patch.object(openlp.core.projectors.pjlink, 'log')111 mock_log.debug.assert_has_calls(log_debug_calls)
124 def test_projector_change_status_connection_status_with_message(self, mock_log, mock_change_status):112 mock_changeStatus.emit.assert_called_once_with(pjlink.ip, S_CONNECTING, STATUS_MSG[S_CONNECTING])
125 """113 assert pjlink.projector_status == S_OK, 'Projector status should not have changed'
126 Test change_status with connection status114 assert pjlink.status_connect == S_CONNECTING, 'Status connect should be CONNECTING'
127 """115 assert mock_UpdateIcons.emit.called is True, 'Should have called UpdateIcons'
128 # GIVEN: Test object116
129 pjlink = pjlink_test117 def test_projector_change_status_connection_status_connected(self):
130 pjlink.projector_status = 0118 """
131 pjlink.status_connect = 0119 Test change_status with connected status
120 """
121 log_debug_calls = [
122 call('(111.111.111.111) Changing status to '
123 '{status} "{msg}"'.format(status=STATUS_CODE[S_CONNECTED],
124 msg=STATUS_MSG[S_CONNECTED])),
125 call('(111.111.111.111) status_connect: '
126 '{code}: "{msg}"'.format(code=STATUS_CODE[S_CONNECTED],
127 msg=STATUS_MSG[S_CONNECTED])),
128 call('(111.111.111.111) projector_status: '
129 '{code}: "{msg}"'.format(code=STATUS_CODE[S_OK],
130 msg=STATUS_MSG[S_OK])),
131 call('(111.111.111.111) error_status: '
132 '{code}: "{msg}"'.format(code=STATUS_CODE[S_OK],
133 msg=STATUS_MSG[S_OK]))]
134
135 # GIVEN: Test object and mocks
136 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
137 patch.object(openlp.core.projectors.pjlink.PJLink, 'changeStatus') as mock_changeStatus:
138
139 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
140 pjlink.projector_status = 0
141 pjlink.status_connect = 0
142
143 # WHEN: change_status called with CONNECTED
144 pjlink.change_status(status=S_CONNECTED)
145
146 # THEN: Proper settings should change and signals sent
147 mock_log.debug.assert_has_calls(log_debug_calls)
148 mock_changeStatus.emit.assert_called_once_with(pjlink.ip, S_CONNECTED, 'Connected')
149 assert pjlink.projector_status == S_OK, 'Projector status should not have changed'
150 assert pjlink.status_connect == S_CONNECTED, 'Status connect should be CONNECTED'
151
152 def test_projector_change_status_connection_status_with_message(self):
153 """
154 Test change_status with connection status
155 """
132 test_message = 'Different Status Message than default'156 test_message = 'Different Status Message than default'
133 test_code = S_ON157 log_debug_calls = [
134 mock_change_status.reset_mock()158 call('(111.111.111.111) Changing status to {status} "{msg}"'.format(status=STATUS_CODE[S_ON],
135 mock_log.reset_mock()159 msg=test_message)),
136160 call('(111.111.111.111) status_connect: {code}: "{msg}"'.format(code=STATUS_CODE[S_OK],
137 # WHEN: change_status called with unknown socket error161 msg=test_message)),
138 pjlink.change_status(status=test_code, msg=test_message)162 call('(111.111.111.111) projector_status: {code}: "{msg}"'.format(code=STATUS_CODE[S_ON],
139163 msg=test_message)),
140 # THEN: Proper settings should change and signals sent164 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')165 msg=test_message))]
142 self.assertEqual(pjlink.status_connect, S_CONNECTED, 'Status connect should be CONNECTED')166
143 mock_change_status.emit.assert_called_once_with(pjlink.ip, S_ON, test_message)167 # GIVEN: Test object and mocks
144 self.assertEqual(mock_log.debug.call_count, 3, 'Debug log should have been called 3 times')168 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
145169 patch.object(openlp.core.projectors.pjlink.PJLink, 'changeStatus') as mock_changeStatus:
146 @patch.object(pjlink_test, 'send_command')170
147 @patch.object(openlp.core.projectors.pjlink, 'log')171 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
148 def test_projector_get_av_mute_status(self, mock_log, mock_send_command):172 pjlink.projector_status = 0
173 pjlink.status_connect = 0
174
175 # WHEN: change_status called with projector ON status
176 pjlink.change_status(status=S_ON, msg=test_message)
177
178 # THEN: Proper settings should change and signals sent
179 mock_log.debug.assert_has_calls(log_debug_calls)
180 mock_changeStatus.emit.assert_called_once_with(pjlink.ip, S_ON, test_message)
181 assert pjlink.projector_status == S_ON, 'Projector status should be ON'
182 assert pjlink.status_connect == S_OK, 'Status connect should not have changed'
183
184 def test_projector_get_av_mute_status(self):
149 """185 """
150 Test sending command to retrieve shutter/audio state186 Test sending command to retrieve shutter/audio state
151 """187 """
152 # GIVEN: Test object
153 pjlink = pjlink_test
154 mock_log.reset_mock()
155 mock_send_command.reset_mock()
156 test_data = 'AVMT'188 test_data = 'AVMT'
157 test_log = '(127.0.0.1) Sending AVMT command'189 log_debug_calls = [call('(111.111.111.111) reset_information() connect status is '
158190 '{state}'.format(state=STATUS_CODE[S_NOT_CONNECTED])),
159 # WHEN: get_av_mute_status is called191 call('(111.111.111.111) Sending {cmd} command'.format(cmd=test_data))]
160 pjlink.get_av_mute_status()192
161193 # GIVEN: Test object and mocks
162 # THEN: log data and send_command should have been called194 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
163 mock_log.debug.assert_called_once_with(test_log)195 patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command:
164 mock_send_command.assert_called_once_with(cmd=test_data)196 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
165197
166 @patch.object(pjlink_test, 'send_command')198 # WHEN: get_av_mute_status is called
167 @patch.object(openlp.core.projectors.pjlink, 'log')199 pjlink.get_av_mute_status()
168 def test_projector_get_available_inputs(self, mock_log, mock_send_command):200
201 # THEN: log data and send_command should have been called
202 mock_log.debug.assert_has_calls(log_debug_calls)
203 mock_send_command.assert_called_once_with(cmd=test_data)
204
205 def test_projector_get_available_inputs(self):
169 """206 """
170 Test sending command to retrieve avaliable inputs207 Test sending command to retrieve avaliable inputs
171 """208 """
172 # GIVEN: Test object
173 pjlink = pjlink_test
174 mock_log.reset_mock()
175 mock_send_command.reset_mock()
176 test_data = 'INST'209 test_data = 'INST'
177 test_log = '(127.0.0.1) Sending INST command'210 log_debug_calls = [call('(111.111.111.111) reset_information() connect status is '
178211 '{state}'.format(state=STATUS_CODE[S_NOT_CONNECTED])),
179 # WHEN: get_available_inputs is called212 call('(111.111.111.111) Sending {cmd} command'.format(cmd=test_data))]
180 pjlink.get_available_inputs()213
181214 # GIVEN: Test object and mocks
182 # THEN: log data and send_command should have been called215 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
183 mock_log.debug.assert_called_once_with(test_log)216 patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command:
184 mock_send_command.assert_called_once_with(cmd=test_data)217 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
185218
186 @patch.object(pjlink_test, 'send_command')219 # WHEN: get_available_inputs is called
187 @patch.object(openlp.core.projectors.pjlink, 'log')220 pjlink.get_available_inputs()
188 def test_projector_get_error_status(self, mock_log, mock_send_command):221
222 # THEN: log data and send_command should have been called
223 mock_log.debug.assert_has_calls(log_debug_calls)
224 mock_send_command.assert_called_once_with(cmd=test_data)
225
226 def test_projector_get_error_status(self):
189 """227 """
190 Test sending command to retrieve projector error status228 Test sending command to retrieve projector error status
191 """229 """
192 # GIVEN: Test object
193 pjlink = pjlink_test
194 mock_log.reset_mock()
195 mock_send_command.reset_mock()
196 test_data = 'ERST'230 test_data = 'ERST'
197 test_log = '(127.0.0.1) Sending ERST command'231 log_debug_calls = [call('(111.111.111.111) reset_information() connect status is '
198232 '{state}'.format(state=STATUS_CODE[S_NOT_CONNECTED])),
199 # WHEN: get_error_status is called233 call('(111.111.111.111) Sending {cmd} command'.format(cmd=test_data))]
200 pjlink.get_error_status()234 # GIVEN: Test object and mocks
201235 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
202 # THEN: log data and send_command should have been called236 patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command:
203 mock_log.debug.assert_called_once_with(test_log)237 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
204 mock_send_command.assert_called_once_with(cmd=test_data)238
205239 # WHEN: get_error_status is called
206 @patch.object(pjlink_test, 'send_command')240 pjlink.get_error_status()
207 @patch.object(openlp.core.projectors.pjlink, 'log')241
208 def test_projector_get_input_source(self, mock_log, mock_send_command):242 # THEN: log data and send_command should have been called
243 mock_log.debug.assert_has_calls(log_debug_calls)
244 mock_send_command.assert_called_once_with(cmd=test_data)
245
246 def test_projector_get_input_source(self):
209 """247 """
210 Test sending command to retrieve current input248 Test sending command to retrieve current input
211 """249 """
212 # GIVEN: Test object
213 pjlink = pjlink_test
214 mock_log.reset_mock()
215 mock_send_command.reset_mock()
216 test_data = 'INPT'250 test_data = 'INPT'
217 test_log = '(127.0.0.1) Sending INPT command'251 log_debug_calls = [call('(111.111.111.111) reset_information() connect status is '
218252 '{state}'.format(state=STATUS_CODE[S_NOT_CONNECTED])),
219 # WHEN: get_input_source is called253 call('(111.111.111.111) Sending {cmd} command'.format(cmd=test_data))]
220 pjlink.get_input_source()254
221255 # GIVEN: Test object and mocks
222 # THEN: log data and send_command should have been called256 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
223 mock_log.debug.assert_called_once_with(test_log)257 patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command:
224 mock_send_command.assert_called_once_with(cmd=test_data)258 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
225259
226 @patch.object(pjlink_test, 'send_command')260 # WHEN: get_input_source is called
227 @patch.object(openlp.core.projectors.pjlink, 'log')261 pjlink.get_input_source()
228 def test_projector_get_lamp_status(self, mock_log, mock_send_command):262
263 # THEN: log data and send_command should have been called
264 mock_log.debug.assert_has_calls(log_debug_calls)
265 mock_send_command.assert_called_once_with(cmd=test_data)
266
267 def test_projector_get_lamp_status(self):
229 """268 """
230 Test sending command to retrieve lamp(s) status269 Test sending command to retrieve lamp(s) status
231 """270 """
232 # GIVEN: Test object
233 pjlink = pjlink_test
234 mock_log.reset_mock()
235 mock_send_command.reset_mock()
236 test_data = 'LAMP'271 test_data = 'LAMP'
237 test_log = '(127.0.0.1) Sending LAMP command'272 log_debug_calls = [call('(111.111.111.111) reset_information() connect status is '
238273 '{state}'.format(state=STATUS_CODE[S_NOT_CONNECTED])),
239 # WHEN: get_lamp_status is called274 call('(111.111.111.111) Sending {cmd} command'.format(cmd=test_data))]
240 pjlink.get_lamp_status()275
241276 # GIVEN: Test object and mocks
242 # THEN: log data and send_command should have been called277 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
243 mock_log.debug.assert_called_once_with(test_log)278 patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command:
244 mock_send_command.assert_called_once_with(cmd=test_data)279 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
245280
246 @patch.object(pjlink_test, 'send_command')281 # WHEN: get_input_source is called
247 @patch.object(openlp.core.projectors.pjlink, 'log')282 pjlink.get_lamp_status()
248 def test_projector_get_manufacturer(self, mock_log, mock_send_command):283
284 # THEN: log data and send_command should have been called
285 mock_log.debug.assert_has_calls(log_debug_calls)
286 mock_send_command.assert_called_once_with(cmd=test_data)
287
288 def test_projector_get_manufacturer(self):
249 """289 """
250 Test sending command to retrieve manufacturer name290 Test sending command to retrieve manufacturer name
251 """291 """
252 # GIVEN: Test object
253 pjlink = pjlink_test
254 mock_log.reset_mock()
255 mock_send_command.reset_mock()
256 test_data = 'INF1'292 test_data = 'INF1'
257 test_log = '(127.0.0.1) Sending INF1 command'293 log_debug_calls = [call('(111.111.111.111) reset_information() connect status is '
258294 '{state}'.format(state=STATUS_CODE[S_NOT_CONNECTED])),
259 # WHEN: get_manufacturer is called295 call('(111.111.111.111) Sending {cmd} command'.format(cmd=test_data))]
260 pjlink.get_manufacturer()296
261297 # GIVEN: Test object and mocks
262 # THEN: log data and send_command should have been called298 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
263 mock_log.debug.assert_called_once_with(test_log)299 patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command:
264 mock_send_command.assert_called_once_with(cmd=test_data)300 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
265301
266 @patch.object(pjlink_test, 'send_command')302 # WHEN: get_input_source is called
267 @patch.object(openlp.core.projectors.pjlink, 'log')303 pjlink.get_manufacturer()
268 def test_projector_get_model(self, mock_log, mock_send_command):304
305 # THEN: log data and send_command should have been called
306 mock_log.debug.assert_has_calls(log_debug_calls)
307 mock_send_command.assert_called_once_with(cmd=test_data)
308
309 def test_projector_get_model(self):
269 """310 """
270 Test sending command to get model information311 Test sending command to get model information
271 """312 """
272 # GIVEN: Test object
273 pjlink = pjlink_test
274 mock_log.reset_mock()
275 mock_send_command.reset_mock()
276 test_data = 'INF2'313 test_data = 'INF2'
277 test_log = '(127.0.0.1) Sending INF2 command'314 log_debug_calls = [call('(111.111.111.111) reset_information() connect status is '
278315 '{state}'.format(state=STATUS_CODE[S_NOT_CONNECTED])),
279 # WHEN: get_model is called316 call('(111.111.111.111) Sending {cmd} command'.format(cmd=test_data))]
280 pjlink.get_model()317
281318 # GIVEN: Test object and mocks
282 # THEN: log data and send_command should have been called319 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
283 mock_log.debug.assert_called_once_with(test_log)320 patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command:
284 mock_send_command.assert_called_once_with(cmd=test_data)321 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
285322
286 @patch.object(pjlink_test, 'send_command')323 # WHEN: get_input_source is called
287 @patch.object(openlp.core.projectors.pjlink, 'log')324 pjlink.get_model()
288 def test_projector_get_name(self, mock_log, mock_send_command):325
326 # THEN: log data and send_command should have been called
327 mock_log.debug.assert_has_calls(log_debug_calls)
328 mock_send_command.assert_called_once_with(cmd=test_data)
329
330 def test_projector_get_name(self):
289 """331 """
290 Test sending command to get user-assigned name332 Test sending command to get user-assigned name
291 """333 """
292 # GIVEN: Test object
293 pjlink = pjlink_test
294 mock_log.reset_mock()
295 mock_send_command.reset_mock()
296 test_data = 'NAME'334 test_data = 'NAME'
297 test_log = '(127.0.0.1) Sending NAME command'335 log_debug_calls = [call('(111.111.111.111) reset_information() connect status is '
298336 '{state}'.format(state=STATUS_CODE[S_NOT_CONNECTED])),
299 # WHEN: get_name is called337 call('(111.111.111.111) Sending {cmd} command'.format(cmd=test_data))]
300 pjlink.get_name()338
301339 # GIVEN: Test object and mocks
302 # THEN: log data and send_command should have been called340 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
303 mock_log.debug.assert_called_once_with(test_log)341 patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command:
304 mock_send_command.assert_called_once_with(cmd=test_data)342 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
305343
306 @patch.object(pjlink_test, 'send_command')344 # WHEN: get_input_source is called
307 @patch.object(openlp.core.projectors.pjlink, 'log')345 pjlink.get_name()
308 def test_projector_get_other_info(self, mock_log, mock_send_command):346
347 # THEN: log data and send_command should have been called
348 mock_log.debug.assert_has_calls(log_debug_calls)
349 mock_send_command.assert_called_once_with(cmd=test_data)
350
351 def test_projector_get_other_info(self):
309 """352 """
310 Test sending command to retrieve other information353 Test sending command to retrieve other information
311 """354 """
312 # GIVEN: Test object
313 pjlink = pjlink_test
314 mock_log.reset_mock()
315 mock_send_command.reset_mock()
316 test_data = 'INFO'355 test_data = 'INFO'
317 test_log = '(127.0.0.1) Sending INFO command'356 log_debug_calls = [call('(111.111.111.111) reset_information() connect status is '
318357 '{state}'.format(state=STATUS_CODE[S_NOT_CONNECTED])),
319 # WHEN: get_other_info is called358 call('(111.111.111.111) Sending {cmd} command'.format(cmd=test_data))]
320 pjlink.get_other_info()359
321360 # GIVEN: Test object and mocks
322 # THEN: log data and send_command should have been called361 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
323 mock_log.debug.assert_called_once_with(test_log)362 patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command:
324 mock_send_command.assert_called_once_with(cmd=test_data)363 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
325364
326 @patch.object(pjlink_test, 'send_command')365 # WHEN: get_input_source is called
327 @patch.object(openlp.core.projectors.pjlink, 'log')366 pjlink.get_other_info()
328 def test_projector_get_power_status(self, mock_log, mock_send_command):367
368 # THEN: log data and send_command should have been called
369 mock_log.debug.assert_has_calls(log_debug_calls)
370 mock_send_command.assert_called_once_with(cmd=test_data)
371
372 def test_projector_get_power_status(self):
329 """373 """
330 Test sending command to retrieve current power state374 Test sending command to retrieve current power state
331 """375 """
332 # GIVEN: Test object
333 pjlink = pjlink_test
334 mock_log.reset_mock()
335 mock_send_command.reset_mock()
336 test_data = 'POWR'376 test_data = 'POWR'
337 test_log = '(127.0.0.1) Sending POWR command'377 log_debug_calls = [call('(111.111.111.111) reset_information() connect status is '
338378 '{state}'.format(state=STATUS_CODE[S_NOT_CONNECTED])),
339 # WHEN: get_power_status called379 call('(111.111.111.111) Sending {cmd} command'.format(cmd=test_data))]
340 pjlink.get_power_status()380
341381 # GIVEN: Test object and mocks
342 # THEN: log data and send_command should have been called382 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
343 mock_log.debug.assert_called_once_with(test_log)383 patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command:
344 mock_send_command.assert_called_once_with(cmd=test_data)384 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
345385
346 def test_projector_get_status_error(self):386 # WHEN: get_input_source is called
347 """387 pjlink.get_power_status()
348 Test to check returned information for error code388
349 """389 # THEN: log data and send_command should have been called
350 # GIVEN: Test object390 mock_log.debug.assert_has_calls(log_debug_calls)
351 pjlink = pjlink_test391 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')
361392
362 def test_projector_get_status_invalid(self):393 def test_projector_get_status_invalid(self):
363 """394 """
364 Test to check returned information for error code395 Test to check returned information for error code
365 """396 """
366 # GIVEN: Test object397 # GIVEN: Test object
367 pjlink = pjlink_test398 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
368 test_string = 'Test string since get_status will only work with int'399 test_string = 'NaN test'
369 test_message = 'Invalid status code'
370400
371 # WHEN: get_status called401 # WHEN: get_status called
372 string, message = pjlink._get_status(status=test_string)402 code, message = pjlink._get_status(status=test_string)
373403
374 # THEN: Proper strings should have been returned404 # THEN: Proper data should have been returned
375 self.assertEqual(string, -1, 'Should have returned -1 as a bad status check')405 assert code == -1, 'Should have returned -1 as a bad status check'
376 self.assertEqual(message, test_message, 'Error message should have been returned')406 assert message is None, 'Invalid code type should have returned None for message'
377407
378 def test_projector_get_status_status(self):408 def test_projector_get_status_valid(self):
379 """409 """
380 Test to check returned information for status codes410 Test to check returned information for status codes
381 """411 """
382 # GIVEN: Test object412 # GIVEN: Test object
383 pjlink = pjlink_test413 test_message = 'Not Connected'
384 test_string = 'S_NOT_CONNECTED'414 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
385 test_message = 'Not connected'
386415
387 # WHEN: get_status called416 # WHEN: get_status called
388 string, message = pjlink._get_status(status=S_NOT_CONNECTED)417 code, message = pjlink._get_status(status=S_NOT_CONNECTED)
389418
390 # THEN: Proper strings should have been returned419 # THEN: Proper strings should have been returned
391 self.assertEqual(string, test_string, 'Code as string should have been returned')420 assert 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')421 assert message == test_message, 'Description of code should have been returned'
393422
394 def test_projector_get_status_unknown(self):423 def test_projector_get_status_unknown(self):
395 """424 """
396 Test to check returned information for unknown code425 Test to check returned information for unknown code
397 """426 """
398 # GIVEN: Test object427 # GIVEN: Test object
399 pjlink = pjlink_test428 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
400 test_string = 999999
401 test_message = 'Unknown status'
402429
403 # WHEN: get_status called430 # WHEN: get_status called
404 string, message = pjlink._get_status(status=test_string)431 code, message = pjlink._get_status(status=9999)
405432
406 # THEN: Proper strings should have been returned433 # THEN: Proper strings should have been returned
407 self.assertEqual(string, test_string, 'Received code should have been returned')434 assert code is None, 'Code returned should have been the same code that was sent'
408 self.assertEqual(message, test_message, 'Unknown status string should have been returned')435 assert message is None, 'Should have returned None as message'
409436
410 def test_projector_process_inf1(self):437 def test_projector_process_inf1(self):
411 """438 """
412 Test saving INF1 data (manufacturer)439 Test saving INF1 data (manufacturer)
413 """440 """
441 test_data = 'TEst INformation MultiCase'
442
414 # GIVEN: Test object443 # GIVEN: Test object
415 pjlink = pjlink_test444 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
416 pjlink.manufacturer = None445 pjlink.manufacturer = None
417 test_data = 'TEst INformation MultiCase'
418446
419 # WHEN: process_inf called with test data447 # WHEN: process_inf called with test data
420 pjlink.process_inf1(data=test_data)448 pjlink.process_inf1(data=test_data)
421449
422 # THEN: Data should be saved450 # THEN: Data should be saved
423 self.assertEqual(pjlink.manufacturer, test_data, 'Test data should have been saved')451 assert pjlink.manufacturer == test_data, 'Test data should have been saved'
424452
425 def test_projector_process_inf2(self):453 def test_projector_process_inf2(self):
426 """454 """
427 Test saving INF2 data (model)455 Test saving INF2 data (model)
428 """456 """
457 test_data = 'TEst moDEl MultiCase'
458
429 # GIVEN: Test object459 # GIVEN: Test object
430 pjlink = pjlink_test460 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
431 pjlink.model = None461 pjlink.model = None
432 test_data = 'TEst moDEl MultiCase'
433462
434 # WHEN: process_inf called with test data463 # WHEN: process_inf called with test data
435 pjlink.process_inf2(data=test_data)464 pjlink.process_inf2(data=test_data)
436465
437 # THEN: Data should be saved466 # THEN: Data should be saved
438 self.assertEqual(pjlink.model, test_data, 'Test data should have been saved')467 assert pjlink.model == test_data, 'Test data should have been saved'
439468
440 def test_projector_process_info(self):469 def test_projector_process_info(self):
441 """470 """
442 Test saving INFO data (other information)471 Test saving INFO data (other information)
443 """472 """
473 test_data = 'TEst ExtrANEous MultiCase INformatoin that MFGR might Set'
474
444 # GIVEN: Test object475 # GIVEN: Test object
445 pjlink = pjlink_test476 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
446 pjlink.other_info = None477 pjlink.other_info = None
447 test_data = 'TEst ExtrANEous MultiCase INformatoin that MFGR might Set'
448478
449 # WHEN: process_inf called with test data479 # WHEN: process_inf called with test data
450 pjlink.process_info(data=test_data)480 pjlink.process_info(data=test_data)
451481
452 # THEN: Data should be saved482 # THEN: Data should be saved
453 self.assertEqual(pjlink.other_info, test_data, 'Test data should have been saved')483 assert pjlink.other_info == test_data, 'Test data should have been saved'
454484
455 @patch.object(pjlink_test, 'projectorUpdateIcons')485 def test_projector_process_avmt_bad_data(self):
456 def test_projector_process_avmt_bad_data(self, mock_UpdateIcons):
457 """486 """
458 Test avmt bad data fail487 Test avmt bad data fail
459 """488 """
460 # GIVEN: Test object489 # GIVEN: Test object
461 pjlink = pjlink_test490 with patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons:
462 pjlink.shutter = True491 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
463 pjlink.mute = True492 pjlink.shutter = True
464493 pjlink.mute = True
465 # WHEN: Called with an invalid setting494
466 pjlink.process_avmt('36')495 # WHEN: Called with an invalid setting
467496 pjlink.process_avmt('36')
468 # THEN: Shutter should be closed and mute should be True497
469 self.assertTrue(pjlink.shutter, 'Shutter should changed')498 # THEN: Shutter should be closed and mute should be True
470 self.assertTrue(pjlink.mute, 'Audio should not have changed')499 assert pjlink.shutter is True, 'Shutter should changed'
471 self.assertFalse(mock_UpdateIcons.emit.called, 'Update icons should NOT have been called')500 assert pjlink.mute is True, 'Audio should not have changed'
472501 assert mock_UpdateIcons.emit.called is False, 'Update icons should NOT have been called'
473 @patch.object(pjlink_test, 'projectorUpdateIcons')502
474 def test_projector_process_avmt_closed_muted(self, mock_UpdateIcons):503 def test_projector_process_avmt_closed_muted(self):
475 """504 """
476 Test avmt status shutter closed and mute off505 Test avmt status shutter closed and mute off
477 """506 """
478 # GIVEN: Test object507 # GIVEN: Test object
479 pjlink = pjlink_test508 with patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons:
480 pjlink.shutter = False509 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
481 pjlink.mute = False510 pjlink.shutter = False
482511 pjlink.mute = False
483 # WHEN: Called with setting shutter to closed and mute on512
484 pjlink.process_avmt('31')513 # WHEN: Called with setting shutter to closed and mute on
485514 pjlink.process_avmt('31')
486 # THEN: Shutter should be closed and mute should be True515
487 self.assertTrue(pjlink.shutter, 'Shutter should have been set to closed')516 # THEN: Shutter should be closed and mute should be True
488 self.assertTrue(pjlink.mute, 'Audio should be muted')517 assert pjlink.shutter is True, 'Shutter should have been set to closed'
489 self.assertTrue(mock_UpdateIcons.emit.called, 'Update icons should have been called')518 assert pjlink.mute is True, 'Audio should be muted'
490519 assert mock_UpdateIcons.emit.called is True, 'Update icons should have been called'
491 @patch.object(pjlink_test, 'projectorUpdateIcons')520
492 def test_projector_process_avmt_shutter_closed(self, mock_UpdateIcons):521 def test_projector_process_avmt_shutter_closed(self):
493 """522 """
494 Test avmt status shutter closed and audio unchanged523 Test avmt status shutter closed and audio unchanged
495 """524 """
496 # GIVEN: Test object525 # GIVEN: Test object
497 pjlink = pjlink_test526 with patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons:
498 pjlink.shutter = False527 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
499 pjlink.mute = True528 pjlink.shutter = False
500529 pjlink.mute = True
501 # WHEN: Called with setting shutter closed and mute off530
502 pjlink.process_avmt('11')531 # WHEN: Called with setting shutter closed and mute off
503532 pjlink.process_avmt('11')
504 # THEN: Shutter should be True and mute should be False533
505 self.assertTrue(pjlink.shutter, 'Shutter should have been set to closed')534 # THEN: Shutter should be True and mute should be False
506 self.assertTrue(pjlink.mute, 'Audio should not have changed')535 assert pjlink.shutter is True, 'Shutter should have been set to closed'
507 self.assertTrue(mock_UpdateIcons.emit.called, 'Update icons should have been called')536 assert pjlink.mute is True, 'Audio should not have changed'
508537 assert mock_UpdateIcons.emit.called is True, 'Update icons should have been called'
509 @patch.object(pjlink_test, 'projectorUpdateIcons')538
510 def test_projector_process_avmt_audio_muted(self, mock_UpdateIcons):539 def test_projector_process_avmt_audio_muted(self):
511 """540 """
512 Test avmt status shutter unchanged and mute on541 Test avmt status shutter unchanged and mute on
513 """542 """
514 # GIVEN: Test object543 # GIVEN: Test object
515 pjlink = pjlink_test544 with patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons:
516 pjlink.shutter = True545 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
517 pjlink.mute = False546 pjlink.shutter = True
518547 pjlink.mute = False
519 # WHEN: Called with setting shutter closed and mute on548
520 pjlink.process_avmt('21')549 # WHEN: Called with setting shutter closed and mute on
521550 pjlink.process_avmt('21')
522 # THEN: Shutter should be closed and mute should be True551
523 self.assertTrue(pjlink.shutter, 'Shutter should not have changed')552 # THEN: Shutter should be closed and mute should be True
524 self.assertTrue(pjlink.mute, 'Audio should be off')553 assert pjlink.shutter is True, 'Shutter should not have changed'
525 self.assertTrue(mock_UpdateIcons.emit.called, 'Update icons should have been called')554 assert pjlink.mute is True, 'Audio should be off'
526555 assert mock_UpdateIcons.emit.called is True, 'Update icons should have been called'
527 @patch.object(pjlink_test, 'projectorUpdateIcons')556
528 def test_projector_process_avmt_open_unmuted(self, mock_UpdateIcons):557 def test_projector_process_avmt_open_unmuted(self):
529 """558 """
530 Test avmt status shutter open and mute off559 Test avmt status shutter open and mute off
531 """560 """
532 # GIVEN: Test object561 # GIVEN: Test object
533 pjlink = pjlink_test562 with patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons:
534 pjlink.shutter = True563 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
535 pjlink.mute = True564 pjlink.shutter = True
536565 pjlink.mute = True
537 # WHEN: Called with setting shutter to closed and mute on566
538 pjlink.process_avmt('30')567 # WHEN: Called with setting shutter to closed and mute on
539568 pjlink.process_avmt('30')
540 # THEN: Shutter should be closed and mute should be True569
541 self.assertFalse(pjlink.shutter, 'Shutter should have been set to open')570 # THEN: Shutter should be closed and mute should be True
542 self.assertFalse(pjlink.mute, 'Audio should be on')571 assert pjlink.shutter is False, 'Shutter should have been set to open'
543 self.assertTrue(mock_UpdateIcons.emit.called, 'Update icons should have been called')572 assert pjlink.mute is False, 'Audio should be on'
573 assert mock_UpdateIcons.emit.called is True, 'Update icons should have been called'
544574
545 def test_projector_process_clss_one(self):575 def test_projector_process_clss_one(self):
546 """576 """
547 Test class 1 sent from projector577 Test class 1 sent from projector
548 """578 """
549 # GIVEN: Test object579 # GIVEN: Test object
550 pjlink = pjlink_test580 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
551581
552 # WHEN: Process class response582 # WHEN: Process class response
553 pjlink.process_clss('1')583 pjlink.process_clss('1')
554584
555 # THEN: Projector class should be set to 1585 # THEN: Projector class should be set to 1
556 self.assertEqual(pjlink.pjlink_class, '1',586 assert pjlink.pjlink_class == '1', 'Projector should have set class=1'
557 'Projector should have set class=1')
558587
559 def test_projector_process_clss_two(self):588 def test_projector_process_clss_two(self):
560 """589 """
561 Test class 2 sent from projector590 Test class 2 sent from projector
562 """591 """
563 # GIVEN: Test object592 # GIVEN: Test object
564 pjlink = pjlink_test593 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
565594
566 # WHEN: Process class response595 # WHEN: Process class response
567 pjlink.process_clss('2')596 pjlink.process_clss('2')
568597
569 # THEN: Projector class should be set to 1598 # THEN: Projector class should be set to 1
570 self.assertEqual(pjlink.pjlink_class, '2',599 assert pjlink.pjlink_class == '2', 'Projector should have set class=2'
571 'Projector should have set class=2')600
572601 def test_projector_process_clss_invalid_nan(self):
573 @patch.object(openlp.core.projectors.pjlink, 'log')602 """
574 def test_projector_process_clss_invalid_nan(self, mock_log):603 Test CLSS reply has no class number
575 """604 """
576 Test CLSS reply has no class number605 log_debug_calls = [call('(111.111.111.111) reset_information() connect status is '
577 """606 '{state}'.format(state=STATUS_CODE[S_NOT_CONNECTED])),
578 # GIVEN: Test object607 call('(111.111.111.111) Setting pjlink_class for this projector to "1"')]
579 pjlink = pjlink_test608 log_error_calls = [call('(111.111.111.111) NAN CLSS version reply "Z" - defaulting to class "1"')]
580609
581 # WHEN: Process invalid reply610 # GIVEN: Test object
582 pjlink.process_clss('Z')611 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"'612 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
584613
585 # THEN: Projector class should be set with default value614 # WHEN: Process invalid reply
586 self.assertEqual(pjlink.pjlink_class, '1',615 pjlink.process_clss('Z')
587 'Non-standard class reply should have set class=1')616
588 mock_log.error.assert_called_once_with(log_text)617 # THEN: Projector class should be set with default value
589618 assert pjlink.pjlink_class == '1', 'Invalid NaN class reply should have set class=1'
590 @patch.object(openlp.core.projectors.pjlink, 'log')619 mock_log.error.assert_has_calls(log_error_calls)
591 def test_projector_process_clss_invalid_no_version(self, mock_log):620 mock_log.debug.assert_has_calls(log_debug_calls)
592 """621
593 Test CLSS reply has no class number622 def test_projector_process_clss_invalid_no_version(self):
594 """623 """
595 # GIVEN: Test object624 Test CLSS reply has no class number
596 pjlink = pjlink_test625 """
597626 log_debug_calls = [call('(111.111.111.111) reset_information() connect status is '
598 # WHEN: Process invalid reply627 '{state}'.format(state=STATUS_CODE[S_NOT_CONNECTED])),
599 pjlink.process_clss('Invalid')628 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"'629 log_error_calls = [call('(111.111.111.111) No numbers found in class version reply "Invalid" '
601630 '- defaulting to class "1"')]
602 # THEN: Projector class should be set with default value631
603 self.assertEqual(pjlink.pjlink_class, '1',632 # GIVEN: Test object
604 'Non-standard class reply should have set class=1')633 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
605 mock_log.error.assert_called_once_with(log_text)634 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
635
636 # WHEN: Process invalid reply
637 pjlink.process_clss('Invalid')
638
639 # THEN: Projector class should be set with default value
640 assert pjlink.pjlink_class == '1', 'Invalid class reply should have set class=1'
641 mock_log.error.assert_has_calls(log_error_calls)
642 mock_log.debug.assert_has_calls(log_debug_calls)
606643
607 def test_projector_process_erst_all_ok(self):644 def test_projector_process_erst_all_ok(self):
608 """645 """
609 Test test_projector_process_erst_all_ok646 Test to verify pjlink.projector_errors is set to None when no errors
610 """647 """
648 chk_data = '0' * PJLINK_ERST_DATA['DATA_LENGTH']
649
611 # GIVEN: Test object650 # GIVEN: Test object
612 pjlink = pjlink_test651 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
613 chk_test = PJLINK_ERST_STATUS['OK']
614 chk_param = chk_test * len(PJLINK_ERST_POSITIONS)
615652
616 # WHEN: process_erst with no errors653 # WHEN: process_erst with no errors
617 pjlink.process_erst(chk_param)654 pjlink.process_erst(chk_data)
618655
619 # THEN: PJLink instance errors should be None656 # THEN: PJLink instance errors should be None
620 self.assertIsNone(pjlink.projector_errors, 'projector_errors should have been set to None')657 assert pjlink.projector_errors is None, 'projector_errors should have been set to None'
621658
622 @patch.object(openlp.core.projectors.pjlink, 'log')659 def test_projector_process_erst_data_invalid_length(self):
623 def test_projector_process_erst_data_invalid_length(self, mock_log):
624 """660 """
625 Test test_projector_process_erst_data_invalid_length661 Test test_projector_process_erst_data_invalid_length
626 """662 """
663 chk_data = '0' * (PJLINK_ERST_DATA['DATA_LENGTH'] + 1)
664 log_debug_calls = [call('(111.111.111.111) reset_information() connect status is '
665 '{state}'.format(state=STATUS_CODE[S_NOT_CONNECTED]))]
666 log_warn_calls = [call('111.111.111.111) Invalid error status response "0000000": '
667 'length != {chk}'.format(chk=PJLINK_ERST_DATA['DATA_LENGTH']))]
668
627 # GIVEN: Test object669 # GIVEN: Test object
628 pjlink = pjlink_test670 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
629 pjlink.projector_errors = None671 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
630 log_text = '127.0.0.1) Invalid error status response "11111111": length != 6'672 pjlink.projector_errors = None
631673
632 # WHEN: process_erst called with invalid data (too many values674 # WHEN: process_erst called with invalid data (too many values
633 pjlink.process_erst('11111111')675 pjlink.process_erst(chk_data)
634676
635 # THEN: pjlink.projector_errors should be empty and warning logged677 # THEN: pjlink.projector_errors should be empty and warning logged
636 self.assertIsNone(pjlink.projector_errors, 'There should be no errors')678 assert pjlink.projector_errors is None, 'There should be no errors'
637 self.assertTrue(mock_log.warning.called, 'Warning should have been logged')679 mock_log.debug.assert_has_calls(log_debug_calls)
638 mock_log.warning.assert_called_once_with(log_text)680 mock_log.warning.assert_has_calls(log_warn_calls)
639681
640 @patch.object(openlp.core.projectors.pjlink, 'log')682 def test_projector_process_erst_data_invalid_nan(self):
641 def test_projector_process_erst_data_invalid_nan(self, mock_log):
642 """683 """
643 Test test_projector_process_erst_data_invalid_nan684 Test test_projector_process_erst_data_invalid_nan
644 """685 """
686 chk_data = 'Z' + ('0' * (PJLINK_ERST_DATA['DATA_LENGTH'] - 1))
687 log_debug_calls = [call('(111.111.111.111) reset_information() connect status is '
688 '{state}'.format(state=STATUS_CODE[S_NOT_CONNECTED]))]
689 log_warn_calls = [call('(111.111.111.111) Invalid error status response "Z00000"')]
690
645 # GIVEN: Test object691 # GIVEN: Test object
646 pjlink = pjlink_test692 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
647 pjlink.projector_errors = None693 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
648 log_text = '(127.0.0.1) Invalid error status response "1111Z1"'694 pjlink.projector_errors = None
649695
650 # WHEN: process_erst called with invalid data (too many values696 # WHEN: process_erst called with invalid data (too many values
651 pjlink.process_erst('1111Z1')697 pjlink.process_erst(chk_data)
652698
653 # THEN: pjlink.projector_errors should be empty and warning logged699 # THEN: pjlink.projector_errors should be empty and warning logged
654 self.assertIsNone(pjlink.projector_errors, 'There should be no errors')700 assert pjlink.projector_errors is None, 'There should be no errors'
655 self.assertTrue(mock_log.warning.called, 'Warning should have been logged')701 mock_log.debug.assert_has_calls(log_debug_calls)
656 mock_log.warning.assert_called_once_with(log_text)702 mock_log.warning.assert_has_calls(log_warn_calls)
657703
658 def test_projector_process_erst_all_warn(self):704 def test_projector_process_erst_all_warn(self):
659 """705 """
660 Test test_projector_process_erst_all_warn706 Test test_projector_process_erst_all_warn
661 """707 """
708 chk_data = '{fan}{lamp}{temp}{cover}{filt}{other}'.format(fan=PJLINK_ERST_STATUS[E_WARN],
709 lamp=PJLINK_ERST_STATUS[E_WARN],
710 temp=PJLINK_ERST_STATUS[E_WARN],
711 cover=PJLINK_ERST_STATUS[E_WARN],
712 filt=PJLINK_ERST_STATUS[E_WARN],
713 other=PJLINK_ERST_STATUS[E_WARN])
714 chk_test = {'Fan': E_WARN,
715 'Lamp': E_WARN,
716 'Temperature': E_WARN,
717 'Cover': E_WARN,
718 'Filter': E_WARN,
719 'Other': E_WARN}
720
662 # GIVEN: Test object721 # GIVEN: Test object
663 pjlink = pjlink_test722 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
664 chk_test = PJLINK_ERST_STATUS[E_WARN]723 pjlink.projector_errors = None
665 chk_string = ERROR_STRING[E_WARN]
666 chk_param = chk_test * len(PJLINK_ERST_POSITIONS)
667724
668 # WHEN: process_erst with status set to WARN725 # WHEN: process_erst with status set to WARN
669 pjlink.process_erst(chk_param)726 pjlink.process_erst(chk_data)
670727
671 # THEN: PJLink instance errors should match chk_value728 # THEN: PJLink instance errors should match chk_value
672 for chk in pjlink.projector_errors:729 assert 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))
676730
677 def test_projector_process_erst_all_error(self):731 def test_projector_process_erst_all_error(self):
678 """732 """
679 Test test_projector_process_erst_all_error733 Test test_projector_process_erst_all_error
680 """734 """
735 chk_data = '{fan}{lamp}{temp}{cover}{filt}{other}'.format(fan=PJLINK_ERST_STATUS[E_ERROR],
736 lamp=PJLINK_ERST_STATUS[E_ERROR],
737 temp=PJLINK_ERST_STATUS[E_ERROR],
738 cover=PJLINK_ERST_STATUS[E_ERROR],
739 filt=PJLINK_ERST_STATUS[E_ERROR],
740 other=PJLINK_ERST_STATUS[E_ERROR])
741 chk_test = {'Fan': E_ERROR,
742 'Lamp': E_ERROR,
743 'Temperature': E_ERROR,
744 'Cover': E_ERROR,
745 'Filter': E_ERROR,
746 'Other': E_ERROR}
747
681 # GIVEN: Test object748 # GIVEN: Test object
682 pjlink = pjlink_test749 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
683 chk_test = PJLINK_ERST_STATUS[E_ERROR]750 pjlink.projector_errors = None
684 chk_string = ERROR_STRING[E_ERROR]
685 chk_param = chk_test * len(PJLINK_ERST_POSITIONS)
686751
687 # WHEN: process_erst with status set to WARN752 # WHEN: process_erst with status set to WARN
688 pjlink.process_erst(chk_param)753 pjlink.process_erst(chk_data)
689754
690 # THEN: PJLink instance errors should match chk_value755 # THEN: PJLink instance errors should match chk_value
691 for chk in pjlink.projector_errors:756 assert 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))
695757
696 def test_projector_process_erst_warn_cover_only(self):758 def test_projector_process_erst_warn_cover_only(self):
697 """759 """
698 Test test_projector_process_erst_warn_cover_only760 Test test_projector_process_erst_warn_cover_only
699 """761 """
762 chk_data = '{fan}{lamp}{temp}{cover}{filt}{other}'.format(fan=PJLINK_ERST_STATUS[S_OK],
763 lamp=PJLINK_ERST_STATUS[S_OK],
764 temp=PJLINK_ERST_STATUS[S_OK],
765 cover=PJLINK_ERST_STATUS[E_WARN],
766 filt=PJLINK_ERST_STATUS[S_OK],
767 other=PJLINK_ERST_STATUS[S_OK])
768 chk_test = {'Cover': E_WARN}
769
700 # GIVEN: Test object770 # GIVEN: Test object
701 pjlink = pjlink_test771 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
702 chk_test = PJLINK_ERST_STATUS[E_WARN]772 pjlink.projector_errors = None
703 chk_string = ERROR_STRING[E_WARN]773
704 pos = PJLINK_ERST_DATA['COVER']774 # WHEN: process_erst with status set to WARN
705 build_chk = []775 pjlink.process_erst(chk_data)
706 for check in range(0, len(PJLINK_ERST_POSITIONS)):776
707 if check == pos:777 # THEN: PJLink instance errors should match only cover warning
708 build_chk.append(chk_test)778 assert 1 == len(pjlink.projector_errors), 'There should only be 1 error listed in projector_errors'
709 else:779 assert 'Cover' in pjlink.projector_errors, '"Cover" should be the only error listed'
710 build_chk.append(PJLINK_ERST_STATUS['OK'])780 assert pjlink.projector_errors['Cover'] == E_WARN, '"Cover" should have E_WARN listed as error'
711 chk_param = ''.join(build_chk)781 assert chk_test == pjlink.projector_errors, 'projector_errors should match test errors'
712782
713 # WHEN: process_erst with cover only set to WARN and all others set to OK783 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 """784 """
725 Test input source status shows current input785 Test input source status shows current input
726 """786 """
787 log_debug_calls = [call('(111.111.111.111) reset_information() connect status is S_NOT_CONNECTED')]
788 chk_source_available = ['11', '12', '21', '22', '31', '32']
789
727 # GIVEN: Test object790 # GIVEN: Test object
728 pjlink = pjlink_test791 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
729 pjlink.source = '0'792 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
730793 pjlink.source_available = chk_source_available
731 # WHEN: Called with input source794 pjlink.source = '11'
732 pjlink.process_inpt('1')795
733796 # WHEN: Called with input source
734 # THEN: Input selected should reflect current input797 pjlink.process_inpt('21')
735 self.assertEqual(pjlink.source, '1', 'Input source should be set to "1"')798
736799 # THEN: Input selected should reflect current input
737 @patch.object(pjlink_test, 'projectorUpdateIcons')800 assert pjlink.source == '21', 'Input source should be set to "21"'
738 @patch.object(openlp.core.projectors.pjlink, 'log')801 mock_log.debug.assert_has_calls(log_debug_calls)
739 def test_projector_process_inst(self, mock_log, mock_UpdateIcons):802
803 def test_projector_process_input_not_in_list(self):
804 """
805 Test setting input outside of available inputs
806
807 TODO: Future test
808 """
809 pass
810
811 def test_projector_process_input_not_in_default(self):
812 """
813 Test setting input with no sources available
814 TODO: Future test
815 """
816 pass
817
818 def test_projector_process_input_invalid(self):
819 """
820 Test setting input with an invalid value
821
822 TODO: Future test
823 """
824
825 def test_projector_process_inst_class_1(self):
740 """826 """
741 Test saving video source available information827 Test saving video source available information
742 """828 """
829 log_debug_calls = [call('(111.111.111.111) Setting projector sources_available to '
830 '"[\'11\', \'12\', \'21\', \'22\', \'31\', \'32\']"')]
831 chk_data = '21 12 11 22 32 31' # Although they should already be sorted, use unsorted to verify method
832 chk_test = ['11', '12', '21', '22', '31', '32']
833
743 # GIVEN: Test object834 # GIVEN: Test object
744 pjlink = pjlink_test835 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
745 pjlink.source_available = []836 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
746 test_data = '21 10 30 31 11 20'837 pjlink.source_available = []
747 test_saved = ["10", "11", "20", "21", "30", "31"]838
748 log_data = "(127.0.0.1) Setting projector sources_available to " \839 # WHEN: process_inst called with test data
749 "\"['10', '11', '20', '21', '30', '31']\""840 pjlink.process_inst(data=chk_data)
750 mock_UpdateIcons.reset_mock()841
751 mock_log.reset_mock()842 # THEN: Data should have been sorted and saved properly
752843 assert pjlink.source_available == chk_test, "Sources should have been sorted and saved"
753 # WHEN: process_inst called with test data844 mock_log.debug.assert_has_calls(log_debug_calls)
754 pjlink.process_inst(data=test_data)845
755846 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 """847 """
764 Test status multiple lamp on/off and hours848 Test status multiple lamp on/off and hours
765 """849 """
850 log_data = [call('(111.111.111.111) process_lamp(): Invalid data "11111 1 22222 0 333A3 1"')]
851
766 # GIVEN: Test object852 # GIVEN: Test object
767 pjlink = pjlink_test853 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
768 pjlink.lamp = [{'Hours': 00000, 'On': True},854 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
769 {'Hours': 11111, 'On': False}]855 pjlink.lamp = [{'Hours': 00000, 'On': True},
770 log_data = '(127.0.0.1) process_lamp(): Invalid data "11111 1 22222 0 333A3 1"'856 {'Hours': 11111, 'On': False}]
771857
772 # WHEN: Call process_command with invalid lamp data858 # WHEN: Call process_command with invalid lamp data
773 pjlink.process_lamp('11111 1 22222 0 333A3 1')859 pjlink.process_lamp('11111 1 22222 0 333A3 1')
774860
775 # THEN: lamps should not have changed861 # THEN: lamps should not have changed
776 self.assertEqual(len(pjlink.lamp), 2,862 assert 2 == len(pjlink.lamp), 'Projector should have kept 2 lamps specified'
777 'Projector should have kept 2 lamps specified')863 assert pjlink.lamp[0]['On'] is True, 'Lamp 1 power status should have stayed TRUE'
778 self.assertEqual(pjlink.lamp[0]['On'], True,864 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')865 assert pjlink.lamp[1]['On'] is False, 'Lamp 2 power status should have stayed FALSE'
780 self.assertEqual(pjlink.lamp[0]['Hours'], 00000,866 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')867 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)
787868
788 def test_projector_process_lamp_multiple(self):869 def test_projector_process_lamp_multiple(self):
789 """870 """
790 Test status multiple lamp on/off and hours871 Test status multiple lamp on/off and hours
791 """872 """
792 # GIVEN: Test object873 # GIVEN: Test object
793 pjlink = pjlink_test874 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
794 pjlink.lamps = []875 pjlink.lamp = []
795876
796 # WHEN: Call process_command with lamp data877 # WHEN: Call process_command with invalid lamp data
797 pjlink.process_lamp('11111 1 22222 0 33333 1')878 pjlink.process_lamp('11111 1 22222 0 33333 1')
798879
799 # THEN: Lamp should have been set with proper lamp status880 # THEN: Lamp should have been set with proper lamp status
800 self.assertEqual(len(pjlink.lamp), 3,881 assert 3 == len(pjlink.lamp), 'Projector should have 3 lamps specified'
801 'Projector should have 3 lamps specified')882 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,883 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')884 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,885 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')886 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,887 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')
814888
815 def test_projector_process_lamp_single(self):889 def test_projector_process_lamp_single(self):
816 """890 """
817 Test status lamp on/off and hours891 Test status lamp on/off and hours
818 """892 """
893
819 # GIVEN: Test object894 # GIVEN: Test object
820 pjlink = pjlink_test895 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
821 pjlink.lamps = []896 pjlink.lamp = []
822897
823 # WHEN: Call process_command with lamp data898 # WHEN: Call process_command with invalid lamp data
824 pjlink.process_lamp('22222 1')899 pjlink.process_lamp('22222 1')
825900
826 # THEN: Lamp should have been set with status=ON and hours=22222901 # THEN: Lamp should have been set with status=ON and hours=22222
827 self.assertEqual(pjlink.lamp[0]['On'], True,902 assert 1 == len(pjlink.lamp), 'Projector should have only 1 lamp'
828 'Lamp power status should have been set to TRUE')903 assert pjlink.lamp[0]['On'] is True, 'Lamp power status should have been set to TRUE'
829 self.assertEqual(pjlink.lamp[0]['Hours'], 22222,904 assert 22222 == pjlink.lamp[0]['Hours'], 'Lamp hours should have been set to 22222'
830 'Lamp hours should have been set to 22222')
831905
832 @patch.object(openlp.core.projectors.pjlink, 'log')906 def test_projector_process_name(self):
833 def test_projector_process_name(self, mock_log):
834 """907 """
835 Test saving NAME data from projector908 Test saving NAME data from projector
836 """909 """
837 # GIVEN: Test data910 chk_data = "Some Name the End-User Set IN Projector"
838 pjlink = pjlink_test911 log_debug_calls = [call('(111.111.111.111) Setting projector PJLink name to '
839 test_data = "Some Name the End-User Set IN Projector"912 '"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"'913
841 mock_log.reset_mock()914 # GIVEN: Test object
842915 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
843 # WHEN: process_name called with test data916 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
844 pjlink.process_name(data=test_data)917
845918 # WHEN: process_name called with test data
846 # THEN: name should be set and logged919 pjlink.process_name(data=chk_data)
847 self.assertEqual(pjlink.pjlink_name, test_data, 'Name test data should have been saved')920
848 mock_log.debug.assert_called_once_with(test_log)921 # THEN: name should be set and logged
849922 assert pjlink.pjlink_name == chk_data, 'Name test data should have been saved'
850 @patch.object(pjlink_test, 'projectorUpdateIcons')923 mock_log.debug.assert_has_calls(log_debug_calls)
851 @patch.object(pjlink_test, 'send_command')924
852 @patch.object(pjlink_test, 'change_status')925 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 """926 """
858 Test status power to ON927 Test status power to ON
859 """928 """
860 # GIVEN: Test object and preset929 # GIVEN: Test object
861 pjlink = pjlink_test930 with patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command, \
862 pjlink.power = S_STANDBY931 patch.object(openlp.core.projectors.pjlink.PJLink, 'change_status') as mock_change_status, \
863 test_data = PJLINK_POWR_STATUS[S_ON]932 patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons:
864933
865 # WHEN: Call process_command with turn power on command934 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
866 pjlink.process_command(cmd='POWR', data=test_data)935 pjlink.power = S_STANDBY
867936
868 # THEN: Power should be set to ON937 # WHEN: process_name called with test data
869 self.assertEqual(pjlink.power, S_ON, 'Power should have been set to ON')938 pjlink.process_powr(data=PJLINK_POWR_STATUS[S_ON])
870 mock_send_command.assert_called_once_with('INST')939
871 mock_change_status.assert_called_once_with(PJLINK_POWR_STATUS[test_data])940 # THEN: Power should be set to ON
872 self.assertEqual(mock_UpdateIcons.emit.called, True, 'projectorUpdateIcons should have been called')941 assert pjlink.power == S_ON, 'Power should have been set to ON'
873942 assert mock_UpdateIcons.emit.called is True, 'projectorUpdateIcons should have been called'
874 @patch.object(pjlink_test, 'projectorUpdateIcons')943 mock_send_command.assert_called_once_with('INST')
875 @patch.object(pjlink_test, 'send_command')944 mock_change_status.assert_called_once_with(S_ON)
876 @patch.object(pjlink_test, 'change_status')945
877 def test_projector_process_powr_invalid(self,946 def test_projector_process_powr_invalid(self):
878 mock_change_status,
879 mock_send_command,
880 mock_UpdateIcons):
881 """947 """
882 Test process_powr invalid call948 Test process_powr invalid call
883 """949 """
884 # GIVEN: Test object and preset950 log_warn_calls = [call('(111.111.111.111) Unknown power response: "99"')]
885 pjlink = pjlink_test951
886 pjlink.power = S_STANDBY952 # GIVEN: Test object
887 test_data = '99'953 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
888954 patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command, \
889 # WHEN: Call process_command with turn power on command955 patch.object(openlp.core.projectors.pjlink.PJLink, 'change_status') as mock_change_status, \
890 pjlink.process_command(cmd='POWR', data=test_data)956 patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons:
891957
892 # THEN: Power should be set to ON958 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
893 self.assertEqual(pjlink.power, S_STANDBY, 'Power should not have changed')959 pjlink.power = S_STANDBY
894 self.assertFalse(mock_change_status.called, 'Change status should not have been called')960
895 self.assertFalse(mock_send_command.called, 'send_command("INST") should not have been called')961 # WHEN: process_name called with test data
896 self.assertFalse(mock_UpdateIcons.emit.called, 'projectorUpdateIcons should not have been called')962 pjlink.process_powr(data='99')
897963
898 @patch.object(pjlink_test, 'projectorUpdateIcons')964 # THEN: Power should be set to ON
899 @patch.object(pjlink_test, 'send_command')965 assert pjlink.power == S_STANDBY, 'Power should not have changed'
900 @patch.object(pjlink_test, 'change_status')966 assert mock_UpdateIcons.emit.called is False, 'projectorUpdateIcons() should not have been called'
901 def test_projector_process_powr_off(self,967 mock_change_status.called is False, 'change_status() should not have been called'
902 mock_change_status,968 mock_send_command.called is False, 'send_command() should not have been called'
903 mock_send_command,969 mock_log.warning.assert_has_calls(log_warn_calls)
904 mock_UpdateIcons):970
971 def test_projector_process_powr_off(self):
905 """972 """
906 Test status power to STANDBY973 Test status power to STANDBY
907 """974 """
908 # GIVEN: Test object and preset975 # GIVEN: Test object
909 pjlink = pjlink_test976 with patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command, \
910 pjlink.power = S_ON977 patch.object(openlp.core.projectors.pjlink.PJLink, 'change_status') as mock_change_status, \
911 test_data = PJLINK_POWR_STATUS[S_STANDBY]978 patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons:
912979
913 # WHEN: Call process_command with turn power on command980 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
914 pjlink.process_command(cmd='POWR', data=test_data)981 pjlink.power = S_ON
915982
916 # THEN: Power should be set to STANDBY983 # WHEN: process_name called with test data
917 self.assertEqual(pjlink.power, S_STANDBY, 'Power should have been set to STANDBY')984 pjlink.process_powr(data=PJLINK_POWR_STATUS[S_STANDBY])
918 self.assertEqual(mock_UpdateIcons.emit.called, True, 'projectorUpdateIcons should have been called')985
919 mock_change_status.assert_called_once_with(PJLINK_POWR_STATUS[test_data])986 # THEN: Power should be set to ON
920 self.assertFalse(mock_send_command.called, "send_command['INST'] should not have been called")987 assert pjlink.power == S_STANDBY, 'Power should have changed to S_STANDBY'
988 assert mock_UpdateIcons.emit.called is True, 'projectorUpdateIcons should have been called'
989 mock_change_status.called is True, 'change_status should have been called'
990 mock_send_command.called is False, 'send_command should not have been called'
921991
922 def test_projector_process_rfil_save(self):992 def test_projector_process_rfil_save(self):
923 """993 """
924 Test saving filter type994 Test saving filter type
925 """995 """
996 filter_model = 'Filter Type Test'
997
926 # GIVEN: Test object998 # GIVEN: Test object
927 pjlink = pjlink_test999 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
928 pjlink.model_filter = None1000 pjlink.model_filter = None
929 filter_model = 'Filter Type Test'
9301001
931 # WHEN: Filter model is received1002 # WHEN: Filter model is received
932 pjlink.process_rfil(data=filter_model)1003 pjlink.process_rfil(data=filter_model)
9331004
934 # THEN: Filter model number should be saved1005 # THEN: Filter model number should be saved
935 self.assertEqual(pjlink.model_filter, filter_model, 'Filter type should have been saved')1006 assert pjlink.model_filter == filter_model, 'Filter type should have been saved'
9361007
937 def test_projector_process_rfil_nosave(self):1008 def test_projector_process_rfil_nosave(self):
938 """1009 """
939 Test saving filter type previously saved1010 Test saving filter type previously saved
940 """1011 """
1012 filter_model = 'Filter Type Test'
1013 log_warn_calls = [call('(111.111.111.111) Filter model already set'),
1014 call('(111.111.111.111) Saved model: "Old filter type"'),
1015 call('(111.111.111.111) New model: "Filter Type Test"')]
1016
941 # GIVEN: Test object1017 # GIVEN: Test object
942 pjlink = pjlink_test1018 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
943 pjlink.model_filter = 'Old filter type'1019
944 filter_model = 'Filter Type Test'1020 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
9451021 pjlink.model_filter = 'Old filter type'
946 # WHEN: Filter model is received1022
947 pjlink.process_rfil(data=filter_model)1023 # WHEN: Filter model is received
9481024 pjlink.process_rfil(data=filter_model)
949 # THEN: Filter model number should be saved1025
950 self.assertNotEquals(pjlink.model_filter, filter_model, 'Filter type should NOT have been saved')1026 # THEN: Filter model number should be saved
1027 assert pjlink.model_filter != filter_model, 'Filter type should NOT have been saved'
1028 mock_log.warning.assert_has_calls(log_warn_calls)
9511029
952 def test_projector_process_rlmp_save(self):1030 def test_projector_process_rlmp_save(self):
953 """1031 """
954 Test saving lamp type1032 Test saving lamp type
955 """1033 """
956 # GIVEN: Test object1034 # GIVEN: Test object
957 pjlink = pjlink_test1035 # GIVEN: Test object
1036 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
958 pjlink.model_lamp = None1037 pjlink.model_lamp = None
959 lamp_model = 'Lamp Type Test'1038 lamp_model = 'Lamp Type Test'
9601039
@@ -962,159 +1041,179 @@
962 pjlink.process_rlmp(data=lamp_model)1041 pjlink.process_rlmp(data=lamp_model)
9631042
964 # THEN: Filter model number should be saved1043 # THEN: Filter model number should be saved
965 self.assertEqual(pjlink.model_lamp, lamp_model, 'Lamp type should have been saved')1044 assert pjlink.model_lamp == lamp_model, 'Lamp type should have been saved'
9661045
967 def test_projector_process_rlmp_nosave(self):1046 def test_projector_process_rlmp_nosave(self):
968 """1047 """
969 Test saving lamp type previously saved1048 Test saving lamp type previously saved
970 """1049 """
1050 lamp_model = 'Lamp Type Test'
1051 log_warn_calls = [call('(111.111.111.111) Lamp model already set'),
1052 call('(111.111.111.111) Saved lamp: "Old lamp type"'),
1053 call('(111.111.111.111) New lamp: "Lamp Type Test"')]
1054
971 # GIVEN: Test object1055 # GIVEN: Test object
972 pjlink = pjlink_test1056 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
973 pjlink.model_lamp = 'Old lamp type'1057
974 lamp_model = 'Filter Type Test'1058 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
9751059 pjlink.model_lamp = 'Old lamp type'
976 # WHEN: Filter model is received1060
977 pjlink.process_rlmp(data=lamp_model)1061 # WHEN: Filter model is received
9781062 pjlink.process_rlmp(data=lamp_model)
979 # THEN: Filter model number should be saved1063
980 self.assertNotEquals(pjlink.model_lamp, lamp_model, 'Lamp type should NOT have been saved')1064 # THEN: Filter model number should be saved
1065 assert pjlink.model_lamp != lamp_model, 'Lamp type should NOT have been saved'
1066 mock_log.warning.assert_has_calls(log_warn_calls)
9811067
982 def test_projector_process_snum_set(self):1068 def test_projector_process_snum_set(self):
983 """1069 """
984 Test saving serial number from projector1070 Test saving serial number from projector
985 """1071 """
1072 log_debug_calls = [call('(111.111.111.111) Setting projector serial number to "Test Serial Number"')]
1073 test_number = 'Test Serial Number'
1074
986 # GIVEN: Test object1075 # GIVEN: Test object
987 pjlink = pjlink_test1076 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
988 pjlink.serial_no = None1077
989 test_number = 'Test Serial Number'1078 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
9901079 pjlink.serial_no = None
991 # WHEN: No serial number is set and we receive serial number command1080
992 pjlink.process_snum(data=test_number)1081 # WHEN: No serial number is set and we receive serial number command
9931082 pjlink.process_snum(data=test_number)
994 # THEN: Serial number should be set1083
995 self.assertEqual(pjlink.serial_no, test_number,1084 # THEN: Serial number should be set
996 'Projector serial number should have been set')1085 assert pjlink.serial_no == test_number, 'Projector serial number should have been set'
1086 mock_log.debug.assert_has_calls(log_debug_calls)
9971087
998 def test_projector_process_snum_different(self):1088 def test_projector_process_snum_different(self):
999 """1089 """
1000 Test projector serial number different than saved serial number1090 Test projector serial number different than saved serial number
1001 """1091 """
1002 # GIVEN: Test object1092 log_warn_calls = [call('(111.111.111.111) Projector serial number does not match saved serial number'),
1003 pjlink = pjlink_test1093 call('(111.111.111.111) Saved: "Previous serial number"'),
1004 pjlink.serial_no = 'Previous serial number'1094 call('(111.111.111.111) Received: "Test Serial Number"'),
1095 call('(111.111.111.111) NOT saving serial number')]
1005 test_number = 'Test Serial Number'1096 test_number = 'Test Serial Number'
10061097
1007 # WHEN: No serial number is set and we receive serial number command1098 # GIVEN: Test object
1008 pjlink.process_snum(data=test_number)1099 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
10091100 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
1010 # THEN: Serial number should be set1101 pjlink.serial_no = 'Previous serial number'
1011 self.assertNotEquals(pjlink.serial_no, test_number,1102
1012 'Projector serial number should NOT have been set')1103 # WHEN: No serial number is set and we receive serial number command
10131104 pjlink.process_snum(data=test_number)
1014 @patch.object(openlp.core.projectors.pjlink, 'log')1105
1015 def test_projector_process_sver(self, mock_log):1106 # THEN: Serial number should be set
1107 assert pjlink.serial_no != test_number, 'Projector serial number should NOT have been set'
1108 mock_log.warning.assert_has_calls(log_warn_calls)
1109
1110 def test_projector_process_sver(self):
1016 """1111 """
1017 Test invalid software version information - too long1112 Test invalid software version information - too long
1018 """1113 """
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'1114 test_data = 'Test 1 Subtest 1'
1024 test_log = '(127.0.0.1) Setting projector software version to "Test 1 Subtest 1"'1115 log_debug_calls = [call('(111.111.111.111) Setting projector software version to "Test 1 Subtest 1"')]
1025 mock_log.reset_mock()1116
10261117 # GIVEN: Test object
1027 # WHEN: process_sver called with invalid data1118 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
1028 pjlink.process_sver(data=test_data)1119 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
10291120 pjlink.sw_version = None
1030 # THEN: Version information should not change1121 pjlink.sw_version_received = None
1031 self.assertEqual(pjlink.sw_version, test_data, 'Software version should have been updated')1122
1032 self.assertIsNone(pjlink.sw_version_received, 'Received software version should not have changed')1123 # WHEN: process_sver called with invalid data
1033 mock_log.debug.assert_called_once_with(test_log)1124 pjlink.process_sver(data=test_data)
10341125
1035 @patch.object(openlp.core.projectors.pjlink, 'log')1126 # THEN: Version information should not change
1036 def test_projector_process_sver_changed(self, mock_log):1127 assert pjlink.sw_version == test_data, 'Software version should have been updated'
1128 mock_log.debug.assert_has_calls(log_debug_calls)
1129
1130 def test_projector_process_sver_changed(self):
1037 """1131 """
1038 Test invalid software version information - Received different than saved1132 Test invalid software version information - Received different than saved
1039 """1133 """
1040 # GIVEN: Test object1134 test_data_old = 'Test 1 Subtest 1'
1041 pjlink = pjlink_test
1042 test_data_new = 'Test 1 Subtest 2'1135 test_data_new = 'Test 1 Subtest 2'
1043 test_data_old = 'Test 1 Subtest 1'1136 log_warn_calls = [call('(111.111.111.111) Projector software version does not match saved software version'),
1044 pjlink.sw_version = test_data_old1137 call('(111.111.111.111) Saved: "Test 1 Subtest 1"'),
1045 pjlink.sw_version_received = None1138 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'1139 call('(111.111.111.111) Updating software version')]
1047 mock_log.reset_mock()1140
10481141 # GIVEN: Test object
1049 # WHEN: process_sver called with invalid data1142 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
1050 pjlink.process_sver(data=test_data_new)1143 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
10511144 pjlink.sw_version = test_data_old
1052 # THEN: Version information should not change1145
1053 self.assertEqual(pjlink.sw_version, test_data_old, 'Software version should not have been updated')1146 # WHEN: process_sver called with invalid data
1054 self.assertEqual(pjlink.sw_version_received, test_data_new,1147 pjlink.process_sver(data=test_data_new)
1055 'Received software version should have been changed')1148
1056 self.assertEqual(mock_log.warning.call_count, 4, 'log.warn should have been called 4 times')1149 # THEN: Version information should not change
1057 # There was 4 calls, but only the last one is checked with this method1150 assert pjlink.sw_version == test_data_new, 'Software version should have changed'
1058 mock_log.warning.assert_called_with(test_log)1151 mock_log.warning.assert_has_calls(log_warn_calls)
10591152
1060 @patch.object(openlp.core.projectors.pjlink, 'log')1153 def test_projector_process_sver_invalid(self):
1061 def test_projector_process_sver_invalid(self, mock_log):
1062 """1154 """
1063 Test invalid software version information - too long1155 Test invalid software version information - too long
1064 """1156 """
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'1157 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"1158 log_warn_calls = [call('Invalid software version - too long')]
1071 mock_log.reset_mock()1159
10721160 # GIVEN: Test object
1073 # WHEN: process_sver called with invalid data1161 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
1074 pjlink.process_sver(data=test_data)1162 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
10751163 pjlink.sw_version = None
1076 # THEN: Version information should not change1164
1077 self.assertIsNone(pjlink.sw_version, 'Software version should not have changed')1165 # WHEN: process_sver called with invalid data
1078 self.assertIsNone(pjlink.sw_version_received, 'Received software version should not have changed')1166 pjlink.process_sver(data=test_data)
1079 mock_log.warning.assert_called_once_with(test_log)1167
1168 # THEN: Version information should not change
1169 assert pjlink.sw_version is None, 'Software version should not have changed'
1170 assert pjlink.sw_version_received is None, 'Received software version should not have changed'
1171 mock_log.warning.assert_has_calls(log_warn_calls)
10801172
1081 def test_projector_reset_information(self):1173 def test_projector_reset_information(self):
1082 """1174 """
1083 Test reset_information() resets all information and stops timers1175 Test reset_information() resets all information and stops timers
1084 """1176 """
1085 # GIVEN: Test object and test data1177 log_debug_calls = [call('(111.111.111.111): Calling timer.stop()'),
1086 pjlink = pjlink_test1178 call('(111.111.111.111): Calling socket_timer.stop()')]
1087 pjlink.power = S_ON1179
1088 pjlink.pjlink_name = 'OPENLPTEST'1180 # GIVEN: Test object
1089 pjlink.manufacturer = 'PJLINK'1181 with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
1090 pjlink.model = '1'1182 pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
1091 pjlink.shutter = True1183 # timer and socket_timer not available until instantiation, so mock here
1092 pjlink.mute = True1184 with patch.object(pjlink, 'socket_timer') as mock_socket_timer, \
1093 pjlink.lamp = True1185 patch.object(pjlink, 'timer') as mock_timer:
1094 pjlink.fan = True1186
1095 pjlink.source_available = True1187 pjlink.power = S_ON
1096 pjlink.other_info = 'ANOTHER TEST'1188 pjlink.pjlink_name = 'OPENLPTEST'
1097 pjlink.send_queue = True1189 pjlink.manufacturer = 'PJLINK'
1098 pjlink.send_busy = True1190 pjlink.model = '1'
10991191 pjlink.shutter = True
1100 # WHEN: reset_information() is called1192 pjlink.mute = True
1101 with patch.object(pjlink, 'timer') as mock_timer:1193 pjlink.lamp = True
1102 with patch.object(pjlink, 'socket_timer') as mock_socket_timer:1194 pjlink.fan = True
1195 pjlink.source_available = True
1196 pjlink.other_info = 'ANOTHER TEST'
1197 pjlink.send_queue = True
1198 pjlink.send_busy = True
1199
1200 # WHEN: reset_information() is called
1103 pjlink.reset_information()1201 pjlink.reset_information()
11041202
1105 # THEN: All information should be reset and timers stopped1203 # THEN: All information should be reset and timers stopped
1106 self.assertEqual(pjlink.power, S_OFF, 'Projector power should be OFF')1204 assert pjlink.power == S_OFF, 'Projector power should be OFF'
1107 self.assertIsNone(pjlink.pjlink_name, 'Projector pjlink_name should be None')1205 assert pjlink.pjlink_name is None, 'Projector pjlink_name should be None'
1108 self.assertIsNone(pjlink.manufacturer, 'Projector manufacturer should be None')1206 assert pjlink.manufacturer is None, 'Projector manufacturer should be None'
1109 self.assertIsNone(pjlink.model, 'Projector model should be None')1207 assert pjlink.model is None, 'Projector model should be None'
1110 self.assertIsNone(pjlink.shutter, 'Projector shutter should be None')1208 assert pjlink.shutter is None, 'Projector shutter should be None'
1111 self.assertIsNone(pjlink.mute, 'Projector shuttter should be None')1209 assert pjlink.mute is None, 'Projector shuttter should be None'
1112 self.assertIsNone(pjlink.lamp, 'Projector lamp should be None')1210 assert pjlink.lamp is None, 'Projector lamp should be None'
1113 self.assertIsNone(pjlink.fan, 'Projector fan should be None')1211 assert pjlink.fan is None, 'Projector fan should be None'
1114 self.assertIsNone(pjlink.source_available, 'Projector source_available should be None')1212 assert pjlink.source_available is None, 'Projector source_available should be None'
1115 self.assertIsNone(pjlink.source, 'Projector source should be None')1213 assert pjlink.source is None, 'Projector source should be None'
1116 self.assertIsNone(pjlink.other_info, 'Projector other_info should be None')1214 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')1215 assert pjlink.send_queue == [], 'Projector send_queue should be an empty list'
1118 self.assertFalse(pjlink.send_busy, 'Projector send_busy should be False')1216 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')1217 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')1218 assert mock_socket_timer.stop.called is True, 'Projector socket_timer.stop() should have been called'
1219 mock_log.debug.assert_has_calls(log_debug_calls)