SCIoT now validates the primary server and static HTTP client YAML files before startup. Invalid values fail with field-level errors such as communication.http.port: must be between 1 and 65535.
- Server runtime:
src/server/settings.yaml - Static HTTP client runtime:
src/client/python/http_config.yaml - Server examples:
docs/config/server.minimal.yaml,docs/config/server.full.yaml - Static client examples:
docs/config/client-http.minimal.yaml,docs/config/client-http.full.yaml
src/server/client_config.yaml is retained as legacy reference material. New runtime changes should use src/server/settings.yaml for server configuration and src/client/python/http_config.yaml for static-client configuration.
For current supported paths, settings are resolved in this order:
- Explicit CLI arguments, where available. For example,
sciot-client --config src/client/python/http_config.yaml --device-id DEVICE_ID --max-cycles 1. - Environment variables.
- YAML file values.
Supported environment overrides:
SCIOT_TRANSPORTS: comma-separated server transports, for examplehttp,mqtt.SCIOT_SERVER_HOST: server HTTP host for the server, or server host used by the static client.SCIOT_SERVER_PORT: server HTTP port for the server, or server port used by the static client.SCIOT_HTTP_MODEL: model key used by the server HTTP transport.SCIOT_VERBOSE:trueorfalseserver verbosity.SCIOT_CLIENT_DEVICE_ID: static-client device ID.SCIOT_CLIENT_MAX_CYCLES: bounded client cycle count.SCIOT_CLIENT_RUN_DURATION_SECONDS: bounded client run duration.
Server validation covers:
- enabled transports in
communication.mode; - HTTP/WebSocket/MQTT hostnames, ports, endpoints/topics, NTP server names, and model references;
- model dimensions, split-layer limits, and model directories;
- local-inference probability in the inclusive range
0.0..1.0; - offloading algorithm selection under
offloading.algorithm(staticoradaptive_risk) and adaptive tuning values; - delay sections and delay distributions;
- boolean flags such as
verbose,debug_cprofiler, compression, and input saving; evaluation.split.max_rowsandevaluation.split.interval_minutes(non-negative);evaluation.outputs.inference_cyclesandevaluation.outputs.offloading_decisions(booleans);- optional Firestore telemetry publishing under
evaluation.firestore.
The server chooses the next split point through the configured offloading
algorithm. If the section is absent, the runtime keeps the legacy static
behavior. To enable the adaptive risk-aware policy:
offloading:
algorithm: adaptive_risk # static | adaptive_risk
adaptive_risk:
network_window_size: 10
uncertainty_weight: 0.50
hysteresis_margin_ms: 5
min_speed_bytes_per_second: 1
probe_probability: 0.05
device_load_weight: 0.50adaptive_risk reuses the same candidate cost components as static, using
the latest server-measured network speed directly for transfer cost. It then
adds penalties for unstable device/edge measurements, noisy network speed, and
small layer switches. network_window_size controls only the recent raw speed
samples used to estimate network variability; it does not smooth the speed used
for transfer cost. The policy also scales device-side compute estimates by the
reported device CPU occupancy so a busy client moves toward earlier offloading
points faster.
The server writes inference-cycle CSV output under
data/results/evaluations/inference_cycles_*.csv. Each offloading decision is
mirrored to both CSV and JSONL:
data/results/offloading_decisions*.csvdata/results/offloading_decisions_<first_inference_timestamp>.jsonl
Each output stream can be enabled or disabled as needed (both default to true);
a disabled stream skips its event construction entirely, so there is no runtime
cost. Stable scalar metrics are emitted as normal CSV columns; variable-length
values such as per-layer timing and offloading cost lists are preserved as
JSON-encoded CSV cells. JSONL batches keep shared layer sizes once in file
metadata and store scalar per-inference compute timing fields:
evaluation:
outputs:
inference_cycles: true # inference_cycles_*.csv (structured evaluation)
offloading_decisions: true # decision CSV and compact JSONL batchesInstead of a single CSV file with size-based rotation (which discards old data), CSV outputs are split into never-deleted segment files:
evaluation:
split:
max_rows: 5000 # open a new segment every N rows (0 = disabled)
interval_minutes: 30 # open a new segment every T minutes (0 = disabled)A new CSV segment is opened at the first criterion that trips. CSV segment
filenames embed a zero-padded index and segment start time, e.g.
offloading_decisions.seg0001_20260706_101500.csv. The JSONL mirror does not use
CSV-style segments: it writes compact batches named from the first inference
decision timestamp, for example offloading_decisions_20260706_101500.jsonl.
Each JSONL batch starts with shared metadata such as layer sizes and then appends
per-inference rows until adding another row would exceed 950 KiB. Fractional
seconds and numeric suffixes are added only when a new batch would otherwise
collide with an existing filename.
Local CSV output remains the primary runtime artifact. Optionally, the server can also queue each telemetry row for Cloud Firestore publishing in the background:
evaluation:
firestore:
enabled: false
project_id: null # Application Default Credentials project if null
database: null # default Firestore database if null
credentials_path: null # optional service-account JSON path
collection: sciot_results
run_document: null # defaults to the compact server-start timestamp
publish_inference_cycles: true
publish_offloading_decisions: true
flush_interval_seconds: 300The Firestore client is part of the server runtime profile. Install the server
with uv sync --extra server.
Documents are written below:
sciot_results/{run_document}/inference_cycles/{document_id}sciot_results/{run_document}/offloading_decisions/{document_id}
For offloading decisions, the Firestore document id and payload reference the
local JSONL batch file containing the buffered inferences, such as
offloading_decisions_20260630_105214.jsonl, via
offloading_decisions_jsonl_file and offloading_decisions_jsonl_path. The
latest pending offloading-decision JSONL file is parsed into structured
batch_metadata and inferences fields on each flush and deleted locally after
the Firestore write succeeds.
Publishing is buffered and best-effort: local CSV files are written immediately,
then queued Firestore rows and the latest pending offloading-decision batch are
flushed every flush_interval_seconds seconds (five minutes by default).
Firestore errors are logged and do not stop local CSV writes or inference.
Static-client validation covers:
- client identity and lifecycle limits;
- server host/port and endpoint paths;
- model image, input size, split layer, TFLite directory, and submodel prefix;
- delay sections and distributions;
- local-inference probability and boolean flags.
- Do not keep edited runtime copies as committed
.backupfiles. The checked-in.backupconfiguration files were removed; use Git history or files outside the repository for local snapshots. - Use the example files under
docs/config/when creating new deployments. - Prefer environment variables for temporary host, port, model, and bounded-run overrides.
- Add new configuration keys to
src/sciot/config.pyand include valid/invalid tests before using them in runtime code.