Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,9 @@ target/
.venv*
venv*

# Built bob files
# Built synoptic files
**/data/
**/config/

# further build artifacts
lockfiles/
Expand Down
5 changes: 5 additions & 0 deletions example-synoptic/b23-services/synoptic/create_gui.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -133,11 +133,16 @@ components:

M2:
prefix: FE23B-OP-MR-02
devsta:
- FE23B-OP-MR-02:MOTORSTA

M3:
prefix: BL23B-OP-MR-03
extras:
- BL23B-MO-PMAC-01
devsta:
- BL23B-OP-MR-03:MOTORSTA
- BL23B-MO-PMAC-01:MOTORSTA

# ----- MOD -----

Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ dependencies = [
"lxml>=5.4.0",
"typer>=0.16.0",
"rich>=14.1.0",
"softioc>=4.6.1",
]
scripts = { create-gui = "techui_builder.__main__:app" }

Expand Down
1 change: 1 addition & 0 deletions src/techui_builder/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ def main(

gui.setup()
gui.generate_screens()
gui.write_devsta_pvs()

LOGGER.info(f"Screens generated for {gui.beamline.dom}.")

Expand Down
56 changes: 56 additions & 0 deletions src/techui_builder/builder.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import json
import logging
import os
from collections import defaultdict
from dataclasses import _MISSING_TYPE, dataclass, field
from pathlib import Path
from typing import Any

import yaml
from epicsdbbuilder.recordbase import Record
from lxml import etree, objectify
from lxml.objectify import ObjectifiedElement
from softioc.builder import records

from techui_builder.generate import Generator
from techui_builder.objects import Beamline, Component, Entity
Expand Down Expand Up @@ -45,6 +48,7 @@ class Builder:
entities: defaultdict[str, list[Entity]] = field(
default_factory=lambda: defaultdict(list), init=False
)
devsta_pvs: dict[str, Record] = field(default_factory=dict, init=False)
_services_dir: Path = field(init=False, repr=False)
_gui_map: dict = field(init=False, repr=False)
_write_directory: Path = field(default=Path("data"), init=False, repr=False)
Expand Down Expand Up @@ -79,6 +83,54 @@ def setup(self):
"""Run intial setup, e.g. extracting entries from service ioc.yaml."""
self._extract_services()

def _create_devsta_pv(self, prefix: str, inputs: list[str]):
# Extract all input PVs, provided a default "" if not provided
values = [(inputs[i] if i < len(inputs) else "") for i in range(12)]
inpa, inpb, inpc, inpd, inpe, inpf, inpg, inph, inpi, inpj, inpk, inpl = values

devsta_pv = records.calc( # pyright: ignore[reportAttributeAccessIssue]
f"{prefix}:DEVSTA",
CALC="(A|B|C|D|E|F|G|H|I|J|K|L)>0?1:0",
SCAN="1 second",
ACKT="NO",
INPA=inpa,
INPB=inpb,
INPC=inpc,
INPD=inpd,
INPE=inpe,
INPF=inpf,
INPG=inpg,
INPH=inph,
INPI=inpi,
INPJ=inpj,
INPK=inpk,
INPL=inpl,
)

self.devsta_pvs[prefix] = devsta_pv

def write_devsta_pvs(self):
conf_dir = self._write_directory.parent.joinpath("config")

# Create the config/ dir if it doesn't exist
if not conf_dir.exists():
os.mkdir(conf_dir)

with open(conf_dir.joinpath("ioc.db"), "w") as f:
# Add a header explaining the file is autogenerated
f.write("#" * 51 + "\n")
f.write(
"#" * 2
+ " THIS FILE HAS BEEN AUTOGENERATED; DO NOT EDIT "
+ "#" * 2
+ "\n"
)
f.write("#" * 51 + "\n")

# Write the devsta PVs
for dpv in self.devsta_pvs.values():
dpv.Print(f)

def _extract_services(self):
"""
Finds the services folders in the services directory
Expand Down Expand Up @@ -134,6 +186,10 @@ def generate_screens(self):
# any extras defined
for component in self.components:
screen_entities: list[Entity] = []

if component.devsta is not None:
self._create_devsta_pv(component.prefix, component.devsta)

# ONLY IF there is a matching component and entity, generate a screen
if component.prefix in self.entities.keys():
screen_entities.extend(self.entities[component.prefix])
Expand Down
1 change: 1 addition & 0 deletions src/techui_builder/objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class Component:
prefix: str
desc: str | None = field(default=None)
file: str | None = field(default=None)
devsta: list[str] | None = field(default=None)
extras: list[str] | None = field(default=None)

def __post_init__(self):
Expand Down
Loading