# EasyCom
**EasyCom** is a Python library designed for **asynchronous serial communication** with USB UART devices such as **Arduino, ESP32, Raspberry Pi Pico, Teensy**, and others. With **non-blocking communication**, **automatic port detection and reconnection**, and an **easy-to-use API**, EasyCom allows you to seamlessly interact with multiple devices. It also supports the **dynamic registration of new devices** at runtime.
---
## Features
- **Asynchronous Communication**: Uses threading to provide non-blocking read and write operations.
- **Automatic Port Detection and Reconnection**: Matches devices using PID/VID for automatic connection and reconnection if disconnected.
- **Pre-configured and Dynamically Registered Devices**: Built-in support for common devices, with the ability to add custom devices dynamically.
- **Thread-safe Writes**: Queue-based data management ensures safe, consistent writes.
- **Customizable Data Handlers**: Process incoming data using custom callback functions for maximum flexibility.
---
## Installation
You can install EasyCom directly with pip:
```bash
pip install easycom
```
---
## Getting Started
### Basic Example: Arduino with Default Parameters
This example demonstrates setting up an **Arduino** device using default parameters. With **automatic port detection**, the library will attempt to connect to the first available port with matching PID/VID.
```python
from easycom.devices import Arduino
# Define a simple callback function to handle received data
def handle_data(data):
print(f"Received: {data}")
# Initialize Arduino with automatic port detection and default settings
arduino = Arduino(data_handler=handle_data)
# Keep the program running to receive data
input("Press Enter to disconnect...")
# Disconnect the Arduino
arduino.disconnect()
```
---
### Overriding Parameters
EasyCom allows you to override specific parameters such as `port`, `baudrate`, `timeout`, and `data_handler`. Each example below illustrates how to set these parameters.
#### 1. Overriding the `port`
If the device is connected to a specific port, you can set it explicitly:
```python
arduino = Arduino(port="/dev/ttyUSB0", data_handler=handle_data)
```
#### 2. Overriding the `baudrate`
To customize the baud rate (e.g., 115200), set it during initialization:
```python
arduino = Arduino(baudrate=115200, data_handler=handle_data)
```
#### 3. Overriding the `timeout`
Adjust the timeout (in seconds) for read and write operations:
```python
arduino = Arduino(timeout=5, data_handler=handle_data)
```
Here’s an updated example using a `struct` in C++ on the Arduino side to send an integer and a float together as a single binary package. This structure will match the Python `struct` for decoding.
---
#### 4. Using a `struct`-based Data Handler
In this example, we’ll send data as a structured binary package from Arduino and parse it in Python using the `struct` module. The Arduino will send an integer and a float in one structured transmission.
```python
import struct
from easycom.devices import Arduino
# Define a data handler to parse binary data
def handle_data(data):
# Parse data as an integer and a float
parsed_data = struct.unpack("<if", data) # "<if" represents little-endian int, float
print(f"Parsed Data: Integer={parsed_data[0]}, Float={parsed_data[1]}")
# Initialize the Arduino device
arduino = Arduino(data_handler=handle_data)
```
##### Arduino Code with C++ Struct
On the Arduino, we’ll define a C++ `struct` to hold the data, then send this struct as binary data.
```cpp
// Arduino code to send a struct with an integer and a float as binary data over Serial
struct DataPacket {
int myInt;
float myFloat;
};
// Create an instance of the struct and populate it
DataPacket packet = {42, 3.14};
void setup() {
Serial.begin(9600); // Ensure this matches the baud rate in EasyCom
}
void loop() {
// Send the struct as binary data
Serial.write((byte*)&packet, sizeof(packet)); // Send entire struct as binary
delay(1000); // Send data every second
}
```
In this code:
- We define a `DataPacket` struct containing an integer (`myInt`) and a float (`myFloat`).
- `Serial.write((byte*)&packet, sizeof(packet));` sends the entire struct as a single binary transmission.
- The data format sent by Arduino matches `struct.unpack("<if", data)` on the Python side, where:
- `"<if"` specifies little-endian format: an integer (`i`) followed by a float (`f`).
This setup allows Python to parse the binary data from Arduino, resulting in correctly structured data for your application.
#### 5. Combining All Parameter Overrides
You can combine multiple overrides, specifying `port`, `baudrate`, `timeout`, and a custom `data_handler`.
```python
arduino = Arduino(
port="/dev/ttyUSB0",
baudrate=115200,
timeout=3,
data_handler=handle_data
)
```
---
### Registering a New Device at Runtime
To add a new device dynamically, use `register_device`. The example below registers a custom device `MyDevice` with a unique PID/VID, baud rate, and timeout.
```python
from easycom.devices import register_device
# Register a custom device class
MyDevice = register_device(
name="MyDevice",
pidvids=["1234:5678"],
default_baudrate=57600,
default_timeout=4
)
# Initialize and use the custom device
device = MyDevice(data_handler=handle_data)
device.write(b"Hello, MyDevice!")
device.disconnect()
```
---
## Supported Devices
EasyCom includes pre-configured support for several common USB UART devices.
| **Device** | **PID/VIDs** | **Default Baudrate** | **Default Timeout** |
|-------------------|----------------------------------|----------------------|---------------------|
| Arduino | 2341:0043, 2341:0010, 0403:6001 | 9600 | 2 |
| Raspberry Pi Pico | 2E8A:0005 | 115200 | 2 |
| Teensy | 16C0:0483, 16C0:0487 | 9600 | 2 |
| ESP32 | 10C4:EA60, 1A86:7523 | 115200 | 3 |
| STM32 | 0483:5740 | 9600 | 2 |
| CP210x | 10C4:EA60 | 115200 | 2 |
| FTDI | 0403:6001, 0403:6015 | 9600 | 2 |
| CH340 | 1A86:7523 | 9600 | 3 |
| Prolific | 067B:2303 | 9600 | 2 |
| RaspberryPi | 2E8A:000A | 115200 | 2 |
| NRF52840 | 1915:520A | 115200 | 2 |
| MCP2200 | 04D8:00DD | 9600 | 2 |
| EFM32 | 10C4:E005 | 115200 | 2 |
| STLink | 0483:374B | 9600 | 2 |
| FT232H | 0403:6015 | 3000000 | 2 |
| FX2LP | 04B4:8613 | 9600 | 2 |
| LPC11Uxx | 1FC9:009C | 115200 | 2 |
### Adding Additional Devices
You can extend this list by registering additional devices with `register_device`, as shown in the example above.
---
## Advanced Features
### Automatic Reconnection
If a device disconnects, EasyCom will attempt to reconnect automatically, simplifying communication in environments where devices are intermittently connected.
### Debug Logging
Enable detailed logging to trace communication flow and troubleshoot issues:
```python
import logging
logging.basicConfig(level=logging.DEBUG)
```
---
## Common Usage Patterns
### Continuous Data Handling
For applications requiring continuous data reading, the following setup ensures the program stays open until manually closed:
```python
from easycom.devices import Arduino
def handle_data(data):
print(f"Data Received: {data}")
arduino = Arduino(data_handler=handle_data)
try:
while True:
pass # Keep the program running to process data
except KeyboardInterrupt:
print("Disconnecting...")
arduino.disconnect()
```
### Sending Data Periodically
To send data at regular intervals, use a loop with a delay, allowing the program to handle data without blocking other operations.
```python
import time
while True:
arduino.write(b"Ping")
time.sleep(1)
```
---
## License
EasyCom is available under the **MIT License**.
---
## Contributing
Contributions are welcome! Please submit issues or pull requests on GitLab to help improve EasyCom.
---
## Resources
- **Source Code**: [GitLab Repository](https://gitlab.com/acemetrics-technologies/easycom)
- **Issue Tracker**: [Report Issues](https://gitlab.com/acemetrics-technologies/easycom/-/issues)
---
## Authors
- **Acemetrics Technologies**
[vishnu@acemetrics.com](mailto:vishnu@acemetrics.com)
---
## Summary
**EasyCom** simplifies working with USB UART devices, providing reliable, non-blocking communication, automatic port detection and reconnection, and dynamic device registration for fast, flexible interaction with serial devices.
Raw data
{
"_id": null,
"home_page": null,
"name": "easycom",
"maintainer": null,
"docs_url": null,
"requires_python": null,
"maintainer_email": null,
"keywords": "serial, communication, arduino, pico, teensy, embedded",
"author": null,
"author_email": "Acemetrics Technologies <vishnu@acemetrics.com>",
"download_url": "https://files.pythonhosted.org/packages/6f/f8/01c8ca907a35f678a33f16038dfb7af1b418d4fbcd3b7d1769f6249c5874/easycom-0.0.8.tar.gz",
"platform": null,
"description": "# EasyCom\n\n**EasyCom** is a Python library designed for **asynchronous serial communication** with USB UART devices such as **Arduino, ESP32, Raspberry Pi Pico, Teensy**, and others. With **non-blocking communication**, **automatic port detection and reconnection**, and an **easy-to-use API**, EasyCom allows you to seamlessly interact with multiple devices. It also supports the **dynamic registration of new devices** at runtime.\n\n---\n\n## Features\n\n- **Asynchronous Communication**: Uses threading to provide non-blocking read and write operations.\n- **Automatic Port Detection and Reconnection**: Matches devices using PID/VID for automatic connection and reconnection if disconnected.\n- **Pre-configured and Dynamically Registered Devices**: Built-in support for common devices, with the ability to add custom devices dynamically.\n- **Thread-safe Writes**: Queue-based data management ensures safe, consistent writes.\n- **Customizable Data Handlers**: Process incoming data using custom callback functions for maximum flexibility.\n\n---\n\n## Installation\n\nYou can install EasyCom directly with pip:\n\n```bash\npip install easycom\n```\n\n---\n\n## Getting Started\n\n### Basic Example: Arduino with Default Parameters\n\nThis example demonstrates setting up an **Arduino** device using default parameters. With **automatic port detection**, the library will attempt to connect to the first available port with matching PID/VID.\n\n```python\nfrom easycom.devices import Arduino\n\n# Define a simple callback function to handle received data\ndef handle_data(data):\n print(f\"Received: {data}\")\n\n# Initialize Arduino with automatic port detection and default settings\narduino = Arduino(data_handler=handle_data)\n\n# Keep the program running to receive data\ninput(\"Press Enter to disconnect...\")\n\n# Disconnect the Arduino\narduino.disconnect()\n```\n\n---\n\n### Overriding Parameters\n\nEasyCom allows you to override specific parameters such as `port`, `baudrate`, `timeout`, and `data_handler`. Each example below illustrates how to set these parameters.\n\n#### 1. Overriding the `port`\n\nIf the device is connected to a specific port, you can set it explicitly:\n\n```python\narduino = Arduino(port=\"/dev/ttyUSB0\", data_handler=handle_data)\n```\n\n#### 2. Overriding the `baudrate`\n\nTo customize the baud rate (e.g., 115200), set it during initialization:\n\n```python\narduino = Arduino(baudrate=115200, data_handler=handle_data)\n```\n\n#### 3. Overriding the `timeout`\n\nAdjust the timeout (in seconds) for read and write operations:\n\n```python\narduino = Arduino(timeout=5, data_handler=handle_data)\n```\n\nHere\u2019s an updated example using a `struct` in C++ on the Arduino side to send an integer and a float together as a single binary package. This structure will match the Python `struct` for decoding.\n\n---\n\n#### 4. Using a `struct`-based Data Handler\n\nIn this example, we\u2019ll send data as a structured binary package from Arduino and parse it in Python using the `struct` module. The Arduino will send an integer and a float in one structured transmission.\n\n```python\nimport struct\nfrom easycom.devices import Arduino\n\n# Define a data handler to parse binary data\ndef handle_data(data):\n # Parse data as an integer and a float\n parsed_data = struct.unpack(\"<if\", data) # \"<if\" represents little-endian int, float\n print(f\"Parsed Data: Integer={parsed_data[0]}, Float={parsed_data[1]}\")\n\n# Initialize the Arduino device\narduino = Arduino(data_handler=handle_data)\n```\n\n##### Arduino Code with C++ Struct\n\nOn the Arduino, we\u2019ll define a C++ `struct` to hold the data, then send this struct as binary data.\n\n```cpp\n// Arduino code to send a struct with an integer and a float as binary data over Serial\n\nstruct DataPacket {\n int myInt;\n float myFloat;\n};\n\n// Create an instance of the struct and populate it\nDataPacket packet = {42, 3.14};\n\nvoid setup() {\n Serial.begin(9600); // Ensure this matches the baud rate in EasyCom\n}\n\nvoid loop() {\n // Send the struct as binary data\n Serial.write((byte*)&packet, sizeof(packet)); // Send entire struct as binary\n\n delay(1000); // Send data every second\n}\n```\n\nIn this code:\n- We define a `DataPacket` struct containing an integer (`myInt`) and a float (`myFloat`).\n- `Serial.write((byte*)&packet, sizeof(packet));` sends the entire struct as a single binary transmission.\n- The data format sent by Arduino matches `struct.unpack(\"<if\", data)` on the Python side, where:\n - `\"<if\"` specifies little-endian format: an integer (`i`) followed by a float (`f`).\n\nThis setup allows Python to parse the binary data from Arduino, resulting in correctly structured data for your application.\n\n#### 5. Combining All Parameter Overrides\n\nYou can combine multiple overrides, specifying `port`, `baudrate`, `timeout`, and a custom `data_handler`.\n\n```python\narduino = Arduino(\n port=\"/dev/ttyUSB0\",\n baudrate=115200,\n timeout=3,\n data_handler=handle_data\n)\n```\n\n---\n\n### Registering a New Device at Runtime\n\nTo add a new device dynamically, use `register_device`. The example below registers a custom device `MyDevice` with a unique PID/VID, baud rate, and timeout.\n\n```python\nfrom easycom.devices import register_device\n\n# Register a custom device class\nMyDevice = register_device(\n name=\"MyDevice\",\n pidvids=[\"1234:5678\"],\n default_baudrate=57600,\n default_timeout=4\n)\n\n# Initialize and use the custom device\ndevice = MyDevice(data_handler=handle_data)\ndevice.write(b\"Hello, MyDevice!\")\ndevice.disconnect()\n```\n\n---\n\n## Supported Devices\n\nEasyCom includes pre-configured support for several common USB UART devices. \n\n| **Device** | **PID/VIDs** | **Default Baudrate** | **Default Timeout** |\n|-------------------|----------------------------------|----------------------|---------------------|\n| Arduino | 2341:0043, 2341:0010, 0403:6001 | 9600 | 2 |\n| Raspberry Pi Pico | 2E8A:0005 | 115200 | 2 |\n| Teensy | 16C0:0483, 16C0:0487 | 9600 | 2 |\n| ESP32 | 10C4:EA60, 1A86:7523 | 115200 | 3 |\n| STM32 | 0483:5740 | 9600 | 2 |\n| CP210x | 10C4:EA60 | 115200 | 2 |\n| FTDI | 0403:6001, 0403:6015 | 9600 | 2 |\n| CH340 | 1A86:7523 | 9600 | 3 |\n| Prolific | 067B:2303 | 9600 | 2 |\n| RaspberryPi | 2E8A:000A | 115200 | 2 |\n| NRF52840 | 1915:520A | 115200 | 2 |\n| MCP2200 | 04D8:00DD | 9600 | 2 |\n| EFM32 | 10C4:E005 | 115200 | 2 |\n| STLink | 0483:374B | 9600 | 2 |\n| FT232H | 0403:6015 | 3000000 | 2 |\n| FX2LP | 04B4:8613 | 9600 | 2 |\n| LPC11Uxx | 1FC9:009C | 115200 | 2 |\n\n\n### Adding Additional Devices\n\nYou can extend this list by registering additional devices with `register_device`, as shown in the example above.\n\n---\n\n## Advanced Features\n\n### Automatic Reconnection\n\nIf a device disconnects, EasyCom will attempt to reconnect automatically, simplifying communication in environments where devices are intermittently connected.\n\n### Debug Logging\n\nEnable detailed logging to trace communication flow and troubleshoot issues:\n\n```python\nimport logging\nlogging.basicConfig(level=logging.DEBUG)\n```\n\n---\n\n## Common Usage Patterns\n\n### Continuous Data Handling\n\nFor applications requiring continuous data reading, the following setup ensures the program stays open until manually closed:\n\n```python\nfrom easycom.devices import Arduino\n\ndef handle_data(data):\n print(f\"Data Received: {data}\")\n\narduino = Arduino(data_handler=handle_data)\n\ntry:\n while True:\n pass # Keep the program running to process data\nexcept KeyboardInterrupt:\n print(\"Disconnecting...\")\n arduino.disconnect()\n```\n\n### Sending Data Periodically\n\nTo send data at regular intervals, use a loop with a delay, allowing the program to handle data without blocking other operations.\n\n```python\nimport time\n\nwhile True:\n arduino.write(b\"Ping\")\n time.sleep(1)\n```\n\n---\n\n## License\n\nEasyCom is available under the **MIT License**.\n\n---\n\n## Contributing\n\nContributions are welcome! Please submit issues or pull requests on GitLab to help improve EasyCom.\n\n---\n\n## Resources\n\n- **Source Code**: [GitLab Repository](https://gitlab.com/acemetrics-technologies/easycom) \n- **Issue Tracker**: [Report Issues](https://gitlab.com/acemetrics-technologies/easycom/-/issues)\n\n---\n\n## Authors\n\n- **Acemetrics Technologies** \n [vishnu@acemetrics.com](mailto:vishnu@acemetrics.com)\n\n---\n\n## Summary\n\n**EasyCom** simplifies working with USB UART devices, providing reliable, non-blocking communication, automatic port detection and reconnection, and dynamic device registration for fast, flexible interaction with serial devices.\n",
"bugtrack_url": null,
"license": "MIT License",
"summary": "A simple library for asynchronous serial communication",
"version": "0.0.8",
"project_urls": {
"Documentation": "https://gitlab.com/acemetrics-technologies/easycom#README",
"Source": "https://gitlab.com/acemetrics-technologies/easycom",
"Tracker": "https://gitlab.com/acemetrics-technologies/easycom/-/issues"
},
"split_keywords": [
"serial",
" communication",
" arduino",
" pico",
" teensy",
" embedded"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "c1d454c0ad47e06dca55f315478ead38c03e971185690b52d592939479a457a7",
"md5": "e6202f4bba1471156769fd3cb3fac944",
"sha256": "beda248fd82301d29e1baa03e5e72813b6d090bda6ea0fc3358ae9655e5b6c02"
},
"downloads": -1,
"filename": "easycom-0.0.8-py3-none-any.whl",
"has_sig": false,
"md5_digest": "e6202f4bba1471156769fd3cb3fac944",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 8356,
"upload_time": "2024-10-31T09:22:29",
"upload_time_iso_8601": "2024-10-31T09:22:29.231364Z",
"url": "https://files.pythonhosted.org/packages/c1/d4/54c0ad47e06dca55f315478ead38c03e971185690b52d592939479a457a7/easycom-0.0.8-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "6ff801c8ca907a35f678a33f16038dfb7af1b418d4fbcd3b7d1769f6249c5874",
"md5": "b1ea1518f4ff817a9036cb4029232c94",
"sha256": "362be8fed52a8f5f69d469724a82a70260341de863d3f738cfa44181f8dcbdf2"
},
"downloads": -1,
"filename": "easycom-0.0.8.tar.gz",
"has_sig": false,
"md5_digest": "b1ea1518f4ff817a9036cb4029232c94",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 10781,
"upload_time": "2024-10-31T09:22:30",
"upload_time_iso_8601": "2024-10-31T09:22:30.434623Z",
"url": "https://files.pythonhosted.org/packages/6f/f8/01c8ca907a35f678a33f16038dfb7af1b418d4fbcd3b7d1769f6249c5874/easycom-0.0.8.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-10-31 09:22:30",
"github": false,
"gitlab": true,
"bitbucket": false,
"codeberg": false,
"gitlab_user": "acemetrics-technologies",
"gitlab_project": "easycom#README",
"lcname": "easycom"
}