--- a/pygpibtoolkit/pygpib.py Sun Feb 17 22:59:59 2008 +0100 +++ b/pygpibtoolkit/pygpib.py Mon Feb 25 18:38:27 2008 +0100 @@ -5,6 +5,7 @@ import serial from serial.serialutil import SerialException import time +from pygpibtoolkit.tools import AbstractRegister class ConnectionError(Exception): pass @@ -30,12 +31,131 @@ if isinstance(k, basestring): k = self.rev_constants[k] return self.descriptions[k] - class MODE(Constants): _constants = [(1, "CONTROLLER", "Set device as Controller in Charge"), (0, "DEVICE", "Set device as simple listener"), ] + +class ModeCommand(object): + def __init__(self, description, name, condition=None): + self.name = name + self.description = description + self.condition = condition + +class CommandRegister(object): + _instances = {} + _registered_type = None #Command + def __new__(cls): + # implements a singleton *per class* + if cls.__name__ not in cls._instances: + if cls._registered_type is None: + cls._registered_type = Command + instance = super(CommandRegister, cls).__new__(cls) + instance.registry = {} + cls._instances[cls.__name__] = instance + return cls._instances[cls.__name__] + + @classmethod + def add(cls, registered_cls): + for registry in cls._instances.values(): + if registry.__module__ == registered_cls.__module__: + break + else: + return + + assert issubclass(registered_cls, registry._registered_type) + if registered_cls is registry._registered_type: + return + + name = registered_cls.__name__ + if name not in registry: + registry.registry[name] = registered_cls + + def __contains__(self, key): + return key in self.registry + def keys(self): + return self.registry.keys() + def items(self): + return self.registry.items() + def values(self): + return self.registry.values() + def __getitem__(self, key): + return self.registry[key] + +class MetaCommand(type): + """ + Metaclass for HPIB command. Used to register all commands. + """ + _commands = {} + def __init__(cls, name, bases, dct): + # called at class creation + super(MetaCommand, cls).__init__(name, bases, dct) + if name not in [ "AbstractCommand","Command"]: + CommandRegister().add(cls) + +class AbstractCommand(object): + """ Base class for HPIB command descritption""" + __metaclass__ = MetaCommand + + +class Command(AbstractCommand): + @classmethod + def get_value(self, cnx): + res = cnx.send_command(self.__class__.__name__) + return self.convert_from(res) + + @classmethod + def set_value(self, cnx, value): + raise ValueError, "Can't set value for command '%s'"%self.__class__.__name__ + + @classmethod + def convert_from(self, value): + return value + +class AbstractValue(Command): + @classmethod + def set_value(self, cnx, value): + res = cnx.send_command("%s %s"%(self.__class__.__name__, + self.convert_to(value))) + return res + @classmethod + def convert_to(self, value): + return str(value) + +class BoolValue(AbstractValue): + _type = bool + @classmethod + def convert_from(self, value): + return value and value.lower() in ['1','true','yes','on'] + @classmethod + def convert_to(self, value): + return value and "1" or "0" + +class IntValue(AbstractValue): + _type = int + +class FloatValue(AbstractValue): + _type = float + +class PercentageValue(FloatValue): + pass #TODO + +class FrequencyValue(FloatValue): + pass + +class DurationValue(FloatValue): + pass + +class StringValue(AbstractValue): + _type = str + +class EnumValue(AbstractValue): + pass + +class Mode(AbstractValue): + pass + # TODO # class STATUS_BYTE(Constants): # # IEEE 488.2 Status Byte constants