Controlling Router Peripherals
Digital Input/Output Interfaces
io Utility
The io utility allows controlling binary outputs and reading binary/analog/counter inputs from the command line.
Caution
Binary I/O often uses inverse logic. Active physical input (e.g., high voltage) might read as logical 0. Setting output to 1 might result in a low voltage physically. Always consult the specific router model's User Manual for I/O logic details.
Synopsis
io get or io set
| Command | Description |
|---|---|
get | Reads the state of input `` (e.g., bin0, an1, cnt1). |
set | Sets the state of output to (typically 0 or 1). |
io Utility Commands
Pin Names
Refer to the router's User Manual for available pin names (bin0, out0, an1, cnt1, etc.), which depend on the model and installed expansion modules (e.g., XC-CNT).
Examples
io set out0 1: Sets binary output OUT0 to state 1.io get bin0: Reads the state of binary input BIN0. Check exit code$?(0 or 1).io get an1: Reads the value of analog input AN1 (if XC-CNT present).io get cnt1: Reads the value of counter input CNT1 (if XC-CNT present).
Activate Binary Output via SMS
Tips
See Section on the custom SMS handling mechanism using /var/scripts/sms. Ensure this mechanism is enabled in the router's SMS configuration.
This example demonstrates the implementation of a new SMS command, "IMPULSE", which activates binary output OUT0 (a GPIO pin) for 5 seconds. It is triggered when an SMS containing the text "IMPULSE" is received by the router. The command is processed only if the sender is authorized.
Authorization Logic Options
The example script includes two common ways to authorize the sender:
- Check the flag passed by the system (
$1): If the sender's number is listed in the Phone Number x fields in the router's SMS settings GUI,$1will be1. - Hardcode specific phone number(s) directly in the script and compare against the sender's number (
$2).
The example uses a combination (OR logic). Adjust the authorization check as needed for your requirements.
Startup Script
This script creates the /var/scripts/sms handler script in RAM at boot time.
#!/bin/sh
# Create the SMS handler script in RAM
cat > /var/scripts/sms ` command that signifies the pin is in its active state (typically 0 for Advantech routers).
- **Reading Input Pin State (`get_input_pin_state` function):**
- This function is responsible for querying the current state of the specified binary input pin.
- It constructs and executes the router's command `io get ` using `subprocess.run()`.
- The function returns the exit code of the `io get` command. For Advantech router binary inputs, an exit code of 0 usually indicates an active state, and 1 indicates an inactive state.
- It includes error handling: if the `io` command is not found or another error occurs during execution, it prints an error message to standard error (`sys.stderr`) and returns `None`.
- **Sending Email Notification (`send_email_notification` function):**
- This function handles the sending of email alerts.
- It takes the recipient email address and the email subject as arguments.
- It forms and executes the router's command `email -t -s ` using `subprocess.run()`. This relies on the router having a configured `email` utility.
- Error handling is included to catch issues such as the `email` command not being found or the command failing (e.g., mail server misconfiguration), printing error messages to `sys.stderr`.
- **Main Monitoring Loop (`main` function):**
- A variable `old_state` is initialized to `None`, representing an unknown initial state of the input pin.
- A startup message is printed to `sys.stderr`, indicating which pin is being monitored and the polling interval.
- The script enters an infinite loop (`while True:`) to continuously monitor the input pin. This loop can be interrupted by pressing Ctrl+C (`KeyboardInterrupt`).
- **Inside the loop:**
- `current_state = get_input_pin_state(INPUT_PIN)`: The current state of the input pin is read.
- `if current_state is not None:`: The script only proceeds if the pin state was successfully read (i.e., `io get` didn't fail).
- `if current_state != old_state:`: This condition checks if the pin's state has changed since the last check. This is key to sending an email only upon a state transition.
- `if current_state == ACTIVE_STATE_EXIT_CODE:`: If the state has changed *and* the new state is the defined active state (e.g., exit code 0), an informational message is printed to `sys.stderr`, and the `send_email_notification` function is called.
- `old_state = current_state`: After processing any change, `old_state` is updated to the `current_state` for the next iteration. This ensures that an email is sent only once when the pin transitions to active, and not repeatedly if it remains active.
- `time.sleep(POLL_INTERVAL_SECONDS)`: The script pauses for the specified interval before repeating the loop.
- The main loop is wrapped in a `try...except KeyboardInterrupt` block to allow the user to stop the script gracefully. A general `except Exception` block is also present to catch other unexpected errors during the loop's execution.
- **Script Execution Entry Point:**
- The standard `if __name__ == "__main__":` construct ensures that the `main()` function is called only when the script is executed directly.
**Script Testing**
Below is the console output, displaying the script's creation (using `vi`) and its testing.
```bash
/var/scripts # vi send_email.py
(...create and save sripty with pi...)
/var/scripts # chmod +x send_email.py
/var/scripts # ./send_email.py
Monitoring bin0 every 1 second(s). Press Ctrl+C to stop.
Input bin0 transitioned to ACTIVE. Sending email.
Email notification sent to x.y@advantech.com with subject: BIN0 is active
^C
Monitoring stopped by user.
/var/scripts #Send SNMP Trap on Binary Input State Change
Tips
Make sure you have correctly configured the SNMP manager in Configuration → Services → SNMP.
This script sends an SNMP trap to the configured SNMP manager whenever the state of binary input BIN0 (a GPIO pin) changes (either becoming active or inactive). It continuously monitors the input state.
Startup Script
#!/bin/sh
# Specify SNMP manager address
SNMP_MANAGER=192.168.1.2
while true
do
io get bin0
VAL=$?
if [ "$VAL" != "$OLD" ]; then
snmptrap $SNMP_MANAGER 1.3.6.1.4.1.30140.2.3.1.0 u $VAL
OLD=$VAL
fi
sleep 1
doneHow It Works
- The script defines the IP address of the SNMP manager (
SNMP_MANAGER). - It enters an infinite loop (
while true) for continuous monitoring. - Inside the loop:
io get bin0: Reads the current state of binary input BIN0.VAL=$?: Captures the exit status (state: 0=active, 1=inactive).if [ "$VAL" != "$OLD" ]: Checks if the state has changed since the last check.- If the state has changed:
snmptrap $SNMP_MANAGER 1.3.6.1.4.1.30140.2.3.1.0 u $VAL: Sends an SNMP trap.$SNMP_MANAGER: The destination IP address.1.3.6.1.4.1.30140.2.3.1.0: The specific OID (Object Identifier) being sent. This OID represents the state ofbin0.u: Specifies the data type of the value being sent as Unsigned32.$VAL: The current state (0 or 1) of the input pin.
OLD=$VAL: Updates the stored state for the next comparison.
sleep 1: Pauses for 1 second before the next check.
- This script sends an SNMP trap containing the specific OID and the new state (0 or 1) every time the binary input changes state.
Serial Interfaces
This chapter provides an overview of using serial interfaces on Advantech routers. It covers identifying available serial ports, command-line utilities for their configuration and use, and an example of interacting with a serial port using a Python script packaged as a Router App via the Advantech ModulesSDK.
Identifying Serial Interfaces
Advantech routers support various serial interface standards, with RS-232 and RS-485 being common. The specific interfaces available (e.g., physical DB9 ports, terminal blocks, or those provided via expansion modules like PORT1/PORT2) and their parameters (e.g., dedicated ttyS* device, configurable modes) vary by router model. Always consult the manual for your specific router model for detailed specifications.
To list available serial device nodes on a router, you can use the following console command. The presence of a device node in /dev/ (e.g., /dev/ttyS0, /dev/ttyUSB0) indicates that the kernel recognizes a serial interface. However, this does not always mean a physical port is directly accessible on the device exterior without additional configuration or hardware. Serial interfaces can also be provided by USB-to-UART converters, which typically appear as /dev/ttyUSB* devices.
~ # ls -l /dev/tty*
crw-rw-rw- 1 root root 5, 0 Jan 1 1970 /dev/tty
crw------- 1 root root 249, 0 Jan 1 1970 /dev/ttyS0
crw-rw---- 1 root daemons 249, 1 Jan 1 1970 /dev/ttyS1
crw-rw---- 1 root daemons 249, 5 Jan 1 1970 /dev/ttyS5
crw-rw---- 1 root daemons 188, 0 May 26 06:56 /dev/ttyUSB0
crw-rw---- 1 root daemons 188, 1 May 26 06:56 /dev/ttyUSB1
% ... (other ttyUSB* devices if present) ...Serial port configuration (baud rate, data bits, parity, stop bits) can be managed using command-line utilities or programmatically, as detailed in the following sections.
Command-Line Utilities for Serial Ports
Two common utilities for managing serial ports from the command line are stty and portd.
stty - Set and Print Terminal Line Settings
The stty program is used to change and print terminal line settings, including those for serial ports. It allows you to configure parameters like baud rate, character size, parity, stop bits, and flow control.
Synopsis:
stty [-a|g] [-F DEVICE] [SETTING]...
Common Options:
| Option | Description |
|---|---|
-F DEVICE | Open and use the specified DEVICE instead of standard input. |
-a | Print all current settings in human-readable form. |
-g | Print all current settings in a stty-readable form (can be used to save and restore settings). |
[SETTING]... | One or more settings to apply. Common settings include:- ``: Set speed to N bits per second (e.g., 115200).- cs: Set character size to N bits (cs7 or cs8).- cstopb: Use two stop bits (prefix with - for one stop bit, e.g., -cstopb).- parenb: Enable parity generation/detection.- -parodd: Use even parity (if parenb is set). parodd for odd parity.- -inpck: Disable input parity checking.- ignpar: Ignore characters with parity errors.- [-]raw: Enable (or disable with -) raw input. Disables most input processing.- [-]echo: Enable (or disable) echoing of input characters.- [-]crtscts: Enable (or disable) RTS/CTS hardware flow control.- [-]ixon: Enable (or disable) XON/XOFF software flow control.For a full list, consult the stty man page or BusyBox documentation. |
Common stty Options and Settings.
Examples:
To display all current settings for the serial port /dev/ttyS0:
stty -F /dev/ttyS0 -aTo display only the current speed of /dev/ttyS1:
stty -F /dev/ttyS1 speedTo configure /dev/ttyS0 to 115200 bps, 8 data bits, no parity, 1 stop bit (8N1), and enable raw mode:
stty -F /dev/ttyS0 115200 cs8 -cstopb -parenb rawportd - Serial Port to TCP/UDP Redirector
The portd daemon is a utility that provides transparent data transfer between a serial line and a TCP or UDP network connection. It can operate either as a server (listening for incoming network connections and forwarding data to/from the serial port) or as a client (connecting to a remote network host and forwarding data). This is often used for "Serial-to-Ethernet" or "Serial-over-IP" applications.
Synopsis:
portd -c [-b ] [-d ] [-p ] [-s ]
[-l ] [-4] [-h ] [-o ] -t
[-k ] [-i ] [-j ]
[-n ] [-r ] [-u user] [-x] [-z] [-f]
Supported Options:
| Option | Description |
|---|---|
-c | Required. Serial line device (e.g., /dev/ttyS0). |
-b | Baud rate (e.g., 115200). Default typically 9600. |
-d | Number of data bits (7 or 8). Default typically 8. |
-p | Parity: none, even, odd. Default typically none. |
-s | Number of stop bits (1 or 2). Default typically 1. |
-l | Data split timeout in milliseconds. If no data arrives from the serial port for this timeout, buffered data is sent over the network. Default typically 50. |
-4 | Forced detection for RS-485 on an Expansion Port. (Advantech-specific functionality). |
-h | Remote hostname or IP address to connect to (client mode). If not specified, portd runs in server mode. |
-o | Network protocol: tcp or udp. |
-t | Required. TCP or UDP port number. |
-k | TCP Keepalive: Time (seconds) of inactivity before sending the first keepalive probe. Default: disabled. |
-i | TCP Keepalive: Interval (seconds) between subsequent keepalive probes. (Often named `` in help). |
-j | Inactivity timeout in seconds. If no data is transferred on the network connection for this period, the connection might be closed. (Often named `` in help). |
-n | When acting as a server and a connection limit is reached (e.g., typically 1 client by default if -N is not supported or set), this option might control how new incoming connection attempts are handled (e.g., reject immediately). The exact behavior should be verified. |
-r | TCP Keepalive: Number of unacknowledged probes before considering the connection dead. |
-u | Run portd as a specified user after starting (drops root privileges if started as root). |
-x | Use CD (Carrier Detect) line as an indicator of TCP connection status (server mode). |
-z | Use DTR (Data Terminal Ready) line to control/reflect TCP connection status (server mode). |
-f | Enable flow control. The type of flow control (hardware/software) might be auto-detected or a default. For specific control (e.g., RTS/CTS vs XON/XOFF), underlying system settings via stty might be needed if portd doesn't offer finer granularity. |
Supported portd options based on router's help output.
Examples:
To run portd as a TCP server on port 1000, redirecting data to/from /dev/ttyS0 configured at 115200 bps, 8 data bits, no parity, 1 stop bit, and with flow control enabled, running it in the background:
portd -c /dev/ttyS0 -b 115200 -d 8 -p none -s 1 -f -o tcp -t 1000 &To run portd as a TCP client, connecting to 192.168.1.100 on port 2000, forwarding data from /dev/ttyS1 (9600 bps, 8N1), and setting an inactivity timeout of 300 seconds:
portd -c /dev/ttyS1 -b 9600 -h 192.168.1.100 -o tcp -t 2000 -j 300 &Scripting Serial Communication with the um Python Module
This example demonstrates how to use the Advantech um Python module to communicate over a serial port (e.g., /dev/ttyS0) on the router. The Python script will be packaged as a Router App using the ModulesSDK.
Caution
To run Python scripts on the router, the Python 3 or Python 3 Lite Router App must be installed from the router's web interface (Customization → Router Apps) or be part of the firmware.
Step 1: Writing the Python Script
We will create a simple Python script named serial_um_example.py. This script will open /dev/ttyS0, send a command, attempt to read a response, and then print the response. For this example to fully work, a device capable of responding must be connected to /dev/ttyS0 and configured with matching serial parameters.
Source code for serial_um_example.py:
This file will be placed in ModulesSDK/modules/serial_um_example/source/serial_um_example.py.
#!/usr/bin/python3
import um
import sys # For exiting with error code
# Define serial port parameters
SERIAL_DEVICE = b"/dev/ttyS0"
BAUD_RATE = 115200
DATA_BITS = 8
PARITY = b"N" # None
STOP_BITS = 1
# Command to send and timeout for response
COMMAND_TO_SEND = b"ATI\r\n" # Example: AT command to request modem info
RESPONSE_TIMEOUT_SEC = 5
def main():
print(f"Attempting to open serial port: {SERIAL_DEVICE.decode()} at {BAUD_RATE} bps...")
fd = um.com_open(SERIAL_DEVICE, BAUD_RATE, DATA_BITS, PARITY, STOP_BITS)
if fd /bin/`). We will also omit metadata files like `name` and `version` for this basic example, though they are recommended for more complete Router Apps.
The primary file we need is our Python script itself (`serial_um_example.py`), which should be placed in the module's `source/` directory within the ModulesSDK.
#### Step 3: Preparing Makefiles for ModulesSDK Integration
The Advantech ModulesSDK uses a Makefile-based build system. To integrate our `serial_um_example` Python application:
1. **Create the module directory:** If it doesn't already exist, create a directory for your new module within the SDK. For example: `ModulesSDK/modules/serial_um_example/`.
2. **Place the Python script:** Copy or move your `serial_um_example.py` script into `ModulesSDK/modules/serial_um_example/source/serial_um_example.py`.
3. **Copy the main Makefile template:** Copy the generic module `Makefile` from `ModulesSDK/modules/template/Makefile` to your new module's directory: `ModulesSDK/modules/serial_um_example/Makefile`. This main Makefile generally handles the overall process of building the module for different platforms and creating the `.tgz` package. It usually calls the `Makefile` within the `source/` directory.
4. **Create the source Makefile:** Inside the `ModulesSDK/modules/serial_um_example/source/` directory, create a new `Makefile` with the following content. This Makefile defines how your Python script and any associated `um` module dependencies are installed into the Router App package.
**Content for `ModulesSDK/modules/serial_um_example/source/Makefile`:**
```bash
include ../../../Rules.mk
all:
@true
clean:
@true
install:
@install -d $(DESTDIR)/bin
@install -m 644 $(SDKDIR)/library/$(OBJDIR)/*.so $(DESTDIR)/bin/
@install -m 644 $(SDKDIR)/library/*.py $(DESTDIR)/bin/
@install -m 755 *.py $(DESTDIR)/bin/Resulting Directory Structure for the serial_um_example Module within SDK:
After these steps, the directory structure for your serial_um_example module within the ModulesSDK should look like this:
ModulesSDK/
|-- Rules.mk (and other root SDK files)
|-- library/ (Example location for um.py and libum.so)
| |-- um.py
| |-- v4/ (Platform-specific subdirectories)
| | `-- libum.so (or libum.v4.so)
| |-- v4i/
| | `-- libum.so
| |-- ...
|-- modules/
| |-- serial_um_example/
| | |-- source/
| | | |-- serial_um_example.py (Your Python script)
| | | `-- Makefile (Source Makefile specific to this module)
| | `-- Makefile (Main module Makefile, copied from template)
| |-- template/
| | `-- Makefile (Original template main Makefile)
| |-- ... (Other example modules)
`-- ... (Other SDK directories)Step 4: Building the Router App Package
Once the Python script and Makefiles are correctly placed within the ModulesSDK structure:
- Navigate to the SDK's root directory:
user@machine:~$ cd /path/to/your/ModulesSDK/- Build for all modules:
Often, simply running make from the root of the SDK might build all modules for all default platforms if the main SDK Makefile is structured that way.
user@machine:/ModulesSDK$ makeThe SDK's build system will invoke the Makefiles you prepared. The install target in your source/Makefile will copy serial_um_example.py, um.py, and the appropriate libum.so into the staging area. The main module Makefile will then package these files into a *.tgz archive.
Step 5: Uploading and Testing the Router App
Upload the generated *.tgz archive file for your target platform (e.g., serial_um_example.v4.tgz) to your Advantech router. This is typically done via the router's web interface, in the section Customization → Router Apps.
After the Router App is installed by the system:
- The Python script, along with
um.pyandlibum.so, should be installed into a directory under/opt/, typically/opt/serial_um_example/bin/. - Test from the router's CLI:
- Run script from any location using the full path:
/opt/serial_um_example/bin/serial_um_example.py- Observe the output. The script will attempt to communicate with
/dev/ttyS0. If a device is connected and responds to "ATI", you should see its response. Otherwise, you'll see a "No data received" message or an error if the port cannot be opened.
This example provides a basic framework for packaging a Python script that uses the um module as a Router App. For more complex applications, you might need to include more sophisticated install/uninstall scripts, manage dependencies, or handle background services with an init script.
USB Interface
Storage Access — USB Flash and SD Card
Connecting a USB device or SD card works in the standard Linux way. When you connect a USB Flash drive to the router, its device node will appear in the /dev directory. You can view details about detected devices using the dmesg command.
- USB Flash drive partitions typically appear as
/dev/sda1. You can mount them using themountcommand (e.g.,mount -t vfat /dev/sda1 /mnt). - Some USB-to-Serial converters are supported and will show up as
/dev/ttyUSB0,/dev/ttyUSB1, etc. (See Section on Supported USB Serial Converter Chips). - An SD Card inserted into the router's reader usually appears with partitions like
/dev/mmcblk0p1. You can mount it similarly (e.g.,mount -t vfat /dev/mmcblk0p1 /mnt).
Info
Firmware version 6.6.2 and later also supports the exFAT file system, so you can directly use USB flash drives and SD cards formatted in Microsoft Windows (e.g., mount -t exfat /dev/sda1 /mnt).
Mounting a USB Flash Drive Partition
To access files on a USB flash drive partition within the router's system, it must first be mounted. Follow these steps:
- Connect the USB Flash Drive: Plug the USB flash drive into the router's USB port.
- Identify the Device Partition: Run
dmesg | tailto display recent system messages. Look for lines indicating the new device name (e.g.,sda) and its partitions (e.g.,sda1). Note the partition identifier, such as/dev/sda1. - Create a Mount Point (Optional but Recommended): Create an empty directory where the filesystem will be mounted. Using
/mntis common practice.mkdir -p /mnt/usb - Mount the Partition: Use the
mountcommand to attach the partition to the mount point. The system often auto-detects the filesystem type.mount /dev/sda1 /mnt/usb - Verify Successful Mount: List mounted filesystems using
mount | grep /mnt/usbor check the contents of the mount point directory (ls /mnt/usb) to confirm access. - Unmount the Partition: Before physically removing the drive, unmount it using the mount point or device name to prevent data corruption.or
umount /mnt/usbumount /dev/sda1
Once unmounted, the USB flash drive can be safely removed. Ensure the correct device name and filesystem type (if specifying manually) are used.
Tips
If the mount command fails, double-check the device name (/dev/sda1) and try specifying the filesystem type with the -t option: mount -t vfat /dev/sda1 /mnt/usb.
Automount USB Flash Disk
Tips
This script provides a basic mechanism to automatically mount the first partition of a detected USB flash drive to /mnt/flash when inserted, and unmount it when removed. It requires firmware version 4.0.0 or later. The monitoring script should be saved to a file (e.g., /root/automount.sh) and launched via the Startup Script.
This example demonstrates how to create a background script that monitors for the presence of a USB flash drive and automatically mounts/unmounts its first partition.
Monitoring Script (automount.sh)
Save the following code into a file, for example, /root/automount.sh.
#!/bin/sh
#
LAST=0
i=0
while true
do
flsh=`cat /proc/diskstats |awk '/8\x20\x20\x20\x20\x20\x20\x201/ {print $3}'`
if [ $flsh ]; then
i=1
else
i=0
fi
if [ $LAST != $i ]; then
LAST=$i
if [ $i = 1 ]; then
echo "Mount flash disk."
if [ -d /mnt/flash ]; then
mount /dev/$flsh /mnt/flash
else
mkdir /mnt/flash
mount /dev/$flsh /mnt/flash
fi
else
echo "UMOUNT flash disk."
umount /mnt/flash
rmdir /mnt/flash
fi
fi
sleep 2
doneStartup Script
Add the following line to your Startup Script to launch the monitoring script in the background when the router boots. Ensure the path (/root/automount.sh) matches where you saved the monitoring script.
#!/bin/sh
# Launch the automount script in the background
sh /root/automount.sh &How It Works
The Startup Script simply executes the saved
automount.shscript in the background usingsh ... &.The
automount.shscript runs an infinite loop (while true).Inside the loop, it reads
/proc/diskstats, a kernel interface providing disk I/O statistics.It uses
awkto search for a line matching the pattern/ 8 1 /. This pattern specifically looks for:- A space.
- The major device number
8(commonly used for SCSI/SATA/USB block devices like/dev/sdX). - Exactly seven spaces (
\x20represents a space in the originalawkpattern). - The minor device number
1(commonly representing the first partition, e.g.,sda1).
If a matching line is found,
awkprints the third field ($3), which is the device name (e.g.,sda1).The device name is stored in the
flshvariable.if [ "$flsh" ]: This checks if theflshvariable is non-empty. If the device partition was found, the variable will contain its name (likesda1), and the condition is true, settingito 1 (detected). Otherwise,iis set to 0 (not detected). Quotes around"$flsh"prevent potential errors if the variable is empty.if [ $LAST != $i ]: The script compares the current detection state (i) with the state from the previous loop iteration (LAST). It only proceeds if the state has changed (device inserted or removed).LAST=$i: Updates the stored state for the next iteration.If state changed to 1 (Device Detected):
- Prints "Mount flash disk."
- Checks if the directory
/mnt/flashexists using[ ! -d ... ]. If it doesn't exist, it creates it usingmkdir. - Executes
mount /dev/$flsh /mnt/flashto mount the detected partition (e.g.,/dev/sda1) onto the/mnt/flashdirectory. Filesystem type is typically auto-detected.
If state changed to 0 (Device Removed/Not Detected):
- Prints "UMOUNT flash disk."
- Executes
umount /mnt/flashto unmount the filesystem. - Executes
rmdir /mnt/flashto remove the mount point directory. Note thatrmdirwill fail if the directory is not empty (e.g., if the unmount failed or files were created outside the mount).
sleep 2: The script pauses for 2 seconds before repeating the loop.
Caution
The method used to detect the USB drive by parsing /proc/diskstats for the specific pattern / 8 1 / is very basic and potentially fragile. It will likely only work for the first partition (sda1) of the first detected USB drive. It may fail if the drive uses different major/minor numbers, has multiple partitions you wish to access, or if other block devices interfere. More robust solutions often involve using udev rules or dedicated automount daemons if available on the system.
Tips
After adding the automount.sh script (e.g., to /root/) and configuring the Startup Script to launch it, reboot the router. When you insert a compatible USB flash drive, its first partition should automatically become accessible under /mnt/flash.
Supported USB Serial Converter Chips
Advantech routers include built-in kernel support (drivers) for several common USB-to-serial converter chipsets. When an adapter using one of these chips is connected, the corresponding kernel module should load automatically, and the adapter should appear as a serial device node in the /dev directory (e.g., /dev/ttyUSB0).
Supported chip families generally include:
- FTDI: FT232R, FT232H, FT2232, FT4232, FT230X, etc. (Driver:
ftdi_sio) - Silicon Labs: CP210x series (e.g., CP2101, CP2102, CP2104) (Driver:
cp210x) - Prolific: PL2303 (various versions, support might vary) (Driver:
pl2303) - CDC-ACM: Standard class for many modern USB serial devices (e.g., based on CH340/CH341 - support might depend on kernel config, some newer Arduino boards). (Driver:
cdc-acm)
When you connect a supported adapter, the corresponding kernel modules load automatically, and the device appears as /dev/ttyUSB0, /dev/ttyUSB1, etc.
You can verify this in console with: dmesg | grep -i ttyUSB
Using an Unsupported Serial Converter Chip
In some cases, you may need to use a USB-to-Serial converter whose specific Vendor ID (VID) and Product ID (PID) combination is not natively recognized by the pre-loaded kernel drivers (like ftdi_sio or pl2303), even if the underlying chip is technically supported by the driver. Every USB device is identified by these two hexadecimal numbers:
- Vendor ID (VID): Identifies the device manufacturer (e.g.,
0403for FTDI). - Product ID (PID): Identifies the specific product model (e.g.,
6001for FT232R).
Finding the VID and PID
You can discover the VID and PID of your USB device in several ways:
- On a Linux PC: Use the
lsusbcommand. The output lists connected devices with their IDs inVID:PIDformat. Note thatlsusbcommand is not available on the router itself. - On Windows: Open Device Manager, find the device (it might appear as an unknown device or under "Ports (COM & LPT)" or "Universal Serial Bus controllers"), right-click, select Properties, go to the Details tab, and choose "Hardware Ids" from the Property dropdown. Look for a string like
USB\VID_xxxx&PID_yyyy. - On the Router: Check kernel messages using
dmesgimmediately after plugging in the device. Look for lines likeusb 1-1: new full-speed USB device number X using ...and potentially lines showingidVendor=xxxx, idProduct=yyyy.
Dynamically Enabling the Device via sysfs
Once you have the VID and PID (as four-digit hexadecimal numbers without the 0x prefix) and know the appropriate kernel driver module name for the chip type (e.g., ftdi_sio, pl2303, cp210x), you can attempt to dynamically tell the driver to handle this specific VID/PID combination using the new_id interface within the sysfs filesystem:
Syntax:
echo > /sys/bus/usb-serial/drivers/ftdi_sio/new_idReplace and with the four-digit hex values (without 0x).
Example (for VID=0403, PID=d921):
echo 0403 d921 > /sys/bus/usb-serial/drivers/ftdi_sio/new_idAfter running this command, check dmesg again. If successful, you should see messages indicating the driver has claimed the device and created a serial port device node (e.g., /dev/ttyUSB0). If not, the driver might not support the underlying chip type.
Caution
This dynamic binding is temporary and will be lost on reboot. To make it persistent, this command must be executed from a Startup Script or a Router App's init script each time the router boots or the device is connected.
User LED
led Utility
The led utility provides basic command-line control over the user-controllable LED (often labeled "USR" or similar) typically found on the router's front panel.
Synopsis
led [on | off]
| Option | Description |
|---|---|
on | Turns the USR LED on (solid state). |
off | Turns the USR LED off. |
led Utility Options
Check IPsec Connection Status via LED
Tips
This script monitors the status of a specific IPsec tunnel and uses the USR LED to indicate whether the tunnel is established. It utilizes the swanctl command (part of strongSwan) and standard Linux utilities like awk and grep. The script should be saved to a file (e.g., /root/ipsec_stat.sh) and launched from the Startup Script.
This example provides a simple script to visually indicate the status of an IPsec connection using the router's USR LED. It checks the status every 5 seconds.
Monitoring Script (ipsec_stat.sh)
Save the following code into a file, for example, /root/ipsec_stat.sh. Adjust the num variable to match the IPsec connection number you want to monitor (typically 1, 2, 3, or 4, corresponding to the configuration order in the GUI).
#!/bin/sh
# ipsec_stat.sh - Monitors IPsec tunnel status and controls USR LED
num=1 # number of IPSec connection to monitor [1,2,3,4]
while true
do
# List Security Associations and filter for the desired IPsec connection
# then check if the line contains "INSTALLED"
/usr/libexec/ipsec/swanctl --list-sas | awk "/ipsec$num/" | grep INSTALLED
sts=$? # Capture the exit status of grep (0 if INSTALLED found, non-zero otherwise)
# Control USR LED based on the status
if [ "$sts" = "0" ]; then
led on # Turn LED ON if tunnel SA is INSTALLED
else
led off # Turn LED OFF otherwise
fi
# Wait before next check
sleep 5
doneStartup Script
Add the following line to your Startup Script (Configuration → Scripts → Startup Script) to launch the monitoring script in the background when the router boots. Ensure the path (/root/ipsec_stat.sh) is correct.
#!/bin/sh
# Launch the IPsec status monitoring script in the background
sh /root/ipsec_stat.sh &
exit 0How It Works
- The Startup Script executes the saved
ipsec_stat.shscript in the background usingsh ... &. - The
ipsec_stat.shscript first sets a variablenumto specify which IPsec connection instance (1-4) to monitor. - It enters an infinite loop (
while true). - Inside the loop:
/usr/libexec/ipsec/swanctl --list-sas: This command lists the current IPsec Security Associations (SAs), providing detailed status information for active tunnels.| awk "/ipsec$num/": The output ofswanctlis piped toawk. This filters the lines to only include those containing the specific connection name pattern (e.g.,ipsec1ifnum=1).| grep INSTALLED: The filtered output is then piped togrepto check if the line contains the word "INSTALLED". A successfully established SA typically shows this state.sts=$?: The exit status of thegrepcommand is captured in the variablests.grepreturns 0 if it finds a match ("INSTALLED" was found for the specified tunnel), and a non-zero value otherwise.if [ "$sts" = "0" ]: The script checks if the exit status is 0.- If
stsis 0 (tunnel is installed/established), it executesled onto turn the USR LED on. - If
stsis non-zero (tunnel is not installed or the line wasn't found), it executesled offto turn the USR LED off.
- If
sleep 5: The script pauses for 5 seconds before repeating the check.
- This provides a continuous visual indication of the specified IPsec tunnel's status via the USR LED.
Tips
After creating the ipsec_stat.sh script (e.g., in /root/), setting the correct IPsec connection number in the num variable, adding the launch command to the Startup Script, and rebooting the router, the USR LED should light up when the monitored IPsec tunnel is established.
Indicate OpenVPN Status via LED
Tips
Advantech routers lack an OpenVPN "management" port, making it difficult to precisely determine if the VPN connection is fully established. However, OpenVPN supports executing scripts when the tunnel process starts (--up) and stops (--down). This example uses these scripts to control the USR LED, providing a visual indication that the OpenVPN process is running, though not necessarily that the connection is fully established and passing traffic.
This example uses simple scripts triggered by OpenVPN's start and stop events to control the router's USR LED.
Up Script (ledon.sh)
Create a file, for example /root/ledon.sh, with the following content:
#!/bin/sh
# ledon.sh - Executed by OpenVPN on --up event
led onDown Script (ledoff.sh)
Create another file, for example /root/ledoff.sh, with the following content:
#!/bin/sh
# ledoff.sh - Executed by OpenVPN on --down event
led offConfiguration
Create the two script files (
ledon.shandledoff.sh) as shown above.Make them executable:
chmod +x /root/ledon.sh /root/ledoff.shCopy these script files to a persistent location on the router (e.g.,
/root/).In the OpenVPN configuration settings within the router's web GUI (Configuration -> VPN -> OpenVPN), add the following line to the Extra Options field:
script-security 2 up /root/ledon.sh down /root/ledoff.sh
Note: Enter each option on a new line in the Extra Options field.
How It Works
- The
script-security 2option allows OpenVPN to call external scripts. It's crucial for security that this level is used, and the scripts themselves are secure. - The
up /root/ledon.shoption tells OpenVPN to execute theledon.shscript after the tunnel device (e.g.,tun0) has been successfully opened and configured. This script simply runs theled oncommand, turning the USR LED on. - The
down /root/ledoff.shoption tells OpenVPN to execute theledoff.shscript when the OpenVPN tunnel process stops or the tunnel device is closed. This script runsled off, turning the USR LED off. - This setup provides a basic visual cue: the LED is on when the OpenVPN process believes the tunnel is up, and off when it's stopped or down.
Caution
As noted, this method only indicates if the OpenVPN process has successfully executed its 'up' script. It does not guarantee that the VPN tunnel connection itself is successfully established, authenticated, or functional for passing traffic.