TQL and JDBC Driver
There are two ways to send queries from the outside to the Time Series Engine (TSE) — the query language is TQL, and the access method is the JDBC driver.
드라이버 plantpulse.timeseries.tql.TQLDriver
URL jdbc:ts://<호스트>:7800
계정 tse / (설치가 정한 비밀번호)
TQL is one of four
The Data Gateway (:5500) selects a backend based on the query language. It is structured so that you don't need to know which engine you are connecting to, and TQL is responsible for the Time Series Engine.
| Language | Backend | What it is used for |
|---|---|---|
| PQL | PostgreSQL | Master data · configuration(mm_*) |
| CQL | Aster TSDB | Raw time series · aggregation(tm_*) |
| SQL | Spark | Lakehouse · large-scale analytics |
| TQL | Time Series Engine (TSE) | Time-window aggregation · gap filling |
When sending to the Gateway, specify the language in the header.
curl -sk -X POST https://<호스트>:5501/api/v1/query \
-H 'X-Lang: TQL' \
-H 'X-API-Key: <data.gateway.api.key>' \
-H 'Content-Type: text/plain' \
--data "SELECT LAST('1 DAYS', 'END') FROM CHANNEL1.PUMP1.TEMP_0001 \
WHERE timestamp BETWEEN '2022-01-01 00:00:00.000' AND '2030-12-31 23:59:59.999'"
The response is in the form {"result":"SUCCESS","data":[...]}.
5500, you get a 302 redirect to 55015500 is plaintext, 5501 is TLS. Even if you send over plaintext, you will be redirected, so it is more efficient to send via 5501 from the start — it saves one round trip.
Table names are "paths"
The FROM clause of TQL is not a relational table name, but a tag path.
FROM <채널>.<설비>.<태그>
예: CHANNEL1.PUMP1.TEMP_0001
Time ranges are specified with WHERE timestamp BETWEEN … AND …, and string literals use 'YYYY-MM-DD HH:mm:ss.SSS'.
Connecting via JDBC
BI tools, batch processes, and custom programs use JDBC.
Class.forName("plantpulse.timeseries.tql.TQLDriver");
try (Connection c = DriverManager.getConnection(
"jdbc:ts://192.168.0.41:7800", "tse", "<password>");
Statement st = c.createStatement();
ResultSet rs = st.executeQuery(
"SELECT LAST('1 DAYS','END') FROM CHANNEL1.PUMP1.TEMP_0001 "
+ "WHERE timestamp BETWEEN '2026-09-01 00:00:00.000' "
+ "AND '2026-09-02 00:00:00.000'")) {
while (rs.next()) System.out.println(rs.getString(1));
}
If you want to provide it via configuration, use jdbc.tse.* in plantpulse-jdbc.properties.
| Key | Value |
|---|---|
jdbc.tse.driver | plantpulse.timeseries.tql.TQLDriver |
jdbc.tse.url | jdbc:ts://<호스트>:${PP_TSE_PORT} |
jdbc.tse.username | tse |
jdbc.tse.password | Value set by the installation |
Optional keys include jdbc.tse.pool.initial|min|max and jdbc.tse.query.timeout|fetch-size.
jdbc.tse.url to tss (7801)The TQL JDBC driver uses the plaintext TSE listener (7800). The default for TSE clients is globally plaintext ts/7800 (as of 2026-08).
If you set it to tss/7801, the failure propagates: JDBC connection failure → Data Gateway boot failure → /api/v1/* returns 404 for everything → analytics catalog 404. That is why ts and PP_TSE_PORT are pinned → Property Reference
TSE Client (Java)
If JDBC is read-oriented, the TSE Client is a native library that supports writes as well. It is the same library that the platform itself uses to push metrics.
plantpulse-platform:plantpulse-timeseries-engine-client
Two variants
| Class | What it does | When to use |
|---|---|---|
TSEClient | Buffered store-and-forward for writes | Default. Writes are not lost even if the engine briefly disconnects |
DirectTSEClient | Unbuffered raw HTTP | When buffering is a hindrance (testing, one-off tools) |
The constructor for TSEClient is identical to that of DirectTSEClient, so you can swap them in directly.
The buffer worker thread starts lazily upon the first buffered write, so clients that only query do not consume additional threads.
Connecting
import plantpulse.timeseries.engine.client.TSEClient;
// protocol · host · port · user · password
TSEClient client = new TSEClient("https", "192.168.0.41", 7801, "tse", "<password>");
// URL 한 줄로도 됩니다
TSEClient client2 = new TSEClient("https://192.168.0.41:7801");
Defaults are https, 7801, and timeout 60초.
They differ. The TSE Client uses DEFAULT_PROTOCOL=https and DEFAULT_PORT=7801, while the JDBC driver uses plaintext 7800 (see the danger above). They are two listeners on the same engine.
Writing values
import plantpulse.timeseries.engine.client.builder.MetricBuilder;
MetricBuilder builder = MetricBuilder.getInstance();
builder.addMetric("PLANTPULSE.LINE1.PUMP1.TEMP")
.addDataPoint(System.currentTimeMillis(), 42.7)
.addTag("site", "SITE_00001");
client.pushMetrics(builder);
Reading values
import plantpulse.timeseries.engine.client.builder.QueryBuilder;
QueryBuilder q = QueryBuilder.getInstance();
// 범위와 메트릭을 지정한 뒤
QueryResponse res = client.query(q);
If you have built the JSON yourself, you can send it directly with client.query(String jsonText).
Other operations
| Operation | Method |
|---|---|
| List metric names | getMetricNames() |
| Engine status | getStatus() · getStatusCheck() |
| Manage rollup (pre-aggregation) jobs | createRollupTask() · getRollupTasks() · deleteRollupTask() |
| Delete metrics | deleteMetric(name) · delete(QueryBuilder) |
| Metadata | getMetricMetadata() · setMetricMetadata() · deleteMetricMetadata() |
| Tag queries | queryTags(QueryTagBuilder) |
Which path to choose
| Scenario | What to use |
|---|---|
| App with a single entry point for all four backends | Gateway POST /api/v1/query + X-Lang |
| Java program accessing only TSE | JDBC (jdbc:ts://) |
| PlantPulse Dashboard · BI tools | JDBC → Build a dashboard |
| Convenient client library | tql() of Data Gateway Client |
| Java with write access to TSE | TSE Client — see the section above |
See also
- Time series functions — bucketing · gap fill · interpolation
- Data Gateway Client — Java wrapper
- Query console — directly from the browser