123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337 |
- #!/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)
|