CEMM basic & plus

CEMM basic en CEMM plus zijn van 2014 tot 2023 ondersteund. Met de komst van CEMM 3.0 zijn deze producten uitgefaseerd, maar uiteraard nog steeds te gebruiken. Documentatie vind je op deze pagina.

Please note that this documentation only applies to CEMM Basic and CEMM Plus.

Authentication

The CEMM Open API uses API keys to authenticate requests. The API key must be send with each request. All API requests are sent over HTTPS, this will automatically encrypt the API key. It is important that you keep your API key safe.

Caution: Everyone with access to your API key is able to request data from any linked CEMM!

Connecting to the Open API

The Open API can be reached at: https://open-api.cemm.nl/v1/

API Promise

The Open API returns a promise when it is unable to immediately fulfill the request. A promise is a unique identifier which expires after 10 seconds. The promise indicates that data is being requested from the CEMM. By repeating the request, the data can still be obtained.

Aliases

Aliases are used to directly address connected meters (I/O). At this point in time it is only possible to select an I/O using an alias.

  • p1 Returns the connected DSMR smart meter. The smart meter is connected to connection 1.1 of the CEMM
  • han Returns the connected AMS HAN meter. The smart meter is connected to connection 1.1 of the CEMM using a HAN converter
  • p1-gas Returns the connected smart gas meter. The smart gas meter is connected via the smart meter to the CEMM
  • s01 Returns the connected pulse meter on connection 2 of the CEMM
  • s02 Returns the connected pulse meter on connection 1.2 of the CEMM
  • s03 Returns the connected pulse meter on connection 1.1 of the CEMM

MeasurementArray

A MeasurementArray is a regular array with a timestamp in milliseconds at index 0 and the corresponding value at index 1.

electric_power<MeasurementArray>
  [0]<Integer> # Timestamp in milliseconds
  [1]<Double>  # Sensor value

Request linked CEMMs

This endpoint returns a dataset of CEMMs that are linked to the API key that was sent. The uid of a CEMM will be used in other endpoints to select that particular CEMM.

Endpoint
GET cemm/
GET Parameters
  • api_key The Open API authentication key
Response

This endpoint returns a JSON object. The structure of the JSON object is illustrated below.

<Object>
  data<Array>
    <Object>
      uid<String> # CEMM mac address
Response codes
200 OK              # Successful API response without errors
202 Accepted        # API is unable to immediately fulfill the request, the API returns a promise
403 Unauthorized    # Access denied. API key invalid for this action
408 Request Timeout # API was unable to respond on time
502 Bad Gateway     # An unexpected error occurred in the API
Example
GET https://mijn.cemm.nl/open-api/v1/cemm/?api_key=4e4f657....

{
    "data": [
        {
            "uid": "00-00-00-00-00-00"
        },
        {
            "uid": "FF-FF-FF-FF-FF-FF"
        }
    ]
}

Request an I/O of a CEMM

This endpoint returns all activated I/Os. An I/O describes a meter/sensor or actuator. Each meter/sensor that is connected to the CEMM is assigned an io_id. The io_id is a unique number that can be used to select the I/O. The io_id is assigned in the order the I/Os are activated. To select a specific connection of the CEMM an alias is used.

Endpoint
GET cemm/<CEMM UID>/io/
URL Parameters
  • <CEMM UID> The mac address of the CEMM as returned by the cemm/ endpoint
GET Parameters
  • api_key The Open API authentication key
Response

This endpoint returns a JSON object. The structure of the JSON object is illustrated below.

<Object>
  data<Array>
    <Object>
      io_id<Integer>      # Id of the I/O
      port<Integer>       # Port number to which the I/O is connected
      type<String>        # I/O type
      port_option<String> # Input or Output type
      full_id<Integer>    # Id of the decentralized unit to which the I/O is connected
Response codes
200 OK              # Successful API response without errors
202 Accepted        # API is unable to immediately fulfill the request, the API returns a promise
403 Unauthorized    # Access denied. API key invalid for this action
408 Request Timeout # API was unable to respond on time
502 Bad Gateway     # An unexpected error occurred in the API
Example
GET https://mijn.cemm.nl/open-api/v1/cemm/FF-FF-FF-FF-FF-FF/io/?api_key=4e4f657....

{  
    "data":[  
        {  
            "io_id":1,
            "port":3,
            "type":"p1",
            "port_option":"p1_in",
            "full_id":16384
        },
        {  
            "io_id":2,
            "port":3,
            "type":"gas",
            "port_option":"enabled",
            "full_id":16384
        },
        {  
            "io_id":3,
            "port":1,
            "type":"solar_energy",
            "port_option":"s0_in",
            "full_id":16384
        }
    ]
}

Request an I/O of a CEMM using an alias

This endpoint returns info about the I/O selected by alias. Available aliases for this endpoint are: p1p1-gass01s02s03

Endpoint
GET cemm/<CEMM UID>/<ALIAS>/
URL Parameters
  • <CEMM UID> The mac address of the CEMM as returned by the cemm/ endpoint
  • <ALIAS> The alias for the I/O to be requested
GET Parameters
  • api_key The Open API authentication key
Response

This endpoint returns a JSON object. The structure of the JSON object is illustrated below.

<Object>
  data<Array>
    <Object>
      io_id<Integer>      # Id of the I/O
      port<Integer>       # Port number to which the I/O is connected
      type<String>        # I/O type
      port_option<String> # Input or Output type
      full_id<Integer>    # Id of the decentralized unit to which the I/O is connected
Response codes
200 OK              # Successful API response without errors
202 Accepted        # API is unable to immediately fulfill the request, the API returns a promise
403 Unauthorized    # Access denied. API key invalid for this action
408 Request Timeout # API was unable to respond on time
412 Precondition Failed # The specified alias is not supported by this endpoint
502 Bad Gateway     # An unexpected error occurred in the API
Example
GET https://mijn.cemm.nl/open-api/v1/cemm/FF-FF-FF-FF-FF-FF/p1/?api_key=4e4f657...

{  
    "data":[  
        {  
            "io_id":1,
            "port":3,
            "type":"p1",
            "port_option":"p1_in",
            "full_id":16384
        }
    ]
}

Requesting realtime data of a I/O using an alias

This endpoint returns a dataset with realtime data for the I/O selected by alias. Available aliases for this endpoint are: p1p1-gass01s02s03

Endpoint
GET cemm/<CEMM UID>/<ALIAS>/realtime/
URL Parameters
  • <CEMM UID> The mac address of the CEMM as returned by the cemm/ endpoint
  • <ALIAS> The alias for the I/O to be requested
GET Parameters
  • api_key The Open API authentication key
Response

This endpoint returns a JSON object. The structure of the JSON object is illustrated below. The response depends on the requested alias. All I/O sensor values in the API responses are returned as a MeasurementArray

Response for aliases: s01, s02, s03

<Object>
  io_id<Integer> # Id of the requested I/O
  data<Object>
      electric_power<MeasurementArray>

Response for alias: p1

<Object>
  io_id<Integer> # Id of the requested I/O
  data<Object>
      t1<MeasurementArray>
      t2<MeasurementArray>
      t3<MeasurementArray>
      t4<MeasurementArray>
      electric_power<MeasurementArray>
      rate<MeasurementArray>
      switch<MeasurementArray>
      gas<MeasurementArray>

Response for alias: p1-gas

<Object>
  io_id<Integer> # Id of the requested I/O
  data<Object>
      gas<MeasurementArray>
Response codes
200 OK              # Successful API response without errors
202 Accepted        # API is unable to immediately fulfill the request, the API returns a promise
403 Unauthorized    # Access denied. API key invalid for this action
408 Request Timeout # API was unable to respond on time
412 Precondition Failed # The specified alias is not supported by this endpoint
502 Bad Gateway     # An unexpected error occurred in the API
Example
GET https://mijn.cemm.nl/open-api/v1/cemm/FF-FF-FF-FF-FF-FF/p1/realtime/?api_key=4e4f657


{  
    "io_id":1,
    "data":{  
        "t1":[  
            1496326765000,
            1351
        ],
        "t2":[  
            1496326765000,
            1614
        ],
        "t3":[  
            1496326765000,
            883
        ],
        "t4":[  
            1496326765000,
            2018
        ],
        "electric_power":[  
            1496326765000,
            -1607
        ],
        "rate":[  
            1496326765000,
            2
        ],
        "switch":[  
            0,
            0
        ],
        "gas":[  
            1496326765000,
            2617
        ]
    }
}

Request daily data of an I/O using an alias

This endpoint returns a dataset containing all minutes of the day for the selected I/O by alias. Available aliases for this endpoint are:p1p1-gass01s02s03Caution: The smart meter updates the gas meter reading only once an hour. This endpoint returns data in hours instead of minutes for p1-gas.

Endpoint
GET cemm/<CEMM UID>/<ALIAS>/data/day/
URL Parameters
  • <CEMM UID> The mac address of the CEMM as returned by the cemm/ endpoint
  • <ALIAS> The alias for the I/O to be requested
GET Parameters
  • api_key The Open API authentication key
  • time Timestamp of the day in seconds (can be any moment between 00:00 and 23:59)
Response

This endpoint returns a JSON object. The structure of the JSON object is illustrated below. The response depends on the requested alias. All I/O sensor values in the API responses are returned as a MeasurementArray


Response for aliases: p1, s01, s02, s03

<Object>
  io_id<Integer> # Id of the requested I/O
  time<Integer>  # Timestamp of the requested day in milliseconds
  data<Object>
      electric_power<Array>
        0<MeasurementArray>
        .
        .
        1439<MeasurementArray>

Response for alias: p1-gas (DSMR 3.x and DSMR 4.x)

<Object>
  io_id<Integer> # Id of the requested I/O
  time<Integer>  # Timestamp of the requested day in milliseconds
  data<Object>
      gas<Array>
        0<MeasurementArray>
        .
        .
        23<MeasurementArray>

Response for alias: p1-gas (DSMR 5.x)

DSMR5.x smart meters update the gas meter reading every 5 minutes. This allows the CEMM to calculate the gas usage in L/min.

<Object>
  io_id<Integer> # Id of the requested I/O
  time<Integer>  # Timestamp of the requested day in milliseconds
  data<Object>
      gas<Array>
        0<MeasurementArray>
        .
        .
        1440<MeasurementArray>
Response codes
200 OK              # Successful API response without errors
202 Accepted        # API is unable to immediately fulfill the request, the API returns a promise
403 Unauthorized    # Access denied. API key invalid for this action
408 Request Timeout # API was unable to respond on time
412 Precondition Failed # The specified alias is not supported by this endpoint
502 Bad Gateway     # An unexpected error occurred in the API
Example
GET https://mijn.cemm.nl/open-api/v1/cemm/FF-FF-FF-FF-FF-FF/p1-gas/data/day/?time=1496242535&api_key=4e4f657....


{  
    "io_id":2,
    "time":1496242535000,
    "data":{  
        "gas":[  
            [  
                1496267999000,
                0
            ],
            [  
                1496264400000,
                0.14208984375
            ],
            .
            .
            .
            [  
                1496185200000,
                0
            ],
            [  
                1496181600000,
                0.0009765625
            ]
        ]
    }
}

Request monthly data of an I/O using an alias

This endpoint returns a dataset containing all days of the month for the selected I/O by alias. Available aliases for this endpoint are:p1p1-gass01s02s03

Endpoint
GET cemm/<CEMM UID>/<ALIAS>/data/month/
URL Parameters
  • <CEMM UID> The mac address of the CEMM as returned by the cemm/ endpoint
  • <ALIAS> The alias for the I/O to be requested
GET Parameters
  • api_key The Open API authentication key
  • time Timestamp of the month in seconds (can be any moment in the month)
Response

This endpoint returns a JSON object. The structure of the JSON object is illustrated below. The response depends on the requested alias. All I/O sensor values in the API responses are returned as a MeasurementArray

Response for aliases: p1, s01, s02, s03

<Object>
  io_id<Integer> # Id of the requested I/O
  time<Integer>  # Timestamp of the requested month in milliseconds
  data<Object>
      electric_energy_low<Array>
        0<MeasurementArray>
        .
        .
        30<MeasurementArray> # Length of the Array depends on the month
      electric_energy_high<Array>
        0<MeasurementArray>
        .
        .
        30<MeasurementArray> # Length of the Array depends on the month

Response for alias: p1-gas

<Object>
  io_id<Integer> # Id of the requested I/O
  time<Integer>  # Timestamp of the requested month in milliseconds
  data<Object>
      gas<Array>
        0<MeasurementArray>
        .
        .
        30<MeasurementArray> # Length of the Array depends on the month
Response codes
200 OK              # Successful API response without errors
202 Accepted        # API is unable to immediately fulfill the request, the API returns a promise
403 Unauthorized    # Access denied. API key invalid for this action
408 Request Timeout # API was unable to respond on time
412 Precondition Failed # The specified alias is not supported by this endpoint
502 Bad Gateway     # An unexpected error occurred in the API
Example
GET https://mijn.cemm.nl/open-api/v1/cemm/FF-FF-FF-FF-FF-FF/p1-gas/data/month/?time=1496242535&api_key=4e4f657....


{  
    "io_id":2,
    "time":1496242535000,
    "data":{  
        "gas":[  
            [  
                1496181600000,
                0.60400390625
            ],
            [  
                1496095200000,
                0.534912109375
            ],
            .
            .
            .
            [  
                1493676000000,
                0.003173828125
            ],
            [  
                1493589600000,
                0.0029296875
            ]
        ]
    }
}

Request yearly data of an I/O using an alias

This endpoint returns a dataset containing all months of the year for the selected I/O by alias. Available aliases for this endpoint are: p1p1-gass01s02s03

Endpoint
GET cemm/<CEMM UID>/<ALIAS>/data/year/
URL Parameters
  • <CEMM UID> The mac address of the CEMM as returned by the cemm/ endpoint
  • <ALIAS> The alias for the I/O to be requested
GET Parameters
  • api_key The Open API authentication key
  • time Timestamp of the year in seconds (can be any moment of the year)
Response

This endpoint returns a JSON object. The structure of the JSON object is illustrated below. The response depends on the requested alias. All I/O sensor values in the API responses are returned as a MeasurementArray

Response for aliases: p1, s01, s02, s03

<Object>
  io_id<Integer> # Id of the requested I/O
  time<Integer>  # Timestamp of the requested year in milliseconds
  data<Object>
      electric_energy_low<Array>
        0<MeasurementArray>
        .
        .
        11<MeasurementArray>
      electric_energy_high<Array>
        0<MeasurementArray>
        .
        .
        11<MeasurementArray>

Response for alias: p1-gas

<Object>
  io_id<Integer> # Id of the requested I/O
  time<Integer>  # Timestamp of the requested year in milliseconds
  data<Object>
      gas<Array>
        0<MeasurementArray>
        .
        .
        11<MeasurementArray>
Response codes
200 OK              # Successful API response without errors
202 Accepted        # API is unable to immediately fulfill the request, the API returns a promise
403 Unauthorized    # Access denied. API key invalid for this action
408 Request Timeout # API was unable to respond on time
412 Precondition Failed # The specified alias is not supported by this endpoint
502 Bad Gateway     # An unexpected error occurred in the API
Example
GET https://mijn.cemm.nl/open-api/v1/cemm/FF-FF-FF-FF-FF-FF/p1-gas/data/year/?time=1496242535&api_key=4e4f657....

{  
    "io_id":2,
    "time":1496242535000,
    "data":{  
        "gas":[  
            [  
                1512082800000,
                0
            ],
            .
            .
            .
            [  
                1488322800000,
                144.4921875
            ],
            [  
                1485903600000,
                229.00390625
            ],
            [  
                1483225200000,
                281.623046875
            ]
        ]
    }
}

Request meter readings of an I/O using an alias

This endpoint returns a dataset with the last known meter reading of the day for the selected I/O by alias. Available aliases for this endpoint are: p1p1-gass01s02s03

Endpoint
GET cemm/<CEMM UID>/<ALIAS>/totals/
URL Parameters
  • <CEMM UID> The mac address of the CEMM as returned by the cemm/ endpoint
  • <ALIAS> The alias for the I/O to be requested
GET Parameters

api_keyThe Open API authentication keytimeTimestamp of the day in seconds (can be any moment of the day)

Response

This endpoint returns a JSON object. The structure of the JSON object is illustrated below. The response depends on the requested alias. All I/O sensor values in the API responses are returned as a MeasurementArray

Response for aliases: s01, s02, s03

<Object>
  io_id<Integer> # Id of the requested I/O
  time<Integer>  # Timestamp of the requested day in milliseconds
  data<Object>
    electric_energy<MeasurementArray>
    electric_energy_high<MeasurementArray>

Response for alias: p1

<Object>
  io_id<Integer> # Id of the requested I/O
  time<Integer>  # Timestamp of the requested day in milliseconds
  data<Object>
    t1<MeasurementArray>
    t2<MeasurementArray>
    t3<MeasurementArray>
    t4<MeasurementArray>
    electric_energy<MeasurementArray>
    electric_energy_high<MeasurementArray>
    gas<MeasurementArray>

Response for alias: p1-gas

<Object>
  io_id<Integer> # Id of the requested I/O
  time<Integer>  # Timestamp of the requested day in milliseconds
  data<Object>
      gas<MeasurementArray>
Response codes
200 OK              # Successful API response without errors
202 Accepted        # API is unable to immediately fulfill the request, the API returns a promise
403 Unauthorized    # Access denied. API key invalid for this action
408 Request Timeout # API was unable to respond on time
412 Precondition Failed # The specified alias is not supported by this endpoint
502 Bad Gateway     # An unexpected error occurred in the API
Example
GET https://mijn.cemm.nl/open-api/v1/cemm/FF-FF-FF-FF-FF-FF/p1/totals/?time=1496242535&api_key=4e4f657....


{
  "io_id": 1,
  "time": 1496242535000,
  "data": {
    "t1": [
      1496242500000,
      1350.5639648438
    ],
    "t2": [
      1496242500000,
      1612.3809814453
    ],
    "t3": [
      1496242500000,
      883.86798095703
    ],
    "t4": [
      1496242500000,
      2005.5209960938
    ],
    "electric_energy": [
      1496242500000,
      466.6960144043
    ],
    "electric_energy_high": [
      1496242500000,
      -393.11401367188
    ],
    "gas": [
      1496242500000,
      2616.8449707031
    ]
  }
}

Please note that this documentation only applies to CEMM Basic and CEMM Plus.

The Local Open API makes it possible to extract data from the CEMM to be used in different applications. This version of the Open API is only accessible in the same network as the CEMM. When you need to access the CEMM from outside the network, please use the Remote Open API. Use the discovery broadcast to find a CEMM in the local network.  

API Endpoints

The API currently supports several HTTP endpoints to extract data from the CEMM. These Each request will respond with JSON. All available endpoints are described below.

CEMM information

GET /open-api/v1/

This is the root of the Open API. The response body will contain basic information about the CEMM. Most useful is the mac property, which contains the unique MAC address of the CEMM. See the example below:

GET /open-api/v1/
{
  "data": {
    "mac": "00:1E:C0:85:96:CC",
    "name": "CEMM Basic",
    "type": "E5AD649292BBBB51060F",
    "version": "2.18.1.0",
    "core": "1.24"
  }
}

Realtime data

GET /open-api/v1/<alias>/realtime/

The realtime endpoint will return the most recent timestamp (in ms) and value for each channel of the specified alias. Which channels are returned, depends on the type of alias. See Common channels.

GET /open-api/v1/p1/realtime/
{
  "data": {
    "t1": [
      1587565238000,
      78659.671875
    ],
    "t2": [
      1587565238000,
      114467.5703125
    ],
    "t3": [
      1587565238000,
      28713.73828125
    ],
    "t4": [
      1587565238000,
      33709.36328125
    ],
    "electric_power": [
      1587565238000,
      -8840
    ],
    "rate": [
      1587565238000,
      2
    ],
    "gas": [
      0,
      0
    ]
  }
}

Historical data

GET /open-api/v1/<alias>/data/day/
Returns one value per minute for the current day. The current and future minutes are not included, except the last minute of the day, which will be null.

GET /open-api/v1/<alias>/data/month/
Returns one value per day for the current month. Days in the future will have value 0.

GET /open-api/v1/<alias>/data/year/
Returns one value per month of the current year. Months in the future will have value 0.

Specify the GET parameter time to set the start timestamp (in Unix epoch seconds) of the requested period.

The response will contain datasets for one or more channels depending on the selected alias. Each dataset is a list of samples where each sample is a list of two items: the timestamp in milliseconds and the value.

GET /open-api/v1/p1/data/day/?time=1587420000
{
  "io_id": "88",
  "time": 1587420000,
  "data": {
    "electric_power": [
      [
        1587506399000,
        null
      ],
      [
        1587506340000,
        1030
      ],
      [
        1587506280000,
        1033
      ],
      [
        1587506220000,
        1030
      ],
      
      ........
      [
        1587420120000,
        1006
      ],
      [
        1587420060000,
        1008
      ],
      [
        1587420000000,
        1000
      ]
    ]
  }
}

Available Aliases

Smart meters

The -usb variant should be used when the meter is connected to the USB port of the CEMM.

p1, p1-usb
emucs, emucs-usb
han
dlms-usb
p1-gas

Pulse meters

Alias (electricity)Alias (water, gas)Physical connection
s01pulse-1connection 2
s02pulse-2connection 1.1
s03pulse-3connection 1.2

Modbus electricity meters

These meters have a dynamic alias, which is based on the Modbus address of the meter. The alias is mbX where X is the Modbus address. A meter with address 5 will use alias mb5.

Electric usage

The actual electric usage can be requested using alias usage.

Common channels

NameUnitDescription
t1kWhMeter reading: usage (low tariff, or single counter)
t2kWhMeter reading: usage (high tariff)
t3kWhMeter reading: feed-in (low tariff, or single counter)
t4kWhMeter reading: feed-in (high tariff)
electric_energykWht1 – t3
electric_energy_highkWht2 – t4
electric_powerWatt
rateThe tariff index
gasMeter reading of the gas meter
volumeMeter reading of the water or gas meter
flowL/minFlow rate of water or gas

Please note that this documentation only applies to CEMM Basic and CEMM Plus.

The discovery broadcast can be used to find and identify CEMMs in the local network. The broadcast works by sending a UDP message to the broadcast IP of the network on port 9777. The data should be an utf-8 encoded string “cemm_query”. Each CEMM with core version 1.23 and above will respond to this query with an answer containing information about the CEMM, see the example response below.

{
    "ip": "192.168.2.115",
    "mac": "00:1E:C0:85:96:CC",
    "version": "1.24",
    "type": "CEMM_basic",
    "init_state": 1
}

A very basic Python implementation to execute the broadcast might look like:

import socket
import time
query_str = b"cemm_query"
broadcast_wait = 5
server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
server.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
server.bind(("", 9777))
server.settimeout(broadcast_wait)
start = time.time()
server.sendto(query_str, ("192.168.2.255", 9777))
while time.time() < start + broadcast_wait:
    try:
        data, addr = server.recvfrom(1024)
        if data == query_str:
            continue
        else:
            print("%s:%s >>> %s" % (addr[0], addr[1], data))
    except socket.timeout:
        pass
server.close()

This script will output:

192.168.2.153:9777 >>> b'{"ip": "192.168.2.153", "mac": "D8:80:39:46:22:B5", "version": "1.23", "type": "CEMM_basic", "init_state": 1}'
192.168.2.115:9777 >>> b'{"ip": "192.168.2.115", "mac": "00:1E:C0:85:96:CC", "version": "1.24", "type": "CEMM_basic", "init_state": 1}'
CEMM Basic & CEMM Plus