Exemplo n.º 1
0
    def transition(self, state, message=""):
        """Change to a new state if the transition is allowed

        Args:
            state (str): State to transition to
            message (str): Message if the transition is to a fault state
        """
        with self.changes_squashed:
            initial_state = self.state.value
            if self.stateSet.transition_allowed(
                    initial_state=initial_state, target_state=state):
                self.log.debug(
                    "Transitioning from %s to %s", initial_state, state)
                if state == ss.DISABLED:
                    alarm = Alarm.invalid("Disabled")
                elif state == ss.FAULT:
                    alarm = Alarm.major(message)
                else:
                    alarm = Alarm()
                self.update_health(self, alarm)
                self.state.set_value(state)
                self.state.set_alarm(alarm)
                for child, writeable in self._children_writeable[state].items():
                    if isinstance(child, AttributeModel):
                        child.meta.set_writeable(writeable)
                    elif isinstance(child, MethodModel):
                        child.set_writeable(writeable)
                        for element in child.takes.elements.values():
                            element.set_writeable(writeable)
            else:
                raise TypeError("Cannot transition from %s to %s" %
                                (initial_state, state))
Exemplo n.º 2
0
    def transition(self, state, message=""):
        """Change to a new state if the transition is allowed

        Args:
            state (str): State to transition to
            message (str): Message if the transition is to a fault state
        """
        with self.changes_squashed:
            initial_state = self.state.value
            if self.state_set.transition_allowed(initial_state=initial_state,
                                                 target_state=state):
                self.log.debug("%s: Transitioning from %s to %s", self.mri,
                               initial_state, state)
                if state == ss.DISABLED:
                    alarm = Alarm.invalid("Disabled")
                elif state == ss.FAULT:
                    alarm = Alarm.major(message)
                else:
                    alarm = Alarm()
                self.update_health(self, HealthInfo(alarm))
                self.state.set_value(state)
                self.state.set_alarm(alarm)
                for child, writeable in self._children_writeable[state].items(
                ):
                    child.meta.set_writeable(writeable)
            else:
                raise TypeError("Cannot transition from %s to %s" %
                                (initial_state, state))
Exemplo n.º 3
0
 def handle_changes(self, changes: Dict[str, Any], ts: TimeStamp) -> None:
     with self.changes_squashed:
         icon_needs_update = False
         if isinstance(changes, Dict):
             for k, v in changes.items():
                 # Health changes are for us
                 if k.upper() == "HEALTH":
                     if v.upper() == "OK":
                         alarm = Alarm.ok
                     else:
                         alarm = Alarm.major(v)
                     self.update_health(
                         self, builtin.infos.HealthInfo(cast(Alarm, alarm), ts)
                     )
                     continue
                 # Work out if there is a part we need to notify
                 try:
                     part = self.field_parts[k]
                 except KeyError:
                     self.log.exception(f"Can't handle field {self.block_name}.{k}")
                     part = None
                 if part is None:
                     continue
                 part.handle_change(v, ts)
                 if not icon_needs_update:
                     icon_needs_update = k in self.icon_part.update_fields
                 try:
                     mux_meta = self.mux_metas[k]
                 except KeyError:
                     pass
                 else:
                     self._handle_mux_update(mux_meta, v)
         if icon_needs_update:
             d = {}
             for key in self.icon_part.update_fields:
                 if key in self.field_parts:
                     field_part = self.field_parts[key]
                     if field_part:
                         d[key] = field_part.attr.value
             icon = builtin.util.SVGIcon(self.icon_part.svg_text)
             self.icon_part.update_icon(icon, d)
             self.icon_part.attr.set_value(str(icon), ts=ts)
Exemplo n.º 4
0
    def test_block_fields_adder(self):
        fields = OrderedDict()
        block_data = BlockData(2, "Adder description", fields)
        fields["INPA"] = FieldData("pos_mux", "", "Input A", ["A.OUT", "B.OUT"])
        fields["INPB"] = FieldData("pos_mux", "", "Input B", ["A.OUT", "B.OUT"])
        fields["DIVIDE"] = FieldData(
            "param", "enum", "Divide output", ["/1", "/2", "/4"]
        )
        fields["OUT"] = FieldData("pos_out", "", "Output", ["No", "Capture"])
        fields["HEALTH"] = FieldData("read", "enum", "What's wrong", ["OK", "Very Bad"])

        o = PandABlockController(self.client, "MRI", "ADDER1", block_data, "/docs")
        self.process.add_controller(o)
        b = self.process.block_view("MRI:ADDER1")

        assert list(b) == [
            "meta",
            "health",
            "icon",
            "label",
            "help",
            "inputs",
            "inpa",
            "inpb",
            "parameters",
            "divide",
            "outputs",
            "out",
        ]

        group = b.inputs
        assert group.meta.tags == ["widget:group", "config:1"]

        inpa = b.inpa
        assert inpa.meta.writeable is True
        assert inpa.meta.typeid == ChoiceMeta.typeid
        assert inpa.meta.tags == [
            "group:inputs",
            "sinkPort:int32:ZERO",
            "widget:combo",
            "config:1",
        ]
        assert inpa.meta.choices == ["A.OUT", "B.OUT"]
        inpa.put_value("A.OUT")
        self.client.set_field.assert_called_once_with("ADDER1", "INPA", "A.OUT")
        self.client.reset_mock()

        divide = b.divide
        assert divide.meta.writeable is True
        assert divide.meta.typeid == ChoiceMeta.typeid
        assert divide.meta.tags == ["group:parameters", "widget:combo", "config:1"]
        assert divide.meta.choices == ["/1", "/2", "/4"]

        out = b.out
        assert out.meta.writeable is False
        assert out.meta.typeid == NumberMeta.typeid
        assert out.meta.dtype == "int32"
        assert out.meta.tags == [
            "group:outputs",
            "sourcePort:int32:ADDER1.OUT",
            "widget:textupdate",
        ]

        queue = Queue()
        subscribe = Subscribe(path=["MRI:ADDER1", "out"], delta=True)
        subscribe.set_callback(queue.put)
        o.handle_request(subscribe)
        delta = queue.get(timeout=1)
        assert delta.changes[0][1]["value"] == 0

        ts = TimeStamp()
        o.handle_changes({"OUT": "145"}, ts)
        delta = queue.get(timeout=1)
        assert delta.changes == [
            [["value"], 145],
            [["timeStamp"], ts],
        ]

        subscribe = Subscribe(path=["MRI:ADDER1", "health"], delta=True)
        subscribe.set_callback(queue.put)
        o.handle_request(subscribe)
        delta = queue.get(timeout=1)
        assert delta.changes[0][1]["value"] == "OK"

        ts = TimeStamp()
        o.handle_changes({"HEALTH": "Very Bad"}, ts)
        delta = queue.get(timeout=1)
        assert delta.changes == [
            [["value"], "Very Bad"],
            [["alarm"], Alarm.major("Very Bad")],
            [["timeStamp"], ts],
        ]
        o.handle_changes({"HEALTH": "OK"}, ts)
        delta = queue.get(timeout=1)
        assert delta.changes == [
            [["value"], "OK"],
            [["alarm"], Alarm.ok],
            [["timeStamp"], ts],
        ]