Device driver development kit (DDK)

This is where the classes for the device driver development kit are defined. Parameters relative to every command are stored in Command (read-only, read-write, or write-only; mnemonic; maximum and minimum value, for example)

Then, the Commands are organized in Subsystems. The Subsystems may be nested, which is useful to organize large drivers or SCPI drivers.

A Protocol may be set on a Subsystem. The Protocol will handle the command, like, for example, formatting and sending a request to the hardware; parse the results; and send it back.

A simplified UML representation of a driver using the classes in this module is

class Command {
  read(node=None): object
  write(value=None, node=None): void
}
class Context {
  reader: Command.reader
  writer: Command.writer
  value: object
  node: object
  path: [Subsystem]
}
class Subsystem {
  read(Context): object
  write(Context): void
}
class Protocol {
  read(Context): object
  write(Context): void
}
class CommandCallerProtocol {
  read(Context): object
  write(Context): void
}
class ObjectWrapperProtocol {
  object
  read(Context): object
  write(Context): void
}
class CommunicationProtocol {
  Socket
  read(Context): object
  write(Context): void
}
Command      "1..*"  --* "parent 1"      Subsystem
(Command, Subsystem) --                  Context
Subsystem    "0..1"  --* "parent 1"      Subsystem
Subsystem    "1..*"  --* "parent 1"      Protocol
Protocol             --* "parent 0..1"   Subsystem
Protocol             <|--                CommandCallerProtocol
Protocol             <|--                CommunicationProtocol
Protocol             <|--                ObjectWrapperProtocol

exception pyhard2.driver.HardwareError

Exception upon error returned from the hardware.

Use this exception for errors documented in the hardware manual.

exception pyhard2.driver.DriverError

Exception occuring after an error in the software.

class pyhard2.driver.Context(command, value=None, node=None)

Request to pass to a Protocol.

reader

The value stored in command.reader.

writer

The value stored in command.writer.

value

The value to write, or None.

node

The node on which to read or write, or None.

subsystem

The Subsystem on which the command is defined.

path

[Subsystem]

The list of subsystem traversed until the Protocol.

append(subsystem)

Append to the path.

class pyhard2.driver.Access

Enum for read-only, read-write, and write-only access.

RO, WO, RW
class pyhard2.driver.Command(reader, writer=None, minimum=None, maximum=None, access='Access.RW', rfunc=None, wfunc=None, doc=None)

Store information related to a Command.

Parameters:
  • reader (str or callable) – Mnemonic or command to read.
  • writer (str or callable, optional) – Mnemonic or command to write. Default to reader.
  • minimum (number, optional) – Minimum value used for data validation.
  • maximum (number, optional) – Maximum value used for data validation. Values passed to the parameter exceeding minimum or maximum will be silently coerced to avoid hardware errors.
  • rfunc (function, optional) – Convert on read.
  • wfunc (function, optional) – Convert on write. These functions can be used either for type conversion (i.e., str to int) or for pretty printing. Do nothing by default.
  • doc – docstring
signal

value, node

Emit the value returned by read() and the node.

Context

class Context

Nested Context class.

class Context(command, value=None, node=None)

Context nested in Command to make derivable.

See Context.

Command.read(node=None)

Request reading a value from node.

Returns:The value.
Raises:DriverError – if trying to read a write-only command.
Command.write(value=None, node=None)

Request writing value in node.

Raises:DriverError – when writing a read-only command or when the value is None for a write-only command.
class pyhard2.driver.Subsystem(parent=None)

A logical group of one or more commands.

__setattr__(name, value)

The subsystem takes the ownership of commands.

protocol()

Return the protocol if one has been set.

setProtocol(protocol)

Set the protocol to protocol.

read(context)

Forward the read request.

Forward to the request to the Protocol if one has been set or to the Subsystem‘s parent otherwise.

Raises:AttributeError – if the Subsystem has neither parent nor Protocol.
write(context)

Forward the write request.

Forward the request to the Protocol if one has been set or to the Subsystem‘s parent otherwise.

Raises:AttributeError – if the Subsystem has neither parent nor Protocol.
class pyhard2.driver.Protocol(parent=None)

Protocols should derive this class.

read(context)

Handle the read request.

write(context)

Handle the write request.

class pyhard2.driver.CommandCallerProtocol(parent=None)

Handle Commands with functions for reader and writer.

Example

>>> class Handled(object):
...
...     def __init__(self):
...         self._value = 0
...
...     def get_value(self):
...         return self._value
...
...     def set_value(self, value):
...         self._value = value
...
>>> handled = Handled()
>>> driver = Subsystem()
>>> driver.measure = Command(handled.get_value, handled.set_value)
>>> driver.setProtocol(CommandCallerProtocol())
>>> driver.measure.read()     # read handled._value
0
>>> driver.measure.write(10)  # write handled._value = 10
>>> driver.measure.read()     # read new handled._value
10
>>> handled._value  # handled._value has changed
10
read(context)

Return context.reader().

write(context)

Call context.writer(context.value).

class pyhard2.driver.ObjectWrapperProtocol(wrapped_obj, parent=None)

Get and set attributes on python objects.

Parameters:wrapped_obj – The nodes are copies of wrapped_obj.

Note

The protocol makes one copy of wrapped_obj per node.

Example

>>> class Handled(object):
...
...     def __init__(self):
...         self.value = 0
...
>>> handled = Handled()
>>> protocol = ObjectWrapperProtocol(handled)
>>> driver = Subsystem()
>>> driver.measure = Command("value")  # reader is the attribute name
>>> driver.setProtocol(protocol)
>>> driver.measure.read(1)       # read handled.value at node 1
0
>>> driver.measure.write(10, 1)  # write handled.value = 10
>>> driver.measure.read(1)       # read new handled.value
10
>>> protocol.node(1).value       # read value directly
10
node(node=None)

Return the actual object at node.

read(context)

Get the attribute named context.reader at context.node.

write(context)

Set the attribute named context.writer at context.node to context.value.

class pyhard2.driver.CommunicationProtocol(socket, parent=None)

Protocols that communicate via a socket should derive this class and implement the read() and write() methods.

pyhard2.driver.splitlines(txt, sep='\n')

Return a list of the lines in txt, breaking at sep.

class pyhard2.driver.TesterSocket(*args, **kwargs)

A fake socket with canned responses, used for testing.

msg

dict

map commands received by the socket to canned answers.

newline

newline character.

write(message)

Buffer the canned answer for message.

read(n)

Return n characters from the buffer.

readline()

Return one line in the buffer.

inWaiting()

Return True is the buffer is not empty.

class pyhard2.driver.Serial(port=None, newline='n', *args, **kwargs)

Fix readline() in pyserial.

readline()

Implement own readline since changing EOL character with io does not work well.