Joule decentralizes signal processing into discrete modules. These modules are connected by streams as shown in the figure below. The interconnection of modules and streams form a data pipeline. A pipeline may execute as a single proces, a collection of processes, or even be distributed across multiple nodes in a network without adjusting any module code.


Joule pipelines are composed of modules and streams

Joule is a system service. Use the joule command to interact with the service.

# joule is a systemd service $> sudo service joule restart # use journalctl to view joule logs $> sudo journalctl -u joule.service ... journalctl output # use the joule CLI to interact with the service $> joule --help Usage: joule [OPTIONS] COMMAND [ARGS]...

Joule constructs the pipeline based on configuration files in /etc/joule. Details on these configuration files is provided in the sections below.

Module Configuration

Modules are executable programs managed by Joule. The module configuration format is shown below:

: Module Configuration File [Main] #required name = module name exec_cmd = /path/to/executable #optional is_app = no description = a short description # Specify command line arguments # (may also include in the exec_cmd) [Arguments] arg1 = val1 arg2 = val2 # additional arguments... [Inputs] path1 = /data/input/stream1 path2 = /data/input/stream2 # additional inputs... [Outputs] path1 = /data/output/stream1 path2 = /data/output/stream2 # additional outputs...

Module configuration files must end with the .conf suffix and should be placed in /etc/joule/module_configs. See the list below for information on each setting. Only the [Main] section is required, other sections should be included as necessary.

  • exec_cmd -- path to module executable, may include command line arguments

  • name -- module name

  • is_app -- [yes|no] whether the module provides a web interface

  • description -- optional module description

  • key = value -- keyword arguments (these may also be specified in the exec_cmd)

  • name = /stream/path -- output pipe configuration

Note: Reader Modules may only have a single output and no inputs. Filter modules have no restrictions on the number of inputs and outputs.

Pipe Configuration

Pipes connect modules to streams and are configured in the [Inputs] and [Outputs] section of the Module Configuration file. At a minimum the configuration specifies a pipe name and a stream path shown in Example 1 below.

: Pipe Configuration Format #1. basic configuration [pipe name] = [stream path] simple = /stream/path/simple #2. with inline stream configuration inline = /stream/path/inline:float32[x,y,z] #3. remote connection, must include inline stream config remote = /stream/path/remote:float32[x,y,z]

The pipe configuration can also include an inline stream configuration. This can be used in place of a DataStream Configuration file or in addition to it. Using both enables static type checking for the pipeline. The inline configuration is separated from the stream path by a colon :. The stream datatype is followed by a list of comma separated element names enclosed with brackets [ ]. If the stream is not explicitly configured or does not already exist in the database it is created with default attributes. In Example 2 above the inline pipe is connected to /stream/path/inline which has three float32 elements named x, y, and z. If this stream already exists with a different datatype or number of elements, Joule will not start the module.

Pipes can also connect to remote streams. To specify a remote source or destination add the URL and optional port number before the stream path. The URL is separated from the stream path by a single space. Remote pipes must include an inline stream configuration. In example 3 above the remote pipe is connected to /stream/path/remote on If this stream does not exist on node2, it will be created with default attributes. If it does exist with a different datatype, or number of elements, Joule will not start the module.

Streams can be connected to multiple input pipes but may only be connected to a single output pipe. If a module attempts to connect an output pipe to a stream that already has a producer, Joule will not start the module.

DataStream Configuration

Streams are timestamped data flows. They are composed of one or more elements as shown below. Timestamps are in Unix microseconds (elapsed time since January 1, 1970).































The configuration format is shown below:

: DataStream Configuration File [Main] #required settings (examples) name = stream name path = /stream/path datatype = float32 keep = 1w #optional settings (defaults) decimate = yes [Element1] #required settings (examples) name = stream name #optional settings (defaults) plottable = yes display_type = continuous offset = 0.0 scale_factor = 1.0 default_max = None default_min = None #additional elements...

DataStream configuration files must end with the .conf suffix and should be placed in /etc/joule/stream_configs. Both [Main] and [Element1] are required. For streams with more than one element include additional sections [Element2], [Element3], etc. See the list below for information on each setting.

  • name -- stream identifier, white space is permitted

  • path -- unique identifier which follows the Unix file naming convention. The web UI visualizes the path as a folder hierarchy.

  • datatype -- element datatype. Valid types for TimeScale backend (default):






    Valid types for NilmDB backend:











  • keep -- how long to store stream data. Format is a value and unit. Units are h: hours, d: days, w: weeks, m: months, y: years. For example 6d will keep the last six days of data. Specify None to keep no data or all to keep all data.

  • decimate -- [yes|no] whether decimated data will be stored for this stream. Decimation roughly doubles the required storage but enables web UI visualization.

  • name -- element identifier, may contain whitespace

  • plottable -- [yes|no] whether the element can be plotted

  • display_type -- [continuous|discrete|event] controls the plot type

  • offset-- apply linear scaling to data visualization y=(x-offset)*scale_factor

  • scale_factor-- apply linear scaling to data visualization y=(x-offset)*scale_factor

  • default_max-- control axis scaling, set to None for auto scale

  • default_min-- control axis scaling, set to None for auto scale

Streams may also be configured using an abbreviated inline syntax in a module's Pipe Configuration.

System Configuration

Joule uses a set of default configurations that should work for most cases. These defaults can be customized by editing /etc/joule/main.conf. Start joule with the --config flag to use a configuration file at an alternate location. The example main.conf below shows the full set of options and their default settings:

: /etc/joule/main.conf #default settings shown [Main] Name = # Module configuration files # files must end with *.conf ModuleDirectory = /etc/joule/module_configs # DataStream configuration files # files must end with *.conf StreamDirectory = /etc/joule/stream_configs # Listen on address # set to to listen on all interfaces # omit to only listen on UNIX socket # IPAddress = # Listen on port # required if IPAddress is specified # Port = 8088 # UNIX Socket directory (must be writable by joule user) SocketDirectory = /tmp/joule # PostgreSQL database connection # DSN format # username:password@[domain|ip_address]:port/database Database = # How often to flush stream data to database InsertPeriod = 5 # How often to remove old data (from DataStream keep settings) CleanupPeriod = 60 # How many lines to keep in each module log (rolling) MaxLogLines = 100 # Manager users with a configuration file # UsersFile = /etc/joule/users.conf # This section enables HTTPS, omit to run server with HTTP. # The default configuration produced by [joule admin initialize] # creates a self signed certificate and associated key. # To prevent MitM attacks, use a PKI to generate credentials [Security] # X.509 certificate Certificate = /etc/joule/security/server.crt # Private key for X.509 certificate Key = /etc/joule/security/server.key # Optional CA Certificate when using a PKI # CertificateAuthority = /etc/joule/security/ca.crt [Proxies] # forward local sites as joule interfaces # list proxies by [site_name = URL] example: # NOTE: do not use "localhost", use the address # rails_app =

See the list below for information on each setting.

  • Name Node name, a random value is generated by the joule admin initialize command

  • ModuleDirectory Absolute path to module configuration files. Only files ending with .conf will be loaded

  • StreamDirectory Absolute path to stream configuration files. Only files ending with .conf will be loaded

  • IPAddress IP address of interface to listen on. Use to listen on all interfaces.

  • Port TCP port to listen on

  • Database PostgreSQL connection information as DSN string. Format is username:password@[domain|ip_address]:port/database. Database must have TimescaleDB extension loaded and initialized.

  • InsertPeriod how often to send stream data to NilmDB (in seconds)

  • CleanupPeriod how often to remove old data (in seconds) as specified by stream keep parameters

  • MaxLogLines max number of lines to keep in a module log file (automatically rolls)

  • UsersFile control access using the specified file (example below), no reload is required.

  • [Security] This section enables HTTPS using the specified credentials. If this section is omitted the server will run with HTTP.

  • [Proxies] This section lists sites to proxy. This allows access to locally hosted sites through Lumen.

Example Users File Syntax:

: /etc/joule/users.conf # Specify user name and key separated by a , # Keys must be unique and at least 32 characters long # If the user exists with a different key, the key is updated. # ---------------------------------------------- # Name, Key alice, 044b1a5153e5f736cd787870cc949f2a bob, f5b37cd7207ac314a74d57d9c2ff8bb0 charlie, 126374f04d61ea485883f6fb287defc0 # Remove users using DELETE, add LIKE for SQL wildcard match (%,_) # ---------------------------------------------------------------- # remove any users with names that begin with temp DELETE LIKE temp% # remove the user named remote_admin DELETE remote_admin

Docker Configuration

Joule is available as a Docker container on Docker Hub. The container tags match the release versions on PyPi, use the latest tag to retrieve the most recent version of the container.

docker pull wattsworth/joule:latest

The container can be configured using environment variables as well as mounted volumes. Configuration variables with their default values are listed below:

  • NODE_NAME : joule name of the node

  • POSTGRES_USER : joule PostgreSQL username

  • POSTGRES_PASSWORD : joule PostgreSQL password

  • POSTGRES_HOST : postgres PostgreSQL host name or IP address

  • POSTGRES_PORT : 5432 PostgreSQL port number

  • POSTGRES_DB : joule PostgreSQL database name

  • USER_KEY : no default value, use a 32 character random string

  • HOST_PORT : 80 Forward facing port when running behind a reverse proxy

  • HOST_SCHEME : http Reverse proxy scheme (http or https)

In addition to these environment variables the container can be further customized by mounting the following volumes:

  • /etc/joule/configs/users.conf : user configuration file, this replaces the USER_KEY value

  • /etc/joule/configs/proxies.conf : list of sites to proxy. The format is the same as the main configuration file with one <name>=<url> pair per line.

For complete control of system configuration mount a volume to /etc/joule with a main.conf and files. This supersedes all other configuration options.