diff --git a/src/ibek/globals.py b/src/ibek/globals.py index 57cdc6608..2624cf27e 100644 --- a/src/ibek/globals.py +++ b/src/ibek/globals.py @@ -65,7 +65,7 @@ def NATIVE(self): @property def STATIC_BUILD(self): """True if the target architecture is not the default architecture.""" - return os.getenv("STATIC_BUILD", self._EPICS_TARGET_ARCH != self._DEFAULT_ARCH) + return os.getenv("STATIC_BUILD", self.EPICS_TARGET_ARCH != self._DEFAULT_ARCH) @property def IBEK_DEFS(self): diff --git a/src/ibek/ioc.py b/src/ibek/ioc.py index 791065867..29d1ab0e1 100644 --- a/src/ibek/ioc.py +++ b/src/ibek/ioc.py @@ -6,7 +6,7 @@ from __future__ import annotations from enum import Enum -from typing import Dict, List +from typing import Any, Dict, List, Sequence from pydantic import ( Field, @@ -72,6 +72,8 @@ def add_ibek_attributes(self): # Jinja expansion of any of the Entity's string args/values value = UTILS.render(entity_dict, value) setattr(self, arg, str(value)) + # update the entity_dict with the rendered value + entity_dict[arg] = value if model_field.annotation == object: # if the field is an object but the type is str then look up @@ -104,3 +106,7 @@ class IOC(BaseSettings): ioc_name: str = Field(description="Name of IOC instance") description: str = Field(description="Description of what the IOC does") entities: List[Entity] + shared: Sequence[Any] = Field( + description="A place to create any anchors required for repeating YAML", + default=(), + ) diff --git a/src/ibek/utils.py b/src/ibek/utils.py index b65054b5d..8361287cd 100644 --- a/src/ibek/utils.py +++ b/src/ibek/utils.py @@ -75,8 +75,7 @@ def set_var(self, key: str, value: Any): def get_var(self, key: str) -> Any: """get the value a global variable for our jinja context""" - # Intentionally raises a KeyError if the key doesn't exist - return self.variables[key] + return self.variables.get(key, "") def counter( self, name: str, start: int = 0, stop: int = 65535, inc: int = 1 @@ -110,13 +109,17 @@ def render(self, context: Any, template_text: Any) -> str: # be passed a non string which will always render to itself return template_text - jinja_template = Template(template_text) - return jinja_template.render( - context, - __utils__=self, - ioc_yaml_file_name=self.file_name, - ioc_name=self.ioc_name, - ) + try: + jinja_template = Template(template_text) + return jinja_template.render( + context, + __utils__=self, + ioc_yaml_file_name=self.file_name, + ioc_name=self.ioc_name, + ) + except Exception: + print(f"ERROR RENDERING TEMPLATE:\n{template_text}") + raise def render_map(self, context: Any, map: Mapping[str, str | None]) -> dict[str, str]: """ diff --git a/tests/generate_samples.sh b/tests/generate_samples.sh index d714bd79f..726879c57 100755 --- a/tests/generate_samples.sh +++ b/tests/generate_samples.sh @@ -59,4 +59,16 @@ mv `pwd`/epics/{runtime,opi}/* `pwd`/outputs/gauges echo making ioc based on quadem support yaml EPICS_ROOT=`pwd`/epics ibek runtime generate iocs/quadem.ibek.ioc.yaml support/ADCore.ibek.support.yaml support/quadem.ibek.support.yaml -mv `pwd`/epics/{runtime,opi}/* `pwd`/outputs/quadem \ No newline at end of file +mv `pwd`/epics/{runtime,opi}/* `pwd`/outputs/quadem + + +############################################################################ + +# technosoft motor example + +echo making an ioc schema using technosoft support yaml +ibek ioc generate-schema --no-ibek-defs support/technosoft.ibek.support.yaml --output schemas/technosoft.ibek.ioc.schema.json + +echo making techosoft ioc +EPICS_ROOT=`pwd`/epics ibek runtime generate iocs/technosoft.ibek.ioc.yaml support/technosoft.ibek.support.yaml +mv `pwd`/epics/{runtime,opi}/* `pwd`/outputs/technosoft diff --git a/tests/samples/iocs/technosoft.ibek.ioc.yaml b/tests/samples/iocs/technosoft.ibek.ioc.yaml new file mode 100644 index 000000000..651547f12 --- /dev/null +++ b/tests/samples/iocs/technosoft.ibek.ioc.yaml @@ -0,0 +1,44 @@ +# yaml-language-server: $schema=../schemas/technosoft.ibek.ioc.schema.json + +ioc_name: yag +description: YAG motors + +shared: + - &motor + type: motorTML.motorAxis + controller: TML + NSTEPS: 200 + NMICROSTEPS: 256 + VELO: 20 + VELO_MAX: 50 + VELO_MIN: 0.1 + ACCL: 0.5 + ACCL_MAX: 1.5 + ACCL_MIN: 0.01 + HAR: 0.5 + HVEL: 10 + JAR: 1 + JVEL: 5 + EGU: "ustep" + SLSP: 0.8 + ENABLED: 1 + TIMEOUT: 0 + +entities: + - type: motorTML.CreateController + controllerName: TML + P: "SPARC:TML" + TTY: /tmp # /var/tmp/ttyV0 + numAxes: 1 + hostid: 15 + + - <<: *motor + axid: 15 + + - <<: *motor + axid: 17 + # example of overriding a value from the shared dictionary merge + ACCL_MIN: 0.011 + # (UNREALISTIC) example of using Jinja expression in an arg value + EGU: |- + {{controller.P}} diff --git a/tests/samples/outputs/technosoft/index.bob b/tests/samples/outputs/technosoft/index.bob new file mode 100644 index 000000000..3821141df --- /dev/null +++ b/tests/samples/outputs/technosoft/index.bob @@ -0,0 +1,28 @@ + + yag + 0 + 0 + 10 + 35 + 4 + 4 + + Title + TITLE + yag + 0 + 0 + 10 + 25 + + + + + + + + + true + 1 + + diff --git a/tests/samples/outputs/technosoft/ioc.subst b/tests/samples/outputs/technosoft/ioc.subst new file mode 100644 index 000000000..535e1a86b --- /dev/null +++ b/tests/samples/outputs/technosoft/ioc.subst @@ -0,0 +1,3 @@ +############################################################################# +# DB substitution file generated by http://github.com/epics-containers/ibek # +############################################################################# diff --git a/tests/samples/outputs/technosoft/reference.cmd b/tests/samples/outputs/technosoft/reference.cmd new file mode 100644 index 000000000..33b4dc5f8 --- /dev/null +++ b/tests/samples/outputs/technosoft/reference.cmd @@ -0,0 +1,6 @@ +ndsCreateDevice "TechnosoftTML", "", "FILE=/tmp/,NAXIS=4,DEV_PATH=/dev/ttyS0,HOST_ID=1, + AXIS_SETUP_0=$(SUPPORT)/motorTechnosoft/tml_lib/config/config.txt,AXIS_ID_0=1,AXIS_HOMING_SW_0=LSN, + AXIS_SETUP_1=$(SUPPORT)/motorTechnosoft/tml_lib/config/config.txt,AXIS_ID_1=2,AXIS_HOMING_SW_1=LSN, + AXIS_SETUP_2=$(SUPPORT)/motorTechnosoft/tml_lib/config/config.txt,AXIS_ID_2=3,AXIS_HOMING_SW_2=LSN, + AXIS_SETUP_3=$(SUPPORT)/motorTechnosoft/tml_lib/config/config.txt,AXIS_ID_3=4,AXIS_HOMING_SW_3=LSN" + diff --git a/tests/samples/outputs/technosoft/st.cmd b/tests/samples/outputs/technosoft/st.cmd new file mode 100644 index 000000000..9802225f6 --- /dev/null +++ b/tests/samples/outputs/technosoft/st.cmd @@ -0,0 +1,21 @@ +# EPICS IOC Startup Script generated by https://github.com/epics-containers/ibek + +cd "/epics/ioc" +dbLoadDatabase dbd/ioc.dbd +ioc_registerRecordDeviceDriver pdbbase + +ndsCreateDevice "TechnosoftTML", "TML", "FILE=/tmp/,NAXIS=1,DEV_PATH=/tmp,HOST_ID=15,AXIS_SETUP_0=$(SUPPORT)/motorTechnosoft/tml_lib/config/star_vat_phs.t.zip,AXIS_ID_0=15,AXIS_HOMING_SW_0=LSN,AXIS_SETUP_1=$(SUPPORT)/motorTechnosoft/tml_lib/config/star_vat_phs.t.zip,AXIS_ID_1=17,AXIS_HOMING_SW_1=LSN" +dbLoadRecords("$(SUPPORT)/motorTechnosoft/db/tmlAxis.template","PREFIX=SPARC:TML, CHANNEL_ID=MOT, CHANNEL_PREFIX=ax, ASYN_PORT=, ASYN_ADDR=0, NSTEPS=200, NMICROSTEPS=256, VELO=20, VELO_MIN=0.1, VELO_MAX=50.0, ACCL=0.5, ACCL_MIN=0.01, ACCL_MAX=1.5, HAR=0.5, HVEL=10.0, JAR=1, JVEL=5, ENABLED=1, SLSP=0.8, EGU=ustep, TIMEOUT=0") +dbLoadRecords("$(SUPPORT)/motorTechnosoft/db/tmlAxis.template","PREFIX=SPARC:TML, CHANNEL_ID=MOT, CHANNEL_PREFIX=ax, ASYN_PORT=, ASYN_ADDR=0, NSTEPS=200, NMICROSTEPS=256, VELO=20, VELO_MIN=0.1, VELO_MAX=50.0, ACCL=0.5, ACCL_MIN=0.011, ACCL_MAX=1.5, HAR=0.5, HVEL=10.0, JAR=1, JVEL=5, ENABLED=1, SLSP=0.8, EGU=SPARC:TML, TIMEOUT=0") + +dbLoadRecords /epics/runtime/ioc.db +iocInit + + + +dbpf("SPARC:TML:MOT:MSGRS","START") +dbl + +dbpf("SPARC:TML:MOT:MSGRS","START") +dbl + diff --git a/tests/samples/schemas/gauges.ibek.ioc.schema.json b/tests/samples/schemas/gauges.ibek.ioc.schema.json index 49ef3a760..113f716b9 100644 --- a/tests/samples/schemas/gauges.ibek.ioc.schema.json +++ b/tests/samples/schemas/gauges.ibek.ioc.schema.json @@ -280,6 +280,13 @@ }, "title": "Entities", "type": "array" + }, + "shared": { + "default": [], + "description": "A place to create any anchors required for repeating YAML", + "items": {}, + "title": "Shared", + "type": "array" } }, "required": [ diff --git a/tests/samples/schemas/motorSim.ibek.ioc.schema.json b/tests/samples/schemas/motorSim.ibek.ioc.schema.json index 7474372f4..832dfe9a6 100644 --- a/tests/samples/schemas/motorSim.ibek.ioc.schema.json +++ b/tests/samples/schemas/motorSim.ibek.ioc.schema.json @@ -354,6 +354,13 @@ }, "title": "Entities", "type": "array" + }, + "shared": { + "default": [], + "description": "A place to create any anchors required for repeating YAML", + "items": {}, + "title": "Shared", + "type": "array" } }, "required": [ diff --git a/tests/samples/schemas/quadem.ibek.ioc.schema.json b/tests/samples/schemas/quadem.ibek.ioc.schema.json index 14af181cd..7d93f5a09 100644 --- a/tests/samples/schemas/quadem.ibek.ioc.schema.json +++ b/tests/samples/schemas/quadem.ibek.ioc.schema.json @@ -3169,6 +3169,13 @@ }, "title": "Entities", "type": "array" + }, + "shared": { + "default": [], + "description": "A place to create any anchors required for repeating YAML", + "items": {}, + "title": "Shared", + "type": "array" } }, "required": [ diff --git a/tests/samples/schemas/single.ibek.ioc.schema.json b/tests/samples/schemas/single.ibek.ioc.schema.json index ae5487e34..6dca67d83 100644 --- a/tests/samples/schemas/single.ibek.ioc.schema.json +++ b/tests/samples/schemas/single.ibek.ioc.schema.json @@ -193,6 +193,13 @@ }, "title": "Entities", "type": "array" + }, + "shared": { + "default": [], + "description": "A place to create any anchors required for repeating YAML", + "items": {}, + "title": "Shared", + "type": "array" } }, "required": [ diff --git a/tests/samples/schemas/technosoft.ibek.ioc.schema.json b/tests/samples/schemas/technosoft.ibek.ioc.schema.json new file mode 100644 index 000000000..22d658ddc --- /dev/null +++ b/tests/samples/schemas/technosoft.ibek.ioc.schema.json @@ -0,0 +1,297 @@ +{ + "$defs": { + "homing": { + "enum": [ + "LSN", + "LSP" + ], + "title": "homing", + "type": "string" + }, + "motorTML_CreateController": { + "additionalProperties": false, + "properties": { + "type": { + "const": "motorTML.CreateController", + "default": "motorTML.CreateController", + "description": "Creates a Technosoft motion controller connected to a serial line", + "title": "Type" + }, + "entity_enabled": { + "default": true, + "description": "enable or disable this entity instance", + "title": "Entity Enabled", + "type": "boolean" + }, + "controllerName": { + "description": "The name of the controller", + "title": "Controllername", + "type": "string" + }, + "P": { + "description": "Device PV Prefix", + "title": "P", + "type": "string" + }, + "TTY": { + "description": "TTY", + "title": "Tty", + "type": "string" + }, + "numAxes": { + "default": 1, + "description": "The number of axes to create", + "title": "Numaxes", + "type": "integer" + }, + "hostid": { + "description": "Host ID", + "title": "Hostid", + "type": "integer" + }, + "CONFIG": { + "default": "FILE=/tmp/,NAXIS={{numAxes}},DEV_PATH={{TTY}},HOST_ID={{hostid}}", + "description": "TML Configuration", + "title": "Config", + "type": "string" + }, + "axisConfiguration": { + "default": "{{ __utils__.set_var('motorTML.axisConfiguration',[]) }}", + "description": "collects the axis configuration from axis entities", + "title": "Axisconfiguration", + "type": "string" + } + }, + "required": [ + "controllerName", + "P", + "TTY", + "hostid" + ], + "title": "motorTML_CreateController", + "type": "object" + }, + "motorTML_motorAxis": { + "additionalProperties": false, + "properties": { + "type": { + "const": "motorTML.motorAxis", + "default": "motorTML.motorAxis", + "description": "Creates a motor axis", + "title": "Type" + }, + "entity_enabled": { + "default": true, + "description": "enable or disable this entity instance", + "title": "Entity Enabled", + "type": "boolean" + }, + "controller": { + "description": "a reference to the motion controller", + "title": "Controller" + }, + "CHANNEL_PREFIX": { + "default": "ax0", + "description": "The axis prefix", + "title": "Channel Prefix", + "type": "string" + }, + "CHANNEL_ID": { + "default": "MOT", + "description": "The axis ID", + "title": "Channel Id", + "type": "string" + }, + "axid": { + "description": "The axis ID", + "title": "Axid", + "type": "integer" + }, + "axconf": { + "default": "star_vat_phs.t.zip", + "description": "The axis configuration", + "title": "Axconf", + "type": "string" + }, + "homing": { + "allOf": [ + { + "$ref": "#/$defs/homing" + } + ], + "default": "LSN", + "description": "Homing direction" + }, + "NSTEPS": { + "default": 200, + "description": "Number of steps", + "title": "Nsteps", + "type": "integer" + }, + "NMICROSTEPS": { + "default": 256, + "description": "Number of microsteps", + "title": "Nmicrosteps", + "type": "integer" + }, + "VELO": { + "default": 20, + "description": "Velocity", + "title": "Velo", + "type": "integer" + }, + "VELO_MIN": { + "default": 0.1, + "description": "Velocity min", + "title": "Velo Min", + "type": "number" + }, + "VELO_MAX": { + "default": 50.0, + "description": "Velocity Max", + "title": "Velo Max", + "type": "number" + }, + "ACCL": { + "default": 0.5, + "description": "Seconds to Velocity", + "title": "Accl", + "type": "number" + }, + "ACCL_MIN": { + "default": 0.01, + "description": "Seconds to Velocity", + "title": "Accl Min", + "type": "number" + }, + "ACCL_MAX": { + "default": 1.5, + "description": "Seconds to Velocity", + "title": "Accl Max", + "type": "number" + }, + "HAR": { + "default": 0.5, + "description": "Homing acceleration", + "title": "Har", + "type": "number" + }, + "HVEL": { + "default": 10.0, + "description": "Homing Velocity", + "title": "Hvel", + "type": "number" + }, + "JAR": { + "default": 1, + "description": "JAR", + "title": "Jar", + "type": "integer" + }, + "JVEL": { + "default": 5, + "description": "JVEL", + "title": "Jvel", + "type": "integer" + }, + "EGU": { + "default": "ustep", + "description": "Engineering Units", + "title": "Egu", + "type": "string" + }, + "SLSP": { + "default": 0.8, + "description": "Limit", + "title": "Slsp", + "type": "number" + }, + "ENABLED": { + "default": 1, + "description": "Enabled", + "title": "Enabled", + "type": "integer" + }, + "TIMEOUT": { + "default": 0, + "description": "Timeout", + "title": "Timeout", + "type": "integer" + }, + "ASYN_ADDR": { + "default": "0", + "description": "Asyn Addr?", + "title": "Asyn Addr", + "type": "string" + }, + "CONFIG": { + "default": "{%- set num = __utils__.counter(\"motorTML.axisCount\", start=0) -%}\n,AXIS_SETUP_{{num}}=$(SUPPORT)/motorTechnosoft/tml_lib/config/{{axconf}},AXIS_ID_{{num}}={{axid}},AXIS_HOMING_SW_{{num}}={{homing}}", + "description": "Axis configuration string to add to the controller configuration", + "title": "Config", + "type": "string" + }, + "axisConfiguration": { + "default": "{{ __utils__.get_var('motorTML.axisConfiguration').append(CONFIG) }}", + "description": "Adds an axis configuration entry to the controller's list", + "title": "Axisconfiguration", + "type": "string" + } + }, + "required": [ + "controller", + "axid" + ], + "title": "motorTML_motorAxis", + "type": "object" + } + }, + "additionalProperties": false, + "properties": { + "ioc_name": { + "description": "Name of IOC instance", + "title": "Ioc Name", + "type": "string" + }, + "description": { + "description": "Description of what the IOC does", + "title": "Description", + "type": "string" + }, + "entities": { + "description": "List of entities this IOC instantiates", + "items": { + "discriminator": { + "mapping": { + "motorTML.CreateController": "#/$defs/motorTML_CreateController", + "motorTML.motorAxis": "#/$defs/motorTML_motorAxis" + }, + "propertyName": "type" + }, + "oneOf": [ + { + "$ref": "#/$defs/motorTML_CreateController" + }, + { + "$ref": "#/$defs/motorTML_motorAxis" + } + ] + }, + "title": "Entities", + "type": "array" + }, + "shared": { + "default": [], + "description": "A place to create any anchors required for repeating YAML", + "items": {}, + "title": "Shared", + "type": "array" + } + }, + "required": [ + "ioc_name", + "description", + "entities" + ], + "title": "NewIOC", + "type": "object" +} \ No newline at end of file diff --git a/tests/samples/schemas/utils.ibek.ioc.schema.json b/tests/samples/schemas/utils.ibek.ioc.schema.json index 62ac6060f..fd064d180 100644 --- a/tests/samples/schemas/utils.ibek.ioc.schema.json +++ b/tests/samples/schemas/utils.ibek.ioc.schema.json @@ -100,6 +100,13 @@ }, "title": "Entities", "type": "array" + }, + "shared": { + "default": [], + "description": "A place to create any anchors required for repeating YAML", + "items": {}, + "title": "Shared", + "type": "array" } }, "required": [ diff --git a/tests/samples/support/technosoft.ibek.support.yaml b/tests/samples/support/technosoft.ibek.support.yaml new file mode 100644 index 000000000..32534b3f8 --- /dev/null +++ b/tests/samples/support/technosoft.ibek.support.yaml @@ -0,0 +1,247 @@ +# yaml-language-server: $schema=../schemas/ibek.support.schema.json + +module: motorTML + +defs: + - name: CreateController + description: |- + Creates a Technosoft motion controller connected to a serial line + + args: + - type: id + name: controllerName + description: |- + The name of the controller + - type: str + name: P + description: |- + Device PV Prefix + + - type: str + name: TTY + description: |- + TTY + + - type: int + name: numAxes + description: |- + The number of axes to create + default: 1 + + - type: int + name: hostid + description: |- + Host ID + + - type: str + name: CONFIG + description: |- + TML Configuration + default: |- + FILE=/tmp/,NAXIS={{numAxes}},DEV_PATH={{TTY}},HOST_ID={{hostid}} + values: + - name: axisConfiguration + description: collects the axis configuration from axis entities + value: |- + {{ __utils__.set_var('motorTML.axisConfiguration',[]) }} + pre_init: + - value: | + ndsCreateDevice "TechnosoftTML", "{{controllerName}}", "{{CONFIG}}{{"".join(__utils__.get_var('motorTML.axisConfiguration')) }}" + + - name: motorAxis + description: |- + Creates a motor axis + + args: + - type: object + name: controller + description: |- + a reference to the motion controller + + - type: str + name: CHANNEL_PREFIX + description: |- + The axis prefix + default: ax0 + + - type: str + name: CHANNEL_ID + description: |- + The axis ID + default: MOT + + - type: int + name: axid + description: |- + The axis ID + + - type: str + name: axconf + description: |- + The axis configuration + default: star_vat_phs.t.zip + + - type: enum + name: homing + description: |- + Homing direction + default: LSN + values: + LSN: + LSP: + + - type: int + name: NSTEPS + description: |- + Number of steps + default: 200 + + - type: int + name: NMICROSTEPS + description: |- + Number of microsteps + default: 256 + + - type: int + name: VELO + description: |- + Velocity + default: 20 + + - type: float + name: VELO_MIN + description: |- + Velocity min + default: 0.1 + + - type: float + name: VELO_MAX + description: |- + Velocity Max + default: 50 + + - type: float + name: ACCL + description: |- + Seconds to Velocity + default: 0.5 + + - type: float + name: ACCL_MIN + description: |- + Seconds to Velocity + default: 0.01 + + - type: float + name: ACCL_MAX + description: |- + Seconds to Velocity + default: 1.5 + + - type: float + name: HAR + description: |- + Homing acceleration + default: 0.5 + + - type: float + name: HVEL + description: |- + Homing Velocity + default: 10 + + - type: int + name: JAR + description: |- + JAR + default: 1 + + - type: int + name: JVEL + description: |- + JVEL + default: 5 + + - type: str + name: EGU + description: |- + Engineering Units + default: "ustep" + + - type: float + name: SLSP + description: |- + Limit + default: 0.8 + + - type: int + name: ENABLED + description: |- + Enabled + default: 1 + + - type: int + name: TIMEOUT + description: |- + Timeout + default: 0 + + - type: str + name: ASYN_ADDR + description: |- + Asyn Addr? + default: "0" + + - type: str + name: CONFIG + description: |- + Axis configuration string to add to the controller configuration + default: |- + {%- set num = __utils__.counter("motorTML.axisCount", start=0) -%} + ,AXIS_SETUP_{{num}}=$(SUPPORT)/motorTechnosoft/tml_lib/config/{{axconf}},AXIS_ID_{{num}}={{axid}},AXIS_HOMING_SW_{{num}}={{homing}} + values: + - name: axisConfiguration + description: Adds an axis configuration entry to the controller's list + value: |- + {{ __utils__.get_var('motorTML.axisConfiguration').append(CONFIG) }} + + pre_init: + - value: | + dbLoadRecords("$(SUPPORT)/motorTechnosoft/db/tmlAxis.template","PREFIX={{controller.P}}, CHANNEL_ID={{CHANNEL_ID}}, CHANNEL_PREFIX=ax{{num}}, ASYN_PORT={{controllerName}}, ASYN_ADDR={{ASYN_ADDR}}, NSTEPS={{NSTEPS}}, NMICROSTEPS={{NMICROSTEPS}}, VELO={{VELO}}, VELO_MIN={{VELO_MIN}}, VELO_MAX={{VELO_MAX}}, ACCL={{ACCL}}, ACCL_MIN={{ACCL_MIN}}, ACCL_MAX={{ACCL_MAX}}, HAR={{HAR}}, HVEL={{HVEL}}, JAR={{JAR}}, JVEL={{JVEL}}, ENABLED={{ENABLED}}, SLSP={{SLSP}}, EGU={{EGU}}, TIMEOUT={{TIMEOUT}}") + + # databases: + # # TODO as this is a simulation I have hard coded some of the DB fields, + # # but these could easily be made into arguments above + # # + # # Note: supplying no value means that the argument of the same name is used + # # (the most common case - if you contrive to make args and db fields the same. + # # Which is good idea for ease of transition from traditional IOCs) + + # - file: tmlAxis.template + # args: + # PREFIX: "{{controller.P}}" + # ASYN_PORT: "{{controller.controllerName}}" + # CHANNEL_ID: + # CHANNEL_PREFIX: + # ASYN_ADDR: + # NSTEPS: + # NMICROSTEPS: + # VELO: + # VELO_MIN: + # VELO_MAX: + # ACCL: + # ACCL_MIN: + # ACCL_MAX: + # HAR: + # HVEL: + # JAR: + # JVEL: + # ENABLED: + # SLSP: + # EGU: + # TIMEOUT: + post_init: + - value: | + + dbpf("{{controller.P}}:{{CHANNEL_ID}}:MSGRS","START") + dbl diff --git a/tests/test_cli.py b/tests/test_cli.py index 4a723978b..af84e12de 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -203,3 +203,35 @@ def test_quadem(tmp_epics_root: Path, samples: Path): example_db = (samples / "outputs" / "quadem" / "ioc.subst").read_text() actual_db = (tmp_epics_root / "runtime" / "ioc.subst").read_text() assert example_db == actual_db + + +def generic_generate( + epics_root: Path, samples: Path, ioc_name: str, support_names: list[str] +): + ioc_yaml = samples / "iocs" / f"{ioc_name}.ibek.ioc.yaml" + support_yamls = [ + samples / "support" / f"{name}.ibek.support.yaml" for name in support_names + ] + expected_outputs = samples / "outputs" / ioc_name + + generate(ioc_yaml, support_yamls) + + example_boot = (expected_outputs / "st.cmd").read_text() + actual_boot = (epics_root / "runtime" / "st.cmd").read_text() + assert example_boot == actual_boot + + example_db = (expected_outputs / "ioc.subst").read_text() + actual_db = (epics_root / "runtime" / "ioc.subst").read_text() + assert example_db == actual_db + + +def test_andreas_motors(tmp_epics_root: Path, samples: Path): + """ + Motor and axis example + """ + generic_generate( + tmp_epics_root, + samples, + "technosoft", + ["asyn", "technosoft"], + ) diff --git a/tests/test_support.py b/tests/test_support.py index 6a7b258b8..22b13de3a 100644 --- a/tests/test_support.py +++ b/tests/test_support.py @@ -20,6 +20,7 @@ def test_symlink_ibek(tmp_path: Path, samples: Path): "ipac.ibek.support.yaml", "motorSim.ibek.support.yaml", "quadem.ibek.support.yaml", + "technosoft.ibek.support.yaml", "utils.ibek.support.yaml", ]