Mon, 25 Feb 2008 19:50:49 +0100
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.
--- 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)
--- 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:
--- 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):