diff --git a/cli/src/core/git.py b/cli/src/core/git.py new file mode 100644 index 0000000..b41b19b --- /dev/null +++ b/cli/src/core/git.py @@ -0,0 +1,44 @@ +import logging +from pathlib import Path + +import git + +logger = logging.getLogger() + + +def git_push_service_directory( + repo_root: str | Path, branch_name: str, service_dir_rel_path: str, commit_msg: str +): + """ + Push newly created service to Gitea + """ + try: + repo = git.Repo(repo_root) + + logger.info(f"Switching to branch '{branch_name}'...") + # Create branch if it doesn't exist, then checkout + if branch_name in repo.heads: + new_branch = repo.heads[branch_name] + else: + new_branch = repo.create_head(branch_name) + new_branch.checkout() + + logger.info(f"Staging files inside: {service_dir_rel_path}...") + repo.index.add([service_dir_rel_path]) + + # Check if there are changes to avoid empty commit crashes + if not repo.is_dirty(index=True, working_tree=False, path=service_dir_rel_path): + logger.info("No changes detected. Skipping commit.") + return + + logger.info("Committing changes...") + repo.index.commit(commit_msg) + + logger.info(f"Pushing branch '{branch_name}' to origin...") + origin = repo.remote(name="origin") + origin.push(refspec=f"{branch_name}:{branch_name}").raise_if_error() + + logger.info("Successfully pushed!") + + except Exception as e: + logger.info(f"Git Operation Failed: {e}") diff --git a/cli/src/core/models.py b/cli/src/core/models.py index 54b7b89..7bfa7c3 100644 --- a/cli/src/core/models.py +++ b/cli/src/core/models.py @@ -1,8 +1,9 @@ +import re from pathlib import Path from typing import ClassVar import yaml -from pydantic import BaseModel +from pydantic import BaseModel, field_validator from core.enums import ServiceStatus @@ -16,12 +17,36 @@ class Service(BaseModel): name: str status: ServiceStatus + @property + def name_upper(self): + return self.name.upper() + + @property + def name_lower(self): + return self.name.lower() + + @property + def dir_name(self): + return f"{self.id_str}-{self.name_lower}" + + @property + def id_str(self): + # TODO: max 999 services, enough? + return f"{self.id:03d}" + def to_dict(self): - return {"name": self.name, "status": str(self.status)} + return {"name": self.name_lower, "status": str(self.status)} class Config: use_enum_values = True + @field_validator("name") + @classmethod + def validate_name_chars(cls, value: str) -> str: + if not re.match(r"^[a-zA-Z0-9-]+$", value): + raise ValueError("name can only contain letters, numbers, and dashes") + return value + class ServiceRegistry(BaseModel): config_path: ClassVar[str] = str(SERVICE_REGISTRY_FILENAME) @@ -40,11 +65,11 @@ class ServiceRegistry(BaseModel): def get_services(self) -> list[Service]: return [Service(id=svc_id, **svc_data) for svc_id, svc_data in self.services.items()] - def add_service(self, name: str) -> int: - s = Service(id=self.next_available_id, name=name, status=ServiceStatus.ACTIVE) - self.services.update({s.id: s.to_dict()}) + def add_service(self, name: str) -> Service: + svc = Service(id=self.next_available_id, name=name, status=ServiceStatus.ACTIVE) + self.services.update({svc.id: svc.to_dict()}) self.next_available_id += 1 with open(self.config_path, "w") as f: yaml.safe_dump(self.model_dump(), f) - return self.next_available_id + return svc diff --git a/cli/src/core/render_templates.py b/cli/src/core/render_templates.py index fb21e73..fba7b4b 100644 --- a/cli/src/core/render_templates.py +++ b/cli/src/core/render_templates.py @@ -8,8 +8,9 @@ SERVICE_DEST_DIR = REPO_ROOT / "services" def render_new_service_templates( - service_id: int, - service_name: str, + service_id: str, + service_name_upper: str, + service_name_lower: str, ioc_host: str, ioc_port: int, user: str, @@ -22,9 +23,8 @@ def render_new_service_templates( dst_path=str(SERVICE_DEST_DIR), data={ "service_id": service_id, - "service_name": service_name, - # TODO: make sure this is ok where used (need to replace some chars by '-'?) - "service_name_lower": service_name.lower(), + "service_name_upper": service_name_upper, + "service_name_lower": service_name_lower, # TODO: restrict this, use enum "ioc_host": ioc_host, "ioc_port": ioc_port, diff --git a/cli/src/core/utils.py b/cli/src/core/utils.py index 9d2ccdd..74c7581 100644 --- a/cli/src/core/utils.py +++ b/cli/src/core/utils.py @@ -1,3 +1,4 @@ +import logging from pathlib import Path import git @@ -8,3 +9,10 @@ def get_git_root(path) -> Path: git_root = git_repo.git.rev_parse("--show-toplevel") return Path(git_root) + + +def init_logging(log_level: str = "info"): + """ + Configure logging -- set log level + """ + logging.basicConfig(level=getattr(logging, log_level.upper())) diff --git a/cli/src/service.py b/cli/src/service.py index 3acb6cb..c3bfb2d 100644 --- a/cli/src/service.py +++ b/cli/src/service.py @@ -1,24 +1,36 @@ import typer +from core.git import git_push_service_directory from core.models import ServiceRegistry from core.render_templates import render_new_service_templates +from core.utils import get_git_root, init_logging service = typer.Typer(no_args_is_help=True) +REPO_ROOT = get_git_root(__file__) + @service.command() def add( name: str = typer.Option(..., "--name", "-n"), ): + init_logging() # TODO: add restriction on name (maybe: [a-zA-Z0-9-]) registry = ServiceRegistry.read_from_config() - service_id = registry.add_service(name) + service = registry.add_service(name) render_new_service_templates( - service_id=service_id, - service_name=name, - ioc_host="", - ioc_port=9999, - user="", + service_id=service.id_str, + service_name_upper=service.name_upper, + service_name_lower=service.name_lower, + ioc_host="ex-host", # TODO + ioc_port=9999, # TODO + user="user", # TODO + ) + git_push_service_directory( + repo_root=REPO_ROOT, + branch_name=f"feature/add-service-{service.name_lower}", + service_dir_rel_path=f"services/{service.dir_name}", + commit_msg=f"feature: add new service {service.name_lower}", ) diff --git a/config/services_registry.yml b/config/services_registry.yml index 8061a24..97ec892 100644 --- a/config/services_registry.yml +++ b/config/services_registry.yml @@ -1,4 +1,4 @@ -next_available_id: 6 +next_available_id: 5 services: 0: name: master @@ -15,6 +15,3 @@ services: 4: name: cool-service status: active - 5: - name: cool-service - status: active diff --git a/services/004-cool-service/app/pyproject.toml b/services/004-cool-service/app/pyproject.toml deleted file mode 100644 index 130f690..0000000 --- a/services/004-cool-service/app/pyproject.toml +++ /dev/null @@ -1,33 +0,0 @@ -[project] -name = "agebd-cool-service" -version = "0.1.0" -description = "AGEBD-COOL-SERVICE Service" -requires-python = ">=3.9" -dependencies = [ - "agebd==1.2.0", -] - -[dependency-groups] -dev = [ - "pytest>=8.4.2", - "ruff>=0.15.20", -] - -# This tells uv where to look for 'agebd' during LOCAL dev work -[tool.uv.sources] -# Path is relative to where agebd package is deployed on hla -# machines (see CI/CD in .gitea/workflows) -agebd = { path = "../../../../../packages/{{ agebd_env }}/agebd", editable = true } - -[tool.ruff] -include = [ - "src/**/*.py", -] -line-length = 100 - -[tool.ruff.lint] -# use isort to sort imports -extend-select = ["I"] - -[tool.ruff.lint.isort] -known-first-party = ["agebd"] diff --git a/services/004-cool-service/app/src/AGEBD-SERVICE-COOL-SERVICE.py b/services/004-cool-service/app/src/AGEBD-SERVICE-COOL-SERVICE.py deleted file mode 100644 index f8c09d0..0000000 --- a/services/004-cool-service/app/src/AGEBD-SERVICE-COOL-SERVICE.py +++ /dev/null @@ -1,108 +0,0 @@ -from time import sleep - -import typer -from epics import dbr - -from agebd.enums import LogLevel -from agebd.pv import LocalPVLink -from agebd.pv import PVLink as PV -from agebd.runner import CallbackRunner -from agebd.service.base import BaseService -from agebd.service.pvs import BasePVs -from agebd.utils import get_pv_class, init_logging, printgetversion - -__version__ = printgetversion(__file__) - -PV = get_pv_class() - - -class PVs(BasePVs): - # Option 1: - ## Service specific PVs from dedicated IOC - my_pv1 = PV("MY_PV1") - - ## Service specific PVs from other IOCs - # ... - - def __init__(self, service_name: str, pv_factory): - super().__init__(service_name, pv_factory) - PV = pv_factory - - # TODO: can we do this cleaner? Maybe mechanism for - # settings initial values in dev mode (e.g. ini file) - if isinstance(self.onoff, LocalPVLink): - self.onoff.value = True - - # Option 2: - ## Service specific PVs from dedicated IOC - self.my_pv2 = PV("MY_PV2") - - ## Service specific PVs from other IOCs - # ... - - # TODO: class attribute names usually lowercase - # usually it is advisable to trigger the mainloop of a service on changes of certain PVs: - self.CallbackPV = PV("...", auto_monitor=dbr.DBE_VALUE) - - -class Service(BaseService[PVs]): - def __init__( - self, name: str, pvs: PVs, version: str = __version__, sleep_interval: float = 0.1 - ): - super().__init__(name, pvs, version, sleep_interval) - - # TODO: What is this for? - self.path = "sls/bd/bin" - - def update(self): - # when callback is fired, this code will be executed - if self.CallbackFired: - ####################################################################################### - ####################################################################################### - # here goes all the code that your service - # is supposed to be running when the callback is fired - sleep(1) - ####################################################################################### - ####################################################################################### - - # callback done - self.CallbackFired = 0 - - ####################################################################################### - ####################################################################################### - # here goes all the code that your service - # is supposed to be running in any case, e.g., - # update some pvs/vals - self.pvs.my_pv1.put("MY_PV1 value") - self.pvs.my_pv2.put("MY_PV2 value") - self.val1 = self.pvs.my_pv1.get() - self.val2 = self.pvs.my_pv2.get() - print(self.val1) - print(self.val2) - # maybe sleep to limit the update loop execution rate - sleep(1) - ####################################################################################### - ####################################################################################### - - -def main( - log_level: LogLevel = typer.Option( - LogLevel.INFO, - "--log-level", - "-l", - # Looks at the OS env variable first. If empty, falls back to "INFO" - envvar="SLS_SERVICE_LOG_LEVEL", - # help="Set log level: DEBUG, INFO, WARNING, ERROR, CRITICAL", - case_sensitive=False, - ), -): - init_logging(log_level) - service_name = "" - pvs = PVs(service_name=service_name, pv_factory=PV) - service = Service(name=service_name, pvs=pvs) - runner = CallbackRunner(service=service) - runner.start() - - -if __name__ == "__main__": - typer.run(main) diff --git a/services/004-cool-service/ioc/AGEBD-CPCL-COOL-SERVICE_main.subs b/services/004-cool-service/ioc/AGEBD-CPCL-COOL-SERVICE_main.subs deleted file mode 100644 index 2761c66..0000000 --- a/services/004-cool-service/ioc/AGEBD-CPCL-COOL-SERVICE_main.subs +++ /dev/null @@ -1,4 +0,0 @@ -file COOL-SERVICE.template { - pattern { DEVICE } - { AGEBD-COOL-SERVICE } -} diff --git a/services/004-cool-service/ioc/AGEBD-CPCL-COOL-SERVICE_parameters.yaml b/services/004-cool-service/ioc/AGEBD-CPCL-COOL-SERVICE_parameters.yaml deleted file mode 100644 index ca3ef27..0000000 --- a/services/004-cool-service/ioc/AGEBD-CPCL-COOL-SERVICE_parameters.yaml +++ /dev/null @@ -1,6 +0,0 @@ -cpu_architecture: x86_64 -epics_version: 7.0.8 -ioc_host: -ioc_port: 9999 -os: RHEL8 -os_id: rhel diff --git a/services/004-cool-service/ioc/startup.script b/services/004-cool-service/ioc/startup.script deleted file mode 100644 index 019214a..0000000 --- a/services/004-cool-service/ioc/startup.script +++ /dev/null @@ -1 +0,0 @@ -epicsEnvSet("ENGINEER", "") diff --git a/services/004-cool-service/systemd/AGEBD-SERVICE-COOL-SERVICE.service b/services/004-cool-service/systemd/AGEBD-SERVICE-COOL-SERVICE.service deleted file mode 100644 index c29fbf2..0000000 --- a/services/004-cool-service/systemd/AGEBD-SERVICE-COOL-SERVICE.service +++ /dev/null @@ -1,16 +0,0 @@ -[Unit] -Description=AGEBD-SERVICE-COOL-SERVICE -After=network.target - -[Service] -Environment=AGEBD_ENV={{ agebd_env }} -ExecStart=/sls/bd/hla/bin/start_service.sh 004 COOL-SERVICE -estart=no - -[Install] -WantedBy=default.target - -# https://www.freedesktop.org/software/systemd/man/latest/systemd.service.html -# systemctl --user daemon-reload -# systemctl --user enable /sls/bd/bin/systemd/AGEBD-SERVICE-COOL-SERVICE.service -# systemctl --user start AGEBD-SERVICE-COOL-SERVICE diff --git a/services/1-cool-service/app/pyproject.toml b/services/1-cool-service/app/pyproject.toml deleted file mode 100644 index 3f96a20..0000000 --- a/services/1-cool-service/app/pyproject.toml +++ /dev/null @@ -1,33 +0,0 @@ -[project] -name = "agebd-cool-service" -version = "0.1.0" -description = "AGEBD-cool-service Service" -requires-python = ">=3.9" -dependencies = [ - "agebd==1.2.0", -] - -[dependency-groups] -dev = [ - "pytest>=8.4.2", - "ruff>=0.15.20", -] - -# This tells uv where to look for 'agebd' during LOCAL dev work -[tool.uv.sources] -# Path is relative to where agebd package is deployed on hla -# machines (see CI/CD in .gitea/workflows) -agebd = { path = "../../../../../packages/{{ agebd_env }}/agebd", editable = true } - -[tool.ruff] -include = [ - "src/**/*.py", -] -line-length = 100 - -[tool.ruff.lint] -# use isort to sort imports -extend-select = ["I"] - -[tool.ruff.lint.isort] -known-first-party = ["agebd"] diff --git a/services/1-cool-service/app/src/__init__.py b/services/1-cool-service/app/src/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/services/1-cool-service/ioc/AGEBD-CPCL-cool-service_main.subs b/services/1-cool-service/ioc/AGEBD-CPCL-cool-service_main.subs deleted file mode 100644 index 1022b8b..0000000 --- a/services/1-cool-service/ioc/AGEBD-CPCL-cool-service_main.subs +++ /dev/null @@ -1,4 +0,0 @@ -file cool-service.template { - pattern { DEVICE } - { AGEBD-cool-service } -} diff --git a/services/1-cool-service/ioc/AGEBD-CPCL-cool-service_parameters.yaml b/services/1-cool-service/ioc/AGEBD-CPCL-cool-service_parameters.yaml deleted file mode 100644 index ca3ef27..0000000 --- a/services/1-cool-service/ioc/AGEBD-CPCL-cool-service_parameters.yaml +++ /dev/null @@ -1,6 +0,0 @@ -cpu_architecture: x86_64 -epics_version: 7.0.8 -ioc_host: -ioc_port: 9999 -os: RHEL8 -os_id: rhel diff --git a/services/1-cool-service/ioc/cool-service.template b/services/1-cool-service/ioc/cool-service.template deleted file mode 100644 index 59bd9ae..0000000 --- a/services/1-cool-service/ioc/cool-service.template +++ /dev/null @@ -1,27 +0,0 @@ -# This is a template for preaparing an IOC providing BD Service specific PVs -# Access Security Groups: -# DEFAULT - logt wenn EGU oder so veraendert werden -# LOG - logt wenn neuer wert geschrieben wird -# PROTECTED - verhindert versuchte caputs auf alle fields ausser VAL -# READONLY - verhindert versuchte caputs und aktiviert caputlog -# Input links can specify CA, CP, or CPP. -# If the input link specifies CA, it will be forced to be a Channel Access link. -# If the input link specifies CP, it will also be forced to be a Channel Access link; in addition, it will cause the record containing the input link to process whenever a monitor is posted, no matter what the record's SCAN field specifies. -# If the input link specifies CPP, it means the same thing as CP, except that the record will be processed if and only if the record itself specifies passive in its SCAN field. Output links can specify CA, which will simply cause them to be Channel Access links. -# - -record(ao, "$(DEVICE):AO") { - field(DESC, "Analog Output Record (ao)") - field(ASG, "PROTECTED") - field(VAL, "0") - field(PINI, "YES") -} - -record(bo, "$(DEVICE):BO") { - field(DESC, "Binary Output Record (bo)") - field(ASG, "READONLY") - field(ZSV, "MINOR") - field(OSV, "NO_ALARM") - field(VAL, "1") - field(PINI, "YES") -} \ No newline at end of file diff --git a/services/1-cool-service/ioc/startup.script b/services/1-cool-service/ioc/startup.script deleted file mode 100644 index 019214a..0000000 --- a/services/1-cool-service/ioc/startup.script +++ /dev/null @@ -1 +0,0 @@ -epicsEnvSet("ENGINEER", "") diff --git a/services/1-cool-service/qt/cool-service.ui b/services/1-cool-service/qt/cool-service.ui deleted file mode 100644 index 4640904..0000000 --- a/services/1-cool-service/qt/cool-service.ui +++ /dev/null @@ -1 +0,0 @@ -# TODO diff --git a/services/1-cool-service/systemd/AGEBD-SERVICE-cool-service.service b/services/1-cool-service/systemd/AGEBD-SERVICE-cool-service.service deleted file mode 100644 index 9c2ffe9..0000000 --- a/services/1-cool-service/systemd/AGEBD-SERVICE-cool-service.service +++ /dev/null @@ -1,16 +0,0 @@ -[Unit] -Description=AGEBD-SERVICE-cool-service -After=network.target - -[Service] -Environment=AGEBD_ENV={{ agebd_env }} -ExecStart=/sls/bd/hla/bin/start_service.sh 1 cool-service -estart=no - -[Install] -WantedBy=default.target - -# https://www.freedesktop.org/software/systemd/man/latest/systemd.service.html -# systemctl --user daemon-reload -# systemctl --user enable /sls/bd/bin/systemd/AGEBD-SERVICE-cool-service.service -# systemctl --user start AGEBD-SERVICE-cool-service diff --git a/templates/service/{{service_id}}-{{service_name}}/app/pyproject.toml.jinja b/templates/service/{{service_id}}-{{service_name_lower}}/app/pyproject.toml.jinja similarity index 92% rename from templates/service/{{service_id}}-{{service_name}}/app/pyproject.toml.jinja rename to templates/service/{{service_id}}-{{service_name_lower}}/app/pyproject.toml.jinja index f675ccb..ac0b81e 100644 --- a/templates/service/{{service_id}}-{{service_name}}/app/pyproject.toml.jinja +++ b/templates/service/{{service_id}}-{{service_name_lower}}/app/pyproject.toml.jinja @@ -1,7 +1,7 @@ [project] name = "agebd-{{ service_name_lower }}" version = "0.1.0" -description = "AGEBD-{{ service_name }} Service" +description = "AGEBD-{{ service_name_upper }} Service" requires-python = ">=3.9" dependencies = [ "agebd==1.2.0", diff --git a/services/1-cool-service/app/src/AGEBD-SERVICE-cool-service.py b/templates/service/{{service_id}}-{{service_name_lower}}/app/src/AGEBD-SERVICE-{{service_name_upper}}.py.jinja similarity index 95% rename from services/1-cool-service/app/src/AGEBD-SERVICE-cool-service.py rename to templates/service/{{service_id}}-{{service_name_lower}}/app/src/AGEBD-SERVICE-{{service_name_upper}}.py.jinja index bc929f8..c48989f 100644 --- a/services/1-cool-service/app/src/AGEBD-SERVICE-cool-service.py +++ b/templates/service/{{service_id}}-{{service_name_lower}}/app/src/AGEBD-SERVICE-{{service_name_upper}}.py.jinja @@ -1,8 +1,6 @@ from time import sleep import typer -from epics import dbr - from agebd.enums import LogLevel from agebd.pv import LocalPVLink from agebd.pv import PVLink as PV @@ -10,6 +8,7 @@ from agebd.runner import CallbackRunner from agebd.service.base import BaseService from agebd.service.pvs import BasePVs from agebd.utils import get_pv_class, init_logging, printgetversion +from epics import dbr __version__ = printgetversion(__file__) @@ -47,7 +46,11 @@ class PVs(BasePVs): class Service(BaseService[PVs]): def __init__( - self, name: str, pvs: PVs, version: str = __version__, sleep_interval: float = 0.1 + self, + name: str, + pvs: PVs, + version: str = __version__, + sleep_interval: float = 0.1, ): super().__init__(name, pvs, version, sleep_interval) @@ -97,7 +100,7 @@ def main( ), ): init_logging(log_level) - service_name = "cool-service" + service_name = "{{ service_name_upper }}" pvs = PVs(service_name=service_name, pv_factory=PV) service = Service(name=service_name, pvs=pvs) runner = CallbackRunner(service=service) diff --git a/services/004-cool-service/app/src/__init__.py b/templates/service/{{service_id}}-{{service_name_lower}}/app/src/__init__.py similarity index 100% rename from services/004-cool-service/app/src/__init__.py rename to templates/service/{{service_id}}-{{service_name_lower}}/app/src/__init__.py diff --git a/templates/service/{{service_id}}-{{service_name_lower}}/ioc/AGEBD-CPCL-{{service_name_upper}}_main.subs.jinja b/templates/service/{{service_id}}-{{service_name_lower}}/ioc/AGEBD-CPCL-{{service_name_upper}}_main.subs.jinja new file mode 100644 index 0000000..95c2b1d --- /dev/null +++ b/templates/service/{{service_id}}-{{service_name_lower}}/ioc/AGEBD-CPCL-{{service_name_upper}}_main.subs.jinja @@ -0,0 +1,4 @@ +file {{ service_name_upper }}.template { + pattern { DEVICE } + { AGEBD-{{ service_name_upper }} } +} diff --git a/templates/service/{{service_id}}-{{service_name}}/ioc/AGEBD-CPCL-{{service_name}}_parameters.yaml.jinja b/templates/service/{{service_id}}-{{service_name_lower}}/ioc/AGEBD-CPCL-{{service_name_upper}}_parameters.yaml.jinja similarity index 100% rename from templates/service/{{service_id}}-{{service_name}}/ioc/AGEBD-CPCL-{{service_name}}_parameters.yaml.jinja rename to templates/service/{{service_id}}-{{service_name_lower}}/ioc/AGEBD-CPCL-{{service_name_upper}}_parameters.yaml.jinja diff --git a/templates/service/{{service_id}}-{{service_name}}/ioc/startup.script.jinja b/templates/service/{{service_id}}-{{service_name_lower}}/ioc/startup.script.jinja similarity index 100% rename from templates/service/{{service_id}}-{{service_name}}/ioc/startup.script.jinja rename to templates/service/{{service_id}}-{{service_name_lower}}/ioc/startup.script.jinja diff --git a/services/004-cool-service/ioc/COOL-SERVICE.template b/templates/service/{{service_id}}-{{service_name_lower}}/ioc/{{service_name_upper}}.template similarity index 100% rename from services/004-cool-service/ioc/COOL-SERVICE.template rename to templates/service/{{service_id}}-{{service_name_lower}}/ioc/{{service_name_upper}}.template diff --git a/services/004-cool-service/qt/COOL-SERVICE.ui b/templates/service/{{service_id}}-{{service_name_lower}}/qt/{{service_name_upper}}.ui.jinja similarity index 100% rename from services/004-cool-service/qt/COOL-SERVICE.ui rename to templates/service/{{service_id}}-{{service_name_lower}}/qt/{{service_name_upper}}.ui.jinja diff --git a/templates/service/{{service_id}}-{{service_name}}/systemd/AGEBD-SERVICE-{{service_name}}.service.jinja b/templates/service/{{service_id}}-{{service_name_lower}}/systemd/AGEBD-SERVICE-{{service_name_upper}}.service.jinja similarity index 69% rename from templates/service/{{service_id}}-{{service_name}}/systemd/AGEBD-SERVICE-{{service_name}}.service.jinja rename to templates/service/{{service_id}}-{{service_name_lower}}/systemd/AGEBD-SERVICE-{{service_name_upper}}.service.jinja index 61a2cdc..d7f73fa 100644 --- a/templates/service/{{service_id}}-{{service_name}}/systemd/AGEBD-SERVICE-{{service_name}}.service.jinja +++ b/templates/service/{{service_id}}-{{service_name_lower}}/systemd/AGEBD-SERVICE-{{service_name_upper}}.service.jinja @@ -1,10 +1,10 @@ [Unit] -Description=AGEBD-SERVICE-{{service_name}} +Description=AGEBD-SERVICE-{{ service_name_upper }} After=network.target [Service] Environment=AGEBD_ENV={{ '{{ agebd_env }}' }} -ExecStart=/sls/bd/hla/bin/start_service.sh {{ service_id }} {{ service_name }} +ExecStart=/sls/bd/hla/bin/start_service.sh {{ service_id }} {{ service_name_upper }} estart=no [Install] @@ -12,5 +12,5 @@ WantedBy=default.target # https://www.freedesktop.org/software/systemd/man/latest/systemd.service.html # systemctl --user daemon-reload -# systemctl --user enable /sls/bd/bin/systemd/AGEBD-SERVICE-{{ service_name }}.service -# systemctl --user start AGEBD-SERVICE-{{ service_name }} +# systemctl --user enable /sls/bd/bin/systemd/AGEBD-SERVICE-{{ service_name_upper }}.service +# systemctl --user start AGEBD-SERVICE-{{ service_name_upper }} diff --git a/templates/service/{{service_id}}-{{service_name}}/app/src/AGEBD-SERVICE-{{service_name}}.py.jinja b/templates/service/{{service_id}}-{{service_name}}/app/src/AGEBD-SERVICE-{{service_name}}.py.jinja deleted file mode 100644 index 8cb5374..0000000 --- a/templates/service/{{service_id}}-{{service_name}}/app/src/AGEBD-SERVICE-{{service_name}}.py.jinja +++ /dev/null @@ -1,108 +0,0 @@ -from time import sleep - -import typer -from epics import dbr - -from agebd.enums import LogLevel -from agebd.pv import LocalPVLink -from agebd.pv import PVLink as PV -from agebd.runner import CallbackRunner -from agebd.service.base import BaseService -from agebd.service.pvs import BasePVs -from agebd.utils import get_pv_class, init_logging, printgetversion - -__version__ = printgetversion(__file__) - -PV = get_pv_class() - - -class PVs(BasePVs): - # Option 1: - ## Service specific PVs from dedicated IOC - my_pv1 = PV("MY_PV1") - - ## Service specific PVs from other IOCs - # ... - - def __init__(self, service_name: str, pv_factory): - super().__init__(service_name, pv_factory) - PV = pv_factory - - # TODO: can we do this cleaner? Maybe mechanism for - # settings initial values in dev mode (e.g. ini file) - if isinstance(self.onoff, LocalPVLink): - self.onoff.value = True - - # Option 2: - ## Service specific PVs from dedicated IOC - self.my_pv2 = PV("MY_PV2") - - ## Service specific PVs from other IOCs - # ... - - # TODO: class attribute names usually lowercase - # usually it is advisable to trigger the mainloop of a service on changes of certain PVs: - self.CallbackPV = PV("...", auto_monitor=dbr.DBE_VALUE) - - -class Service(BaseService[PVs]): - def __init__( - self, name: str, pvs: PVs, version: str = __version__, sleep_interval: float = 0.1 - ): - super().__init__(name, pvs, version, sleep_interval) - - # TODO: What is this for? - self.path = "sls/bd/bin" - - def update(self): - # when callback is fired, this code will be executed - if self.CallbackFired: - ####################################################################################### - ####################################################################################### - # here goes all the code that your service - # is supposed to be running when the callback is fired - sleep(1) - ####################################################################################### - ####################################################################################### - - # callback done - self.CallbackFired = 0 - - ####################################################################################### - ####################################################################################### - # here goes all the code that your service - # is supposed to be running in any case, e.g., - # update some pvs/vals - self.pvs.my_pv1.put("MY_PV1 value") - self.pvs.my_pv2.put("MY_PV2 value") - self.val1 = self.pvs.my_pv1.get() - self.val2 = self.pvs.my_pv2.get() - print(self.val1) - print(self.val2) - # maybe sleep to limit the update loop execution rate - sleep(1) - ####################################################################################### - ####################################################################################### - - -def main( - log_level: LogLevel = typer.Option( - LogLevel.INFO, - "--log-level", - "-l", - # Looks at the OS env variable first. If empty, falls back to "INFO" - envvar="SLS_SERVICE_LOG_LEVEL", - # help="Set log level: DEBUG, INFO, WARNING, ERROR, CRITICAL", - case_sensitive=False, - ), -): - init_logging(log_level) - service_name = "{{service_name}}" - pvs = PVs(service_name=service_name, pv_factory=PV) - service = Service(name=service_name, pvs=pvs) - runner = CallbackRunner(service=service) - runner.start() - - -if __name__ == "__main__": - typer.run(main) diff --git a/templates/service/{{service_id}}-{{service_name}}/app/src/__init__.py b/templates/service/{{service_id}}-{{service_name}}/app/src/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/templates/service/{{service_id}}-{{service_name}}/ioc/AGEBD-CPCL-{{service_name}}_main.subs.jinja b/templates/service/{{service_id}}-{{service_name}}/ioc/AGEBD-CPCL-{{service_name}}_main.subs.jinja deleted file mode 100644 index 6c098d9..0000000 --- a/templates/service/{{service_id}}-{{service_name}}/ioc/AGEBD-CPCL-{{service_name}}_main.subs.jinja +++ /dev/null @@ -1,4 +0,0 @@ -file {{ service_name }}.template { - pattern { DEVICE } - { AGEBD-{{ service_name }} } -} diff --git a/templates/service/{{service_id}}-{{service_name}}/ioc/{{service_name}}.template b/templates/service/{{service_id}}-{{service_name}}/ioc/{{service_name}}.template deleted file mode 100644 index 59bd9ae..0000000 --- a/templates/service/{{service_id}}-{{service_name}}/ioc/{{service_name}}.template +++ /dev/null @@ -1,27 +0,0 @@ -# This is a template for preaparing an IOC providing BD Service specific PVs -# Access Security Groups: -# DEFAULT - logt wenn EGU oder so veraendert werden -# LOG - logt wenn neuer wert geschrieben wird -# PROTECTED - verhindert versuchte caputs auf alle fields ausser VAL -# READONLY - verhindert versuchte caputs und aktiviert caputlog -# Input links can specify CA, CP, or CPP. -# If the input link specifies CA, it will be forced to be a Channel Access link. -# If the input link specifies CP, it will also be forced to be a Channel Access link; in addition, it will cause the record containing the input link to process whenever a monitor is posted, no matter what the record's SCAN field specifies. -# If the input link specifies CPP, it means the same thing as CP, except that the record will be processed if and only if the record itself specifies passive in its SCAN field. Output links can specify CA, which will simply cause them to be Channel Access links. -# - -record(ao, "$(DEVICE):AO") { - field(DESC, "Analog Output Record (ao)") - field(ASG, "PROTECTED") - field(VAL, "0") - field(PINI, "YES") -} - -record(bo, "$(DEVICE):BO") { - field(DESC, "Binary Output Record (bo)") - field(ASG, "READONLY") - field(ZSV, "MINOR") - field(OSV, "NO_ALARM") - field(VAL, "1") - field(PINI, "YES") -} \ No newline at end of file diff --git a/templates/service/{{service_id}}-{{service_name}}/qt/{{service_name}}.ui.jinja b/templates/service/{{service_id}}-{{service_name}}/qt/{{service_name}}.ui.jinja deleted file mode 100644 index 4640904..0000000 --- a/templates/service/{{service_id}}-{{service_name}}/qt/{{service_name}}.ui.jinja +++ /dev/null @@ -1 +0,0 @@ -# TODO