Esempio n. 1
0
 def run(self):
     global errFlag, frames
     errFlag = False
     while not globals.exitFlag:  # mind you, this is the implementation coming straight from the firmware ;)
         # CHECKING FOR CONTROL MESSAGES
         if not globals.evt.is_set():
             globals.cxn1.write(globals.evtDefinition['message'])
             try:  # if a delay has been set, sleep for that length of time
                 sleep(globals.evtDefinition['delay'])
                 globals.evt.set()
             except:  # otherwise, do not resume until an external event happens which resets the event flag
                 globals.evt.wait()
         # STOP RUNNING SERIAL COMMANDS ON AN ERROR (TODO: make this more elegant)
         if errFlag:
             continue
         # WRITING THE MESSAGE ON THE BOARD
         for frame in frames:  # iterate through each frame of the "text animation"
             try:  # write the frame to the marquee
                 # TODO: This had to change recently
                 #       Join the chars in frame ahead of time to optimize this
                 globals.cxn1.write(''.join(
                     [chr(ord(char)) for char in frame]))
             except Exception as e:  # something unexpected happened
                 console.cwrite("Serial communication disconnected")
                 errFlag = True
                 break
             # Now just sleep for a wee bit before we go to the next character column
             sleep(globals.delay)
         # MESSAGE EXPIRATION
         console.cwrite("Updating messages...\n")
         updateMessages()
Esempio n. 2
0
def analyzeImage(path):
    im = Image.open(path)
    results = {
        'size': im.size,
        'mode': 'full',
        'framecount': 0,
    }
    try:
        #while True:
            print "Tile?", im.tile
            if im.tile:
                results['framecount'] += 1
                tile = im.tile[0]
                update_region = tile[1]
                update_region_dimensions = update_region[2:]
                if update_region_dimensions != im.size:
                    results['mode'] = 'partial'
                    return results
            #im.seek(im.tell() + 1)
            return results
    except EOFError:
        console.cwrite("Unexpected end of file in your GIF.  Your image does not conform to GIF 87a or 89a, or could be corrupt.")
        return
    except:
        console.cwrite("Unhandled exception while parsing GIF animation.")
        return
Esempio n. 3
0
def analyzeImage(path):
    im = Image.open(path)
    results = {
        'size': im.size,
        'mode': 'full',
        'framecount': 0,
    }
    try:
        #while True:
        print "Tile?", im.tile
        if im.tile:
            results['framecount'] += 1
            tile = im.tile[0]
            update_region = tile[1]
            update_region_dimensions = update_region[2:]
            if update_region_dimensions != im.size:
                results['mode'] = 'partial'
                return results
        #im.seek(im.tell() + 1)
        return results
    except EOFError:
        console.cwrite(
            "Unexpected end of file in your GIF.  Your image does not conform to GIF 87a or 89a, or could be corrupt."
        )
        return
    except:
        console.cwrite("Unhandled exception while parsing GIF animation.")
        return
Esempio n. 4
0
 def run(self):
     global errFlag, frames
     errFlag = False
     while not globals.exitFlag:  # mind you, this is the implementation coming straight from the firmware ;)
         # CHECKING FOR CONTROL MESSAGES
         if not globals.evt.is_set():
             globals.cxn1.write(globals.evtDefinition['message'])
             try:      # if a delay has been set, sleep for that length of time
                 sleep(globals.evtDefinition['delay'])
                 globals.evt.set()
             except:   # otherwise, do not resume until an external event happens which resets the event flag
                 globals.evt.wait()
         # STOP RUNNING SERIAL COMMANDS ON AN ERROR (TODO: make this more elegant)
         if errFlag:
             continue
         # WRITING THE MESSAGE ON THE BOARD
         for frame in frames:      # iterate through each frame of the "text animation"
             try:                  # write the frame to the marquee
                 # TODO: This had to change recently
                 #       Join the chars in frame ahead of time to optimize this
                 globals.cxn1.write(''.join([chr(ord(char)) for char in frame]))
             except Exception as e:               # something unexpected happened
                 console.cwrite("Serial communication disconnected")
                 errFlag = True
                 break
             # Now just sleep for a wee bit before we go to the next character column
             sleep(globals.delay)
         # MESSAGE EXPIRATION
         console.cwrite("Updating messages...\n")
         updateMessages()
Esempio n. 5
0
def makeMessageString(message):
    # TODO FIXME: Rows needs to be dynamic based on number of open COMs
    rows = 1
    # Initialize subMessage & serialMsg as empty arrays
    subMessage = len(globals.panelColors) * ['']
    serialMsg = len(globals.panelColors) * [None]
    # Find out which color we need to make the message in
    tree = ET.ElementTree(ET.fromstring(message))
    body = tree.find("body")
    # Iterate through each element in the html <body> tag
    for element in body.iter():
        # Parse out the <span style=' color=#{this is what we want};'>
        segmentColor = re.search(r'color\:\#([0-9a-fA-F]{6})', element.attrib['style'], flags=re.S)
        if segmentColor is None:
            continue    # the element was the <body> tag itself
        segmentColor = int(segmentColor.group(1), 16)
        # find out if the font color in the rich text box matches the deque whose color we're making now
        # Default red is 0xFF0000, default yellow is 0x808000, and default green is 0x008000.  Default blue would probably be 0x0000FF.
        # The point is the high bit is always set when the text is a default color.
        # The lower bits are only set if a special arrangement is desired -- e.g. 0x1F7C00 would be bottom 2 rows red, top 2 rows green, and middle rows yellow
        for i in range(0, len(globals.panelColors)):
            panelColor = globals.panelColors[i]
            if panelColor & segmentColor == panelColor:
                # "rich text" color is set to contain this panel's color completely (i.e. no special pattern)
                subMessage[i] += element.text
            else:  #if (panelColor & segmentColor == 0):
                # "rich text" color is not set to contain this panel's color at all
                subMessage[i] += " " * (element.text.__len__())
            #else:
                # this color is set for specific rows, not the whole matrix
            #    pass

    # Find out how many rows exist in the selected font & size
    rows = 1 # TODO FIXME: globals.font['LEDgoes Default Font']['size'][7]['weight'][4]['spacing']  It's not spacing, there should be a separate "height"
    # Make the message string from the letters, iterating over all colors
    for colorIdx in range(0, len(subMessage)):
        serialMsg[colorIdx] = [deque() for i in range(0, rows)]
        # Make that many rows of serialMsg
        for d in serialMsg[colorIdx]:
            # TODO: Allow an optional amount of padding before the message is shown
            d.extend(["\x00", "\x00", "\x00", "\x00", "\x00"])    # add padding to the left of the message
        for character in subMessage[colorIdx]:
            # Map the current letter to something that appears in the font
            for r in range(0, rows):
                try:
                    # Add the prescribed row of the prescribed character
                    serialMsg[colorIdx][r].extend( globals.font['LEDgoes Default Font']['size'][7]['weight'][4][character][r] )
                except KeyError:
                    serialMsg[colorIdx][r].extend(["\x00", "\x00", "\x00", "\x00", "\x00"])
                    console.cwrite("Character " + character + " unknown; substituting with whitespace")
            # Insert spacing between characters
            for r in range(0, rows):
                try:
                    # Add the prescribed spacing between characters for this font
                    serialMsg[colorIdx][r].extend(['\x00'] * globals.font['LEDgoes Default Font']['size'][7]['weight'][4]['spacing'])
                except:
                    # Tell the user there was a problem
                    console.cwrite("Character spacing is unknown for this font; assuming 0")
    return serialMsg
Esempio n. 6
0
 def __init__(self):
     # Carry out the rest of the "serial welcome" here by posting initial messages: default is "Awaiting Messages"
     updateMessages()
     # Start the thread
     super(serialThread, self).__init__()
     console.cwrite(
         "IO Thread is now running; when it stops may not necessarily be advertised..."
     )
Esempio n. 7
0
 def run(self):
     global desiredIndex
     while self.active:  # The user can toggle if this RSS feed is actively being read
         sleep(1)
         if not self.evt.is_set():
             # Get the feed, and massage it so we can parse it
             # TODO: use the user's desired quotes
             console.cwrite("Stock quote thread: Fetching quotes...")
             d = "dummy"
             try:
                 d = feedparser.parse(self.feedURL)
             except:
                 console.cwrite(
                     "There was an error in fetching the requested RSS document."
                 )
                 self.active = False
                 continue
             info = []
             feed = "<body>%s</body>" % d.entries[
                 0].summary_detail.value.replace("&nbsp;", "")
             tree = ET.ElementTree(ET.fromstring(feed))
             root = tree.getroot()
             # Find the last updated time
             last = root.find(".//table[@width='180']/tr/td")
             info.append("%s%s  %s" %
                         ((setColor % yellow), last.text.strip(), endColor))
             # Find all the quotes
             counter = 0
             for elem in root.findall(".//table[@width='200']"):
                 for elem2 in elem.findall(".//td"):
                     for text in elem2.itertext():
                         idx = counter % 13
                         if idx == 0:  # Ticker symbol
                             info.append(
                                 "%s%s " %
                                 ((setColor % yellow), text.strip()))
                         if idx == 3:  # Last trade
                             info.append("%s %s" % (text.strip(), endColor))
                         if idx == 5:  # Change sign
                             sign = text.strip()
                             info.append(
                                 "%s%s" %
                                 ((setColor %
                                   (green if sign == "+" else red)), sign))
                         if idx == 6:  # Change amount
                             info.append("%s %s" % (text.strip(), endColor))
                         counter += 1
             # We're done parsing, so join everything together
             newMessage = globals.html % ''.join(info)
             desiredIndex = globals.pushMsg("RSS-stocks",
                                            "This is the stock feed",
                                            newMessage, True, desiredIndex)
             self.evt.set()
     # After the while loop terminates, remove references to the event
     globals.asyncEvts.remove(self.evt)
Esempio n. 8
0
def twitterStream(properties):
    global twitterThread
    try:
        if twitterThread.isAlive():
            console.cwrite("Shutting down Twitter stream...")
            twitterEvt.clear()
            return False
        _twitterStart(properties)
        return True
    except:
        _twitterStart(properties)
        return True
Esempio n. 9
0
 def run(self):
     global desiredIndex
     while self.active:  # The user can toggle if this RSS feed is actively being read
         sleep(1)
         if not self.evt.is_set():
             # Get the feed, and massage it so we can parse it
             # TODO: use the user's desired quotes
             console.cwrite("Stock quote thread: Fetching quotes...")
             d = "dummy"
             try:
                 d = feedparser.parse(self.feedURL)
             except:
                 console.cwrite("There was an error in fetching the requested RSS document.")
                 self.active = False
                 continue
             info = []
             feed = "<body>%s</body>" % d.entries[0].summary_detail.value.replace("&nbsp;", "")
             tree = ET.ElementTree(ET.fromstring(feed))
             root = tree.getroot()
             # Find the last updated time
             last = root.find(".//table[@width='180']/tr/td")
             info.append("%s%s  %s" % ((setColor % yellow), last.text.strip(), endColor))
             # Find all the quotes
             counter = 0
             for elem in root.findall(".//table[@width='200']"):
                 for elem2 in elem.findall(".//td"):
                     for text in elem2.itertext():
                         idx = counter % 13
                         if idx == 0:  # Ticker symbol
                             info.append("%s%s " % ((setColor % yellow), text.strip()))
                         if idx == 3:  # Last trade
                             info.append("%s %s" % (text.strip(), endColor))
                         if idx == 5:  # Change sign
                             sign = text.strip()
                             info.append("%s%s" % ((setColor % (green if sign == "+" else red)), sign))
                         if idx == 6:  # Change amount
                             info.append("%s %s" % (text.strip(), endColor))
                         counter += 1
             # We're done parsing, so join everything together
             newMessage = globals.html % ''.join(info)
             desiredIndex = globals.pushMsg("RSS-stocks", "This is the stock feed", newMessage, True, desiredIndex)
             self.evt.set()
     # After the while loop terminates, remove references to the event
     globals.asyncEvts.remove(self.evt)
Esempio n. 10
0
 def __init__(self, tickerString):
     global desiredIndex
     # Find out if there is enough space in the message list to start this thread
     # Start the thread; call it active, and register the event
     super(stockThread, self).__init__()
     self.active = True
     self.evt = threading.Event()
     self.evt.set()
     globals.asyncEvts.append(self.evt)
     # TODO: Add an item to the main UI list to show that this is taking place
     # FIXME: For now, this will be Message #1
     stocks = re.split(" |,", tickerString)
     stocks = filter(None, stocks)
     if len(stocks) < 1:
         console.cwrite("You did not enter any valid ticker symbols.")
         return;
     self.feedURL = 'http://www.nasdaq.com/aspxcontent/NasdaqRSS.aspx?data=quotes&symbol=%s' % ("&symbol=".join(stocks))
     desiredIndex = globals.pushMsg("RSS-stocks", "This is the stock feed", globals.html % "Awaiting stock data...", True, desiredIndex)
     console.cwrite("Stock quote thread is now running...")
Esempio n. 11
0
def toggleQuotes(windowInstance):
    global stockInstance
    tickerString = windowInstance.ui.txtQuotes.toPlainText()
    if len(tickerString) == 0:
        console.cwrite("You must enter at least one ticker symbol in order to use this feature.")
        return
    # For now, treat this as a static class (one instance)
    # TODO: Make a mechanism to handle toggling multiple class instances
    # Initialize a new instance of the Nasdaq RSS feed
    if stockInstance is not None:
        stockInstance.active = False
        stockInstance.join()
        stockInstance = None
        console.cwrite("Stock quote thread terminated.")
        windowInstance.ui.btnGetQuotes.setText("Get Quotes")
    else:
        stockInstance = stockThread(tickerString)
        stockInstance.setDaemon(True)
        stockInstance.start()
        windowInstance.ui.btnGetQuotes.setText("Stop Quotes")
Esempio n. 12
0
def updateMessages():
    global frames
    # NOTE: This is where we used to print messages to the console.  If we want to do this again, put it here
    serialMsgRed = [
    ]  # array holds deques containing red pixel data for all messages
    serialMsgGreen = [
    ]  # array holds deques containing green pixel data for all messages
    # Ask any asynchronous calls to update their messages
    for evt in globals.asyncEvts:
        evt.clear()
    for evt in globals.asyncEvts:
        if not evt.wait(15):
            console.cwrite(
                "Timed out after waiting 15 seconds for a data provider before refreshing scrolling."
            )
    for msg in globals.richMsgs:
        # Fill the new data structures with pixel data
        [msgRed, msgGreen] = makeMessageString(msg)
        zipMessageString(msgRed, serialMsgRed)
        zipMessageString(msgGreen, serialMsgGreen)
        #zipMessageString(makeMessageStringFromFont(msg, "red"), serialMsgRed)
        #zipMessageString(makeMessageStringFromFont(msg, "green"), serialMsgGreen)
    # Make the frames
    frames.clear()
    for f in range(0, len(serialMsgRed[0])):
        frame = deque()
        # each board has an x & y assigned by the "marquee arrangement" UI; sort the boards by y first then x
        # this will help ensure a nice, smooth scrolling effect (assuming we aren't scrolling top-down)
        sortedBoards = sorted(globals.boards, key=itemgetter(0, 1))
        for b in sortedBoards:
            # b[0] := x with respect to the marquee; b[1] = y; b[2] = board index
            # b[0] + f := x with respect to the whole message
            # add the board address of the red chip and its data to the serial message
            x = b[0] * 5
            frame.extend(chr(int(b[2] + 128)))
            frame.extend(list(serialMsgRed[b[1]])[x + f:x + f + 5])
            # add the board address of the green chip and its data to the serial message
            frame.extend(chr(int(b[2] + 192)))
            frame.extend(list(serialMsgGreen[b[1]])[x + f:x + f + 5])
        # don't forget to add the completed work to the deque of frames :-P
        frames.append(frame)
Esempio n. 13
0
 def __init__(self, tickerString):
     global desiredIndex
     # Find out if there is enough space in the message list to start this thread
     # Start the thread; call it active, and register the event
     super(stockThread, self).__init__()
     self.active = True
     self.evt = threading.Event()
     self.evt.set()
     globals.asyncEvts.append(self.evt)
     # TODO: Add an item to the main UI list to show that this is taking place
     # FIXME: For now, this will be Message #1
     stocks = re.split(" |,", tickerString)
     stocks = filter(None, stocks)
     if len(stocks) < 1:
         console.cwrite("You did not enter any valid ticker symbols.")
         return
     self.feedURL = 'http://www.nasdaq.com/aspxcontent/NasdaqRSS.aspx?data=quotes&symbol=%s' % (
         "&symbol=".join(stocks))
     desiredIndex = globals.pushMsg("RSS-stocks", "This is the stock feed",
                                    globals.html % "Awaiting stock data...",
                                    True, desiredIndex)
     console.cwrite("Stock quote thread is now running...")
Esempio n. 14
0
def toggleQuotes(windowInstance):
    global stockInstance
    tickerString = windowInstance.ui.txtQuotes.toPlainText()
    if len(tickerString) == 0:
        console.cwrite(
            "You must enter at least one ticker symbol in order to use this feature."
        )
        return
    # For now, treat this as a static class (one instance)
    # TODO: Make a mechanism to handle toggling multiple class instances
    # Initialize a new instance of the Nasdaq RSS feed
    if stockInstance is not None:
        stockInstance.active = False
        stockInstance.join()
        stockInstance = None
        console.cwrite("Stock quote thread terminated.")
        windowInstance.ui.btnGetQuotes.setText("Get Quotes")
    else:
        stockInstance = stockThread(tickerString)
        stockInstance.setDaemon(True)
        stockInstance.start()
        windowInstance.ui.btnGetQuotes.setText("Stop Quotes")
Esempio n. 15
0
def zipMessageString(new, messages):
    # handle the special case if messages is empty
    if len(messages) == 0:
        for row in range(0, len(new)):
            messages.append(new[row])
        return
    # we did that because the first message would always look weird if higher rows always get shifted
    # here's the usual case:
    for row in range(0, len(new)):
        # for each row in the "new" messages,
        try:
            # extend the existing messages' row with the data from the new message
            messages[row].extend(new[row])
        except IndexError:
            # the row doesn't exist yet in the existing messages, so make it.
            try:
                # Pad it with \x00s so the letters will remain coherent if we have taller fonts than last time
                # Chances are that row 0 (the bottom) has been made already
                messages.append(deque(['\x00'] * len(messages[0])))
                messages.append(new[row])
            except IndexError:
                console.cwrite("There was a problem extending the message contents.")
Esempio n. 16
0
def pushMsg(source, rawMessage, richMessage, isSticky, desiredIndex=None):
    global richMsgs, msgLimit, msgToOverwrite, uiMsgList
    console.cwrite("Attempting to add message: " + rawMessage)
    console.cwrite(richMessage)
    # Count how many items exist in the list now
    msgList = uiMsgList.findItems('.*', Qt.MatchRegExp)
    if desiredIndex is None:
        if len(msgList) >= msgLimit:
            # We are at or above our message limit; find one to overwrite
            written = False    # Keep track of if we've successfully overwritten a message
            # Start with the message at index "msgToOverwrite", go to the end of the list, then restart at the beginning
            msgIndexes = range(msgToOverwrite, msgLimit) + range(0, msgToOverwrite)
            for index in msgIndexes:
                if not msgList[index].sticky:    # Do not overwrite sticky messages
                    formattedSource = "[%s]" % source
                    formattedSource = formattedSource + " sticky" if isSticky else formattedSource
                    msgList[index].setText("%s %s" % (formattedSource, rawMessage))
                    msgList[index].formattedText = richMessage
                    msgList[index].sticky = isSticky
                    msgToOverwrite = index + 1
                    written = True
                    break
            if not written:
                raise Exception("Could not overwrite any messages; they are all sticky")
        else:
            # We have not exceeded the maximum message count; add the message to the UI list
            RawTextItem(richMessage, source, isSticky, uiMsgList)
    else:
        # This is the same code as before
        formattedSource = "[%s]" % source
        formattedSource = formattedSource + " sticky" if isSticky else formattedSource
        msgList[desiredIndex].setText("%s %s" % (formattedSource, rawMessage))
        msgList[desiredIndex].formattedText = richMessage
        msgList[desiredIndex].sticky = isSticky

    # Reconstruct the global list by pulling out "formattedText" from the UI list objects
    richMsgs = [x.formattedText for x in uiMsgList.findItems('.*', Qt.MatchRegExp)]
    return len(uiMsgList.findItems('.*', Qt.MatchRegExp)) - 1
Esempio n. 17
0
def zipMessageString(new, messages):
    # handle the special case if messages is empty
    if len(messages) == 0:
        for row in range(0, len(new)):
            messages.append(new[row])
        return
    # we did that because the first message would always look weird if higher rows always get shifted
    # here's the usual case:
    for row in range(0, len(new)):
        # for each row in the "new" messages,
        try:
            # extend the existing messages' row with the data from the new message
            messages[row].extend(new[row])
        except IndexError:
            # the row doesn't exist yet in the existing messages, so make it.
            try:
                # Pad it with \x00s so the letters will remain coherent if we have taller fonts than last time
                # Chances are that row 0 (the bottom) has been made already
                messages.append(deque(['\x00'] * len(messages[0])))
                messages.append(new[row])
            except IndexError:
                console.cwrite(
                    "There was a problem extending the message contents.")
Esempio n. 18
0
def analyzeImage(path):
    im = Image.open(path)
    results = {"size": im.size, "mode": "full", "framecount": 0}
    try:
        while True:
            if im.tile:
                results["framecount"] += 1
                tile = im.tile[0]
                update_region = tile[1]
                update_region_dimensions = update_region[2:]
                if update_region_dimensions != im.size:
                    results["mode"] = "partial"
                    return results
            im.seek(im.tell() + 1)
        return results
    except EOFError:
        console.cwrite(
            "Unexpected end of file in your GIF.  Your image does not conform to GIF 87a or 89a, or could be corrupt."
        )
        return
    except:
        console.cwrite("Unhandled exception while parsing GIF animation.")
        return
Esempio n. 19
0
def updateMessages():
    global frames
    # NOTE: This is where we used to print messages to the console.  If we want to do this again, put it here
    serialMsgRed = []             # array holds deques containing red pixel data for all messages
    serialMsgGreen = []           # array holds deques containing green pixel data for all messages
    # Ask any asynchronous calls to update their messages
    for evt in globals.asyncEvts:
        evt.clear()
    for evt in globals.asyncEvts:
        if not evt.wait(15):
            console.cwrite("Timed out after waiting 15 seconds for a data provider before refreshing scrolling.")
    for msg in globals.richMsgs:
        # Fill the new data structures with pixel data
        [msgRed, msgGreen] = makeMessageString(msg)
        zipMessageString(msgRed, serialMsgRed)
        zipMessageString(msgGreen, serialMsgGreen)
        #zipMessageString(makeMessageStringFromFont(msg, "red"), serialMsgRed)
        #zipMessageString(makeMessageStringFromFont(msg, "green"), serialMsgGreen)
    # Make the frames
    frames.clear()
    for f in range(0, len(serialMsgRed[0])):
        frame = deque()
        # each board has an x & y assigned by the "marquee arrangement" UI; sort the boards by y first then x
        # this will help ensure a nice, smooth scrolling effect (assuming we aren't scrolling top-down)
        sortedBoards = sorted(globals.boards, key=itemgetter(0, 1))
        for b in sortedBoards:
            # b[0] := x with respect to the marquee; b[1] = y; b[2] = board index
            # b[0] + f := x with respect to the whole message
            # add the board address of the red chip and its data to the serial message
            x = b[0] * 5
            frame.extend( chr(int(b[2] + 128)) )
            frame.extend(list( serialMsgRed[b[1]] )[ x + f : x + f + 5 ] )
            # add the board address of the green chip and its data to the serial message
            frame.extend( chr(int(b[2] + 192)) )
            frame.extend(list( serialMsgGreen[b[1]] )[ x + f : x + f + 5 ])
        # don't forget to add the completed work to the deque of frames :-P
        frames.append(frame)
Esempio n. 20
0
    def run(self):
        currentCel = 0
        redChannel = globals.animTuple[0]
        try:
            greenChannel = globals.animTuple[1]
        except:
            greenChannel = redChannel
        celWidth = globals.animTuple[2]
        maxCel = len(redChannel) / celWidth

        # Find out a little bit more about the frames & bands present
        console.cwrite("Num bands: %d" % len(globals.animTuple))
        totCols = len(
            redChannel
        )  # The deque stores each frame continuously along the x axis
        console.cwrite("Total # of columns: %d" % totCols)
        boardRows = len(
            redChannel[0])  # Number of rows of boards in the animation
        console.cwrite("Height in boards: %d" % boardRows)
        while not globals.exitFlag:  # mind you, this is the implementation coming straight from the firmware ;)
            # CHECKING FOR CONTROL MESSAGES
            if not globals.evt.is_set():
                globals.cxn1.write(globals.evtDefinition['message'])
                try:  # if a delay has been set, sleep for that length of time
                    sleep(globals.evtDefinition['delay'])
                    globals.evt.set()
                except:  # otherwise, do not resume until an external event happens which resets the event flag
                    globals.evt.wait()
            # WRITING THE MESSAGE ON THE BOARD
            #print "Frame", currentCel, " Boards:",
            celOffset = currentCel * celWidth
            for board in globals.boards:
                #print board[2],
                rPart = chr(board[2] | 0x80)
                gPart = chr(board[2] | 0xC0)
                boardLeft = board[0] * 5
                myRange = range(boardLeft, boardLeft + 5)
                row = board[1]
                for col in myRange:
                    try:
                        rPart += chr(redChannel[celOffset + col][row])
                    except IndexError:
                        rPart += '\x00'
                    try:
                        gPart += chr(greenChannel[celOffset + col][row])
                    except IndexError:
                        gPart += '\x00'
                #print "rPart", repr(rPart),
                #print "gPart", repr(gPart)
                globals.cxn1.write(rPart)
                globals.cxn1.write(gPart)
            #print " "
            # GOING TO THE NEXT FRAME
            currentCel = (currentCel + 1) % maxCel
            sleep(globals.delay)
Esempio n. 21
0
 def run(self):
     currentCel = 0;
     redChannel = globals.animTuple[0]
     try:
         greenChannel = globals.animTuple[1]
     except:
         greenChannel = redChannel
     celWidth = globals.animTuple[2]
     maxCel = len(redChannel) / celWidth
     
     # Find out a little bit more about the frames & bands present
     console.cwrite("Num bands: %d" % len(globals.animTuple))
     totCols = len(redChannel)          # The deque stores each frame continuously along the x axis
     console.cwrite("Total # of columns: %d" % totCols)
     boardRows = len(redChannel[0])     # Number of rows of boards in the animation
     console.cwrite("Height in boards: %d" % boardRows)
     while not globals.exitFlag:  # mind you, this is the implementation coming straight from the firmware ;)
         # CHECKING FOR CONTROL MESSAGES
         if not globals.evt.is_set():
             globals.cxn1.write(globals.evtDefinition['message'])
             try:      # if a delay has been set, sleep for that length of time
                 sleep(globals.evtDefinition['delay'])
                 globals.evt.set()
             except:   # otherwise, do not resume until an external event happens which resets the event flag
                 globals.evt.wait()
         # WRITING THE MESSAGE ON THE BOARD
         #print "Frame", currentCel, " Boards:",
         celOffset = currentCel * celWidth
         for board in globals.boards:
             #print board[2],
             rPart = chr(board[2] | 0x80)
             gPart = chr(board[2] | 0xC0)
             boardLeft = board[0] * 5
             myRange = range(boardLeft, boardLeft + 5)
             row = board[1]
             for col in myRange:
                 try:
                     rPart += chr(redChannel[celOffset + col][row])
                 except IndexError:
                     rPart += '\x00'
                 try:
                     gPart += chr(greenChannel[celOffset + col][row])
                 except IndexError:
                     gPart += '\x00'
             #print "rPart", repr(rPart),
             #print "gPart", repr(gPart)
             globals.cxn1.write(rPart)
             globals.cxn1.write(gPart)
         #print " "
         # GOING TO THE NEXT FRAME
         currentCel = (currentCel + 1) % maxCel
         sleep(globals.delay)
Esempio n. 22
0
 def run(self):
     global twitterApi, twitterProperties, twitterEvt
     maxTweets = 10
     curIndex = 0
     for item in twitterApi.GetStreamFilter(track=[twitterProperties]):
         if item.has_key('text'):
             try:
                 # Output all Tweets including language
                 console.cwrite("===== %s " % item['lang'])
                 console.cwrite(item['text'])
                 # Display only English tweets (change as you see fit)
                 if item['lang'] == "en":
                     rawTweetText = '@%s %s' % (item['user']['screen_name'], item['text'])
                     formattedTweetText = '<span style=" color:#ff0000;">@%s </span><span style=" color:#808000;">%s</span>' % (item['user']['screen_name'], item['text'])
                     globals.pushMsg("twitter", rawTweetText, globals.html % formattedTweetText, False)
             except Exception as ex:
                 console.cwrite(ex)
         if not twitterEvt.is_set():
             console.cwrite("Twitter stream shut down!")
             twitterEvt.set()
             return
Esempio n. 23
0
def makeMessageString(message):
    # TODO FIXME: Rows needs to be dynamic based on number of open COMs
    rows = 1
    # Initialize subMessage & serialMsg as empty arrays
    subMessage = len(globals.panelColors) * ['']
    serialMsg = len(globals.panelColors) * [None]
    # Find out which color we need to make the message in
    tree = ET.ElementTree(ET.fromstring(message))
    body = tree.find("body")
    # Iterate through each element in the html <body> tag
    for element in body.iter():
        # Parse out the <span style=' color=#{this is what we want};'>
        segmentColor = re.search(r'color\:\#([0-9a-fA-F]{6})',
                                 element.attrib['style'],
                                 flags=re.S)
        if segmentColor is None:
            continue  # the element was the <body> tag itself
        segmentColor = int(segmentColor.group(1), 16)
        # find out if the font color in the rich text box matches the deque whose color we're making now
        # Default red is 0xFF0000, default yellow is 0x808000, and default green is 0x008000.  Default blue would probably be 0x0000FF.
        # The point is the high bit is always set when the text is a default color.
        # The lower bits are only set if a special arrangement is desired -- e.g. 0x1F7C00 would be bottom 2 rows red, top 2 rows green, and middle rows yellow
        for i in range(0, len(globals.panelColors)):
            panelColor = globals.panelColors[i]
            if panelColor & segmentColor == panelColor:
                # "rich text" color is set to contain this panel's color completely (i.e. no special pattern)
                subMessage[i] += element.text
            else:  #if (panelColor & segmentColor == 0):
                # "rich text" color is not set to contain this panel's color at all
                subMessage[i] += " " * (element.text.__len__())
            #else:
            # this color is set for specific rows, not the whole matrix
            #    pass

    # Find out how many rows exist in the selected font & size
    rows = 1  # TODO FIXME: globals.font['LEDgoes Default Font']['size'][7]['weight'][4]['spacing']  It's not spacing, there should be a separate "height"
    # Make the message string from the letters, iterating over all colors
    for colorIdx in range(0, len(subMessage)):
        serialMsg[colorIdx] = [deque() for i in range(0, rows)]
        # Make that many rows of serialMsg
        for d in serialMsg[colorIdx]:
            # TODO: Allow an optional amount of padding before the message is shown
            d.extend(["\x00", "\x00", "\x00", "\x00",
                      "\x00"])  # add padding to the left of the message
        for character in subMessage[colorIdx]:
            # Map the current letter to something that appears in the font
            for r in range(0, rows):
                try:
                    # Add the prescribed row of the prescribed character
                    serialMsg[colorIdx][r].extend(
                        globals.font['LEDgoes Default Font']['size'][7]
                        ['weight'][4][character][r])
                except KeyError:
                    serialMsg[colorIdx][r].extend(
                        ["\x00", "\x00", "\x00", "\x00", "\x00"])
                    console.cwrite("Character " + character +
                                   " unknown; substituting with whitespace")
            # Insert spacing between characters
            for r in range(0, rows):
                try:
                    # Add the prescribed spacing between characters for this font
                    serialMsg[colorIdx][r].extend(
                        ['\x00'] * globals.font['LEDgoes Default Font']['size']
                        [7]['weight'][4]['spacing'])
                except:
                    # Tell the user there was a problem
                    console.cwrite(
                        "Character spacing is unknown for this font; assuming 0"
                    )
    return serialMsg
Esempio n. 24
0
def processImage(path, results):
    console.cwrite("Incoming results: %s" % results)
    size = results['size']
    mode = results['mode']
    # Open the image
    im = Image.open(path)
    # Convert to RGBA so we can do mathematical processing easier
    last_frame = im.convert('RGBA')

    # Iterate through the entire gif
    redFrames = deque()  # collective red data
    greenFrames = deque()  # collective green data
    # Each "frame" will have a series of rows, and each row contains the data of 0-127 or 0-255
    try:
        while 1:
            console.cwrite("Analyzing frame %d" % im.tell())
            # make a couple new frames
            # size[0] = width, size[1] = height
            rowsOfBoards = int(
                math.ceil(1.0 * results['size'][1] / globals.rowPixels))
            redFrame = [[0 for i in range(rowsOfBoards)]
                        for j in range(results['size'][0])]
            greenFrame = [[0 for i in range(rowsOfBoards)]
                          for j in range(results['size'][0])]
            # Apply the global palette to the frame, if necessary
            if not im.getpalette():
                im.putpalette(p)
            # Store this frame in memory
            new_frame = Image.new('RGBA', im.size)
            # Apply the current "partial" frame to the last frame if this is a partial-mode GIF
            if mode == 'partial':
                new_frame.paste(last_frame)
            # Paste the current frame of the GIF onto the blank canvas
            new_frame.paste(im, (0, 0), im.convert('RGBA'))
            # Run analysis on each band of each pixel to decide if it should be illuminated
            bands = Image.eval(new_frame, doThreshold)
            # This makes a list of tuples containing the results: 4 channels, 1 if illuminated, 0 if not
            colorPresent = list(bands.getdata())

            board = 0  # which row of boards we're concerned with
            yOnBoard = 0  # which row we're accessing w.r.t. the current board
            # along the x axis of the image...
            for x in range(0, new_frame.size[0]):
                # Reset variables
                yOnBoard = 0
                board = 0
                # Add the image data to the redRow & greenRow deques from along the y axis
                #print redFrame, greenFrame
                for y in range(new_frame.size[1] - 1, -1, -1):
                    pix = (y * new_frame.size[0]) + x
                    # Red band
                    if colorPresent[pix][0] == 1:
                        redFrame[x][board] |= (1 << yOnBoard)
                    # Green band
                    if colorPresent[pix][1] == 1:
                        greenFrame[x][board] |= (1 << yOnBoard)
                    # If we cared about the blue band, we would call on colorPresent[pix][2]
                    yOnBoard += 1
                    if yOnBoard >= globals.rowPixels:
                        yOnBoard = 0
                        board += 1

            # Add the converted frames to the respective deques
            redFrames.extend(redFrame)
            greenFrames.extend(greenFrame)
            #print redFrame, greenFrame
            # Go on to the next frame
            last_frame = new_frame
            im.seek(im.tell() + 1)
    except EOFError:
        # return a tuple containing the deques of redFrames & greenFrames, plus the GIF size
        console.cwrite("Final length: %d * %d" %
                       (len(redFrames), len(greenFrames)))
        return (redFrames, greenFrames, size[0], size[1])
Esempio n. 25
0
def _twitterStart(properties):
    global twitterThread, twitterProperties
    console.cwrite("Starting Twitter stream with properties %s" % properties)
    twitterProperties = properties
    twitterThread = twitterStreamThread()
    twitterThread.start()
Esempio n. 26
0
 def __init__(self):
     super(animationThread, self).__init__()
     console.cwrite(
         "Animation thread is now running; when it stops may not necessarily be advertised..."
     )
Esempio n. 27
0
def processImage(path, results):
    console.cwrite("Incoming results: %s" % results)
    size = results['size']
    mode = results['mode']
    # Open the image
    im = Image.open(path)
    # Convert to RGBA so we can do mathematical processing easier
    last_frame = im.convert('RGBA')

    # Iterate through the entire gif
    redFrames = deque()     # collective red data
    greenFrames = deque()   # collective green data
    # Each "frame" will have a series of rows, and each row contains the data of 0-127 or 0-255
    try:
        while 1:
            console.cwrite("Analyzing frame %d" % im.tell())
            # make a couple new frames
            # size[0] = width, size[1] = height
            rowsOfBoards = int(math.ceil(1.0 * results['size'][1] / globals.rowPixels))
            redFrame = [ [ 0 for i in range(rowsOfBoards) ] for j in range(results['size'][0]) ]
            greenFrame = [ [ 0 for i in range(rowsOfBoards) ] for j in range(results['size'][0]) ]
            # Apply the global palette to the frame, if necessary
            if not im.getpalette():
                im.putpalette(p)
            # Store this frame in memory
            new_frame = Image.new('RGBA', im.size)
            # Apply the current "partial" frame to the last frame if this is a partial-mode GIF
            if mode == 'partial':
                new_frame.paste(last_frame)
            # Paste the current frame of the GIF onto the blank canvas
            new_frame.paste(im, (0,0), im.convert('RGBA'))
            # Run analysis on each band of each pixel to decide if it should be illuminated
            bands = Image.eval(new_frame, doThreshold)
            # This makes a list of tuples containing the results: 4 channels, 1 if illuminated, 0 if not
            colorPresent = list(bands.getdata())
            
            board = 0          # which row of boards we're concerned with
            yOnBoard = 0       # which row we're accessing w.r.t. the current board
            # along the x axis of the image...
            for x in range(0, new_frame.size[0]):
                # Reset variables
                yOnBoard = 0
                board = 0
                # Add the image data to the redRow & greenRow deques from along the y axis
                #print redFrame, greenFrame
                for y in range(new_frame.size[1] - 1, -1, -1):
                    pix = (y * new_frame.size[0]) + x
                    # Red band
                    if colorPresent[pix][0] == 1:
                        redFrame[x][board] |= (1 << yOnBoard)
                    # Green band
                    if colorPresent[pix][1] == 1:
                        greenFrame[x][board] |= (1 << yOnBoard)
                    # If we cared about the blue band, we would call on colorPresent[pix][2]
                    yOnBoard += 1
                    if yOnBoard >= globals.rowPixels:
                        yOnBoard = 0
                        board += 1

            # Add the converted frames to the respective deques
            redFrames.extend(redFrame)
            greenFrames.extend(greenFrame)
            #print redFrame, greenFrame
            # Go on to the next frame
            last_frame = new_frame
            im.seek(im.tell()+1)
    except EOFError:
        # return a tuple containing the deques of redFrames & greenFrames, plus the GIF size
        console.cwrite("Final length: %d * %d" % (len(redFrames), len(greenFrames)))
        return (redFrames, greenFrames, size[0], size[1])
Esempio n. 28
0
 def __init__(self):
     # Carry out the rest of the "serial welcome" here by posting initial messages: default is "Awaiting Messages"
     updateMessages()
     # Start the thread
     super(serialThread, self).__init__()
     console.cwrite("IO Thread is now running; when it stops may not necessarily be advertised...")
Esempio n. 29
0
 def __init__(self):
     super(twitterStreamThread, self).__init__()
     console.cwrite("Twitter thread is now running; when it stops may not necessarily be advertised...")
Esempio n. 30
0
 def __init__(self):
     super(animationThread, self).__init__()
     console.cwrite("Animation thread is now running; when it stops may not necessarily be advertised...")