Skip to content
22 changes: 22 additions & 0 deletions BlockServer/config/block.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
# along with this program; if not, you can obtain a copy from
# https://www.eclipse.org/org/documents/epl-v10.php or
# http://opensource.org/licenses/eclipse-1.0.php

from typing import Dict, TypedDict, Union

from server_common.helpers import PVPREFIX_MACRO
Expand All @@ -33,6 +34,11 @@ class Block:
log_periodic (bool): Whether the block is sampled periodically in the archiver
log_rate (float): Time between archive samples (in seconds)
log_deadband (float): Deadband for the block to be archived
alarmenabled (bool): Whether the alarm should be enabled
alarmlatched (bool): Whether the alarm should be latched
alarmdelay (float): The delay for trigerring alarm
alarmguidance (string): The guidance for the alarm

"""

def __init__(
Expand All @@ -51,6 +57,10 @@ def __init__(
log_deadband: float = 0,
set_block: bool = False,
set_block_val: str | None = None,
alarmenabled: bool = False,
alarmlatched: bool = False,
alarmdelay: float | None = None,
alarmguidance: str | None = None,
) -> None:
"""Constructor.

Expand All @@ -69,6 +79,10 @@ def __init__(
log_deadband: Deadband for the block to be archived
set_block: whether the block should be set upon config change
set_block_val: what the block should be set to upon config change
alarmenabled (bool): Whether the alarm should be enabled
alarmlatched (bool): Whether the alarm should be latched
alarmdelay (float): The delay for trigerring alarm
alarmguidance (string): The guidance for the alarm
"""
self.name = name
self.pv = pv
Expand All @@ -84,6 +98,10 @@ def __init__(
self.log_deadband = log_deadband
self.set_block = set_block
self.set_block_val = set_block_val
self.alarmenabled = alarmenabled
self.alarmlatched = alarmlatched
self.alarmdelay = alarmdelay
self.alarmguidance = alarmguidance

def _get_pv(self) -> str:
pv_name = self.pv
Expand Down Expand Up @@ -132,6 +150,10 @@ def to_dict(self) -> Dict[str, Union[str, float, bool, None]]:
"suspend_on_invalid": self.rc_suspend_on_invalid,
"set_block": self.set_block,
"set_block_val": self.set_block_val,
"alarmenabled": self.alarmenabled,
"alarmlatched": self.alarmlatched,
"alarmdelay": self.alarmdelay,
"alarmguidance": self.alarmguidance,
}


Expand Down
64 changes: 62 additions & 2 deletions BlockServer/config/xml_converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
# along with this program; if not, you can obtain a copy from
# https://www.eclipse.org/org/documents/epl-v10.php or
# http://opensource.org/licenses/eclipse-1.0.php

from typing import Dict, List, OrderedDict
from xml.dom import minidom
from xml.etree import ElementTree
Expand All @@ -27,6 +28,10 @@
from BlockServer.core.constants import (
GRP_NONE,
SIMLEVELS,
TAG_ALARM_DELAY,
TAG_ALARM_ENABLED,
TAG_ALARM_GUIDANCE,
TAG_ALARM_LATCHED,
TAG_AUTOSTART,
TAG_BLOCK,
TAG_BLOCKS,
Expand Down Expand Up @@ -276,6 +281,17 @@ def _block_to_xml(root_xml: ElementTree.Element, block: Block, macros: Dict) ->
set_block_val = ElementTree.SubElement(block_xml, TAG_SET_BLOCK_VAL)
set_block_val.text = str(block.set_block_val)

# Alarm Config
alarmenabled = ElementTree.SubElement(block_xml, TAG_ALARM_ENABLED)
alarmenabled.text = str(block.alarmenabled)
alarmlatched = ElementTree.SubElement(block_xml, TAG_ALARM_LATCHED)
alarmlatched.text = str(block.alarmlatched)
if block.alarmdelay is not None:
alarmdelay = ElementTree.SubElement(block_xml, TAG_ALARM_DELAY)
alarmdelay.text = str(block.alarmdelay)
alarmguidance = ElementTree.SubElement(block_xml, TAG_ALARM_GUIDANCE)
alarmguidance.text = block.alarmguidance

@staticmethod
def _group_to_xml(root_xml: ElementTree.Element, group: Group) -> None:
"""Generates the XML for a group"""
Expand Down Expand Up @@ -414,6 +430,28 @@ def blocks_from_xml(
if set_block_val is not None:
blocks[name.lower()].set_block_val = set_block_val.text

# Alarm Config
alarmenabled = ConfigurationXmlConverter._find_single_node(
b, NS_TAG_BLOCK, TAG_ALARM_ENABLED
)
if alarmenabled is not None:
blocks[name.lower()].alarmenabled = alarmenabled.text == "True"
alarmlatched = ConfigurationXmlConverter._find_single_node(
b, NS_TAG_BLOCK, TAG_ALARM_LATCHED
)
if alarmlatched is not None:
blocks[name.lower()].alarmlatched = alarmlatched.text == "True"
alarmdelay = ConfigurationXmlConverter._find_single_node(
b, NS_TAG_BLOCK, TAG_ALARM_DELAY
)
if alarmdelay is not None and alarmdelay.text is not None:
blocks[name.lower()].alarmdelay = float(alarmdelay.text)
alarmguidance = ConfigurationXmlConverter._find_single_node(
b, NS_TAG_BLOCK, TAG_ALARM_GUIDANCE
)
if alarmguidance is not None:
blocks[name.lower()].alarmguidance = alarmguidance.text

@staticmethod
def groups_from_xml(
root_xml: ElementTree.Element, groups: OrderedDict, blocks: OrderedDict
Expand Down Expand Up @@ -525,6 +563,17 @@ def components_from_xml(root_xml: ElementTree.Element, components: OrderedDict)
if n is not None and n != "":
components[n.lower()] = n

@staticmethod
def get_configures_block_gw_and_archiver_from_xml(root_xml: ElementTree.Element) -> bool:
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed
configureblock_gw_and_archiver = root_xml.find("./" + TAG_CONFIGURES_BLOCK_GW_AND_ARCHIVER)
if (
configureblock_gw_and_archiver is not None
and configureblock_gw_and_archiver.text is not None
):
return configureblock_gw_and_archiver.text.lower() == "true"
else:
return False

@staticmethod
def get_configures_block_g_w_and_archiver(root_xml: ElementTree.Element) -> bool:
configures_block_g_w_and_archiver = root_xml.find(
Expand Down Expand Up @@ -554,6 +603,10 @@ def meta_from_xml(root_xml: ElementTree.Element, data: MetaData) -> None:
if synoptic is not None:
data.synoptic = synoptic.text if synoptic.text is not None else ""

protected = root_xml.find("./" + TAG_PROTECTED)
if protected is not None:
if protected.text is not None:
data.isProtected = protected.text.lower() == "true"
is_protected = root_xml.find("./" + TAG_PROTECTED)
if is_protected is not None:
if is_protected.text is not None:
Expand All @@ -562,9 +615,15 @@ def meta_from_xml(root_xml: ElementTree.Element, data: MetaData) -> None:
data.isProtected = False

data.configuresBlockGWAndArchiver = (
ConfigurationXmlConverter.get_configures_block_g_w_and_archiver(root_xml)
ConfigurationXmlConverter.get_configures_block_gw_and_archiver_from_xml(root_xml)
)

dynamic = root_xml.find("./" + TAG_DYNAMIC)
if dynamic is not None:
if dynamic.text is not None:
data.isDynamic = dynamic.text.lower() == "true"
ConfigurationXmlConverter.get_configures_block_g_w_and_archiver(root_xml)

is_dynamic = root_xml.find("./" + TAG_DYNAMIC)
if is_dynamic is not None:
if is_dynamic.text is not None:
Expand All @@ -581,7 +640,8 @@ def _find_all_nodes(
) -> List[ElementTree.Element]:
"""Finds all the nodes regardless of whether it has a namespace or not.

For example the name space for IOCs is xmlns:ioc="http://epics.isis.rl.ac.uk/schema/iocs/1.0"
For example the name space for IOCs is
xmlns:ioc="http://epics.isis.rl.ac.uk/schema/iocs/1.0"

Args:
root: The XML tree object
Expand Down
6 changes: 6 additions & 0 deletions BlockServer/core/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,9 @@
FILENAME_GLOBALS = "globals.txt"

SCHEMA_FOR = [FILENAME_BLOCKS, FILENAME_GROUPS, FILENAME_IOCS, FILENAME_COMPONENTS, FILENAME_META]

# Alarm element nodes
TAG_ALARM_ENABLED = "alarm_enabled"
TAG_ALARM_LATCHED = "alarm_latched"
TAG_ALARM_DELAY = "alarm_delay"
TAG_ALARM_GUIDANCE = "alarm_guidance"
15 changes: 14 additions & 1 deletion BlockServer/test_modules/test_configuration_xml.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,14 @@
from collections import OrderedDict
from xml.etree import ElementTree

from server_common.helpers import MACROS

from BlockServer.config.block import Block
from BlockServer.config.configuration import Configuration
from BlockServer.config.group import Group
from BlockServer.config.ioc import IOC
from BlockServer.config.metadata import MetaData
from BlockServer.config.xml_converter import ConfigurationXmlConverter
from server_common.helpers import MACROS

BLOCKS_XML = """
<?xml version="1.0" ?>
Expand All @@ -44,6 +45,9 @@
<log_deadband>0</log_deadband>
<set_block>False</set_block>
<set_block_val>None</set_block_val>
<alarm_enabled>False</alarm_enabled>
Comment thread
Chsudeepta marked this conversation as resolved.
<alarm_latched>False</alarm_latched>
<alarm_guidance/>
</block>
<block>
<name>TESTBLOCK2</name>
Expand All @@ -59,6 +63,9 @@
<log_deadband>0</log_deadband>
<set_block>False</set_block>
<set_block_val>None</set_block_val>
<alarm_enabled>False</alarm_enabled>
<alarm_latched>False</alarm_latched>
<alarm_guidance/>
</block>
<block>
<name>TESTBLOCK3</name>
Expand All @@ -74,6 +81,9 @@
<log_deadband>0</log_deadband>
<set_block>False</set_block>
<set_block_val>None</set_block_val>
<alarm_enabled>False</alarm_enabled>
<alarm_latched>False</alarm_latched>
<alarm_guidance/>
</block>
<block>
<name>TESTBLOCK4</name>
Expand All @@ -89,6 +99,9 @@
<log_deadband>0</log_deadband>
<set_block>False</set_block>
<set_block_val>None</set_block_val>
<alarm_enabled>False</alarm_enabled>
<alarm_latched>False</alarm_latched>
<alarm_guidance/>
</block>
</blocks>"""

Expand Down
Loading