Network module

Network module API ( require "network" )

network module supports only async mode.

It's possible to inspect data without fetching them while receiving data, use network.inspect().

All methods throw exceptions in a case of errors, unless otherwise stated.

Events

network module notifies a script subscribed by network.subscribe( "script_name" ) about events happened within it.

After a connection has been established (network.connect()) for TCP socket or UDP socket is created, io async notifications are sent to a script subscribed by network.subscribe(), to change script use network.set_handler()

Name of a network event: "network"

Structure of a network event:
{
    "event": "network",
    "data": {
        "event_type": "io_activity",
        "event": {
           "handle": 2810,
           "io_activity_type": "IN"
        }
}
fields type description
event string network
data table data specific to a network event
data.event_type string io_activity
data.event table data specific to a io_activity event
data.event.handle int handle an I/O activity happened on
data.event.io_activity_type string type of an I/O activity

Note: Currently only I/O activity events are emitted

Type of an I/O activity:
IN there's some data on a handle to read
OUT it's possible to write to a TCP socket handle
CLOSED remote side closed a connection
CONNECTED connection has been established successfully
FAILED_TO_CONNECT fail to establish a connection

Constants

network.event_types

{
    "io_activity": {
        "type_name": "io_activity",
        "IN": "IN",
        "OUT": "OUT",
        "CLOSED": "CLOSED",
        "CONNECTED": "CONNECTED",
        "FAILED_TO_CONNECT": "FAILED_TO_CONNECT"
    }
}

Common

Implementation keeps an internal buffer for each connection handler, which can be fetched by network.receive or inspected by network.inspect_data. Size of such buffer can be inspected by network.inspect_data_size method.

subscribe()

Subscribes a specified script for network events.

Subscribed script can be notified (called) concurrently with other scripts, it's up to a plugin's author to make a proper protection.

call: network.subscribe()

params: script name (string).

return: nothing

example:

require "network"
network.subscribe("event_handling")

set_handler()

Set a custom events handler. If network.subscribe() wasn't called this is the only one way to get I/O async notifications for handler.

After this call network sends events for the handler only to a specified events handler.

call: network.set_handler()

params: hndl (int), events handler script (string).

return: nothing

example:

require "network"

handle = network.connect({ ip = "127.0.0.1", port = "6010", connection_type = "TCP" })
network.set_handler(handle, "events_handler")

connect()

Establishes a connection to a remote side with a specified address. It's an async call, when connection has been established, an event CONNECTED or FAILED_TO_CONNECT gets sent to a set events handler.

Throw an exception if something local went wrong.

Both IPv4 and IPv6 along with a host name can be used as a remote address.

Once connection has been established there's no way to change its type (TCP, UDP) and an address it's connected to.

call: network.connect()

params: address (table), options (int) [optional].

Structure of an address parameter:

{
    "ip": "string",
    "port": "string"
    "connection_type": "string"
}

return: connection handle (int).

Example
require "network"

handle = network.connect( { ip = "127.0.0.1", port = "6010", connection_type = "TCP" } )
if not handle then
   print( "fail to connect" )
end

inspect_data()

Inspects received data on a connection handle without fetching them from an internal buffer.

Makes a copy of an internal implementation buffer.

call: network.inspect_data()

params: hndl (int).

return: binary data (string)

example:

require "network"

hndl = network.connect( {} )
data = network.inspect_data( hndl )

if string.find( data, "OK" ) then
    print( "we got a specific chunk of data, do something useful..." )
end

inspect_data_size()

Inspects a size of received data, doesn't make a copy of an internal buffer;

call: network.inspect_data_size()

params: hndl (int).

return: size of received data, in bytes (int)

example:

require "network"

hndl = network.connect( {} )
amount = network.inspect_data_size( hndl )

if amount >= 10 then
    print( "we got enough data to start processing..." )
end

TCP

send()

Sends data to a remote side.

It's a plugin's author responsibility to make sure all data was sent (repeatedly calling this function till all data gets sent or, using I/O async notification, call this function when it exact has to be called).

call: network.send()

params: hndl (int), binary data (string).

return: amount of sent data (int)

example:

require "network"

hndl = network.connect( {} )
conn = network.send( hndl, "hello_world" )

receive()

Receives data from a remote side. It's an async call, never blocks, if there's no data to read, returns immediately.

It's a plugin's author responsibility to make sure all data was consumed (repeatedly calling this function till all data gets consumed or, using I/O async notification, call this function when it exact has to be called).

Fetch data from an internal buffer, see inspect_data to inspect data without fetching them.

call: network.receive()

params: hndl (int), amount of data to return, in bytes (int) [optional, by default receive will return all there is].

return: received data (string) [may be empty if there's no data to read]

example:

require "network"

hndl = network.connect( {} )
data = network.receive( hndl, 100 )

close()

Close a connection handle. Implementation has to free all associated resources.

call: network.close()

params: hndl (int).

return: nothing

example:

require "network"

hndl = network.connect( {} )
network.close( hndl )

UDP

For UDP sockets all TCP functions work, In addition there are few new:

udp()

Creates IPv4 UDP socket and returns its handle. Unconnected socket support the sendto, receive, receivefrom, setoption, setpeername, setsockname, and close. The setpeername is used to connect socket.

Parameters

none

Returns

Type Description
int Udp socket handle

Example

local network = require("network")
local handle = network.udp();

close()

Closes a UDP socket.

Parameters

Parameter Type Required Description
handle int + Connection handle

Returns

nothing

Example

local network = require("network")
local handle = network.udp();
network.sendto(handle, "Hi there!", "192.168.1.100", "8021")
network.close(handle)

getsockname()

Returns the local address information associated to UDP socket.

Note: UDP sockets are not bound to any address until the setsockname or the sendto method is called for the first time (in which case it is bound to an ephemeral port and the wild-card address).

Params

Parameter Type Required Description
handle int + Connection handle

Returns

Type Description
string Local address
string Local port

Example

local network = require("network")
local handle = network.udp();
network.setpeername(handle, "8.8.8.8", "80")
local ip, _ = network.getsockname(handle)
print(ip)

receive()

Receives a datagram from the UDP socket. If the UDP socket is connected, only datagrams coming from the peer are accepted. Otherwise, the returned datagram can come from any host. If there are more than size bytes available in the datagram, the excess bytes are discarded. If there are less then size bytes available in the current datagram, the available bytes are returned.

Params

Parameter Type Required Description
handle int + Connection handle
size int - Maximum size of the datagram to be retrieved. If omitted, the maximum datagram size is used (which is currently limited by the implementation to 8192 bytes).

Returns

Type Description
string Received datagram

Example

local params = ...

local network = require("network")
if params.event == "network" and params.data.event_type == "io_activity" then
    if params.data.event.io_activity_type == "IN" then
        print("Message: " .. network.receive(params.data.event.handle))
    end
    return
end

receivefrom()

Works exactly as the receive method, except it returns address and port as extra return values (and is therefore slightly less efficient).

Params

Parameter Type Required Description
handle int + Connection handle
size int - Maximum size of the datagram to be retrieved. If omitted, the maximum datagram size is used (which is currently limited by the implementation to 8192 bytes).

Returns

Type Description
string Received datagram
string Sender address
string Sender port

Example

local params = ...

local network = require("network")
if params.event == "network" and params.data.event_type == network.event_types.io_activity.type_name then
    if params.data.event.io_activity_type == network.event_types.io_activity.IN then
        data, address, port = network.receivefrom(params.data.event.handle)
        print("Message: " .. data)
        print("Address: " .. address)
        print("Port: " .. port)
    end
    return
end

request()

Request to receive datagram. Specified script will be called when datagram will be received. Note that only one datagram will be received for a single request() call. Multiple requests may be scheduled.

Params

Parameter Type Required Description
handle int + Connection handle
callback string + Plugin script file that will be called with recieved data
user_data string - Any data which will be passed to callback
size int - Maximum size of the datagram to be retrieved. If omitted, the maximum datagram size is used (which is currently limited by the implementation to 8192 bytes).

Returns

nothing

Callback

Parameter Type Description
event string request
data.handle int Connection handle
data.user_data string User data passed to request() call
data.datagram string Received datagram

Example

local params = ...

local network = require("network")

if params.event == "request" then
    print(params.data.user_data .. params.data.datagram)
    return
end

local handle = network.udp();
network.setsockname(handle, "*", "8021")
network.sendto(handle, "Is there anyone?", "192.168.1.255", "8021")
network.request(handle, "this_script_name", "Found: ")

requestfrom()

Works exactly as the request method, except it passes address and port as extra parameters to a callback.

Params

Parameter Type Required Description
handle int + Connection handle
callback string + Plugin script file that will be called with recieved data
user_data string - Any data which will be passed to callback
size int - Maximum size of the datagram to be retrieved. If omitted, the maximum datagram size is used (which is currently limited by the implementation to 8192 bytes).

Returns

nothing

Callback

Parameter Type Description
event string requestfrom
data.handle int Connection handle
data.user_data string User data passed to request() call
data.datagram string Received datagram
data.address string Sender address
data.port string Sender port

Example

local params = ...

local network = require("network")

if params.event == "requestfrom" then
    network.sendto(
        params.data.handle,
        params.data.user_data .. params.data.datagram,
        params.data.address,
        params.data.port)
    return
end

local handle = network.udp();
network.setsockname(handle, "*", "8021")
network.sendto(handle, "Is there anyone?", "192.168.1.255", "8021")
network.requestfrom(handle, "this_script_name", "Hi, ")

send()

Sends a datagram to the UDP peer of a connected socket.

Params

Parameter Type Required Description
handle int + Connection handle
datagram string + Datagram contents

Returns

nothing

Example

local network = require("network")
local handle = network.udp();
network.setpeername(handle, "192.168.1.100", "8021")
network.sendto(handle, "Hi there!")
network.sendto(handle, "What's up!")

sendto()

Sends a datagram to the specified IP address and port number.

Params

Parameter Type Required Description
handle int + Connection handle
datagram string + Datagram contents
address string + IP address of the recipient
port string + Port at the recipient

Returns

nothing

Example

local network = require("network")
local handle = network.udp();
network.sendto(handle, "Hi there!", "192.168.1.100", "8021")

setpeername()

Changes the peer of a UDP socket. This method turns an unconnected UDP socket into a connected UDP socket or vice versa.

For connected sockets, outgoing datagrams will be sent to the specified peer, and datagrams received from other peers will be discarded by the OS. Connected UDP sockets must use the send and receive methods instead of sendto and receivefrom.

If address is '*' and the socket is connected, the peer association is removed and the socket becomes an unconnected again. In that case, the port argument is ignored.

Note: Since the address of the peer does not have to be passed to and from the OS, the use of connected UDP sockets is recommended when the same peer is used for several transmissions.

Params

Parameter Type Required Description
handle int + Connection handle
address string + IP address or a host name to connect
port string - Port to connect

Returns

nothing

Example

local network = require("network")
local handle = network.udp();
network.setpeername(handle, "192.168.1.100", "8021")

setsockname()

Binds the UDP socket to a local address. Address can be an IP address or a host name. If address is '*' the system binds to all local interfaces using the constant INADDR_ANY. If port is 0, the system chooses an ephemeral port.

Note: This method can only be called before any datagram is sent through the UDP socket, and only once. Otherwise, the system automatically binds the socket to all local interfaces and chooses an ephemeral port as soon as the first datagram is sent. After the local address is set, either automatically by the system or explicitly by setsockname, it cannot be changed.

Params

Parameter Type Required Description
handle int + Connection handle
address string - Address to bind
port string - Port to bind

Returns

nothing

Example

local network = require("network")
local handle = network.udp();
network.setsockname(handle, "*", "8021")

setoption()

Sets options for the UDP socket. Options are only needed by low-level or time-critical applications. You should only modify an option if you are sure you need it.

Option is a string with the option name, and value depends on the option being set

Params

Parameter Type Required Description
handle int + Connection handle
option string + Option name
value depends - Option value
Supported options
Option Value type Default value Description
broadcast bool True Requests permission to send broadcast datagrams on the socket

Returns

nothing

Example

local network = require("network")
local handle = network.udp();
network.setoption(handle, "broadcast")

Network scanning

start_scan_network()

Scan network for existing devices.

call: network.start_scan_network()

params:

fields type description
script string The path to handle script. Example: "HUB:zwave/scripts/handle_network_scan_results". The every since result comes to this script as argument.
ip_addresses string The list format is set of ip addresses are separated by comma. Example: "192.168.0.0, 192.168.0.1, 192.168.122.1, 192.168.0.34". The range format are two ip addresses are separated by hyphen. Example: "192.168.0.0 - 192.168.122.9"
ip_version string The two possible values are "ip4" and "ip6"
ports intArray [opt] The array of ports what should be scanned.

return: scan_id (int)

result table fields:

fields type description
event string The name of this module "network"
data table The result of scanning.

data table fields

fields type description
scan_id int The Id of scanning.
status string The status of scanning. The possible tokens: started, finished, progress.
ip_address string [opt] The IP address of device
mac string [opt] The MAC address of device
host_name string [opt] The host name of device
ports intArray [opt] The array of open ports.

example:

require "network"

local ip_list = "192.168.0.0, 192.168.0.1, 192.168.122.1, 192.168.0.34"
local ip_range = "192.168.0.0 - 192.168.122.9"
local ports = { 2020, 30, 8080 }
local handle_results = "HUB:zwave/scripts/handle_network_scan_results"
local scan_id1 = network.start_scan_network( ip_list, "IPv4", handle_results )
local scan_id2 = network.start_scan_network( ip_range, "IPv4", handle_results, ports )
network.stop_scan_network( scan_id1 )
network.stop_scan_network( scan_id2 )

stop_scan_network()

Stop network scanning by using scan id.

call: network.stop_scan_network()

params:

fields type description
scan_id int The scan id is returned by start_scan_network method

return: nothing

example:

require "network"

local ip_list = "192.168.0.0, 192.168.0.1, 192.168.122.1, 192.168.0.34"
local handle_results = "HUB:zwave/scripts/handle_network_scan_results"
local scan_id1 = network.start_scan_network( ip_list, "IPv4", handle_results )
network.stop_scan_network( scan_id1 )

DHCP events listening

start_dhcp_discovery()

Creates a subscription on DHCP events.

call: network.start_listening_dhcp()

params:

fields type description
path string The path to notification script.
operations string[] The list of event names to subscribe to, one of: discovery, offer, request, acknowledge

return: subscriptionId: string

result table fields:

fields type description
event string Event name, one of: dhcp_discovery, dhcp_offer, dhcp_request, dhcp_acknowledge
data table DHCP event data.

data table fields

fields type description
id string Subscription Identifier
client_address string MAC address of "sender" (from Ethernet protocol header)
destination_address string MAC-address of "destination" (from Ethernet protocol header)
ip_source string IP-address, specific to every DHCP command.
ip_destination string IP-address, specific to every DHCP command.
params object event-specific data

See list of fields specific to every DHCP command:

dhcp_discovery

fields type description
id string Subscription Identifier
client_address string MAC address of "sender"
destination_address string MAC address of "destination"
ip_source string The last know ip address from a client
ip_destination string the specific subnet broadcast address
params object event-specific data
params.hostname string (optional) Client host name

dhcp_offer

fields type description
id string Subscription Identifier
client_address string MAC address of "sender"
destination_address string MAC address of "destination"
ip_source string IP of DHCP server
ip_destination string the specific subnet broadcast address
params object Offered data to client
params.ip string Offered IP
params.mask string Offered subnet address
params.gateway string Offered gateway/router IP
params.lease_time integer IP address lease time in seconds
params.dhcp string DHCP IP address
params.dns string[] DNS servers' IP array
params.domain_name string Domain name
params.ntp string NTP servers list

dhcp_request

fields type description
id string Subscription Identifier
client_address string MAC address of "sender"
destination_address string MAC address of "destination"
ip_source string The last know ip address from a client
ip_destination string the specific subnet broadcast address
params object event-specific data
params.ip string Requested IP address
params.hostname string (optional) Requested host name
params.gateway string Requested gateway IP address
params.ntp string NTP servers list

dhcp_acknowledge

fields type description
id string Subscription Identifier
client_address string MAC address of "sender"
destination_address string MAC address of "destination"
ip_source string IP of DHCP server
ip_destination string the specific subnet broadcast address
params object Offered data to client
params.ip string Offered IP
params.mask string Offered subnet address
params.gateway string Offered gateway/router IP
params.lease_time integer IP address lease time in seconds
params.dhcp string DHCP IP address
params.dns string[] DNS servers' IP array
params.domain_name string Domain name
params.ntp string NTP servers list

example:

local network = require('network')

local value = 'unknown result'

local subscriptionId = network.start_listening_dhcp("HUB:path/to/script", ["request", "discovery", "offer", "acknowledgement"])

value = network.stop_listening_dhcp(subscriptionId)

stop_listening_dhcp()

Drops subscription to DHCP events.

call: network.stop_listening_dhcp()

params:

fields type description
subscriptionId string Subscription ID returned by start_listening_dhcp() method

return: string: Ok