# HG changeset patch # User David Douard # Date 1203965449 -3600 # Node ID 5c1a312830e7ab52086f8b3266cca8bb702c7bd0 # Parent 8e32c806fcdd631a368483921134c5b7dc0b8462 An AbstractGPIBDevice and the Command should now behave quite OK ie. one can type d.MyCommand and it will return the value (either from the cache or after having asked it to the device), and use d.FRS = 10000 to send the command "FRS 10000 Hz" to the device transparently. diff -r 8e32c806fcdd -r 5c1a312830e7 pygpibtoolkit/HP3562A/HP356X.py --- a/pygpibtoolkit/HP3562A/HP356X.py Mon Feb 25 18:38:27 2008 +0100 +++ b/pygpibtoolkit/HP3562A/HP356X.py Mon Feb 25 19:50:49 2008 +0100 @@ -1,9 +1,9 @@ # -from pygpibtoolkit.pygpib import CommandRegister, Constants, Command -from pygpibtoolkit.pygpib import BoolValue, IntValue, FloatValue -from pygpibtoolkit.pygpib import PercentageValue, FrequencyValue, DurationValue -from pygpibtoolkit.pygpib import EnumValue, StringValue -from pygpibtoolkit.pygpib import Mode, ModeCommand +from pygpibtoolkit.pygpib import CommandRegister, Constants, Command +from pygpibtoolkit.pygpib import BoolValue, IntValue, FloatValue +from pygpibtoolkit.pygpib import PercentageValue, FrequencyValue, DurationValue +from pygpibtoolkit.pygpib import EnumValue, StringValue +from pygpibtoolkit.pygpib import Mode, ModeCommand from pygpibtoolkit.gpibcontroller import AbstractGPIBDevice, deviceRegister @@ -233,25 +233,6 @@ class HP356XDevice(AbstractGPIBDevice): _accepts = ["HP3562A", "HP3563A"] _idn = "ID?" + _cmd_register = Register - def __init__(self, idn, address, controller): - super(HP356XDevice, self).__init__(idn, address, controller) - self._registry = Register() # singleton - self._cache = dict([(k, None) for k, v in self._registry.items() if isinstance(v, Mode)]) - for k in self._registry.keys(): - setattr(self, - - def _get(self, name): - print "get ", name - assert name in self._registry - if name in self._cache: - if self._cache[name] is None: - # where to get the info? - # ... compute value - self._cache[name] = value - return self._cache[name] - self._registry[name].get_value(self._cnx) - def _set(self, name, value): - assert name in self._registry - self._registry[name].set_value(self._cnx, value) deviceRegister.register_manager(HP356XDevice) diff -r 8e32c806fcdd -r 5c1a312830e7 pygpibtoolkit/gpibcontroller.py --- a/pygpibtoolkit/gpibcontroller.py Mon Feb 25 18:38:27 2008 +0100 +++ b/pygpibtoolkit/gpibcontroller.py Mon Feb 25 19:50:49 2008 +0100 @@ -5,10 +5,26 @@ import sys import threading import time +from inspect import isclass + +from serial.serialutil import SerialException from prologix import GPIB, GPIB_CONTROLLER, GPIB_DEVICE +from pygpibtoolkit.pygpib import AbstractCommand + +class AbstractGPIBDeviceMetaclass(type): + def __new__(mcs, name, bases, classdict): + new_cls = type.__new__(mcs, name, bases, classdict) + module = sys.modules[new_cls.__module__] + for pname, param in module.__dict__.items(): + if isclass(param) and issubclass(param, AbstractCommand) and param.__module__ == new_cls.__module__: + setattr(new_cls, pname, param()) + return new_cls class AbstractGPIBDevice(object): + __metaclass__ = AbstractGPIBDeviceMetaclass _accepts = [] + _cmd_register = None # to be defined in son classes + @classmethod def accepts(cls, idn): return idn in cls._accepts @@ -18,6 +34,29 @@ self._address = address self._controller = controller + self._registry = self._cmd_register() # singleton + self._cache = {} + for pname, param in self.__class__.__dict__.items(): + if isinstance(param, AbstractCommand) and not param._readonly: + self._cache[pname] = param._init_value + + def _get(self, name): + assert name in self._registry + if name in self._cache: + if self._cache[name] is None: + # where to get the info? + # ... compute value + value = self._registry[name].get_value(self._cnx) + self._cache[name] = value + return self._cache[name] + + def _set(self, name, value): + assert name in self._registry + res = self._registry[name].set_value(self._cnx, value) + if name in self._cache: + self._cache[name] = value + return res + def manage_srq(self): pass @@ -69,7 +108,10 @@ """ def __init__(self, device="/dev/ttyUSB0", controller_address=21): self._address = controller_address - self._cnx = GPIB(device) + try: + self._cnx = GPIB(device) + except SerialException: + self._cnx = None self._devices = {} self._setup_threading_system() @@ -92,7 +134,7 @@ self._loop_interrupter.set() def _check_srq(self): - if self._cnx.check_srq(): + if self._cnx and self._cnx.check_srq(): addrs = sorted(self._devices.keys()) polled = self._cnx.poll(addrs) for add in addrs: diff -r 8e32c806fcdd -r 5c1a312830e7 pygpibtoolkit/pygpib.py --- a/pygpibtoolkit/pygpib.py Mon Feb 25 18:38:27 2008 +0100 +++ b/pygpibtoolkit/pygpib.py Mon Feb 25 19:50:49 2008 +0100 @@ -95,9 +95,24 @@ CommandRegister().add(cls) class AbstractCommand(object): - """ Base class for HPIB command descritption""" + """ + Base class for HPIB command descritption. + + This is actually a attribute descriptor, which should have + AbstractGPIBDevice derived classes as owner. + """ __metaclass__ = MetaCommand + _readonly = True + _init_value = None + def __get__(self, instance, owner): + if instance is None: + return self + return instance._get(self.__class__.__name__) + def __set__(self, instance, value): + if instance is None: + return self + return instance._set(self.__class__.__name__, value) class Command(AbstractCommand): @classmethod @@ -114,10 +129,11 @@ return value class AbstractValue(Command): + _readonly = False @classmethod def set_value(self, cnx, value): - res = cnx.send_command("%s %s"%(self.__class__.__name__, - self.convert_to(value))) + value = self.convert_to(value) + res = cnx.send_command("%s %s"%(self.__class__.__name__, value) return res @classmethod def convert_to(self, value):