示例#1
0
    def put(self, pv: SharedPV, op: ServerOperation) -> None:
        path = [self.controller.mri]
        # We work out what to Put by taking every field that is marked as
        # changed and walking up the tree, adding every dotted field name
        # to the tree on the way up. This set will contain something like:
        #  {"attr.value", "attr"}
        # Or for a table:
        #  {"table.value.colA", "table.value.colB", "table.value", "table"}
        # Or if self.field:
        #  {"value"}
        changed_fields_inc_parents = op.value().changedSet(parents=True,
                                                           expand=False)
        # Taking the intersection with all puttable paths should yield the
        # thing we want to change, so value_changed would be:
        #  {"attr.value"} or {"table.value"} or {"value"}
        value_changed = changed_fields_inc_parents.intersection(self.put_paths)
        assert (
            len(value_changed) == 1
        ), "Can only do a Put to a single field, got %s" % list(value_changed)
        changed = list(value_changed)[0]
        if self.field is not None:
            # Only accept a Put to "value"
            assert changed == "value", "Can only put to value of %s.%s, not %s" % (
                self.controller.mri,
                self.field,
                changed,
            )
            path += [self.field, "value"]
            op_value = op.value()
        else:
            # Get the path and string "value" from the put value
            split = changed.split(".")
            assert (len(split) == 2 and split[1]
                    == "value"), "Can only put to value of %s.%s, not %s" % (
                        self.controller.mri,
                        split[0],
                        split[1],
                    )
            path += list(split)
            op_value = op.value()[split[0]]
        value = convert_value_to_dict(op_value)["value"]
        put = Put(path=path, value=value)

        def handle_put_response(response: Response) -> None:
            if isinstance(response, Return):
                op.done()
            else:
                if isinstance(response, Error):
                    message = stringify_error(response.message)
                else:
                    message = "BadResponse: %s" % response.to_dict()
                op.done(error=message)

        put.set_callback(handle_put_response)
        self.controller.handle_request(put).get()
示例#2
0
    def send_put(self, mri, attribute_name, value):
        """Abstract method to dispatch a Put to the server

        Args:
            mri (str): The mri of the Block
            attribute_name (str): The name of the Attribute within the Block
            value: The value to put
        """
        q = Queue()
        request = Put(path=[mri, attribute_name, "value"], value=value)
        request.set_callback(q.put)
        IOLoopHelper.call(self._send_request, request)
        response = q.get()
        if isinstance(response, Error):
            raise response.message
        else:
            return response.value
示例#3
0
 def _mqtt_receive(self, clnt, userdata, message):
     [block, attribute] = message.topic.split("/")
     self._disable_mqtt()
     controller = self.process.get_controller(block)
     request = Put(path=[block, attribute, "value"],
                   value=message.payload,
                   callback=self._enable_mqtt)
     controller.handle_request(request)
示例#4
0
 def test_counter_subscribe(self):
     q = Queue()
     # Subscribe to the value
     sub = Subscribe(id=20, path=["counting", "counter"], delta=False)
     sub.set_callback(q.put)
     self.controller.handle_request(sub)
     # Check initial return
     response = q.get(timeout=1.0)
     self.assertIsInstance(response, Update)
     assert response.id == 20
     assert response.value["typeid"] == "epics:nt/NTScalar:1.0"
     assert response.value["value"] == 0
     # Post increment()
     post = Post(id=21, path=["counting", "increment"])
     post.set_callback(q.put)
     self.controller.handle_request(post)
     # Check the value updates...
     response = q.get(timeout=1)
     self.assertIsInstance(response, Update)
     assert response.id == 20
     assert response.value["value"] == 1
     # ... then we get the return
     response = q.get(timeout=1)
     self.assertIsInstance(response, Return)
     assert response.id == 21
     assert response.value is None
     # Check we can put too
     put = Put(id=22, path=["counting", "counter", "value"], value=31)
     put.set_callback(q.put)
     self.controller.handle_request(put)
     # Check the value updates...
     response = q.get(timeout=1)
     self.assertIsInstance(response, Update)
     assert response.id == 20
     assert response.value["value"] == 31
     # ... then we get the return
     response = q.get(timeout=1)
     self.assertIsInstance(response, Return)
     assert response.id == 22
     assert response.value is None
     # And that there isn't anything else
     with self.assertRaises(TimeoutError):
         q.get(timeout=0.05)
示例#5
0
 def test_concurrency(self):
     q = Queue()
     # Subscribe to the whole block
     sub = Subscribe(id=0, path=["mri"], delta=True)
     sub.set_callback(q.put)
     self.c.handle_request(sub)
     # We should get first Delta through with initial value
     r = q.get().to_dict()
     assert r["id"] == 0
     assert len(r["changes"]) == 1
     assert len(r["changes"][0]) == 2
     assert r["changes"][0][0] == []
     assert r["changes"][0][1]["meta"]["label"] == "My label"
     assert r["changes"][0][1]["label"]["value"] == "My label"
     # Do a Put on the label
     put = Put(id=2, path=["mri", "label", "value"], value="New", get=True)
     put.set_callback(q.put)
     self.c.handle_request(put)
     # Check we got two updates before the return
     r = q.get().to_dict()
     assert r["id"] == 0
     assert len(r["changes"]) == 2
     assert len(r["changes"][0]) == 2
     assert r["changes"][0][0] == ["label", "value"]
     assert r["changes"][0][1] == "New"
     assert len(r["changes"][0]) == 2
     assert r["changes"][1][0] == ["label", "timeStamp"]
     r = q.get().to_dict()
     assert r["id"] == 0
     assert len(r["changes"]) == 1
     assert len(r["changes"][0]) == 2
     assert r["changes"][0][0] == ["meta", "label"]
     assert r["changes"][0][1] == "New"
     # Then the return
     r3 = q.get().to_dict()
     assert r3["id"] == 2
     assert r3["value"] == "New"
示例#6
0
    def test_handle_request(self):
        q = Queue()

        request = Get(id=41, path=["mri", "myAttribute"])
        request.set_callback(q.put)
        self.o.handle_request(request)
        response = q.get(timeout=0.1)
        self.assertIsInstance(response, Return)
        assert response.id == 41
        assert response.value["value"] == "hello_block"
        self.part.my_attribute.meta.writeable = False
        request = Put(
            id=42, path=["mri", "myAttribute"], value="hello_block2", get=True
        )
        request.set_callback(q.put)
        self.o.handle_request(request)
        response = q.get(timeout=0.1)
        self.assertIsInstance(response, Error)  # not writeable
        assert response.id == 42

        self.part.my_attribute.meta.writeable = True
        self.o.handle_request(request)
        response = q.get(timeout=0.1)
        self.assertIsInstance(response, Return)
        assert response.id == 42
        assert response.value == "hello_block2"

        request = Post(id=43, path=["mri", "method"])
        request.set_callback(q.put)
        self.o.handle_request(request)
        response = q.get(timeout=0.1)
        self.assertIsInstance(response, Return)
        assert response.id == 43
        assert response.value == "world"

        # cover the controller._handle_post path for parameters
        request = Post(id=43, path=["mri", "method"], parameters={"dummy": 1})
        request.set_callback(q.put)
        self.o.handle_request(request)
        response = q.get(timeout=0.1)
        self.assertIsInstance(response, Error)
        assert response.id == 43
        assert (
            str(response.message)
            == "Given keys ['dummy'], some of which aren't in allowed keys []"
        )

        request = Subscribe(id=44, path=["mri", "myAttribute"], delta=False)
        request.set_callback(q.put)
        self.o.handle_request(request)
        response = q.get(timeout=0.1)
        self.assertIsInstance(response, Update)
        assert response.id == 44
        assert response.value["typeid"] == "epics:nt/NTScalar:1.0"
        assert response.value["value"] == "hello_block2"

        request = Unsubscribe(id=44)
        request.set_callback(q.put)
        self.o.handle_request(request)
        response = q.get(timeout=0.1)
        self.assertIsInstance(response, Return)
        assert response.id == 44
示例#7
0
 def set_value(self, value):
     self._state = self.RUNNING
     request = Put(self, None, self.endpoint + ("value",), str(value))
     return request