Ejemplo n.º 1
0
    def go(self, argv):
        self.download_dir = ".airframe"
        self.get_options(argv)

        if self.local_dir:
            photo_filenames = self.local_dir_mode()
        elif self.facebook:
            photo_filenames = self.facebook_mode()
        else:
            photo_filenames = self.flickr_mode()

        if self.resize:
            self.resize_pictures(photo_filenames)

        self.flashair = FlashAir(self.flashair_ip)
        self.flashair.sync_files_on_card_to_list(photo_filenames, self.force_upload)
Ejemplo n.º 2
0
 def connectionMade(self):
     logger.info('Connected to serial port')
     self.accumulated = ''
     self.transport.setDTR(False)
     Sleep(1)
     self.transport.setDTR(True)
     self.waiton = dict()
     self.waiton = {"{State:Ready}" : self.initProjector1}
     self.sdCard = FlashAir()
     self.sdCard.disconnect()
     self.currentSlowSeq = None
     self.slowSeqInterval = 2
Ejemplo n.º 3
0
class SerialProtocol(LineOnlyReceiver):
    def connectionMade(self):
        logger.info('Connected to serial port')
        self.accumulated = ''
        self.transport.setDTR(False)
        Sleep(1)
        self.transport.setDTR(True)
        self.waiton = dict()
        self.waiton = {"{State:Ready}" : self.initProjector1}
        self.sdCard = FlashAir()
        self.sdCard.disconnect()
        self.currentSlowSeq = None
        self.slowSeqInterval = 2

    def connectionLost(self, reason):
        logger.info('Disconnected from serial port %s', reason)
        reactor.callFromThread(reactor.stop)

    def lineReceived(self, line):
        logger.debug('lineReceived %s, %d waiton entries' % (line, len(self.waiton)))
        self.accumulated += line
        for kk, vv in self.waiton.iteritems():
            if -1 != self.accumulated.find(kk):
                logger.debug("Triggered on %s", kk)
                self.accumulated = ''
                reactor.callLater(0, vv)

    def send(self, data):
        logger.debug("Sending: %s" % data)
        self.transport.write(data)

    def generator(self, sequence):
        ii = 0;
        if sequence is None:
            pdb.set_trace()
        try:
            for ll in sequence:
                ii += 1
                if None != ll.__doc__:
                    logger.debug('Generator executing %u:%s' % (ii, ll.__doc__))
                else:
                    logger.debug('Generator executing %u:%s' % (ii, ll.__name__))
                ll()
                yield

        except TypeError as tt:
            logger.error(tt.message)

        except RuntimeError as ee:
            logger.error("%s at generator step %u" % (ee.message, ii))
            raise

    def initProjector1(self):
        self.waiton.pop('{State:Ready}', None)
        logger.debug("initProjector1")
        self.waiton['{pt:'] = self.initProjector2

        sequence = [
            lambda: self.send(' '),
            lambda: self.send('vt')  # autotension
            ]
        self.slowSequence(sequence)

    def initProjector2(self):
        self.waiton.pop('{pt:}', None)
        logger.debug("initProjector2")

        def noMoreFrames(self):
            global exitcode
            exitcode = EX_TIMEOUT;
            self.transport.loseConnection();

        def setWaiton(self):
            self.waiton = dict()
            #self.waiton['{Remaining:0}'] = lambda: self.getFileInfo(last = False)
            self.waiton['{Remaining:0}'] = lambda: noMoreFrames(self)
            self.waiton['Opto int timeout'] = self.stopProjector

        sequence = [
            lambda: self.setSSInterval(2),
            lambda: self.send('c'),
            lambda: self.send({'8mm': 'd', 'super8': 'D'}[options.mode]),
            lambda: self.send("%so" % options.numframes),
            lambda: setWaiton(self),
            lambda: self.send('S'),
            ]
        self.slowSequence(sequence)

    def setSSInterval(self, interval):
        logger.debug("SlowSeq Interval %d" % interval)
        self.slowSeqInterval = interval

    def slowSequence(self, sequence = None):
        logger.debug("slowSequence, sequence is %s" % sequence)
        if sequence is not None:
            self.currentSlowSeq = sequence
            logger.debug("self.currentSlowSeq %s" % self.currentSlowSeq)
            self.ssIter = self.generator(sequence)

        if False == hasattr(self, 'ssIter') or self.ssIter is None:
            return

        try:
            next(self.ssIter)
            reactor.callLater(self.slowSeqInterval, self.slowSequence)

        except StopIteration:
            del self.ssIter
            del self.currentSlowSeq

        except RuntimeError as ee:
            del self.ssIter
            if 'restart' == ee.message and self.currentSlowSeq is not None:
                logger.info("Restarting sequence")
#                self.ssITer = self.generator(self.currentSlowSeq)
                reactor.callLater(2, lambda: self.slowSequence(self.currentSlowSeq))
            else:    
                pdb.set_trace()
            

    def stopProjector(self):
        reactor.callLater(0, lambda: self.getFileInfo(last = True))
#        self.waiton = dict()
#        logger.debug("Projector stopped")
#        sequence = [
#            lambda: self.send('c'),
#            lambda: self.send('s'),
#            lambda: reactor.callLater(0, lambda: self.getFileInfo(last = True))
#            ]
#        global exitCode
#        exitCode = EX_TIMEOUT
#        self.slowSequence(sequence)

#    def findSDFiles(self):
#        self.urls = self.sdCard.getFiles()
#        if False == self.urls:
#            logger.error("getFiles failed, aborting")
#            raise RuntimeError("getFiles")
#
#        if self.urls is None:
#            logger.info("No ready files yet")
#            raise RuntimeError("No ready files")

    def getFileInfo(self, last = False):
        logger.debug("getFileInfo")

        def testLast(self, last):
            if False == last:
                reactor.callLater(1, self.initProjector1)
            else:
                global exitCode
                exitCode = EX_TIMEOUT
                self.transport.loseConnection()

        self.slowSequence([
            lambda: self.setSSInterval(2),
            lambda: self.send('C'),
            lambda: self.send('c'),
            lambda: self.setSSInterval(5),
            self.sdCard.turnAirportOff,
            self.sdCard.turnAirportOn,
            lambda: self.setSSInterval(10),
            lambda: self.sdCard.waitingForAP(FlashAir.SSID),
            self.sdCard.connectToCard,
            self.sdCard.processFiles,
            lambda: self.setSSInterval(2),
            self.sdCard.clearCard,
            self.sdCard.disconnect,
            lambda: testLast(self, last)
            ])
Ejemplo n.º 4
0
class AirFrame(object):

    def __init__(self):
        pass

    def _parse_csv_list(self, s):
        try:
            assert isinstance(s,str)
            s = s.strip()
            value_list = s.split(',')
        except:
            raise argparse.ArgumentTypeError("Could not parse tag list")
        return value_list

    def get_options(self, argv):
        """
            Parse the command-line options and set the following object properties:

            I really need to convert this to use docopt!

            :param argv: usually just sys.argv[1:]
            :returns: Nothing

            :ivar debug: Enable logging debug statements
            :ivar verbose: Enable verbose logging
        """
        p = argparse.ArgumentParser(
                description = "Push pictures from Flickr, Facebook or local files to a Toshiba FlashAir automatically",
                epilog = "AirFrame version %s (Copyright 2014 Virantha Ekanayake)" % __version__,
                )

        p.add_argument('-b', '--facebook', action='store_true',
            default=False, help='Upload pictures from Flickr to Flashair')

        p.add_argument('-r', '--flickr', action='store_true',
            default=True, help='Upload pictures from Facebook to Flashair (default)')

        p.add_argument('-l', '--local-dir', type=str,
            help='Upload all .jpg files from this directory instead of Flickr or Facebook')
        
        p.add_argument('-s', '--resize', type=str,
            help='Resize all images to fit in this box (e.g. 1024x768) before uploading them to Flashair')

        p.add_argument('-d', '--debug', action='store_true',
            default=False, dest='debug', help='Turn on debugging')

        p.add_argument('-v', '--verbose', action='store_true',
            default=False, dest='verbose', help='Turn on verbose mode')

        p.add_argument('-f', '--force', action='store_true',
            default=False, help='Force upload of all pictures to Flashair (instead of only new pictures)')

        p.add_argument('-n', '--number', type=int,
            default=100, dest='number', help='Max number of photos to sync')

        p.add_argument('-t', '--tags', type=self._parse_csv_list,
                default=[], dest='tags', help='List of Flickr tags to match')

        p.add_argument('flashair_ip', type=str,
                        help='The ip/hostname of your FlashAir card')


        args = p.parse_args(argv)

        self.debug = args.debug
        self.verbose = args.verbose
        self.photo_count = args.number
        self.photo_tags = args.tags
        self.force_upload = args.force
        self.flashair_ip = args.flashair_ip
        self.local_dir = args.local_dir
        self.resize = args.resize
        self.facebook = args.facebook
        self.flickr = args.flickr

        if self.debug:
            logging.basicConfig(level=logging.DEBUG, format='%(message)s')

        if self.verbose:
            logging.basicConfig(level=logging.INFO, format='%(message)s')

    def flickr_mode(self):
        # Connect to Flickr
        logging.debug("list of tags: %s" % self.photo_tags)
        self.flickr = Flickr()
        if len(self.photo_tags) > 0:
            photo_filenames = self.flickr.get_tagged(self.photo_tags, self.photo_count, download_dir=self.download_dir)
        else:
            photo_filenames = self.flickr.get_recent(self.photo_count,download_dir=self.download_dir)
        return photo_filenames

    def facebook_mode(self):
        # Connect to Facebook
        logging.debug("list of tags: %s" % self.photo_tags)
        self.facebookphotos = FacebookPhotos()
#        if len(self.photo_tags) > 0:
#            photo_filenames = self.flickr.get_tagged(self.photo_tags, self.photo_count, download_dir=self.download_dir)
#        else:
#            photo_filenames = self.flickr.get_recent(self.photo_count,download_dir=self.download_dir)
        photo_filenames = self.facebookphotos.get_recent(self.photo_count,download_dir=self.download_dir)
        return photo_filenames

    def local_dir_mode(self):
        # Copy all the files in the named directory to the cache (download_dir).
        # completely replaces both the local cached files and the ones on the 
        # wifi sd card
        pattern = '/*.[jJ][pP][gG]'
        match = self.local_dir + pattern
        
        if os.path.isdir(self.download_dir):
            logging.debug("removing existing cache dir: %s", self.download_dir)
            shutil.rmtree(self.download_dir)
        
        os.mkdir(self.download_dir)
        logging.debug("caching files from: %s" % match)
        photo_filenames = glob.glob(match)
        for filename in photo_filenames:
            logging.debug("copy %s to %s" % (filename, self.download_dir))
            shutil.copy(filename, self.download_dir)
        return photo_filenames    

    def resize_pictures(self, photo_filenames):
        print 'Resizing images...'
        size = self.resize.split('x')
        size = [int(x) for x in tuple(size)]
        for infile in photo_filenames:
            im = Image.open(infile)
            if im.size[0] > size[0] or im.size[1] > size[1]:
                im.thumbnail(size, Image.ANTIALIAS)
                im.save(infile)
            im.close()


    def go(self, argv):
        self.download_dir = ".airframe"
        self.get_options(argv)

        if self.local_dir:
            photo_filenames = self.local_dir_mode()
        elif self.facebook:
            photo_filenames = self.facebook_mode()
        else:
            photo_filenames = self.flickr_mode()

        if self.resize:
            self.resize_pictures(photo_filenames)

        self.flashair = FlashAir(self.flashair_ip)
        self.flashair.sync_files_on_card_to_list(photo_filenames, self.force_upload)