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
orFAILED_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
, andclose
. Thesetpeername
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 thesendto
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
andreceive
methods instead ofsendto
andreceivefrom
.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 constantINADDR_ANY
. If port is0
, 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
dhcp_request
dhcp_acknowledge
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