JohnBrodie/pyjector

the power on command completes in the command line but the projector does not recieve the message

Closed this issue · 24 comments

from what i have gathered my serial connection is established and minicom verifies that its talking (i think, like you said kind of a weird program to understand) and i can do the ./pyjector_controller benq "/dev/ttyUSB0" power on , the termianl pauses for a sec like its sending the command but the projector still stays off. Also have tried to turn it off from an "on" state , but no luck either. Any help would be greatly appeciated!

Try some of the other commands with the projector on to verify that things are working... Although the instructions for the BenQ list power on/off, I've never been able to get that command to work, even when using the minicom directly. Seems to be a model-specific issue, but I don't have a large enough sample size to really say that definitively.

I seem to be running into something quite similar. I can turn off my projector (Benq W1070) using pyjector but trying to turn it on (when it is off) results in a "block item" response :(
Other actions, while the projector is turned on, seems to be working, although I have only tried a limited amount of commands.

Is anyone actually able to turn on their projector from RS232?

kll@PompousTheather:~/pyjector$ sudo ./pyjector_controller -v benq /dev/ttyUSB0 power status
INFO send:
*pow=?#

INFO recv: >
*pow=?#

*Block item#

Traceback (most recent call last):
  File "./pyjector_controller", line 21, in <module>
    command(args.action)
  File "/home/kll/pyjector/pyjector/pyjector.py", line 276, in handler
    return self._command_handler(command, action)
  File "/home/kll/pyjector/pyjector/pyjector.py", line 235, in _command_handler
    self._check_response(response)
  File "/home/kll/pyjector/pyjector/pyjector.py", line 261, in _check_response
    'Command failed! This is likely due to an invalid state '
pyjector.pyjector.CommandFailedError: Command failed! This is likely due to an invalid state change.

http://d165.fish-u.ac.jp/kk/up/BenQ/BenQ%20RS232%20commands.pdf in its chinglish says:

5. If the command format is correct, but it is not valid for this model, it will echo
“Unsupported item”.
6. If the command format is correct, but can’t be execute in some condition, it will echo
“Block item”.
Note: 1.Item 5 and item 6 is not support at power saving mode (standby power < 1W).
2. Each input upper case and lower case character should be action.
7. All of status command and power on command should be action when low power mode
(<0.5W)

I have difficulty parsing this. In the Note under point 6 it says that item 5 and 6 are not supported at power saving mode. What is item 5 and 6? The points in this very list or something else?

Point 7 seems to support the argument that power on and various status command are available when the projector is turned off (I am assuming "off" = "low power mode")

I don't know about the Benq W1070 but on my Mitsubishi HC5500 the manual state that only some commands are functional while in power off mode and that more commands are available when powered on. It also states that some commands gets disable for a while after being issued until state change is complete.

In your case it looks like you get a response. ''_pow=?#\r\n\r\n_Block item#\r\n"
if you do git pull you will see the escaped characters too now.

Indeed, with new version I see those escaped characters;

kll@PompousTheather:~/pyjector$ sudo ./pyjector_controller -v benq /dev/ttyUSB0 power on
INFO send: '\r\n*pow=on#\r\n'
INFO recv: '>\n*pow=on#\r\n\r\n*Block item#\r\n'

kll@PompousTheather:~/pyjector$ sudo ./pyjector_controller -v benq /dev/ttyUSB0 power status
INFO send: '\r\n*pow=?#\r\n'
INFO recv: '>\n*pow=?#\r\n\r\n*Block item#\r\n'

I tried pulling the power cable on my projector, wait till all the LEDs die out completely (some rather big capacitor in there!) and reconnect. I would assume this puts the projector in a state where it would be receptive to the pow=on command but alas, it's giving me the good ol' block item :/

Could it be firmware version related? Would of course be very nice to hear someone with a successful experience with w1070...

Stating the obvious, the speed is correct as anything else just gives garbled output (also checked with projector setting). And encapsulation of command (\r\n et al) seems correct given that pow=off works when the projector is on.

I find 2 and 3 of interest

2: When give “Enter”(ASCII 13), it will echo 3E,00. It means projector is ready to accept RS 232 command.
3: If no any command, it should echo 0D,0A,00 after 5 seconds.(5 sec time out)

I interpret this as

tx: '\r'
rx: '>\0' <-- must wait before sending command
tx: your command
rx: response to command
rx: '\r\n\0' <--- will be sent after 5 seconds (timeout) and after this one must issue '\r' again before sending any new commands.

Ok, so I added a bit of code to check initial response before sending the command, this is what I got:

kll@PompousTheather:~/pyjector$ sudo ./pyjector_controller -v benq /dev/ttyUSB0 power status
INFO send init: \r
INFO Decoding response: > = 62 (0x3e)
INFO send: '\r\n*pow=?#\r\n'
INFO recv: '\r\n*pow=?#\r\n\r\n*Block item#\r\n'

The manual says I should get 3E,00. I get 0x3e. Not actually sure if I can expect to see a 00 (NULL) character. Anyway, it's close enough - it's certainly no 0d,0a
But, still I get block item for the actual command :(

I added 'repr()' and time to logging, please do git pull

Ok, with timings (and still my little patch for decoding initial response):

kll@PompousTheather:~/pyjector$ sudo ./pyjector_controller -v benq /dev/ttyUSB0 power on
1445263282.387815 INFO send init: \r
1445263283.389784 INFO decoding response: > = 62 (0x3e)
1445263283.390318 INFO send: '\r\n*pow=on#\r\n'
1445263284.393487 INFO recv: '\r\n*pow=on#\r\n\r\n*Block item#\r\n'

And FYI, my crude patch:

+       # send init
+        logging.info("send init: \\r")
+        self.serial.write('\r')
+        sleep(1)
+        init_response = self.get_response()
+        for c in init_response:
+                logging.info("decoding response: " + c + " = " + str(ord(c)) + " (" + hex(ord(c)) + ")")

It may be required to examine the read loop in get_response()
it does not really handle waiting for input correctly

I did actually have a quick look at it before deciding to use it. But just to look deeper, I rewrote the code a bit;

        # send init
        logging.info("send init: \\r")
        self.serial.write('\r')
        while True:
                c = self.serial.read(1)
                logging.info("decoding response: " + str(ord(c)) + " (" + hex(ord(c)) + ")")

Output

kll@PompousTheather:~/pyjector$ sudo ./pyjector_controller -v benq /dev/ttyUSB0 power on
1445264138.219559 INFO send init: \r
1445264138.235229 INFO decoding response: 62 (0x3e)
1445264143.250049 INFO decoding response: 13 (0xd)
1445264143.250495 INFO decoding response: 10 (0xa)

We can clearly see that we are getting the OK (0x3e) and after the timeout of five seconds we get 0xd and 0xa, i.e. command timeout. Yet, actually sending a command within those five seconds consistently leads to "block item" :(

I agree. Interesting!

But this does look very much like a model specific issue. pyjector has some areas where it can be improved but this issue looks like it's a matter of figuring out what sequence of commands is needed to get it to power on since it does respond to commands.

the manual say "" carriage return. can it be something other then \r\n. On my Mitsubishi HC5500 it is simply \r

when you issue your power on command, try to obmit the first \r as it is sent in your first command-wait part.

1445263283.390318 INFO send: '\r\n*pow=on#\r\n' <--- here you can obmit the first \r is it has already been sent?

There are also other power related commands?

<CR>*directpower=on#<CR>
<CR>*autopower=on#<CR>
<CR>*ins=on#<CR>

I just got it to turn on. I hacked in some stuff with the idea being to manually format the string to send. I was lazy enough to not comment out the other parts so ran two commands. Output:

kll@PompousTheather:~/pyjector$ sudo ./pyjector_controller -v benq /dev/ttyUSB0 power on
1445265880.078027 INFO send init: \r
1445265881.080054 INFO decoding response: > = 62 (0x3e)
1445265881.080383 INFO send pow: '\r*pow=on#\r'
1445265882.083274 INFO recv: '\r*pow=on#\r\r\n*Block item#\r\n'
1445265882.083594 INFO send: '\r*pow=on#\r'

let me clean up my mess... debugging runs are painfully slow as I have to wait for fan to power down (like a bloody minute or something)

great, try the power status command instead of power on. Should work. and try to obmit the first \r after your initial write(\r);read(1) loop:

write("\r")
read(1)
write("*pow=?#\r")

Indeed, minimising my changes the crucial difference is going from \r\n to just using \r.

Is this a typo in the benq model or are there actually other Benq models out there that requires the use of \r\n ? If not, we could just change the benq model. If there is a difference (somehow I find it unlikely) then we would need to copy the entire model...

I'm guessing that all \n chars is ignored/removed on a very low level when the benq projector reads it's input. So all \n can be removed from the config file of benq. but it is sensitive to double \r.

What do you mean ignored/removed? It is the use of \n that actually messes things up for me, so I don't think it's ignored ;)

Just to clarify, I only changed left_surround and right_surround to get it working, like this

kll@PompousTheather:~/pyjector$ git diff
diff --git a/pyjector/projector_configs/benq.json b/pyjector/projector_configs/benq.json
index aee46a0..199a5e4 100644
--- a/pyjector/projector_configs/benq.json
+++ b/pyjector/projector_configs/benq.json
@@ -1,6 +1,6 @@
 {
-    "left_surround": "\r\n*",
-    "right_surround": "#\r\n",
+    "left_surround": "\r*",
+    "right_surround": "#\r",
     "seperator": "=",
     "wait_time": 1,

I guess it would be a nice thing to actually read the status after the first \r instead of just pushing all the commands through. Once we start reading on the port we do actually see the 0x3e, signaling that the projector is ready to receive:

kll@PompousTheather:~/pyjector$ sudo ./pyjector_controller -v benq /dev/ttyUSB0 power status
1445268566.132128 INFO send: '\r*pow=?#\r'
1445268567.135313 INFO recv: '>*pow=?#\r\r\n*POW=OFF#\r\n'

The first character in the response, i.e. '>', is ASCII for 0x3e.

So instead of doing \r*pow=?#\r it would be nice to

  • send \r
  • check we get 0x3e (or fail on 0xd, 0xa)
  • send actual command
  • receive output

But I feel this would change the program flow from what it currently is (with additional complexity to the config file) and to be honest I don't want to spend the time doing that. It works good enough for me as is ;)

Would be nice to get the \r and not \r\n in to this repo though..

please make a pull request for the benq config changes and John can decide if he likes it or not. I see no reason not to merge it.

at some point we should do some refactoring too to do the \r-wait-command thing.

Ok, done!

Thanks for quick feedback et al, very nice :)

Also, I feel like I hijacked this issue - was just looking for some feedback on what might be a related issue. Apologies if I did.

Thanks for the trouble shooting and PRs. I've pushed version 0.2.2 to PyPi, which should fix the issue thanks to #8 . Certainly fixes the issue on my w1070.