Closed mweimerskirch closed 3 years ago
Good idea, so far there was only return code check. I'm using a standard RS232 cable as I have an RS232 port in my server but I also receive lots of bad returned data so I rather assume it is poor module on the unit. Actually I remember that when using standard control panel it was also not very responsive, sometimes getting wrong responses so most probably it was also not working very well and I guess also the reason why Zehnder has changed the panel and protocol in later models (I think it is a modebus or something similar).
Please do not merge yet. I'm still working on some improvements
I'm happy with the code now. I still have a few improvements planned, but I can do those in a separate PR. There have been major changes, so I hope I didn't introduce any bugs.
The most important changes are:
I hope you like the changes as well and feel comfortable merging the PR. Feel free to ask if anything is unclear or if I broke anything.
Something is wrong as it does not work at all. It fails at the first function "get_temp function could not get serial data", when I enable the PC mode it does not even complete the set_pc_mode(3)
call. Need to debug further to see where it gets stuck. My old code still works so nothing wrong with serial cable and the rest of it.
@mweimerskirch
Seems something is wrong with the send_data function, the command sent in the set_pc_mode(3) is: b'\x07\xf0\x00\x9b\x01\x03L\x07\x0f'
but should be b'\x07\xF0\x00\x9B\x01\x03\x4C\x07\x0F'
.
So I guess the checksum is not properly calculated.
Further into debugging I think I know where the problem is. checksum.to_bytes(((checksum.bit_length() + 8) // 8), byteorder='big')[-1:]
returns a character instead of byte at least for this specific case:
checksum += int(byte)
debug_msg(checksum)
debug_msg(checksum.to_bytes(((checksum.bit_length() + 8) // 8), byteorder='big')[-1:])
28-01-2021 17:47:19 DEBUG: 173
28-01-2021 17:47:19 DEBUG: b'\xad'
28-01-2021 17:47:19 DEBUG: 328
28-01-2021 17:47:19 DEBUG: b'H'
28-01-2021 17:47:19 DEBUG: 329
28-01-2021 17:47:19 DEBUG: b'I'
28-01-2021 17:47:19 DEBUG: 332
28-01-2021 17:47:19 DEBUG: b'L'
28-01-2021 17:47:19 DEBUG: b'\x07\xf0\x00\x9b\x01\x03L\x07\x0f'
Hope this helps :)
And one last hint. The problem seems to be with the fact that if the calculated checksum is larger than 255 (\xff) it becomes a 2 byte number and only the last byte should be taken. So in that example the checksum is 332 = x\14c so it should be \x4c :) Uff. Now if you could fix it would be great, it will take me much more time with my programming skills.
Something is wrong as it does not work at all. It fails at the first function "get_temp function could not get serial data", when I enable the PC mode it does not even complete the
set_pc_mode(3)
call. Need to debug further to see where it gets stuck. My old code still works so nothing wrong with serial cable and the rest of it.
The fact that sometimes characters are printed is not a bug, but just how Python works. When calling "print()", any byte that correspond to a "printable" ASCII character, will be displayed as that letter, not as the hex code. I learned that only a couple days ago when I was working on the project. If you have a look at an ASCII table (e.g. https://ascii.cl/) you'll see that 4C is the hex code for the letter L. So those are the same.
When you run print(b'\x4C')
, it will output b'L'
. If you want the hex code instead, you should call print(b'\x4C'.hex())
to get "4c".
What I find a bit funny is that the conversion also works the other way around. so if you call print(b'L'.hex())
, it will print "4c" as well.
Very strange, the PC mode works as expected here. I made a small change so the PC mode gets disabled in case it's set to "False" (I only temporarily enabled it to test and wanted to return to normal behaviour).
And one last hint. The problem seems to be with the fact that if the calculated checksum is larger than 255 (\xff) it becomes a 2 byte number and only the last byte should be taken. So in that example the checksum is 332 = x\14c so it should be \x4c :) Uff. Now if you could fix it would be great, it will take me much more time with my programming skills.
The [-1:]
part in the code will do just that: take only the last byte.
Can you try changing the time.sleep(2)
in line 230 to something higher? Like sleep(2.5), and see if that helps? In line 233, I now read 10 bytes at a time, instead of just 1 at a time. Maybe that's just a couple milliseconds faster and the reply is not available yet, leading to the "Expected return not found" issue.
Indeed when I print(cmd.hex())
it returns the actual hex values.
Changing the sleep duration does not help.
Digging further it seems that the serial_command
is waiting forever to get the data. When I changed it to read 1 byte at the time it works ok. I've also tested to read 2 bytes at a time, and it works ok only if number of returned bytes is even and stuck on waiting if the number of returned bytes (should be) odd. Not sure if this is something that can be fixed or reading 1 byte at a time is the only option. Increasing the sleep time even to 5 seconds does not help.
Strange behaviour. I'll revert it to 1 byte this evening.
My guess is that it's due to the chip in the cable. I used to have a cable with CHM340 chip and got some strange behaviour. Since switching to one with FTDI chip the connection is almost flawless (maybe one error message per hour).
I'm using just a standard serial port on my server (actually it is a PCI-E card). So maybe we add a config parameter to control it? Btw what would be the reason to read 10 bytes instead of 1?
I'm using just a standard serial port on my server (actually it is a PCI-E card).
Interesting that this behaves so differently. And very good that you found out where the issue was. I'm really glad that it's just that and none of the bigger changes ;-D
So maybe we add a config parameter to control it? Btw what would be the reason to read 10 bytes instead of 1?
There is no technical reason (I think), it was more like a personal preference. That's why it's not problem at all to revert. No configuration needed. I'll add a commit after work.
Many thanks @mweimerskirch ! This update makes the program much more robust, modular and open for future expansion with new features.
Work in Progess. Do not merge yet.
Currently, I'm not sure if the validation works correctly as I get a lot of invalid checksums. I suspect this is due to the rather cheap RS232 cable I'm using. The replacement (this time with FTDI chip) will arrive by the end of next week and I'll continue working on this PR as soon as that is the case.
In the mean time, feedback is welcome. I'd really like to know if this implementation works for anybody else.