Ignition Project
An importable Ignition project archive that adds a waterly script library to your
Gateway. Post selected tag paths from a Gateway Scheduled or Timer event, authenticate with a
token in the Gateway environment, and choose source or execution timestamps for your readings. No
intermediate server is required.
Prerequisites
- Ignition 8.1+ Gateway with Designer access.
- An Ignition tag provider with the tags you want to submit.
-
A Waterly-provided device ID, API token, submission URL, and device type. This project uses
device type
Ignition. Email support@waterly.com to request credentials and confirm your configuration. - Outbound HTTPS access from the Ignition host to the WaterlyConnect endpoint.
- Administrator access to the Gateway host and a service restart coordinated with the site operator.
Import the Project
Updating an existing installation? Follow the upgrade steps before replacing the module, and preserve your configuration when reviewing import prompts.
-
1
Open the Gateway Webpage. Navigate to Config ▸ System ▸ Projects.
-
2
Import. Click Import project…, select
ignition_to_waterly.zip, and follow the prompts. -
3
Verify. Check Status ▸ Gateway Scripts to confirm the project loaded. You can also verify via Designer ▸ Project Browser ▸ Scripting ▸ Script Library ▸ waterly.
Configure the Endpoint and Device
In Designer, open Project Browser ▸ Scripting ▸ Script Library ▸ waterly. Update the non-secret settings at the top of the module and save with Ctrl+S:
# --- Non-secret Waterly configuration ---
waterly_api_url = "https://connect.waterly.com/api/data-submission/v1/submit"
waterly_device_id = "<WATERLY_DEVICE_ID>" # Provided by Waterly
Use the endpoint supplied by Waterly, including /submit. The request device type
remains Ignition. Keep the device ID here; configure the token on the Gateway host
below.
Set the Gateway Token
Set WATERLY_DEVICE_TOKEN in the environment of the
Ignition Gateway process. A variable on your Designer workstation does not
configure the Gateway. Coordinate restarts with the site operator because they interrupt the
Gateway's other work.
The module uses Java's System.getenv("WATERLY_DEVICE_TOKEN") and sends the value in
the existing x-waterly-connect-token header. It reads the environment inherited by
the JVM at startup; it does not provision, persist, or dynamically reload environment variables.
Windows Gateway Server
-
1
Sign in to the Gateway server as an administrator. Search for Edit the system environment variables, then open System Properties ▸ Advanced ▸ Environment Variables.
-
2
Under System variables, add or edit
WATERLY_DEVICE_TOKEN. Paste the Waterly-provided value without extra quotes or spaces and save all dialogs. Use system variables, not user variables. -
3
Open Services (
services.msc) and restart the actual Ignition Gateway service. Its name may be customized. Restart the full Windows service, not only Designer or the project. -
4
After the Gateway returns, run a Gateway event and verify the log and received submission.
A variable set only in Command Prompt or PowerShell does not configure the service. If the variable is still missing after a full service restart, ask the administrator to check system variables and the service configuration; a server reboot may be needed if the service launcher retains its old environment.
Linux Gateway Server
For a systemd installation, have the administrator create
/etc/ignition-waterly/gateway.env outside the project and repository, owned by root
with file permissions 600 and directory permissions 700. In an editor,
replace this fictional value with the Waterly token:
WATERLY_DEVICE_TOKEN=REPLACE_WITH_WATERLY_PROVIDED_TOKEN
Find the service with systemctl list-unit-files '*[Ii]gnition*'. If it is
Ignition-Gateway.service, run
sudo systemctl edit Ignition-Gateway.service
and add this override. Substitute your actual service name throughout:
[Service]
EnvironmentFile=/etc/ignition-waterly/gateway.env
Reload the service definition, restart, and verify a submission:
sudo systemctl daemon-reload
sudo systemctl restart Ignition-Gateway.service
A shell export or user profile alone does not configure a system service. For a
non-systemd installation, set the variable in that service's startup environment and restart the
entire service.
Containerized Gateway
Inject the variable when creating the Gateway container. For an existing Docker Compose service
named gateway, add an env_file entry. Preserve its current image, ports,
and persistent data volume; this is an addition to your deployment, not a complete Compose file:
services:
gateway:
env_file:
- /secure/ignition/waterly.env
Create that file on the deployment host, restrict access to the deployment administrator, and keep
it outside source control. Use the
WATERLY_DEVICE_TOKEN=REPLACE_WITH_WATERLY_PROVIDED_TOKEN
format above, replacing the fictional value locally. After setting or changing it, recreate the
Gateway container using your actual service name:
docker compose up -d --force-recreate --no-deps gateway
A host .env file alone does not inject the token into the container.
docker compose restart does not apply changed environment settings. Keep the
Gateway's persistent data volume when recreating it, then verify a submission.
This integration supports only WATERLY_DEVICE_TOKEN in the Gateway environment. Do
not put the token in project scripts, tags, ignition.conf, or Java
-D properties. There is no alternate variable name or hard-coded fallback.
Environment variables are not encrypted secret storage; restrict access to the host and
deployment files, and never print the token or include it in screenshots or support material.
Upgrade, Rotate Tokens, and Configure Redundancy
Existing installations must change how they supply the token. Existing tag lists, function calls, and timestamp options remain compatible once the Gateway environment is configured.
-
1
Provision
WATERLY_DEVICE_TOKENon the Gateway host or in the container deployment as described above. -
2
Replace the complete
waterlymodule, including its imports, using the current project ZIP or source. Preserve the endpoint, device ID, tag configuration, and Gateway Event scripts when reviewing import/overwrite prompts. -
3
Remove the old token assignment. Restore only the non-secret endpoint and device ID to the module, save, then restart the full Gateway service or recreate the container.
-
4
Verify a successful submission using both Gateway logs and Waterly.
Copying only the function omits the required Java import. Replace the whole module from
waterly/code.py, which includes:
from java.lang import Exception as JavaException, System
Token Rotation
Update WATERLY_DEVICE_TOKEN, restart the entire Gateway service or recreate the
container, then verify submissions succeed. Removing the old assignment does not erase earlier
exports, backups, or source history; rotate a token that was exposed.
Redundant Gateways
Provision the token independently on each node and coordinate restarts with the site operator. Project synchronization, Gateway backup/restore, and redundancy do not replicate the operating-system environment variable. Verify each node when it is active.
Add a Gateway Event
The helper is sendDataToWaterly(tags=None, send_now_time_all=False). A full-path
string or a list of strings continues to work with source timestamps by default.
-
1
In Designer, open Project Browser ▸ Scripting ▸ Gateway Events.
-
2
Add a Scheduled (specific times) or Timer (fixed rate) event. Give it a descriptive name and configure the timing.
-
3
Paste one of the example scripts below into the Script tab, enable the event, and Save the project.
Scheduled Event Script
Use a Scheduled event to run at specific times (e.g., midnight and noon). Available in Ignition 8.1.6+.
def onScheduledEvent():
tags = [
"[default]SiteA/WetWellLevel",
"[default]SiteA/InfluentFlow",
"[default]SiteA/PumpRuntime",
]
waterly.sendDataToWaterly(tags)
Timer Event Script
Use a Timer event for a fixed heartbeat (e.g., every 60 000 ms). Set Delay and Delay Type in the event configuration.
tags = [
"[default]SiteA/WetWellLevel",
"[default]SiteA/InfluentFlow",
"[default]SiteA/PumpRuntime",
]
waterly.sendDataToWaterly(tags)
Choose Source or Execution Timestamps
By default, last_change_timestamp comes from the Ignition
QualifiedValue.timestamp, converted from milliseconds to whole Unix seconds. Keep
this default for process values where the last actual change matters.
Periodic totals can repeat: daily runtime might be 8.5 hours on two consecutive days, while Ignition retains the earlier timestamp. Use execution time for those calculated observations and schedule the submission after their calculation completes. Execution time is when the helper runs; it does not backdate a reading to a previous reporting period.
Select Individual Tags
Mix full-path strings with dictionaries containing tag_name and optional
send_now_time. An omitted or False setting keeps source time. Both
opted-in aggregate tags below receive the same execution timestamp:
tags = [
"[default]Process/TankLevel",
{"tag_name": "[default]DailyTotals/DailyRuntime", "send_now_time": True},
{"tag_name": "[default]DailyTotals/DailyStarts", "send_now_time": True},
{"tag_name": "[default]Process/Pressure"},
]
waterly.sendDataToWaterly(tags)
Use this in a Timer event, or inside onScheduledEvent() for a Scheduled event.
Replace these fictional paths with your full Ignition paths, including provider and folders. The
helper reads that exact tag_name and sends it unchanged as the payload's
name. No alias or separate path field is needed.
Use Execution Time for Every Tag
Set send_now_time_all=True for this invocation to override every individual setting,
including an explicit False:
tags = [
"[default]DailyTotals/DailyFlowTotal",
{"tag_name": "[default]DailyTotals/DailyRuntime", "send_now_time": False},
]
waterly.sendDataToWaterly(tags, send_now_time_all=True)
| Global send_now_time_all | Per-tag send_now_time | Timestamp sent |
|---|---|---|
False or omitted |
False or omitted (including strings) |
Ignition source timestamp |
False or omitted |
True |
Shared batch execution timestamp |
True |
Any setting | Shared batch execution timestamp |
After the blocking tag read and before processing values, the helper captures
now = int(time.time()) once. It reuses that whole-second Unix timestamp for the
payload's timestamp and every tag using execution time. A later invocation captures a
new now. These options configure the connector; they are not additional API payload
fields.
Automatically Included System Tags
The helper appends [System]Gateway/CurrentDateTime,
[System]Gateway/Timezone, and [System]Gateway/UptimeSeconds. They keep
source timestamps by default; send_now_time_all=True applies to them too.
In either mode, only good-quality tags are submitted, values remain strings, and caller-owned tag lists remain unchanged so events can reuse them.
Verify and Troubleshoot
-
1
Save and enable the Timer or Scheduled event. Use Gateway Webpage ▸ Status ▸ Gateway Scripts to check that it runs.
-
2
Check the
WaterlyConnectlogger forSuccessful Post to WaterlyConnect, then verify the corresponding received submission in Waterly, including the tag paths and intended timestamps.
A completed event alone does not prove a successful submission. Configuration and HTTP failures are logged and return without raising. Missing, empty, whitespace-only, or unreadable token values stop the invocation before any tag read or HTTP request.
Gateway Token and Module Errors
-
WATERLY_DEVICE_TOKEN environment variable is not set or is blank: Set a nonblank value in the Gateway environment, then restart the service or recreate the container. On Windows, use System variables. No request is sent while this error persists. -
cannot read WATERLY_DEVICE_TOKEN from the Gateway environment: Ask the administrator to check Java environment access. No request is sent; do not restore a script token as a workaround. -
NameErrorforSystemorJavaExceptionunderTimerScriptTask: Replace the complete module, including its imports, and save. This indicates an incomplete update; the intended missing-token error appears under theWaterlyConnectlogger. -
Unexpected keyword argument: Update the imported module before calling it
with
send_now_time_all.
Submission and Timestamp Checks
-
Error posting to WaterlyConnect: Check the endpoint, device ID, Gateway token setup, network access, and TLS trust. Response bodies, request headers, and Python/Java exception details are intentionally omitted from logs to avoid exposing credentials. Share the failure time and non-secret configuration with support, never the token or full headers. -
Repeated daily values have an older date: Opt those aggregate tags into
send_now_time=Trueand run the event after their calculation finishes. -
Unexpected execution timestamps:
send_now_time_all=Trueoverrides per-tagFalse. Omit the global option or set it toFalseto honor individual settings. - Missing tags or events: Check full paths, tag quality, and whether the event is enabled and saved. Designer Script Console reads can help check tag paths, but that console does not run in the Gateway process and cannot verify its environment.
Files
Importable .zip containing the gateway script library and project manifest.
The complete waterly/code.py module, including imports, Gateway token lookup,
and timestamp options.
Full installation, Gateway token setup, timestamp options, upgrade, and troubleshooting guidance.
Open README