This chapter provides the most essential hardware information and test commands to help you start using hardware interfaces within 5 minutes.
| Model | Serial Port 1 | Serial Port 2 | DI | DO | DO (Relay) | CAN | Bluetooth |
|---|---|---|---|---|---|---|---|
| EG5100 | RS232/485 | RS232/485 | 2 | 2 | 0 | ✓ | ✓ |
| LG5100 | RS232/485 | RS232/485 | 2 | 2 | 0 | ✗ | ✗ |
| R1520LG | RS485 | RS232 | 0 | 0 | 0 | ✗ | ✗ |
| EV8100 | RS485 | RS232 | 4 | 0 | 1 | ✓ | ✓ |
| EG5101 | RS485 | RS232 | 0 | 0 | 0 | ✗ | ✗ |
| EG5200 | RS232/422/485 | RS232/422/485 | 2 | 0 | 2 | ✗ | ✓ |
| EG5120 | RS232/485 | RS232/485 | 2 | 2 | 0 | ✗ | ✓ |
| EG3110 | RS485 (×4) | RS232 | 4 | 4 | 0 | ✓ | ✗ |
Note: "✓" means supported, "✗" means not supported. Interface quantities represent the maximum supported by the model; specific models may vary.
| Interface | Device File Path | Description |
|---|---|---|
| Serial Port 1 | /dev/ttyCOM1 | RS232/RS485 serial port |
| Serial Port 2 | /dev/ttyCOM2 | RS232/RS485 serial port |
| Digital Input 1 (DI1) | /dev/DI1 | Links to /dev/input/event* |
| Digital Output 1 (DO1) | /sys/class/leds/do1/brightness | Write 1 or 0 |
| Digital Output 2 (DO2) | /sys/class/leds/do2/brightness | Write 1 or 0 |
| Bluetooth Power | /sys/class/gpio/gpio1/value | Write 1 or 0 to power the module on/off |
| Bluetooth Serial | /dev/ttymxc* | HCI communication serial port, number varies by model |
Before testing hardware interfaces, it's recommended to complete the following environment configuration.
Use the following command to check your device model:
sudo renv get board
Example output: eg5120, eg5100, eg5200, etc.
Hardware interface operations require appropriate permissions. Two methods:
Method 1: Use sudo (Recommended for testing)
# Add sudo before each command
sudo <command>
Method 2: Add user to relevant groups (Recommended for production)
# Add current user to dialout and input groups
sudo usermod -a -G dialout,input $USER
# Re-login for changes to take effect
# Or use: newgrp dialout
If you plan to use Python for development, install relevant dependencies:
# Update package manager
sudo apt-get update
# Install serial library (for serial communication)
sudo apt-get install -y python3-serial
# Install evdev library (for digital input DI monitoring)
sudo apt-get install -y python3-evdev
Verify installation:
python3 -c "import serial; print('pyserial OK')"
python3 -c "import evdev; print('evdev OK')"
Tip: The following commands require sudo privileges or complete permission configuration per section 1.3.2.
# Set to RS485 mode, disable SDK built-in service
sudo uci set serial_port.port_setting[1].enable false
sudo uci set serial_port.port_setting[1].port_type RS485
sudo uci commit
# Set baud rate to 9600, 8 data bits, no parity, 1 stop bit
sudo stty -F /dev/ttyCOM1 9600 cs8 -parenb -cstopb
# Terminal 1: Listen on serial port
sudo cat /dev/ttyCOM1
# Terminal 2: Send data
echo "Hello" | sudo tee /dev/ttyCOM1
# Terminal 1 should display "Hello"
DI works as an input event device. Can use evtest tool for testing.
sudo apt-get update
sudo apt-get install evtest
# Monitor DI1 events
sudo evtest /dev/DI1
DO is controlled through the sysfs filesystem.
sudo sh -c 'echo 1 > /sys/class/leds/do1/brightness'
cat /sys/class/leds/do1/brightness
sudo sh -c 'echo 0 > /sys/class/leds/do1/brightness'
Please follow these steps to enable and quickly test it.
Only EG5200 needs to enable the bluetooth module, other models please skip this step!
# Enable Bluetooth module (EG5200)
sudo sh -c 'echo 1 > /sys/class/gpio/gpio1/value'
# Attach interface (EG5200)
sudo hciattach /dev/ttymxc3 qca -t120 3000000 flow
# Attach interface (EG5120/EG5100)
# sudo hciattach /dev/ttymxc3 any 115200 flow
# Attach interface (EV8100)
# sudo hciattach /dev/ttymxc1 any 115200 flow
# Activate controller
sudo hciconfig hci0 up
Note: The hciattach command varies by device model. Please refer to Chapter 5 for details.
hciconfig
# Observe if the status of hci0 in the output includes "UP RUNNING"
timeout 5 bluetoothctl scan on
Use uci commands to flexibly configure serial port working mode and parameters.
# Example: Configure COM1 to RS485 mode, baud rate 9600
# 1. Disable RobustOS built-in serial service for application exclusive use
sudo uci set serial_port.port_setting[1].enable false
# 2. Set port type
sudo uci set serial_port.port_setting[1].port_type RS485
# 3. Set serial port parameters
sudo uci set serial_port.port_setting[1].baud_rate 9600
sudo uci set serial_port.port_setting[1].data_bits 8
sudo uci set serial_port.port_setting[1].parity none
sudo uci set serial_port.port_setting[1].stop_bits 1
# 4. Commit configuration for it to take effect
sudo uci commit
Configuration Dependency: Serial port applications depend on uci configuration to set their working mode (such as RS232/RS485). When the application starts, you must ensure the relevant uci configuration has already taken effect.
Systemd Service Dependency: If your application runs as a systemd service, your service unit needs to declare it starts after router.service. This is because the router service configures the correct serial port working mode (such as RS232/RS485) based on uci configuration. Ensuring your application starts after the router service completes this configuration can avoid serial port mode errors and other issues.
For example, add After=router.service in your .service file:
[Unit]
Description=My Serial Port Application
After=router.service
[Service]
ExecStart=/path/to/your/application
[Install]
WantedBy=multi-user.target
Requires pyserial library installation.
sudo apt-get install python3-serial
#!/usr/bin/env python3
import serial
import time
try:
# Initialize serial port
ser = serial.Serial(
port='/dev/ttyCOM1',
baudrate=115200,
timeout=1
)
print(f"Serial port {ser.port} opened.")
# Send data
message = b"Hello from Python!\n"
ser.write(message)
print(f"Sent: {message.decode()}")
# Receive data
time.sleep(0.5)
if ser.in_waiting > 0:
response = ser.read(ser.in_waiting)
print(f"Received: {response.decode(errors='ignore')}")
except serial.SerialException as e:
print(f"Error: {e}. Please run with sudo or check permissions.")
finally:
if 'ser' in locals() and ser.is_open:
ser.close()
print("Serial port closed.")
DI is managed through Linux's input event subsystem. When DI state changes (such as high-low level transition), the system generates an input event. Applications capture these events by reading the corresponding device file (such as /dev/DI1).
Requires evdev library installation.
sudo apt-get install python3-evdev
#!/usr/bin/env python3
import evdev
try:
# /dev/DI1 here is a symbolic link, actually pointing to /dev/input/eventX
device = evdev.InputDevice('/dev/DI1')
print(f"Monitoring DI device: {device.name}")
for event in device.read_loop():
# We only care about key/switch type events
if event.type == evdev.ecodes.EV_KEY:
key_event = evdev.categorize(event)
state = "ON (Pressed)" if key_event.keystate == 1 else "OFF (Released)"
print(f"DI Event: {key_event.keycode} is {state}")
except FileNotFoundError:
print("Error: DI device not found. Check /dev/DI1.")
except PermissionError:
print("Error: Permission denied. Please run with sudo.")
except Exception as e:
print(f"An error occurred: {e}")
DO is controlled through Linux's sysfs virtual filesystem, abstracted as LED devices. The core of controlling DO is writing values to its corresponding brightness file.
Path: /sys/class/leds/doX/brightness (X is DO number)
Values:
0: Turn off DO
1: Turn on DO
Note: The DO hardware implementation may vary across device models, being either open-drain output or relay output. Refer to the hardware manual for details.
This is the most direct testing and control method.
# Turn on DO1
sudo sh -c 'echo 1 > /sys/class/leds/do1/brightness'
# Turn off DO1
sudo sh -c 'echo 0 > /sys/class/leds/do1/brightness'
# Check DO1 status
cat /sys/class/leds/do1/brightness
#!/usr/bin/env python3
import time
import os
class DOController:
def __init__(self, do_num):
self.path = f"/sys/class/leds/do{do_num}/brightness"
if not os.path.exists(self.path):
raise FileNotFoundError(f"DO{do_num} device not found at {self.path}")
def set_state(self, state):
"""
Sets the state of the DO.
:param state: True for ON, False for OFF.
"""
try:
with open(self.path, 'w') as f:
f.write("1" if state else "0")
except PermissionError:
print("Permission denied. Please run with sudo.")
raise
except Exception as e:
print(f"Failed to set DO state: {e}")
raise
def on(self):
self.set_state(True)
def off(self):
self.set_state(False)
# --- Main execution ---
if __name__ == "__main__":
try:
do1 = DOController(1)
print("Turning DO1 ON")
do1.on()
time.sleep(2)
print("Turning DO1 OFF")
do1.off()
time.sleep(2)
print("Blinking DO1 5 times")
for _ in range(5):
do1.on()
time.sleep(0.3)
do1.off()
time.sleep(0.3)
except (FileNotFoundError, PermissionError) as e:
print(f"Error: {e}")
The Bluetooth functionality on the RobustOS Pro platform is managed through the BlueZ protocol stack. Its hardware communication relies on a UART serial port (HCI interface), and the power is controlled by a specific GPIO pin. Developers primarily interact with the Bluetooth service through command-line tools such as bluetoothctl, hcitool, and gatttool.
bluetoothctl: The recommended official interactive tool, offering the most comprehensive features, including scanning, pairing, and connecting.
gatttool: Used for connecting to Bluetooth Low Energy (BLE) devices to perform GATT service discovery, characteristic value read/write operations, etc.
hciconfig: Used for configuring HCI interfaces, such as enabling/disabling devices, checking status, etc.
EG5200's Bluetooth functionality needs to be enabled before it can be used. Use the following command to enable the Bluetooth module. This operation requires root privileges.
# Enable the Bluetooth module
sudo sh -c 'echo 1 > /sys/class/gpio/gpio1/value'
# Verify (should output 1)
cat /sys/class/gpio/gpio1/value
Note: Only EG5200 devices need to enable the Bluetooth module. Do not execute this command on other devices!
After powering on, you need to use the hciattach tool to bind the Bluetooth serial port to the BlueZ stack, creating the hci0 interface. Please select the command corresponding to your device model:
EG5200:
sudo hciattach /dev/ttymxc3 qca -t120 3000000 flow
EG5120 / EG5100:
sudo hciattach /dev/ttymxc3 any 115200 flow
EV8100:
sudo hciattach /dev/ttymxc1 any 115200 flow
After creating the interface, activate it using hciconfig.
sudo hciconfig hci0 up
Execute the following command. If you see the hci0 device and its status is UP RUNNING, the Bluetooth module has been successfully enabled.
hciconfig
Use the bluetoothctl tool to scan.
# Start the interactive tool
bluetoothctl
After entering interactive mode, execute:
# 1. Turn on Bluetooth power
power on
# 2. Start scanning
scan on
# ...wait for scan results...
# 3. Stop scanning
scan off
# 4. Exit
exit
Quick scan for 5 seconds:
timeout 5 bluetoothctl scan on
gatttool is a powerful tool for debugging BLE devices. Below is the basic process for connecting to a device and reading/writing data.
Note: BLE devices have public and random address types. You may need to use the -t random parameter when connecting.
sudo gatttool -b <MAC_address> -t random --primary
sudo gatttool -b <MAC_address> -t random --characteristics
sudo gatttool -b <MAC_address> -t random --char-read -a <handle>
# Example: Write "Hello" (HEX: 48656c6c6f)
sudo gatttool -b <MAC_address> -t random --char-write-req -a <handle> -n 48656c6c6f
The most direct way to interact with Bluetooth devices in Python is by calling the system's built-in bluez toolset. The example below shows how to wrap bluetoothctl and gatttool commands using Python's subprocess module to programmatically scan for BLE devices and read/write characteristic values.
Example Code (ble_controller.py)
#!/usr/bin/env python3
import subprocess
import time
import re
def run_command(command, timeout=15):
"""
Executes a shell command and returns its output.
"""
try:
result = subprocess.run(
command,
shell=True,
capture_output=True,
text=True,
check=True,
timeout=timeout
)
return result.stdout.strip()
except subprocess.CalledProcessError as e:
print(f"Command failed: {command}")
print(f"Error: {e.stderr.strip()}")
return None
except subprocess.TimeoutExpired:
print(f"Command timed out: {command}")
return None
def ble_scan(duration=5):
"""
Scans for BLE devices using bluetoothctl.
"""
print(f"Scanning for BLE devices ({duration} seconds)...")
devices = {}
try:
# bluetoothctl is an interactive tool and needs special handling
child = subprocess.Popen(
['bluetoothctl'],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True
)
child.stdin.write('scan on\n')
child.stdin.flush()
time.sleep(duration)
child.stdin.write('scan off\n')
child.stdin.flush()
time.sleep(0.5) # Wait for command response
child.terminate()
stdout, stderr = child.communicate()
# Parse scan results
mac_regex = r"Device ([0-9A-F:]{17})"
for line in stdout.split('\n'):
match = re.search(mac_regex, line)
if match:
mac = match.group(1)
name = line[line.find(mac) + len(mac):].strip()
devices[mac] = name # Use a dictionary to avoid duplicates
print("Scan complete.")
return list(devices.items())
except Exception as e:
print(f"An error occurred during scanning: {e}")
return []
def gatt_read(mac, handle, addr_type="public"):
"""
Reads a characteristic value using gatttool.
"""
print(f"Reading handle {handle} from {mac}...")
addr_param = f"-t {addr_type}" if addr_type == "random" else ""
command = f"sudo gatttool -b {mac} {addr_param} --char-read -a {handle}"
output = run_command(command)
if output and "value/descriptor:" in output:
try:
value_hex = output.split(':')[1].strip().replace(' ', '')
value_ascii = bytes.fromhex(value_hex).decode('utf-8', errors='ignore')
print(f"Read successful -> Hex: {value_hex}, ASCII: '{value_ascii}'")
return value_hex
except (IndexError, ValueError) as e:
print(f"Failed to parse gatttool output: {output}, Error: {e}")
else:
print("Read failed.")
return None
def gatt_write(mac, handle, value_hex, addr_type="public"):
"""
Writes a characteristic value using gatttool.
"""
print(f"Writing {value_hex} to handle {handle} on {mac}...")
addr_param = f"-t {addr_type}" if addr_type == "random" else ""
command = f"sudo gatttool -b {mac} {addr_param} --char-write-req -a {handle} -n {value_hex}"
output = run_command(command)
if output and "successfully" in output:
print("Write successful.")
return True
print("Write failed.")
return False
# --- Main execution ---
if __name__ == "__main__":
# 1. Scan for devices
found_devices = ble_scan(5)
if not found_devices:
print("No devices found.")
else:
print("\nFound devices:")
for i, (mac, name) in enumerate(found_devices):
print(f" {i}: MAC: {mac}, Name: {name}")
# --- Note: The following is a read/write demo. Please replace with your own device information. ---
# In a real application, you should select your target device from the scan results.
# Example device information (Please modify!)
TARGET_MAC = "58:9E:35:ED:FD:B3" # Replace with your BLE device MAC address
TARGET_ADDR_TYPE = "random" # Change to "public" if not a random address
# Characteristic handles (Please modify!)
# You need to find your device's handles using `gatttool --characteristics`
READ_HANDLE = "0x0016" # Example: handle for device name
WRITE_HANDLE = "0x0031" # Example: a writable characteristic handle
print(f"\n--- Starting read/write test for device {TARGET_MAC} ---")
# 2. Read characteristic
gatt_read(TARGET_MAC, READ_HANDLE, addr_type=TARGET_ADDR_TYPE)
time.sleep(1)
# 3. Write characteristic
# "Hello" in Hex is 48656c6c6f
hello_hex = "48656c6c6f"
gatt_write(TARGET_MAC, WRITE_HANDLE, hello_hex, addr_type=TARGET_ADDR_TYPE)
| Model | CPU | Architecture | Total Flash Capacity | Total RAM Capacity |
|---|---|---|---|---|
| EG5100 | i.MX 6ULL | ARMv7 (armhf) | 4GB/8GB | 1GB |
| LG5100 | i.MX 6ULL | ARMv7 (armhf) | 8GB | 1GB |
| R1520LG | i.MX 6ULL | ARMv7 (armhf) | 8GB | 512MB |
| EV8100 | i.MX 6ULL | ARMv7 (armhf) | 8GB | 512MB |
| EG5101 | i.MX 6ULL | ARMv7 (armhf) | 8GB | 512MB/1GB |
| EG5200 | i.MX 8M Plus | ARMv8 (arm64) | 32GB/64GB | 4GB/8GB |
| EG5120 | i.MX 8M Plus | ARMv8 (arm64) | 16GB | 2GB/4GB/8GB |
| EG3110 | RK3562 | ARMv8 (arm64) | 8GB/64GB | 512MB/2GB/8GB |
Note: Actual available capacity varies depending on system version, pre-installed software, and configuration. Use df -h / to check actual available storage, use free -h to check actual available memory.
| Interface Type | Device File | Description |
|---|---|---|
| Serial Communication | ||
| Serial Port 1 | /dev/ttyCOM1 | RS232/RS485 serial port |
| Serial Port 2 | /dev/ttyCOM2 | RS232/RS485 serial port |
| GPS Serial Port | /dev/ttyGPS | GPS data port (optional) |
| Digital I/O | ||
| Digital Input 1 | /dev/DI1 | Digital input port |
| Digital Input 2 | /dev/DI2 | Digital input port |
| Digital Output 1 | /sys/class/leds/do1/ | Digital output port |
| Digital Output 2 | /sys/class/leds/do2/ | Digital output port |
| Storage Devices | ||
| USB Mount Point | /mnt/usb | USB disk mount point |
| Wireless Communication | ||
| Bluetooth Serial | /dev/ttymxc3 | Bluetooth device serial port (optional) |
| Network Interface | ||
| CAN Interface | can0 | ip link set can0 up type can bitrate 12500 |
| Interface Type | Device File | Description |
|---|---|---|
| Serial Communication | ||
| Serial Port 1 | /dev/ttyCOM1 | RS232/RS485 serial port |
| Serial Port 2 | /dev/ttyCOM2 | RS232/RS485 serial port |
| GPS Serial Port | /dev/ttyGPS | GPS data port (optional) |
| Digital I/O | ||
| Digital Input 1 | /dev/DI1 | Digital input port |
| Digital Input 2 | /dev/DI2 | Digital input port |
| Digital Output 1 | /sys/class/leds/do1/ | Digital output port |
| Digital Output 2 | /sys/class/leds/do2/ | Digital output port |
| Storage Devices | ||
| USB Mount Point | /mnt/usb | USB disk mount point |
| Wireless Communication | ||
| LoRa SPI | /dev/spidev1.0 | LoRa device SPI interface |
| Interface Type | Device File | Description |
|---|---|---|
| Serial Communication | ||
| Serial Port 1 | /dev/ttyCOM1 | RS485 serial port |
| Serial Port 2 | /dev/ttyCOM2 | RS232 serial port |
| Storage Devices | ||
| USB Mount Point | /mnt/usb | USB disk mount point |
| Wireless Communication | ||
| LoRa SPI | /dev/spidev0.0 | LoRa device SPI interface |
| Interface Type | Device File | Description |
|---|---|---|
| Serial Communication | ||
| Serial Port 1 | /dev/ttyCOM1 | RS485 serial port |
| Serial Port 2 | /dev/ttyCOM2 | RS232 serial port |
| Digital I/O | ||
| Digital Input 1 | /dev/DI1 | Digital input port |
| Digital Input 2 | /dev/DI2 | Digital input port |
| Digital Input 3 | /dev/DI3 | Digital input port |
| Digital Input 4 | /dev/DI4 | Digital input port |
| Storage Devices | ||
| USB Mount Point | /mnt/usb | USB disk mount point |
| Wireless Communication | ||
| Bluetooth Serial | /dev/ttymxc1 | Bluetooth device serial port (optional) |
| Network Interface | ||
| CAN Interface | can0 | ip link set can0 up type can bitrate 12500 |
| Interface Type | Device File | Description |
|---|---|---|
| Serial Communication | ||
| Serial Port 1 | /dev/ttyCOM1 | RS485 serial port |
| Serial Port 2 | /dev/ttyCOM2 | RS232 serial port |
| Storage Devices | ||
| USB Mount Point | /mnt/usb | USB disk mount point |
| Interface Type | Device File | Description |
|---|---|---|
| Serial Communication | ||
| Serial Port 1 | /dev/ttyCOM1 | RS232/RS485 serial port |
| Serial Port 2 | /dev/ttyCOM2 | RS232/RS485 serial port |
| GPS Serial Port | /dev/ttyGPS | GPS data port (optional) |
| Digital I/O | ||
| Digital Input 1 | /dev/DI1 | Digital input port |
| Digital Input 2 | /dev/DI2 | Digital input port |
| Digital Output 1 | /sys/class/leds/do1/ | Digital output port |
| Digital Output 2 | /sys/class/leds/do2/ | Digital output port |
| Storage Devices | ||
| USB Mount Point | /mnt/usb | USB disk mount point |
| Wireless Communication | ||
| Bluetooth Serial | /dev/ttymxc3 | Bluetooth device serial port (optional) |
| External Storage | ||
| SD Card Device | /dev/mmcblk0 | SD card device (optional) |
| Interface Type | Device File | Description |
|---|---|---|
| Serial Communication | ||
| Serial Port 1 | /dev/ttyCOM1 | RS232/RS422/RS485 serial port |
| Serial Port 2 | /dev/ttyCOM2 | RS232/RS422/RS485 serial port |
| GPS Serial Port | /dev/ttyGPS | GPS data port (optional) |
| Digital I/O | ||
| Digital Input 1 | /dev/DI1 | Digital input port |
| Digital Input 2 | /dev/DI2 | Digital input port |
| Storage Devices | ||
| USB Mount Point | /mnt/usb | USB disk mount point |
| Wireless Communication | ||
| Bluetooth Serial | /dev/ttymxc3 | Bluetooth device serial port (optional) |
| Bluetooth Enable | /sys/class/gpio/gpio1/value | Controls module enable via the value file |
| External Storage | ||
| SD Card Device | /dev/mmcblk0 | SD card device (optional) |
| Interface Type | Device File | Description |
|---|---|---|
| Serial Communication | ||
| Serial Port 1 | /dev/ttyCOM1 | RS485 serial port (optional) |
| Serial Port 2 | /dev/ttyCOM2 | RS485 serial port (optional) |
| Serial Port 3 | /dev/ttyCOM3 | RS485 serial port (optional) |
| Serial Port 4 | /dev/ttyCOM4 | RS485 serial port (optional) |
| Serial Port 5 | /dev/ttyCOM5 | RS232 serial port (optional) |
| Digital I/O | ||
| Digital Input 1 | /dev/DI1 | Digital input port (optional) |
| Digital Input 2 | /dev/DI2 | Digital input port (optional) |
| Digital Input 3 | /dev/DI3 | Digital input port (optional) |
| Digital Input 4 | /dev/DI4 | Digital input port (optional) |
| Digital Output 1 | /sys/class/leds/do1/ | Digital output port (optional) |
| Digital Output 2 | /sys/class/leds/do2/ | Digital output port (optional) |
| Digital Output 3 | /sys/class/leds/do3/ | Digital output port (optional) |
| Digital Output 4 | /sys/class/leds/do4/ | Digital output port (optional) |
| Storage Devices | ||
| USB Mount Point | /mnt/usb | USB disk mount point |
| Network Interface | ||
| CAN Interface | /sys/class/net/can0/ | CAN network interface (optional) |
| Switch Interface | /sys/class/net/switch0 | Network switch port |
☐ Permissions: Is the user running the program in the dialout group? Try running with sudo.
☐ Device Exists: Can you see the device with ls -la /dev/ttyCOM*?
☐ Parameters Match: Do baud rate, data bits, stop bits, and parity match the peripheral device?
☐ Correct Mode: Is RS232/RS485 mode correctly set via uci commands?
☐ Physical Connection: Are TX/RX reversed? Do RS485 A/B lines correspond? Is GND common?
☐ Loopback Test: Short TX/RX, send data to see if received, to rule out external device issues.
☐ Permissions: Are you executing with sudo or root privileges?
☐ Device Exists: Can you see devices with ls -la /dev/DI* and ls -la /sys/class/leds/do*?
☐ DI Events: Does sudo evtest /dev/DI1 show event responses?
☐ DO Control: Does sudo sh -c 'echo 1 > ... light up external LED or drive relay?
☐ External Circuit: Check if external wiring, power supply, and load are normal.
☐ Permissions: Are you running Bluetooth-related commands with sudo?
☐ Enable (EG5200): If using EG5200, is the output of cat /sys/class/gpio/gpio1/value equal to 1?
☐ Service: Is the status of systemctl status bluetooth active (running)?
☐ Interface: Does the output of the hciconfig command include the UP RUNNING status?
☐ Connection: When connecting to a BLE device with a random address type, did you add the -t random parameter to the gatttool command?