Merge lp:~alisonken1/openlp/pjlink2-r into lp:openlp
- pjlink2-r
- Merge into trunk
Status: | Superseded |
---|---|
Proposed branch: | lp:~alisonken1/openlp/pjlink2-r |
Merge into: | lp:openlp |
Diff against target: |
840 lines (+254/-128) 8 files modified
openlp/core/common/settings.py (+1/-0) openlp/core/projectors/manager.py (+25/-2) openlp/core/projectors/pjlink.py (+88/-82) openlp/core/projectors/tab.py (+8/-0) tests/openlp_core/projectors/test_projector_pjlink_base_01.py (+2/-12) tests/openlp_core/projectors/test_projector_pjlink_base_02.py (+101/-0) tests/openlp_core/projectors/test_projector_pjlink_cmd_routing.py (+14/-4) tests/openlp_core/projectors/test_projector_pjlink_udp.py (+15/-28) |
To merge this branch: | bzr merge lp:~alisonken1/openlp/pjlink2-r |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Phill | Needs Fixing | ||
Tim Bentley | Needs Fixing | ||
Review via email: mp+344795@code.launchpad.net |
This proposal has been superseded by a proposal from 2018-04-28.
Commit message
PJLink2 update R
Description of the change
-------
lp:~alisonken1/openlp/pjlink2-r (revision 2819)
https:/
https:/
https:/
https:/
https:/
https:/
https:/
https:/
-------
- Convert UDP packet to send pyqtSignal and let individual projectors decide who it's for
- Remove unneccessary *args **kwargs from commands
- Remove projector_list and projector block search since switching to signals
- pass on ACKN, and SRCH commands until I think about it some more
- Cleanup extraneous args on process_* commands since switching to signals
- Add UDP socket listener(s) for PJLink2 UDP options
- Added process_lkup method code
- Add projector configure option to connect when LKUP packet received
- Fix _send_queue to ignore call if no data to send
- Rename tests/openlp_
- Added tests/openlp_
- Added test for PJLink.
- Removed unused test_projector_
- Cleanup tests/openlp_
- Fix test_projector_
Phill (phill-ridout) wrote : | # |
Ran out of time to complete a review, but a few in lines to start.
Ken Roberts (alisonken1) wrote : | # |
On Sat, Apr 28, 2018 at 12:15 AM, Phill <email address hidden> wrote:
> Review: Needs Fixing
>
> Ran out of time to complete a review, but a few in lines to start.
>
> Diff comments:
>
>>
>> === modified file 'openlp/
>> --- openlp/
>> +++ openlp/
>> if read_size < 0:
>> log.warning('(UDP) No data (-1)')
>> return
>> - if read_size < 1:
>> + elif read_size < 1:
>
> given the < 0 condition above, this condition will only be True when read_size == 0, which to me is a bit readable / obvious at a quick glance.
-1 indicates a socket problem - which is distinct from no data (0 or
empty packet)
>> @@ -654,10 +651,10 @@
>> :param host: IP address of sending host
>> :param port: Port received on
>> """
>> - log.warning('(UDP) SRCH packet received from {host} - ignoring'
>> + log.warning("({ip}) I don't do SRCH packets - ignoring"
>
> Why this change? the original is more understandable to me!
This method is only called from within a projector instance - not the
UDP monitor.
However, just noticed it's using the wrong option for {ip} - should be
ip=self.entry.name
>
>> return
>>
>> - def process_sver(self, data, *args, **kwargs):
>> + def process_sver(self, data):
>> """
>> Software version of projector
>> """
>> @@ -1181,7 +1187,7 @@
>> try:
>> self.readyRead.
>> except TypeError:
>> - pass
>> + log.debug('({ip}) disconnect_
>
> You're just disconnecting a slot here right? Do we need to log that?
Since this is in the projector instance, I would like to know if
there's a type issue - if so, then I would like to see it in the log.
>
>> log.debug('({ip}) disconnect_
>> 'Current status {data}'
>> if abort:
>
>
> --
> https:/
> You are the owner of lp:~alisonken1/openlp/pjlink2-r.
--
- Ken
Registered Linux user 296561
Slackin' since 1993
Slackware Linux (http://
OpenLP - Church Projection Software
Empower Your Church http://
On Sat, Apr 28, 2018 at 12:15 AM, Phill <email address hidden> wrote:
> Review: Needs Fixing
>
> Ran out of time to complete a review, but a few in lines to start.
>
> Diff comments:
>
>>
>> === modified file 'openlp/
>> --- openlp/
>> +++ openlp/
>> @@ -513,6 +519,18 @@
>> projector.
>> except (AttributeError, TypeError):
>> pass
>> + # Disconnect signals from projector being deleted
>> + try:
>> + self.pjlink_
Phill (phill-ridout) wrote : | # |
See inlines please.
Phill (phill-ridout) : | # |
- 2819. By Ken Roberts
-
PJLink2 update R
- 2820. By Ken Roberts
-
Fix settings calls
Unmerged revisions
Preview Diff
1 | === modified file 'openlp/core/common/settings.py' |
2 | --- openlp/core/common/settings.py 2018-02-02 21:33:41 +0000 |
3 | +++ openlp/core/common/settings.py 2018-04-28 07:12:35 +0000 |
4 | @@ -199,6 +199,7 @@ |
5 | 'projector/db database': '', |
6 | 'projector/enable': True, |
7 | 'projector/connect on start': False, |
8 | + 'projector/connect when LKUP received': True, # PJLink v2: Projector sends LKUP command after it powers up |
9 | 'projector/last directory import': None, |
10 | 'projector/last directory export': None, |
11 | 'projector/poll time': 20, # PJLink timeout is 30 seconds |
12 | |
13 | === modified file 'openlp/core/projectors/manager.py' |
14 | --- openlp/core/projectors/manager.py 2018-04-20 06:04:43 +0000 |
15 | +++ openlp/core/projectors/manager.py 2018-04-28 07:12:35 +0000 |
16 | @@ -37,7 +37,7 @@ |
17 | from openlp.core.projectors import DialogSourceStyle |
18 | from openlp.core.projectors.constants import E_AUTHENTICATION, E_ERROR, E_NETWORK, E_NOT_CONNECTED, \ |
19 | E_UNKNOWN_SOCKET_ERROR, S_CONNECTED, S_CONNECTING, S_COOLDOWN, S_INITIALIZE, S_NOT_CONNECTED, S_OFF, S_ON, \ |
20 | - S_STANDBY, S_WARMUP, STATUS_CODE, STATUS_MSG, QSOCKET_STATE |
21 | + S_STANDBY, S_WARMUP, PJLINK_PORT, STATUS_CODE, STATUS_MSG, QSOCKET_STATE |
22 | |
23 | from openlp.core.projectors.db import ProjectorDB |
24 | from openlp.core.projectors.editform import ProjectorEditForm |
25 | @@ -294,6 +294,9 @@ |
26 | self.projectordb = projectordb |
27 | self.projector_list = [] |
28 | self.source_select_form = None |
29 | + # Dictionary of PJLinkUDP objects to listen for UDP broadcasts from PJLink 2+ projectors. |
30 | + # Key is port number that projectors use |
31 | + self.pjlink_udp = {} |
32 | |
33 | def bootstrap_initialise(self): |
34 | """ |
35 | @@ -307,12 +310,15 @@ |
36 | else: |
37 | log.debug('Using existing ProjectorDB() instance') |
38 | self.get_settings() |
39 | - self.pjlink_udp = PJLinkUDP(self.projector_list) |
40 | |
41 | def bootstrap_post_set_up(self): |
42 | """ |
43 | Post-initialize setups. |
44 | """ |
45 | + # Default PJLink port UDP socket |
46 | + log.debug('Creating PJLinkUDP listener for default port {port}'.format(port=PJLINK_PORT)) |
47 | + self.pjlink_udp = {PJLINK_PORT: PJLinkUDP(port=PJLINK_PORT)} |
48 | + self.pjlink_udp[PJLINK_PORT].bind(PJLINK_PORT) |
49 | # Set 1.5 second delay before loading all projectors |
50 | if self.autostart: |
51 | log.debug('Delaying 1.5 seconds before loading all projectors') |
52 | @@ -513,6 +519,14 @@ |
53 | projector.socket_timer.timeout.disconnect(projector.link.socket_abort) |
54 | except (AttributeError, TypeError): |
55 | pass |
56 | + # Disconnect signals from projector being deleted |
57 | + if self.pjlink_udp[projector.port]: |
58 | + try: |
59 | + self.pjlink_udp[projector.port].data_received.disconnect(projector.get_buffer) |
60 | + except (AttributeError, TypeError): |
61 | + pass |
62 | + |
63 | + # Rebuild projector list |
64 | new_list = [] |
65 | for item in self.projector_list: |
66 | if item.link.db_item.id == projector.link.db_item.id: |
67 | @@ -726,6 +740,15 @@ |
68 | item.link.projectorAuthentication.connect(self.authentication_error) |
69 | item.link.projectorNoAuthentication.connect(self.no_authentication_error) |
70 | item.link.projectorUpdateIcons.connect(self.update_icons) |
71 | + # Connect UDP signal to projector instances with same port |
72 | + if item.link.port not in self.pjlink_udp: |
73 | + log.debug('Adding new PJLinkUDP listener fo port {port}'.format(port=item.link.port)) |
74 | + self.pjlink_udp[item.link.port] = PJLinkUDP(port=item.link.port) |
75 | + self.pjlink_udp[item.link.port].bind(item.link.port) |
76 | + log.debug('Connecting PJLinkUDP port {port} signal to "{item}"'.format(port=item.link.port, |
77 | + item=item.link.name)) |
78 | + self.pjlink_udp[item.link.port].data_received.connect(item.link.get_buffer) |
79 | + |
80 | self.projector_list.append(item) |
81 | if start: |
82 | item.link.connect_to_host() |
83 | |
84 | === modified file 'openlp/core/projectors/pjlink.py' |
85 | --- openlp/core/projectors/pjlink.py 2018-04-20 06:04:43 +0000 |
86 | +++ openlp/core/projectors/pjlink.py 2018-04-28 07:12:35 +0000 |
87 | @@ -54,6 +54,7 @@ |
88 | |
89 | from openlp.core.common import qmd5_hash |
90 | from openlp.core.common.i18n import translate |
91 | +from openlp.core.common.settings import Settings |
92 | from openlp.core.projectors.constants import CONNECTION_ERRORS, PJLINK_CLASS, PJLINK_DEFAULT_CODES, PJLINK_ERRORS, \ |
93 | PJLINK_ERST_DATA, PJLINK_ERST_STATUS, PJLINK_MAX_PACKET, PJLINK_PREFIX, PJLINK_PORT, PJLINK_POWR_STATUS, \ |
94 | PJLINK_SUFFIX, PJLINK_VALID_CMD, PROJECTOR_STATE, STATUS_CODE, STATUS_MSG, QSOCKET_STATE, \ |
95 | @@ -78,25 +79,27 @@ |
96 | """ |
97 | Socket service for PJLink UDP socket. |
98 | """ |
99 | - def __init__(self, projector_list, port=PJLINK_PORT): |
100 | + |
101 | + data_received = QtCore.pyqtSignal(QtNetwork.QHostAddress, int, str, name='udp_data') # host, port, data |
102 | + |
103 | + def __init__(self, port=PJLINK_PORT): |
104 | """ |
105 | Socket services for PJLink UDP packets. |
106 | |
107 | Since all UDP packets from any projector will come into the same |
108 | port, process UDP packets here then route to the appropriate |
109 | projector instance as needed. |
110 | + |
111 | + :param port: UDP port to listen on |
112 | """ |
113 | - # Keep track of currently defined projectors so we can route |
114 | - # inbound packets to the correct instance |
115 | super().__init__() |
116 | - self.projector_list = projector_list |
117 | self.port = port |
118 | # Local defines |
119 | self.search_active = False |
120 | self.search_time = 30000 # 30 seconds for allowed time |
121 | self.search_timer = QtCore.QTimer() |
122 | self.readyRead.connect(self.get_datagram) |
123 | - log.debug('(UDP) PJLinkUDP() Initialized') |
124 | + log.debug('(UDP) PJLinkUDP() Initialized for port {port}'.format(port=self.port)) |
125 | |
126 | @QtCore.pyqtSlot() |
127 | def get_datagram(self): |
128 | @@ -108,22 +111,20 @@ |
129 | if read_size < 0: |
130 | log.warning('(UDP) No data (-1)') |
131 | return |
132 | - if read_size < 1: |
133 | + elif read_size < 1: |
134 | log.warning('(UDP) get_datagram() called when pending data size is 0') |
135 | return |
136 | - data, peer_address, peer_port = self.readDatagram(self.pendingDatagramSize()) |
137 | + elif read_size > PJLINK_MAX_PACKET: |
138 | + log.warning('(UDP) UDP Packet too large ({size} bytes)- ignoring'.format(size=read_size)) |
139 | + return |
140 | + data_in, peer_host, peer_port = self.readDatagram(read_size) |
141 | + data = data_in.decode('utf-8') if isinstance(data_in, bytes) else data_in |
142 | log.debug('(UDP) {size} bytes received from {adx} on port {port}'.format(size=len(data), |
143 | - adx=peer_address, |
144 | - port=peer_port)) |
145 | + adx=peer_host.toString(), |
146 | + port=self.port)) |
147 | log.debug('(UDP) packet "{data}"'.format(data=data)) |
148 | - # Send to appropriate instance to process packet |
149 | - log.debug('(UDP) Checking projector list for ip {host} to process'.format(host=peer_address)) |
150 | - for projector in self.projector_list: |
151 | - if peer_address == projector.ip: |
152 | - # Dispatch packet to appropriate remote instance |
153 | - log.debug('(UDP) Dispatching packet to {host}'.format(host=projector.entry.name)) |
154 | - return projector.get_data(buff=data, ip=peer_address, host=peer_address, port=peer_port) |
155 | - log.warning('(UDP) Could not find projector with ip {ip} to process packet'.format(ip=peer_address)) |
156 | + log.debug('(UDP) Sending data_received signal to projectors') |
157 | + self.data_received.emit(peer_host, self.localPort(), data) |
158 | return |
159 | |
160 | def search_start(self): |
161 | @@ -131,7 +132,6 @@ |
162 | Start search for projectors on local network |
163 | """ |
164 | self.search_active = True |
165 | - self.ackn_list = {} |
166 | # TODO: Send SRCH packet here |
167 | self.search_timer.singleShot(self.search_time, self.search_stop) |
168 | |
169 | @@ -240,7 +240,7 @@ |
170 | for cmd in self.pjlink_functions: |
171 | self.pjlink_functions[cmd]["version"] = PJLINK_VALID_CMD[cmd]['default'] |
172 | |
173 | - def process_command(self, cmd, data, *args, **kwargs): |
174 | + def process_command(self, cmd, data): |
175 | """ |
176 | Verifies any return error code. Calls the appropriate command handler. |
177 | |
178 | @@ -272,25 +272,18 @@ |
179 | return self.change_status(status=E_AUTHENTICATION) |
180 | # Command checks already passed |
181 | log.debug('({ip}) Calling function for {cmd}'.format(ip=self.entry.name, cmd=cmd)) |
182 | - self.pjlink_functions[cmd]["method"](data=data, *args, **kwargs) |
183 | + self.pjlink_functions[cmd]["method"](data=data) |
184 | |
185 | - def process_ackn(self, data, host, port): |
186 | + def process_ackn(self, data): |
187 | """ |
188 | Process the ACKN command. |
189 | |
190 | :param data: Data in packet |
191 | - :param host: IP address of sending host |
192 | - :param port: Port received on |
193 | """ |
194 | - log.debug('({ip}) Processing ACKN packet'.format(ip=self.entry.name)) |
195 | - if host not in self.ackn_list: |
196 | - log.debug('({ip}) Adding {host} to ACKN list'.format(ip=self.entry.name, host=host)) |
197 | - self.ackn_list[host] = {'data': data, |
198 | - 'port': port} |
199 | - else: |
200 | - log.warning('({ip}) Host {host} already replied - ignoring'.format(ip=self.entry.name, host=host)) |
201 | + # TODO: Have to rethink this one |
202 | + pass |
203 | |
204 | - def process_avmt(self, data, *args, **kwargs): |
205 | + def process_avmt(self, data): |
206 | """ |
207 | Process shutter and speaker status. See PJLink specification for format. |
208 | Update self.mute (audio) and self.shutter (video shutter). |
209 | @@ -319,7 +312,7 @@ |
210 | self.projectorUpdateIcons.emit() |
211 | return |
212 | |
213 | - def process_clss(self, data, *args, **kwargs): |
214 | + def process_clss(self, data): |
215 | """ |
216 | PJLink class that this projector supports. See PJLink specification for format. |
217 | Updates self.class. |
218 | @@ -365,7 +358,7 @@ |
219 | |
220 | return |
221 | |
222 | - def process_erst(self, data, *args, **kwargs): |
223 | + def process_erst(self, data): |
224 | """ |
225 | Error status. See PJLink Specifications for format. |
226 | Updates self.projector_errors |
227 | @@ -417,7 +410,7 @@ |
228 | PJLINK_ERST_STATUS[other] |
229 | return |
230 | |
231 | - def process_inf1(self, data, *args, **kwargs): |
232 | + def process_inf1(self, data): |
233 | """ |
234 | Manufacturer name set in projector. |
235 | Updates self.manufacturer |
236 | @@ -429,7 +422,7 @@ |
237 | data=self.manufacturer)) |
238 | return |
239 | |
240 | - def process_inf2(self, data, *args, **kwargs): |
241 | + def process_inf2(self, data): |
242 | """ |
243 | Projector Model set in projector. |
244 | Updates self.model. |
245 | @@ -440,7 +433,7 @@ |
246 | log.debug('({ip}) Setting projector model to "{data}"'.format(ip=self.entry.name, data=self.model)) |
247 | return |
248 | |
249 | - def process_info(self, data, *args, **kwargs): |
250 | + def process_info(self, data): |
251 | """ |
252 | Any extra info set in projector. |
253 | Updates self.other_info. |
254 | @@ -451,7 +444,7 @@ |
255 | log.debug('({ip}) Setting projector other_info to "{data}"'.format(ip=self.entry.name, data=self.other_info)) |
256 | return |
257 | |
258 | - def process_inpt(self, data, *args, **kwargs): |
259 | + def process_inpt(self, data): |
260 | """ |
261 | Current source input selected. See PJLink specification for format. |
262 | Update self.source |
263 | @@ -473,7 +466,7 @@ |
264 | log.debug('({ip}) Setting data source to "{data}"'.format(ip=self.entry.name, data=self.source)) |
265 | return |
266 | |
267 | - def process_inst(self, data, *args, **kwargs): |
268 | + def process_inst(self, data): |
269 | """ |
270 | Available source inputs. See PJLink specification for format. |
271 | Updates self.source_available |
272 | @@ -490,7 +483,7 @@ |
273 | data=self.source_available)) |
274 | return |
275 | |
276 | - def process_lamp(self, data, *args, **kwargs): |
277 | + def process_lamp(self, data): |
278 | """ |
279 | Lamp(s) status. See PJLink Specifications for format. |
280 | Data may have more than 1 lamp to process. |
281 | @@ -516,18 +509,22 @@ |
282 | self.lamp = lamps |
283 | return |
284 | |
285 | - def process_lkup(self, data, host, port): |
286 | + def process_lkup(self, data): |
287 | """ |
288 | Process reply indicating remote is available for connection |
289 | |
290 | :param data: Data packet from remote |
291 | - :param host: Remote IP address |
292 | - :param port: Local port packet received on |
293 | """ |
294 | - # TODO: Check if autoconnect is enabled and connect? |
295 | - pass |
296 | + log.debug('({ip}) Processing LKUP command'.format(ip=self.entry.name)) |
297 | + settings = Settings() |
298 | + settings.beginGroup(self.settings_section) |
299 | + autostart = settings.value('connect when LKUP received') |
300 | + settings.endGroup() |
301 | + del settings |
302 | + if autostart: |
303 | + self.connect_to_host() |
304 | |
305 | - def process_name(self, data, *args, **kwargs): |
306 | + def process_name(self, data): |
307 | """ |
308 | Projector name set in projector. |
309 | Updates self.pjlink_name |
310 | @@ -538,7 +535,7 @@ |
311 | log.debug('({ip}) Setting projector PJLink name to "{data}"'.format(ip=self.entry.name, data=self.pjlink_name)) |
312 | return |
313 | |
314 | - def process_pjlink(self, data, *args, **kwargs): |
315 | + def process_pjlink(self, data): |
316 | """ |
317 | Process initial socket connection to terminal. |
318 | |
319 | @@ -579,7 +576,7 @@ |
320 | # Since this is an initial connection, make it a priority just in case |
321 | return self.send_command(cmd="CLSS", salt=data_hash, priority=True) |
322 | |
323 | - def process_powr(self, data, *args, **kwargs): |
324 | + def process_powr(self, data): |
325 | """ |
326 | Power status. See PJLink specification for format. |
327 | Update self.power with status. Update icons if change from previous setting. |
328 | @@ -602,7 +599,7 @@ |
329 | log.warning('({ip}) Unknown power response: "{data}"'.format(ip=self.entry.name, data=data)) |
330 | return |
331 | |
332 | - def process_rfil(self, data, *args, **kwargs): |
333 | + def process_rfil(self, data): |
334 | """ |
335 | Process replacement filter type |
336 | """ |
337 | @@ -613,7 +610,7 @@ |
338 | log.warning('({ip}) Saved model: "{old}"'.format(ip=self.entry.name, old=self.model_filter)) |
339 | log.warning('({ip}) New model: "{new}"'.format(ip=self.entry.name, new=data)) |
340 | |
341 | - def process_rlmp(self, data, *args, **kwargs): |
342 | + def process_rlmp(self, data): |
343 | """ |
344 | Process replacement lamp type |
345 | """ |
346 | @@ -624,7 +621,7 @@ |
347 | log.warning('({ip}) Saved lamp: "{old}"'.format(ip=self.entry.name, old=self.model_lamp)) |
348 | log.warning('({ip}) New lamp: "{new}"'.format(ip=self.entry.name, new=data)) |
349 | |
350 | - def process_snum(self, data, *args, **kwargs): |
351 | + def process_snum(self, data): |
352 | """ |
353 | Serial number of projector. |
354 | |
355 | @@ -644,7 +641,7 @@ |
356 | log.warning('({ip}) NOT saving serial number'.format(ip=self.entry.name)) |
357 | self.serial_no_received = data |
358 | |
359 | - def process_srch(self, data, host, port): |
360 | + def process_srch(self, data): |
361 | """ |
362 | Process the SRCH command. |
363 | |
364 | @@ -654,10 +651,10 @@ |
365 | :param host: IP address of sending host |
366 | :param port: Port received on |
367 | """ |
368 | - log.warning('(UDP) SRCH packet received from {host} - ignoring'.format(host=host)) |
369 | + log.warning("({ip}) I don't do SRCH packets - ignoring".format(ip=self.ip)) |
370 | return |
371 | |
372 | - def process_sver(self, data, *args, **kwargs): |
373 | + def process_sver(self, data): |
374 | """ |
375 | Software version of projector |
376 | """ |
377 | @@ -705,14 +702,16 @@ |
378 | args=args, |
379 | kwargs=kwargs)) |
380 | super().__init__() |
381 | + self.settings_section = 'projector' |
382 | self.entry = projector |
383 | self.ip = self.entry.ip |
384 | + self.qhost = QtNetwork.QHostAddress(self.ip) |
385 | self.location = self.entry.location |
386 | self.mac_adx = self.entry.mac_adx |
387 | self.name = self.entry.name |
388 | self.notes = self.entry.notes |
389 | self.pin = self.entry.pin |
390 | - self.port = self.entry.port |
391 | + self.port = int(self.entry.port) |
392 | self.pjlink_class = PJLINK_CLASS if self.entry.pjlink_class is None else self.entry.pjlink_class |
393 | self.ackn_list = {} # Replies from online projectors (Class 2 option) |
394 | self.db_update = False # Use to check if db needs to be updated prior to exiting |
395 | @@ -928,19 +927,21 @@ |
396 | count=trash_count)) |
397 | return |
398 | |
399 | - @QtCore.pyqtSlot(str, str) |
400 | - def get_buffer(self, data, ip): |
401 | + @QtCore.pyqtSlot(QtNetwork.QHostAddress, int, str, name='udp_data') # host, port, data |
402 | + def get_buffer(self, host, port, data): |
403 | """ |
404 | Get data from somewhere other than TCP socket |
405 | |
406 | + :param host: QHostAddress of sender |
407 | + :param port: Destination port |
408 | :param data: Data to process. buffer must be formatted as a proper PJLink packet. |
409 | - :param ip: Destination IP for buffer. |
410 | """ |
411 | - log.debug('({ip}) get_buffer(data="{buff}" ip="{ip_in}"'.format(ip=self.entry.name, buff=data, ip_in=ip)) |
412 | - if ip is None: |
413 | - log.debug("({ip}) get_buffer() Don't know who data is for - exiting".format(ip=self.entry.name)) |
414 | - return |
415 | - return self.get_data(buff=data, ip=ip) |
416 | + if (port == int(self.port)) and (host.isEqual(self.qhost)): |
417 | + log.debug('({ip}) Received data from {host}'.format(ip=self.entry.name, host=host.toString())) |
418 | + log.debug('({ip}) get_buffer(data="{buff}")'.format(ip=self.entry.name, buff=data)) |
419 | + return self.get_data(buff=data) |
420 | + else: |
421 | + log.debug('({ip}) Ignoring data for {host} - not me'.format(ip=self.entry.name, host=host.toString())) |
422 | |
423 | @QtCore.pyqtSlot() |
424 | def get_socket(self): |
425 | @@ -960,20 +961,16 @@ |
426 | log.debug('({ip}) get_socket(): No data available (-1)'.format(ip=self.entry.name)) |
427 | return self.receive_data_signal() |
428 | self.socket_timer.stop() |
429 | - return self.get_data(buff=read, ip=self.ip) |
430 | + return self.get_data(buff=read) |
431 | |
432 | - def get_data(self, buff, ip=None, *args, **kwargs): |
433 | + def get_data(self, buff, *args, **kwargs): |
434 | """ |
435 | Process received data |
436 | |
437 | :param buff: Data to process. |
438 | - :param ip: (optional) Destination IP. |
439 | """ |
440 | - # Since "self" is not available to options and the "ip" keyword is a "maybe I'll use in the future", |
441 | - # set to default here |
442 | - if ip is None: |
443 | - ip = self.ip |
444 | - log.debug('({ip}) get_data(ip="{ip_in}" buffer="{buff}"'.format(ip=self.entry.name, ip_in=ip, buff=buff)) |
445 | + log.debug('({ip}) get_data(buffer="{buff}"'.format(ip=self.entry.name, buff=buff)) |
446 | + ignore_class = 'ignore_class' in kwargs |
447 | # NOTE: Class2 has changed to some values being UTF-8 |
448 | if isinstance(buff, bytes): |
449 | data_in = decode(buff, 'utf-8') |
450 | @@ -990,7 +987,9 @@ |
451 | elif not data.startswith(PJLINK_PREFIX): |
452 | self._trash_buffer(msg='get_data(): Invalid packet - PJLink prefix missing') |
453 | return self.receive_data_signal() |
454 | - elif data[6] != '=': |
455 | + elif data[6] != '=' and data[8] != '=': |
456 | + # data[6] = standard command packet |
457 | + # data[8] = initial PJLink connection (after mangling) |
458 | self._trash_buffer(msg='get_data(): Invalid reply - Does not have "="') |
459 | return self.receive_data_signal() |
460 | log.debug('({ip}) get_data(): Checking new data "{data}"'.format(ip=self.entry.name, data=data)) |
461 | @@ -1020,16 +1019,16 @@ |
462 | return self.receive_data_signal() |
463 | ''' |
464 | if cmd not in PJLINK_VALID_CMD: |
465 | - self._trash_buffer('get_data(): Invalid packet - unknown command "{data}"'.format(ip=self.entry.name, |
466 | - data=cmd)) |
467 | + self._trash_buffer('get_data(): Invalid packet - unknown command "{data}"'.format(data=cmd)) |
468 | return self.receive_data_signal() |
469 | elif version not in PJLINK_VALID_CMD[cmd]['version']: |
470 | self._trash_buffer(msg='get_data() Command reply version does not match a valid command version') |
471 | return self.receive_data_signal() |
472 | elif int(self.pjlink_class) < int(version): |
473 | - log.warning('({ip}) get_data(): Projector returned class reply higher ' |
474 | - 'than projector stated class'.format(ip=self.entry.name)) |
475 | - self.process_command(cmd, data, *args, **kwargs) |
476 | + if not ignore_class: |
477 | + log.warning('({ip}) get_data(): Projector returned class reply higher ' |
478 | + 'than projector stated class'.format(ip=self.entry.name)) |
479 | + self.process_command(cmd, data) |
480 | return self.receive_data_signal() |
481 | |
482 | @QtCore.pyqtSlot(QtNetwork.QAbstractSocket.SocketError) |
483 | @@ -1107,11 +1106,18 @@ |
484 | """ |
485 | Socket interface to send data. If data=None, then check queue. |
486 | |
487 | - :param data: Immediate data to send |
488 | + :param data: Immediate data to send (Optional) |
489 | :param utf8: Send as UTF-8 string otherwise send as ASCII string |
490 | """ |
491 | - # Funny looking data check, but it's a quick check for data=None |
492 | - log.debug('({ip}) _send_command(data="{data}")'.format(ip=self.entry.name, data=data.strip() if data else data)) |
493 | + if not data and not self.priority_queue and not self.send_queue: |
494 | + log.debug('({ip}) _send_command(): Nothing to send - returning'.format(ip=self.entry.name)) |
495 | + return |
496 | + log.debug('({ip}) _send_command(data="{data}")'.format(ip=self.entry.name, |
497 | + data=data.strip() if data else data)) |
498 | + log.debug('({ip}) _send_command(): priority_queue: {queue}'.format(ip=self.entry.name, |
499 | + queue=self.priority_queue)) |
500 | + log.debug('({ip}) _send_command(): send_queue: {queue}'.format(ip=self.entry.name, |
501 | + queue=self.send_queue)) |
502 | conn_state = STATUS_CODE[QSOCKET_STATE[self.state()]] |
503 | log.debug('({ip}) _send_command(): Connection status: {data}'.format(ip=self.entry.name, |
504 | data=conn_state)) |
505 | @@ -1149,9 +1155,9 @@ |
506 | self.waitForBytesWritten(2000) # 2 seconds should be enough |
507 | if sent == -1: |
508 | # Network error? |
509 | - log.warning('({ip}) _send_command(): -1 received - disconnecting from host'.format(ip=self.entry.name)) |
510 | self.change_status(E_NETWORK, |
511 | translate('OpenLP.PJLink', 'Error while sending data to projector')) |
512 | + log.warning('({ip}) _send_command(): -1 received - disconnecting from host'.format(ip=self.entry.name)) |
513 | self.disconnect_from_host() |
514 | |
515 | def connect_to_host(self): |
516 | @@ -1164,7 +1170,7 @@ |
517 | return |
518 | self.error_status = S_OK |
519 | self.change_status(S_CONNECTING) |
520 | - self.connectToHost(self.ip, self.port if isinstance(self.port, int) else int(self.port)) |
521 | + self.connectToHost(self.ip, self.port) |
522 | |
523 | @QtCore.pyqtSlot() |
524 | def disconnect_from_host(self, abort=False): |
525 | @@ -1181,7 +1187,7 @@ |
526 | try: |
527 | self.readyRead.disconnect(self.get_socket) |
528 | except TypeError: |
529 | - pass |
530 | + log.debug('({ip}) disconnect_from_host(): TypeError detected'.format(ip=self.entry.name)) |
531 | log.debug('({ip}) disconnect_from_host() ' |
532 | 'Current status {data}'.format(ip=self.entry.name, data=self._get_status(self.status_connect)[0])) |
533 | if abort: |
534 | |
535 | === modified file 'openlp/core/projectors/tab.py' |
536 | --- openlp/core/projectors/tab.py 2017-12-29 09:15:48 +0000 |
537 | +++ openlp/core/projectors/tab.py 2018-04-28 07:12:35 +0000 |
538 | @@ -89,6 +89,10 @@ |
539 | self.connect_box_layout.addRow(self.dialog_type_label, self.dialog_type_combo_box) |
540 | self.left_layout.addStretch() |
541 | self.dialog_type_combo_box.activated.connect(self.on_dialog_type_combo_box_changed) |
542 | + # Connect on LKUP packet received (PJLink v2+ only) |
543 | + self.connect_on_linkup = QtWidgets.QCheckBox(self.connect_box) |
544 | + self.connect_on_linkup.setObjectName('connect_on_linkup') |
545 | + self.connect_box_layout.addRow(self.connect_on_linkup) |
546 | |
547 | def retranslateUi(self): |
548 | """ |
549 | @@ -109,6 +113,8 @@ |
550 | translate('OpenLP.ProjectorTab', 'Tabbed dialog box')) |
551 | self.dialog_type_combo_box.setItemText(DialogSourceStyle.Single, |
552 | translate('OpenLP.ProjectorTab', 'Single dialog box')) |
553 | + self.connect_on_linkup.setText( |
554 | + translate('OpenLP.ProjectorTab', 'Connect to projector when LINKUP received (v2 only)')) |
555 | |
556 | def load(self): |
557 | """ |
558 | @@ -120,6 +126,7 @@ |
559 | self.socket_timeout_spin_box.setValue(settings.value('socket timeout')) |
560 | self.socket_poll_spin_box.setValue(settings.value('poll time')) |
561 | self.dialog_type_combo_box.setCurrentIndex(settings.value('source dialog type')) |
562 | + self.connect_on_linkup.setChecked(settings.value('connect when LKUP received')) |
563 | settings.endGroup() |
564 | |
565 | def save(self): |
566 | @@ -132,6 +139,7 @@ |
567 | settings.setValue('socket timeout', self.socket_timeout_spin_box.value()) |
568 | settings.setValue('poll time', self.socket_poll_spin_box.value()) |
569 | settings.setValue('source dialog type', self.dialog_type_combo_box.currentIndex()) |
570 | + settings.setValue('connect when LKUP received', self.connect_on_linkup.isChecked()) |
571 | settings.endGroup() |
572 | |
573 | def on_dialog_type_combo_box_changed(self): |
574 | |
575 | === renamed file 'tests/openlp_core/projectors/test_projector_pjlink_base.py' => 'tests/openlp_core/projectors/test_projector_pjlink_base_01.py' |
576 | --- tests/openlp_core/projectors/test_projector_pjlink_base.py 2018-01-13 05:41:42 +0000 |
577 | +++ tests/openlp_core/projectors/test_projector_pjlink_base_01.py 2018-04-28 07:12:35 +0000 |
578 | @@ -27,23 +27,13 @@ |
579 | |
580 | import openlp.core.projectors.pjlink |
581 | from openlp.core.projectors.constants import \ |
582 | - E_NOT_CONNECTED, \ |
583 | - E_PARAMETER, \ |
584 | - E_UNKNOWN_SOCKET_ERROR, \ |
585 | - STATUS_CODE, \ |
586 | - STATUS_MSG, \ |
587 | - S_CONNECTED, \ |
588 | - S_CONNECTING, \ |
589 | - S_NOT_CONNECTED, \ |
590 | - S_OK, \ |
591 | - S_ON, \ |
592 | + E_NOT_CONNECTED, E_PARAMETER, E_UNKNOWN_SOCKET_ERROR, STATUS_CODE, STATUS_MSG, \ |
593 | + S_CONNECTED, S_CONNECTING, S_NOT_CONNECTED, S_OK, S_ON, \ |
594 | QSOCKET_STATE |
595 | from openlp.core.projectors.db import Projector |
596 | from openlp.core.projectors.pjlink import PJLink |
597 | from tests.resources.projector.data import TEST1_DATA |
598 | |
599 | -pjlink_test = PJLink(Projector(**TEST1_DATA), no_poll=True) |
600 | - |
601 | |
602 | class TestPJLinkBase(TestCase): |
603 | """ |
604 | |
605 | === added file 'tests/openlp_core/projectors/test_projector_pjlink_base_02.py' |
606 | --- tests/openlp_core/projectors/test_projector_pjlink_base_02.py 1970-01-01 00:00:00 +0000 |
607 | +++ tests/openlp_core/projectors/test_projector_pjlink_base_02.py 2018-04-28 07:12:35 +0000 |
608 | @@ -0,0 +1,101 @@ |
609 | +# -*- coding: utf-8 -*- |
610 | +# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4 |
611 | + |
612 | +############################################################################### |
613 | +# OpenLP - Open Source Lyrics Projection # |
614 | +# --------------------------------------------------------------------------- # |
615 | +# Copyright (c) 2008-2015 OpenLP Developers # |
616 | +# --------------------------------------------------------------------------- # |
617 | +# This program is free software; you can redistribute it and/or modify it # |
618 | +# under the terms of the GNU General Public License as published by the Free # |
619 | +# Software Foundation; version 2 of the License. # |
620 | +# # |
621 | +# This program is distributed in the hope that it will be useful, but WITHOUT # |
622 | +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # |
623 | +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # |
624 | +# more details. # |
625 | +# # |
626 | +# You should have received a copy of the GNU General Public License along # |
627 | +# with this program; if not, write to the Free Software Foundation, Inc., 59 # |
628 | +# Temple Place, Suite 330, Boston, MA 02111-1307 USA # |
629 | +############################################################################### |
630 | +""" |
631 | +Package to test the openlp.core.projectors.pjlink base package. |
632 | +""" |
633 | +from unittest import TestCase |
634 | +from unittest.mock import call, patch |
635 | + |
636 | +import openlp.core.projectors.pjlink |
637 | + |
638 | +from openlp.core.projectors.constants import S_NOT_CONNECTED |
639 | +from openlp.core.projectors.db import Projector |
640 | +from openlp.core.projectors.pjlink import PJLink |
641 | +from tests.resources.projector.data import TEST1_DATA |
642 | + |
643 | + |
644 | +class TestPJLinkBase(TestCase): |
645 | + """ |
646 | + Tests for the PJLink module |
647 | + """ |
648 | + @patch.object(openlp.core.projectors.pjlink.PJLink, 'state') |
649 | + @patch.object(openlp.core.projectors.pjlink.PJLink, 'reset_information') |
650 | + @patch.object(openlp.core.projectors.pjlink.PJLink, '_send_command') |
651 | + @patch.object(openlp.core.projectors.pjlink, 'log') |
652 | + def test_send_command_no_data(self, mock_log, mock_send_command, mock_reset, mock_state): |
653 | + """ |
654 | + Test _send_command with no data to send |
655 | + """ |
656 | + # GIVEN: Test object |
657 | + log_warning_calls = [call('({ip}) send_command(): Not connected - returning'.format(ip=TEST1_DATA['name']))] |
658 | + |
659 | + log_debug_calls = [call('PJlink(projector="< Projector(id="None", ip="111.111.111.111", port="1111", ' |
660 | + 'mac_adx="11:11:11:11:11:11", pin="1111", name="___TEST_ONE___", ' |
661 | + 'location="location one", notes="notes one", pjlink_name="None", ' |
662 | + 'pjlink_class="None", manufacturer="None", model="None", ' |
663 | + 'serial_no="Serial Number 1", other="None", sources="None", source_list="[]", ' |
664 | + 'model_filter="Filter type 1", model_lamp="Lamp type 1", ' |
665 | + 'sw_version="Version 1") >", args="()" kwargs="{\'no_poll\': True}")'), |
666 | + call('PJlinkCommands(args=() kwargs={})')] |
667 | + mock_state.return_value = S_NOT_CONNECTED |
668 | + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) |
669 | + pjlink.send_queue = [] |
670 | + pjlink.priority_queue = [] |
671 | + |
672 | + # WHEN: _send_command called with no data and queue's empty |
673 | + pjlink.send_command(cmd='DONTCARE') |
674 | + |
675 | + # THEN: |
676 | + mock_log.debug.assert_has_calls(log_debug_calls) |
677 | + mock_log.warning.assert_has_calls(log_warning_calls) |
678 | + assert mock_reset.called is True |
679 | + assert mock_reset.called is True |
680 | + |
681 | + @patch.object(openlp.core.projectors.pjlink, 'log') |
682 | + def test_local_send_command_no_data(self, mock_log): |
683 | + """ |
684 | + Test _send_command with no data to send |
685 | + """ |
686 | + # GIVEN: Test object |
687 | + log_debug_calls = [call('PJlink(projector="< Projector(id="None", ip="111.111.111.111", port="1111", ' |
688 | + 'mac_adx="11:11:11:11:11:11", pin="1111", name="___TEST_ONE___", ' |
689 | + 'location="location one", notes="notes one", pjlink_name="None", ' |
690 | + 'pjlink_class="None", manufacturer="None", model="None", ' |
691 | + 'serial_no="Serial Number 1", other="None", sources="None", source_list="[]", ' |
692 | + 'model_filter="Filter type 1", model_lamp="Lamp type 1", ' |
693 | + 'sw_version="Version 1") >", args="()" kwargs="{\'no_poll\': True}")'), |
694 | + call('PJlinkCommands(args=() kwargs={})'), |
695 | + call('(___TEST_ONE___) reset_information() connect status is S_NOT_CONNECTED'), |
696 | + call('(___TEST_ONE___) _send_command(): Nothing to send - returning')] |
697 | + |
698 | + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) |
699 | + pjlink.send_queue = [] |
700 | + pjlink.priority_queue = [] |
701 | + |
702 | + # WHEN: _send_command called with no data and queue's emtpy |
703 | + # Patch here since pjlink does not have socket_timer until after instantiation |
704 | + with patch.object(pjlink, 'socket_timer') as mock_timer: |
705 | + pjlink._send_command(data=None, utf8=False) |
706 | + |
707 | + # THEN: |
708 | + mock_log.debug.assert_has_calls(log_debug_calls) |
709 | + assert mock_timer.called is False |
710 | |
711 | === modified file 'tests/openlp_core/projectors/test_projector_pjlink_cmd_routing.py' |
712 | --- tests/openlp_core/projectors/test_projector_pjlink_cmd_routing.py 2018-04-20 06:04:43 +0000 |
713 | +++ tests/openlp_core/projectors/test_projector_pjlink_cmd_routing.py 2018-04-28 07:12:35 +0000 |
714 | @@ -49,13 +49,23 @@ |
715 | pjlink.pjlink_functions = MagicMock() |
716 | log_warning_text = [call('({ip}) get_data(): Invalid packet - ' |
717 | 'unknown command "UNKN"'.format(ip=pjlink.name))] |
718 | - log_debug_text = [call('(___TEST_ONE___) get_data(ip="111.111.111.111" buffer="%1UNKN=Huh?"'), |
719 | + log_debug_text = [call('PJlink(projector="< Projector(id="None", ip="111.111.111.111", port="1111", ' |
720 | + 'mac_adx="11:11:11:11:11:11", pin="1111", name="___TEST_ONE___", ' |
721 | + 'location="location one", notes="notes one", pjlink_name="None", ' |
722 | + 'pjlink_class="None", manufacturer="None", model="None", serial_no="Serial Number 1", ' |
723 | + 'other="None", sources="None", source_list="[]", model_filter="Filter type 1", ' |
724 | + 'model_lamp="Lamp type 1", sw_version="Version 1") >", ' |
725 | + 'args="()" kwargs="{\'no_poll\': True}")'), |
726 | + call('PJlinkCommands(args=() kwargs={})'), |
727 | + call('(___TEST_ONE___) reset_information() connect status is S_NOT_CONNECTED'), |
728 | + call('(___TEST_ONE___) get_data(buffer="%1UNKN=Huh?"'), |
729 | call('(___TEST_ONE___) get_data(): Checking new data "%1UNKN=Huh?"'), |
730 | call('(___TEST_ONE___) get_data() header="%1UNKN" data="Huh?"'), |
731 | call('(___TEST_ONE___) get_data() version="1" cmd="UNKN"'), |
732 | - call('(___TEST_ONE___) Cleaning buffer - msg = "get_data(): ' |
733 | - 'Invalid packet - unknown command "UNKN""'), |
734 | - call('(___TEST_ONE___) Finished cleaning buffer - 0 bytes dropped')] |
735 | + call('(___TEST_ONE___) Cleaning buffer - msg = "get_data(): Invalid packet - ' |
736 | + 'unknown command "UNKN""'), |
737 | + call('(___TEST_ONE___) Finished cleaning buffer - 0 bytes dropped'), |
738 | + call('(___TEST_ONE___) _send_command(): Nothing to send - returning')] |
739 | |
740 | # WHEN: get_data called with an unknown command |
741 | pjlink.get_data(buff='{prefix}1UNKN=Huh?'.format(prefix=PJLINK_PREFIX)) |
742 | |
743 | === modified file 'tests/openlp_core/projectors/test_projector_pjlink_udp.py' |
744 | --- tests/openlp_core/projectors/test_projector_pjlink_udp.py 2018-04-20 06:04:43 +0000 |
745 | +++ tests/openlp_core/projectors/test_projector_pjlink_udp.py 2018-04-28 07:12:35 +0000 |
746 | @@ -30,37 +30,23 @@ |
747 | import openlp.core.projectors.pjlink |
748 | from openlp.core.projectors.constants import PJLINK_PORT |
749 | |
750 | -from openlp.core.projectors.db import Projector |
751 | -from openlp.core.projectors.pjlink import PJLinkUDP, PJLink |
752 | -from tests.resources.projector.data import TEST1_DATA, TEST2_DATA |
753 | +from openlp.core.projectors.pjlink import PJLinkUDP |
754 | +from tests.resources.projector.data import TEST1_DATA |
755 | |
756 | |
757 | class TestPJLinkBase(TestCase): |
758 | """ |
759 | Tests for the PJLinkUDP class |
760 | """ |
761 | - def setUp(self): |
762 | - """ |
763 | - Setup generic test conditions |
764 | - """ |
765 | - self.test_list = [PJLink(projector=Projector(**TEST1_DATA)), |
766 | - PJLink(projector=Projector(**TEST2_DATA))] |
767 | - |
768 | - def tearDown(self): |
769 | - """ |
770 | - Close generic test condidtions |
771 | - """ |
772 | - self.test_list = None |
773 | - |
774 | @patch.object(openlp.core.projectors.pjlink, 'log') |
775 | def test_get_datagram_data_negative_zero_length(self, mock_log): |
776 | """ |
777 | Test get_datagram when pendingDatagramSize = 0 |
778 | """ |
779 | # GIVEN: Test setup |
780 | - pjlink_udp = PJLinkUDP(projector_list=self.test_list) |
781 | - log_warn_calls = [call('(UDP) No data (-1)')] |
782 | - log_debug_calls = [call('(UDP) PJLinkUDP() Initialized'), |
783 | + pjlink_udp = PJLinkUDP() |
784 | + log_warning_calls = [call('(UDP) No data (-1)')] |
785 | + log_debug_calls = [call('(UDP) PJLinkUDP() Initialized for port 4352'), |
786 | call('(UDP) get_datagram() - Receiving data')] |
787 | with patch.object(pjlink_udp, 'pendingDatagramSize') as mock_datagram, \ |
788 | patch.object(pjlink_udp, 'readDatagram') as mock_read: |
789 | @@ -71,7 +57,7 @@ |
790 | pjlink_udp.get_datagram() |
791 | |
792 | # THEN: Log entries should be made and method returns |
793 | - mock_log.warning.assert_has_calls(log_warn_calls) |
794 | + mock_log.warning.assert_has_calls(log_warning_calls) |
795 | mock_log.debug.assert_has_calls(log_debug_calls) |
796 | |
797 | @patch.object(openlp.core.projectors.pjlink, 'log') |
798 | @@ -80,9 +66,10 @@ |
799 | Test get_datagram when data length = 0 |
800 | """ |
801 | # GIVEN: Test setup |
802 | - pjlink_udp = PJLinkUDP(projector_list=self.test_list) |
803 | - log_warn_calls = [call('(UDP) get_datagram() called when pending data size is 0')] |
804 | - log_debug_calls = [call('(UDP) get_datagram() - Receiving data')] |
805 | + pjlink_udp = PJLinkUDP() |
806 | + log_warning_calls = [call('(UDP) get_datagram() called when pending data size is 0')] |
807 | + log_debug_calls = [call('(UDP) PJLinkUDP() Initialized for port 4352'), |
808 | + call('(UDP) get_datagram() - Receiving data')] |
809 | with patch.object(pjlink_udp, 'pendingDatagramSize') as mock_datagram, \ |
810 | patch.object(pjlink_udp, 'readDatagram') as mock_read: |
811 | mock_datagram.return_value = 0 |
812 | @@ -92,7 +79,7 @@ |
813 | pjlink_udp.get_datagram() |
814 | |
815 | # THEN: Log entries should be made and method returns |
816 | - mock_log.warning.assert_has_calls(log_warn_calls) |
817 | + mock_log.warning.assert_has_calls(log_warning_calls) |
818 | mock_log.debug.assert_has_calls(log_debug_calls) |
819 | |
820 | @patch.object(openlp.core.projectors.pjlink, 'log') |
821 | @@ -101,9 +88,9 @@ |
822 | Test get_datagram when pendingDatagramSize = 0 |
823 | """ |
824 | # GIVEN: Test setup |
825 | - pjlink_udp = PJLinkUDP(projector_list=self.test_list) |
826 | - log_warn_calls = [call('(UDP) get_datagram() called when pending data size is 0')] |
827 | - log_debug_calls = [call('(UDP) PJLinkUDP() Initialized'), |
828 | + pjlink_udp = PJLinkUDP() |
829 | + log_warning_calls = [call('(UDP) get_datagram() called when pending data size is 0')] |
830 | + log_debug_calls = [call('(UDP) PJLinkUDP() Initialized for port 4352'), |
831 | call('(UDP) get_datagram() - Receiving data')] |
832 | with patch.object(pjlink_udp, 'pendingDatagramSize') as mock_datagram: |
833 | mock_datagram.return_value = 0 |
834 | @@ -112,5 +99,5 @@ |
835 | pjlink_udp.get_datagram() |
836 | |
837 | # THEN: Log entries should be made and method returns |
838 | - mock_log.warning.assert_has_calls(log_warn_calls) |
839 | + mock_log.warning.assert_has_calls(log_warning_calls) |
840 | mock_log.debug.assert_has_calls(log_debug_calls) |
A question in the code
In future can you put the test results at the bottom of the request as it makes the history easier to read.