/** Example configuration file for VILLASnode.
 *
 * This example includes all valid configuration options for the server.
 * Please note, that using all options at the same time does not really
 * makes sense. The purpose of this example is to serve as a reference.
 *
 * The syntax of this file is similar to JSON.
 * A detailed description of the format can be found here:
 *   http://www.hyperrealm.com/libconfig/libconfig_manual.html#Configuration-Files
 *
 * @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
 * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC
 * @license GNU General Public License (version 3)
 *
 * VILLASnode
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *********************************************************************************/

# Some global settings are used by multiple configuration files
# and therefore defined in separate files
@include "global.conf"
@include "plugins.conf"

############    Dictionary of nodes    ############

nodes = {
	udp_node = {					# The dictionary is indexed by the name of the node.
		type = "socket",			# For a list of available node-types run: 'villas-node -h'
		vectorize = 30,				# Receive and sent 30 samples per message (combining).
		samplelen = 10				# The maximum number of samples this node can receive
		
		hooks = (
			{
				type = "stats",
				
				warmup = 100,		# The first 100 samples are used to estimate bounds for the histograms
				format = "human",	# One of: human, json, matlab
				bucket = 30,		# The number of buckets for the histograms
				verbose = true		# Plot histograms during shutdown
			}
		),

	### The following settings are specific to the socket node-type!! ###

		layer	= "udp",			# Layer can be one of:
							#   - udp     Send / receive L4 UDP packets
							#   - ip      Send / receive L3 IP packets
							#   - eth     Send / receive L2 Ethernet frames (IEEE802.3)

		format	= "gtnet-fake",			# For a list of available node-types run: 'villas-node -h'

		verify_source = true, 			# Check if source address of incoming packets matches the remote address.

		local	= "127.0.0.1:12001",		# This node only received messages on this IP:Port pair
		remote	= "127.0.0.1:12000",		# This node sents outgoing messages to this IP:Port pair

		netem = {				# Network emulation settings
			enabled		= true,
							# Those settings can be specified for each node invidually!
			delay		= 100000,	# Additional latency in microseconds
			jitter		= 30000,	# Jitter in uS
			distribution	= "normal",	# Distribution of delay: uniform, normal, pareto, paretonormal
			loss		= 10		# Packet loss in percent
			duplicate	= 10,		# Duplication in percent
			corrupt 	= 10		# Corruption in percent
		},

		multicast = {				# IGMP multicast is only support for layer = (ip|udp)
			enabled		= true,

			group		= "224.1.2.3",	# The multicast group. Must be within 224.0.0.0/4
			interface	= "1.2.3.4",	# The IP address of the interface which should receive multicast packets.
			ttl		= 128,		# The time to live for outgoing multicast packets.
			loop		= false,	# Whether or not to loopback outgoing multicast packets to the local host.
		}
	},
	ethernet_node = {
		type	= "socket",			# See above.

	### The following settings are specific to the socket node-type!! ###

		layer	= "eth",
		local	= "12:34:56:78:90:AB%eth0:12002",
		remote	= "12:34:56:78:90:AB%eth0:12002"
	},
	opal_node = {					# The server can be started as an Asynchronous process
		type	= "opal",			# from within an OPAL-RT model.

	### The following settings are specific to the opal node-type!! ###

		send_id	= 1,				# It's possible to have multiple send / recv Icons per model
		recv_id	= 1,				# Specify the ID here.
		reply = true
	},
	file_node = {
		type	= "file",

	### The following settings are specific to the file node-type!! ###

		uri = "logs/input.log",			# These options specify the path prefix where the the files are stored

		epoch_mode = "direct"			# One of: direct (default), wait, relative, absolute
		epoch = 10				# The interpretation of this value depends on epoch_mode (default is 0).
							# Consult the documentation of a full explanation

		rate = 2.0				# A constant rate at which the lines of the input files should be read
							# A missing or zero value will use the timestamp in the first column
							# of the file to determine the pause between consecutive lines.
	},
	ngsi_node = {
		type = "ngsi",

	### The following settings are specific to the ngsi node-type!! ###

		endpoint = "http://46.101.131.212:1026",# The HTTP REST API endpoint of the FIRWARE context broker

		entity_id = "S3_ElectricalGrid",
		entity_type = "ElectricalGridMonitoring",

		timeout = 5,				# Timeout of HTTP request in seconds (default is 1)
		verify_ssl = false,			# Verification of SSL server certificates (default is true)

		mapping = [				# Format: "AttributeName(AttributeType)"
			"PTotalLosses(MW)",
			"QTotalLosses(Mvar)"
		]
	},
	websocket_node = {
		type = "websocket",

		destinations = [
			"http://example.com/node-name1",
			"https://example.com/another-node"
		]
	},
	nanomsg_node = {
		type = "nanomsg",

		publish = [
			"tcp://*:12000",		# TCP socket
			"ipc:///tmp/test.ipc",		# Interprocess communication
			"inproc://test"			# Inprocess communication
		],
		subscribe = [
			"tcp://127.0.0.1:12000",
			"ipc:///tmp/test.ipc",
			"inproc://test"
		]
	},
	zeromq_node = {
		type = "zeromq",

		pattern = "pubsub",			# The ZeroMQ pattern. One of pubsub, radiodish
		ipv6 = false,				# Enable IPv6 support
		filter = "ab184",			# A filter which is prefix matched
		curve = {				# Z85 encoded Curve25519 keys
			enabled = true,
			public_key = "Veg+Q.V-c&1k>yVh663gQ^7fL($y47gybE-nZP1L",
			secret_key = "HPY.+mFuB[jGs@(zZr6$IZ1H1dZ7Ji*j>oi@O?Pc"
		}

		subscribe = "tcp://*:1234"		# The subscribe endpoint.
							# See http://api.zeromq.org/2-1:zmq-bind for details.
		
		publish = [				# The publish endpoints.
			"tcp://localhost:1235",		# See http://api.zeromq.org/2-1:zmq-connect for details.
			"tcp://localhost:12444"
		],
	},
	signal_node = {
		type = "signal",

		signal = "sine",			# One of: sine, square, ramp, counter, constant, triangle, random, mixed, constant"
		values = 4,				# Number of values per sample
		amplitude = 2.3,			# Amplitude of generated signals
		frequency = 10,				# Frequency of generated signals
		stddev = 2,				# Standard deviation of random signals (normal distributed)
		rate = 10.0,				# Sample rate
		offset = -4.5				# DC bias / Offset
	},
	loopback_node = {
		type = "loopback",			# A loopback node will receive exactly the same data which has been sent to it.
							# The internal implementation is based on queue.
		queuelen = 1024				# The queue length of the internal queue which buffers the samples.
		samplelen = 64				# Each buffered sample can contain up to 64 values.
	},
	shmem_node = {
		type = "shmem",
		
		in_name = "sn1_in",			# Name of shared memory segment for receiving side
		out_name = "sn1_in",			# Name of shared memory segment for sending side
		
		queuelen = 1024,			# Length of the queues
		polling = true,				# We can busy-wait or use pthread condition variables for synchronizations
		
		# Execute an external process when starting the node which
		# then starts the other side of this shared memory channel
		# Usually we also pass the shmem names as parameters.
		exec = [ "villas-shmem", "sn1_in", "sn1_out" ]
	},
	stats_node = {					# The "stats" node-type streams statistics of a second node
		type = "stats",
			
		node = "udp_node",
		rate = "2"
	},
	rtt_node = {					# The "test_rtt" node-type runs a set of test cases for varying
		type = "test_rtt",			# sending rates, number of values and generates statistics.
		cooldown = 2,				# The cooldown time between each test case in seconds
		
		prefix = "test_rtt",			# An optional prefix in the filename
		output = "/tmp/results/testA",		# The output directory for all results
							# The results of each test case will be written to a seperate file.
		format = "villas-human",		# The output format of the result files.

		cases = (				# The list of test cases
							# Each test case can specify a single or an array of rates and values
							# If arrays are used, we will generate multiple test cases with all
							# possible combinations
			{
				"rates": 55.0,		# The sending rate in Hz
				"values": 5,		# The number of values which should be send in each sample
				"limit": 100		# The number of samples which should be send during this test case
			},
			{
				"rates": [ 5, 10, 30 ],	# An array of rates in Hz
				"values": [ 2, 10, 20 ],# An array of number of values
				"duration": 5		# The duration of the test case in seconds (depending on the sending rate)
			}
		)
	}
};


############       List of paths       ############

paths = (
	{
		enabled = true,				# Enable this path (default: true)
		reverse = true,				# Setup a path in the reverse direction as well (default: false)

		in = "acs",				# Name of the node we receive messages from (see node dictionary)
		out = "sintef",				# Name of the node we send messages to.

		rate = 100,				# Send message over this path with a fixed (constant) rate (default: 0).
							# Setting this value to 0 will disable this feature.

		queuelen = 128
	},
	{
		enabled = false,
		reverse = false,

		in = [					# Multiple source nodes are multiplexed
			"opal_node.data[0-4]",
			"signal_node.data[0-4]"
		],
		out = [					# Multiple destination nodes are supported too.
			"udp_node",			# All destination nodes receive the same sample
			"zeromq_node"			# Which gets constructed by the 'in' mapping.
		]
	},
	{
		in = "socket_node",
		out = "file_node",			# This path includes all available example hooks.

		# A complete list of supported hooks

		hooks = (
			{
				type = "print"

				output = "stdout"
				priority = 0
			},
			{
				type = "ts"

				priority = 1
			},
			{
				type = "decimate"

				ratio = 2			# Only forward every 2nd message
			},
			{
				type = "convert"

				mask = 0x1			# only convert the first value
				mode = "fixed"			# Convert all values to fixed precission. Use 'float' to convert to floating point.
				scale = 1.0
			},
			{
				type = "skip_first"

				seconds = 10			# Skip the first 10 seconds of this path
				# samples = 1000		# Skip the first 1000 samples
			},
			{
				type = "shift"

				mode = "origin",		# Shift origin timestam of samples by +10 seconds
				offset = 10			# Seconds
			},
			{					# Remap values within a sample.
				type = "map",			# The values of the new samples are constructed
								# from a concatenation of the following mapping entries.
				map = [	
					"data[0]",		# The first value of the original sample
					"data[2-5]",		# Values 3-6 of the original sample
					"hdr.sequence",		# The sequence no of the original sample
					"hdr.length",		# The number of values of the original sample
					"hdr.id",		# The id of the original sample
					"hdr.format",		# A bitmask of the format of each value
					"ts.origin",		# The timestamp as sent by the origin simulator
					"ts.received",		# The timestamp of the arrival time of the original sample
					"ts.send",		# The timestamp when this sample was sent (does not work)

					# Statistics of the current path. Allowed stats are:
					#  owd			One-way-delay (OWD) of received messages
					#  gap_sample		Inter-message timestamps (as sent by remote)
					#  gap_received		Inter-message arrival time (as seen by this instance)
					#  reordered		Reordered samples and the distance between them
					#  skipped		Skipped samples by hooks and the distance between them

					# For each stats the following details are available:
					"stats.owd.last",	# The last ovserved value
					"stats.owd.highest",	# The highest observed value
					"stats.owd.lowest",	# The lowest observed value
					"stats.owd.mean",	# The average observed value
					"stats.owd.var",	# The variance of the observed value
					"stats.owd.stddev",	# The standard deviation of the observed value
					"stats.owd.total"	# The total number ob observed values
				]
			}
		)
	}
);