eGauge Meter Communication

Covers meter communication options, including Modbus TCP/RTU, BACnet, and remote eGauge meters.


Information about the eGauge meter's JSON-based API



The WebAPI documentation may be found at

The eGauge WebAPI is a JSON-based API framework that allows for automated meter configuration, recorded data retrieval, status information, and more.

eGauge Systems provides a Python library to assist with authentication and other interactions with the eGauge meter WebAPI and can be obtained from Bitbucket or PyPi (pip).

Getting Started With Python

To make it easy to get started, eGauge provides an open source Python package. It can be installed with the command:

pip install egauge-python

With this package installed, accessing an eGauge meter becomes very simple. For example, to fetch the hostname of the meter, you could use:

from egauge import webapi

URI = "" # replace DEV with meter name
USR = "USER" # replace USER with user name
PWD = "PASS" # replace PASS with password

dev = webapi.device.Device(URI, webapi.JWTAuth(USR,PWD))

print("hostname is " + dev.get("/config/net/hostname")["result"])

The package also contains various convenience classes to read meter data, capture waveform samples, convert between physical units, and so on.

The official GIT repository for this package is at Various code examples can be found in the examples directory.

Getting started without the eGauge Python library

Check out the support library page on WebAPI Authentication for examples on authentication.

Common WebAPI service descriptions

See the WebAPI documentation for full details and all service endpoints available. The endpoints below are only several commonly accessed endpoints that retrieve data and configuration.


The /config service allows you to read and write configuration to the meter.


The /register service provides instantanoues and historical register data that is recorded on the meter.


The /local service provides instantaneous information derived from configured channel inputs, including RMS value, mean value, frequency value and instantanoues power and energy values if power registers are configured.

For historical or newly generated register data, use the /register service.


The /capture service is used for obtaining raw waveform data from the inputs. To obtain normal RMS, mean or frequency from the sensors directly, use the /local service. For obtaining stored or newly generated register data, use the /register service.

Other WebAPI service descriptions

Below are the additional service endpoints not listed above. See the WebAPI documentation for full details and all service endpoints available.


Service used to obtain or invalidate a JSON web token used for authenticating with the WebAPI.


Service used to send commands to the meter such as reboot or firmware upgrade.


Service used to read or configure CTid sensors from a meter or flash the LED on the sensor (EG4xxx only).


Service used for controlling supported remote devices, such as the PRM3 relay module.


Service used to access syslog or kernel logs. Syslog must be enabled through the /config service endpoint first.


Service used for managing Lua scripts on the meter.


Service used for obtaining information about third-party providers that support meter services such as push data sharing, push alerts, and tariffs.


Service used for storing and retrieving preferences and other settings typically used in the user's web browser interface.


Service used for configuring remote devices on the meter.


Service used to obtain system information such as firmware version, uptime, serial number, meter model, and more.



View the /auth section information in the WebAPI documentation for full details on the authentication methods of the eGauge meter WebAPI.

The eGauge WebAPI uses JSON web token (JWT) authentication for all interactions. An "Authorization" header must be provided with WebAPI requests in the format of Authorization: Bearer JWT where JWT is a valid JSON web token.

Tokens typically expire after 10 minutes and need to be renewed periodically.

Authentication workflow

  1. Send a GET to /auth/unauthorized to get a 401 to get the realm (rlm) and server nonce (nnc)

  2. Generate a client nonce (cnnc)

  3. Calculate hash in the format:

    ha1 = MD5(usr:rlm:pwd)
    hash = MD5(ha1:nnc:cnnc)
    where usr and pwd are a valid user and password on the meter

  4. Send rlm, usr, nnc, cnnc and hash to /auth/login for the token

Authentication in Python

eGauge Systems provides a Python library with helper functions to deal with authentication and other interactions. See the WebAPI introduction page for more information.

#!/usr/bin/env python3

# Example Python script obtaining a JSON web token (JWT) from a meter's WebAPI.
# JWTs are needed for any interactions with the meter's JSON-based WebAPI.

# eGauge provides a Python library that handles authentication automatically and
# provides additional helper functions. It may be found on Bitbucket or PyPi

# Main WebAPI documentation:

import requests
import hashlib
from secrets import token_hex

# meter and credential information
URI = ""
USER = "admin"
PASS = "as$kS2345da2@4vK9"

# get realm (rlm) and server nonce (nnc):
auth_req = requests.get(f"{URI}/api/auth/unauthorized").json()
realm = auth_req["rlm"]
nnc = auth_req["nnc"]

cnnc = str(token_hex(64)) # generate a client nonce (cnnc)

# generate our hash
# ha1 = MD5(usr:rlm:pwd)
# hash = MD5(ha1:nnc:cnnc)
ha1_content = f"{USER}:{realm}:{PASS}"
ha1 = hashlib.md5(ha1_content.encode("utf-8")).hexdigest()

hash_content = f"{ha1}:{nnc}:{cnnc}"
hash = hashlib.md5(hash_content.encode("utf-8")).hexdigest()

# Generate our payload
payload = {
    "rlm": realm,
    "usr": USER,
    "nnc": nnc,
    "cnnc": cnnc,
    "hash": hash

# POST to /auth/login to get a JWT
auth_login ="{URI}/api/auth/login", json=payload).json()

rights = auth_login["rights"] # rights this token has (save, control, etc)
jwt = auth_login["jwt"] # the actual bearer token

print(f"Got token with rights {rights}.")

# We can verify this token works.
# Add an authorization header with our token and make a request
headers = {"Authorization": f"Bearer {jwt}"}

api_request = requests.get(

# {'result': 'eGauge67385'}

# This token may be used until it expires, in which case a 401 response will be
# returned, to which this process can be reperformed.

Authentication with Bash

This bash script uses curl and jq to obtain a JWT for use with the WebAPI.


auth_req=$(curl -s "$URI/api/auth/unauthorized")
rlm=$(jq -r '.rlm' <<< $auth_req)
nnc=$(jq -r '.nnc' <<< $auth_req)
cnnc=$(openssl rand -hex 64)

ha1=$(echo -n "$USER:$rlm:$PASS" | md5sum | cut -f1 -d" ")
hash=$(echo -n "$ha1:$nnc:$cnnc" | md5sum | cut -f1 -d" ")

auth_login=$(curl -s -X POST "$URI/api/auth/login" \
     -H "Content-Type: application/json" \
     -d "{\"rlm\": \"$rlm\", \"usr\": \"$USER\", \"nnc\": \"$nnc\", \"cnnc\": \"$cnnc\", \"hash\": \"$hash\"}")

jwt=$(jq -r '.jwt' <<< $auth_login)

api_request=$(curl -s "$URI/api/config/net/hostname" -H "Authorization: Bearer $jwt")

echo $api_request

Register Data Examples

This page contains a few basic examples of obtaining historical register data from an eGauge meter using the WebAPI.

These examples use the eGauge Python library but other languages and libraries may be used.

Get Instantaneous values

Request: dev.get('/register?reg=3+5+7+9&rate')

reg=3+5+7+9 asks for those register IDs
rate asks for the instantaneous rate of change at the time
No time parameter was provided, so it gets the latest value


  "ts": "1679506470.000420096",
  "registers": [
    {"name": "Panel 3 Mains", "type": "P", "idx": 3, "did": 0, "rate": 2400},
    {"name": "Panel 3 L1",    "type": "P", "idx": 5, "did": 2, "rate": 551},
    {"name": "Panel 3 L2",    "type": "P", "idx": 7, "did": 3, "rate": 1080},
    {"name": "Panel 3 L3",    "type": "P", "idx": 9, "did": 4, "rate": 769},

Get 6 hour period of historical data

Request: dev.get('/register?reg=3+5+7+9&rate&time=1672556400:3600:1672578000')

reg=3+5+7+9 asks for those register IDs
rate asks for the instantaneous rate of change at the time
time=1672556400:3600:1672578000 is:


    "ts": "1679505959.000420096",
    "registers": [
        {"name": "Panel 3 Mains", "type": "P", "idx": 3, "did": 0, "rate": 4185},
        {"name": "Panel 3 L1",    "type": "P", "idx": 5, "did": 2, "rate": 506},
        {"name": "Panel 3 L2",    "type": "P", "idx": 7, "did": 3, "rate": 2902},
        {"name": "Panel 3 L3",    "type": "P", "idx": 9, "did": 4, "rate": 777},
    "ranges": [
            "ts": "1672578000",
            "delta": 3600.0,
            "rows": [
                ["150555067851", "64158660544", "57705425071", "28690982234"],
                ["150552980706", "64157713471", "57704901028", "28690366205"],
                ["150550413006", "64156764160", "57703892567", "28689756277"],
                ["150548310776", "64155810457", "57703366875", "28689133443"],
                ["150546201980", "64154853051", "57702841741", "28688507186"],
                ["150543949276", "64153896433", "57702279596", "28687773245"],
                ["150541826993", "64152938219", "57701751003", "28687137769"],


Parse output the same way that would be done for XML data.

Each row is delta seconds (3600) older than the previous row. The columns are in order of the registers, that is the first value in each row is for "Panel 3 Mains", the second value in each row is for "Panel 3 L1", and so on.

Row 1:
150555067851 is the cumulative value of "Panel 3 Mains" at time "ts" (1672578000 = Jan 1 6:00AM)
64158660544 is the cumulative value of "Panel 3 L1" at time "ts" (1672578000 = Jan 1 6:00AM)
57705425071 is the cumulative value of "Panel 3 L2" at time "ts" (1672578000 = Jan 1 6:00AM)

Row 2:
150552980706 is the cumulative value of "Panel 3 Mains" at time "ts"-"delta"*1 (1672578000-3600*1 = Jan 1 5:00AM)

Row 3:
150550413006 is the cumulative value of "Panel 3 Mains" at time "ts"-"delta"*2 (1672578000-3600*2 = Jan 1 4:00AM)

Row 4:
150548310776 is the cumulative value of "Panel 3 Mains" at time "ts"-"delta"*3 (1672578000-3600*3 = Jan 1 3:00AM)

Row 7:
28687137769 is the cumulative value of "Panel 3 L3" at time "ts"-"delta"*6 (1672578000-3600*6 = Jan 1 12:00AM)

For example, "Panel 3 Mains", between 12:00AM and 6:00AM on Jan 1 used (150555067851-150541826993)/3,600,000 == 3.679 kWh

Get 3 particular timestamps

Request: dev.get('/register?reg=3:5&time=1672556400,1672642800,1672729200')

reg=3:5 asks for registers starting at ID 3 and ending at ID 5
time=1672556400,1672642800,1672729200 requests the values at timestamps of:


    "ts": "1679507855.000420096",
    "registers": [
        {"name": "Panel 3 Mains", "type": "P", "idx": 3, "did": 0},
        {"name": "Panel 3 Mains*", "type": "S", "idx": 4, "did": 1},
        {"name": "Panel 3 L1", "type": "P", "idx": 5, "did": 2},
    "ranges": [
            "ts": "1672556400",
            "delta": 60.0,
            "rows": [["150541826993", "182491473811", "64152938219"]],
            "ts": "1672642800",
            "delta": 60.0,
            "rows": [["150591166950", "182556552340", "64175776009"]],
            "ts": "1672729200",
            "delta": 60.0,
            "rows": [["150704245365", "182691087288", "64205578174"]],


Parse the same as XML output. There are 3 ranges, one for each of the requested timestamps, and each register's cumulative value at that time.

For example:

The last range shows on January 1 ("ts" of 1672729200) that "Panel 3 L1*" (middle column) had a cumulative value of 64205578174 watt-seconds.

The second to last range shows on January 2 ("ts" of 1672642800) that "Panel 3 L1*" (middle column) had a cumulative value of 64175776009 watt-seconds.

This means between January 1 and January 2, the "Panel L1" register changed by (64175776009-64205578174) = -29802165 watt-seconds, which is -29802165/3600000 = -8.27 kWh

Depending on the orientation of the amperage sensor (CT), the power/energy will register as positive or negative. If there is unidirectional power (no back-feeding, etc.) it is usually safe to take the absolute value between dates. However, unexpected power polarity can also be caused by physical installation issues that are generating innacurate data.


eGauge has a free XML-format API for requesting data


Interpreting XML data and examples

Contained in this article:

  1. General Information
  2. Example: Energy and power for specific dates

General Information

XML data is sent with cumulative register values. In the case for power registers, the cumulative values are in watt-seconds. To convert watt-seconds to kWh, divide the watt-seconds by 3,600,000. Cumulative values can be imagined as meter readings at that point in time, where consumption readings continuously increase over time. To get the kWh usage between two dates, subtract the more recent value from the older value and divide by 3,600,000.

EG4xxx meters support TLSv1.2, while EG30xx only supports TLSv1.0

At the bottom of the page is the output of a minute granular export showing the past ten minutes of cumulative data (obtained with the URL time_stamp represents the time of the export (unix timestamp in hex); time_delta indicates the time in seconds between exports; epoch represents the date and time recording started on that device (unix timestamp in hex).  

Each <cname> tag contains data on a column header; in this case, that translates to a physical register on the device. t indicates the register type (P for power, V for Voltage, etc) and the text inside the tag represents the register name as recorded on the device. Virtual registers may also be shows in the appropriate parameter is passed in the initial request.

Each row (<r> tag) contains a series of columns (<c> tag) that show the cumulative value of each register. To determine the average value of a register over a given time, simply find the difference between the two cumulative values and divide by the appropriate time delta. The resulting values are expressed in units based on the register type (see the chart in section 2.2.1 of the XML API document for the unit type).  It should be noted that prior to firmware 3.01 cumulative values do not necessarily count up from zero. On firmware 3.01 and newer passing the option when requesting data returns values relative to device epoch (ie, values start at zero). Using the parameter epoch in a data push has the same effect. This assumes that the date and time recording started option is set correctly on the eGauge.

Some examples (based on the sample output below):

Average Grid usage over the most recent minute 55357226851 - 55357243343 = −16492 / 60 = -274.86 Watts (remember, Power registers are bidirectional)

Average Voltage L2 over ten minutes 4511385868513 - 4511319123106 = 66745407 / 600 = 111242.345 mV / 1000 = 111.24 Volts


<group serial="0x4e842294">
<data columns="12" time_stamp="0x564cb0e8" time_delta="60" epoch="0x55973268">
<cname t="P">Grid</cname>
<cname t="S">Grid*</cname>
<cname t="V">VL2</cname>
<cname t="V">VL1</cname>
<cname t="F">Frequency</cname>


Example: Energy and power for specific dates

You can make CGI calls to http://DEV-URL/cgi-bin/egauge-show where DEV-URL is the URL of your eGauge (for example, 

The T parameter lets you request data from specific points in time. It expects a comma separated list of Unix time-stamps.

The E parameter requests the values be relative to the Date and Time when recording started. This needs to be set correctly in Settings -> Date & time when recording started. It effectively makes the reading start at zero when the date and time when recording started is set to, otherwise the raw database value could be arbitrary. This requires firmware v3.02 or greater.

The a parameter requests total and virtual registers, such as "Usage" and "Generation". This is optional.,1483228800 returns data for January 1 2018 00:00:00 UTC, and January 1 2017 00:00:00 UTC respectively, using epoch-relative values and requesting total and virtual registers. The output below has all the other registers except for Usage and Generation removed for readability.

<group serial="0x3b2d1cb7">
  <data columns="27" time_stamp="0x5a497a00" time_delta="60" epoch="0x52a0f760">
    <cname t="P">use</cname>
    <cname t="P">gen</cname>
  <data time_stamp="0x58684680" time_delta="900">

Generation is zero because there is none recorded on this device.


Usage for timestamp 0x5a497a00 (Jan 1 2018) is 241517238757 joules (241517238757/3600000 =  67088 kWh).

Usage for timestamp 0x58684680 (Jan 1 2017) is 171138633823 joules (171138633823/3600000 = 47538 kWh).

If you want power instead of energy, subtract the values and divide by the amount of time between them:

67088 kWh - 47538 kWh = 19550 kWh were used between 2017 and 2018. 1 year is 8760 hours, so 19550 kWh / 8760 h = 2.23 kW average over the year. This can be done using any two points in time.


Another description example:



eGauge Systems offers access to a free, unrestricted API for use in developing applications which fetch data from the eGauge meter. This API covers the same functions used by the default eGauge interface. The eGauge push service functionality is also covered in the API.

eGauge technical support can offer assistance interpreting XML data. Code review and similar support is not available.

EG4xxx meters support TLSv1.2, while EG30xx only supports TLSv1.0





Timezone and "Z" parameter

The "Z" parameter and timezone information is only used in the XML API when exporting in CSV format. This only affects human-friendly Date & Time values in CSV exports. It does not have any affect when returning XML formatted data, nor any affect on any time-related input parameters.

Beginning in firmware v1.2, omitting the value of the "Z" parameter will cause the CSV output to use the locally configured timezone for human-friendly CSV Date & Time values (configured in Settings -> Date & Time). For this to work, the "Z" parameter must be passed, but with an empty value (e.g., egauge-show?n=60&m&c&Z=)

When using the XML API to request data in CSV format, the query string parameter "Z" is used to specify a timezone to format the Date & Time column in the CSV output. Omitting this parameter completely will cause the Date & Time column to output Unix Timestamps. Providing an invalid value is undefined, but may cause the Date & Time to output in UTC time in human-friendly format.

The format of this string is described under the environment variable TZ at Examples of how to decode and write custom timezones can be found at the end of this page.

Common Timezones

US/Eastern LST5LDT4,M3.2.0/02:00,M11.1.0/02:00
US/Central LST6LDT5,M3.2.0/02:00,M11.1.0/02:00
US/Mountain LST7LDT6,M3.2.0/02:00,M11.1.0/02:00
US/Arizona LST7
US/Pacific LST8LDT7,M3.2.0/02:00,M11.1.0/02:00
US/Alaska LST9LDT8,M3.2.0/02:00,M11.1.0/02:00
US/Hawaii LST10
US/Baker Island LST-12
US/Samoa LST11
Australia/Central LST-10:30
Australia/Eastern LST-10LDT-11,M10.1.0/02:00,M4.1.0/03:00
Australia/Norfolk LST-12:30
Azores Islands LST1LDT0,M3.5.6/24:00,M10.5.0/01:00
Brazil LST3LDT2,M10.3.6/24:00,M2.5.6/24:00
Canada/Atlantic LST4LDT3,M3.2.0/02:00,M11.1.0/02:00
China/Beijing LST-8
Europe/Central LST-1LDT-2,M3.5.0/02:00,M10.5.0/03:00
Europe/Eastern LST-2LDT-3,M3.5.0/03:00,M10.5.0/04:00
Europe/Western LST0LDT-1,M3.5.0/01:00,M10.5.0/02:00
India LST-6:30
Iran LST-4:30LDT-5:30,M3.3.2/24:00,M9.3.4/24:00
Iraq/Baghdad LST-3
Kazakhstan/Astana LST-6
New Zealand LST-12LDT-13,M9.5.0/02:00,M4.1.0/03:00
Pakistan/Karachi LST-5
Russia/Moscow LST-4
Russia/Vladivostok LST-11
South Sandwich LST2
Thailand/Bangkok LST-7
Tokyo LST-9



Decoding and understanding timezone strings

In the timezone strings, "LST" and "DST" stand for "Local Standard Time" and "Daylight Standard Time", respectively.

For a full description of the timezone string format, see the environment variable TZ at

The string is generally divided into 3 sections separated by commas. The first section describes the difference between UTC and local times. The second section describes when daylight time begins, and the third section describes when it ends.

The sections describing when daylight savings starts and ends is in the following format:


The d'th day (0 <= d <= 6) of week n of month m of the year (1 <= n <= 5, 1 <= m <= 12, where week 5 means "the last d day in month m" which may occur in either the fourth or the fifth week). Week 1 is the first week in which the d'th day occurs. Day zero is Sunday. t is the 24-hour time in which it occurs. If omitted, it defaults to 2:00 AM.


Timezone string: LST5LDT4,M3.2.0/02:00,M11.1.0/02:00

Each section, separated by commas, is described as such:


Timezone string: LST10

UTC is 10 hours after local Hawaii time. Daylight savings time is not observed, so there is no LDT definition or additional sections.

New Zealand

Timezone string: LST-12LDT-13,M9.5.0/02:00,M4.1.0/03:00

Each section, separated by commas, is described as such:



Authentication (HTTP Digest Authentication)

If the eGauge meter is set with site-wide password authentication, all resources will require HTTP Digest Authentication. Many programming languages and libraries have support for HTTP Digest Authentication, so well maintained and trusted libraries for HTTP Digest Authentication are preferable to use over custom implementations. In the event there is no existing support for HTTP Digest Authentication, it can be manually implemented. eGauge Systems cannot provide assistance on this implementation.

Wikipedia has information and examples of how to perform Digest Authentication and what header values must be returned. Note, any protected resources under the XML API will use a "quality of protection" (qop) of "auth", which will affect how the header values are calculated using HTTP Digest Authentication.

The basic steps to perform HTTP Digest Authentication are:

  1. Make an unauthenticated request to the resource you wish to access.

  2. Look at the WWW-Authentication header returned. Store the following values:
    Digest realm (realm space of protected resource. Generally this is "eGauge Administration" unless the interface is custom-branded)
    nonce (server nonce, changes for each unauthenticated request)
    qop (always will be "auth" for the eGauge XML API)

  3. Perform the following calculations:
    HA1 = MD5(username:realm:password)
    HA2 = MD5(method:digestURI) (note the digestURI is the path of the resource, not including host or FQDN. E.g., /cgi-bin/egauge-show)
    response = MD5(HA1:nonce:nonceCount:cnonce:qop:HA2) (nonceCount may be "1" for the initial request. cnonce
    is a nonce generated by the client, such as a 64 bit hexadecimal value)

  4. Send a request to the same URI in step 1, and this time include an "Authorization" header with the following parameters and values:
    1. Digest username = username for authentication
    2. realm = realm (from step 2)
    3. nonce = server nonce (from step 2)
    4. uri = request uri (used in HA2 in step 3)
    5. response = response (generated in step 3)
    6. qop = "auth"
    7. nc = nonce count (can simply be "1" for testing, should be incremented for subsequent requests that reuse the same nonce)
    8. cnonce = client nonce generated in step 3

It is not always necessary to perform step 2 in this process if making repeated requests to the same resource (URI or "digestURI"). A server nonce expire after 10 minutes and attempting to re-use will result in a 401 with WWW-Authenticate header like found in step 1, with a "stale=true" parameter in the header string.


eGauge meters can read and output Modbus RTU and TCP


Modbus Output Communication

All eGauge models with firmware v3.2 or higher have Modbus TCP output capability. eGauge models with USB ports also have capability for Modbus RTU (serial via RS485) output capability, with use of the eGauge USB485 converter. The Modbus server can be enabled in Settings -> Modbus Server. If the Modbus Server option is not available, upgrade your firmware in Tools -> Firmware Upgrade.

NOTICE: Prior to firmware v4.0, the Modbus map addresses are liable to change if the register name or contents is modified. Firmware v4.0 adds additional ranges that are tied to the register ID. The addresses used prior to v4.0 are still usable to provide backwards-compatibility, but are marked as deprecated and are not recommended to use as installation settings reconfiguration may change them. Virtual registers are in the order they appear on the settings page, meaning addresses can change if virtual registers are added or deleted.

Enabling the Modbus server

In the eGauge interface, navigate to Settings -> Modbus Server. The following options are available:

Check the box for "Enable Modbus" for the appropriate service (Modbus TCP uses Ethernet, Modbus RTU uses the eGauge USB485 serial converter).

For Modbus TCP, choose the port to listen on (default: 502).

For Modbus RTU, click inside the serial device box and detected adapters will be listed to choose from as shown below. Choose the appropriate baud rate, parity and stop bits to match the Modbus master.

Modbus Register Map

The exact Modbus map depends on the eGauge device configuration and is available on the Modbus settings screen. The map is available for viewing in the web browser or for download as a comma-separated value (CSV) file which can then be imported into any spreadsheet program.

Address range



30000 -- 30003

local timestamp (for use when reading from addresses <35000)

30004 -- 30007

THD timestamp indicates when data was acquired that is used by FFTarg(), FFTarg2(), FFTmag(), and THD() functions

30008 -- 30009

register timestamp (for use when reading from addresses ≥35000)

Local data (channel checker)

30500 -- 30999

Line voltages (RMS)

31000 -- 31499

Line voltages (DC/mean)

31500 -- 31999

Line frequencies

32000 -- 32499

Sensor values (normal/RMS)

32500 -- 32999

Sensor values (mean/DC)

33000 -- 33949

Sensor frequencies

Register Data [v4.0 and greater]

34000 -- 34999

Reduced precision cumulative physical register values (float)
35000 -- 35999

Cumulative virtual register values (signed 64-bit integers)
36000 -- 36999

Change of virtual register value (float)

37000 -- 37999 Reduced precision cumulative virtual register values (float)
38000 -- 38999 Cumulative physical register values (signed 64-bit integers)
39000 -- 39999 Change of physical register value (float)

Register Data [PRIOR to firmware v4.0, now deprecated]

35000 -- 35999

Cumulative register values (signed 64-bit integers) [DEPRECATED]

36000 -- 36999

Change of register value (float) [DEPRECATED]

37000 -- 37999

Reduced precision cumulative register values (float) [DEPRECATED]

In v4.0 or greater, the Modbus addresses are tied to the eGauge register IDs. They can be calculated as:

Physical float cumulative value = 34000+(ID*2)

Physical s64   cumulative value = 38000+(ID*4)

Physical float instant value    = 39000+(ID*2)

Virtual registers are in the order they appear on the installation settings page, and are therefore liable to shift during deletions or additions.

The register ID can be found by hovering over the register delete button in the Installation Settings page:

An example Modbus map, which can be found in Settings -> Modbus Server, is displayed below:

The t16 type Modbus registers are variable-length UTF-8 strings and therefore multiple registers may need to be read until a UTF-8 null character is reached.

Example Modbus Transmissions:

Example Modbus TCP request and response for L1 RMS voltage:

Request: [00 01] [00 00] [00 06] [01] [04] [01 f4] [00 02]

[00 01] = Transaction identifier

[00 00] = Protocol identifier (always 00 00)

[00 06] = Bytes following (0x0006 = 6 bytes)

[01] = Unit ID

[04] = Function code (0x04 is read input registers)

[01 f4] = Starting register address (500)

[00 02] = Number of words to return (2 words for float value)

Response: [00 01] [00 00] [00 07] [01] [04] [04] [42 f6 2a 06]

[00 01] = Transaction identifier

[00 00] = Protocol identifier (always 00 00)

[00 07] = Bytes following (0x0007 = 7 bytes)

[01] = Unit ID

[04] = Function code (0x04 is read input registers)

[42 f6 2a 06] = Contents of register 500 and 501 respectively

0x42f62a06 decoded as big-endian (ABCD) float is roughly 123.08, so L1 voltage is 123.08Vrms

Example Modbus RTU request and response for L1 RMS voltage:

Request: [01] [04] [01 f4] [00 02] [31 c5]

[01] = Unit ID

[04] = Function code (0x04 is read input registers)

[01 f4] = Starting register address (500)

[31 c5] = CRC error check

Response: [01] [04] [04] [42 f6 2a 06] [90 ac]

[01] = Unit ID

[04] = Function code (0x04 is read input registers)

[04] = Data bytes to follow (not including CRC)

[42 f6 2a 06] = Contents of register 500 and 501 respectively

0x42f62a06 decoded as big-endian (ABCD) float is roughly 123.08, so L1 voltage is 123.08Vrms

Additional technical information

The maximum Modbus frame size is 255 bytes. This translates to (61) 32-bit registers or (30) 64-bit registers. Most DAS and Modbus systems will automatically split any requests to limit the response size to not exceed the upper limit. If requesting more registers than can be returned in a single frame, the response may be truncated or an exception may be returned.

Additional help is available by clicking the [?] buttons on the Modbus Server settings page.

All data is provided as Modbus input registers and therefore their Modbus addresses start at 30000. The raw frame sent does not include the prefixed '30', this indicates the function code used.

For each register recorded by eGauge, the register's current cumulative value and the amount by which it changed since the previous one-second interval can be read. The cumulative value is available with full resolution as a signed 64-bit value. For convenience, the same value is also available, at reduced resolution, as a 32-bit floating point number. The change-in-value is available only as a 32-bit floating point number. In addition to the register data, it is also possible to read locally measured data such as line-voltages, frequencies, and the value measured by each sensor-port.

The Modbus server guarantees that any data read with a single request is consistent. Timestamps are provided as a means to ensure consistency when data is read with multiple requests (e.g., to read multiple, discontiguous registers). This is accomplished by (i) reading the timestamp, (ii) performing the desired read requests, and (iii) reading the timestamp again. If the two timestamp values are the same, then reader can be certain that the data is consistent.


Sunspec Support

Sunspec is a communication standard used by many types of devices (including inverters). It is intended to ease configuration when working with hardware from different manufacturers by providing common addressing block for different device types and allowing devices to query for applicable address blocks. Essentially, Sunspec allows a Modbus master (such as the eGauge) the ability to read the list of available registers from a device, eliminating the need to create inline definitions manually.


It's fairly easy to configure a Sunspec remote device:

1. Create a new remote device entry.

2. Name the entry (names are arbitrary but should make sense to the user).

3. Select the appropriate protocol. "Serial" for Modbus RTU, and "Modbus TCP" for Modbus TCP.

4. Enter the device address. This is in the form "modbus://sunspec.<id>@<addr>" where <id> is replaced with the Modbus slave address of the remote device and <addr> is replaced with the address of the remote device.

4a. With Modbus RTU, the address will be a USB port (USB1 or USB2) along with serial settings in the form ": baud / databits parity stopbits". For example, @USB1:9600/8n1 would indicate USB port 1, 9600 baud, 8 data bits, no parity, 1 stop bit. 

4b. With Modbus TCP, the address will simply be the IP address of the Sunspec device on the local network. For example, @ would indicate the remote device is located at

5. Click the grey "?" to the left of the device address. This will cause the eGauge to query the remote device for a full list of registers, and a green checkmark will appear if the query was successful. A red "X" will appear if the address is invalid or incorrectly entered. Click the blue info button to see detailed information on the state of the query (shown below).


6. Once the register list has been retrieved, the eGauge needs to be configured to store registers of interest. To do this, create a new physical register, set the register type to the remote device name used in step 2, and then use the dropdown menu to select the remote register to record. The eGauge will only record the registers configured in this step, regardless of how many registers exist on the remote device.


7. Click the "Save" button at the bottom of the page to save these changes. The eGauge must be rebooted after adding new registers (this process typically takes about 30 seconds).


To add additional registers from a remote device, repeat steps 5 and 6.


Custom Modbus definitions (read from any Modbus device)

In firmware v4.0 and greater, a graphical interface to edit Modbus maps is available. This is recommended to be used over in-line definitions. See this article for information on using the Modbus map editor.

The following table describes the full Modbus address format and syntax. In-line definitions may be used to allow the eGauge to read from arbitrary or unsupported Modbus devices. Examples are provided at the end of this document.

Some options have been added in newer firmware releases, if the behavior is not as expected please check the firmware revision notes at and upgrade the device firmware in Tools -> Firmware Upgrade.

Remote devices are configured in Settings -> Installation -> Remote Devices. The protocol for Modbus RTU is "RS485" The protocol for Modbus TCP is "Modbus TCP".

USB485 connected (EG4xxx with USB485 only) serial devices have a remote device address in the format of:


Note: Modbus RTU requires prefixing the address with modbus://


BF-430 connected (older and all models) serial devices have a remote device address in the format of:


Note: Modbus RTU requires prefixing the address with modbus://


Modbus TCP connected devices have a remote device address in the format of:


Note: Modbus TCP does not start with "modbus://". Instead, the protocol drop-down is set to "Modbus TCP"


Variable Definition
DEVTYPE Remote device type or inline Modbus register definitions using the following syntax to define the following elements:
name Name for data being read into this register
addr Modbus register address
! Indicates a read-only (function code 0x04 read input) register type
type Modbus register type (see following tables)*
offset Additive offset for register value
scale Multiplicative scale value for register value
unit Physical Unit (see following tables)**
SLAVE_ADDR The Modbus address (0-255) of the device
USB_PORT Modbus RTU, USB485 (EG4xxx) use only. The USB port number with the USB485 converter
SERIAL_SETTINGS Modbus RTU, USB485 (EG4xxx) use only. Serial settings for the USB485 converter to use in the format of 9600/8n1 (baud rate, data bits, parity, stop bits). Required for custom definitions
CONV_ADDRESS Modbus RTU, BF-430 use only. MAC address or IP address of BF-430
IP_ADDRESS Modbus TCP use only. The IP address of the Modbus slave
PORT Port number for BF-430 Modbus RTU (default: 50,000), or Modbus TCP slave (default: 502)


Register Type * Description    
bit 1-bit value (coil or discrete input if read-only)
s16 Signed 16-bit integer
u16 Unsigned 16-bit integer
float16 IEEE-754 half-precision binary 16-bit float value
float16l Little-endian IEEE-754 half-precision binary 16-bit float value
s32 Signed 32-bit integer
s32l Little-endian signed 32-bit integer
u32 Unsigned 32-bit integer
u32l Little-endian unsigned 32-bit integer
s64 Signed 64-bit integer
u64 Unsigned 64-bit integer
float IEEE-754 32-bit float value
floatl Little-endian IEEE-754 32-bit float value
double Double value


Unit Code ** Physical Quantity Unit Code ** Physical Quantity
Ohm Resistance (Ω) mA Current (milliampere)
W Power (watt) As Charge (ampere-second)
kWh Energy (kWh) Ah Charge (ampere-hour)
degC Temperature (degrees Celsius) mAh Charge (milliampere-hour)
m/s Speed (meters per second) Hz Frequency (hertz)
mm Length (millimeter) % Percentage (%)
W/m^2 Irradiance (watts per square meter) m3/s Volumetric flow (cubic meters per second)
ms Time (millisecond) m3 Volume (cubic meters)
s Time (seconds) Pa Pressure (pascal)
h Time (hours) kPa Pressure (kilopascal)
V Voltage (volt) deg Angle (degree)
mV Voltage (millivolt) RH Relative humidity (%)
A Current (ampere) #3 Number with 3 decimals
var Reactive power (VAr) enum enumeration digital value (e.g., fault code)
bitset Bitfield value    



Modbus RTU:


Modbus RTU supported device "ae75_100tx", slave address 2 using USB485 on USB port 1



Modbus RTU supported device "ae75_100tx", slave address 2 using a BF-430 connecting via MAC address



Same as above, but specifying to use port 500 instead of 50,000



Modbus RTU unsupported device measuring "power" at address 1, signed 16-bit integer, recording Watts, slave address 5, connecting via USB485 on USB port 2. Using 19200 baud, 8 data bits, no parity and one stop bit



Same as above, but also recording voltage and current at addresses 2 and 3 respectively



Here, the "power" value is being scaled by 10 (multiply by .1), and is using function code 0x04 (read input registers) as depicted by the exclamation mark


Note: "Protocol" is RS485 for Modbus RTU, and the device address starts with "modbus://"


Modbus TCP:


Supported Modbus TCP device "ae75_100tx" at slave address 1 at IP address



Supported Modbus TCP device "ae75_100tx" at slave address 1 at IP address, using port 503 instead of 502



Unsupported Modbus TCP device recording impedance from register 598 and phase angle from register 600. Both are reading as little-endian float.


Note: "Protocol" is "Modbus TCP", and the device address does not start with "Modbus://"



Creating, Sharing, and Using Modbus Maps


From firmware 4.1 and up, the eGauge supports the creation and sharing of Modbus maps through the Modbus map editor. Modbus maps are essentially a set of instructions for the eGauge meter describing how to read data from third party Modbus devices (hardware not manufactured or supported by eGauge Systems).

Traditionally, configuring the eGauge to read correctly from a Modbus device required the creation of inline definitions. This approach is still supported, but it is difficult to apply to multiple meters. It also requires that each user of a specific device create their own inline definitions. With the addition of Modbus maps, definitions for a given remote device can be freely shared and improved upon. These maps can also be applied directly to a meter without risk of error due to copy/pasting issues or typing mistakes.

Firmware 4.1 or later is required.



Accessing the Modbus Map Editor

Creating a New Map

    Adding Registers

    Adding Default Options

Sharing Modbus Maps

    Downloading Maps

    Uploading Maps

Using a Modbus Map

    Modbus RTU

    Modbus TCP

    Creating a Local Register



Accessing the Modbus Map Editor

The Modbus Map Editor can be accessed through the Installation Settings screen by clicking the "Modbus Maps" button under the "Remote Devices" section:




A list of available Modbus maps will load. From here, maps can be created, edited, shared, or applied to the meter.



Creating a New Map

To create a new map, click or tap the icon in the top right corner of the page.


This will open a new page.


First, enter an appropriate map name. Typically, this should identify the hardware. Hardware model numbers are recommended. Click the "Save" button in the bottom right corner of the page to create an empty map with this name. The meter will load the list of available maps again, with the new (empty) map at the top. Click on this again to return to the empty map.


Adding Registers

To add registers, click the "Add Register" button. Enter the appropriate information for your register. "Scale" and "Offset" are optional values; all other fields must be filled. This information will be available in the documentation for the third party hardware - if it is not, it will be necessary to contact that hardware manufacturer directly. eGauge Systems cannot provide Modbus register maps for third party hardware.

As an example, the manufacturer's Modbus register map used to create the register below is available here: XY-MD02 manual. Note that Modbus register maps are not standardized, and it may require some effort to find the values required for eGauge configuration in a given map.

Below is an example register:



Modbus register address, in decimal form. Note that Modbus documentation is not consistent, and it may be necessary to modify the address. For example, many addresses are listed with a preceding 3 or 4, but this number is usually dropped along with any preceding 0s. Thus, 30001 becomes 1, 40258 becomes 258, and so on. Some addresses may have a +/- 1 offset, so 301 might actually need to be entered as 300. Finally convert hex values (which usually start with 0x) to decimal values using a hexidecimal to decimal converter.

Register Name

The register name is an arbitrary value, but should reflect the item being measured for the sake of clarity. For example, "Temperature" implies a temperature measurement. "Ambient Temperature" might be a better fit for a device which records multiple temperature measurements.


The data type of the register. If this setting is not correct the register data will not be read correctly, although it will usually read something. 32 and 64 bit data types read more than one Modbus register (a single Modbus register is 16 bits). In the absence of a defined data type, a register described by an address range (eg, 10-11, or 1000-1003) is likely a 32 or 64 bit register.


The kind of register. There are three options:

Analog - A simple numerical value. Most applications will use analog values.
Bitset - A numerical value representing a binary string. Typically, each 1 or 0 in this string would represent a state on the remote device. This selection is never averaged or allowed to accumulate excess, because it would change the fundamental value.
Enum - A numerical value representing a state on the remote device. This selection is never averaged or allowed to accumulate excess, because it would change the fundamental value.


Applies a scale factor to the raw value read from the Modbus device. This may be used to scale incoming values to better fit a certain data type. In the example above, the Temperature register at address 1 records temperature in .1 C increments, but the eGauge uses C as a unit. A raw value of 334 would therefore be displayed and recorded as 33.4 degrees Celsius with a .1 scale factor. If left blank, this is set to "1".


Applies a numerical offset to a raw value. This may be used for calibration purposes (eg, if a sensor is known to read 2 units too low, an offset of 2 would display the reading from that sensor as "raw_value + 2"). If left blank, this is set to "0".

Recorded Unit

Associates a supported unit with the value recorded from that register. This assigns a unit to the register in the eGauge user interface. For unsupported units, "record as integer" will record whole numbers and "record with 3 digits" will record fractional numbers to three digits (note that the incoming data may not actually be precise to three digits). 

Read-only Input Register

The eGauge supports reading values from remote devices using either function code 3 (read holding registers) or function code 4 (read input registers). By default, function code 3 is used. However, some devices may only support function code 4 - in this case, selecting "read-only input register" will force the eGauge to use function code 4 for that register. Note that it is possible to use a mix of function codes on a single device.


Once a register has been added, click "OK" to save that register into the map. The register will be added to the map, and additional registers can be added by clicking the add icon in the top right corner of the page.

This example device has two registers, shown configured below:


Make sure to click "Save" in the bottom right corner of the page once all registers are added. Navigating away from the page before clicking save will revert all changes (including newly added registers).


Adding Default Options

This section allows the user to specify various communication options on a per-device level. There are four options which can be set. Note that some of these options are mutually exclusive or not required depending on the device type. For example, a serial device (Modbus RTU) will not have a default TCP port.

Default Unit Number


The default unit number is also referred to as "Modbus ID", "Modbus slave address", "Slave address", and so on. Each device on a single serial chain must have a unique unit number. Typically, hardware will ship with a default unit number, so if multiple devices from the same manufacturer are preset the unit number must be set to a unique value on each device.

The process for changing a device's unit number depends on the hardware - reach out to the hardware manufacturer for additional information or instructions.

Default Serial Port Parameters


Only applies to Modbus RTU devices

Most Modbus RTU devices ship with a predefined set of serial parameters. These include baud rate, data bits, parity, and stop bits. These parameters must be identical across all devices on a single serial chain. If using multiple identical devices they should all be set to use the same values, but devices from different manufacturers may need to be set so they all use the same serial parameters.

The process for changing serial parameters depends on the hardware - reach out to the hardware manufacturer for additional information or instructions.

Default TCP Port


Only applies to Modbus TCP devices

Most Modbus TCP devices ship with a default TCP port of 502. However, in some cases this may not be true, or it may be desirable to use a different TCP port. TCP ports do not need to match across multiple Modbus TCP devices, even on the same network (each Modbus TCP device should have a unique IP address, so the port used is immaterial). 


Base Address


The base address field can be used to apply a starting address for registers. This can be useful if a manufacturer's Modbus map has a +/-1 offset, or if the addresses all require a specific prefix (eg, 30000, 40000, 1000). The address queried by the eGauge will be (base address) + (configured address).

If in doubt, this setting can generally be ignored.



Sharing Modbus Maps

Modbus maps can be downloaded and shared as CSV files. There is no charge for this service. This can be used to copy a single map to multiple meters, or to share a map with other users. For best results, ensure that the source and destination meters are both on the same firmware version.

Always verify that maps downloaded from unknown sources are valid and complete. A misconfigured map can't cause damage to the eGauge, but it might not work correctly or may report incorrect values.


Downloading a Map


To download a Modbus map, select the desired map from the map list and click the "Download" button. A confirmation window will appear:


After clicking "OK", the map will be downloaded as a CSV file.

Although it is possible to edit the CSV file directly, this is not supported or recommended. 


Uploading a Map


To upload a Modbus map, click the "Upload" button in the top right corner of the map list. A confirmation window will appear:


Click the "Filename" field to select the location of the saved map on your computer or device. Optionally, enter the desired map name. Click "OK" to upload the map. 

An error message will appear at the bottom of the page if the map is invalid, corrupted, or incomplete.

Modbus maps can be shared freely as desired. eGauge Systems makes no guarantees as to the correctness or validity of these maps. When uploading a map, always verify that map configuration is correct and complete.



Using a Modbus Map

Once a Modbus map has been fully configured and saved, it can used in remote device addresses (under Settings -> Installation). Note that a map doesn't do anything until it's added as a remote device and at least one local register is created to store data based on that map.

The process for this varies based on whether the map applies to a Modbus RTU or Modbus TCP device. Make a note of the map name - it will be required to configure the eGauge.


Modbus RTU

Modbus RTU device addresses are prefixed with modbus:// and end with the address of either a USB port when using the USB-RS485 adapter (USB1 or USB2) or the MAC address of a Serial to Ethernet converter

The protocol type "Serial" should be selected for all Modbus RTU devices.

In the example below, the map XY-MD02 is associated with a serial to USB adapter in USB port 1


Serial settings can also be added if default serial settings weren't specified in the map or if different serial settings need to be used. For example:


In the above example, the serial settings are:

Baud Data Bits Parity Stop Bits
9600 8 n (none) 1

Finally, it's also possible to specify a different Modbus address/slave address/unit number. This will be necessary if a default value isn't specified or if multiple devices are on the same serial chain. To do this, add the address in the form .X after the map name, where X is the address. For example:


In the above example, an address of 55 is used instead of the default.


Modbus TCP

Modbus TCP devices have no prefix, and end with the IP address or MAC address of the Modbus device on the local network. Note that Modbus TCP devices must be on the same local network as the eGauge.

The Protocol type "Modbus TCP" should be selected for all Modbus TCP devices.

In the example below, the map XY-MD02 is associated with the address (presumably the same network the eGauge is connected to):


A different Modbus address/slave address/unit number may also need to be specified. To do this, add the address in the form .X after the map name, where X is the address. For example:


In the above example, an address of 55 is used instead of the default.


Creating a Local Register

To create a local register and record data from a remote device, you must first validate the Modbus address. To do this, click the grey "?" to the left of the remote device address. A green check mark should appear. If a red "X" appears, it means the remote device is unreachable or the address or map is configured incorrectly.

Once the green check mark appears, registers can be added to the eGauge configuration to store data fetched from the Modbus device. In the example below, the eGauge is importing two registers ("Humidity" and "Temperature") from the remote device "Sensor":


After adding registers, make sure to save changes by clicking "Save" at the bottom of the page. 

For an introduction to making configuration changes to the eGauge, see this article.







eGauge meters can output BACnet information via MS/TP and IP (UDP)


BACnet Overview

Quick Links:
BACnet register map and PICS
Configuring BACnet service

What is BACnet?

BACnet is a communication protocol designed for Building Automation and Control (Networks), for use with a Building Automation System (BAS) which controls and automates certain functions within a building. A BAS typically receives data from multiple remote devices, such as temperature, electrical consumption, air quality, and many other types of data depending on what is or can be automated in the building. Based on this data, the BAS can send alerts to building managers and control loads, such as turning on heating if an area becomes too cold or turning off non-critical systems to load shed when overall consumption becomes too high.

eGauge compatibility

The eGauge can provide BACnet data over an Ethernet LAN (BACnet IP) as well as over RS485 serial (BACnet MS/TP). Any data the eGauge collects, including from other remote devices, are available to send

General overview

A building automation system (BAS) will periodically request data from a remote device (e.g., the eGauge meter), and based on this data it may do nothing, trigger an alarm, or switch on or off loads or other controllable equipment.

BACnet is disabled by default on the eGauge meter and may be enabled through Settings → BACnet. For an example of the configuration and options available see this knowledgebase article.


BACnet MS/TP (Serial)

Using the eGauge USB485, the eGauge meter can provide data via BACnet to a building automation system.

Be sure to review general (non-eGauge specific) serial communication considerations when considering serial lines for BACnet communication. This includes but not limited to:3CmxGraphModel%3E%3Croot%3E%3CmxCell%20id%3D%220%22%2F%3E%3CmxCell%20id%3D%221%22%20parent%3D%220%22%2F%3E%3CmxCell%20id%3D%222%22%20value%3D%22%26lt%3Bfont%20color%3D%26quot%3B%23ff3333%26quot%3B%26gt%3BData%20from%20eGauge%20Meter%20electrical%20readings%20are%20sent%20to%20Building%20Automation%20System%26lt%3B%2Ffont%26gt%3B%22%20style%3D%22text%3Bhtml%3D1%3BstrokeColor%3Dnone%3BfillColor%3Dnone%3Balign%3Dcenter%3BverticalAlign%3Dmiddle%3BwhiteSpace%3Dwrap%3Brounded%3D0%3BfontSize%3D15%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22530.23%22%20y%3D%22580%22%20width%3D%22150%22%20height%3D%2280%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3C%2Froot%3E%3C%2FmxGraphModel%3Eaaaaaadasdas
• Using twisted pair wire for data +/- lines
• Choosing appropriate wire gauge and baud rate (becomes increasingly important with long wire runs)
• Appropriate termination methods (the eGauge USB485 has a selectable termination switch)
• Software and hardware configuration for BAS system controller



BACnet IP (over an Ethernet network)

BACnet over a LAN has the same functionality as BACnet MS/TP over serial, but it uses an Ethernet network and can connect to an existing LAN instead of requiring its own serial chain.