Module: core/gateways

This module is used to communicate by address on the field buses. It currently has 2 building automation protocols, modbus TCP (master) and KNX through connection to an KNX IP gateway. It also has a "virtual" driver for storing applications custom variables, and a SMTP driver to send email / sms notifications. There is also an SMTP driver for senging emails. New protocols can be easily added by implementing their driver.
This module has two levels:
  • The gateways that connects to field buses. Gateways can be inserted, updated, deleted, started, or stopped. Gateways are linked to a specific driver (a javascript file). Parameters for each protocols (knx / modbus / smtp / ...) are different depending on the driver type.
  • The addresses. Each address is linked to one gateway. An address can be inserted, updated, or deleted. An address can be read or written. Changes on addresses are emitted by this module and can be listened by the client(s). Each address values can be logged as time series in the database, and then retrieved with the loggers module.


Structure of gateways


{
	1:{
		"id" : 1,
		"name"  : "modbus - modbus rtu 192.168.1.13",
		"description" : "...", 
		"active" : 1,
		"driver": "modbus", //is linked to driver code (modbus.js) implementing the driver functions.
		"json"  : { // used to store driver parameters.
			"port":502,
			"host":"192.168.1.13",
			"unitId":1,
			"readLoopDelay":60000
		},
		"private_json" : {...} //can be used by anyone to store custom informations independent from the driver itself.
	},
	5:{
		"id" : 5,
		"name" : "knx ip",
		"description" : "...",
		"active" : 1,
		"driver": "knx"  // links to the knx driver code (knx.js)
		"json"  : {"port":3671,"host":"192.168.1.11","mode":"ipt","server":1},
		"private_json" : {...}
	}
	.
	.
	.
}


Structure of addresses


{
	.
	.
	.,
  '23055':{ 
		id: 23055,	//database id		
		alias: null,  
		name: '4/7/25', // KNX group address
		description: null,
		log: 'always',		//logs whenever a new value is written on this address (even if the value stays the same).
		logs_validity: null, //used internally by the system to know if the logged values are still correct.
		json:{  //additional parameters that depends on the type of the address. Those are used by the driver.
			datatype: '3.xxx 3 bits with control (6 bits)', // KNX datatype, when this value is modified, it impacts the logs_validity.
			read: 'never', 	// may be used to automatically send a knx read request when the group address is not communicated on the bus.
			sources: ['3.3.2', '2.2.1']  // physical devices which already have written on the 4/7/25 group address.
		},
		gateway_id: 137,	
		value: 1,			//	last decoded numerical value
		value_string: '0.0.15|01',	// last encoded value here hexadecimal value 01 with the KNX source device (0.0.15) 
		value_date: 2017-06-30T13:07:40.354Z  //last time the address was written.
	},
	'23056':{ 
		id: 23056,	 //database id, 
		alias: 'tempDev1', // an unique alias can be used to access the address (instead of using the id 23056).
		name: '3.3.1',	// name/identifier of the address on the KNX bus. Here it is a physical address
		description: 'device used to measure temperature', 
		log: 'on_change', //logs everytime the device writes a different value on the KNX bus.
		logs_validity: null, 
		json: {},	
		gateway_id: 137,
		value: 1,
		value_string: '4/7/17|01',
		value_date: 2017-06-30T13:05:25.892Z  
	},
	.
	.
	.
}


Reading and writing values

The reading (gateways.readValue) and writing (gateways.writeValue) methods are mainly used by the graphical user interface and the logics module. There is different possible ways to read or write a value :
  • By address name (string). The name of the address is its identifier on the gateway / bus.
  • By address alias (string). Each address can have one unique alias in the system. This alias is usually defined by the system administrator / integrator. It is useful to give an human readable name with a meaning to an address. It should be used to decouple the application business logic from the fields bus addressing specifities (hence improving portability of the developed code / logic / user interface). It can also be useful to uniquely identify an address when the system is connected simultaneously to multiple gateways having conflicting (same) address names.
  • By address id (integer). Here the database id (e.g. an integer number) is used to identify the address. This method should only be used when the addresss id is retrieved dynamically. It is not a good practice to have hard-coded address ids in any codes/configuration files.


gateways.writeValue('14/7/25', 0) // by address name

gateways.readValue('tempDev1', function(err, value){ //read by alias. Here alias 'tempDev1' was given to the address (see above the gateways example)
	//In this example value would be 0. The knx values are decoded according to their configured datatype (e.g. '3.xxx 3 bits with control (6 bits)')
})

gateways.writeValue(23055, 1) // by address id



Events emitted by the address module


//for gateways : 

gateways.on('gatewayInserted',function(newGateway){ ... })
gateways.on('gatewayUpdated',function(updatedGateway, oldGateway){ ... })
gateways.on('gatewayDeleted',function(deletedGateway){ ... })
gateways.on('gatewayState',function(gatewayId, state){ 
	// gateway numerical id (e.g. 5)
	// where state equal to 'connecting', 'connected', or 'disconnected' 
})  

//for addresses : 

gateways.on('addressInserted',function(newAddress){ ... })
gateways.on('addressUpdated',function(updatedAddress, oldAddress){ ... })
gateways.on('addressDeleted',function(deletedAddress){ ... })

gateways.on('newValue', function(addressId, newValue, newRawStringValue, date){}) //emitted when an address has a new value. 
gateways.on('newValueLog', function(addressId, newValue, newRawStringValue, date){}) //emitted when an address change has to be logged on disk.

//all gateways and addresses events can be listened on individual objects by adding the id to the event:

gateways.once('gatewayDeleted 5',function(deletedGateway){ ... }) //emitted when gateway with id 5 is deleted.
gateways.on('newValue 23056', function(newValue, newRawStringValue, date){ ... }) //emitted when address with id 23056 has a new value. 
gateways.on('addressUpdated 23056', function(updatedAddress, oldAddress){ ... }) //emitted when address with id 23056 is modified.

// it is possible to listen to new values by address name or alias. 

gateways.on('newValue 4/7/25', function(newValue, newRawStringValue, date){ ... })

function temperatureListener(newValue, newRawStringValue, date){ ... }
gateways.on('newValue $tempDev1',temperatureListener)
gateways.removeListener('newValue $tempDev1', temperatureListener) //stops to listen to the event

Methods

(static) deleteAddress(addressKey, callback)

Delete an address from the system. This operation is definitive. The callback returns an error if the operation failed.
Parameters:
Name Type Description
addressKey number/string/object Address identifier. Either id (e.g. 23056), alias (e.g. 'tempDev1'), name (e.g. '3.3.1'), or address object (e.g. {id:23056, ...})
callback function function(err){...}

(static) deleteGateway(gatewayKey, callback)

Deletes a gateway from the system. This operation is definitive. The callback returns an error if the operation failed.
Parameters:
Name Type Description
gatewayKey number/string/object Gateway identifier. Either id (e.g. 5), name (e.g. "knx ip"), or gateway object (e.g. {id:5, ...})
callback function function(err){...}

(static) getAddress(addressKey, callback)

Returns in the callback function the desired address. If the address does not exists, the callback returns an error. The address object is not updated automatically. The addressUpdated event needs to be listened in order to get parameters modifications. Note that change of the address value are notified seperately with the 'newValue' event.
Parameters:
Name Type Description
addressKey number/string/object Address identifier. Either id (e.g. 23056), alias (e.g. 'tempDev1'), name (e.g. '3.3.1'), or address object (e.g. {id:23056, ...})
callback function function(err, address){...}

(static) getAddresses(callback)

Returns in the callback function all the addresses. The returned addresses object is not updated. Modification events needs to be listened.

addresses.getAddresses(function(err, addrs){
	if(err){
		//...
	}else{
		//the addrs object has the structure shown at the top of this documentation page.
		console.log(addrs) 
	}
})
addresses.on('addressInserted', function(newAddr){...})
addresses.on('addressDeleted', function(deletedAddr){...})
addresses.on('addressUpdated', function(updatedAddr, oldAddr){...})
Parameters:
Name Type Description
callback function function(err, addrs){...}

(static) getAddressesByGateway(callback)

Returns in the callback function all the addresses belonging to the gateway. The returned addresses object is not updated. Modification events needs to be listened.

addresses.getAddresses(function(err, addrs){
	if(err){
		//...
	}else{
		console.log(addrs)
	}
})
addresses.on('addressInserted', function(newAddr){...})
addresses.on('addressDeleted', function(deletedAddr){...})
addresses.on('addressUpdated', function(updatedAddr, oldAddr){...})
Parameters:
Name Type Description
callback function function(err, addrs){...}

(static) getGateway(gatewayKey, callback)

Returns in the callback function the desired gateway object. The gateway object is not updated automatically. The gatewayUpdated event needs to be listened in order to get potential modifications.
Parameters:
Name Type Description
gatewayKey number/string/object Gateway identifier. Either id (e.g. 5), name (e.g. "knx ip"), or gateway full object (e.g. {id:5, ...})
callback function function(err, gateway){...}

(static) getGateways(callback)

Returns in the callback function all the configured system gateways. The returned gateways object is not updated. Modification events needs to be listened.

addresses.getGateways(function(err, gateways){
	if(err){
		//...
	}else{
		//the gateways object has the structure shown at the top of this documentation page.
		console.log(gateways)
	}
})
addresses.on('gatewayInserted', function(newGateway){...})
addresses.on('gatewayDeleted', function(deletedGateway){...})
addresses.on('gatewayUpdated', function(updatedGateway, oldGateway){...})
Parameters:
Name Type Description
callback function function(err, gateways){...}

(static) getGatewaysCache(callback)

Returns in the callback function all the configured system gateways. The gateways object is automatically updated without notice when a gateway is inserted, updated, or deleted.
Parameters:
Name Type Description
callback function function(err, gatewaysCache){...}

(static) getLastValue(addressKey, value, callback)

Returns in the callback the last known value of the given address (without sending a read request to the driver). If the address does not exists or the gateway is not connected, then the callback returns an error.
Parameters:
Name Type Description
addressKey number/string/object Address identifier. Either id (e.g. 23055), alias (e.g. '...'), name (e.g. '4/7/25'), or address object (e.g. {id:23055, ...})
value number/string/object the decoded value to write on the address.
callback function function(err, value){...}

(static) importAddresses(addresses, callback)

Can import thousands of addresses in the system without impacting too much the performance of other processes. It can be used for example to import addresses from an external system (e.g. ETS for KNX).
Parameters:
Name Type Description
addresses array multiple addresses e.g. ([{name:'1/2/0',...},{name:'1/2/1', ...},..,..,...])
callback function function(err, newAddressId){...}

(static) insertAddress(address, callback)

Insert one or multiple addresses in the system. The callback returns an error if the operation failed. If one address was inserted, it returns the id of the newly inserted address.
Parameters:
Name Type Description
address object/array address full object without id (e.g. {name: '4/7/25', description: 'new knx address..',log: 'always',...}). An array of objects can also be passed in order to insert multiple addresses e.g. ([{name:'1/2/0',...},{name:'1/2/1', ...}])
callback function function(err, newAddressId){...}

(static) insertGateway(gateway, callback)

Inserts a new gateway in the system. The callback returns an error if the operation failed. Otherwise it returns the id of the newly inserted gateway.
Parameters:
Name Type Description
gateway object gateway full object without id (e.g. {name:'new knx gateway',description:'...', driver : 'knx',json:{...}, ...})
callback function function(err, newGatewayId){...}

(static) readValue(addressKey, callback)

Send a read command to the gateway driver on the given address. This function returns in the callback the decoded value of the address. If the address does not exists or the gateway is not connected, then the callback returns an error.
Parameters:
Name Type Description
addressKey number/string/object Address identifier. Either id (e.g. 23056), alias (e.g. 'tempDev1'), name (e.g. '3.3.1'), or address object (e.g. {id:23056, ...})
callback function function(err, value){...}

(static) startGateway(gatewayKey, callback)

Starts a gateway. Once started, the gateway tries to connect to the field bus. The event stateGateway is fired once with 'connecting', and then once again with 'connected' if the operation succed. If the connection attempt fails, the event stateGateway 'disconnected' is fired. Which means that the process is killed and will automatically restart after a short delay in order to make new connection attempts. In the rare case when the driver process crashes due to an unexpected issue or because the machine runs out of memory ressources, it will also be restarted after a short delay.
Parameters:
Name Type Description
gatewayKey number/string/object Gateway identifier. Either id (e.g. 5), name (e.g. "knx ip"), or gateway object (e.g. {id:5, ...})
callback function function(err){...}

(static) stopGateway(gatewayKey, callback)

Stops a gateway. The driver process is killed and stateGateway 'disconnected' is fired.
Parameters:
Name Type Description
gatewayKey number/string/object Gateway identifier. Either id (e.g. 5), name (e.g. "knx ip"), or gateway object (e.g. {id:5, ...})
callback function function(err){...}

(static) testGateway(gatewayKey, callback)

Test the connectivity to a given gateway. If the connection attempt succeed, the callback can depending on the driver (knx, modbus, ...) return information about the gateway.
Parameters:
Name Type Description
gatewayKey number/string/object Gateway identifier. Either id (e.g. 5), name (e.g. "knx ip"), or gateway object (e.g. {id:5, ...})
callback function function(err, gatewayInfo){...}

(static) updateAddress(address, callback)

Update one or multiple addresses. The callback returns an error if the operation failed.
Parameters:
Name Type Description
address object/array address object. It does not need to be full (e.g. {id:23055, description : 'my new description'} updates only the description of the address). An array of objects can also be passed in order to update multiple addresses e.g. ([{id:23055, description:'new description 1'},{id:23056,'new description 2'}])
callback function function(err){...}

(static) updateGateway(gateway, callback)

Updates a gateway. The callback returns an error if the operation failed.
Parameters:
Name Type Description
gateway object gateway object. It does not need to be full (e.g. {id:5, description : 'my new description'} updates only the description of the gateway)
callback function function(err){...}

(static) writeValue(addressKey, value, callback)

Send a write command to the gateway driver on the given address. If the address does not exists or the gateway is not connected, then the callback returns an error.
Parameters:
Name Type Description
addressKey number/string/object Address identifier. Either id (e.g. 23055), alias (e.g. '...'), name (e.g. '4/7/25'), or address object (e.g. {id:23055, ...})
value number/string/object the decoded value to write on the address.
callback function function(err, value){...}