wln is a small, deterministic CLI for exporting telemetry from Wialon Hosting
or Wialon Local to analysis-ready CSV. It provides profile management, unit
discovery, authenticated access to arbitrary Remote API services, unit
creation, connectivity identity editing, and the server/port data needed to
connect a tracker.
The implementation is written in Go and talks to Wialon only through the documented Remote API. It never prints access tokens or session IDs.
macOS or Linux:
curl -fsSL https://raw.githubusercontent.com/Shooa/wln/main/install.sh | shWindows PowerShell:
irm https://raw.githubusercontent.com/Shooa/wln/main/install.ps1 | iexBoth installers detect the operating system and architecture, download the
latest GitHub release, verify its SHA-256 checksum, and install wln and
wlna in a
per-user directory. The Unix installer uses ~/.local/bin; override the target
on either platform with WLN_INSTALL_DIR.
Download the archive for your platform from the latest GitHub release:
| Platform | Intel/AMD 64-bit | ARM 64-bit |
|---|---|---|
| Linux | linux_amd64.tar.gz |
linux_arm64.tar.gz |
| macOS | darwin_amd64.tar.gz |
darwin_arm64.tar.gz |
| Windows | windows_amd64.zip |
windows_arm64.zip |
Each release includes SHA256SUMS and both executable names. Extract the
archive and put wln/wlna (or their .exe variants) somewhere on PATH.
Alternatively, with Go 1.23 or newer:
go install github.com/Shooa/wln/cmd/wln@latestgo install installs only the canonical wln name. Use the release installer
or copy that executable to wlna to activate agent defaults by invocation name.
For a repository-local binary:
make build
./bin/wln --version
./bin/wlna --versionThe help is hierarchical and does not require a configured profile or network access. Open a command group, a specific command, or one self-contained manual:
wln help
wln help messages
wln help messages get
wln messages get --help
wln help --allRunning a command group without a subcommand shows that level directly, so
wln profile, wln units, wln messages, and wln api are also valid help
entry points. A leaf command that cannot run without a positional argument also
shows its complete help when invoked bare; for example, wln messages get
includes every interval shortcut instead of returning a shortened usage line.
wln help --all is intended for shell agents and LLMs that have only the
binary: it includes every command, argument, default, constraint, and example
in one output.
wlna is the same executable under an agent-oriented name. It selects compact
JSON by default for command results, version output, help, and errors, disables
the automatic update prompt, and sends message downloads to stdout unless an
output file is explicitly requested. Human-friendly wln behavior is
unchanged. Explicit --format and --compact=false options override defaults.
wlna units get 1001
wlna units get 1001 --fields unit_id,unique_id,device_type,tcp_port
wlna units list --fields id,name,unique_idNative messages export --output - is the intentional exception: it writes
the requested binary export bytes to stdout.
wln checks GitHub Releases at startup at most once every 24 hours. When a new
version is available in an interactive terminal, it offers to install the
update before running the requested command. In non-interactive sessions it
prints a notice and continues without prompting.
Check or update explicitly:
wln update --check
wln updateRelease archives are always verified against SHA256SUMS before the executable
is replaced. On Windows, a background helper finishes replacement immediately
after the running process exits. Explicit wln update also creates or
synchronizes the adjacent wlna command; invoking the update as wlna does the
same for wln. Disable startup checks in automation when needed:
WLN_NO_UPDATE_CHECK=1 wln units listThe normal login flow opens Wialon's authorization page in the system browser,
listens on a one-time loopback callback, verifies the issued token with
token/login, and then saves the profile:
wln profile login hosting \
--server https://hosting.wialon.com \
--default--server is the base address of the Wialon installation containing
login.html, not necessarily its Remote API address. Wialon Hosting returns
wialon_sdk_url in the callback, so a login through hosting.wialon.com
automatically stores hst-api.wialon.com. Wialon Local falls back to the same
installation base address.
The default access value is 768 (0x100 + 0x200): online/message access plus
viewing connectivity properties such as the unit unique ID. Wialon groups
editing connectivity settings into the broad 0x1000 critical-data scope,
which also includes destructive rights, so wln does not request it by
default. Explicitly authorize a write-capable profile when needed:
wln profile login editor \
--server https://hosting.wialon.com \
--access 4864The authenticated user must also have the Edit connectivity settings right
to the unit. The default token duration is unlimited (0), though Wialon
removes tokens after 100 days of inactivity. Useful options:
wln profile login local \
--server https://wialon.example.test \
--user operator \
--lang ru \
--duration 720h \
--callback-timeout 10mUse --no-open when the URL should be opened manually. The callback still must
reach the same machine where wln is running.
If browser login is unavailable, do not put the token directly in a shell argument. Supply it through a temporary environment variable:
read -s WLN_TOKEN
export WLN_TOKEN
wln profile add hosting --server https://hst-api.wialon.com --default
unset WLN_TOKENOr pipe it on standard input:
security find-generic-password -w -s wialon-token |
wln profile add hosting --token-stdin --defaultProfiles are stored in the OS user configuration directory. The directory is
created with mode 0700 and the JSON file with mode 0600. profile list
never shows tokens:
wln profile list
wln profile use hosting
wln profile check hosting
wln profile remove old-profileUse --profile NAME before the command to override the default profile:
wln --profile staging units listwln units list
wln units list --search 'Truck*'
wln units list --format json
wln units list --format json --fields id,name,unique_id
wlna units get 1001--search is a Wialon unit-name mask, not an IMEI search. JSON output uses
stable CLI field names. Human-readable table output resolves Wialon hardware
IDs through core/get_hw_types and uses Unicode borders:
┌──────┬──────────┬─────────────────┬───────────┐
│ ID │ NAME │ UNIQUE ID │ HARDWARE │
├──────┼──────────┼─────────────────┼───────────┤
│ 1001 │ Truck 01 │ 123456789012345 │ Tracker X │
└──────┴──────────┴─────────────────┴───────────┘
JSON retains both the readable name and raw Wialon ID:
[
{
"id": 1001,
"name": "Truck 01",
"unique_id": "123456789012345",
"hardware": "Tracker X",
"hardware_id": 42
}
]Find the exact device type and its numeric Wialon ID:
wln units device-types --search Teltonika
wln units device-types --search Teltonika --format jsonShow everything needed to point an existing tracker to Wialon: primary unique ID, device type, hardware gateway address, and the type's TCP/UDP ports:
wln units connection 1001
wln units connection 123456789012345 --format jsonThe gateway address comes from hw_gw_ip in the authenticated token/login
response. Ports come from core/get_hw_types. An empty TCP or UDP port means
that the device type does not advertise that transport through the API.
The device type accepts either the numeric ID printed by device-types or its
exact name. --imei is an alias for Wialon's primary --unique-id field:
wln units create "Truck 02" \
--device-type "Teltonika FMB920" \
--imei 123456789012345
wln units update 1001 --imei 987654321098765
wln units update 1001 --device-type "Teltonika FMB920"
wln units update 1001 --device-type 123 --unique-id 987654321098765For updates, an omitted value is preserved. Wialon applies the device type and
primary unique ID together through unit/update_device_type. Creation requires
two documented API calls: core/create_unit, followed by
unit/update_device_type to assign the unique ID. If the second call fails,
wln reports the ID of the unit that was already created instead of hiding the
partial result.
Show connection state, the last coordinate, its age, the last message, and the last known position:
wln units status
wln units status 1001
wln units status --offline --stale 30d --sort age --limit 20
wln units status --offline --inactive 30d --sort ageThe default age order puts units with no known position first, followed by
the oldest positions. --stale is based on the coordinate timestamp, not the
last arbitrary message timestamp, so the two are shown separately. For reuse
candidates, --inactive is safer: it requires both the last position and the
last message to be older than the threshold.
Tables detect the current terminal width and fit before printing: optional
columns are removed by command-specific priority and long values receive an
ellipsis instead of being wrapped by the terminal. units status always keeps
the name, unique ID, connection state, point age, and message age. A compact
notice lists hidden columns. Use global --wide to disable fitting or
--width N to reproduce a specific layout:
wln --width 106 units status
wln --wide units statusCSV, JSON, NDJSON, and redirected table output remain unabridged.
The table also includes the current unique ID, making the selected unit
unambiguous before its connectivity settings are changed.
The unit argument accepts an exact Wialon ID, exact name, or exact unique ID/IMEI. Timestamps must be ISO 8601/RFC 3339 values with explicit offsets.
With no interval or output options, wln exports from local midnight through
the current time and creates wialon-UNIQUE_ID-YYYY-MM-DD.csv in the current
directory:
wln messages get 1001Before loading messages, wln reports the resolved unit and interval. Use the
explicit form to set either boundary:
wln messages get 1001 \
--from 2026-07-19T11:00:00+05:00 \
--to 2026-07-19T12:00:00+05:00 \
--batch-size 10000 \
--output /tmp/wialon-123456789012345.csvRelative and calendar intervals are also supported:
wln messages get 1001 --last 2h
wln messages get 1001 --last 7d
wln messages get 1001 --today
wln messages get 1001 --yesterday
wln messages get 1001 --since 08:30Write structured data to stdout for pipelines, or retain only selected message parameters:
wln messages get 1001 --last 30m --format ndjson --output -
wln messages get 1001 --today --format json --params temperature,voltageBy default, only telemetry/data messages are selected. Pass --all-types to
include events, commands, logs, and other Wialon message types. Existing output
is not replaced unless --force is specified.
The exporter:
- resolves the unit without guessing;
- logs in with
token/login; - loads the complete interval through
messages/load_interval; - reads the server-side loader in
--batch-sizepages; - flattens nested fields without renaming them (
pos.x,p.sensor_temp, etc.); - writes CSV atomically and verifies the returned row count;
- unloads messages and logs out even after most failures.
Preferred columns are ordered first when present:
t,r,rt,tp,f,i,o,pos.x,pos.y,pos.z,pos.s,pos.c,pos.sc,...sorted dynamic fields
All discovered parameters are retained as p.<name> columns. CSV, JSON, and
NDJSON files are built through a private temporary spool so large exports do
not have to remain in memory and partially written destination files are not
published.
wln messages tail 1001
wln messages tail 1001 -n 100 --format ndjson
wln messages tail 1001 --follow --poll 2s
wln messages tail 1001 --max-params 60
wln messages tail 1001 --full-params--follow polls for new messages until interrupted. Table output shortens the
parameter JSON to 100 characters by default; use --max-params to change the
limit or --full-params to disable it. Use --all-types to include events,
commands, logs, and other non-telemetry messages.
Download formats produced directly by Wialon without converting them:
wln messages export 1001 --today --format wln
wln messages export 1001 --last 24h --format kml
wln messages export 1001 --yesterday --format wlb --compressSupported formats are kml, plt, wln, and wlb. Although some Wialon API
documentation also lists txt, Wialon Hosting currently rejects that value as
invalid input, so wln does not advertise an option it cannot reliably export.
wln doctor
wln --profile staging doctor
wln profile check hostingThe diagnostic checks the configuration, selected profile, API login latency, server time, authenticated user, and accessible unit count without displaying the token or session ID.
For fields not covered by units or messages, call an authenticated Wialon
service while still using the configured profile:
wln api call core/search_items --params @request.json
wln api call user/get_locale --params '{}'The response is pretty-printed JSON. Use --compact for a compact response.
Credential-management services are blocked, and credential-like response fields
are redacted. token/login and core/logout are managed internally.
--profile NAME
--config PATH
--timeout 2m
--width N
--wide
--version
Global options must precede the top-level command. Command-specific options may follow their positional argument, matching the examples above.
- Remote API introduction and POST request format
- Getting an access token with
login.htmlandredirect_uri - Token access flags
token/logincore/search_itemscore/get_hw_typescore/create_unitunit/update_device_typemessages/load_intervalmessages/load_lastmessages/get_messagesexchange/export_messages- Message data format
- Remote API limitations
go test ./...
go vet ./...Tests use local httptest servers and never require a real Wialon token.