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 <pin> or io set <pin> <value>
| Command | Description |
|---|---|
get <pin> | Reads the state of input <pin> (e.g., bin0, an1, cnt1). |
set <pin> <value> | Sets the state of output <pin> to <value> (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 << EOF
#!/bin/sh
# Specify the authorized phone number
PHONE=+420123456789
if [ "$1" = "1" ] || [ "$2" = "$PHONE" ]; then
if [ "$3" = "IMPULSE" ]; then
io set out0 1
sleep 5
io set out0 0
fi
fi
EOFHow It Works
- The startup script creates the handler script
/var/scripts/sms. - Inside the handler script:
- It first checks for authorization:
[ "$1" = "1" ]: Is it an authorized sender?;||: Logical OR.[ "$2" = "$PHONE" ]: Is the sender's phone number hardcoded?
if [ "$3" = "IMPULSE" ]: Checks if the third parameter (the first word of the SMS text) is exactly "IMPULSE". Note: This check is case-sensitive.- If the command matches:
io set out0 1: Uses the Advantechioutility to set binary output OUT0 to state 1 (check the router manual for physical logic — often active-low).sleep 5: Pauses execution for 5 seconds.io set out0 0: Sets binary output OUT0 back to state 0 (inactive state).
- It first checks for authorization:
- This sequence effectively creates a 5-second pulse on OUT0 when an authorized SMS containing the word "IMPULSE" is received.
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 <device> [-b <baudrate>] [-d <databits>] [-p <parity>] [-s <stopbits>]
[-l <split timeout>] [-4] [-h <hostname>] [-o <proto>] -t <port>
[-k <keepalive time>] [-i <keepalive interval>] [-j <inactivity timeout>]
[-n <reject new>] [-r <keepalive probes>] [-u user] [-x] [-z] [-f]
Supported Options:
| Option | Description |
|---|---|
-c <device> | Required. Serial line device (e.g., /dev/ttyS0). |
-b <baudrate> | Baud rate (e.g., 115200). Default typically 9600. |
-d <databits> | Number of data bits (7 or 8). Default typically 8. |
-p <parity> | Parity: none, even, odd. Default typically none. |
-s <stopbits> | Number of stop bits (1 or 2). Default typically 1. |
-l <split timeout> | 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 <hostname> | Remote hostname or IP address to connect to (client mode). If not specified, portd runs in server mode. |
-o <proto> | Network protocol: tcp or udp. |
-t <port> | Required. TCP or UDP port number. |
-k <keepalive time> | TCP Keepalive: Time (seconds) of inactivity before sending the first keepalive probe. Default: disabled. |
-i <keepalive intvl> | TCP Keepalive: Interval (seconds) between subsequent keepalive probes. (Often named <keepalive interval> in help). |
-j <inactivity to> | Inactivity timeout in seconds. If no data is transferred on the network connection for this period, the connection might be closed. (Often named <inactivity timeout> in help). |
-n <reject new> | 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 <keepalive probes> | TCP Keepalive: Number of unacknowledged probes before considering the connection dead. |
-u <user> | 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 < 0:
print(f"Error: Failed to open serial port {SERIAL_DEVICE.decode()}. Error code: {fd}")
sys.exit(1)
print(f"Serial port opened successfully (fd: {fd}). Sending command...")
try:
received_data = um.com_xmit(fd, COMMAND_TO_SEND, RESPONSE_TIMEOUT_SEC)
print(f"Sent to {SERIAL_DEVICE.decode()}: {COMMAND_TO_SEND.decode(errors='replace').strip()}")
if received_data:
print(f"Received from {SERIAL_DEVICE.decode()}:")
# Print byte-by-byte hex and ASCII for detailed view if needed
# print("Hex: " + " ".join(f"{b:02x}" for b in received_data))
print(f"ASCII: {received_data.decode(errors='replace')}")
else:
print("No data received within the timeout period.")
except Exception as e:
print(f"An error occurred during serial communication: {e}")
finally:
print(f"Closing serial port (fd: {fd})...")
um.com_close(fd)
print("Serial port closed.")
if __name__ == "__main__":
main()How the Script Works
The script performs the following actions:
- Imports the necessary
ummodule (andsysfor exit codes). - Defines constants for serial port parameters, the command to send (an AT command
ATIwhich typically requests modem identification), and a timeout for waiting for a response. - The
main()function is the entry point. - It calls
um.com_open()to open and configure the specified serial port. - If opening fails (indicated by a negative file descriptor
fd), it prints an error and exits. - If successful, it calls
um.com_xmit()to send theCOMMAND_TO_SENDand wait up toRESPONSE_TIMEOUT_SECseconds for a response. - It then prints the sent command and the received data (if any). The received data is decoded from bytes to a string, replacing any non-decodable characters.
- A
try...finallyblock ensures thatum.com_close()is called to close the serial port, even if an error occurs during communication. - The standard
if __name__ == "__main__":idiom ensuresmain()is called when the script is executed directly.
Step 2: Creating the Router App Package Files (Simplified)
This step involves preparing the necessary files for the ModulesSDK to package the Python script as a Router App. For this simple command-line script, we do not need complex init, install, or uninstall scripts. The SDK's default packaging will usually place the script in a bin/ directory within the Router App's installation path (e.g., /opt/<app_name>/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:
- 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/. - Place the Python script: Copy or move your
serial_um_example.pyscript intoModulesSDK/modules/serial_um_example/source/serial_um_example.py. - Copy the main Makefile template: Copy the generic module
MakefilefromModulesSDK/modules/template/Makefileto 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.tgzpackage. It usually calls theMakefilewithin thesource/directory. - Create the source Makefile: Inside the
ModulesSDK/modules/serial_um_example/source/directory, create a newMakefilewith the following content. This Makefile defines how your Python script and any associatedummodule dependencies are installed into the Router App package.
Content for ModulesSDK/modules/serial_um_example/source/Makefile:
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 <VID> <PID> > /sys/bus/usb-serial/drivers/ftdi_sio/new_idReplace <VID> and <PID> 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.