A route of a TwinCAT system, as its system service lists them, one entry at a time, for
ADS.Client.routes/2: index group 803, SYSTEMSERVICE_ENUMREMOTE in Beckhoff's Tc2_Utilities,
on AMS port 10000, the entry's index as the offset. After the last, the system answers
:device_no_more_handles.
Beckhoff documents the index group, and the fields of a route (ST_AmsRouteEntry), but not how
an entry comes; this layout is as TwinCAT 3.1 4026 answers. All numbers are little-endian:
| Bytes | Field |
|---|---|
| 6 | the route's AMS NetId |
| 2 | its transport, 1 for TCP/IP |
| 4 | its flags |
| 4 | its timeout, in ms |
| 16 | zeros |
| 4, 4, 4 | the lengths of its address, its name, and a third string, each with a zero after |
| ... | the address, the name, and the third, empty on every route seen |
Of the flags, Beckhoff names 0x1, temporary, 0x2, dynamic, a host name rather than an
address, and 0x4, not to be overridden (see flags/1); TwinCAT sets others as well, such as
0x8 and 0x40, which it doesn't name. The strings are in the system's code page, Windows-1252
unless told otherwise (see ADS.Codepage).
Summary
Functions
A route from the bytes of an entry, or :error if they don't make one.
The flags of a route that Beckhoff names, and :unknown with the bits it doesn't, if any.
Types
@type t() :: %ADS.Route{ address: String.t(), flags: non_neg_integer(), name: String.t(), net_id: ADS.net_id(), timeout: non_neg_integer(), transport: atom() | non_neg_integer() }
Functions
@spec decode(binary(), ADS.Codepage.t()) :: {:ok, t()} | :error
A route from the bytes of an entry, or :error if they don't make one.
iex> entry =
...> <<10, 0, 0, 7, 1, 1, 1::16-little, 0::32, 60_000::32-little, 0::128, 9::32-little,
...> 6::32-little, 0::32, "10.0.0.7", 0, "scada", 0>>
iex> ADS.Route.decode(entry)
{:ok, %ADS.Route{name: "scada", net_id: "10.0.0.7.1.1", address: "10.0.0.7",
transport: :tcp_ip, flags: 0, timeout: 60_000}}
@spec flags(t()) :: [:temporary | :dynamic | :no_override | {:unknown, pos_integer()}]
The flags of a route that Beckhoff names, and :unknown with the bits it doesn't, if any.
iex> ADS.Route.flags(%ADS.Route{flags: 0x41})
[:temporary, {:unknown, 0x40}]