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
- In testo Smart open Settings → Advanced settings.
- In the section Test beta features switch on Live values UDP broadcast.
- 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 noContent-Typeheader. 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-Lengthheader; chunked transfer encoding is not supported. - Unknown endpoints and wrong methods return
404 Not Foundwith 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°Cin English,21,4°Cin German). - Special values:
+++above measuring range,---below measuring range,xxxinvalid value,-no value. - Serial numbers are returned as strings (object keys and
Serial). Note that/api/remotecontrol/buttonclickexpects 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 OKwith 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 returns200 OK, but nothing happens.400 Bad Requestif the body is not a JSON object orserialis missing.- For the testo 805i thermometer the request toggles Hold (freezes the displayed value);
clickIdis 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 OKwith the customer as a JSON object.404 Not Foundwith the textUser with UUID not foundif 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 OKwith an empty body on success.400 Bad Requestif 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.