plantpulse-timeseries (Time Series)
Role
A dedicated time series engine (TSE) and PlantPulse Dashboard. It stores tag values in Aster TSDB with row-level TTL, and provides aggregation and query APIs.
| Item | Value |
|---|---|
| Module Name | plantpulse-timeseries |
| Installation Path | /opt/kopens/plantpulse-platform/plantpulse-timeseries/ |
| Engine Ports | 7800 (HTTP) · 7801 (TLS) |
| UI Port | 3000 (PlantPulse Dashboard, TLS-only) |
pd Service | timeseries — MASTER only (as of 2026-09-05). engine(tse) → dashboard(grafana) |
| Account | PP_TSE_USER / PP_TSE_PASSWORD |
The worker's engine was just copying rows already written by the master back into the same ring — no one reads it (measured 4.4G). All query consumers point to the master's engine, so it has been made MASTER-only.
Configuration
Directory Structure
plantpulse-timeseries/
├── engine/ # 시계열 엔진 (Java)
│ ├── bin/
│ ├── conf/plantpulse-timeseries-engine.conf # 생성물 (옛 이름 timeseries-engine.conf 로도 한 벌)
│ └── logs/
└── dashboard/ # PlantPulse Dashboard
├── bin/
├── conf/custom.ini # protocol = https · http_port = 3000
├── data/ # PlantPulse Dashboard DB — 이미지 트리 안 (볼륨 아님)
└── logs/
Time Series Engine (7800 · 7801)
There is one configuration template, /etc/kopens/conf/plantpulse-timeseries-engine.conf.template, which is rendered as two files. Key items:
| Item | Value |
|---|---|
jetty.port · jetty.ssl.port | PP_TSE_PORT(7800) · PP_TSE_TLS_PORT(7801). TLS uses the platform-wide keystore |
service.datastore | Aster TSDB module — tables pp.ts_data_points, etc., UnifiedCompactionStrategy |
| Data Point TTL | PP_TSE_DATAPOINT_TTL — default 31536000 seconds (365 days). It is set on every write, so a new value starts a new row |
| Authentication | PP_TSE_USER / PP_TSE_PASSWORD — Not for passwd.sh, but for sidecar updates + restarts |
curl -fsS http://127.0.0.1:7800/api/health # 컨테이너 안
curl -kfsS https://<server-ip>:7801/api/health # 밖에서 — 401 은 «로그인 필요» 이지 «없음» 이 아닙니다
The «Timeseries Engine» card (7801) under Tools in the management console is the management screen for the engine itself. To view time series data, use PlantPulse Dashboard.
PlantPulse Dashboard (3000)
https://<server-ip>:3000/ — TLS-only. Opening with http:// returns a 400 error.
The login account is stored in PlantPulse Dashboard's own repository. To change it, use the PlantPulse Dashboard UI (Profile → Change password) → Console Login Accounts — PlantPulse Dashboard
Dashboards, data sources, users, notification rules, and API keys are now stored in the PostgreSQL grafana database.
Previously, they were in a SQLite file under the image tree (dashboard/data/grafana.db), so recreating the container would revert everything; now they persist.
| Variable | Value |
|---|---|
PP_GRAFANA_DB_USER | grafana (fixed — the schema creates a role with this name) |
PP_GRAFANA_DB_PASSWORD | 🔑 Required for startup — without it, pd start exits with code 3 |
The role password is set from the sidecar value at every boot.
🔴 PlantPulse Dashboard does not move its repository by itself. Pointing it to an empty PostgreSQL results in an empty PlantPulse Dashboard — no dashboards, no data sources, no users. There is a separate procedure to migrate content from the previous SQLite.
After migration, the console opens with the PlantPulse Dashboard default account. Since there's no mechanism to set it at every boot, a person must change it once. Setting an admin account in the configuration file is useless — once the repository has at least one user, the repository wins, and there's no error indicating this.
Operations Commands
docker exec plantpulse-datalake pd status timeseries
docker exec plantpulse-datalake pd restart timeseries # 엔진 + PlantPulse Dashboard
docker exec plantpulse-datalake pd logs --lines 100 timeseries
docker exec plantpulse-datalake pd retention # ts_data_points 의 크기 · 압축 전략
Common Issues
| Symptom | Cause | Action |
|---|---|---|
| Kafka lag increasing | Insufficient engine processing · Aster TSDB I/O | pd flow, pd node compactionstats |
| Data disappearing after a few days | TTL | PP_TSE_DATAPOINT_TTL — older images used a 31-day literal. Already-written rows expire per the old value |
| PlantPulse Dashboard is empty (no dashboards, no data sources) | Migrating repository to PostgreSQL without moving content | See warning above — go through the migration procedure |
pd start exits with code 3 | PP_GRAFANA_DB_PASSWORD is empty | Set a value in the sidecar and restart |
http://…:3000 returns 400 | TLS-only | https:// |
| Slow dashboard responses | Time range too large | Shorten the range, increase the aggregation interval |