def setUp(self, mock_client, catools): self.process = Mock() self.o = PandABlocksRunnableController(mri="P", config_dir="/tmp", prefix="PV:") self.o.setup(self.process) blocks_data = OrderedDict() fields = OrderedDict() fields["TS"] = FieldData("ext_out", "", "Timestamp", ["No", "Capture"]) blocks_data["PCAP"] = BlockData(1, "", fields) fields = OrderedDict() fields["VAL"] = FieldData("pos_out", "", "Output", ["No", "Capture"]) blocks_data["INENC"] = BlockData(1, "", fields) self.client = self.o.client self.client.get_blocks_data.return_value = blocks_data self.o._make_blocks_parts()
def test_block_fields_lut(self): fields = OrderedDict() block_data = BlockData(8, "Lut description", fields) fields["FUNC"] = FieldData("param", "lut", "Function", []) o = PandABlockController(self.client, "MRI", "LUT3", block_data, "/docs") self.process.add_controller(o) b = self.process.block_view("MRI:LUT3") func = b.func assert func.meta.writeable is True assert func.meta.typeid == StringMeta.typeid assert func.meta.tags == ["group:parameters", "widget:textinput", "config:1"] queue = Queue() subscribe = Subscribe(path=["MRI:LUT3"], delta=True) subscribe.set_callback(queue.put) o.handle_request(subscribe) delta = queue.get() assert delta.changes[0][1]["func"]["value"] == "" assert '<path id="OR"' in delta.changes[0][1]["icon"]["value"] # This is the correct FUNC.RAW value for !A&!B&!C&!D&!E self.client.get_field.return_value = "1" ts = TimeStamp() o.handle_changes({"FUNC": "!A&!B&!C&!D&!E"}, ts) self.client.get_field.assert_called_once_with("LUT3", "FUNC.RAW") delta = queue.get() assert delta.changes == [ [["func", "value"], "!A&!B&!C&!D&!E"], [["func", "timeStamp"], ts], [["icon", "value"], ANY], [["icon", "timeStamp"], ts], ] assert '<path id="OR"' not in delta.changes[2][1]
def test_block_data(self): messages = [ "!TTLIN 6\n!TTLOUT 10\n.\n", "OK =TTL input\n", "OK =TTL output\n", "!VAL 1 ext_out funny\n!TERM 0 param enum\n.\n", "!VAL 0 bit_mux\n.\n", "OK =TTL termination\n", "OK =TTL input value\n", "!High-Z\n!50-Ohm\n.\n", "!No\n!Value\n.\n", "OK =TTL output value\n", "!ZERO\n!TTLIN1.VAL\n!TTLIN2.VAL\n.\n", ] self.start(messages) block_data = self.c.get_blocks_data() self.c.stop() assert self.socket.sendall.call_args_list == [ call(b"*BLOCKS?\n"), call(b"*DESC.TTLIN?\n"), call(b"*DESC.TTLOUT?\n"), call(b"TTLIN.*?\n"), call(b"TTLOUT.*?\n"), call(b"*DESC.TTLIN.TERM?\n"), call(b"*DESC.TTLIN.VAL?\n"), call(b"*ENUMS.TTLIN.TERM?\n"), call(b"*ENUMS.TTLIN.VAL.CAPTURE?\n"), call(b"*DESC.TTLOUT.VAL?\n"), call(b"*ENUMS.TTLOUT.VAL?\n"), ] assert list(block_data) == ["TTLIN", "TTLOUT"] in_fields = OrderedDict() in_fields["TERM"] = FieldData( "param", "enum", "TTL termination", ["High-Z", "50-Ohm"] ) in_fields["VAL"] = FieldData( "ext_out", "funny", "TTL input value", ["No", "Value"] ) assert block_data["TTLIN"] == (BlockData(6, "TTL input", in_fields)) out_fields = OrderedDict() out_fields["VAL"] = FieldData( "bit_mux", "", "TTL output value", ["ZERO", "TTLIN1.VAL", "TTLIN2.VAL"] ) assert block_data["TTLOUT"] == (BlockData(10, "TTL output", out_fields))
def setUp(self, mock_client, mock_adbase_parts): mock_adbase_parts.return_value = ([], []) self.process = Process() self.o = PandARunnableController( mri="P", config_dir="/tmp", prefix="PV:", use_git=False ) self.o.add_part(DatasetTablePart("DSET")) self.client = self.o._client self.client.started = False blocks_data = OrderedDict() fields = OrderedDict() fields["TS"] = FieldData("ext_out", "", "Timestamp", ["No", "Capture"]) blocks_data["PCAP"] = BlockData(1, "", fields) fields = OrderedDict() fields["VAL"] = FieldData("pos_out", "", "Output", ["No", "Capture"]) blocks_data["INENC"] = BlockData(4, "", fields) self.client.get_blocks_data.return_value = blocks_data self.process.add_controller(self.o) self.process.start()
def setUp(self, mock_client): self.process = Process() self.config_dir = tmp_dir("config_dir") self.o = PandAManagerController(mri="P", config_dir=self.config_dir.value, poll_period=1000) self.client = self.o._client self.client.started = False blocks_data = OrderedDict() fields = OrderedDict() fields["INP"] = FieldData("pos_mux", "", "Input A", ["ZERO", "COUNTER.OUT"]) fields["START"] = FieldData("param", "", "Start position", []) fields["STEP"] = FieldData("param", "", "Step position", []) fields["OUT"] = FieldData("bit_out", "", "Output", []) blocks_data["PCOMP"] = BlockData(1, "Position Compare", fields) fields = OrderedDict() fields["INP"] = FieldData("bit_mux", "", "Input", ["ZERO", "TTLIN.VAL"]) fields["START"] = FieldData("param", "pos", "Start position", []) fields["OUT"] = FieldData("pos_out", "", "Output", ["No", "Capture"]) blocks_data["COUNTER"] = BlockData(1, "", fields) fields = OrderedDict() fields["VAL"] = FieldData("bit_out", "", "Output", []) blocks_data["TTLIN"] = BlockData(2, "", fields) blocks_data["PCAP"] = BlockData(1, "", {}) self.client.get_blocks_data.return_value = blocks_data changes = [ ["PCOMP.INP", "ZERO"], ["PCOMP.STEP", "0"], ["PCOMP.START", "0"], ["PCOMP.OUT", "0"], ["COUNTER.INP", "ZERO"], ["COUNTER.INP.DELAY", "0"], ["COUNTER.OUT", "0"], ["COUNTER.OUT.SCALE", "1"], ["COUNTER.OUT.OFFSET", "0"], ["COUNTER.OUT.UNITS", ""], ["TTLIN1.VAL", "0"], ["TTLIN2.VAL", "0"], ] self.client.get_changes.return_value = changes pcap_bit_fields = { "PCAP.BITS0.CAPTURE": ["TTLIN1.VAL", "TTLIN2.VAL", "PCOMP.OUT", ""] } self.client.get_pcap_bits_fields.return_value = pcap_bit_fields self.process.add_controller(self.o) self.process.start()
def setUp(self, mock_client): self.o = PandABlocksManagerController(mri="P", config_dir="/tmp") self.process = MagicMock() self.o.setup(self.process) blocks_data = OrderedDict() fields = OrderedDict() fields["INP"] = FieldData("pos_mux", "", "Input A", ["ZERO", "COUNTER.OUT"]) fields["START"] = FieldData("param", "", "Start position", []) fields["STEP"] = FieldData("param", "", "Step position", []) fields["OUT"] = FieldData("bit_out", "", "Output", []) blocks_data["PCOMP"] = BlockData(1, "", fields) fields = OrderedDict() fields["INP"] = FieldData("bit_mux", "", "Input", ["ZERO", "TTLIN.VAL"]) fields["START"] = FieldData("param", "pos", "Start position", []) fields["OUT"] = FieldData("pos_out", "", "Output", ["No", "Capture"]) blocks_data["COUNTER"] = BlockData(1, "", fields) fields = OrderedDict() fields["VAL"] = FieldData("bit_out", "", "Output", []) blocks_data["TTLIN"] = BlockData(1, "", fields) self.client = self.o.client self.client.get_blocks_data.return_value = blocks_data self.o._make_blocks_parts() changes = OrderedDict() changes["PCOMP.INP"] = "ZERO" for field_name in ("START", "STEP"): changes["PCOMP.%s" % field_name] = "0" changes["PCOMP.OUT"] = "0" changes["COUNTER.INP"] = "ZERO" changes["COUNTER.INP.DELAY"] = "0" changes["COUNTER.OUT"] = "0" changes["COUNTER.OUT.SCALE"] = "1" changes["COUNTER.OUT.OFFSET"] = "0" changes["COUNTER.OUT.UNITS"] = "" changes["TTLIN.VAL"] = "0" self.o.handle_changes(changes.items()) # Once more to let the bit_outs toggle back self.o.handle_changes(())
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"]) o = PandABlocksMaker(self.client, "ADDER1", block_data, "/docs") assert list(o.parts) == [ 'icon', 'label', 'help', 'inputs', 'INPA', 'INPA.CURRENT', 'INPB', 'INPB.CURRENT', 'parameters', 'DIVIDE', 'outputs', 'OUT', 'OUT.UNITS', 'OUT.SCALE', 'OUT.OFFSET', 'OUT.SCALED', 'OUT.CAPTURE' ] group = o.parts["inputs"] assert group.name == "inputs" assert group.attr.meta.tags == ["widget:group", "config:1"] inpa = o.parts["INPA"] assert inpa.block_name == "ADDER1" assert inpa.field_name == "INPA" assert inpa.meta.writeable == True self.assertIsInstance(inpa.meta, ChoiceMeta) assert inpa.meta.tags == [ "group:inputs", "sinkPort:int32:ZERO", "widget:combo", "config:1" ] assert inpa.meta.choices == ["A.OUT", "B.OUT"] val = o.parts["INPA.CURRENT"] assert val.block_name == "ADDER1" assert val.meta.writeable == False self.assertIsInstance(val.meta, NumberMeta) assert val.meta.dtype == "int32" assert val.meta.tags == ["group:inputs", "widget:textupdate"] valb = o.parts["INPB"] assert valb.field_name == "INPB" divide = o.parts["DIVIDE"] assert divide.block_name == "ADDER1" assert divide.field_name == "DIVIDE" assert divide.meta.writeable == True self.assertIsInstance(divide.meta, ChoiceMeta) assert divide.meta.tags == [ "group:parameters", "widget:combo", "config:1" ] assert divide.meta.choices == ["/1", "/2", "/4"] out = o.parts["OUT"] assert out.block_name == "ADDER1" assert out.field_name == "OUT" assert out.meta.writeable == False self.assertIsInstance(out.meta, NumberMeta) assert out.meta.dtype == "int32" assert out.meta.tags == [ "group:outputs", "sourcePort:int32:ADDER1.OUT", "widget:textupdate" ] units = o.parts["OUT.UNITS"] assert units.block_name == "ADDER1" assert units.field_name == "OUT.UNITS" assert units.meta.writeable == True self.assertIsInstance(units.meta, StringMeta) assert units.meta.tags == [ "group:outputs", "widget:textinput", "config:1" ] scale = o.parts["OUT.SCALE"] assert scale.block_name == "ADDER1" assert scale.field_name == "OUT.SCALE" assert scale.meta.writeable == True self.assertIsInstance(scale.meta, NumberMeta) assert scale.meta.dtype == "float64" assert scale.meta.tags == [ "group:outputs", "widget:textinput", "config:1" ] offset = o.parts["OUT.OFFSET"] assert offset.block_name == "ADDER1" assert offset.field_name == "OUT.OFFSET" assert offset.meta.writeable == True self.assertIsInstance(offset.meta, NumberMeta) assert offset.meta.dtype == "float64" assert offset.meta.tags == [ "group:outputs", "widget:textinput", "config:1" ] capture = o.parts["OUT.CAPTURE"] assert capture.block_name == "ADDER1" assert capture.field_name == "OUT.CAPTURE" assert capture.meta.writeable == True self.assertIsInstance(capture.meta, ChoiceMeta) assert capture.meta.tags == [ "group:outputs", "widget:combo", "config:1" ] assert capture.meta.choices == ["No", "Capture"] scale = o.parts["OUT.SCALED"] assert scale.block_name == "ADDER1" assert scale.meta.writeable == False self.assertIsInstance(scale.meta, NumberMeta) assert scale.meta.dtype == "float64" assert scale.meta.tags == ["group:outputs", "widget:textupdate"]
def test_block_fields_pulse(self): fields = OrderedDict() block_data = BlockData(4, "Pulse description", fields) fields["DELAY"] = FieldData("time", "", "Time", []) fields["INP"] = FieldData("bit_mux", "", "Input", ["X.OUT", "Y.OUT"]) fields["OUT"] = FieldData("bit_out", "", "Output", []) fields["ERR_PERIOD"] = FieldData("read", "bit", "Error", []) o = PandABlocksMaker(self.client, "PULSE2", block_data, "/docs") assert list(o.parts) == [ 'icon', 'label', 'help', 'parameters', 'DELAY', 'DELAY.UNITS', 'inputs', 'INP', 'INP.CURRENT', 'INP.DELAY', 'outputs', 'OUT', 'readbacks', 'ERR_PERIOD' ] help = o.parts['help'] assert help.attr.value == "/docs/build/pulse_doc.html" delay = o.parts["DELAY"] assert delay.block_name == "PULSE2" assert delay.field_name == "DELAY" assert delay.meta.writeable == True self.assertIsInstance(delay.meta, NumberMeta) assert delay.meta.dtype == "float64" assert delay.meta.tags == [ "group:parameters", "widget:textinput", "config:2" ] units = o.parts["DELAY.UNITS"] assert units.block_name == "PULSE2" assert units.field_name == "DELAY.UNITS" assert units.meta.writeable == True self.assertIsInstance(units.meta, ChoiceMeta) assert units.meta.tags == [ "group:parameters", "widget:combo", "config:1" ] assert units.meta.choices == ["s", "ms", "us"] inp = o.parts["INP"] assert inp.block_name == "PULSE2" assert inp.field_name == "INP" assert inp.meta.writeable == True self.assertIsInstance(inp.meta, ChoiceMeta) assert inp.meta.tags == [ "group:inputs", "sinkPort:bool:ZERO", "widget:combo", "config:1" ] assert inp.meta.choices == ["X.OUT", "Y.OUT"] val = o.parts["INP.CURRENT"] assert val.block_name == "PULSE2" assert val.meta.writeable == False self.assertIsInstance(val.meta, BooleanMeta) assert val.meta.tags == ["group:inputs", "widget:led"] delay = o.parts["INP.DELAY"] assert delay.block_name == "PULSE2" assert delay.field_name == "INP.DELAY" assert delay.meta.writeable == True self.assertIsInstance(delay.meta, NumberMeta) assert delay.meta.dtype == "uint8" assert delay.meta.tags == [ "group:inputs", "widget:textinput", "config:1" ] out = o.parts["OUT"] assert out.block_name == "PULSE2" assert out.field_name == "OUT" assert out.meta.writeable == False self.assertIsInstance(out.meta, BooleanMeta) assert out.meta.tags == [ "group:outputs", "sourcePort:bool:PULSE2.OUT", "widget:led" ] err = o.parts["ERR_PERIOD"] assert err.block_name == "PULSE2" assert err.field_name == "ERR_PERIOD" assert err.meta.writeable == False self.assertIsInstance(err.meta, BooleanMeta) assert err.meta.tags == ["group:readbacks", "widget:led"]
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], ]
def test_block_fields_pulse(self): fields = OrderedDict() block_data = BlockData(4, "Pulse description", fields) fields["DELAY"] = FieldData("time", "", "Time", []) fields["INP"] = FieldData("bit_mux", "", "Input", ["ZERO", "X.OUT", "Y.OUT"]) fields["OUT"] = FieldData("bit_out", "", "Output", []) fields["ERR_PERIOD"] = FieldData("read", "bit", "Error", []) o = PandABlockController(self.client, "MRI", "PULSE2", block_data, "/docs") self.process.add_controller(o) b = self.process.block_view("MRI:PULSE2") assert list(b) == [ "meta", "health", "icon", "label", "help", "parameters", "delay", "delayUnits", "inputs", "inp", "inpDelay", "outputs", "out", "readbacks", "errPeriod", ] assert b.meta.label == "Pulse description 2" assert b.label.value == "Pulse description 2" # check setting label b.label.put_value("A new label") assert b.meta.label == "A new label" assert b.label.value == "A new label" self.client.set_field.assert_called_once_with( "*METADATA", "LABEL_PULSE2", "A new label" ) self.client.set_field.reset_mock() # check updated with nothing o.handle_changes(dict(LABEL=""), ts=TimeStamp()) assert b.meta.label == "Pulse description 2" assert b.label.value == "Pulse description 2" self.client.set_field.assert_not_called() # check updated with something from the server o.handle_changes(dict(LABEL="A server label"), ts=TimeStamp()) assert b.meta.label == "A server label" assert b.label.value == "A server label" self.client.set_field.assert_not_called() help = b.help assert help.value == "/docs/build/pulse_doc.html" delay = b.delay assert delay.meta.writeable is True assert delay.meta.typeid == NumberMeta.typeid assert delay.meta.dtype == "float64" assert delay.meta.tags == ["group:parameters", "widget:textinput", "config:2"] units = b.delayUnits assert units.meta.writeable is True assert units.meta.typeid == ChoiceMeta.typeid assert units.meta.tags == ["group:parameters", "widget:combo", "config:1"] assert units.meta.choices == ["s", "ms", "us"] inp = b.inp assert inp.meta.writeable is True assert inp.meta.typeid == ChoiceMeta.typeid assert inp.meta.tags == [ "group:inputs", "sinkPort:bool:ZERO", "widget:combo", "badgevalue:plus:inpDelay:MRI:PULSE2", "config:1", ] assert inp.meta.choices == ["ZERO", "X.OUT", "Y.OUT"] delay = b.inpDelay assert delay.meta.writeable is True assert delay.meta.typeid == NumberMeta.typeid assert delay.meta.dtype == "uint8" assert delay.meta.tags == ["group:inputs", "widget:textinput", "config:1"] out = b.out assert out.meta.writeable is False assert out.meta.typeid == BooleanMeta.typeid assert out.meta.tags == [ "group:outputs", "sourcePort:bool:PULSE2.OUT", "widget:led", ] err = b.errPeriod assert err.meta.writeable is False assert err.meta.typeid == BooleanMeta.typeid assert err.meta.tags == ["group:readbacks", "widget:led"] queue = Queue() subscribe = Subscribe(path=["MRI:PULSE2", "inp"], delta=True) subscribe.set_callback(queue.put) o.handle_request(subscribe) delta = queue.get() assert delta.changes[0][1]["value"] == "ZERO" ts = TimeStamp() o.handle_changes({"INP": "X.OUT"}, ts) delta = queue.get() assert delta.changes == [ [["value"], "X.OUT"], [["timeStamp"], ts], [ ["meta", "tags"], [ "group:inputs", "sinkPort:bool:ZERO", "widget:combo", "badgevalue:plus:inpDelay:MRI:PULSE2", "config:1", "linkedvalue:out:MRI:X", ], ], ]