Skip to content

Device to Device interface

testo Smart offers a local network interface that other software in the same network (e.g. a PC, a tablet or a building control system) can use to discover the app, read live measurement values and manage customers.

Open interface — changes coming

The network interfaces described here are unauthenticated and unencrypted (plain HTTP / UDP). Only use them in trusted networks. Due to regulatory requirements (e.g. the EU Cyber Resilience Act) these interfaces will change. How these changes will look is not yet defined. Design your integration so that an authentication step can be added later without breaking your client.

Overview

Port Protocol Direction Purpose Availability
53955 UDP broadcast testo Smart → network Discovery broadcast (IP address of the app) always
53957 UDP broadcast testo Smart → network Live values broadcast beta, opt-in
54000 HTTP (TCP) client → testo Smart HTTP interface: live values, customers, remote control always
sequenceDiagram
  participant S as testo Smart
  participant C as Your software
  S-->>C: UDP broadcast :53955 (every second, IP address of the app)
  opt Beta "Live values UDP broadcast" enabled
    S-->>C: UDP broadcast :53957 (every second, live values)
  end
  C->>S: HTTP GET http://<HttpServerIPv4>:54000/api/data/live
  S-->>C: JSON live values

All interfaces are available on Android and iOS while testo Smart is running in the foreground. On iOS the user has to allow Local Network access for testo Smart.

UDP discovery broadcast

testo Smart sends a UDP broadcast (255.255.255.255) to port 53955 once per second on every network it is connected to. Use it to find the IP address of the phone or tablet running testo Smart.

Note

No discovery broadcast is sent while a measurement is running. The HTTP interface stays available during that time — remember the last received IP address.

Field Type Description
AppVersion string Version of testo Smart, e.g. 33.1.0
DeviceId string Always SmartProbesApp for testo Smart (testo 400 for the testo 400)
FirmwareVersion string Empty for testo Smart
HttpServerIPv4 string IPv4 address of the app in the network the broadcast was sent to
HttpServerPort number Not the HTTP port — internal port reserved for testo PC software. Use port 54000 for HTTP
Serial string Random ID of this testo Smart installation (not a device serial number)

You can test the broadcast by using netcat as shown below.

REM Receive the broadcast using netcat
nc -ulp 53955
{"AppVersion":"33.1.0","DeviceId":"SmartProbesApp","FirmwareVersion":"","HttpServerIPv4":"192.168.178.34","HttpServerPort":53956,"Serial":"1804289383"}
# Receive the broadcast using netcat
nc -ul 53955
{"AppVersion":"33.1.0","DeviceId":"SmartProbesApp","FirmwareVersion":"","HttpServerIPv4":"192.168.178.34","HttpServerPort":53956,"Serial":"1804289383"}
# Receive the broadcast using netcat
nc -ul 53955
{"AppVersion":"33.1.0","DeviceId":"SmartProbesApp","FirmwareVersion":"","HttpServerIPv4":"192.168.178.34","HttpServerPort":53956,"Serial":"1804289383"}

Warning

Ignore HttpServerPort in this message — always use port 54000 for HTTP connections!

UDP live values broadcast (beta)

As a beta feature, testo Smart can push the current measurement values of all connected probes as a UDP broadcast, so no polling is required.

Enabling the broadcast

  1. In testo Smart open Settings → Advanced settings.
  2. In the section Test beta features switch on Live values UDP broadcast.
  3. Restart testo Smart. The setting is only evaluated at app start.

Beta

Beta features may change or be removed in future versions of testo Smart.

Format

  • Destination: 255.255.255.255:53957, sent on every connected network.
  • Rate: once per second, also while a measurement is running.
  • Each broadcast is one datagram containing one compact JSON object, in the same format as GET /api/data/live.
REM Receive the live values using netcat
nc -ulp 53957
{"40123456":{"DeviceId":"T605i","Humidity":"45.3%RH","Serial":"40123456","Temperature":"21.4°C"},"AppVersion":"33.1.0"}
# Receive the live values using netcat
nc -ul 53957
{"40123456":{"DeviceId":"T605i","Humidity":"45.3%RH","Serial":"40123456","Temperature":"21.4°C"},"AppVersion":"33.1.0"}
# Receive the live values using netcat
nc -ul 53957
{"40123456":{"DeviceId":"T605i","Humidity":"45.3%RH","Serial":"40123456","Temperature":"21.4°C"},"AppVersion":"33.1.0"}

HTTP interface

testo Smart runs an HTTP/1.1 server on port 54000 on all network interfaces. Use the IP address from the discovery broadcast to connect.

Method Endpoint Description
GET / Returns a HTML live view as displayed on the app
GET /api/data/live Returns JSON live data as displayed on the app
GET /api/deviceInfo Returns information about the testo Smart installation
POST /api/remotecontrol/buttonclick Triggers a button of a connected probe (e.g. start/stop)
GET /api/contact Get a list of customers currently available in the testo Smart
GET /api/contact/{uuid} Get one specific customer identified by {uuid}
POST /api/contact Create one or more customers

General behaviour:

  • No authentication. Responses carry Access-Control-Allow-Origin: * but no Content-Type header. Successful responses of the /api/... routes are UTF-8 JSON (or empty), / returns HTML. Error responses have an empty body or a plain-text message (e.g. User with UUID not found) — check the status code before parsing the body.
  • Send request bodies with a Content-Length header; chunked transfer encoding is not supported.
  • Unknown endpoints and wrong methods return 404 Not Found with an empty body.
  • Query strings are not evaluated.

GET /

A simple HTML page for a web browser that shows all probes with their current values. The page reloads itself every second. Each probe has a Trigger button, which calls /api/remotecontrol/buttonclick.

Open http://<HttpServerIPv4>:54000/ in your browser to try it.

GET /api/data/live

Returns the current values of all connected probes as displayed in the app. Only channels that are visible in the app are included.

curl http://192.168.178.34:54000/api/data/live
{
  "40123456": {
    "DeviceId": "T605i",
    "Humidity": "45.3%RH",
    "Serial": "40123456",
    "Temperature": "21.4°C"
  },
  "51234567": {
    "DeviceId": "T510i",
    "DifferentialPressure": "12.35hPa",
    "Serial": "51234567"
  },
  "AppVersion": "33.1.0"
}
Field Type Description
AppVersion string Version of testo Smart
<serial> object One object per connected probe, keyed by the probe serial number (decimal string)
<serial>.DeviceId string Probe type, e.g. T115i, T405i, T510i, T549i, T605i, T805i, T915i
<serial>.Serial string Probe serial number
<serial>.<MeasType> string One entry per measurement channel (e.g. Temperature, Humidity, DifferentialPressure): value and unit as shown in the app

Notes on the values:

  • Values are strings: the rounded value directly followed by the unit selected in the app, without a space (e.g. 21.4°C).
  • The decimal separator follows the app language (21.4°C in English, 21,4°C in German).
  • Special values: +++ above measuring range, --- below measuring range, xxx invalid value, - no value.
  • Serial numbers are returned as strings (object keys and Serial). Note that /api/remotecontrol/buttonclick expects the serial as a JSON number.
  • The returned JSON is compact (no whitespace) and its keys are sorted alphabetically.

GET /api/deviceInfo

Returns information about the testo Smart installation.

{
    "app": "smartprobesappgen2",
    "appVersion": "33.1.0",
    "name": "SmartProbesApp",
    "serial": "3f2a1c9e-8b7d-4e21-9a0b-1c2d3e4f5a6b"
}
Field Type Description
app string Internal application name
appVersion string Version of testo Smart
name string Always SmartProbesApp for testo Smart
serial string Unique ID of this testo Smart installation

POST /api/remotecontrol/buttonclick

Simulates a button press on a connected probe, e.g. to start or stop a measurement remotely.

curl -X POST http://192.168.178.34:54000/api/remotecontrol/buttonclick \
     -H "Content-Type: application/json" \
     -d '{"serial": 40123456, "clickId": "StartStopToggle"}'
Field Type Required Description
serial number yes Serial number of a connected probe (JSON number, not a string)
clickId string no StartStopToggle (default), Start, Stop, Save or New
  • 200 OK with an empty body when the request was accepted (also when the serial is unknown). A serial sent as a string ("40123456") is treated as unknown: the request returns 200 OK, but nothing happens.
  • 400 Bad Request if the body is not a JSON object or serial is missing.
  • For the testo 805i thermometer the request toggles Hold (freezes the displayed value); clickId is ignored.
  • Whether a button is handled depends on the measurement application currently open in testo Smart.

GET /api/contact

Returns all customers stored in testo Smart as a JSON array ([] if there are none).

[
  {
    "City": "Titisee-Neustadt",
    "Country": "Germany",
    "Email": "info@example.com",
    "Fax": "",
    "Homepage": "https://www.example.com",
    "HouseNumber": "1",
    "Logo": "",
    "Name": "ACME GmbH",
    "PersonOfContact": "Max Mustermann",
    "Phone": "+49 7653 0",
    "PostCode": "79822",
    "Street": "Testo-Straße",
    "Uuid": "6c1f0e8a-2b3c-4d5e-8f90-a1b2c3d4e5f6"
  }
]

All fields are strings. Uuid is a lower-case UUID without braces.

GET /api/contact/{uuid}

Returns one customer (same fields as above) identified by its Uuid.

  • 200 OK with the customer as a JSON object.
  • 404 Not Found with the text User with UUID not found if no customer has this UUID.

POST /api/contact

Creates customers in testo Smart. The body is either a single customer object or an array of customer objects with the fields listed under GET /api/contact (except Uuid). Missing fields are stored as empty strings.

curl -X POST http://192.168.178.34:54000/api/contact \
     -H "Content-Type: application/json" \
     -d '{"Name": "ACME GmbH", "Street": "Testo-Straße", "HouseNumber": "1", "PostCode": "79822", "City": "Titisee-Neustadt", "Country": "Germany"}'
  • 200 OK with an empty body on success.
  • 400 Bad Request if the body is not a JSON object or array, or an array element is not an object. Array elements before the invalid element have already been stored.

Note

Every request creates new customers: a Uuid in the request body is ignored and existing customers are not updated. The new UUID is not returned; use GET /api/contact to read it.