Initial scaffold: CLAUDE.md modules, directory structure, .gitignore
This commit is contained in:
188
ignition/CLAUDE.md
Normal file
188
ignition/CLAUDE.md
Normal file
@@ -0,0 +1,188 @@
|
||||
# Ignition Project Structure — CLAUDE.md
|
||||
|
||||
Parent: [../CLAUDE.md](../CLAUDE.md)
|
||||
|
||||
## Overview
|
||||
|
||||
Ignition 8.3 with Git-native project storage. The project directory is
|
||||
mounted into the Ignition Docker container and is the single source of truth.
|
||||
All resources are JSON files on disk.
|
||||
|
||||
## Git-Native Project Storage
|
||||
|
||||
Ignition 8.3 stores projects as files and directories:
|
||||
|
||||
```
|
||||
ignition/project/
|
||||
├── project.json ← project metadata
|
||||
├── com.inductiveautomation.perspective/
|
||||
│ ├── views/
|
||||
│ │ └── <view-name>/
|
||||
│ │ ├── view.json ← view definition
|
||||
│ │ └── resource.json ← resource metadata
|
||||
│ └── page-config/
|
||||
├── com.inductiveautomation.webdev/
|
||||
│ └── <endpoint-name>/
|
||||
│ ├── code.py ← Jython 2.7 handler
|
||||
│ └── resource.json
|
||||
└── ignition/
|
||||
├── named-query/
|
||||
│ └── <query-name>/
|
||||
│ ├── query.sql
|
||||
│ └── resource.json
|
||||
├── script-python/
|
||||
│ └── <package>/
|
||||
│ ├── code.py ← project library scripts
|
||||
│ └── resource.json
|
||||
└── global-props/
|
||||
└── props.json
|
||||
```
|
||||
|
||||
## JSON File Rules
|
||||
|
||||
All JSON files in the project directory:
|
||||
|
||||
1. **Must be valid JSON** — validate before writing (use `json.loads()` then write).
|
||||
2. **Must use sorted keys** — `json.dumps(data, sort_keys=True, indent=2)`
|
||||
3. **Must be backed up** before overwriting — `cp file.json file.json.bak`
|
||||
4. **Must use 2-space indentation** — matches Ignition's native format.
|
||||
|
||||
### resource.json Template
|
||||
|
||||
Every resource directory contains a `resource.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"props": {
|
||||
"resource.name": "<resource-name>"
|
||||
},
|
||||
"scope": "G",
|
||||
"version": 1
|
||||
}
|
||||
```
|
||||
|
||||
- `scope`: `"G"` = gateway, `"C"` = client, `"A"` = all
|
||||
- `version`: increment on changes for cache-busting
|
||||
|
||||
## UDT / Linking Pattern
|
||||
|
||||
### Structure
|
||||
|
||||
```
|
||||
[Device Type UDT]
|
||||
├── Config/
|
||||
│ ├── DeviceType (String)
|
||||
│ ├── DeviceId (String)
|
||||
│ └── Description (String)
|
||||
├── Status/
|
||||
│ ├── Running (Boolean)
|
||||
│ ├── Faulted (Boolean)
|
||||
│ └── ...
|
||||
├── Command/
|
||||
│ ├── Start (Boolean)
|
||||
│ ├── Stop (Boolean)
|
||||
│ └── ...
|
||||
└── Linking/
|
||||
└── Link/
|
||||
├── LinkPath (String) ← path to PLC tag
|
||||
└── LinkData (Dataset/Document) ← signal mapping
|
||||
```
|
||||
|
||||
### How LinkPath Works
|
||||
|
||||
`LinkPath` contains the OPC tag path prefix for the PLC signals.
|
||||
Example: `[ControlLogix]Program:MainProgram.P_101`
|
||||
|
||||
`LinkData` maps UDT members to PLC tag suffixes:
|
||||
- `Status/Running` → `LinkPath + ".Sts_Running"`
|
||||
- `Command/Start` → `LinkPath + ".Cmd_Start"`
|
||||
|
||||
This decouples the test/simulation layer from specific PLC I/O structures.
|
||||
Changing the PLC program only requires updating `LinkPath` and `LinkData`.
|
||||
|
||||
### Rules
|
||||
|
||||
- Never modify `LinkPath` or `LinkData` at runtime from external tools.
|
||||
- Set linking configuration through Ignition Designer or startup scripts.
|
||||
- Test scenarios reference device UDT paths, not raw PLC tag paths.
|
||||
|
||||
## Scripting
|
||||
|
||||
### Project Library Scripts (`script-python/`)
|
||||
|
||||
Jython 2.7 — see root CLAUDE.md for language constraints.
|
||||
|
||||
Naming convention:
|
||||
```
|
||||
script-python/
|
||||
├── testing/
|
||||
│ ├── code.py ← testing.runScenario(), testing.validateResults()
|
||||
│ └── resource.json
|
||||
├── devices/
|
||||
│ ├── code.py ← devices.getStatus(), devices.sendCommand()
|
||||
│ └── resource.json
|
||||
└── util/
|
||||
├── code.py ← util.formatTag(), util.validateJson()
|
||||
└── resource.json
|
||||
```
|
||||
|
||||
Access in Ignition: `project.testing.runScenario()`
|
||||
|
||||
### Gateway Event Scripts
|
||||
|
||||
Located in project config, not in `script-python/`.
|
||||
Used for startup initialization, tag change events, scheduled tasks.
|
||||
|
||||
### Common Ignition API Calls
|
||||
|
||||
```python
|
||||
# Tag operations
|
||||
system.tag.readBlocking(["path/to/tag"])
|
||||
system.tag.writeBlocking(["path/to/tag"], [value])
|
||||
system.tag.browseConfiguration("path", {})
|
||||
|
||||
# Named queries
|
||||
system.db.runNamedQuery("queryName", {"param": value})
|
||||
|
||||
# WebDev (inside endpoint handlers)
|
||||
# request object has: data, params, headers, remoteAddr
|
||||
# return dict or string — Ignition serializes to JSON
|
||||
|
||||
# Logging
|
||||
logger = system.util.getLogger("testing")
|
||||
logger.info("message")
|
||||
```
|
||||
|
||||
## Tag Provider Structure
|
||||
|
||||
```
|
||||
[default]
|
||||
├── _types_/ ← UDT definitions
|
||||
│ ├── Devices/
|
||||
│ │ ├── Motor/
|
||||
│ │ ├── Valve/
|
||||
│ │ └── Pump/
|
||||
│ └── Linking/
|
||||
│ └── Link/
|
||||
├── Devices/ ← UDT instances
|
||||
│ ├── Pumps/
|
||||
│ │ ├── P-101/
|
||||
│ │ └── P-102/
|
||||
│ ├── Valves/
|
||||
│ │ └── XV-1001/
|
||||
│ └── Motors/
|
||||
│ └── M-201/
|
||||
└── System/ ← system/status tags
|
||||
├── Health/
|
||||
└── Config/
|
||||
```
|
||||
|
||||
## Perspective Views
|
||||
|
||||
Views are JSON definitions in `com.inductiveautomation.perspective/views/`.
|
||||
Each view folder contains `view.json` (component tree) and `resource.json`.
|
||||
|
||||
Rules:
|
||||
- Do not hand-edit `view.json` unless you understand the component schema.
|
||||
- Prefer creating views through Ignition Designer when possible.
|
||||
- If editing programmatically, validate the full JSON structure before writing.
|
||||
Reference in New Issue
Block a user