forked from openlp/openlp
PJLink Updates N
This commit is contained in:
parent
6e2bc427a7
commit
598a373929
@ -32,9 +32,128 @@ log.debug('projector_constants loaded')
|
||||
# Set common constants.
|
||||
CR = chr(0x0D) # \r
|
||||
LF = chr(0x0A) # \n
|
||||
PJLINK_PORT = 4352
|
||||
TIMEOUT = 30.0
|
||||
PJLINK_CLASS = '1' # Default to class 1 until we query the projector
|
||||
PJLINK_MAX_PACKET = 136
|
||||
PJLINK_PREFIX = '%'
|
||||
PJLINK_PORT = 4352
|
||||
PJLINK_SUFFIX = CR
|
||||
PJLINK_TIMEOUT = 30.0
|
||||
|
||||
# Error and status codes
|
||||
S_OK = E_OK = 0 # E_OK included since I sometimes forget
|
||||
|
||||
# Error codes. Start at 200 so we don't duplicate system error codes.
|
||||
E_GENERAL = 200 # Unknown error
|
||||
E_NOT_CONNECTED = 201
|
||||
E_UNDEFINED = 202 # PJLink ERR1
|
||||
E_PARAMETER = 203 # PJLink ERR2
|
||||
E_UNAVAILABLE = 204 # PJLink ERR3
|
||||
E_PROJECTOR = 205 # PJLink ERR4
|
||||
E_AUTHENTICATION = 206 # PJLink ERRA
|
||||
E_NO_AUTHENTICATION = 207 # PJLink authentication mismatch between projector and program
|
||||
E_PREFIX = 208 # PJLink invalid prefix for packet
|
||||
E_CLASS = 209 # PJLink class version mismatch
|
||||
E_INVALID_DATA = 210
|
||||
E_WARN = 211
|
||||
E_ERROR = 212
|
||||
E_FAN = 213
|
||||
E_LAMP = 214
|
||||
E_TEMP = 215
|
||||
E_COVER = 216
|
||||
E_FILTER = 217
|
||||
E_UNKNOWN = 218
|
||||
|
||||
# Remap Qt socket error codes to local error codes
|
||||
E_CONNECTION_REFUSED = 230
|
||||
E_REMOTE_HOST_CLOSED_CONNECTION = 231
|
||||
E_HOST_NOT_FOUND = 232
|
||||
E_SOCKET_ACCESS = 233
|
||||
E_SOCKET_RESOURCE = 234
|
||||
E_SOCKET_TIMEOUT = 235
|
||||
E_DATAGRAM_TOO_LARGE = 236
|
||||
E_NETWORK = 237
|
||||
E_ADDRESS_IN_USE = 238
|
||||
E_SOCKET_ADDRESS_NOT_AVAILABLE = 239
|
||||
E_UNSUPPORTED_SOCKET_OPERATION = 240
|
||||
E_PROXY_AUTHENTICATION_REQUIRED = 241
|
||||
E_SLS_HANDSHAKE_FAILED = 242
|
||||
E_UNFINISHED_SOCKET_OPERATION = 243
|
||||
E_PROXY_CONNECTION_REFUSED = 244
|
||||
E_PROXY_CONNECTION_CLOSED = 245
|
||||
E_PROXY_CONNECTION_TIMEOUT = 246
|
||||
E_PROXY_NOT_FOUND = 247
|
||||
E_PROXY_PROTOCOL = 248
|
||||
E_UNKNOWN_SOCKET_ERROR = 249
|
||||
|
||||
# Status codes start at 300
|
||||
|
||||
# Remap Qt socket states to local status codes
|
||||
S_NOT_CONNECTED = 300
|
||||
S_HOST_LOOKUP = 301
|
||||
S_CONNECTING = 302
|
||||
S_CONNECTED = 303
|
||||
S_BOUND = 304
|
||||
S_LISTENING = 305 # Listed as internal use only in QAbstractSocket
|
||||
S_CLOSING = 306
|
||||
|
||||
# Projector states
|
||||
S_INITIALIZE = 310
|
||||
S_STATUS = 311
|
||||
S_OFF = 312
|
||||
S_STANDBY = 313
|
||||
S_WARMUP = 314
|
||||
S_ON = 315
|
||||
S_COOLDOWN = 316
|
||||
S_INFO = 317
|
||||
|
||||
# Information that does not affect status
|
||||
S_NETWORK_IDLE = 400
|
||||
S_NETWORK_SENDING = 401
|
||||
S_NETWORK_RECEIVING = 402
|
||||
|
||||
# Map PJlink errors to local status
|
||||
PJLINK_ERRORS = {
|
||||
'ERRA': E_AUTHENTICATION, # Authentication error
|
||||
'ERR1': E_UNDEFINED, # Undefined command error
|
||||
'ERR2': E_PARAMETER, # Invalid parameter error
|
||||
'ERR3': E_UNAVAILABLE, # Projector busy
|
||||
'ERR4': E_PROJECTOR, # Projector or display failure
|
||||
E_AUTHENTICATION: 'ERRA',
|
||||
E_UNDEFINED: 'ERR1',
|
||||
E_PARAMETER: 'ERR2',
|
||||
E_UNAVAILABLE: 'ERR3',
|
||||
E_PROJECTOR: 'ERR4'
|
||||
}
|
||||
|
||||
# Map QAbstractSocketState enums to local status
|
||||
QSOCKET_STATE = {
|
||||
0: S_NOT_CONNECTED, # 'UnconnectedState',
|
||||
1: S_HOST_LOOKUP, # 'HostLookupState',
|
||||
2: S_CONNECTING, # 'ConnectingState',
|
||||
3: S_CONNECTED, # 'ConnectedState',
|
||||
4: S_BOUND, # 'BoundState',
|
||||
5: S_LISTENING, # 'ListeningState' - Noted as "Internal Use Only" on Qt website
|
||||
6: S_CLOSING, # 'ClosingState',
|
||||
S_NOT_CONNECTED: 0,
|
||||
S_HOST_LOOKUP: 1,
|
||||
S_CONNECTING: 2,
|
||||
S_CONNECTED: 3,
|
||||
S_BOUND: 4,
|
||||
S_LISTENING: 5,
|
||||
S_CLOSING: 6
|
||||
}
|
||||
|
||||
PROJECTOR_STATE = [
|
||||
S_INITIALIZE,
|
||||
S_STATUS,
|
||||
S_OFF,
|
||||
S_STANDBY,
|
||||
S_WARMUP,
|
||||
S_ON,
|
||||
S_COOLDOWN,
|
||||
S_INFO
|
||||
]
|
||||
|
||||
# NOTE: Changed format to account for some commands are both class 1 and 2
|
||||
PJLINK_VALID_CMD = {
|
||||
'ACKN': {'version': ['2', ],
|
||||
@ -144,227 +263,140 @@ PJLINK_VALID_CMD = {
|
||||
}
|
||||
}
|
||||
|
||||
# QAbstractSocketState enums converted to string
|
||||
S_QSOCKET_STATE = {
|
||||
0: 'QSocketState - UnconnectedState',
|
||||
1: 'QSocketState - HostLookupState',
|
||||
2: 'QSocketState - ConnectingState',
|
||||
3: 'QSocketState - ConnectedState',
|
||||
4: 'QSocketState - BoundState',
|
||||
5: 'QSocketState - ListeningState (internal use only)',
|
||||
6: 'QSocketState - ClosingState',
|
||||
'UnconnectedState': 0,
|
||||
'HostLookupState': 1,
|
||||
'ConnectingState': 2,
|
||||
'ConnectedState': 3,
|
||||
'BoundState': 4,
|
||||
'ListeningState': 5,
|
||||
'ClosingState': 6
|
||||
}
|
||||
CONNECTION_ERRORS = [
|
||||
E_ADDRESS_IN_USE,
|
||||
E_CONNECTION_REFUSED,
|
||||
E_DATAGRAM_TOO_LARGE,
|
||||
E_HOST_NOT_FOUND,
|
||||
E_NETWORK,
|
||||
E_NOT_CONNECTED,
|
||||
E_PROXY_AUTHENTICATION_REQUIRED,
|
||||
E_PROXY_CONNECTION_CLOSED,
|
||||
E_PROXY_CONNECTION_REFUSED,
|
||||
E_PROXY_CONNECTION_TIMEOUT,
|
||||
E_PROXY_NOT_FOUND,
|
||||
E_PROXY_PROTOCOL,
|
||||
E_REMOTE_HOST_CLOSED_CONNECTION,
|
||||
E_SLS_HANDSHAKE_FAILED,
|
||||
E_SOCKET_ACCESS,
|
||||
E_SOCKET_ADDRESS_NOT_AVAILABLE,
|
||||
E_SOCKET_RESOURCE,
|
||||
E_SOCKET_TIMEOUT,
|
||||
E_UNFINISHED_SOCKET_OPERATION,
|
||||
E_UNKNOWN_SOCKET_ERROR,
|
||||
E_UNSUPPORTED_SOCKET_OPERATION
|
||||
]
|
||||
|
||||
# Error and status codes
|
||||
S_OK = E_OK = 0 # E_OK included since I sometimes forget
|
||||
# Error codes. Start at 200 so we don't duplicate system error codes.
|
||||
E_GENERAL = 200 # Unknown error
|
||||
E_NOT_CONNECTED = 201
|
||||
E_FAN = 202
|
||||
E_LAMP = 203
|
||||
E_TEMP = 204
|
||||
E_COVER = 205
|
||||
E_FILTER = 206
|
||||
E_NO_AUTHENTICATION = 207 # PIN set and no authentication set on projector
|
||||
E_UNDEFINED = 208 # ERR1
|
||||
E_PARAMETER = 209 # ERR2
|
||||
E_UNAVAILABLE = 210 # ERR3
|
||||
E_PROJECTOR = 211 # ERR4
|
||||
E_INVALID_DATA = 212
|
||||
E_WARN = 213
|
||||
E_ERROR = 214
|
||||
E_AUTHENTICATION = 215 # ERRA
|
||||
E_CLASS = 216
|
||||
E_PREFIX = 217
|
||||
PROJECTOR_ERRORS = [
|
||||
E_AUTHENTICATION,
|
||||
E_CLASS,
|
||||
E_INVALID_DATA,
|
||||
E_NO_AUTHENTICATION,
|
||||
E_PARAMETER,
|
||||
E_PREFIX,
|
||||
E_PROJECTOR,
|
||||
E_UNAVAILABLE,
|
||||
E_UNDEFINED,
|
||||
E_UNKNOWN
|
||||
]
|
||||
|
||||
# Remap Qt socket error codes to projector error codes
|
||||
E_CONNECTION_REFUSED = 230
|
||||
E_REMOTE_HOST_CLOSED_CONNECTION = 231
|
||||
E_HOST_NOT_FOUND = 232
|
||||
E_SOCKET_ACCESS = 233
|
||||
E_SOCKET_RESOURCE = 234
|
||||
E_SOCKET_TIMEOUT = 235
|
||||
E_DATAGRAM_TOO_LARGE = 236
|
||||
E_NETWORK = 237
|
||||
E_ADDRESS_IN_USE = 238
|
||||
E_SOCKET_ADDRESS_NOT_AVAILABLE = 239
|
||||
E_UNSUPPORTED_SOCKET_OPERATION = 240
|
||||
E_PROXY_AUTHENTICATION_REQUIRED = 241
|
||||
E_SLS_HANDSHAKE_FAILED = 242
|
||||
E_UNFINISHED_SOCKET_OPERATION = 243
|
||||
E_PROXY_CONNECTION_REFUSED = 244
|
||||
E_PROXY_CONNECTION_CLOSED = 245
|
||||
E_PROXY_CONNECTION_TIMEOUT = 246
|
||||
E_PROXY_NOT_FOUND = 247
|
||||
E_PROXY_PROTOCOL = 248
|
||||
E_UNKNOWN_SOCKET_ERROR = -1
|
||||
|
||||
# Status codes start at 300
|
||||
S_NOT_CONNECTED = 300
|
||||
S_CONNECTING = 301
|
||||
S_CONNECTED = 302
|
||||
S_INITIALIZE = 303
|
||||
S_STATUS = 304
|
||||
S_OFF = 305
|
||||
S_STANDBY = 306
|
||||
S_WARMUP = 307
|
||||
S_ON = 308
|
||||
S_COOLDOWN = 309
|
||||
S_INFO = 310
|
||||
|
||||
# Information that does not affect status
|
||||
S_NETWORK_SENDING = 400
|
||||
S_NETWORK_RECEIVED = 401
|
||||
|
||||
CONNECTION_ERRORS = {
|
||||
E_NOT_CONNECTED, E_NO_AUTHENTICATION, E_AUTHENTICATION, E_CLASS,
|
||||
E_PREFIX, E_CONNECTION_REFUSED, E_REMOTE_HOST_CLOSED_CONNECTION,
|
||||
E_HOST_NOT_FOUND, E_SOCKET_ACCESS, E_SOCKET_RESOURCE, E_SOCKET_TIMEOUT,
|
||||
E_DATAGRAM_TOO_LARGE, E_NETWORK, E_ADDRESS_IN_USE, E_SOCKET_ADDRESS_NOT_AVAILABLE,
|
||||
E_UNSUPPORTED_SOCKET_OPERATION, E_PROXY_AUTHENTICATION_REQUIRED,
|
||||
E_SLS_HANDSHAKE_FAILED, E_UNFINISHED_SOCKET_OPERATION, E_PROXY_CONNECTION_REFUSED,
|
||||
E_PROXY_CONNECTION_CLOSED, E_PROXY_CONNECTION_TIMEOUT, E_PROXY_NOT_FOUND,
|
||||
E_PROXY_PROTOCOL, E_UNKNOWN_SOCKET_ERROR
|
||||
}
|
||||
|
||||
PJLINK_ERRORS = {
|
||||
'ERRA': E_AUTHENTICATION, # Authentication error
|
||||
'ERR1': E_UNDEFINED, # Undefined command error
|
||||
'ERR2': E_PARAMETER, # Invalid parameter error
|
||||
'ERR3': E_UNAVAILABLE, # Projector busy
|
||||
'ERR4': E_PROJECTOR, # Projector or display failure
|
||||
E_AUTHENTICATION: 'ERRA',
|
||||
E_UNDEFINED: 'ERR1',
|
||||
E_PARAMETER: 'ERR2',
|
||||
E_UNAVAILABLE: 'ERR3',
|
||||
E_PROJECTOR: 'ERR4'
|
||||
}
|
||||
|
||||
# Map error/status codes to string
|
||||
ERROR_STRING = {
|
||||
0: 'S_OK',
|
||||
E_GENERAL: 'E_GENERAL',
|
||||
E_NOT_CONNECTED: 'E_NOT_CONNECTED',
|
||||
E_FAN: 'E_FAN',
|
||||
E_LAMP: 'E_LAMP',
|
||||
E_TEMP: 'E_TEMP',
|
||||
E_COVER: 'E_COVER',
|
||||
E_FILTER: 'E_FILTER',
|
||||
E_AUTHENTICATION: 'E_AUTHENTICATION',
|
||||
E_NO_AUTHENTICATION: 'E_NO_AUTHENTICATION',
|
||||
E_UNDEFINED: 'E_UNDEFINED',
|
||||
E_PARAMETER: 'E_PARAMETER',
|
||||
E_UNAVAILABLE: 'E_UNAVAILABLE',
|
||||
E_PROJECTOR: 'E_PROJECTOR',
|
||||
E_INVALID_DATA: 'E_INVALID_DATA',
|
||||
E_WARN: 'E_WARN',
|
||||
E_ERROR: 'E_ERROR',
|
||||
E_CLASS: 'E_CLASS',
|
||||
E_PREFIX: 'E_PREFIX', # Last projector error
|
||||
E_CONNECTION_REFUSED: 'E_CONNECTION_REFUSED', # First QtSocket error
|
||||
E_REMOTE_HOST_CLOSED_CONNECTION: 'E_REMOTE_HOST_CLOSED_CONNECTION',
|
||||
E_HOST_NOT_FOUND: 'E_HOST_NOT_FOUND',
|
||||
E_SOCKET_ACCESS: 'E_SOCKET_ACCESS',
|
||||
E_SOCKET_RESOURCE: 'E_SOCKET_RESOURCE',
|
||||
E_SOCKET_TIMEOUT: 'E_SOCKET_TIMEOUT',
|
||||
E_DATAGRAM_TOO_LARGE: 'E_DATAGRAM_TOO_LARGE',
|
||||
E_NETWORK: 'E_NETWORK',
|
||||
# Show status code as string
|
||||
STATUS_CODE = {
|
||||
E_ADDRESS_IN_USE: 'E_ADDRESS_IN_USE',
|
||||
E_SOCKET_ADDRESS_NOT_AVAILABLE: 'E_SOCKET_ADDRESS_NOT_AVAILABLE',
|
||||
E_UNSUPPORTED_SOCKET_OPERATION: 'E_UNSUPPORTED_SOCKET_OPERATION',
|
||||
E_AUTHENTICATION: 'E_AUTHENTICATION',
|
||||
E_CLASS: 'E_CLASS',
|
||||
E_CONNECTION_REFUSED: 'E_CONNECTION_REFUSED',
|
||||
E_COVER: 'E_COVER',
|
||||
E_DATAGRAM_TOO_LARGE: 'E_DATAGRAM_TOO_LARGE',
|
||||
E_ERROR: 'E_ERROR',
|
||||
E_FAN: 'E_FAN',
|
||||
E_FILTER: 'E_FILTER',
|
||||
E_GENERAL: 'E_GENERAL',
|
||||
E_HOST_NOT_FOUND: 'E_HOST_NOT_FOUND',
|
||||
E_INVALID_DATA: 'E_INVALID_DATA',
|
||||
E_LAMP: 'E_LAMP',
|
||||
E_NETWORK: 'E_NETWORK',
|
||||
E_NO_AUTHENTICATION: 'E_NO_AUTHENTICATION',
|
||||
E_NOT_CONNECTED: 'E_NOT_CONNECTED',
|
||||
E_PARAMETER: 'E_PARAMETER',
|
||||
E_PREFIX: 'E_PREFIX',
|
||||
E_PROJECTOR: 'E_PROJECTOR',
|
||||
E_PROXY_AUTHENTICATION_REQUIRED: 'E_PROXY_AUTHENTICATION_REQUIRED',
|
||||
E_SLS_HANDSHAKE_FAILED: 'E_SLS_HANDSHAKE_FAILED',
|
||||
E_UNFINISHED_SOCKET_OPERATION: 'E_UNFINISHED_SOCKET_OPERATION',
|
||||
E_PROXY_CONNECTION_REFUSED: 'E_PROXY_CONNECTION_REFUSED',
|
||||
E_PROXY_CONNECTION_CLOSED: 'E_PROXY_CONNECTION_CLOSED',
|
||||
E_PROXY_CONNECTION_REFUSED: 'E_PROXY_CONNECTION_REFUSED',
|
||||
E_PROXY_CONNECTION_TIMEOUT: 'E_PROXY_CONNECTION_TIMEOUT',
|
||||
E_PROXY_NOT_FOUND: 'E_PROXY_NOT_FOUND',
|
||||
E_PROXY_PROTOCOL: 'E_PROXY_PROTOCOL',
|
||||
E_UNKNOWN_SOCKET_ERROR: 'E_UNKNOWN_SOCKET_ERROR'
|
||||
}
|
||||
|
||||
STATUS_STRING = {
|
||||
S_NOT_CONNECTED: 'S_NOT_CONNECTED',
|
||||
S_CONNECTING: 'S_CONNECTING',
|
||||
S_CONNECTED: 'S_CONNECTED',
|
||||
S_STATUS: 'S_STATUS',
|
||||
S_OFF: 'S_OFF',
|
||||
S_INITIALIZE: 'S_INITIALIZE',
|
||||
S_STANDBY: 'S_STANDBY',
|
||||
S_WARMUP: 'S_WARMUP',
|
||||
S_ON: 'S_ON',
|
||||
E_REMOTE_HOST_CLOSED_CONNECTION: 'E_REMOTE_HOST_CLOSED_CONNECTION',
|
||||
E_SLS_HANDSHAKE_FAILED: 'E_SLS_HANDSHAKE_FAILED',
|
||||
E_SOCKET_ACCESS: 'E_SOCKET_ACCESS',
|
||||
E_SOCKET_ADDRESS_NOT_AVAILABLE: 'E_SOCKET_ADDRESS_NOT_AVAILABLE',
|
||||
E_SOCKET_RESOURCE: 'E_SOCKET_RESOURCE',
|
||||
E_SOCKET_TIMEOUT: 'E_SOCKET_TIMEOUT',
|
||||
E_TEMP: 'E_TEMP',
|
||||
E_UNAVAILABLE: 'E_UNAVAILABLE',
|
||||
E_UNDEFINED: 'E_UNDEFINED',
|
||||
E_UNFINISHED_SOCKET_OPERATION: 'E_UNFINISHED_SOCKET_OPERATION',
|
||||
E_UNKNOWN: 'E_UNKNOWN',
|
||||
E_UNKNOWN_SOCKET_ERROR: 'E_UNKNOWN_SOCKET_ERROR',
|
||||
E_UNSUPPORTED_SOCKET_OPERATION: 'E_UNSUPPORTED_SOCKET_OPERATION',
|
||||
E_WARN: 'E_WARN',
|
||||
S_BOUND: 'S_BOUND',
|
||||
S_COOLDOWN: 'S_COOLDOWN',
|
||||
S_CLOSING: 'S_CLOSING',
|
||||
S_CONNECTED: 'S_CONNECTED',
|
||||
S_CONNECTING: 'S_CONNECTING',
|
||||
S_HOST_LOOKUP: 'S_HOST_LOOKUP',
|
||||
S_INFO: 'S_INFO',
|
||||
S_INITIALIZE: 'S_INITIALIZE',
|
||||
S_LISTENING: 'S_LISTENING',
|
||||
S_NETWORK_RECEIVING: 'S_NETWORK_RECEIVING',
|
||||
S_NETWORK_SENDING: 'S_NETWORK_SENDING',
|
||||
S_NETWORK_RECEIVED: 'S_NETWORK_RECEIVED'
|
||||
S_NETWORK_IDLE: 'S_NETWORK_IDLE',
|
||||
S_NOT_CONNECTED: 'S_NOT_CONNECTED',
|
||||
S_OFF: 'S_OFF',
|
||||
S_OK: 'S_OK', # S_OK or E_OK
|
||||
S_ON: 'S_ON',
|
||||
S_STANDBY: 'S_STANDBY',
|
||||
S_STATUS: 'S_STATUS',
|
||||
S_WARMUP: 'S_WARMUP',
|
||||
}
|
||||
|
||||
# Map error/status codes to message strings
|
||||
ERROR_MSG = {
|
||||
E_OK: translate('OpenLP.ProjectorConstants', 'OK'), # E_OK | S_OK
|
||||
E_GENERAL: translate('OpenLP.ProjectorConstants', 'General projector error'),
|
||||
E_NOT_CONNECTED: translate('OpenLP.ProjectorConstants', 'Not connected error'),
|
||||
E_LAMP: translate('OpenLP.ProjectorConstants', 'Lamp error'),
|
||||
E_FAN: translate('OpenLP.ProjectorConstants', 'Fan error'),
|
||||
E_TEMP: translate('OpenLP.ProjectorConstants', 'High temperature detected'),
|
||||
E_COVER: translate('OpenLP.ProjectorConstants', 'Cover open detected'),
|
||||
E_FILTER: translate('OpenLP.ProjectorConstants', 'Check filter'),
|
||||
E_AUTHENTICATION: translate('OpenLP.ProjectorConstants', 'Authentication Error'),
|
||||
E_UNDEFINED: translate('OpenLP.ProjectorConstants', 'Undefined Command'),
|
||||
E_PARAMETER: translate('OpenLP.ProjectorConstants', 'Invalid Parameter'),
|
||||
E_UNAVAILABLE: translate('OpenLP.ProjectorConstants', 'Projector Busy'),
|
||||
E_PROJECTOR: translate('OpenLP.ProjectorConstants', 'Projector/Display Error'),
|
||||
E_INVALID_DATA: translate('OpenLP.ProjectorConstants', 'Invalid packet received'),
|
||||
E_WARN: translate('OpenLP.ProjectorConstants', 'Warning condition detected'),
|
||||
E_ERROR: translate('OpenLP.ProjectorConstants', 'Error condition detected'),
|
||||
E_CLASS: translate('OpenLP.ProjectorConstants', 'PJLink class not supported'),
|
||||
E_PREFIX: translate('OpenLP.ProjectorConstants', 'Invalid prefix character'),
|
||||
E_CONNECTION_REFUSED: translate('OpenLP.ProjectorConstants',
|
||||
'The connection was refused by the peer (or timed out)'),
|
||||
E_REMOTE_HOST_CLOSED_CONNECTION: translate('OpenLP.ProjectorConstants',
|
||||
'The remote host closed the connection'),
|
||||
E_HOST_NOT_FOUND: translate('OpenLP.ProjectorConstants', 'The host address was not found'),
|
||||
E_SOCKET_ACCESS: translate('OpenLP.ProjectorConstants',
|
||||
'The socket operation failed because the application '
|
||||
'lacked the required privileges'),
|
||||
E_SOCKET_RESOURCE: translate('OpenLP.ProjectorConstants',
|
||||
'The local system ran out of resources (e.g., too many sockets)'),
|
||||
E_SOCKET_TIMEOUT: translate('OpenLP.ProjectorConstants',
|
||||
'The socket operation timed out'),
|
||||
E_DATAGRAM_TOO_LARGE: translate('OpenLP.ProjectorConstants',
|
||||
'The datagram was larger than the operating system\'s limit'),
|
||||
E_NETWORK: translate('OpenLP.ProjectorConstants',
|
||||
'An error occurred with the network (Possibly someone pulled the plug?)'),
|
||||
# Map status codes to message strings
|
||||
STATUS_MSG = {
|
||||
E_ADDRESS_IN_USE: translate('OpenLP.ProjectorConstants',
|
||||
'The address specified with socket.bind() '
|
||||
'is already in use and was set to be exclusive'),
|
||||
E_SOCKET_ADDRESS_NOT_AVAILABLE: translate('OpenLP.ProjectorConstants',
|
||||
'The address specified to socket.bind() '
|
||||
'does not belong to the host'),
|
||||
E_UNSUPPORTED_SOCKET_OPERATION: translate('OpenLP.ProjectorConstants',
|
||||
'The requested socket operation is not supported by the local '
|
||||
'operating system (e.g., lack of IPv6 support)'),
|
||||
E_AUTHENTICATION: translate('OpenLP.ProjectorConstants', 'PJLink returned "ERRA: Authentication Error"'),
|
||||
E_CONNECTION_REFUSED: translate('OpenLP.ProjectorConstants',
|
||||
'The connection was refused by the peer (or timed out)'),
|
||||
E_COVER: translate('OpenLP.ProjectorConstants', 'Projector cover open detected'),
|
||||
E_CLASS: translate('OpenLP.ProjectorConstants', 'PJLink class not supported'),
|
||||
E_DATAGRAM_TOO_LARGE: translate('OpenLP.ProjectorConstants',
|
||||
"The datagram was larger than the operating system's limit"),
|
||||
E_ERROR: translate('OpenLP.ProjectorConstants', 'Error condition detected'),
|
||||
E_FAN: translate('OpenLP.ProjectorConstants', 'Projector fan error'),
|
||||
E_FILTER: translate('OpenLP.ProjectorConstants', 'Projector check filter'),
|
||||
E_GENERAL: translate('OpenLP.ProjectorConstants', 'General projector error'),
|
||||
E_HOST_NOT_FOUND: translate('OpenLP.ProjectorConstants', 'The host address was not found'),
|
||||
E_INVALID_DATA: translate('OpenLP.ProjectorConstants', 'PJLink invalid packet received'),
|
||||
E_LAMP: translate('OpenLP.ProjectorConstants', 'Projector lamp error'),
|
||||
E_NETWORK: translate('OpenLP.ProjectorConstants',
|
||||
'An error occurred with the network (Possibly someone pulled the plug?)'),
|
||||
E_NO_AUTHENTICATION: translate('OpenLP.ProjectorConstants', 'PJlink authentication Mismatch Error'),
|
||||
E_NOT_CONNECTED: translate('OpenLP.ProjectorConstants', 'Projector not connected error'),
|
||||
E_PARAMETER: translate('OpenLP.ProjectorConstants', 'PJLink returned "ERR2: Invalid Parameter"'),
|
||||
E_PREFIX: translate('OpenLP.ProjectorConstants', 'PJLink Invalid prefix character'),
|
||||
E_PROJECTOR: translate('OpenLP.ProjectorConstants', 'PJLink returned "ERR4: Projector/Display Error"'),
|
||||
E_PROXY_AUTHENTICATION_REQUIRED: translate('OpenLP.ProjectorConstants',
|
||||
'The socket is using a proxy, '
|
||||
'and the proxy requires authentication'),
|
||||
E_SLS_HANDSHAKE_FAILED: translate('OpenLP.ProjectorConstants',
|
||||
'The SSL/TLS handshake failed'),
|
||||
E_UNFINISHED_SOCKET_OPERATION: translate('OpenLP.ProjectorConstants',
|
||||
'The last operation attempted has not finished yet '
|
||||
'(still in progress in the background)'),
|
||||
E_PROXY_CONNECTION_REFUSED: translate('OpenLP.ProjectorConstants',
|
||||
'Could not contact the proxy server because the connection '
|
||||
'to that server was denied'),
|
||||
E_PROXY_CONNECTION_CLOSED: translate('OpenLP.ProjectorConstants',
|
||||
'The connection to the proxy server was closed unexpectedly '
|
||||
'(before the connection to the final peer was established)'),
|
||||
E_PROXY_CONNECTION_REFUSED: translate('OpenLP.ProjectorConstants',
|
||||
'Could not contact the proxy server because the connection '
|
||||
'to that server was denied'),
|
||||
E_PROXY_CONNECTION_TIMEOUT: translate('OpenLP.ProjectorConstants',
|
||||
'The connection to the proxy server timed out or the proxy '
|
||||
'server stopped responding in the authentication phase.'),
|
||||
@ -373,51 +405,91 @@ ERROR_MSG = {
|
||||
E_PROXY_PROTOCOL: translate('OpenLP.ProjectorConstants',
|
||||
'The connection negotiation with the proxy server failed because the '
|
||||
'response from the proxy server could not be understood'),
|
||||
E_UNKNOWN_SOCKET_ERROR: translate('OpenLP.ProjectorConstants', 'An unidentified error occurred'),
|
||||
S_NOT_CONNECTED: translate('OpenLP.ProjectorConstants', 'Not connected'),
|
||||
S_CONNECTING: translate('OpenLP.ProjectorConstants', 'Connecting'),
|
||||
E_REMOTE_HOST_CLOSED_CONNECTION: translate('OpenLP.ProjectorConstants',
|
||||
'The remote host closed the connection'),
|
||||
E_SLS_HANDSHAKE_FAILED: translate('OpenLP.ProjectorConstants',
|
||||
'The SSL/TLS handshake failed'),
|
||||
E_SOCKET_ADDRESS_NOT_AVAILABLE: translate('OpenLP.ProjectorConstants',
|
||||
'The address specified to socket.bind() '
|
||||
'does not belong to the host'),
|
||||
E_SOCKET_ACCESS: translate('OpenLP.ProjectorConstants',
|
||||
'The socket operation failed because the application '
|
||||
'lacked the required privileges'),
|
||||
E_SOCKET_RESOURCE: translate('OpenLP.ProjectorConstants',
|
||||
'The local system ran out of resources (e.g., too many sockets)'),
|
||||
E_SOCKET_TIMEOUT: translate('OpenLP.ProjectorConstants',
|
||||
'The socket operation timed out'),
|
||||
E_TEMP: translate('OpenLP.ProjectorConstants', 'Projector high temperature detected'),
|
||||
E_UNAVAILABLE: translate('OpenLP.ProjectorConstants', 'PJLink returned "ERR3: Busy"'),
|
||||
E_UNDEFINED: translate('OpenLP.ProjectorConstants', 'PJLink returned "ERR1: Undefined Command"'),
|
||||
E_UNFINISHED_SOCKET_OPERATION: translate('OpenLP.ProjectorConstants',
|
||||
'The last operation attempted has not finished yet '
|
||||
'(still in progress in the background)'),
|
||||
E_UNKNOWN: translate('OpenLP.ProjectorConstants', 'Unknown condiction detected'),
|
||||
E_UNKNOWN_SOCKET_ERROR: translate('OpenLP.ProjectorConstants', 'An unidentified socket error occurred'),
|
||||
E_UNSUPPORTED_SOCKET_OPERATION: translate('OpenLP.ProjectorConstants',
|
||||
'The requested socket operation is not supported by the local '
|
||||
'operating system (e.g., lack of IPv6 support)'),
|
||||
E_WARN: translate('OpenLP.ProjectorConstants', 'Warning condition detected'),
|
||||
S_BOUND: translate('OpenLP.ProjectorConstants', 'Socket is bount to an address or port'),
|
||||
S_CLOSING: translate('OpenLP.ProjectorConstants', 'Socket is about to close'),
|
||||
S_CONNECTED: translate('OpenLP.ProjectorConstants', 'Connected'),
|
||||
S_STATUS: translate('OpenLP.ProjectorConstants', 'Getting status'),
|
||||
S_OFF: translate('OpenLP.ProjectorConstants', 'Off'),
|
||||
S_INITIALIZE: translate('OpenLP.ProjectorConstants', 'Initialize in progress'),
|
||||
S_STANDBY: translate('OpenLP.ProjectorConstants', 'Power in standby'),
|
||||
S_WARMUP: translate('OpenLP.ProjectorConstants', 'Warmup in progress'),
|
||||
S_ON: translate('OpenLP.ProjectorConstants', 'Power is on'),
|
||||
S_CONNECTING: translate('OpenLP.ProjectorConstants', 'Connecting'),
|
||||
S_COOLDOWN: translate('OpenLP.ProjectorConstants', 'Cooldown in progress'),
|
||||
S_HOST_LOOKUP: translate('OpenLP.ProjectorConstants', 'Performing a host name lookup'),
|
||||
S_INFO: translate('OpenLP.ProjectorConstants', 'Projector Information available'),
|
||||
S_INITIALIZE: translate('OpenLP.ProjectorConstants', 'Initialize in progress'),
|
||||
S_LISTENING: translate('OpenLP.ProjectorConstants', 'Socket it listening (internal use only)'),
|
||||
S_NETWORK_IDLE: translate('OpenLP.ProjectorConstants', 'No network activity at this time'),
|
||||
S_NETWORK_RECEIVING: translate('OpenLP.ProjectorConstants', 'Received data'),
|
||||
S_NETWORK_SENDING: translate('OpenLP.ProjectorConstants', 'Sending data'),
|
||||
S_NETWORK_RECEIVED: translate('OpenLP.ProjectorConstants', 'Received data')
|
||||
S_NOT_CONNECTED: translate('OpenLP.ProjectorConstants', 'Not Connected'),
|
||||
S_OFF: translate('OpenLP.ProjectorConstants', 'Off'),
|
||||
S_OK: translate('OpenLP.ProjectorConstants', 'OK'),
|
||||
S_ON: translate('OpenLP.ProjectorConstants', 'Power is on'),
|
||||
S_STANDBY: translate('OpenLP.ProjectorConstants', 'Power in standby'),
|
||||
S_STATUS: translate('OpenLP.ProjectorConstants', 'Getting status'),
|
||||
S_WARMUP: translate('OpenLP.ProjectorConstants', 'Warmup in progress'),
|
||||
}
|
||||
|
||||
# Map ERST return code positions to equipment
|
||||
# Map ERST reply positions to equipment
|
||||
PJLINK_ERST_LIST = {
|
||||
"FAN": translate('OpenLP.PJLink', 'Fan'),
|
||||
"LAMP": translate('OpenLP.PJLink', 'Lamp'),
|
||||
"TEMP": translate('OpenLP.PJLink', 'Temperature'),
|
||||
"COVER": translate('OpenLP.PJLink', 'Cover'),
|
||||
"FILTER": translate('OpenLP.PJLink', 'Filter'),
|
||||
"OTHER": translate('OpenPL.PJLink', 'Other')
|
||||
}
|
||||
|
||||
# Map projector item to ERST data position
|
||||
PJLINK_ERST_DATA = {
|
||||
'DATA_LENGTH': 6,
|
||||
0: 'FAN',
|
||||
1: 'LAMP',
|
||||
2: 'TEMP',
|
||||
3: 'COVER',
|
||||
4: 'FILTER',
|
||||
5: 'OTHER',
|
||||
'DATA_LENGTH': 6, # Zero based so enums are 0-5
|
||||
'FAN': 0,
|
||||
'LAMP': 1,
|
||||
'TEMP': 2,
|
||||
'COVER': 3,
|
||||
'FILTER': 4,
|
||||
'OTHER': 5
|
||||
'OTHER': 5,
|
||||
0: 'FAN',
|
||||
1: 'LAMP',
|
||||
2: 'TEMP',
|
||||
3: 'COVER',
|
||||
4: 'FILTER',
|
||||
5: 'OTHER'
|
||||
}
|
||||
|
||||
# Map for ERST return codes to string
|
||||
# Map ERST reply codes to string
|
||||
PJLINK_ERST_STATUS = {
|
||||
'0': 'OK',
|
||||
'1': ERROR_STRING[E_WARN],
|
||||
'2': ERROR_STRING[E_ERROR],
|
||||
'OK': '0',
|
||||
E_OK: '0',
|
||||
'0': S_OK,
|
||||
'1': E_WARN,
|
||||
'2': E_ERROR,
|
||||
S_OK: '0',
|
||||
E_WARN: '1',
|
||||
E_ERROR: '2'
|
||||
}
|
||||
|
||||
# Map for POWR return codes to status code
|
||||
# Map POWR return codes to status code
|
||||
PJLINK_POWR_STATUS = {
|
||||
'0': S_STANDBY,
|
||||
'1': S_ON,
|
||||
@ -485,3 +557,7 @@ for source in PJLINK_DEFAULT_SOURCES:
|
||||
label = "{source}{item}".format(source=source, item=item)
|
||||
PJLINK_DEFAULT_CODES[label] = "{source} {item}".format(source=PJLINK_DEFAULT_SOURCES[source],
|
||||
item=PJLINK_DEFAULT_ITEMS[item])
|
||||
# Remove temp variables so they don't become part of the module dict
|
||||
del(source)
|
||||
del(item)
|
||||
del(label)
|
||||
|
@ -35,9 +35,25 @@ from openlp.core.common.registry import RegistryBase
|
||||
from openlp.core.common.settings import Settings
|
||||
from openlp.core.lib.ui import create_widget_action
|
||||
from openlp.core.projectors import DialogSourceStyle
|
||||
from openlp.core.projectors.constants import ERROR_MSG, ERROR_STRING, E_AUTHENTICATION, E_ERROR, \
|
||||
E_NETWORK, E_NOT_CONNECTED, E_UNKNOWN_SOCKET_ERROR, STATUS_STRING, S_CONNECTED, S_CONNECTING, S_COOLDOWN, \
|
||||
S_INITIALIZE, S_NOT_CONNECTED, S_OFF, S_ON, S_STANDBY, S_WARMUP
|
||||
from openlp.core.projectors.constants import \
|
||||
E_AUTHENTICATION, \
|
||||
E_ERROR, \
|
||||
E_NETWORK, \
|
||||
E_NOT_CONNECTED, \
|
||||
E_UNKNOWN_SOCKET_ERROR, \
|
||||
S_CONNECTED, \
|
||||
S_CONNECTING, \
|
||||
S_COOLDOWN, \
|
||||
S_INITIALIZE, \
|
||||
S_NOT_CONNECTED, \
|
||||
S_OFF, \
|
||||
S_ON, \
|
||||
S_STANDBY, \
|
||||
S_WARMUP, \
|
||||
STATUS_CODE, \
|
||||
STATUS_MSG, \
|
||||
QSOCKET_STATE
|
||||
|
||||
from openlp.core.projectors.db import ProjectorDB
|
||||
from openlp.core.projectors.pjlink import PJLink, PJLinkUDP
|
||||
from openlp.core.projectors.editform import ProjectorEditForm
|
||||
@ -440,11 +456,12 @@ class ProjectorManager(QtWidgets.QWidget, RegistryBase, UiProjectorManager, LogM
|
||||
:param opt: Needed by PyQt5
|
||||
"""
|
||||
projector = item.data(QtCore.Qt.UserRole)
|
||||
if projector.link.state() != projector.link.ConnectedState:
|
||||
if QSOCKET_STATE[projector.link.state()] != S_CONNECTED:
|
||||
try:
|
||||
log.debug('ProjectorManager: Calling connect_to_host() on "{ip}"'.format(ip=projector.link.ip))
|
||||
projector.link.connect_to_host()
|
||||
except:
|
||||
pass
|
||||
log.debug('ProjectorManager: "{ip}" already connected - skipping'.format(ip=projector.link.ip))
|
||||
return
|
||||
|
||||
def on_connect_projector(self, opt=None):
|
||||
@ -647,7 +664,7 @@ class ProjectorManager(QtWidgets.QWidget, RegistryBase, UiProjectorManager, LogM
|
||||
'Other info'),
|
||||
data=projector.link.other_info)
|
||||
message += '<b>{title}</b>: {data}<br />'.format(title=translate('OpenLP.ProjectorManager', 'Power status'),
|
||||
data=ERROR_MSG[projector.link.power])
|
||||
data=STATUS_MSG[projector.link.power])
|
||||
message += '<b>{title}</b>: {data}<br />'.format(title=translate('OpenLP.ProjectorManager', 'Shutter is'),
|
||||
data=translate('OpenLP.ProjectorManager', 'Closed')
|
||||
if projector.link.shutter
|
||||
@ -692,7 +709,7 @@ class ProjectorManager(QtWidgets.QWidget, RegistryBase, UiProjectorManager, LogM
|
||||
else:
|
||||
message += '<b>{data}</b>'.format(data=translate('OpenLP.ProjectorManager', 'Current errors/warnings'))
|
||||
for (key, val) in projector.link.projector_errors.items():
|
||||
message += '<b>{key}</b>: {data}<br />'.format(key=key, data=ERROR_MSG[val])
|
||||
message += '<b>{key}</b>: {data}<br />'.format(key=key, data=STATUS_MSG[val])
|
||||
QtWidgets.QMessageBox.information(self, translate('OpenLP.ProjectorManager', 'Projector Information'), message)
|
||||
|
||||
def _add_projector(self, projector):
|
||||
@ -817,31 +834,18 @@ class ProjectorManager(QtWidgets.QWidget, RegistryBase, UiProjectorManager, LogM
|
||||
if ip == list_item.link.ip:
|
||||
item = list_item
|
||||
break
|
||||
message = translate('OpenLP.ProjectorManager', 'No message') if msg is None else msg
|
||||
if status in STATUS_STRING:
|
||||
status_code = STATUS_STRING[status]
|
||||
message = ERROR_MSG[status] if msg is None else msg
|
||||
elif status in ERROR_STRING:
|
||||
status_code = ERROR_STRING[status]
|
||||
message = ERROR_MSG[status] if msg is None else msg
|
||||
else:
|
||||
status_code = status
|
||||
message = ERROR_MSG[status] if msg is None else msg
|
||||
log.debug('({name}) updateStatus(status={status}) message: "{message}"'.format(name=item.link.name,
|
||||
status=status_code,
|
||||
message=message))
|
||||
if status in STATUS_ICONS:
|
||||
if item.status == status:
|
||||
return
|
||||
item.status = status
|
||||
item.icon = QtGui.QIcon(QtGui.QPixmap(STATUS_ICONS[status]))
|
||||
if status in ERROR_STRING:
|
||||
status_code = ERROR_STRING[status]
|
||||
elif status in STATUS_STRING:
|
||||
status_code = STATUS_STRING[status]
|
||||
log.debug('({name}) Updating icon with {code}'.format(name=item.link.name, code=status_code))
|
||||
item.widget.setIcon(item.icon)
|
||||
self.update_icons()
|
||||
if item is None:
|
||||
log.error('ProjectorManager: Unknown item "{ip}" - not updating status'.format(ip=ip))
|
||||
return
|
||||
elif item.status == status:
|
||||
log.debug('ProjectorManager: No status change for "{ip}" - not updating status'.format(ip=ip))
|
||||
return
|
||||
|
||||
item.status = status
|
||||
item.icon = QtGui.QIcon(QtGui.QPixmap(STATUS_ICONS[status]))
|
||||
log.debug('({name}) Updating icon with {code}'.format(name=item.link.name, code=STATUS_CODE[status]))
|
||||
item.widget.setIcon(item.icon)
|
||||
return self.update_icons()
|
||||
|
||||
def get_toolbar_item(self, name, enabled=False, hidden=False):
|
||||
item = self.one_toolbar.findChild(QtWidgets.QAction, name)
|
||||
@ -877,7 +881,7 @@ class ProjectorManager(QtWidgets.QWidget, RegistryBase, UiProjectorManager, LogM
|
||||
self.get_toolbar_item('show_projector_multiple', hidden=True)
|
||||
elif count == 1:
|
||||
projector = self.projector_list_widget.selectedItems()[0].data(QtCore.Qt.UserRole)
|
||||
connected = projector.link.state() == projector.link.ConnectedState
|
||||
connected = QSOCKET_STATE[projector.link.state()] == S_CONNECTED
|
||||
power = projector.link.power == S_ON
|
||||
self.get_toolbar_item('connect_projector_multiple', hidden=True)
|
||||
self.get_toolbar_item('disconnect_projector_multiple', hidden=True)
|
||||
|
@ -54,11 +54,12 @@ from PyQt5 import QtCore, QtNetwork
|
||||
|
||||
from openlp.core.common import qmd5_hash
|
||||
from openlp.core.common.i18n import translate
|
||||
from openlp.core.projectors.constants import CONNECTION_ERRORS, CR, ERROR_MSG, ERROR_STRING, \
|
||||
E_AUTHENTICATION, E_CONNECTION_REFUSED, E_GENERAL, E_INVALID_DATA, E_NETWORK, E_NOT_CONNECTED, E_OK, \
|
||||
E_PARAMETER, E_PROJECTOR, E_SOCKET_TIMEOUT, E_UNAVAILABLE, E_UNDEFINED, PJLINK_ERRORS, PJLINK_ERST_DATA, \
|
||||
PJLINK_ERST_STATUS, PJLINK_MAX_PACKET, PJLINK_PORT, PJLINK_POWR_STATUS, PJLINK_VALID_CMD, \
|
||||
STATUS_STRING, S_CONNECTED, S_CONNECTING, S_INFO, S_NOT_CONNECTED, S_OFF, S_OK, S_ON, S_QSOCKET_STATE, S_STATUS
|
||||
from openlp.core.projectors.constants import CONNECTION_ERRORS, PJLINK_CLASS, PJLINK_DEFAULT_CODES, PJLINK_ERRORS, \
|
||||
PJLINK_ERST_DATA, PJLINK_ERST_STATUS, PJLINK_MAX_PACKET, PJLINK_PREFIX, PJLINK_PORT, PJLINK_POWR_STATUS, \
|
||||
PJLINK_SUFFIX, PJLINK_VALID_CMD, PROJECTOR_STATE, STATUS_CODE, STATUS_MSG, QSOCKET_STATE, \
|
||||
E_AUTHENTICATION, E_CONNECTION_REFUSED, E_GENERAL, E_INVALID_DATA, E_NETWORK, E_NOT_CONNECTED, \
|
||||
E_OK, E_SOCKET_TIMEOUT, \
|
||||
S_CONNECTED, S_CONNECTING, S_INFO, S_NOT_CONNECTED, S_OFF, S_OK, S_ON, S_STATUS
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
log.debug('pjlink loaded')
|
||||
@ -69,12 +70,9 @@ __all__ = ['PJLink']
|
||||
SocketError = QtNetwork.QAbstractSocket.SocketError
|
||||
SocketSTate = QtNetwork.QAbstractSocket.SocketState
|
||||
|
||||
PJLINK_PREFIX = '%'
|
||||
PJLINK_CLASS = '1' # Default to class 1 until we query the projector
|
||||
# Add prefix here, but defer linkclass expansion until later when we have the actual
|
||||
# PJLink class for the command
|
||||
PJLINK_HEADER = '{prefix}{{linkclass}}'.format(prefix=PJLINK_PREFIX)
|
||||
PJLINK_SUFFIX = CR
|
||||
|
||||
|
||||
class PJLinkUDP(QtNetwork.QUdpSocket):
|
||||
@ -136,8 +134,9 @@ class PJLinkCommands(object):
|
||||
"""
|
||||
Initialize instance variables. Also used to reset projector-specific information to default.
|
||||
"""
|
||||
conn_state = STATUS_CODE[QSOCKET_STATE[self.state()]]
|
||||
log.debug('({ip}) reset_information() connect status is {state}'.format(ip=self.ip,
|
||||
state=S_QSOCKET_STATE[self.state()]))
|
||||
state=conn_state))
|
||||
self.fan = None # ERST
|
||||
self.filter_time = None # FILT
|
||||
self.lamp = None # LAMP
|
||||
@ -183,42 +182,25 @@ class PJLinkCommands(object):
|
||||
# Due to some replies should stay as mixed-case, validate using separate uppercase check
|
||||
_data = data.upper()
|
||||
# Check if we have a future command not available yet
|
||||
if cmd not in PJLINK_VALID_CMD:
|
||||
log.error('({ip}) Ignoring command="{cmd}" (Invalid/Unknown)'.format(ip=self.ip, cmd=cmd))
|
||||
if cmd not in self.pjlink_functions:
|
||||
log.warning('({ip}) Unable to process command="{cmd}" (Future option?)'.format(ip=self.ip, cmd=cmd))
|
||||
return
|
||||
elif _data == 'OK':
|
||||
log.debug('({ip}) Command "{cmd}" returned OK'.format(ip=self.ip, cmd=cmd))
|
||||
# A command returned successfully, so do a query on command to verify status
|
||||
return self.send_command(cmd=cmd)
|
||||
elif cmd not in self.pjlink_functions:
|
||||
log.warning('({ip}) Unable to process command="{cmd}" (Future option?)'.format(ip=self.ip, cmd=cmd))
|
||||
return
|
||||
elif _data in PJLINK_ERRORS:
|
||||
# Oops - projector error
|
||||
log.error('({ip}) Projector returned error "{data}"'.format(ip=self.ip, data=data))
|
||||
if _data == PJLINK_ERRORS[E_AUTHENTICATION]:
|
||||
# Authentication error
|
||||
log.error('({ip}) {cmd}: {err}'.format(ip=self.ip,
|
||||
cmd=cmd,
|
||||
err=STATUS_MSG[PJLINK_ERRORS[_data]]))
|
||||
if PJLINK_ERRORS[_data] == E_AUTHENTICATION:
|
||||
self.disconnect_from_host()
|
||||
self.change_status(E_AUTHENTICATION)
|
||||
log.debug('({ip}) emitting projectorAuthentication() signal'.format(ip=self.ip))
|
||||
self.projectorAuthentication.emit(self.name)
|
||||
elif _data == PJLINK_ERRORS[E_UNDEFINED]:
|
||||
# Projector does not recognize command
|
||||
self.change_status(E_UNDEFINED, '{error}: "{data}"'.format(error=ERROR_MSG[E_UNDEFINED],
|
||||
data=cmd))
|
||||
elif _data == PJLINK_ERRORS[E_PARAMETER]:
|
||||
# Invalid parameter
|
||||
self.change_status(E_PARAMETER)
|
||||
elif _data == PJLINK_ERRORS[E_UNAVAILABLE]:
|
||||
# Projector busy
|
||||
self.change_status(E_UNAVAILABLE)
|
||||
elif _data == PJLINK_ERRORS[E_PROJECTOR]:
|
||||
# Projector/display error
|
||||
self.change_status(E_PROJECTOR)
|
||||
return
|
||||
return self.change_status(status=E_AUTHENTICATION)
|
||||
# Command checks already passed
|
||||
log.debug('({ip}) Calling function for {cmd}'.format(ip=self.ip, cmd=cmd))
|
||||
self.pjlink_functions[cmd](data)
|
||||
self.pjlink_functions[cmd](data=data)
|
||||
|
||||
def process_avmt(self, data):
|
||||
"""
|
||||
@ -313,22 +295,22 @@ class PJLinkCommands(object):
|
||||
data[PJLINK_ERST_DATA['COVER']],
|
||||
data[PJLINK_ERST_DATA['FILTER']],
|
||||
data[PJLINK_ERST_DATA['OTHER']])
|
||||
if fan != PJLINK_ERST_STATUS[E_OK]:
|
||||
if fan != PJLINK_ERST_STATUS[S_OK]:
|
||||
self.projector_errors[translate('OpenLP.ProjectorPJLink', 'Fan')] = \
|
||||
PJLINK_ERST_STATUS[fan]
|
||||
if lamp != PJLINK_ERST_STATUS[E_OK]:
|
||||
if lamp != PJLINK_ERST_STATUS[S_OK]:
|
||||
self.projector_errors[translate('OpenLP.ProjectorPJLink', 'Lamp')] = \
|
||||
PJLINK_ERST_STATUS[lamp]
|
||||
if temp != PJLINK_ERST_STATUS[E_OK]:
|
||||
if temp != PJLINK_ERST_STATUS[S_OK]:
|
||||
self.projector_errors[translate('OpenLP.ProjectorPJLink', 'Temperature')] = \
|
||||
PJLINK_ERST_STATUS[temp]
|
||||
if cover != PJLINK_ERST_STATUS[E_OK]:
|
||||
if cover != PJLINK_ERST_STATUS[S_OK]:
|
||||
self.projector_errors[translate('OpenLP.ProjectorPJLink', 'Cover')] = \
|
||||
PJLINK_ERST_STATUS[cover]
|
||||
if filt != PJLINK_ERST_STATUS[E_OK]:
|
||||
if filt != PJLINK_ERST_STATUS[S_OK]:
|
||||
self.projector_errors[translate('OpenLP.ProjectorPJLink', 'Filter')] = \
|
||||
PJLINK_ERST_STATUS[filt]
|
||||
if other != PJLINK_ERST_STATUS[E_OK]:
|
||||
if other != PJLINK_ERST_STATUS[S_OK]:
|
||||
self.projector_errors[translate('OpenLP.ProjectorPJLink', 'Other')] = \
|
||||
PJLINK_ERST_STATUS[other]
|
||||
return
|
||||
@ -373,8 +355,18 @@ class PJLinkCommands(object):
|
||||
|
||||
:param data: Currently selected source
|
||||
"""
|
||||
# First, see if we have a valid input based on what is installed (if available)
|
||||
if self.source_available is not None:
|
||||
# We have available inputs, so verify it's in the list
|
||||
if data not in self.source_available:
|
||||
log.warn('({ip}) Input source not listed in available sources - ignoring'.format(ip=self.ip))
|
||||
return
|
||||
elif data not in PJLINK_DEFAULT_CODES:
|
||||
# Hmm - no sources available yet, so check with PJLink defaults
|
||||
log.warn('({ip}) Input source not listed as a PJLink available source - ignoring'.format(ip=self.ip))
|
||||
return
|
||||
self.source = data
|
||||
log.info('({ip}) Setting data source to "{data}"'.format(ip=self.ip, data=self.source))
|
||||
log.debug('({ip}) Setting data source to "{data}"'.format(ip=self.ip, data=self.source))
|
||||
return
|
||||
|
||||
def process_inst(self, data):
|
||||
@ -390,7 +382,6 @@ class PJLinkCommands(object):
|
||||
sources.append(source)
|
||||
sources.sort()
|
||||
self.source_available = sources
|
||||
self.projectorUpdateIcons.emit()
|
||||
log.debug('({ip}) Setting projector sources_available to "{data}"'.format(ip=self.ip,
|
||||
data=self.source_available))
|
||||
return
|
||||
@ -551,17 +542,15 @@ class PJLinkCommands(object):
|
||||
return
|
||||
elif self.sw_version is None:
|
||||
log.debug('({ip}) Setting projector software version to "{data}"'.format(ip=self.ip, data=data))
|
||||
self.sw_version = data
|
||||
self.db_update = True
|
||||
else:
|
||||
# Compare software version and see if we got the same projector
|
||||
if self.serial_no != data:
|
||||
if self.sw_version != data:
|
||||
log.warning('({ip}) Projector software version does not match saved '
|
||||
'software version'.format(ip=self.ip))
|
||||
log.warning('({ip}) Saved: "{old}"'.format(ip=self.ip, old=self.sw_version))
|
||||
log.warning('({ip}) Received: "{new}"'.format(ip=self.ip, new=data))
|
||||
log.warning('({ip}) Saving new serial number as sw_version_received'.format(ip=self.ip))
|
||||
self.sw_version_received = data
|
||||
log.warning('({ip}) Updating software version'.format(ip=self.ip))
|
||||
self.sw_version = data
|
||||
self.db_update = True
|
||||
|
||||
|
||||
class PJLink(QtNetwork.QTcpSocket, PJLinkCommands):
|
||||
@ -678,7 +667,7 @@ class PJLink(QtNetwork.QTcpSocket, PJLinkCommands):
|
||||
Retrieve information from projector that changes.
|
||||
Normally called by timer().
|
||||
"""
|
||||
if self.state() != S_QSOCKET_STATE['ConnectedState']:
|
||||
if QSOCKET_STATE[self.state()] != S_CONNECTED:
|
||||
log.warning('({ip}) poll_loop(): Not connected - returning'.format(ip=self.ip))
|
||||
return
|
||||
log.debug('({ip}) poll_loop(): Updating projector status'.format(ip=self.ip))
|
||||
@ -688,13 +677,8 @@ class PJLink(QtNetwork.QTcpSocket, PJLinkCommands):
|
||||
self.timer.setInterval(self.poll_time)
|
||||
# Restart timer
|
||||
self.timer.start()
|
||||
# These commands may change during connection
|
||||
check_list = ['POWR', 'ERST', 'LAMP', 'AVMT', 'INPT']
|
||||
if self.pjlink_class == '2':
|
||||
check_list.extend(['FILT', 'FREZ'])
|
||||
for command in check_list:
|
||||
self.send_command(command)
|
||||
# The following commands do not change, so only check them once
|
||||
# Call them first in case other functions rely on something here
|
||||
if self.power == S_ON and self.source_available is None:
|
||||
self.send_command('INST')
|
||||
if self.other_info is None:
|
||||
@ -715,22 +699,28 @@ class PJLink(QtNetwork.QTcpSocket, PJLinkCommands):
|
||||
self.send_command('RFIL')
|
||||
if self.model_lamp is None:
|
||||
self.send_command('RLMP')
|
||||
# These commands may change during connection
|
||||
check_list = ['POWR', 'ERST', 'LAMP', 'AVMT', 'INPT']
|
||||
if self.pjlink_class == '2':
|
||||
check_list.extend(['FILT', 'FREZ'])
|
||||
for command in check_list:
|
||||
self.send_command(command)
|
||||
|
||||
def _get_status(self, status):
|
||||
"""
|
||||
Helper to retrieve status/error codes and convert to strings.
|
||||
|
||||
:param status: Status/Error code
|
||||
:returns: (Status/Error code, String)
|
||||
:returns: tuple (-1 if code not INT, None)
|
||||
:returns: tuple (string: code as string, None if no description)
|
||||
:returns: tuple (string: code as string, string: Status/Error description)
|
||||
"""
|
||||
if not isinstance(status, int):
|
||||
return -1, 'Invalid status code'
|
||||
elif status in ERROR_STRING:
|
||||
return ERROR_STRING[status], ERROR_MSG[status]
|
||||
elif status in STATUS_STRING:
|
||||
return STATUS_STRING[status], ERROR_MSG[status]
|
||||
return -1, None
|
||||
elif status not in STATUS_MSG:
|
||||
return None, None
|
||||
else:
|
||||
return status, translate('OpenLP.PJLink', 'Unknown status')
|
||||
return STATUS_CODE[status], STATUS_MSG[status]
|
||||
|
||||
def change_status(self, status, msg=None):
|
||||
"""
|
||||
@ -740,19 +730,27 @@ class PJLink(QtNetwork.QTcpSocket, PJLinkCommands):
|
||||
:param status: Status code
|
||||
:param msg: Optional message
|
||||
"""
|
||||
message = translate('OpenLP.PJLink', 'No message') if msg is None else msg
|
||||
(code, message) = self._get_status(status)
|
||||
if msg is not None:
|
||||
message = msg
|
||||
if status in STATUS_CODE:
|
||||
log.debug('({ip}) Changing status to {status} '
|
||||
'"{msg}"'.format(ip=self.ip,
|
||||
status=STATUS_CODE[status],
|
||||
msg=msg if msg is not None else STATUS_MSG[status]))
|
||||
else:
|
||||
log.warning('({ip}) Unknown status change code: {code}'.format(ip=self.ip,
|
||||
code=status))
|
||||
return
|
||||
if status in CONNECTION_ERRORS:
|
||||
# Projector, connection state
|
||||
self.projector_status = self.error_status = self.status_connect = E_NOT_CONNECTED
|
||||
elif status >= S_NOT_CONNECTED and status < S_STATUS:
|
||||
# Connection state error affects both socket and projector
|
||||
self.error_status = status
|
||||
self.status_connect = E_NOT_CONNECTED
|
||||
elif status >= S_NOT_CONNECTED and status in QSOCKET_STATE:
|
||||
# Socket connection status update
|
||||
self.status_connect = status
|
||||
self.projector_status = S_NOT_CONNECTED
|
||||
elif status <= S_INFO:
|
||||
self.status_connect = S_CONNECTED
|
||||
elif status >= S_NOT_CONNECTED and status in PROJECTOR_STATE:
|
||||
# Only affects the projector status
|
||||
self.projector_status = status
|
||||
|
||||
# These log entries are for troubleshooting only
|
||||
(status_code, status_message) = self._get_status(self.status_connect)
|
||||
log.debug('({ip}) status_connect: {code}: "{message}"'.format(ip=self.ip,
|
||||
code=status_code,
|
||||
@ -765,6 +763,15 @@ class PJLink(QtNetwork.QTcpSocket, PJLinkCommands):
|
||||
log.debug('({ip}) error_status: {code}: "{message}"'.format(ip=self.ip,
|
||||
code=status_code,
|
||||
message=status_message if msg is None else msg))
|
||||
|
||||
# Now that we logged extra information for debugging, broadcast the original change/message
|
||||
(code, message) = self._get_status(status)
|
||||
if msg is not None:
|
||||
message = msg
|
||||
elif message is None:
|
||||
# No message for status code
|
||||
message = translate('OpenLP.PJLink', 'No message') if msg is None else msg
|
||||
|
||||
self.changeStatus.emit(self.ip, status, message)
|
||||
self.projectorUpdateIcons.emit()
|
||||
|
||||
@ -794,7 +801,7 @@ class PJLink(QtNetwork.QTcpSocket, PJLinkCommands):
|
||||
data = decode(read, 'utf-8')
|
||||
# Possibility of extraneous data on input when reading.
|
||||
# Clean out extraneous characters in buffer.
|
||||
self.readLine(self.max_size)
|
||||
self.read(2048)
|
||||
log.debug('({ip}) check_login() read "{data}"'.format(ip=self.ip, data=data.strip()))
|
||||
# At this point, we should only have the initial login prompt with
|
||||
# possible authentication
|
||||
@ -805,6 +812,7 @@ class PJLink(QtNetwork.QTcpSocket, PJLinkCommands):
|
||||
# Invalid initial packet - close socket
|
||||
log.error('({ip}) Invalid initial packet received - closing socket'.format(ip=self.ip))
|
||||
return self.disconnect_from_host()
|
||||
# Convert the initial login prompt with the expected PJLink normal command format for processing
|
||||
log.debug('({ip}) check_login(): Formatting initial connection prompt to PJLink packet'.format(ip=self.ip))
|
||||
return self.get_data('{start}{clss}{data}'.format(start=PJLINK_PREFIX,
|
||||
clss='1',
|
||||
@ -895,7 +903,7 @@ class PJLink(QtNetwork.QTcpSocket, PJLinkCommands):
|
||||
Get data from TCP socket.
|
||||
"""
|
||||
log.debug('({ip}) get_socket(): Reading data'.format(ip=self.ip))
|
||||
if self.state() != self.ConnectedState:
|
||||
if QSOCKET_STATE[self.state()] != S_CONNECTED:
|
||||
log.debug('({ip}) get_socket(): Not connected - returning'.format(ip=self.ip))
|
||||
self.send_busy = False
|
||||
return
|
||||
@ -907,8 +915,7 @@ class PJLink(QtNetwork.QTcpSocket, PJLinkCommands):
|
||||
log.debug('({ip}) get_socket(): No data available (-1)'.format(ip=self.ip))
|
||||
return self.receive_data_signal()
|
||||
self.socket_timer.stop()
|
||||
self.get_data(buff=read, ip=self.ip)
|
||||
return self.receive_data_signal()
|
||||
return self.get_data(buff=read, ip=self.ip)
|
||||
|
||||
def get_data(self, buff, ip=None):
|
||||
"""
|
||||
@ -927,13 +934,17 @@ class PJLink(QtNetwork.QTcpSocket, PJLinkCommands):
|
||||
data = data_in.strip()
|
||||
# Initial packet checks
|
||||
if (len(data) < 7):
|
||||
return self._trash_buffer(msg='get_data(): Invalid packet - length')
|
||||
self._trash_buffer(msg='get_data(): Invalid packet - length')
|
||||
return self.receive_data_signal()
|
||||
elif len(data) > self.max_size:
|
||||
return self._trash_buffer(msg='get_data(): Invalid packet - too long')
|
||||
self._trash_buffer(msg='get_data(): Invalid packet - too long')
|
||||
return self.receive_data_signal()
|
||||
elif not data.startswith(PJLINK_PREFIX):
|
||||
return self._trash_buffer(msg='get_data(): Invalid packet - PJLink prefix missing')
|
||||
self._trash_buffer(msg='get_data(): Invalid packet - PJLink prefix missing')
|
||||
return self.receive_data_signal()
|
||||
elif '=' not in data:
|
||||
return self._trash_buffer(msg='get_data(): Invalid reply - Does not have "="')
|
||||
self._trash_buffer(msg='get_data(): Invalid reply - Does not have "="')
|
||||
return self.receive_data_signal()
|
||||
log.debug('({ip}) get_data(): Checking new data "{data}"'.format(ip=self.ip, data=data))
|
||||
header, data = data.split('=')
|
||||
# At this point, the header should contain:
|
||||
@ -947,15 +958,17 @@ class PJLink(QtNetwork.QTcpSocket, PJLinkCommands):
|
||||
except ValueError as e:
|
||||
self.change_status(E_INVALID_DATA)
|
||||
log.warning('({ip}) get_data(): Received data: "{data}"'.format(ip=self.ip, data=data_in))
|
||||
return self._trash_buffer('get_data(): Expected header + command + data')
|
||||
self._trash_buffer('get_data(): Expected header + command + data')
|
||||
return self.receive_data_signal()
|
||||
if cmd not in PJLINK_VALID_CMD:
|
||||
log.warning('({ip}) get_data(): Invalid packet - unknown command "{data}"'.format(ip=self.ip, data=cmd))
|
||||
return self._trash_buffer(msg='get_data(): Unknown command "{data}"'.format(data=cmd))
|
||||
self._trash_buffer(msg='get_data(): Unknown command "{data}"'.format(data=cmd))
|
||||
return self.receive_data_signal()
|
||||
if int(self.pjlink_class) < int(version):
|
||||
log.warning('({ip}) get_data(): Projector returned class reply higher '
|
||||
'than projector stated class'.format(ip=self.ip))
|
||||
self.send_busy = False
|
||||
return self.process_command(cmd, data)
|
||||
self.process_command(cmd, data)
|
||||
return self.receive_data_signal()
|
||||
|
||||
@QtCore.pyqtSlot(QtNetwork.QAbstractSocket.SocketError)
|
||||
def get_error(self, err):
|
||||
@ -993,7 +1006,7 @@ class PJLink(QtNetwork.QTcpSocket, PJLinkCommands):
|
||||
:param salt: Optional salt for md5 hash initial authentication
|
||||
:param priority: Option to send packet now rather than queue it up
|
||||
"""
|
||||
if self.state() != self.ConnectedState:
|
||||
if QSOCKET_STATE[self.state()] != S_CONNECTED:
|
||||
log.warning('({ip}) send_command(): Not connected - returning'.format(ip=self.ip))
|
||||
return self.reset_information()
|
||||
if cmd not in PJLINK_VALID_CMD:
|
||||
@ -1018,7 +1031,7 @@ class PJLink(QtNetwork.QTcpSocket, PJLinkCommands):
|
||||
header=header,
|
||||
command=cmd,
|
||||
options=opts,
|
||||
suffix=CR)
|
||||
suffix=PJLINK_SUFFIX)
|
||||
if out in self.priority_queue:
|
||||
log.debug('({ip}) send_command(): Already in priority queue - skipping'.format(ip=self.ip))
|
||||
elif out in self.send_queue:
|
||||
@ -1044,9 +1057,10 @@ class PJLink(QtNetwork.QTcpSocket, PJLinkCommands):
|
||||
"""
|
||||
# Funny looking data check, but it's a quick check for data=None
|
||||
log.debug('({ip}) _send_command(data="{data}")'.format(ip=self.ip, data=data.strip() if data else data))
|
||||
conn_state = STATUS_CODE[QSOCKET_STATE[self.state()]]
|
||||
log.debug('({ip}) _send_command(): Connection status: {data}'.format(ip=self.ip,
|
||||
data=S_QSOCKET_STATE[self.state()]))
|
||||
if self.state() != self.ConnectedState:
|
||||
data=conn_state))
|
||||
if QSOCKET_STATE[self.state()] != S_CONNECTED:
|
||||
log.debug('({ip}) _send_command() Not connected - abort'.format(ip=self.ip))
|
||||
self.send_busy = False
|
||||
return self.disconnect_from_host()
|
||||
@ -1088,10 +1102,11 @@ class PJLink(QtNetwork.QTcpSocket, PJLinkCommands):
|
||||
"""
|
||||
Initiate connection to projector.
|
||||
"""
|
||||
log.debug('{ip}) connect_to_host(): Starting connection'.format(ip=self.ip))
|
||||
if self.state() == self.ConnectedState:
|
||||
log.debug('({ip}) connect_to_host(): Starting connection'.format(ip=self.ip))
|
||||
if QSOCKET_STATE[self.state()] == S_CONNECTED:
|
||||
log.warning('({ip}) connect_to_host(): Already connected - returning'.format(ip=self.ip))
|
||||
return
|
||||
self.error_status = S_OK
|
||||
self.change_status(S_CONNECTING)
|
||||
self.connectToHost(self.ip, self.port if isinstance(self.port, int) else int(self.port))
|
||||
|
||||
@ -1100,12 +1115,13 @@ class PJLink(QtNetwork.QTcpSocket, PJLinkCommands):
|
||||
"""
|
||||
Close socket and cleanup.
|
||||
"""
|
||||
if abort or self.state() != self.ConnectedState:
|
||||
if abort or QSOCKET_STATE[self.state()] != S_NOT_CONNECTED:
|
||||
if abort:
|
||||
log.warning('({ip}) disconnect_from_host(): Aborting connection'.format(ip=self.ip))
|
||||
self.abort()
|
||||
else:
|
||||
log.warning('({ip}) disconnect_from_host(): Not connected'.format(ip=self.ip))
|
||||
self.disconnectFromHost()
|
||||
self.disconnectFromHost()
|
||||
try:
|
||||
self.readyRead.disconnect(self.get_socket)
|
||||
except TypeError:
|
||||
@ -1201,7 +1217,7 @@ class PJLink(QtNetwork.QTcpSocket, PJLinkCommands):
|
||||
elif src not in self.source_available:
|
||||
return
|
||||
log.debug('({ip}) Setting input source to "{data}"'.format(ip=self.ip, data=src))
|
||||
self.send_command(cmd='INPT', opts=src)
|
||||
self.send_command(cmd='INPT', opts=src, priority=True)
|
||||
self.poll_loop()
|
||||
|
||||
def set_power_on(self):
|
||||
@ -1209,7 +1225,7 @@ class PJLink(QtNetwork.QTcpSocket, PJLinkCommands):
|
||||
Send command to turn power to on.
|
||||
"""
|
||||
log.debug('({ip}) Setting POWR to 1 (on)'.format(ip=self.ip))
|
||||
self.send_command(cmd='POWR', opts='1')
|
||||
self.send_command(cmd='POWR', opts='1', priority=True)
|
||||
self.poll_loop()
|
||||
|
||||
def set_power_off(self):
|
||||
@ -1217,7 +1233,7 @@ class PJLink(QtNetwork.QTcpSocket, PJLinkCommands):
|
||||
Send command to turn power to standby.
|
||||
"""
|
||||
log.debug('({ip}) Setting POWR to 0 (standby)'.format(ip=self.ip))
|
||||
self.send_command(cmd='POWR', opts='0')
|
||||
self.send_command(cmd='POWR', opts='0', priority=True)
|
||||
self.poll_loop()
|
||||
|
||||
def set_shutter_closed(self):
|
||||
@ -1225,7 +1241,7 @@ class PJLink(QtNetwork.QTcpSocket, PJLinkCommands):
|
||||
Send command to set shutter to closed position.
|
||||
"""
|
||||
log.debug('({ip}) Setting AVMT to 11 (shutter closed)'.format(ip=self.ip))
|
||||
self.send_command(cmd='AVMT', opts='11')
|
||||
self.send_command(cmd='AVMT', opts='11', priority=True)
|
||||
self.poll_loop()
|
||||
|
||||
def set_shutter_open(self):
|
||||
@ -1233,8 +1249,9 @@ class PJLink(QtNetwork.QTcpSocket, PJLinkCommands):
|
||||
Send command to set shutter to open position.
|
||||
"""
|
||||
log.debug('({ip}) Setting AVMT to "10" (shutter open)'.format(ip=self.ip))
|
||||
self.send_command(cmd='AVMT', opts='10')
|
||||
self.send_command(cmd='AVMT', opts='10', priority=True)
|
||||
self.poll_loop()
|
||||
self.projectorUpdateIcons.emit()
|
||||
|
||||
def receive_data_signal(self):
|
||||
"""
|
||||
|
@ -23,12 +23,51 @@
|
||||
Package to test the openlp.core.projectors.constants module.
|
||||
"""
|
||||
from unittest import TestCase
|
||||
from openlp.core.projectors import constants
|
||||
from openlp.core.projectors.constants import STATUS_CODE, STATUS_MSG
|
||||
|
||||
|
||||
class TestProjectorConstants(TestCase):
|
||||
"""
|
||||
Test specific functions in the projector constants module.
|
||||
"""
|
||||
def test_defined_codes_in_status_code(self):
|
||||
"""
|
||||
Test defined status/error codes have equivalent strings
|
||||
"""
|
||||
check = []
|
||||
missing_str = []
|
||||
|
||||
# GIVEN: List of defined E_* and S_* items defined in constants
|
||||
for item in constants.__dict__:
|
||||
if item.startswith('E_') or item.startswith('S_'):
|
||||
check.append(item)
|
||||
|
||||
# WHEN: Verify defined list against STATUS_STR
|
||||
for item in check:
|
||||
if constants.__dict__[item] not in STATUS_CODE:
|
||||
missing_str.append(item)
|
||||
|
||||
# THEN: There should be no missing items
|
||||
assert 0 == len(missing_str), 'Status string missing: {msg}'.format(msg=missing_str)
|
||||
|
||||
def test_status_code_in_status_message(self):
|
||||
"""
|
||||
Test if entries in STATUS_CODE have equivalent descriptions in STATUS_MSG
|
||||
"""
|
||||
missing_msg = []
|
||||
|
||||
# GIVEN: Test items
|
||||
check = STATUS_CODE
|
||||
|
||||
# WHEN: Verify each entry in STATUS_MSG against STATUS_CODE
|
||||
for item in check:
|
||||
if item not in STATUS_MSG:
|
||||
missing_msg.append(item)
|
||||
|
||||
# THEN: There should be no missing items
|
||||
assert 0 == len(missing_msg), 'Status message missing: {msg}'.format(msg=missing_msg)
|
||||
|
||||
def test_build_pjlink_video_label(self):
|
||||
"""
|
||||
Test building PJLINK_DEFAULT_CODES dictionary
|
||||
|
@ -25,7 +25,7 @@ Package to test the openlp.core.projectors.pjlink base package.
|
||||
from unittest import TestCase
|
||||
from unittest.mock import call, patch, MagicMock
|
||||
|
||||
from openlp.core.projectors.constants import E_PARAMETER, ERROR_STRING, S_ON, S_CONNECTED, S_QSOCKET_STATE
|
||||
from openlp.core.projectors.constants import E_PARAMETER, STATUS_CODE, S_ON, S_CONNECTED, QSOCKET_STATE
|
||||
from openlp.core.projectors.db import Projector
|
||||
from openlp.core.projectors.pjlink import PJLink
|
||||
|
||||
@ -65,7 +65,7 @@ class TestPJLinkBase(TestCase):
|
||||
# as first parameter
|
||||
mock_change_status.called_with(E_PARAMETER,
|
||||
'change_status should have been called with "{}"'.format(
|
||||
ERROR_STRING[E_PARAMETER]))
|
||||
STATUS_CODE[E_PARAMETER]))
|
||||
|
||||
@patch.object(pjlink_test, 'disconnect_from_host')
|
||||
def test_socket_abort(self, mock_disconnect):
|
||||
@ -104,7 +104,7 @@ class TestPJLinkBase(TestCase):
|
||||
"""
|
||||
# GIVEN: Mocks and test data
|
||||
mock_state = patch.object(self.pjlink_test, 'state').start()
|
||||
mock_state.return_value = S_QSOCKET_STATE['ConnectedState']
|
||||
mock_state.return_value = QSOCKET_STATE[S_CONNECTED]
|
||||
mock_timer = patch.object(self.pjlink_test, 'timer').start()
|
||||
mock_timer.interval.return_value = 10
|
||||
mock_send_command = patch.object(self.pjlink_test, 'send_command').start()
|
||||
@ -117,7 +117,6 @@ class TestPJLinkBase(TestCase):
|
||||
pjlink.manufacturer = None
|
||||
pjlink.model = None
|
||||
pjlink.pjlink_name = None
|
||||
pjlink.ConnectedState = S_CONNECTED
|
||||
call_list = [
|
||||
call('POWR'),
|
||||
call('ERST'),
|
||||
|
@ -24,209 +24,222 @@ Package to test the openlp.core.projectors.pjlink command routing.
|
||||
"""
|
||||
|
||||
from unittest import TestCase
|
||||
from unittest.mock import patch, MagicMock
|
||||
from unittest.mock import MagicMock, call, patch
|
||||
|
||||
import openlp.core.projectors.pjlink
|
||||
from openlp.core.projectors.constants import PJLINK_ERRORS, \
|
||||
from openlp.core.projectors.constants import PJLINK_ERRORS, PJLINK_PREFIX, STATUS_MSG, \
|
||||
E_AUTHENTICATION, E_PARAMETER, E_PROJECTOR, E_UNAVAILABLE, E_UNDEFINED
|
||||
from openlp.core.projectors.db import Projector
|
||||
from openlp.core.projectors.pjlink import PJLink
|
||||
|
||||
'''
|
||||
from openlp.core.projectors.constants import ERROR_STRING, PJLINK_ERST_DATA, PJLINK_ERST_STATUS, \
|
||||
PJLINK_POWR_STATUS, PJLINK_VALID_CMD, E_WARN, E_ERROR, S_OFF, S_STANDBY, S_ON
|
||||
'''
|
||||
from tests.resources.projector.data import TEST_PIN, TEST1_DATA
|
||||
|
||||
pjlink_test = PJLink(Projector(**TEST1_DATA), pin=TEST_PIN, no_poll=True)
|
||||
pjlink_test.ip = '127.0.0.1'
|
||||
from tests.resources.projector.data import TEST1_DATA
|
||||
|
||||
|
||||
class TestPJLinkRouting(TestCase):
|
||||
"""
|
||||
Tests for the PJLink module command routing
|
||||
"""
|
||||
def setUp(self):
|
||||
'''
|
||||
TestPJLinkCommands part 2 initialization
|
||||
'''
|
||||
self.pjlink_test = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
||||
def test_get_data_unknown_command(self):
|
||||
"""
|
||||
Test not a valid command
|
||||
"""
|
||||
# GIVEN: Test object
|
||||
log_warning_text = [call('(111.111.111.111) get_data(): Invalid packet - unknown command "UNK"')]
|
||||
log_debug_text = [call('(111.111.111.111) get_data(ip="111.111.111.111" buffer="b\'%1UNK=Huh?\'"'),
|
||||
call('(111.111.111.111) get_data(): Checking new data "%1UNK=Huh?"')]
|
||||
|
||||
def tearDown(self):
|
||||
'''
|
||||
TestPJLinkCommands part 2 cleanups
|
||||
'''
|
||||
self.pjlink_test = None
|
||||
with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
|
||||
patch.object(openlp.core.projectors.pjlink.PJLink, '_trash_buffer') as mock_buffer:
|
||||
|
||||
@patch.object(openlp.core.projectors.pjlink, 'log')
|
||||
def test_process_command_call_clss(self, mock_log):
|
||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
||||
pjlink.pjlink_functions = MagicMock()
|
||||
|
||||
# WHEN: get_data called with an unknown command
|
||||
pjlink.get_data(buff='{prefix}1UNK=Huh?'.format(prefix=PJLINK_PREFIX).encode('utf-8'))
|
||||
|
||||
# THEN: Appropriate log entries should have been made and methods called/not called
|
||||
mock_log.debug.assert_has_calls(log_debug_text)
|
||||
mock_log.warning.assert_has_calls(log_warning_text)
|
||||
self.assertFalse(pjlink.pjlink_functions.called, 'Should not have accessed pjlink_functions')
|
||||
self.assertTrue(mock_buffer.called, 'Should have called _trash_buffer')
|
||||
|
||||
def test_process_command_call_clss(self):
|
||||
"""
|
||||
Test process_command calls proper function
|
||||
"""
|
||||
# GIVEN: Test object
|
||||
pjlink = pjlink_test
|
||||
log_text = '(127.0.0.1) Calling function for CLSS'
|
||||
mock_log.reset_mock()
|
||||
mock_process_clss = MagicMock()
|
||||
pjlink.pjlink_functions['CLSS'] = mock_process_clss
|
||||
# GIVEN: Test object and mocks
|
||||
log_debug_calls = [call('(111.111.111.111) Processing command "CLSS" with data "1"'),
|
||||
call('(111.111.111.111) Calling function for CLSS')]
|
||||
|
||||
# WHEN: process_command is called with valid function and data
|
||||
pjlink.process_command(cmd='CLSS', data='1')
|
||||
with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
|
||||
patch.object(openlp.core.projectors.pjlink.PJLink, 'process_clss') as mock_process_clss:
|
||||
|
||||
# THEN: Process method should have been called properly
|
||||
mock_log.debug.assert_called_with(log_text)
|
||||
mock_process_clss.assert_called_with('1')
|
||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
||||
|
||||
@patch.object(pjlink_test, 'change_status')
|
||||
@patch.object(openlp.core.projectors.pjlink, 'log')
|
||||
def test_process_command_err1(self, mock_log, mock_change_status):
|
||||
"""
|
||||
Test ERR1 - Undefined projector function
|
||||
"""
|
||||
# GIVEN: Test object
|
||||
pjlink = pjlink_test
|
||||
log_text = '(127.0.0.1) Projector returned error "ERR1"'
|
||||
mock_change_status.reset_mock()
|
||||
mock_log.reset_mock()
|
||||
# WHEN: process_command is called with valid function and data
|
||||
pjlink.process_command(cmd='CLSS', data='1')
|
||||
|
||||
# WHEN: process_command called with ERR1
|
||||
pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_UNDEFINED])
|
||||
# THEN: Appropriate log entries should have been made and methods called
|
||||
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||
mock_process_clss.assert_called_once_with(data='1')
|
||||
|
||||
# THEN: Error should be logged and status_change should be called
|
||||
mock_change_status.assert_called_once_with(E_UNDEFINED, 'Undefined Command: "CLSS"')
|
||||
mock_log.error.assert_called_with(log_text)
|
||||
|
||||
@patch.object(pjlink_test, 'change_status')
|
||||
@patch.object(openlp.core.projectors.pjlink, 'log')
|
||||
def test_process_command_err2(self, mock_log, mock_change_status):
|
||||
"""
|
||||
Test ERR2 - Parameter Error
|
||||
"""
|
||||
# GIVEN: Test object
|
||||
pjlink = pjlink_test
|
||||
log_text = '(127.0.0.1) Projector returned error "ERR2"'
|
||||
mock_change_status.reset_mock()
|
||||
mock_log.reset_mock()
|
||||
|
||||
# WHEN: process_command called with ERR2
|
||||
pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_PARAMETER])
|
||||
|
||||
# THEN: Error should be logged and status_change should be called
|
||||
mock_change_status.assert_called_once_with(E_PARAMETER)
|
||||
mock_log.error.assert_called_with(log_text)
|
||||
|
||||
@patch.object(pjlink_test, 'change_status')
|
||||
@patch.object(openlp.core.projectors.pjlink, 'log')
|
||||
def test_process_command_err3(self, mock_log, mock_change_status):
|
||||
"""
|
||||
Test ERR3 - Unavailable error
|
||||
"""
|
||||
# GIVEN: Test object
|
||||
pjlink = pjlink_test
|
||||
log_text = '(127.0.0.1) Projector returned error "ERR3"'
|
||||
mock_change_status.reset_mock()
|
||||
mock_log.reset_mock()
|
||||
|
||||
# WHEN: process_command called with ERR3
|
||||
pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_UNAVAILABLE])
|
||||
|
||||
# THEN: Error should be logged and status_change should be called
|
||||
mock_change_status.assert_called_once_with(E_UNAVAILABLE)
|
||||
mock_log.error.assert_called_with(log_text)
|
||||
|
||||
@patch.object(pjlink_test, 'change_status')
|
||||
@patch.object(openlp.core.projectors.pjlink, 'log')
|
||||
def test_process_command_err4(self, mock_log, mock_change_status):
|
||||
"""
|
||||
Test ERR3 - Unavailable error
|
||||
"""
|
||||
# GIVEN: Test object
|
||||
pjlink = pjlink_test
|
||||
log_text = '(127.0.0.1) Projector returned error "ERR4"'
|
||||
mock_change_status.reset_mock()
|
||||
mock_log.reset_mock()
|
||||
|
||||
# WHEN: process_command called with ERR3
|
||||
pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_PROJECTOR])
|
||||
|
||||
# THEN: Error should be logged and status_change should be called
|
||||
mock_change_status.assert_called_once_with(E_PROJECTOR)
|
||||
mock_log.error.assert_called_with(log_text)
|
||||
|
||||
@patch.object(pjlink_test, 'projectorAuthentication')
|
||||
@patch.object(pjlink_test, 'change_status')
|
||||
@patch.object(pjlink_test, 'disconnect_from_host')
|
||||
@patch.object(openlp.core.projectors.pjlink, 'log')
|
||||
def test_process_command_erra(self, mock_log, mock_disconnect, mock_change_status, mock_err_authenticate):
|
||||
def test_process_command_erra(self):
|
||||
"""
|
||||
Test ERRA - Authentication Error
|
||||
"""
|
||||
# GIVEN: Test object
|
||||
pjlink = pjlink_test
|
||||
log_text = '(127.0.0.1) Projector returned error "ERRA"'
|
||||
mock_change_status.reset_mock()
|
||||
mock_log.reset_mock()
|
||||
log_error_calls = [call('(111.111.111.111) PJLINK: {msg}'.format(msg=STATUS_MSG[E_AUTHENTICATION]))]
|
||||
log_debug_calls = [call('(111.111.111.111) Processing command "PJLINK" with data "ERRA"')]
|
||||
|
||||
# WHEN: process_command called with ERRA
|
||||
pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_AUTHENTICATION])
|
||||
with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
|
||||
patch.object(openlp.core.projectors.pjlink.PJLink, 'process_pjlink') as mock_process_pjlink, \
|
||||
patch.object(openlp.core.projectors.pjlink.PJLink, 'change_status') as mock_change_status, \
|
||||
patch.object(openlp.core.projectors.pjlink.PJLink, 'disconnect_from_host') as mock_disconnect, \
|
||||
patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorAuthentication') as mock_authentication:
|
||||
|
||||
# THEN: Error should be logged and several methods should be called
|
||||
self.assertTrue(mock_disconnect.called, 'disconnect_from_host should have been called')
|
||||
mock_change_status.assert_called_once_with(E_AUTHENTICATION)
|
||||
mock_log.error.assert_called_with(log_text)
|
||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
||||
|
||||
# WHEN: process_command called with ERRA
|
||||
pjlink.process_command(cmd='PJLINK', data=PJLINK_ERRORS[E_AUTHENTICATION])
|
||||
|
||||
# THEN: Appropriate log entries should have been made and methods called/not called
|
||||
mock_log.error.assert_has_calls(log_error_calls)
|
||||
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||
self.assertTrue(mock_disconnect.called, 'disconnect_from_host should have been called')
|
||||
mock_change_status.assert_called_once_with(status=E_AUTHENTICATION)
|
||||
mock_authentication.emit.assert_called_once_with(pjlink.name)
|
||||
mock_process_pjlink.assert_not_called()
|
||||
|
||||
def test_process_command_err1(self):
|
||||
"""
|
||||
Test ERR1 - Undefined projector function
|
||||
"""
|
||||
# GIVEN: Test object
|
||||
log_error_text = [call('(111.111.111.111) CLSS: {msg}'.format(msg=STATUS_MSG[E_UNDEFINED]))]
|
||||
log_debug_text = [call('(111.111.111.111) Processing command "CLSS" with data "ERR1"'),
|
||||
call('(111.111.111.111) Calling function for CLSS')]
|
||||
|
||||
with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
|
||||
patch.object(openlp.core.projectors.pjlink.PJLink, 'process_clss') as mock_process_clss:
|
||||
|
||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
||||
|
||||
# WHEN: process_command called with ERR1
|
||||
pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_UNDEFINED])
|
||||
|
||||
# THEN: Appropriate log entries should have been made and methods called
|
||||
mock_log.error.assert_has_calls(log_error_text)
|
||||
mock_log.debug.assert_has_calls(log_debug_text)
|
||||
mock_process_clss.assert_called_once_with(data=PJLINK_ERRORS[E_UNDEFINED])
|
||||
|
||||
def test_process_command_err2(self):
|
||||
"""
|
||||
Test ERR2 - Parameter Error
|
||||
"""
|
||||
# GIVEN: Test object
|
||||
log_error_text = [call('(111.111.111.111) CLSS: {msg}'.format(msg=STATUS_MSG[E_PARAMETER]))]
|
||||
log_debug_text = [call('(111.111.111.111) Processing command "CLSS" with data "ERR2"'),
|
||||
call('(111.111.111.111) Calling function for CLSS')]
|
||||
|
||||
with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
|
||||
patch.object(openlp.core.projectors.pjlink.PJLink, 'process_clss') as mock_process_clss:
|
||||
|
||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
||||
|
||||
# WHEN: process_command called with ERR2
|
||||
pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_PARAMETER])
|
||||
|
||||
# THEN: Appropriate log entries should have been made and methods called/not called
|
||||
mock_log.error.assert_has_calls(log_error_text)
|
||||
mock_log.debug.assert_has_calls(log_debug_text)
|
||||
mock_process_clss.assert_called_once_with(data=PJLINK_ERRORS[E_PARAMETER])
|
||||
|
||||
def test_process_command_err3(self):
|
||||
"""
|
||||
Test ERR3 - Unavailable error
|
||||
"""
|
||||
# GIVEN: Test object
|
||||
log_error_text = [call('(111.111.111.111) CLSS: {msg}'.format(msg=STATUS_MSG[E_UNAVAILABLE]))]
|
||||
log_debug_text = [call('(111.111.111.111) Processing command "CLSS" with data "ERR3"'),
|
||||
call('(111.111.111.111) Calling function for CLSS')]
|
||||
|
||||
with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
|
||||
patch.object(openlp.core.projectors.pjlink.PJLink, 'process_clss') as mock_process_clss:
|
||||
|
||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
||||
|
||||
# WHEN: process_command called with ERR3
|
||||
pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_UNAVAILABLE])
|
||||
|
||||
# THEN: Appropriate log entries should have been made and methods called
|
||||
mock_log.error.assert_has_calls(log_error_text)
|
||||
mock_log.debug.assert_has_calls(log_debug_text)
|
||||
mock_process_clss.assert_called_once_with(data=PJLINK_ERRORS[E_UNAVAILABLE])
|
||||
|
||||
def test_process_command_err4(self):
|
||||
"""
|
||||
Test ERR3 - Unavailable error
|
||||
"""
|
||||
# GIVEN: Test object
|
||||
log_error_text = [call('(111.111.111.111) CLSS: {msg}'.format(msg=STATUS_MSG[E_PROJECTOR]))]
|
||||
log_debug_text = [call('(111.111.111.111) Processing command "CLSS" with data "ERR4"'),
|
||||
call('(111.111.111.111) Calling function for CLSS')]
|
||||
|
||||
with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
|
||||
patch.object(openlp.core.projectors.pjlink.PJLink, 'process_clss') as mock_process_clss:
|
||||
|
||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
||||
|
||||
# WHEN: process_command called with ERR4
|
||||
pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_PROJECTOR])
|
||||
|
||||
# THEN: Appropriate log entries should have been made and methods called
|
||||
mock_log.error.assert_has_calls(log_error_text)
|
||||
mock_log.debug.assert_has_calls(log_debug_text)
|
||||
mock_process_clss.assert_called_once_with(data=PJLINK_ERRORS[E_PROJECTOR])
|
||||
|
||||
def test_process_command_future(self):
|
||||
"""
|
||||
Test command valid but no method to process yet
|
||||
"""
|
||||
# GIVEN: Initial mocks and data
|
||||
mock_log = patch.object(openlp.core.projectors.pjlink, 'log').start()
|
||||
mock_functions = patch.object(self.pjlink_test, 'pjlink_functions').start()
|
||||
mock_functions.return_value = []
|
||||
|
||||
pjlink = self.pjlink_test
|
||||
log_text = '(111.111.111.111) Unable to process command="CLSS" (Future option?)'
|
||||
|
||||
# WHEN: process_command called with an unknown command
|
||||
pjlink.process_command(cmd='CLSS', data='DONT CARE')
|
||||
|
||||
# THEN: Error should be logged and no command called
|
||||
self.assertFalse(mock_functions.called, 'Should not have gotten to the end of the method')
|
||||
mock_log.warning.assert_called_once_with(log_text)
|
||||
|
||||
@patch.object(pjlink_test, 'pjlink_functions')
|
||||
@patch.object(openlp.core.projectors.pjlink, 'log')
|
||||
def test_process_command_invalid(self, mock_log, mock_functions):
|
||||
"""
|
||||
Test not a valid command
|
||||
"""
|
||||
# GIVEN: Test object
|
||||
pjlink = pjlink_test
|
||||
mock_functions.reset_mock()
|
||||
mock_log.reset_mock()
|
||||
log_warning_text = [call('(111.111.111.111) Unable to process command="CLSS" (Future option?)')]
|
||||
log_debug_text = [call('(111.111.111.111) Processing command "CLSS" with data "Huh?"')]
|
||||
|
||||
# WHEN: process_command called with an unknown command
|
||||
pjlink.process_command(cmd='Unknown', data='Dont Care')
|
||||
log_text = '(127.0.0.1) Ignoring command="Unknown" (Invalid/Unknown)'
|
||||
with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
|
||||
patch.object(openlp.core.projectors.pjlink.PJLink, 'process_clss') as mock_process_clss:
|
||||
|
||||
# THEN: Error should be logged and no command called
|
||||
self.assertFalse(mock_functions.called, 'Should not have gotten to the end of the method')
|
||||
mock_log.error.assert_called_once_with(log_text)
|
||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
||||
pjlink.pjlink_functions = MagicMock()
|
||||
|
||||
# WHEN: Processing a possible future command
|
||||
pjlink.process_command(cmd='CLSS', data="Huh?")
|
||||
|
||||
# THEN: Appropriate log entries should have been made and methods called/not called
|
||||
mock_log.debug.assert_has_calls(log_debug_text)
|
||||
mock_log.warning.assert_has_calls(log_warning_text)
|
||||
self.assertFalse(pjlink.pjlink_functions.called, 'Should not have accessed pjlink_functions')
|
||||
self.assertFalse(mock_process_clss.called, 'Should not have called process_clss')
|
||||
|
||||
def test_process_command_ok(self):
|
||||
"""
|
||||
Test command returned success
|
||||
"""
|
||||
# GIVEN: Initial mocks and data
|
||||
mock_log = patch.object(openlp.core.projectors.pjlink, 'log').start()
|
||||
mock_send_command = patch.object(self.pjlink_test, 'send_command').start()
|
||||
# GIVEN: Test object and mocks
|
||||
log_debug_calls = [call('(111.111.111.111) Processing command "CLSS" with data "OK"'),
|
||||
call('(111.111.111.111) Command "CLSS" returned OK')]
|
||||
|
||||
pjlink = self.pjlink_test
|
||||
log_text = '(111.111.111.111) Command "POWR" returned OK'
|
||||
with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
|
||||
patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command, \
|
||||
patch.object(openlp.core.projectors.pjlink.PJLink, 'process_clss') as mock_process_clss:
|
||||
|
||||
# WHEN: process_command called with a command that returns OK
|
||||
pjlink.process_command(cmd='POWR', data='OK')
|
||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
||||
|
||||
# THEN: Appropriate calls should have been made
|
||||
mock_log.debug.assert_called_with(log_text)
|
||||
mock_send_command.assert_called_once_with(cmd='POWR')
|
||||
# WHEN: process_command is called with valid function and data
|
||||
pjlink.process_command(cmd='CLSS', data='OK')
|
||||
|
||||
# THEN: Appropriate log entries should have been made and methods called
|
||||
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||
mock_send_command.assert_called_once_with(cmd='CLSS')
|
||||
mock_process_clss.assert_not_called()
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user