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.

Mon, 25 Feb 2008 19:50:49 +0100

author
David Douard <david.douard@logilab.fr>
date
Mon, 25 Feb 2008 19:50:49 +0100
changeset 54
5c1a312830e7
parent 53
8e32c806fcdd
child 55
d400eaa4b048

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.

pygpibtoolkit/HP3562A/HP356X.py file | annotate | diff | comparison | revisions
pygpibtoolkit/gpibcontroller.py file | annotate | diff | comparison | revisions
pygpibtoolkit/pygpib.py file | annotate | diff | comparison | revisions
--- 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):

mercurial