RS485 Modbus RTU - Comms snooping

Hey Guys,

I have a new Serial Tap i have purchased.

The purpose for this was to snoop on comms between my Goodwe AC Battery inverter - SBP5000 and the energy meter i comes supplied with the GM1000D.

I have a 3 phase house and these energy meters are single phase only - as are the batteries/inverters - so i have one connected to each phase of my house.

My plan is to have a raspberry pi talk to the 3 energy meters, request the data and then fool the Inverters into thinking they are talking to the meter by sendng back altered information that will ensure i end up with batteries that are evenly servicing the loads to ensure our grid import/export is Net Zero.

I have therefore disconnected one of the inverters from the Meter, connected it to the Serial tap - RS485 port and then created a new short lead to go from the RS485 on the Serial Tap to the Meter.

I was therefore expecting to see a continual stream of information - requests every 200ms from the inverter and then responses from the Meters.

The link speed and settings are well documented by Goodwe as 9600,N,8,1 which is what i have set in IO Ninja (V5) but i am getting continual framing errors.

If i disconnect the Serial Tap and instead put the inverter back to the meter they start communicating straight away.

Any pointers on this ?

Craig

Framing errors are a common symptom of (a) wrong wiring or (b) wrong serial parameters (most likely, baud rate or parity). From your description, it sounds like you "inserted" your Serial Tap in-between the two nodes.

First, be sure to use the terminal block on the top. The DB9 connectors on the sides are not going to work with RS485 -- they are only for RS232 (as can be seen on this block diagram).

Next, another common misconception is "breaking" the original lines and inserting the Serial Tap in-between as shown on the left side of the picture below:

IMG_5337.jpg

For sniffing half-duplex RS485 links, use the wiring shown on the right (also, if there is a GND line besides D+/D-, it helps to connect it as well).

Once you receive a sensible-looking stream of raw data (with no or maybe occasional FRAMING errors) you can try attaching the Modbus Analyzer. Keypoints of configuring the Modbus Analyzer for half-duplex RS485 links are outlined in this KB article.

Hope this helps!

Hey Vladimir, Thanks for the quick response - yes i have gone for the diagram on the left when connecting as i assumed i would want to be a man in the middle rather than thinking about how RS485 works and just tapping into the interface as you have shown.

I assume as i am just listening i would tap into the RX+/RX- lines - whereas if i wanted to inject i would tap into the TX+/TX- instead ?

regards

Craig

Hey Vladimir,

Perfect thanks !!! Now i am getting a good decode of what is going on

Is there anyway to export the Hex Strings (without decode) into a text file

I often find it easier when decoding unknown devices (in terms of registers) to look for patterns and things that are constantly changing to give a hint as to what the data could represent.

Your decode window etc is brilliant i must say though !!

Great product

Craig

I assume as i am just listening i would tap into the RX+/RX- lines - whereas if i wanted to inject i would tap into the TX+/TX- instead ?

Serial Tap is a read-only sniffer device; it can't drive lines. TX+/TX- connectors are for the full-duplex RS485 links, aka 4-line RS485. It's not as common as half-duplex RS485, though.

BTW it's also possible to connect the D+/D- pair to TX+/TX- connectors (instead of RX+/RX-). The only difference it will make is the icon and color of captured data in the log (green for RX, blue for TX).

Perfect thanks !!! Now i am getting a good decode of what is going on

Glad to hear it works now!

Is there anyway to export the Hex Strings (without decode) into a text file

Yes, you can export your log as a text file (Menu -> File -> Save Log As...) at any time.

I often find it easier when decoding unknown devices (in terms of registers) to look for patterns and things that are constantly changing to give a hint as to what the data could represent.

If you want just the pure data without annotations added by Modbus Analyzer -- remove the Modbus Analyzer layer, and you will get back to the original log. Modbus Analyzer (as well as other protocol analyzers) does not destroy the original log, so it's totally reversible.

Another option to get to the raw data is to post-process the original .njlog file. It will be more efficient than parsing a hex view inside a text file. The .njlog file format is open-source (log file structure definitions are in scripts/api/log_RecordFile.jnc), so you can use any programming language of your choice.

An example of decoding *.njlog files can be found in scripts/plugins/ReplayLog/ReplayLogLayer.jnc, function ReplayLogLayer.readLoop(). This plugin reads a log and "replays" TX or RX data with respect to inter-packet delays. It's probably not exactly what you want, but it should give an idea of how to "walk" across a raw .njlog file to process the captured data.

Your decode window etc is brilliant i must say though !!
Great product

Thank you! We work hard to make our product as versatile and convenient as possible, so I really do appreciate such feedback 🙂

Yep - thanks for all the hints and help.

Hopefully 1 last questions - you are calculating the CRCs and reporting whether they are accurate/correct - do you just run through a bunch of different CRC algorithms at the start of a capture to try and work out which is the correct one ?

I need to have my system generate packets and was wondering is there somewhere that you identify which algo you settle on for the checksum decode ?

Craig

Hopefully 1 last questions - you are calculating the CRCs and reporting whether they are accurate/correct - do you just run through a bunch of different CRC algorithms at the start of a capture to try and work out which is the correct one ?

Modbus RTU is using CRC16 (ANSI) with the seed value of 0xffff. You can see the Modbus checksum of any data block in the "Checksum calculator" of the Information pane on the right. Select a range of data, and it will be instantly calculated.

The code should look something like this:

uint16_t modbusChecksum = crc16_ansi(p, size, 0xffff);

The implementation of crc16_ansi is in scripts/common/crc16.jnc