Items marked deprecated should not be used going forward as they will be removed in a future firmware release.
Most device attributes are simple name/value pairs with both the
name and the value consisting of strings. Two exceptions are the
path
and interface
attributes:
path
: The value of this attribute is a list of strings. The
list provides a unique path to the device. If present, it
must be the first attribute. This is the only attribute which
provides a guaranteed unique identifier for the device. The
flip-side is that the path is not necessary stable. For
example, if a USB device is moved from one port to another,
the path would change. Thus, depending on the needs of the
application, it may be more appropriate to identify a device
through other means, such as the manufacturer, model, and
serial-number, which, together, might provide a unique
identifier for the device that remains stable regardless of
how the device is connected to the meter.
interface
: The value of this attribute is also a list of
strings. Each entry is the name of an interface that is
supported by the device. A description of each interface can
be obtained from /ctrl/interface.
The meaning of other attributes is given below:
link
: The physical link used by the device. If present, the
value must be one of:
Ethernet
: The device is connected via Ethernet.
USB
: The device is connected via USB.
serial
: The device is connected via a serial link such as
RS485, RS232, or similar.
mfg
: The name of the manufacturer of the device (e.g.,
eGauge
).
model
: The model name of the device (e.g., PRM3
).
name
: If present, a user-selected name of the device.
prot
: The communication protocol used by the device. If
present, it must be one of:
CoAP
: The device uses the Constrained Application
Protocol.
CtrlByWeb
: The device uses the ControlByWeb XML protocol.
Modbus
: The device uses the
Modbus protocol.
RTCoA
: The device uses the Radio Thermostat Co of America
protocol.
SCPI
: The device uses the
SCPI
protocol (pronounced "skippy".
SMANet
: The device uses the SMAnet protocol used by older PV
inverters manufactured by SMA.
quality
: Devices that can potentially be reached through
multiple paths may set this attribute to indicate the
communication-quality of a particular path. The value of this
attribute must be a decimal string. Paths that provide better
communication-quality in some sense (e.g., higher speed or
smaller loss-rate) should have a higher value. When mapping a
set of attributes to a set of paths, the paths will be ordered
by decreasing quality value such that higher quality paths
will appear before lower quality ones.
sn
: The serial "number" of the device. Even though called a
number, the value may also contain non-digit characters (e.g.,
0Y0035
).
eScript is a simple scripting langage which supports basic arithmetic operations (addition, subtraction, multiplication, and division) of double-precision floating point numbers. The operations follow normal precedence rules. Parentheses can be used to force evaluation in a particular order. A C-like ternary operator is also supported for conditional evaluation. Specifically:
c ? e1 : e2
evaluates to e1
if c
is non-zero and to e2
otherwise.
The latest instantaneous value of a meter register can be obtained
with the $
operator which must be followed by a register name in
quotes. For example:
$"Grid"
would evaluate to the instantaneous value of register Grid
.
eScript also supports various functions such as sin()
to
calculate the sine of an angle or THD()
to calculate
total-harmonic distortion in a signal. A list of functions is
available at /sys/func.
An eScript expression which starts with a colon (:
) is
interpreted as a Lua expression.
Filter-specs can be used to return only certain members of an object or certain elements of an array.
For example, {foo,bar}
would limit the output of an object to the
members with names foo
and bar
. Similarly, [0,3:5]
would
limit the output of an array to the elements with indices 0, 3, 4,
and 5.
If a member or array filter is empty, all members/elements of that
object/array are returned. This is handy when filtering deeper
levels of a response. For example [{addr}]
would return only
member addr
from all the objects in the returned array.
For a more complex example, the filter-spec {reg[7:8{addr}]}
would, for each object in the response, only return the reg
member
and, within each reg
array, only elements with indices 7 or 8
would be returned. Within the objects of those elements, only the
addr
member would be returned.
Note that braces and square brackets normally need to be
percent-encoded before using them in a URL (e.g., %7B
for {
).
The formal syntax of a filter-spec (FSPEC) is given by the EBNF syntax below. No whitespace is allowed between symbols.
FSPEC = [OBJECT_FILTER | ARRAY_FILTER] .
OBJECT_FILTER = "{" MEMBER_FILTER {"," MEMBER_FILTER)} "}" .
ARRAY_FILTER = "["INDEX_FILTER {"," INDEX_FILTER)} "]" .
MEMBER_FILTER = [NAME | "(" NAME {"," NAME} ")"] FSPEC .
INDEX_FILTER = [RANGE | "(" RANGE {"," RANGE} ")"] FSPEC .
RANGE = UINT [ ":" UINT ] .
UINT = DIGIT { DIGIT } .
DIGIT = "0".."9".
NAME = ALPHA | DIGIT | "-" | "." | "_" | "~" | PCT_ENC .
ALPHA = "a".."z" | "A".."Z" .
PCT_ENC = "%" HEX HEX .
HEX = DIGIT | "a".."f" | "A".."F" .
EMPTY = .
In words: a filter-spec can restrict the members returned from an
object by listing zero or more member names, separated by commas, in
curly braces. Only listed member names will be returned. As a
special case, the empty object filter {}
returns all members. A
member name can be followed by a nested filter-spec to further
filter the value the member with that name. A common nested
filter-spec can also be applied to several comma-separated member
names by enclosing them in parentheses and writing the common
filter-spec after the closing parenthesis.
Similarly, a filter-spec can restrict the elements returned from an
array by listing zero or more indices, separated by commas, in
square brackets. Only listed indices will be returned. As a
special case, the empty array filter []
returns all elements in an
array. An index can be a single unsigned integer or a range of
indices written as a starting index, a colon, and an ending index.
For example, range 10:20
would corresponds to indices 10 through
20. An index can be followed by a nested filter-spec to further
filter the value of the element with that index. A common nested
filter-spec can also be applied to several comma-separated indices
by enclosing them in parentheses and writing the common filter-spec
after the closing parenthesis.
The link type of a remote device determines the communication protocol that is used to talk to the device and the format of the address string. Supported link-types are:
ailux
: This link type can be used to read data from heat
pump controllers manufactured by Alpha
Innotec. The address must be
the hostname or IP address of the heat pump controller. The
data is fetched from TCP port 8088 of the controller.
coap
: This link type can be used to read data from devices
that support the
CoAP
protocol. The address must be the hostname or IP address of
the device. The data is fetched from UDP port 5683.
ctrlbyweb
: This link type can be used to read data from
devices manufactured by
ControlByWeb. The address
must be the hostname or IP address of the device. An optional
port number may be specified after a colon (:
). By default,
port 80 is used. The data is fetched from the device with the
HTTP protocol.
modbus
: This link type can be used to read data from a
Modbus/TCP
device. The address must have the format
map.unit@host:port
:
map
: The name of the Modbus address map to use for the
device (see
/sys/modbus/client/map and
/config/modbus/client/map).
If the Modbus device supports the SunSpec
standard, this can be sunspec
instead. With SunSpec, the meter can automatically detect
the available Modbus registers.
unit
: The Modbus unit number of the device (defaults to 255).
host
: The hostname or IP address of the device.
port
: The port number to use. Defaults to the value of
map option default-tcp-port
, or port 502 if the option
is not present.
An example address is sunspec.1@192.168.1.34
which would
refer to a SunSpec-compatible device with unit number 1 and
IP address 192.168.1.34
.
po
: This link type can be used to read data from Aurora
solar inverters manufactured by Power One. The inverter's
serial port must be connected to an RS485-to-Ethernet adapter
such as the Chiyu
BF-430.
The default RS485 serial parameters used by the inverter are:
19200 baud, 1 stop bit, no parity. The address must have the
format devnum@addr:port
, where devnum
is the inverter's
serial address in the range from 2 to 254, addr
is the host
or IP address of the RS485-to-Ethernet adapter, and port
is the port number of the adapter.
rtcoa
: This link type can be used to read data from
thermostats manufactured by Radio Thermostat Company of
America. The address must
be the hostname or IP address of the thermostat. An optional
port number may be specified after a colon (:
). By default,
port 80 is used. The data is fetched from the device with the
HTTP protocol.
slowd
: This link type can be used to read data from various
devices connected over a serial port. The address must have
the format proto://devaddr
, where proto
is the name of the
communication protocol and devaddr
is a device-address in a
format that depends on the protocol. The available protocols
are:
alphatechnics
: Implements a proprietary protocol for
reading AlphaTechnics
5000
series precision thermometers. These devices have a USB
port which emulates a serial interface, so they can be
plugged directly into EG4xxx meters.
The serial port parameters default to 57600 baud, no
parity, and one stop bit. devaddr
must be a
serial-port name and optional
serial parameters.
An example address is alphatechnics://USB2
which would
connect to the thermometer plugged into the meter's USB2
port.
modbus
: Implements the
Modbus/RTU
protocol which can connect two or more devices over
RS485. devaddr
must have the format
modbus://map.unit@serdev
where:
map
: The name of the Modbus address map to use for
the device (see
/sys/modbus/client/map
and
/config/modbus/client/map).
If the Modbus device supports the SunSpec
standard, this can be sunspec
instead. With SunSpec, the meter can automatically
detect the available Modbus registers.
unit
: The Modbus unit number of the device. This
defaults to the value of map option
default-modbus-addr
or 0 if the option is not
present.
serdev
: The serial port
and optional serial parameters of the meter which is
wired to the RS485 bus. The serial parameters default
to the values given by map option
default-serial-params
or 19200 baud, no parity and 1
stop bit if the option is not present. Alternatively,
serdev
may also have the format host:port
where
host
is the hostname or IP address of an
RS485-to-Ethernet adapter and port
is an optional TCP
port number.
An example address is modbus://sunspec.1@USB1
which
would refer to a SunSpec-compatible device with unit
number 1, connected to the meter via serial port USB1
.
po
: Implements the protocol used by older Power One
Aurora inverters. These inverters are no longer being
manufactured and Power One has been acquired by
ABB.
The inverters are connected via RS485. The serial
communication parameters are 19200 baud, 1 stop-bit, and
no parity. devaddr
must have the format num@addr
where num
is the inverter's serial address in the range
from 2 to 254 and addr
is the name of the meter's
serial-port that is wired to the RS485 bus.
Alternatively, addr
may also be the hostname or IP
address of an RS485-to-Ethernet adapter that the bus is
wired to.
scpi
: Implements the
SCPI
(skippy) protocol. devaddr
must be a
serial-port name and optional
serial parameters or a hostname or IP-address of
serial-to-Ethernet adapter to which the SCPI-compatible
device is connected.
The registers available to be read are automatically
detected based on the result of SCPI command *IDN?
(Identify). Currently, only eGauge
PRM3 relay
modules are recognized.
sma
: Implements the SMA Data Communication protocol
which is used by older inverters and weather stations
manufactured by SMA. These devices
are connected via RS485. The serial communication
parameters are 1200 baud, 1 stop-bit, and no parity. The
protocol automatically detects connected devices and the
available registers. However, since the bus operates at
only 1200 baud, detection can take several minutes.
devaddr
must be the name of the meter's serial-port that
is wired to the RS485 bus. It may also be the hostname or
IP address of an RS485-to-Ethernet adapter that the bus is
wired to.
sony
: Implements a proprietary protocol for reading
certain Sony battery charge controllers (BMUs) over RS232.
Specifically, specification P5-9 027, version 2 is
supported. The serial port parameters are fixed to 19200
baud, even parity, and one stop bit.
devaddr
must have the format sony://num@addr
where:
num
: Is the number of the battery charge controller
to read from. It must be in the range from 0 to 15.
addr
: Must be the hostname or IP address of the
RS232-to-Ethernet adapter which the charge controller
is connected to.
An example address is sony://1@192.168.1.34:10001
which
would connect to battery charge controller 1 which is
wired to the RS232-to-Ethernet adapter at IP address
192.168.1.34, port 10001.
tcp
: This link type can be used to read the data from
another eGauge meter over the TCP protocol. The address must
be a hostname or IP address which may optionally followed by a
vertical bar character (|
) and a comma-separated list of
options. The available options are:
async
: This option must be used if two or more eGauge
meters read each other's data. This causes a cyclic
dependency which, without this option, would result in
timeouts and the inability to read the remote meter's
data. To break the cycle, it is sufficient for one of the
meters in the cycle to turn on this option. The downside
of turning on this option is that remote data will be
recorded at the time it is received by the local meter,
rather than the time when it was measured by the remote
meter, as would normally be the case.
sync
: This is enables the default synchronous read mode
where remote data is recorded with the time that it was
measured at by the remote meter.
spiky
: This option affects how data is recorded after
the remote meter is unavailable for a period of time. By
default, the local meter will smooth out any jumps
(spikes) in the data that are due to the remote meter not
being reachable. Turning on this option disables the
smoothing and instead records jumps as they occur.
Normally, smoothing is preferable. However, if a remote
meter is frequently unreachable (10% or more of the time),
the local meter will fall behind the remote meter data
more and more and, in such a case, turning on this option
would be advisable.
The remote data is fetched via HTTP protocol (TCP port 80). It is not possible to specify authentication credentials.
An example address is eGauge1234.local|sync,spiky
. This
would connect to the remote meter with hostname
eGauge1234.local
using the sync
and spiky
options.
tempalert
: This link type can be used to read data from
temperature sensors manufactured by Temperature Alert (no
longer in business). The address must be the hostname or IP
address of the sensor. The data is fetched from port 80 of
the device with the HTTP protocol.
udp
: This link type can be used to read the data from
another eGauge meter over a proprietary UDP protocol. As
such, it provides the same functionality as tcp
, but since
it runs over UDP, it is a lighter-weight, more efficient
protocol. The data is read from UDP port 59046. The address
syntax and available options are the same as for link type
tcp
.
The max-depth
parameter can be specified to limit
the depth to which a response object or array is output. When the
depth-limit is reached, only a list of member names is returned for
objects and only the length is returned for arrays.
For example, if the full result object were:
{"obj": {"a": ..., "b": ...}, "arr": [1, 2, 3, 4]}
then this restricted to max-depth=2
would return:
{"obj": ["a", "b"], "arr": 4}
That is, the value of obj
was replaced by the list of the
object's member names and the value of array arr
was replaced by
its length.
When a modification request to a resource is not executed transactionally, it means that it may be possible to observe the modification of that resource before or after modifications to the other resources being updated within the same request. It is also possible for the modification to take effect even though the overall request may end up failing with an error.
Passwords are never written directly to this API. Instead, only
hashes are written which are derived from the user name, realm,
and password. Specifically, the hash is calculated as the
MD5 sum over the string
obtained when concatenating the user name, the realm, and the
password while using colons as field-separators. For example, the
hash of user name jane
, realm domain
, and password secret
,
would be:
MD5("jane:domain:secret") = 251910de04f5eab86859939167d4fded
Physical register names may not be empty, contain control
characters, dots (.
), or commas (,
). They may also not
consist entirely of digits.
Register names of locally calculated registers (registers with
dev
set to local
)
attach special meaning to the last character (suffix):
+
: Allowed only for power-registers (type
code P
). Only positive power will be
accumulated.
-
: Allowed only for power-registers (type
code P
). Only negative measured
power will be accumulated.
|
: Allowed only for power-registers (type
code P
). The absolute value of the
measured power will be accumulated.
*
: Allowed only and required for apparent-power registers
(type code S
).
These suffixes are not allowed for registers whose value is calculated by an eScript expression.
If the name of a locally calculated power register does not end with one of the above suffixes, the measured net real power is accumulated. Net real power may be positive or negative, depending on the direction of the power flow.
A serial port may be specified either as a device name or as a USB
path. A device name must have the format /dev/ttyUSBn
, where
n
is a non-negative integer. A USB path must have the format
USBpath
where path
is a sequence of one or more non-negative
integers, separated by dots (.
). Resource
/sys/dev/serial returns a list of serial
ports detected by the meter.
A serial port string may optionally also specify serial
parameters. The parameters must follow the device name and have
the format :b/8ps
where b
is the baud rate (positive integer),
8
is the number of bits per character (must be 8), p
is the
parity (n
for none, e
for even, o
for odd), and s
is the
number of stop bits (1 or 2).
WebAPI provides an automatic mechanism to setup communication between a meter and a service provider (web server). The resulting communication path can be used, for example, to send register data ("push data") or alerts to the service provider.
The setup mechanism is called service activation and is initiated by posting a request to end-point /cmd/activate. The command, in turn, executes the follow steps:
Meter sends an activation request to a URL defined by the service provider. This URL is called the control URL.
The service provider may respond with an error, a challenge, or a service URL. If an error is returned, service activation has failed and an error response is returned. If a challenge is returned, execution resumes with step 3 below. If a service URL is returned, execution resumes with step 4.
Given a challenge response, the meter decrypts the challenge using a private key and sends the result to the service provider. The service provider checks if the result is valid and, if so, responds with a service URL. Otherwise, it responds with an error and service activation has failed.
The meter extracts the service URL from the service provider's response and starts sending data to that URL. With this, service activation has completed sucessfully.
Once activated, the meter will send data to the service URL as needed (e.g., periodically for push data or when an alert occurs for the alert service). This stops if a post to the service URL returns HTTP status code 418 (I'm a teapot) or if the meter gets reconfigured to deactivate the service.
The details of the above steps are described below.
The activation request the meter sends to the control URL is a
POST
request with a JSON-body containing the following members:
name
(required): The hostname
of the meter.
sn
(required): The serial-number of the
meter.
opts
: If present, this is an array of strings specifying the
service options that are understood by the meter for the service
being activated. If not present, the service provider must
assume that the meter does not understand any service options.
Additional members may be present in the posted object. If so, the service provider must ignore any members whose meaning it does not understand.
A typical activation request body is shown below (formatted for readability):
{
"name": "Test1234",
"sn": "G13456789",
"opts": ["gzip", "json", "secure"]
}
A service provider may choose to return a challenge response to ascertain that the activation request was actually sent by the meter identified in the request. If the service provider does not require authentication, it can skip to directly returning a service URL response (see below).
A challenge response consists of a JSON-object with the following members:
nnc
(required): The server nonce. This must be a string
consisting entirely of lowercase hexadecimal digits (0-9, or
a-f). The server creates this nonce by:
generating a sequence of cryptographically random bytes,
encrypting the sequence with the meter's public key, and, finally,
converting the encrypted sequence to a hexadecimal string.
rid
(required): A non-negative integer that uniquely identifies
this service activation request.
Additional members may be present in the returned object. If so, the meter will ignore any members whose meaning it does not understand.
Once the meter receives a challenge response, it:
rnd
,creates a cryptographically strong random hexadecimal string
which we'll call cnnc
(client nonce),
calculates the MD5 hash of the string obtained by
concatenating rnd
, a colon (:
), and cnnc
.
sends a post request to the control URL whose body is a JSON object with the following members:
cnnc
(required): The client nonce.
hash
(required): The calculated MD5 hash as a hexadecimal
string.
rid
(required): A copy of the rid
member as received in
the challenge response.
When the service provider receives the post request, it can check
whether the meter is authentic by calculating the MD5 sum of the
concatenation of the server's random hexadecimal string rnd
, a
colon, and the client nonce and confirming that it matches the
value of hash
in the posted JSON object. If there is a
mismatch, service activation has failed and the provider returns
an error response.
A typical challenge response is shown below (formatted for
readability and nnc
shortened with an ellipsis):
{
"nnc": "76e75...9fbc",
"rid": 4102166033
}
In return to this challenge, the meter would then send a post request to the control URL with a body that might look like this:
{
"cnnc": "565ce9541eddec103347b5174704e188",
"hash": "ce5e308c27da651964de14f65bd8b059",
"rid": 4102166033
}
If the authentication is successful, the service provider responds with a service URL response.
Upon successful service activation, the provider returns a response body containing a JSON object with the following members:
url
(required): The service URL to which the service's data
should be sent.
options
: The service options to use. This must be a string
containing a comma-separated list of option names. Certain
options may require a value. For those, the option name must be
followed immediately by an equal sign (=
) and the option value
(no whitespace is allowed).
pw
: If specified, the password to use when sending the post
request to the service URL.
user
: If specified, the username to use when sending the
post request to the service URL. The username and password are
sent using an HTTP basic authentication
header. For
security reasons, this should only be used over secure (https
)
connections.
Additional members may be present in the returned object. If so, the meter will ignore any members whose meaning it does not understand.
{
"url": "https://provider.com/alert/post/a08b44098",
"options": "json,gzip,min_prio=7"
}
If service activation fails, HTTP status 200 must be returned with
a response body which contains member error
. The value of
error
must be a string explaining why service activation failed.
The string is typically in the locale of the service provider.
The returned JSON object may contain additional members which the meter must ignore.
A time expression defines a single point in time. An absolute time expression is a number, a time-point name, or a function call. A number is interpreted as a Unix timestamp. Time-point names are described here. A function call consists of a name, immediately followed by a time expression in parentheses. The following supported function names and their meaning are as follows:
soy(t)
: Returns the timestamp of the start of the year in
which t
falls.
soq(t)
: Returns the timestamp of the start of the quarter in
which t
falls.
sob(t)
: Returns the timestamp of the start of the billing
cycle in which t
falls. Server-storage
variable global/billing/start_day
establishes the day of the
month a new billing period starts. If that day is greater than
the number of days in the current month, the last day of that
month is taken as the start of the billing period. The new
billing cycle is assumed to start at 12pm on the billing day
(meter-local time).
som(t)
: Returns the timestamp of the start of the month in
which time t
falls.
sow(t)
: Returns the timestamp of the start of the week in
which t
falls. Monday is considered to be the start of
the week.
sod(t)
: Returns the timestamp of the start of the day in
which t
falls.
soh(t)
: Returns the timestamp of the start of the hour in
which t
falls.
soQ(t)
: Returns the timestamp of the start of the quarter
hour in which t
falls.
soM(t)
: Returns the timestamp of the start of the minute in
which t
falls.
sos(t)
: Returns the timestamp of the start of the second in
which t
falls.
An absolute time expression may be followed by one or more offsets that are added to or subtracted from the value of the absolute time expression. Each offset starts with a plus or minus sign, an integer number, and an optional unit. Without a unit, the specified number may contain a fractional part and indicates the number of seconds to be added/subtracted. Otherwise, the unit may be one of:
y
: yearsq
: quartersb
: billing-cyclesm
: monthsw
: weeksd
: daysh
: hoursQ
: quarter-hoursM
: minutesFor an offset with a unit, the specified number of time periods
are added to/subtracted from the timestamp. For example,
som(now)+1d-1h
would return the start of the last hour of the
first day of the current month as som(now)
returns the start of
the current month, +1d
would add one day to that, and -1h
would subtract 1 hour from the result.
Due to irregularities in the Gregorian calendar, normal rules of
addition do not apply and the order in which the offsets are
applied is significant. When adding/subtracting months or
billing-cycles, the operations ensures that the final date is
valid. For example, adding 1m
to January 31st would yield the
last day of February, which would be either February 28th or 29th,
depending on whether or not the year is a leap-year.
The full syntax for a time expression is given in EBNF syntax below:
TIME = ABSOLUTE {("+" | "-")OFFSET} .
ABSOLUTE = UNIX_TS | POINT_NAME | FCALL .
UNIX_TS = ["+"|"-"] SECONDS .
FCALL = FNAME "(" TIME ")" .
FNAME = "soy" | "soq" | "sob" | "som" | "sow" | "sod" | "soh" | "soQ" | "soM" .
POINT_NAME = "now" | "epoch" | FNAME .
OFFSET = (UNSIGNED_INTEGER UNIT) | SECONDS.
UNIT = "y" | "q" | "b" | "m" | "w" | "d" | "h" | "Q" | "M".
SECONDS = UNSIGNED_INTEGER ["." UNSIGNED_INTEGER] .
A time point name that consists of a function name which is not
immediately followed by a left parenthesis is interpreted as if
the function of the same name had been called on the current time
(now
). For example, sod
is equivalent to sod(now)
.
Time-point names provide a way to refer to both absolute points in time as well as times relative to the current time. Specifically:
now
: The most recent time for which the meter has collected
data.
epoch
: The time at which the meter started recording data.
That is, the oldest time for which the database will return
data. This time is user configurable via
/config/db/epoch.
soy
: Short for soy(now)
.
soq
: Short for soq(now)
.
sob
: Short for sob(now)
.
som
: Short for som(now)
.
sow
: Short for sow(now)
.
sod
: Short for sod(now)
.
soh
: Short for soh(now)
.
soQ
: Short for soQ(now)
.
soM
: Short for soM(now)
.
A time range is an ordered series of Unix
timestamps which are spaced out at a
certain interval between two points in time. Time ranges are
written as three decimal numbers, separated by colons:
start:step:stop
, where start
is the oldest timestamp, step
is the interval between timestamps, and stop
is the youngest
timestamp. For example, 100:1:103
would correspond to the
timestamp series [100, 101, 102, 103]
. If step
and the
subsequent colon are left out, the interval defaults to one
second. If step
is an empty string, the range consists of only
the start and end timestamps. For example, 100::103
would
correspond to [100, 103]
. If the timerange consists of only a
single number, it is interpreted as a singleton consisting of only
the specified time.
The timestamps are generated from youngest
to oldest
. Thus, if
the oldest timestamp is not an integer-multiple of step
apart
from youngest
, then the oldest timestamp will not be in the
series of generated timestamps.
In general, start
and stop
can be not just Unix timestamps
but arbitrary time expressions.
Similarly, the time step may also be expressed as an integer count
followed by a unit character. The available units are the same as
for offsets in time expressions. For example, 1d
would step
through the time range one day at a time, taking daylight savings
into account (assuming the correct
timezone is set on the meter).
As a complete example, the time range som:1d:sod
would generate
the timestamps that correspond to midnight each day of the current
month to date. sod
is the start (midnight) of today and from
there, the timestamps step back one day at a time until som
, the
start of the month is reached.
When a time range is used to select rows from the database, the
resulting timestamps may not align with the timestamps of the rows
stored in the database. When this happens, the meter will, by
default, round down the specified timestamp to that of the nearest
older row. However, if the starting or ending timestamp starts
with a plus sign (+
), the meter will instead round the timestamp
up to that of the nearest younger row.
The full syntax for a time range is given in EBNF syntax below:
TIME_RANGE = [FROM ":" [[STEP] ":"]]TO .
FROM = TIME_WITH_ROUNDING .
TO = TIME_WITH_ROUNDING .
STEP = OFFSET .
TIME_WITH_ROUNDING = ["+"]TIME .
See section Time Expressions for definitions of OFFSET and TIME.
Each register records values in a physical unit indicated by a type code. Apart from the physical unit, the type code also defines the quantum with which a value is recorded in the database.
To understand the role of the quantum, you need to know that the
database stores all values as signed 64-bit integer numbers. For
all type codes except d
(discrete numbers), the meter
accumulates values before storing them in the database. Let us
see how this is done for a sensor that measures a voltage. If we
look up type code V
in the table below, we see that the quantum
q for a voltage is 0.001. Now, suppose the voltage v of a
sensor was measured to be 120V on average over a measurement
interval dt of one second and that the previous accumulated
value of that sensor was c0. The meter would then calculate the
new accumulated value c1 as:
c1 = c0 + round(v / quantum)·dt
or
c1 = c0 + round(120V / 0.001)·1s = c0 + 120000 V·s
This new accumulated value is then stored in the database. In other words, for every second where the average voltage is 120V, the value stored in the database would increase by 120000. This also shows that the accumulated values stored in the database have a unit that is the rate unit multiplied by seconds. For volts, that turns into volt-seconds. Similarly, power in watts would be recorded as watt-seconds (or joules), and speed in meters-per-second would be recorded as meters.
Note that an accumulated value may eventually overflow if the measured rate has predominantly the same sign for a very long period of time. If that were to happen, the value would wrap around from a large positive value to a large negative value or vice versa. The quanta have been selected such that under normal circumstances, wrap-arounds will not occur within the lifetime of a meter. Nevertheless, when calculating how much an accumulated value changed between two points in time, we recommend calculating that difference modulo 263 since that will give the correct result provided at most one wrap-around occurred between the two points in time.
Discrete numbers (type code d
) are unit-less and are used to
record discrete states (such as error states or bitsets). Such
quantities cannot be averaged and hence they are not accumulated.
Instead, they are stored directly as signed 64-bit integers in the
database.
Type code | Physical quantity | Rate unit | Quantum |
---|---|---|---|
# |
Whole number | 1 | |
#3 |
Number with 3 decimal places | 0.001 | |
% |
Percentage | % | 0.001 |
$ |
Monetary accrual rate | ${currency}/s | 2-29 |
a |
Angle | ° | 0.001 |
aq |
Air quality index (0=good, 500=bad) | s | 0.001 |
d |
Discrete number | 1 | |
Ee |
Irradiance | W/m2 | 1 |
F |
Frequency | Hz | 0.001 |
h |
Relative humidity | % | 0.001 |
I |
Electrical current | A | 0.001 |
m |
Mass | g | 0.001 |
P |
Power | W | 1 |
Pa |
Pressure | Pa | 1 |
ppm |
Parts per million | ppm | 0.001 |
var |
Reactive power | var | 1 |
Q |
Mass flow | g/s | 1 |
Qe |
Electric charge | Ah | 0.001 |
Qv |
Volumetric flow | m3/s | 10-9 |
R |
Electric resistance | Ω | 1 |
S |
Apparent power | VA | 1 |
T |
Temperature | °C | 0.001 |
THD |
Total harmonic distortion | % | 0.001 |
V |
Voltage | V | 0.001 |
v |
Speed | m/s | 0.001 |
Note For the monetary unit, ${currency}
should be replaced
by the the currency symbol applicable to the region the meter is
installed in. The builtin user interface of the meter uses the
value of server-storage variable
global/default/currency_symbol
for this purpose or, if
undefined, a dollar sign ($
).
A Unix timestamp is a number that counts the seconds since the start of January 1, 1970 UTC.
Users may have the one or more of the following privileges:
unlimited_save
: The user may change (save) the meter
configuration.
local_save
: The user may change (save) the meter
configuration but only when connected over a local network
connection. LAN-connections are considered local if the user's
browser is on the same subnet as the meter. Bluetooth
connections are always considered local. All other connections
(e.g., via proxy server) are considered not local.
view_settings
: The user may view the meter configuration.
Without this privilege, the user only has access to
configuration settings that are directly related to the user.
ctrl
: The user may issue control operations such as putting
a device in a particular operational state (e.g., opening or
closing a relay or setting the temperature on a thermostat).
restricted_view
: The user only has restricted access to the
meter data. Specifically, the user may only view registers in
the view that matches the user
name.
While access to the device is generally governed by these privileges, there are two exceptions:
* Users without `view_settings` privilege may still read their
own user configuration (but not that of any other user).
* Users without `save` privilege (`unlimited_save` or
`local_save`) may still change their own password.
Views are used to group related registers. For example, if a single meter measures multiple apartments, a separate view could be defined for each apartment. A user-interface can then offer to display all measurements for a particular apartment by selecting the desired apartment's view name. Similarly, users can be setup so that they may access only a particular view. That way, views can be used to ensure, for example, that each apartment tenant can only view their own data.
In this API, view names are defined as part of a register name.
Specifically, the view name is written as prefix of the register
name, followed by a dot. For example, the string apt1.cooktop
defines register cooktop
as being part of view apt1
.
The values of virtual registers are calculated based on the values
of physical registers. The formulas for these calculations are
limited to addition and subtraction. When expressed as a JSON
string, virtual register formulas are written as a sequence of
register names which are prefixed either by a plus sign (+
) to
indicate addition or by a minus sign (-
) to indicate
subtraction. The register names are enclosed in double-quotes.
Within a register name, a double-quote character can be included
by prefixing it with a backslash character: \"
. Likewise, to
include a literal backslash character in the name, it must be
doubled up and written as \\
.
As an example, the formula:
+"Panel \"A\""+"Solar+"-"EV"
would calculate the virtual register value by adding the values of
registers Panel "A"
and Solar+
and then subtracting the value
of register EV
.
Note
Old meters may still use deprecated operators in virtual register
formulas. The syntax for these operators is op(reg,n)
where
op
is either MIN
or MAX
(case-sensitive), reg
is a
register name, and n
is an integer constant (usually 0). These
operators are deprecated because they only work correctly when the
formula is applied to rates, not when applied to accumulated
register values. When applied to rates, these operators should
work as follows:
MAX(reg,n)
: Returns the value of register reg
if it is
greater than n
or n
otherwise.
MIN(reg,n)
: Returns the value of register reg
if it is
less than n
or n
otherwise.