Browse Source

Starting major code refactor

Matt Sparks 15 years ago
parent
commit
815a25231c

+ 14 - 0
alphasign/__init__.py

@@ -0,0 +1,14 @@
+import datetime
+import os
+import sys
+import serial
+
+import constants
+from interfaces.local import DebugInterface
+from interfaces.local import Serial
+
+from time import Time
+from date import Date
+from string import String
+from packet import Packet
+from text import Text

+ 0 - 337
alphasign/alphasign.py

@@ -1,337 +0,0 @@
-#!/usr/bin/python
-import datetime
-import os
-import sys
-import serial
-
-import constants
-
-
-class Alpha:
-  def __init__(self, device="/dev/ttyS0"):
-    self.device   = device
-    self.type     = "Z"            # Type Code (see protocol)
-    self.address  = "00"           # Sign Address (see protocol)
-    self.mode     = "rotate"       # Default display mode
-    self.position = "middle_line"  # Appropriate for one-line signs
-    self.debug    = False
-
-  def connect(self):
-    """Establish connection to the device.
-
-    Args:
-      device: character device (default: /dev/ttyS0)
-    """
-    # TODO(ms): these settings can probably be tweaked and still support most of
-    # the devices.
-    self._conn = serial.Serial(port=self.device,
-                               baudrate=4800,
-                               parity=serial.PARITY_EVEN,
-                               stopbits=serial.STOPBITS_TWO,
-                               timeout=1,
-                               xonxoff=0,
-                               rtscts=0)
-
-  def disconnect(self):
-    if self._conn:
-      self._conn.close()
-
-  def _packet(self, contents):
-    pkt = ("%s%s%s%s%s%s%s" % (constants.NUL * 5, constants.SOH, self.type,
-                               self.address, constants.STX, contents,
-                               constants.EOT))
-    return pkt
-
-  def _write(self, packet):
-    if not self._conn:
-      return
-    if self.debug:
-      print "Writing packet: %s" % repr(packet)
-    self._conn.write(packet)
-
-  def write_text(self, msg, label="A"):
-    # [WRITE_TEXT][File Label][ESC][Display Position][Mode Code]
-    #   [Special Specifier][ASCII Message]
-    packet = self._packet("%s%s%s%s%s%s" % (constants.WRITE_TEXT, label,
-                                            constants.ESC,
-                                            constants.positions[self.position],
-                                            constants.modes[self.mode],
-                                            msg))
-    self._write(packet)
-
-  def create_string(self, string_label="1", string_size=32):
-    """Create a STRING.
-
-    This is necessary to allocate memory for the STRING on the sign
-
-    Args:
-      string_label: label of the STRING to create
-      string_size: size of the STRING to create, in bytes. 125 max.
-                   Default is 32.
-    """
-    if string_size > 125:
-      string_size = 125
-    size_hex = "%04x" % string_size
-    packet = self._packet("%s%s%s%s%s%s%s%s%s%s%s%s%s" %
-                          (constants.WRITE_SPECIAL, "\$",
-                           "A",          # call label.. why does this matter?
-                           "A",          # text file type
-                           "U",          # this TEXT file is unlocked
-                           "0100",       # text file size in hex
-                           "FF",         # text file's start time (FF = always)
-                           "00",         # text file's stop time
-                           string_label,
-                           "B",          # string file type
-                           "L",          # this string file is locked
-                           size_hex,
-                           "0000"))      # padding
-    self._write(packet)
-
-  def write_string(self, data, label="1"):
-    """Write a STRING.
-
-    Args:
-      data: data to write
-      label: STRING label to write
-    """
-    packet = self._packet("%s%s%s" % (constants.WRITE_STRING, label, data))
-    self._write(packet)
-
-  def call_string(self, string_label="1"):
-    """Call a STRING.
-
-    This is for inserting a STRING file into a TEXT file.
-
-    Args:
-      string_label: label of string to call (default: 1)
-
-    Returns:
-      control code of specified string label
-    """
-    return "\x10%s" % string_label
-
-  def call_date(self, format=0):
-    """Call date for insertion into a TEXT file.
-
-    Args:
-      format: integer from 0 to 9
-                0 - MM/DD/YY
-                1 - DD/MM/YY
-                2 - MM-DD-YY
-                3 - DD-MM-YY
-                4 - MM.DD.YY
-                5 - DD.MM.YY
-                6 - MM DD YY
-                7 - DD MM YY
-                8 - MMM.DD, YYYY
-                9 - Day of week
-
-    Returns:
-      formatted string to use in a TEXT
-    """
-    if format < 0 or format > 9:
-      format = 0
-    return "\x0B%s" % format
-
-  def call_time(self):
-    """Call time for insertion into a TEXT file.
-
-    Returns:
-      formatted string to use in a TEXT
-    """
-    return "\x13"
-
-  def set_mode(self, mode):
-    """FIXME
-    """
-    if mode in self.modes:
-      self.mode = mode
-    # FIXME: error handling for invalid mode
-
-  def set_position(self, mode):
-    """FIXME
-    """
-    if position in self.positions:
-      self.position = position
-    # FIXME: error handling
-
-  def clear_memory(self):
-    """Clear the sign's memory.
-    """
-    packet = self._packet("%s%s" % (constants.WRITE_SPECIAL, "$"))
-    self._write(packet)
-
-  def beep(self, frequency=0, duration=0.1, repeat=0):
-    """Make the sign beep.
-
-    Args:
-      frequency: frequency integer (not in Hz), 0 - 254
-      duration: beep duration, 0.1 - 1.5
-      repeat: number of times to repeat, 0 - 15
-    """
-    if frequency < 0:
-      frequency = 0
-    elif frequency > 254:
-      frequency = 254
-
-    duration = int(duration / 0.1)
-    if duration < 1:
-      duration = 1
-    elif duration > 15:
-      duration = 15
-
-    if repeat < 0:
-      repeat = 0
-    elif repeat > 15:
-      repeat = 15
-
-    packet = self._packet("%s%s%02X%X%X" % (constants.WRITE_SPECIAL, "(2",
-                                            frequency, duration, repeat))
-    self._write(packet)
-
-  def soft_reset(self):
-    """Perform a soft reset on the sign.
-
-    This is non-destructive and does not clear the sign's memory.
-    """
-    packet = self._packet("%s%s" % (constants.WRITE_SPECIAL, ","))
-    self._write(packet)
-
-  def set_day(self, day=None):
-    """Set the day of the week on the sign.
-
-    If the argument is omitted, today's day will be used.
-
-    Args:
-      day (optional): integer between 1 (Sunday) and 7 (Saturday)
-    """
-    if day is None or day < 1 or day > 7:
-      day = datetime.datetime.today().weekday() + 1
-    packet = self._packet("%s%s%s" % (constants.WRITE_SPECIAL, "&", day))
-    self._write(packet)
-
-  def set_date(self, year=None, month=None, day=None):
-    """Sets the date in the memory of the sign. This must be done each day to
-    keep the clock 'up to date', because the sign will not automatically advance
-    the day.
-
-    If the date is not specified in the arguments, today's date will be used.
-
-    Args:
-      year (optional): two-digit year (98, 99, 00, ...)
-      month (optional): integer month (1, 2, ..., 12)
-      day (optional): integer day (1, ..., 31)
-    """
-    today = datetime.datetime.today()
-    if year is None:
-      year = str(today.year)[2:4]
-    if month is None:
-      month = today.month
-    if day is None:
-      day = today.day
-
-    packet = self._packet("%s%s%02d%02d%02d" % (constants.WRITE_SPECIAL, ";",
-                                                year, month, day))
-    self._write(packet)
-
-  def set_time(self, hour=None, minute=None):
-    """Sets ths hour and minute of the internal clock on the sign.
-
-    If the time is not specified in the arguments, the time now will be used.
-
-    Args:
-      hour: hour in 24-hour format (18 instead of 6 for 6PM)
-      minute: minute (0 - 59)
-    """
-    now = datetime.datetime.today()
-    if hour is None:
-      hour = now.hour
-    if minute is None:
-      minute = now.minute
-
-    packet = self._packet("%s%s%02d%02d" % (constants.WRITE_SPECIAL, "\x20",
-                                            hour, minute))
-    self._write(packet)
-
-  def set_time_format(self, format=1):
-    """Sets the time format on the sign.
-
-    Args:
-      format: 1 - 24-hour (military) time
-              0 - 12-hour (standard am/pm) format
-    """
-    if format < 0 or format > 1:
-      format = 1
-    byte = (format == 0) and "S" or "M"
-    packet = this._packet("%s%s%s" % (constants.WRITE_SPECIAL, "\x27", byte))
-    self._write(packet)
-
-  def color(self, color="autocolor"):
-    """Returns color code for a specified color.
-
-    Args:
-      color: color string
-
-    Returns:
-      FIXME
-    """
-    if color not in constants.colors:
-      color = "autocolor"
-    return "%s%s" % ("\x1C", constants.colors[color])
-
-  def charset(self, charset="five_high_std"):
-    """Returns control code for a specified character set.
-
-    Args:
-      charset: charset name string
-
-    Returns:
-      FIXME
-    """
-    if charset not in constants.charsets:
-      charset = "five_high_std"
-    return "%s%s" % ("\x1A", constants.charsets[charset])
-
-  def extchar(self, extchar="left_arrow"):
-    """Returns control code for a specified extended character.
-
-    Args:
-      extchar: extended character name
-
-    Returns:
-      FIXME
-    """
-    if extchar not in constants.extchars:
-      extchar = "left_arrow"
-    return "%s%s" % ("\x08", constants.extchars[extchar])
-
-  def spacing(self, option=0):
-    """Returns control code to set the character spacing.
-
-    Args:
-      option: 0 - set proportional characters
-              1 - fixed width left justified characters
-
-    Returns:
-      FIXME
-    """
-    byte = (option == 0) and "0" or "1"
-    return "\x1E%s" % byte
-
-  def speed(self, speed):
-    """Set the speed of the scrolling text.
-
-    Args:
-      speed: integer 1 (slowest) through 5 (fastest) inclusive
-
-    Returns:
-      FIXME
-    """
-    if speed < 1:
-      speed = 1
-    elif speed > 5:
-      speed = 5
-
-    n = 20 + speed
-    return chr(n)
-

+ 64 - 0
alphasign/date.py

@@ -0,0 +1,64 @@
+import constants
+from packet import Packet
+
+
+class Date(object):
+  def call_date(self, format=0):
+    """Call date for insertion into a TEXT file.
+
+    Args:
+      format: integer from 0 to 9
+                0 - MM/DD/YY
+                1 - DD/MM/YY
+                2 - MM-DD-YY
+                3 - DD-MM-YY
+                4 - MM.DD.YY
+                5 - DD.MM.YY
+                6 - MM DD YY
+                7 - DD MM YY
+                8 - MMM.DD, YYYY
+                9 - Day of week
+
+    Returns:
+      formatted string to use in a TEXT
+    """
+    if format < 0 or format > 9:
+      format = 0
+    return "\x0B%s" % format
+
+  def set(self, year=None, month=None, day=None):
+    """Sets the date in the memory of the sign. This must be done each day to
+    keep the clock 'up to date', because the sign will not automatically advance
+    the day.
+
+    If the date is not specified in the arguments, today's date will be used.
+
+    Args:
+      year (optional): two-digit year (98, 99, 00, ...)
+      month (optional): integer month (1, 2, ..., 12)
+      day (optional): integer day (1, ..., 31)
+    """
+    today = datetime.datetime.today()
+    if year is None:
+      year = str(today.year)[2:4]
+    if month is None:
+      month = today.month
+    if day is None:
+      day = today.day
+
+    packet = self._packet("%s%s%02d%02d%02d" % (constants.WRITE_SPECIAL, ";",
+                                                year, month, day))
+    return packet
+
+  def set_day(self, day=None):
+    """Set the day of the week on the sign.
+
+    If the argument is omitted, today's day will be used.
+
+    Args:
+      day (optional): integer between 1 (Sunday) and 7 (Saturday)
+    """
+    if day is None or day < 1 or day > 7:
+      day = datetime.datetime.today().weekday() + 1
+    packet = self._packet("%s%s%s" % (constants.WRITE_SPECIAL, "&", day))
+    return packet

+ 0 - 0
alphasign/interfaces/__init__.py


+ 49 - 0
alphasign/interfaces/base.py

@@ -0,0 +1,49 @@
+from alphasign import constants
+from alphasign import packet
+
+
+class BaseInterface(object):
+  def write(self, data):
+    pass
+
+  def clear_memory(self):
+    """Clear the sign's memory.
+    """
+    pkt = packet.Packet("%s%s" % (constants.WRITE_SPECIAL, "$"))
+    self.write(pkt)
+
+  def beep(self, frequency=0, duration=0.1, repeat=0):
+    """Make the sign beep.
+
+    Args:
+      frequency: frequency integer (not in Hz), 0 - 254
+      duration: beep duration, 0.1 - 1.5
+      repeat: number of times to repeat, 0 - 15
+    """
+    if frequency < 0:
+      frequency = 0
+    elif frequency > 254:
+      frequency = 254
+
+    duration = int(duration / 0.1)
+    if duration < 1:
+      duration = 1
+    elif duration > 15:
+      duration = 15
+
+    if repeat < 0:
+      repeat = 0
+    elif repeat > 15:
+      repeat = 15
+
+    pkt = packet.Packet("%s%s%02X%X%X" % (constants.WRITE_SPECIAL, "(2",
+                                          frequency, duration, repeat))
+    self.write(pkt)
+
+  def soft_reset(self):
+    """Perform a soft reset on the sign.
+
+    This is non-destructive and does not clear the sign's memory.
+    """
+    pkt = packet.Packet("%s%s" % (constants.WRITE_SPECIAL, ","))
+    self.write(pkt)

+ 53 - 0
alphasign/interfaces/local.py

@@ -0,0 +1,53 @@
+import serial
+import time
+
+from alphasign.interfaces import base
+
+
+class Serial(base.BaseInterface):
+  def __init__(self, device="/dev/ttyS0"):
+    self.device = device
+    self.debug = True
+
+  def connect(self):
+    """Establish connection to the device.
+
+    Args:
+      device: character device (default: /dev/ttyS0)
+    """
+    # TODO(ms): these settings can probably be tweaked and still support most of
+    # the devices.
+    self._conn = serial.Serial(port=self.device,
+                               baudrate=4800,
+                               parity=serial.PARITY_EVEN,
+                               stopbits=serial.STOPBITS_TWO,
+                               timeout=1,
+                               xonxoff=0,
+                               rtscts=0)
+
+  def disconnect(self):
+    if self._conn:
+      self._conn.close()
+
+  def write(self, packet):
+    if not self._conn:
+      return
+    if self.debug:
+      print "Writing packet: %s" % repr(packet)
+    self._conn.write(str(packet))
+
+
+class DebugInterface(base.BaseInterface):
+  def __init__(self):
+    self.debug = True
+
+  def connect(self):
+    pass
+
+  def disconnect(self):
+    pass
+
+  def write(self, packet):
+    if self.debug:
+      print "Writing packet: %s" % repr(packet)
+

+ 18 - 0
alphasign/packet.py

@@ -0,0 +1,18 @@
+import constants
+
+
+class Packet(object):
+  def __init__(self, contents):
+    self.type     = "Z"            # Type Code (see protocol)
+    self.address  = "00"           # Sign Address (see protocol)
+    self._pkt = ("%s%s%s%s%s%s%s" %
+                 (constants.NUL * 5, constants.SOH, self.type,
+                  self.address, constants.STX, contents,
+                  constants.EOT))
+
+  def __str__(self):
+    return self._pkt
+
+  def __repr__(self):
+    return repr(self._pkt)
+

+ 62 - 0
alphasign/string.py

@@ -0,0 +1,62 @@
+import constants
+from packet import Packet
+
+
+class String(object):
+  def __init__(self, data=None, label=None, size=None):
+    if label is None:
+      label = "1"
+    if size is None:
+      size = 32
+    if len(data) > size:
+      size = len(data)
+    if size > 125:
+      size = 125
+    if size < 1:
+      size = 1
+    self.label = label
+    self.size = size
+    self.data = data
+
+  def allocate(self):
+    """Create a STRING.
+
+    This is necessary to allocate memory for the STRING on the sign
+
+    Args:
+      label: label of the STRING to create
+      size: size of the STRING to create, in bytes. 125 max.
+    """
+    size_hex = "%04x" % self.size
+    packet = Packet("%s%s%s%s%s%s%s%s%s%s%s%s%s" %
+                    (constants.WRITE_SPECIAL, "\$",
+                     "A",          # call label.. why does this matter?
+                     "A",          # text file type
+                     "U",          # this TEXT file is unlocked
+                     "0100",       # text file size in hex
+                     "FF",         # text file's start time (FF = always)
+                     "00",         # text file's stop time
+                     self.label,
+                     "B",          # string file type
+                     "L",          # this string file is locked
+                     size_hex,
+                     "0000"))      # padding
+    return packet
+
+  def call(self):
+    """Call a STRING.
+
+    This is for inserting a STRING file into a TEXT file.
+
+    Returns:
+      control code and specified string label
+    """
+    return "\x10%s" % self.label
+
+  def __str__(self):
+    return str(Packet("%s%s%s" % (constants.WRITE_STRING, self.label,
+                                  self.data)))
+
+  def __repr__(self):
+    return repr(self.__str__())
+

+ 98 - 0
alphasign/text.py

@@ -0,0 +1,98 @@
+import constants
+from packet import Packet
+
+
+class Text(object):
+  def __init__(self, msg=None, label=None, position=None, mode=None):
+    if label is None:
+      label = "A"
+    self.label = label
+    self.msg = msg
+    # TODO(ms): need support for position and mode
+
+  def __str__(self):
+    # [WRITE_TEXT][File Label][ESC][Display Position][Mode Code]
+    #   [Special Specifier][ASCII Message]
+    packet = Packet("%s%s%s%s%s%s" % (constants.WRITE_TEXT, self.label,
+                                      constants.ESC,
+                                      constants.positions["middle_line"],
+                                      constants.modes["rotate"],
+                                      self.msg))
+    return str(packet)
+
+  def __repr__(self):
+    return repr(self.__str__())
+
+
+def color(color="autocolor"):
+  """Returns color code for a specified color.
+
+  Args:
+    color: color string
+
+  Returns:
+    FIXME
+  """
+  if color not in constants.colors:
+    color = "autocolor"
+  return "%s%s" % ("\x1C", constants.colors[color])
+
+
+def charset(charset="five_high_std"):
+  """Returns control code for a specified character set.
+
+  Args:
+    charset: charset name string
+
+  Returns:
+    FIXME
+  """
+  if charset not in constants.charsets:
+    charset = "five_high_std"
+  return "%s%s" % ("\x1A", constants.charsets[charset])
+
+
+def extchar(extchar="left_arrow"):
+  """Returns control code for a specified extended character.
+
+  Args:
+    extchar: extended character name
+
+  Returns:
+    FIXME
+  """
+  if extchar not in constants.extchars:
+    extchar = "left_arrow"
+  return "%s%s" % ("\x08", constants.extchars[extchar])
+
+
+def spacing(option=0):
+  """Returns control code to set the character spacing.
+
+  Args:
+    option: 0 - set proportional characters
+            1 - fixed width left justified characters
+
+  Returns:
+    FIXME
+  """
+  byte = (option == 0) and "0" or "1"
+  return "\x1E%s" % byte
+
+
+def speed(speed):
+  """Set the speed of the scrolling text.
+
+  Args:
+    speed: integer 1 (slowest) through 5 (fastest) inclusive
+
+  Returns:
+    FIXME
+  """
+  if speed < 1:
+    speed = 1
+  elif speed > 5:
+    speed = 5
+
+  n = 20 + speed
+  return chr(n)

+ 51 - 0
alphasign/time.py

@@ -0,0 +1,51 @@
+import constants
+from packet import Packet
+
+
+class Time(object):
+  def call(self):
+    """Call time for insertion into a TEXT file.
+
+    Returns:
+      formatted string to use in a TEXT
+    """
+    return "\x13"
+
+  def set(self, hour=None, minute=None):
+    """Sets ths hour and minute of the internal clock on the sign.
+
+    If the time is not specified in the arguments, the time now will be used.
+
+    Args:
+      hour: hour in 24-hour format (18 instead of 6 for 6PM)
+      minute: minute (0 - 59)
+
+    Returns:
+      Packet object
+    """
+    now = datetime.datetime.today()
+    if hour is None:
+      hour = now.hour
+    if minute is None:
+      minute = now.minute
+
+    packet = Packet("%s%s%02d%02d" % (constants.WRITE_SPECIAL, "\x20",
+                                      hour, minute))
+    return packet
+
+  def set_format(self, format=1):
+    """Sets the time format on the sign.
+
+    Args:
+      format: 1 - 24-hour (military) time
+              0 - 12-hour (standard am/pm) format
+
+    Returns:
+      Packet object
+    """
+    if format < 0 or format > 1:
+      format = 1
+    byte = (format == 0) and "S" or "M"
+    packet = Packet("%s%s%s" % (constants.WRITE_SPECIAL, "\x27", byte))
+    return packet
+