| 660 | return attval.value |
| 661 | |
| 662 | def set_attribute_value(self, nodeid, attr, value): |
| 663 | with self._lock: |
| 664 | self.logger.debug("set attr val: %s %s %s", nodeid, attr, value) |
| 665 | node = self._nodes.get(nodeid, None) |
| 666 | if node is None: |
| 667 | return ua.StatusCode(ua.StatusCodes.BadNodeIdUnknown) |
| 668 | attval = node.attributes.get(attr, None) |
| 669 | if attval is None: |
| 670 | self.logger.warning("Tried to write attribute '%s' in %s, but the attribute is missing", attr, nodeid) |
| 671 | return ua.StatusCode(ua.StatusCodes.BadAttributeIdInvalid) |
| 672 | |
| 673 | old = attval.value |
| 674 | attval.value = value |
| 675 | cbs = [] |
| 676 | if old.Value != value.Value: # only send call callback when a value change has happend |
| 677 | cbs = list(attval.datachange_callbacks.items()) |
| 678 | |
| 679 | for k, v in cbs: |
| 680 | try: |
| 681 | v(k, value) |
| 682 | except Exception as ex: |
| 683 | self.logger.exception("Error calling datachange callback %s, %s, %s", k, v, ex) |
| 684 | |
| 685 | return ua.StatusCode() |
| 686 | |
| 687 | def add_datachange_callback(self, nodeid, attr, callback): |
| 688 | with self._lock: |