I have 2 devices communicating with each other using Modbus and I would like to sniff this communication line using Python for logging purposes. I have connected my computer to the communication bus via a Modbus dongle, but I don't know how I can actually read the data.
I have used Pymodbus before, but I don't think that would work in this case since it only allows for master or slave devices (as far as I know)
Are there any other libraries that I can use for my purpose? Would it be possible for me to implement something like a read only socket on the COM port that doesn't interfere with existing communication on the bus?
Thank you!
You can try a MODBUS simulator like this one: It has an option to see the activity on the bus.
If you want to use another python MODBUS I recommend using modbus_tk. It has an example on how to create an MODBUS simulator. But to be able sniff the packets sent to other devices you will need to do some modifications to disable the automatic response.
If the only thing you want to do is to see the activity on the bus I recommend the first option.
I hope this helps you.
[Edit]:To be more specific you will need to download the following software : Modbus Poll - MODBUS slave simulator(which works on Windows) and plug your MODBUS dongle in the port you intend to use. After you do all the settings for the serial communications go to the Display tab and click on Communication. You will be able to see the traffic on the line.
Related
I've recently been learning electric circuitry using arduino and am looking to implement some changes to my Raspberry Pi application.
I used this outdated tutorial a few years ago to create my pi bluetooth receiver which is working well at the moment (https://www.instructables.com/id/Turn-your-Raspberry-Pi-into-a-Portable-Bluetooth-A/) but one downfall of this out-dated tutorial is that bluetooth connections have to be accepted via the screen (which is off because bluetooth speakers do not have screens).
My plan: use a button to accept bluetooth connections and use a flashing green LED to indicate a connection request.
How can I create a script that 'listens' for bluetooth pairing requests and run python code accordingly when its listening? With this, how can I connect to the bluetooth to accept a pair request?
I'm not too familiar with Raspberry Pi script placement, but am familiar with Python and know how I can connect to GPIO.
Thanks :)
What you are searching for is called a Bluetooth Agent. You need to use an official linux bluetooth protocol stack BlueZ. There is documentation describing the Agent API link. It uses DBus for communication. You need to invoke the following steps:
Create a bluetooth agent written in python and publish it at certain DBus object path. Your agent must implement org.bluez.Agent1 interface as described in Agent API doc.
Then you need to register this agent by calling RegisterAgent method from Agent API. Here you will provide the DBus path where your agent is located and also you will provide the capability in your case "DisplayYesNo" (LED as a display for pairing request, and button with some timeout for implementing Yes/No).
Also register your agent as a default agent by calling RequestDefaultAgent
Now if you try to pair with your device the appropriate function in your agent will be called (I think for your use case it will be RequestAuthorization) If you want to accept the pairing you will just return from this function, if you want to reject the pairing you must throw a DBus error inside this function.
As a starting point for you I would suggest you to look at this simple python Agent: https://github.com/pauloborges/bluez/blob/master/test/simple-agent
It implements all the functionality you need so just update it according to your needs.
Have fun :)
Have you tried using this Python library ? It lists Raspberry Pi support
Additionally, here's some info on listening for incoming Bluetooth connections:
Bluetooth programming in Python follows the socket programming model.
This is a concept that should be familiar to almost all network
programmers, and makes the transition from Internet programming to
Bluetooth programming much simpler. Example 3-2 and Example 3-3 show
how to establish a connection using an RFCOMM socket, transfer some
data, and disconnect.
import bluetooth
server_sock=bluetooth.BluetoothSocket( bluetooth.RFCOMM )
port = 1
server_sock.bind(("",port))
server_sock.listen(1)
client_sock,address = server_sock.accept()
print "Accepted connection from ",address
data = client_sock.recv(1024)
print "received [%s]" % data
client_sock.close()
server_sock.close()
An RFCOMM BluetoothSocket used to accept incoming connections must be
attached to operating system resources with the bind method. bind
takes in a tuple specifying the address of the local Bluetooth adapter
to use and a port number to listen on. Usually, there is only one
local Bluetooth adapter or it doesn't matter which one to use, so the
empty string indicates that any local Bluetooth adapter is acceptable.
Once a socket is bound, a call to listen puts the socket into
listening mode and it is then ready to accept incoming connections.
...
Source
I have two PLC modbus devices. These two are different companies.
The first one is that A will return the temperature and humidity. The second is that B will return five values. In both devices, the connection is modbus TCP.
One problem is that the same test software can be connected but the other cannot be connected. One device can be connected using pyModbus, but the other device is not working.
I also tested some software and python libraries. List is as follows
Device A
Software
modbus Poll (OK)
ModScan32 (NO)
Python Lib
pyModbus (OK)
EasyModbus (NO)
Device B
Software
modbus Poll (NO)
ModScan32 (OK)
Python Lib
pyModbus (NO)
EasyModbus (OK)
I don't know the difference between the two devices.
I want to integrate these two into the web system for monitoring, and new devices can be added in the future.
If there is a third device, I have to retest the connection to see which Python lib is available.
How can I implement this?
Learn more about the communication format of PLC devices?
Write a set of Python Libs for all devices?
Thank You.
Use one library for each, save the data somewhere centralized and view it with a different app. I don't see the problem. Also, have you tried re-trying the connection or reading after a few seconds? In my experience, modbus devices fail every so often to answer (or maybe is a library problem, I don't know) and a retry usually works.
For this, and it sounds like any good IOT framework would solve it, you should send the data from each device separately to one central point, like an IOT cloud solution, then you can build a webapp to view whatever data you have on the IOT framework, regardless of when or if it came in. Most frameworks will show you the old data as well if its not connected, so you can still display data, indicating it is stale or something to your user.
Using a Lantronix UDS-1100 serial to IP converter. The goal is to write a small proof of concept piece in Python to capture serial data output by this device over IP.
I've done a couple test projects using sockets in python, but they were all done between python processes (python > python): listen() on one end, and connect(), sendall() etc on the other.
I think I can use sockets for this project, but before I invest a bunch of time into it, wanted to make sure it is a viable solution.
Can python sockets be used to capture IP traffic when the traffic is originating from a non-python source? I have full control over the IP and port that the device sends the serial data to, but there will be no python connect() initiated by the client. I can pre-pend then serial data with some connect() string if needed.
If sockets won't work, please recommend another solution...guessing it will be REST or similar.
Of course. TCP/IP is supposed to be cross-platform and cross-language, so in theory you should be able to communicate with every kind of device as long as you manage to process and send the expected protocol.
The solution to this problem is probably pretty simple, but I am new to interfacing with a device dynamically. What I'm doing is I am making a python executable code, so the user doesn't have to have Idle on their computer or any kind of python interpreter, which means I don't know which USB port the device will be plugged in to. The program needs to be able to open a connection to a device that is connected through a serial to usb converter. How can I determine which connected device is the correct device to open a port to? I am using pySerial to interact with the device. Any help would be greatly appreciated.
No matter how you configure your device, at some point you're probably going to have to ask the user where the port is, or poll all serial devices for a known response. (Polling has it's pitfalls though, so read on!). Unlike USB devices, there is no vendor/device ID that is made known to the OS when you attach a plain-old serial device.
First you need to find the serial ports. Here's a question that might help: What is the cross-platform method of enumerating serial ports in Python (including virtual ports)?.
Once you have a list of serial ports, you could ask the user whether they know which one to use. If they do, problem solved!
If they don't, you could offer to poll ALL serial devices with some data that you know will yield a certain response from your device. Keep in mind though that if the user has other serial devices attached, your string of "hello" bytes might actually be the self-destruct sequence for some other device! Hence, you should warn the user that polling may interfere with other devices, and always prompt them before you do so.
Without knowing more about your code (eg. what comms framework, if any, you're using; are you doing this in the console or are you using a GUI toolkit, etc), it's impossible to say what the best way to code this might be. In the simplest case, you could just loop over all of your serial devices, send the greeting and check for a response. (You could also do this in parallel: loop once for the greeting, and loop again to check what's in the buffer. If you're going to get more fancy than that, use a proper library.)
Side note: You might be able to get around this if you have a built-in converter that you can set the vendor/device ID for, but the converter will still be automatically detected by any modern OS and enumerated as a serial port; you won't get to talk to it directly as a USB device. It could be possible to figure out which port goes with which ID, but I've never tried to do that. But this approach is useless if you're not the one who gets to pick the converter (eg. if it's a user-supplied cable).
This is the way that I used for identify Serial-USB conveter device like Arduino.
It checks 'USB' String of device description.
import serial as ser
import serial.tools.list_ports as prtlst
global COMs
COMs=[]
def getCOMs():
global COMs
pts= prtlst.comports()
for pt in pts:
if 'USB' in pt[1]: #check 'USB' string in device description
COMs.append(pt[0])
The only way I can think to get around the problem with probing unknown devices is to have the device send unsolicited "hello" responses continually. That was you can just connect to all serial devices and listen for the "hellos". Connecting and listening to a serial device shouldn't ever mess it up.
The downside is you have these messages cluttering up your serial stream. You could have a "I'm here now, stfu" command but then you can only connect to it once.
FTDI chips have a method of identification but you have to use their library to access the data.
Is there anyway to do this without getting a "COM PORT IN USE" error? I have a a service that listens to gps GPRMC sentences on a com port. But I don't have this device on my testing computer. So I wanted to write a python script to simulate GPRMC sentences on the port while my other python script listens to the same port and parses.
Writing to a serial port does not leave a message on the serial port to be read by the same device. This just isn't how a serial port works and is not how most OSes are written to allow as a buffer behavior. What you really need is a virtual serial port.
Check out this section of a wikipedia article on COM port redirectors and see if any of it will fulfill your needs. Otherwise I recommend searching for COM port emulator, serial port virtualization, etc. until you find software that will work for your use case and operating system. This might be hard, especially if timing is important to your simulations.
Edit: To make this slightly more clear, let's talk about what the pySerial library is actually doing to communicate with python. pySerial is just communicating to the OS's API for the serial port. The OS will, generally, model this as a location to write information to and a location to read information from (buffered in just about all modern computing systems). What's important to understand is that from the point of view of the OS (how the serial port is modeled), the write location can ONLY be written to and the read location can only be read from. This may or may not be how the actual serial hardware interfaces with the machine, in most serial port hardware and interface designs that I've worked with, this is the case for the sake of simplicity and reduced cost. Because of this, you are down to two basic choices.
Give the OS a virtual serial port that you can read to AND write from somehow
Possibly simpler, put a null modem adapter on one of your computer's serial ports and, using a serial cable, connect the two ports. You can now have your service on one port and your simulated device script on the other.