Serial Communication through Bluetooth ble - python

I am trying to communicate with my battery that has a ble Bluetooth module on it. the goal is to be able to connect to it and then communicate via serial communication by sending bytes back and forth
for example, I have a read and write uuid for it and some byte lines to send to it that it should send back bytes that I can interpret to read voltage temperature and current. like if I send the battery this EA D1 01 04 FF 02 F9 F5 in bytes it should send a byte line very similar back that tells me what the voltage is for the 4 different cells in the battery.
the things that I have are a service uuid and those bytes line commands.
I have tried using bleak as I have had some experience in this but for whatever reason it would not connect, I would get timeout errors or an os error.
I haven't been able to manually connect the Bluetooth with my Bluetooth settings on the desktop, so I haven't been able to setup a com port
I have been able to connect to it with a Arduino nano 33 but haven't been able to send and receive serial communication
I have been able to do this successfully with a Serial Bluetooth terminal on my android device and it works very nicely on that, but I would like to get it on my desktop as it would help me out a lot to automate getting that information and using it.
any help is greatly appreciated and i look forward to possibly communicating with some of you. feel free to ask for any addition information as maybe i was unclear with some things

Welcome to Stack Overflow. You want to become familiar with Bluetooth and need to understand that Bluetooth classic and Bluetooth LE are different standards that are incompatible to each other.
So while the Serial Bluetooth terminal probably uses the classic standard with SPP, other things you've tried seem to work with Bluetooth LE. The battery, for example, seems to work with Bluetooth LE and the GATT service, as indicated by the service UUID.
All in all, it looks to me as if you should first familiarise yourself with the technology before you start writing your program.

Related

Multi clients modbus to single modbus server

I have two python scripts which need to get data from the same modbus server.
However they cannot be simultaneously connected to the same modbus server, so I am looking for a "proxy" software.
This proxy will then sequentially transfer the modbus queries to the modbus server.
Solution should run on debian 11 lite.
Thanks!
I have the same challenges before and ended up with Modbus-to-MQTT bridge solution, because each protocol has its limit, Modbus is designed for master-slave poll in nature and MQTT is good for multiple clients/subscribers.
Modbus + MQTT, such a combination is just nice and could be very powerful in modern IoT applications. You can try modpoll, which is a python-based Modbus tool and can run as a Modbus-to-MQTT bridge in your case.
Assuming you are dealing with Modbus TCP you can try modbus-proxy:
Many modbus devices support only one or very few clients. This proxy
acts as a bridge between the client and the modbus device. It can be
seen as a layer 7 reverse proxy. This allows multiple clients to
communicate with the same modbus device.
When multiple clients are connected, cross messages are avoided by
serializing communication on a first come first served REQ/REP basis.
EDIT: According to your comment below:
...it is RTU over a linux file descriptor /dev/ttyS1
That seems to me a not-so-straightforward way of saying that you are dealing with a serial link.
If that's the case I'm afraid you need to go back all the way to the physical layer.
If you have a point-to-point serial connection (no matter the voltage levels you have, they can be TTL 3.3VDC or RS-232) there is no way you can have more than one Modbus client connecting to the same server.
For a serial link to have more than two devices (two or multiple clients sending queries to a Modbus server, for instance) you need a way for the devices to take control of the bus when they communicate and let go of it when they are idle. An RS-485 multipoint serial link is the most frequent solution to this problem.
If you follow the link you will find many resources and documentation. That might be a bit overwhelming but it is actually very easy: instead of connecting RX to TX as you'd do for a normal serial port you will have two cables for each device (they are called A and B or D+ and D-) that you can put together. And you only need to add a TTL to RS-485 transceiver in between each device and the bus (or RS-232 to RS-485, depending on your devices).
There are a couple of nuances:
You might need terminating resistors, but that should only be the case if your devices are far away (more than several meters) from each other.
If you go for the cheapest transceivers you might end up being forced to toggle the bus in your software, which is not a good solution. See my answer here for more details. And better aim for something with automatic TX enable.
The most complete reference on all these topics I know of is Jan Axelson's book Serial Port Complete. It's a bit old (the last edition was released in 2007) but still very relevant. And you can find older editions secondhand for next to nothing. If you need to work with serial ports, this book will be a very valuable companion.
Final note: if you are not able or willing to mess with the phy layer, you might, of course, find other solutions that are more palatable. You might, for instance, implement a software forwarder to take queries from your clients and convert them to Modbus RTU to be sent to your server. Pymodbus includes an example, but since you did not elaborate much I'm not sure it will be useful for your situation.

How do I fix Unknown Format?

This is my first time trying out to code on C# or VisualStudio.
Sorry if I am too much of a newbie.
I have a raspberry pi zero setup as a BLE GATT server, which I followed exactly with this guide.
My ultimate goal is just trying to send a text from the pi zero to my laptop.
Being a little familiar with python, I have tried to use Bleak to communicate with the GATT server but for some reason, I'm never able to connect to the GATT server. So I gave up trying to tinker with Bleak.
( Please note that I have used nRF Toolbox to verify that the pi zero BLE GATT server is set up correctly )
Fast foward, one day I saw this BLE GATT Client Sample from Microsoft. So I downloaded VisualStudio and followed the guide to deploy the sample.
Everything worked fine, I can connect to the GATT server and write data to the specific RX characteristics.
But the real problem resides on the TX characteristics, when I try to send data from the GATT server console to the laptop. The BLE Client Sample will show the value as "Unknown Format"
It seems that the data will be encoded ( value.append(dbus.Byte(c.encode())) ) with this before updating the TX charactersitics.
I tried to Google about this, but any further research will only make my head burn harder.
I'm sorry, can anyone tell me how to fix this "Unknown Format" data decode problem?
Thanks so much in advance.
On the server (RPi) you have:
UART_TX_CHARACTERISTIC_UUID = '6e400003-b5a3-f393-e0a9-e50e24dcca9e' as 'notify'
UART_RX_CHARACTERISTIC_UUID = '6e400002-b5a3-f393-e0a9-e50e24dcca9e' is 'write'
This means on the client (PC) you need 0003 to be 'write' and 0002 to be 'notify'.
You say the problem is when the server does a write to 0002 you are get unknown format?
BLE will always send the data as a byte array, I suspect you need to do something like this previous answer on the client for the data you receive

Understanding why missing serial port I'm receiving data from usb

I've a device which is supposed to send data via a usb connection. When I connect my laptop via usb to this device and open a terminal I get sone weird characters and are printed as a command line. However I haven't configured anything.
If I try to connect to the device via serial port initializing it I cannot know which port is? Plugging ang unplugging the device shows no difference in the result of:
>ls /dev/*
Which seems the device is not detected, but as I said in the command promp or even if I use any other application, it is as if I was writing, but random characters
Does anyone k ow why does it happen?
How can I set communication characteristics to be able to connect to the device at a certain baud-rate?
The idea is to get data via Python.
Lots of thanks ;)

Pyserial microcontroller to host communication

I am using a Beaglebone Black (BBB) with Python and pyserial to communicate with an OBD-II reader. I am essentially trying to build a customizable digital gauge panel. Ideally I would like to use Flash for the GUI. Sadly Linux support for Flash is pretty weak. I would like to be able to send data from the BBB using Python to a OSX host computer.
I am currently using terminal to shell into the BBB to run code. I would need to be able to send data from the BBB via a USB/serial interface to the OSX computer running Flash. What would be the best method of accomplishing this?
I have not used beaglebone. I have worked with arduino's serial I/O. But this post says you have multiple serial I/O ports on BBB. Find appropriate connectors/convertors for serial to USB.
Then use the pyserial python module.
On OSX, you will find your device when connected on a path like /dev/ttyo1 where dev is my system name and ttyo1 or something similar will be your device.
import serial as s
device = "/dev/tty01"
bbb = s.Serial(device, 4800) #the second param is baudrate
while(True):
bbb.readline()
# do what you want with the output.
bbb.write('input')
This will read till the end of line character and give you a string. and then write "input" to the serial io on bbb. You will need a similar program running on BBB to read this input and do what you want to do with it.
So there will be two python programs. One on the OSX and the other on the BBB
That way you can give commands from OSX.py, let your BBB.py process and send a response. Which the OSX.py will read and do what is to be done.
You will have to design the input/output cycle properly.
Also if flash is not really necessary you can check out pyside.

Serial Communication one to one

If this is a stupid question, please don't mind me. But I spent some time trying to find the answer but I couldn't get anything solid. Maybe this is a hardware question, but I figured I'd try here first.
Does Serial Communication only work one to one? The reason this came up is because I had an arduino board listening for communication on its serial port. I had a python script feed bytes to the port as well. However, whenever I opened up the arduino's serial monitor, the connection with the python script failed. The serial monitor also connects to the serial port for communication for its little text input field.
So what's the deal? Does serial communication only work between a single client and a single server? Is there a way to get multiple clients writing to the server? I appreciate your suggestions.
Multiple clients (e.g. Arduinos) communicating with one server (e.g. a desktop computer) is commonly done with the serial variant:
RS-485
This is a simple method widely used in industrial settings where you want to have many devices connected to one computer via one serial port. This type of arrangement is also called multi-drop, because one cable strings around a building with Tees that tap in and drop lines to each device.
The hardware for this is widely available. You can buy USB serial adapters that provide the hardware interface for a computer. Programmatically the port looks just like an RS232 port. For the Arduino you would just add a transceiver chip. A sea of serial transceivers exists, e.g.
Example computer USB adapter with 485 interface
Sample RS485 transceiver chip from Element14
All the devices hang on the same bus listening at the same time. A simple communication protocol used is just add a device address before every command. For example:
001SETLIGHT1 <- tells Arduino "001" to turn on the light
013SETLIGHT0 <- tells "013" to turn off the light
Any device hanging on the cable ignores commands that do not start with their address. When a device responds, it prepends its address.
001SETLIGHT1DONE <- response from device "001" that the command has been received and executed
The address in the response lets the receiving party know which device was talking.
Well, your question can be quite wide, so I'm going to layer my answer:
On the hardware side, the same pair of wires can work be shared with many devices. It is mostly a question of electronics (maintaining the signal in the good voltage range), and not having all devices writing to the serial port at the same time (or you'll get wreckage).
On the software side, on the host, yes you can share the same serial connection to a device with multiple processes. But that's not straight forward. I'll assume you're using an unix (macos or linux):
in unix, everything is a file, your serial connection is one too: /dev/ttyACM0 on linux, for example.
When you have a process opening that file, it will block it (using ioctl, iirc) so no other process can mess with that file too.
Then, you can input and output to that file using the process that opened it, that's all.
But hopefully, it is still possible to share the connection between processes. One of them would simply be to use the tee command, that will be able to get input from one process, and give it back output, and copy the output to another process. You can also do it from within python, by duplicating the file descriptor.
To easily output stuff that can be redirected the unix way (using pipes), you can use socat: http://www.dest-unreach.org/socat/
here's an usage example:
socat -,raw,echo=0,escape=0x0f /dev/ttyACM0,raw,echo=0,crnl
you may want to tweak it for your needs.
Edit:
I forgot about RS-485, which 'jdr5ca' was smart enough to recommend. My explanation below is restricted to RS-232, the more "garden variety" serial port. As 'jdr5ca' points out, RS-485 is a much better alternative for the described problem.
Original:
To expand on zmo's answer a bit, it is possible to share serial at the hardware level, and it has been done before, but it is rarely done in practice.
Likewise, at the software driver level, it is again theoretically possible to share, but you run into similar problems as the hardware level, i.e. how to "share" the link to prevent collisions, etc.
A "typical" setup would be two serial (hardware) devices attached to each other 1:1. Each would run a single software process that would manage sending/receiving data on the link.
If it is desired to share the serial link amongst multiple processes (on either side), the software process that manages the link would also need to manage passing the received data to each reading process (keeping track of which data each process had read) and also arbitrate which sending process gets access to the link during "writes".
If there are multiple read/write processes on each end of the link, the handshaking/coordination of all this gets deep as some sort of meta-signaling arrangement may be needed to coordinate the comms between the process on each end.
Either a real mess or a fun challenge, depending on your needs and how you view such things.

Categories

Resources