The next part is to figure out how the protocol works, and the format of the data.
I started with taking some live captures in a running system (A MATE connected to an MX charge controller), and looking at what kind of packets were being exchanged. The MATE behaves as a master, and all communication is initiated by it. No data is sent from the MX by itself.
On start-up, the following packet is exchanged (presumably some sort of scan/ID packet):
TX: 00 02 00 00 00 00 00 02
RX: 03 00 03 00 06
(TX is what the MATE sends, RX is what the MX sends back)
And while on the status panel, the following packet is sent every second:
TX: 00 04 00 01 00 00 00 05
RX: 03 81 80 82 00 6A 3F 01 00 1D 00 FF 02 40 03 8E
It's worth noting that the first byte in both TX and RX actually have bit 9 set. I wasn't able to capture this on my PC, which just treated the 9th bit as a parity bit. This is how they denote the start of a packet
After observing a few packets, it became clear that the last two bytes were a checksum - but not a proper checksum - it was literally just the sum of all the bytes in the packet! (03+00+03 == 00 06)
There were also some obvious patterns in the TX packet, like the second byte which seems to correspond to some kind of command or packet type (02 for start-up, 04 for requesting a status packet)
I then tried matching the received status packet with the information that was currently on the screen, and was able to pick out some of the fields (status, battery voltage, pv voltage). Unfortunately the rest of the data proved elusive, but it was definitely encoded somewhere within the packet!
I decided a different plan of attack was in order, since I couldn't see any other obvious patterns in the data. I started writing a simple MX emulator in python, communicating through my MATE adapter mentioned in the last progress log.
It was able to spoof packets to the MATE, and I could then see the result on the screen and figure out what each byte did (or at least every byte that was visible on the LCD). By doing this I was able to figure out almost all of the status packet so I could correctly decode one sent from the MX unit itself. (Since the goal of this project is to replace the MATE and talk directly to an MX unit)
Spoofing the status packet sent to a MATE unit
At this point I decided to try spoofing some other devices which I did not have access to, such as an FX inverter, a Hub, and a FlexNET DC monitor.
This was a bit trickier to spoof since I had no idea what kind of data the MATE would expect. Luckily I discovered that the MATE would actually tell me if the packet had an error if it was too short, so I just kept padding 0x00s until it reported no errors (at which point it showed all 0s on the LCD for each read-out). I was then able to poke each byte and see what effect it had on the LCD, and mostly determine what each byte did.
The spoofing code I used is available in my python library, but the MATE adapter needs to have the RX/TX swapped since it will be connected to the MATE, not the MX/FX unit.
The next thing I discovered was that some of the other LCD screens sent a separate packet, which appeared to obtain the value of one specific register (eg. battery voltage, relay status, etc.):
TX: 00 02 00 44 00 00 00 46
RX: 03 00 12 34 03
And I also discovered a similar packet was sent when I tried to control something (the MATE allows you to turn an attached inverter on/off):
TX: 00 04 00 61 00 00 01 65
The full details of what each byte represents is available in my python library