ProbeAgent Usage
ProbeAgent
Deploy
Raspberry Pi system
Hardware: Raspberry Pi 4B (4 GB RAM / 16 GB SD card) + Quectel RM520N-GL.
-
Flash the OS. Use Raspberry Pi Imager: select Raspberry Pi 4 > Raspberry Pi OS (other) > Raspberry Pi OS Lite (64-bit) or Raspberry Pi OS Lite (Legacy 64-bit). Both have been tested (Debian Trixie and Bookworm). Non-Lite editions are expected to work as well. Enable SSH access over Wi-Fi or Ethernet.
-
Set the RM520N-GL network driver to QMI. This requires AT commands.
AT+QCFG="usbnet",0 // set driver to QMI AT+CFUN=1,1 // reboot modem, wait ~30 s or moreTTY layout:
/dev/ttyUSB0 : DIAG port (developer messages) /dev/ttyUSB1 : NMEA port (GNSS NMEA output) /dev/ttyUSB2 : AT port (AT commands) /dev/ttyUSB3 : ModemIf the TTY is busy when sending AT commands, stop ModemManager first and restart it after:
# stop ModemManager service sudo systemctl stop ModemManager # start ModemManager service sudo systemctl start ModemManager -
Test the QMI interface (prints the device IMEI):
sudo qmicli -p -d /dev/cdc-wdm0 --dms-get-ids -
Create a connection:
sudo nmcli connection add type gsm con-name "5G-RM520" connection.autoconnect yes -
Verify the connection:
$ nmcli connection netplan-wlan0-xxxxx 378cab80-f8cd-3dac-8c67-58d6a367c921 wifi wlan0 5G-RM520 8a61f345-f9e8-462c-abfc-bd51b67b8fb1 gsm cdc-wdm0 lo db38f6ad-fc1b-4c7c-9cd9-b023b4b1d43f loopback lo netplan-eth0 75a1216a-9d1a-30cd-8aca-ace5526ec021 ethernet -- $ ip a show wwan0 3: wwan0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 1000 link/none inet 10.169.220.50/30 brd 10.169.220.51 scope global noprefixroute wwan0 valid_lft forever preferred_lft forever inet6 2409:8900:26d3:203e:549:cc8e:ab41:3bbd/64 scope global noprefixroute valid_lft forever preferred_lft forever -
Test connectivity:
ping -I wwan0 www.baidu.com -
Power-cycle test. Verify the device reconnects to the Internet automatically after a power cycle.
Install and uninstall
# install
sudo apt install ./probeagent_5.10.0-1_arm64.deb
# uninstall
sudo apt remove probeagentVerify the installation
# view the service status
sudo systemctl status probeagentExpected output:
● probeagent.service - Probe Agent Service
Loaded: loaded (/lib/systemd/system/probeagent.service; enabled; preset: enabled)
Active: active (running) since Fri 2026-03-13 14:37:28 CST; 1h 19min ago
Main PID: 680 (probeagent)
Tasks: 7 (limit: 3927)
CPU: 30.536s
CGroup: /system.slice/probeagent.service
└─680 /usr/bin/probeagent --config /etc/probeagent/probeagent.ini
Mar 13 14:37:28 raspberrypi4 systemd[1]: Started probeagent.service - Probe Agent Service.Check whether the HTTP service is reachable:
curl -vv --abstract-unix-socket probeagent.socket http://localhost/test/statusExpected output (lines starting with *, <, or > are curl debug; remove -vv to suppress):
* Trying :0...
* Connected to localhost () port 80 (#0)
> GET /test/status HTTP/1.1
> Host: localhost
> User-Agent: curl/7.88.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Fri, 13 Mar 2026 08:00:01 GMT
< Connection: Keep-Alive
< Server: ProbeAgent/5.10.0alpha
< Content-Type: application/json
< Content-Length: 109
<
* Connection #0 to host localhost left intact
{ "dataConnection": false, "device": 0, "deviceNormal": 0, "initialized": false, "task": 0, "testing": false }A valid JSON response indicates the system service is running.
Development environment
A development license is provided that expires in early August 2026. Within that window, this method licenses any number of machines.
Write the fixed machine ID:
echo "b777fe54cdab4fc787a5a57790fc3d77" | sudo tee /etc/machine-id
sudo systemd-machine-id-setup --commitCopy configuration.xml into the current directory and import it:
# import the license, should respond HTTP/1.1 200 OK
curl -vv --abstract-unix-socket probeagent.socket --data-binary @configuration.xml http://localhost/import
# verify start, should respond HTTP/1.1 200 OK
curl -vv --abstract-unix-socket probeagent.socket http://localhost/startInterface setting
The server address is configurable in /etc/probeagent/probeagent.ini. For example, setting server.address = 0.0.0.0:6226 lets you call the API over the LAN (curl -vv http://<RaspberryPi IP>:6226/start, etc.).
[setting]
; The address where the HTTP server listens.
; Start with '@' to indicate an abstract domain socket.
; Start with '/' to indicate a unix domain socket, e.g. /tmp/probeagent.socket.
; A value in <IP>:<Port> format indicates a TCP address.
; If this line is commented out, the default value is "127.0.0.1:6226".
server.address = @probeagent.socketA service restart is required for changes to take effect:
sudo systemctl restart probeagentRESTful interface
Query status
Request
- URL:
/test/status - Method:
GET
Response
A valid JSON string when HTTP code is 200. If initialized is false, the caller must call /start to initialize the test service.
| key | type | description |
|---|---|---|
device | integer | Number of configured devices |
deviceNormal | integer | Number of devices working normally |
initialized | boolean | Whether the test service is initialized |
testing | boolean | Whether the test service is started |
task | integer | Number of test scripts currently running |
initialized— whenfalse, every interface starting with/test/fails (except/test/status). A successful/startsets it totrue; a successful/stopsets it tofalse.testing— indicates whether data collection has started. Set totrueby a successful/test/start, and tofalseby a successful/test/stop.deviceanddeviceNormal— only meaningful whentestingistrue. Both equal1when data is being collected normally.device = 1anddeviceNormal = 0indicates the device is not functioning. Both0indicates a configuration error.task— only meaningful whentestingistrue. After a successful/test/startscript, this is the number of running scripts. It returns to0when the scripts finish (normal completion). A successful/test/stopscriptalso sets it to0(user interruption).
Initialize
All test-related functions must be executed after initialization (except Query Status).
Request
- URL:
/start - Method:
GET
# example
curl -vv --abstract-unix-socket probeagent.socket http://localhost/startResponse
Check the response HTTP code.
Deinitialize
All test-related functions must be executed after initialization (except Query Status).
Request
- URL:
/stop - Method:
GET
# example
curl -vv --abstract-unix-socket probeagent.socket http://localhost/stopResponse
Check the response HTTP code.
Import license
Import a license file (for off-line license registration).
Request
- URL:
/import - Method:
POST
# example: import configuration.xml
curl -vv --abstract-unix-socket probeagent.socket --data-binary @configuration.xml http://localhost/importResponse
Check the response HTTP code. If the response is OK, call /stop and then /start to re-initialize the test service.
Test start
Connect to the device(s), start recording log files, etc.
Request
- URL:
/test/start - Method:
GET
# example
curl -vv --abstract-unix-socket probeagent.socket http://localhost/test/startResponse
Check the response HTTP code.
Test stop
Disconnect the device(s), stop log files, etc.
Request
- URL:
/test/stop - Method:
GETorPOST
A GET request means the user does not care whether the log file is archived. A POST request expects a JSON body:
| key | type | description |
|---|---|---|
path | string | File name. The archive will be written to ${setting.data.dir}/test_<path>.log.gz |
async | boolean | Optional, default false. If true, the response only indicates that archive generation has started and does not guarantee completion; otherwise the call waits for completion before responding. |
# example with archive file
curl -vv --abstract-unix-socket probeagent.socket -H "Content-Type:application/json" \
-X POST -d '{"path":"20260313154000_dev_demo"}' http://localhost/test/stop
# example without archive file
curl -vv --abstract-unix-socket probeagent.socket http://localhost/test/stopResponse
Check the response HTTP code.
Test script start
Run a test script.
Request
- URL:
/test/startscript - Method:
POST - Content-Type:
text/xml
# example
curl -vv --abstract-unix-socket probeagent.socket -X POST \
-H "Content-Type: text/xml" -d @ping.xml http://localhost/test/startscriptping.xml:
<config>
<test>
<cases>
<case>
<host>www.baidu.com</host>
<index>1</index>
<name>Ping baidu</name>
<pause>1</pause>
<repeat>4</repeat>
<type>ping</type>
<!-- Specify the mobile network interface. If omitted, the system's default network is used. -->
<interface>wwan0</interface>
</case>
</cases>
</test>
</config>You can query status while the script is running:
curl -vv --abstract-unix-socket probeagent.socket http://localhost/test/statusSample response:
* Trying :0...
* Connected to localhost () port 80 (#0)
> GET /test/status HTTP/1.1
> Host: localhost
> User-Agent: curl/7.88.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Fri, 13 Mar 2026 08:00:01 GMT
< Connection: Keep-Alive
< Server: ProbeAgent/5.10.0alpha
< Content-Type: application/json
< Content-Length: 109
<
* Connection #0 to host localhost left intact
{ "dataConnection": false, "device": 1, "deviceNormal": 1, "initialized": true, "task": 1, "testing": true }Response
Check the response HTTP code.
Test script stop
Stop the running test script, if any.
Request
- URL:
/test/stopscript - Method:
GET
# example
curl -vv --abstract-unix-socket probeagent.socket http://localhost/test/stopscriptResponse
Check the response HTTP code.
Forcing feature
Forced functions map one-to-one with the SDK. The mapping rule:
For any forced function implemented by Workspace.control(String action, JSONObject argument): action corresponds to /test/modules/1/<action>. If argument is null, the request has no body; otherwise serialize argument to JSON and set Content-Type: application/json.
The caller must check the return value to confirm success (HTTP 200).
# Workspace.instance.control("lockclearall", null)
curl -vv --abstract-unix-socket probeagent.socket http://localhost/test/modules/1/lockclearall
# Workspace.instance.control("lockrat", rat) -> lock to LTE
curl -vv --abstract-unix-socket probeagent.socket -H "Content-Type:application/json" \
-X POST -d '{"rat": ["LTE"]}' http://localhost/test/modules/1/lockrat
# Workspace.instance.control("lockrat", rat) -> AUTO
curl -vv --abstract-unix-socket probeagent.socket -H "Content-Type:application/json" \
-X POST -d '{"rat": ["AUTO"]}' http://localhost/test/modules/1/lockratLog files
These APIs are intended for LAN access. Locally, you can manage files directly under /var/lib/probeagent. Do not delete or modify test.log — it is constantly in use by the running service.
List all files:
# list all files; response is a JSON array
curl -vv --abstract-unix-socket probeagent.socket http://localhost/logs/Result:
[
{
"lastModified": "2026-03-26T10:06:37+08:00",
"name": "test.03261006.log.gz",
"size": 104000
},
{
"lastModified": "2026-03-26T10:07:27+08:00",
"name": "test.log",
"size": 50715
}
]Download a file:
# download test.03261006.log.gz to the local directory
curl -vv --abstract-unix-socket probeagent.socket http://localhost/logs/test.03261006.log.gz -ODelete a file:
# delete test.03261006.log.gz
curl -vv --abstract-unix-socket probeagent.socket -X DELETE http://localhost/logs/test.03261006.log.gzTypical usage
- Initialize (call
/start) - Test start (call
/test/start) - Run a test script, or skip
- Run your own routine, or wait for a specific event
- Test stop and archive file (call
/test/stop) - Run your own file processing workflow
Repeat steps 2 to 6.