def __init__(self, side='L',*, mode=NORMAL, model=EMBEDDED_ARTISTS, use_flash=False, up_time=None):
        self.flash = None                       # Assume flash is unused
        self.in_context = False
        try:
            intside = {'l':0, 'r':1}[side.lower()]
        except (KeyError, AttributeError):
            raise ValueError("Side must be 'L' or 'R'")
        if model not in (EMBEDDED_ARTISTS, ADAFRUIT):
            raise ValueError('Unsupported model')
        if mode == FAST and use_flash:
            raise ValueError('Flash memory unavailable in fast mode')
        if mode == NORMAL and up_time is not None:
            raise ValueError('Cannot set up_time in normal mode')
        if mode == NORMAL:
            from epd import EPD
            self.epd = EPD(intside, model)
        elif mode == FAST:
            from epdpart import EPD
            self.epd = EPD(intside, model, up_time)
        else:
            raise ValueError('Unsupported mode {}'.format(mode))
        self.mode = mode
        self.font = Font()
        gc.collect()
        self.locate(0, 0)                       # Text cursor: default top left

        self.mounted = False                    # umountflash() not to sync
        if use_flash:
            from flash import FlashClass
            self.flash = FlashClass(intside)
            self.umountflash()                  # In case mounted by prior tests.
            self.mountflash()
        gc.collect()
Beispiel #2
0
    def __init__(self, side='L',*, mode=NORMAL, model=EMBEDDED_ARTISTS, use_flash=False, up_time=None):
        self.flash = None                       # Assume flash is unused
        self.in_context = False
        try:
            intside = {'l':0, 'r':1}[side.lower()]
        except (KeyError, AttributeError):
            raise ValueError("Side must be 'L' or 'R'")
        if model not in (EMBEDDED_ARTISTS, ADAFRUIT):
            raise ValueError('Unsupported model')
        if mode == FAST and use_flash:
            raise ValueError('Flash memory unavailable in fast mode')
        if mode == NORMAL and up_time is not None:
            raise ValueError('Cannot set up_time in normal mode')
        if mode == NORMAL:
            from epd import EPD
            self.epd = EPD(intside, model)
        elif mode == FAST:
            from epdpart import EPD
            self.epd = EPD(intside, model, up_time)
        else:
            raise ValueError('Unsupported mode {}'.format(mode))
        self.mode = mode
        self.font = Font()
        gc.collect()
        self.locate(0, 0)                       # Text cursor: default top left

        self.mounted = False                    # umountflash() not to sync
        if use_flash:
            from flash import FlashClass
            gc.collect()
            self.flash = FlashClass(intside)
            self.umountflash()                  # In case mounted by prior tests.
            self.mountflash()
        gc.collect()
Beispiel #3
0
    def __init__(self, debug=False):
        self.cfg = None
        self.rtc = RTC()
        self.debug = debug
        self.battery = Battery()

        # use this pin for debug
        self.wifi_pin = Pin("GP24", mode=Pin.IN, pull=Pin.PULL_UP)

        # Empty WDT object
        self.wdt = None

        if not debug:
            if not self.wifi_pin():
                self.wdt = WDT(timeout=20000)
            self.sd = None
        else:
            from machine import SD
            try:
                self.sd = SD()
                mount(self.sd, '/sd')
                self.logfile = open("/sd/display.log", "a")
            except OSError:
                self.sd = None
                self.logfile = None

        self.epd = EPD()

        self.log("Time left on the alarm: %dms" % self.rtc.alarm_left())

        # Don't flash when we're awake outside of debug
        heartbeat(self.debug)
Beispiel #4
0
    def __init__(self, side = 'L', use_flash = False, pwr_controller = None):
        self.flash = None                       # Assume flash is unused
        try:
            self.intside = {'x':1, 'X':1, 'y':0,'Y':0, 'l':0, 'L':0, 'r':1, 'R':1}[side]
        except KeyError:
            raise ValueError("Side must be 'L' or 'R'")
        self.pwr_controller = pwr_controller

        self.epd = EPD(self.intside, pwr_controller)
        self.font = Font()
        self.locate(0, 0)                       # Text cursor: default top left

        self.mounted = False                    # umountflash() not to sync
        if use_flash:
            from flash import FlashClass
            self.flash = FlashClass(self.intside, pwr_controller)
            self.umountflash()                  # In case mounted by prior tests.
            if self.pwr_controller is None:     # Normal operation: flash is mounted continuously
                self.mountflash()
Beispiel #5
0
def update_loop(url, interval=0, port=80):
    """
    Download image, update display, sleep, loop.
    Gives up on any error
    :param url:
    :param interval:
    :param port:
    :return:
    """
    e = EPD()
    e.enable()
    sep = url.find('/')
    host = url[:sep]
    path = url[sep:]

    del sep
    while True:
        print("Mem free: %d" % gc.mem_free())

        c = Connect(host, port, debug=True)

        content = c.get_quick(path)

        print("Uploading...", end='')
        e.upload_whole_image(content)

        print("done.")
        e.display_update()
        del content
        del c

        if interval > 0:
            to_sleep = interval
            print("Sleeping for %ds" % interval, end='')
            time.sleep(to_sleep)
            print('.')
        else:
            input("Press enter to update (Ctrl-C to stop).")

        gc.collect()
Beispiel #6
0
class Display(object):
    FONT_HEADER_LENGTH = 4
    def __init__(self, side='L',*, mode=NORMAL, model=EMBEDDED_ARTISTS, use_flash=False, up_time=None):
        self.flash = None                       # Assume flash is unused
        self.in_context = False
        try:
            intside = {'l':0, 'r':1}[side.lower()]
        except (KeyError, AttributeError):
            raise ValueError("Side must be 'L' or 'R'")
        if model not in (EMBEDDED_ARTISTS, ADAFRUIT):
            raise ValueError('Unsupported model')
        if mode == FAST and use_flash:
            raise ValueError('Flash memory unavailable in fast mode')
        if mode == NORMAL and up_time is not None:
            raise ValueError('Cannot set up_time in normal mode')
        if mode == NORMAL:
            from epd import EPD
            self.epd = EPD(intside, model)
        elif mode == FAST:
            from epdpart import EPD
            self.epd = EPD(intside, model, up_time)
        else:
            raise ValueError('Unsupported mode {}'.format(mode))
        self.mode = mode
        self.font = Font()
        gc.collect()
        self.locate(0, 0)                       # Text cursor: default top left

        self.mounted = False                    # umountflash() not to sync
        if use_flash:
            from flash import FlashClass
            gc.collect()
            self.flash = FlashClass(intside)
            self.umountflash()                  # In case mounted by prior tests.
            self.mountflash()
        gc.collect()

    def checkcm(self):
        if not (self.mode == NORMAL or self.in_context):
            raise EPDError('Fast mode must be run using a context manager')

    def __enter__(self):                        # Power up
        checkstate(self.mode == FAST, "In normal mode, can't use context manager")
        self.in_context = True
        self.epd.enter()
        return self

    def __exit__(self, *_):                     # shut down
        self.in_context = False
        self.epd.exit()
        pass

    def mountflash(self):
        if self.flash is None:                  # Not being used
            return
        self.flash.begin()                      # Initialise.
        vfs = uos.VfsFat(self.flash)  # Instantiate FAT filesystem
        uos.mount(vfs, self.flash.mountpoint)
        self.mounted = True

    def umountflash(self):                      # Unmount flash
        if self.flash is None:
            return
        if self.mounted:
            self.flash.synchronise()
        try:
            uos.umount(self.flash.mountpoint)
        except OSError:
            pass                                # Don't care if it wasn't mounted
        self.flash.end()                        # Shut down
        self.mounted = False                    # flag unmounted to prevent spurious syncs

    def show(self):
        self.checkcm()
        self.umountflash()                      # sync, umount flash, shut it down and disable SPI
        if self.mode == NORMAL:                 # EPD functions which access the display electronics must be
            with self.epd as epd:               # called from a with block to ensure proper startup & shutdown
                epd.showdata()
        else:                                   # Fast mode: already in context manager
            self.epd.showdata()
        self.mountflash()

    def clear_screen(self, show=True):
        self.checkcm()
        self.locate(0, 0)                       # Reset text cursor
        self.epd.clear_data()
        if show:
            if self.mode == NORMAL:
                self.show()
            else:
                self.epd.EPD_clear()

    def refresh(self, fast =True):              # Fast mode only functions
        checkstate(self.mode == FAST, 'refresh() invalid in normal mode')
        self.checkcm()
        self.epd.refresh(fast)

    def exchange(self, clear_data):
        checkstate(self.mode == FAST, 'exchange() invalid in normal mode')
        self.checkcm()
        self.epd.exchange(clear_data)

    @property
    def temperature(self):                      # return temperature as integer in Celsius
        return self.epd.temperature

    @property
    def location(self):
        return self.char_x, self.char_y

    @micropython.native
    def setpixel(self, x, y, black):            # 41uS. Clips to borders. x, y must be integer
        if y < 0 or y >= LINES_PER_DISPLAY or x < 0 or x >= BITS_PER_LINE :
            return
        image = self.epd.image
        omask = 1 << (x & 0x07)
        index = (x >> 3) + y *BYTES_PER_LINE
        if black:
            image[index] |= omask
        else:
            image[index] &= (omask ^ 0xff)

    @micropython.viper
    def setpixelfast(self, x: int, y: int, black: int): # 27uS. Caller checks bounds
        image = ptr8(self.epd.image)
        omask = 1 << (x & 0x07)
        index = (x >> 3) + y * 33 #BYTES_PER_LINE
        if black:
            image[index] |= omask
        else:
            image[index] &= (omask ^ 0xff)

# ****** Simple graphics support ******

    def _line(self, x0, y0, x1, y1, black = True): # Sinle pixel line
        dx = x1 -x0
        dy = y1 -y0
        dx_sym = 1 if dx > 0 else -1
        dy_sym = 1 if dy > 0 else -1

        dx = dx_sym*dx
        dy = dy_sym*dy
        dx_x2 = dx*2
        dy_x2 = dy*2
        if (dx >= dy):
            di = dy_x2 - dx
            while (x0 != x1):
                self.setpixel(x0, y0, black)
                x0 += dx_sym
                if (di<0):
                    di += dy_x2
                else :
                    di += dy_x2 - dx_x2
                    y0 += dy_sym
            self.setpixel(x0, y0, black)
        else:
            di = dx_x2 - dy
            while (y0 != y1):
                self.setpixel(x0, y0, black)
                y0 += dy_sym
                if (di < 0):
                    di += dx_x2
                else:
                    di += dx_x2 - dy_x2
                    x0 += dx_sym
            self.setpixel(x0, y0, black)

    def line(self, x0, y0, x1, y1, width =1, black = True): # Draw line
        x0, y0, x1, y1 = int(x0), int(y0), int(x1), int(y1)
        if abs(x1 - x0) > abs(y1 - y0): # < 45 degrees
            for w in range(-width//2 +1, width//2 +1):
                self._line(x0, y0 +w, x1, y1 +w, black)
        else:
            for w in range(-width//2 +1, width//2 +1):
                self._line(x0 +w, y0, x1 +w, y1, black)

    def _rect(self, x0, y0, x1, y1, black): # Draw rectangle
        self.line(x0, y0, x1, y0, 1, black)
        self.line(x0, y0, x0, y1, 1, black)
        self.line(x0, y1, x1, y1, 1, black)
        self.line(x1, y0, x1, y1, 1, black)

    def rect(self, x0, y0, x1, y1, width =1, black = True): # Draw rectangle
        x0, y0, x1, y1 = int(x0), int(y0), int(x1), int(y1)
        x0, x1 = (x0, x1) if x1 > x0 else (x1, x0) # x0, y0 is top left, x1, y1 is bottom right
        y0, y1 = (y0, y1) if y1 > y0 else (y1, y0)
        for w in range(width):
            self._rect(x0 +w, y0 +w, x1 -w, y1 -w, black)

    def fillrect(self, x0, y0, x1, y1, black = True): # Draw filled rectangle
        x0, y0, x1, y1 = int(x0), int(y0), int(x1), int(y1)
        x0, x1 = (x0, x1) if x1 > x0 else (x1, x0)
        y0, y1 = (y0, y1) if y1 > y0 else (y1, y0)
        for x in range(x0, x1):
            for y in range(y0, y1):
                self.setpixel(x, y, black)

    def _circle(self, x0, y0, r, black = True): # Single pixel circle
        x = -r
        y = 0
        err = 2 -2*r
        while x <= 0:
            self.setpixel(x0 -x, y0 +y, black)
            self.setpixel(x0 +x, y0 +y, black)
            self.setpixel(x0 +x, y0 -y, black)
            self.setpixel(x0 -x, y0 -y, black)
            e2 = err
            if (e2 <= y):
                y += 1
                err += y*2 +1
                if (-x == y and e2 <= x):
                    e2 = 0
            if (e2 > x):
                x += 1
                err += x*2 +1

    def circle(self, x0, y0, r, width =1, black = True): # Draw circle
        x0, y0, r = int(x0), int(y0), int(r)
        for r in range(r, r -width, -1):
            self._circle(x0, y0, r, black)

    def fillcircle(self, x0, y0, r, black = True): # Draw filled circle
        x0, y0, r = int(x0), int(y0), int(r)
        x = -r
        y = 0
        err = 2 -2*r
        while x <= 0:
            self._line(x0 -x, y0 -y, x0 -x, y0 +y, black)
            self._line(x0 +x, y0 -y, x0 +x, y0 +y, black)
            e2 = err
            if (e2 <= y):
                y +=1
                err += y*2 +1
                if (-x == y and e2 <= x):
                    e2 = 0
            if (e2 > x):
                x += 1
                err += x*2 +1

# ****** Image display ******

    def load_xbm(self, sourcefile, x = 0, y = 0):
        g = get_xbm_data(sourcefile)
        width = next(g)
        height = next(g)
        self.loadgfx(g, width, height, x, y)

# Load a rectangular region with a bitmap supplied by a generator.

    def loadgfx(self, gen, width, height, x0, y0):
        byteoffset = x0 >> 3
        bitshift = x0 & 7   # Offset of image relative to byte boundary
        bytes_per_line = width >> 3
        if width & 7 > 0:
            bytes_per_line += 1
        for line in range(height):
            y = y0 + line
            if y >= LINES_PER_DISPLAY:
                break
            index = y * BYTES_PER_LINE + byteoffset
            bitsleft = width
            x = x0
            for byte in range(bytes_per_line):
                val = next(gen)
                bits_to_write = min(bitsleft, 8)
                x += bits_to_write
                if x <= BITS_PER_LINE:
                    if bitshift == 0 and bits_to_write == 8:
                        self.epd.image[index] = val
                        index += 1
                    else:
                        mask = ((1 << bitshift) -1) # Bits in current byte to preserve
                        bitsused = bitshift + bits_to_write
                        overflow = max(0, bitsused -8)
                        underflow = max(0, 8 -bitsused)
                        if underflow:               # Underflow in current byte
                            mask = (mask | ~((1 << bitsused) -1)) & 0xff
                        nmask = ~mask & 0xff        # Bits to overwrite
                        self.epd.image[index] = (self.epd.image[index] & mask) | ((val << bitshift) & nmask)
                        index += 1
                        if overflow :               # Bits to write to next byte
                            mask = ~((1 << overflow) -1) & 0xff    # Preserve
                            self.epd.image[index] = (self.epd.image[index] & mask) | (val >> (8 - bitshift))
                bitsleft -= bits_to_write

# ****** Text support ******

    def locate(self, x, y):                     # set cursor position
        self.char_x = x                         # Text input cursor to (x, y)
        self.char_y = y

# font.bytes_horiz
# In cse of font file it's the pysical width of every character as stored in file
# In case of Python font it's the value of max_width converted to bytes
    def _character(self, c, usefile):
        font = self.font                        # Cache for speed
        bits_vert = font.bits_vert
        if usefile:
            ff = font.fontfile
            ff.seek(self.FONT_HEADER_LENGTH + (c -32) * (font.bytes_per_ch + 1))
            buf = ff.read(font.bytes_per_ch + 1)
            # Characters are stored as constant width.
            bytes_horiz = font.bytes_horiz      # No. of bytes before next row
            # Advance = bits_horiz if variable pitch else font.bits_horiz
            bits_horiz = buf[0]
            offset = 1
        else:
            modfont = font.modfont
            buf, height, bits_horiz = modfont.get_ch(chr(c))
            # Width varies between characters
            bytes_horiz = (bits_horiz + 7) // 8
            offset = 0
        # Sanity checks: prevent index errors. Wrapping should be done at string/word level.
        if (self.char_x + bytes_horiz * 8) > BITS_PER_LINE :
            self.char_x = 0
            self.char_y += bits_vert
        if self.char_y >= (LINES_PER_DISPLAY - bits_vert):
            self.char_y = 0

        image = self.epd.image
        y = self.char_y                         # x, y are pixel coordinates
        for bit_vert in range(bits_vert):       # for each vertical line
            x = self.char_x
            for byte_horiz in range(bytes_horiz):
                fontbyte = buf[bit_vert * bytes_horiz + byte_horiz + offset]
                index = (x >> 3) + y * BYTES_PER_LINE
                nbits = x & 0x07
                if nbits == 0:
                    image[index] = fontbyte
                else:
                    image[index] &= (0xff >> (8 - nbits))
                    image[index] |= (fontbyte << nbits)
                    image[index + 1] &= (0xff << nbits)
                    image[index + 1] |= (fontbyte >> (8 - nbits))
                x += 8
            y += 1
        self.char_x += font.bits_horiz if font.monospaced else bits_horiz

    def _putc(self, value, usefile):            # print char
        if (value == NEWLINE):
            self.char_x = 0
            self.char_y += self.font.bits_vert
            if (self.char_y >= LINES_PER_DISPLAY - self.font.bits_vert):
                self.char_y = 0
        else:
            self._character(value, usefile)
        return value

    def puts(self, s):                          # Output a string at cursor
        if self.font.exists:
            if self.font.modfont is None:       # No font module: using binary file
                for char in s:
                    c = ord(char)
                    if (c > 31 and c < 127) or c == NEWLINE:
                        self._putc(c, True)
            else:                               # Python font file is self-checking
                for char in s:
                    self._putc(ord(char), False)
        else:
             raise FontFileError("There is no current font")
Beispiel #7
0
class Display(object):
    FONT_HEADER_LENGTH = 4
    def __init__(self, side = 'L', use_flash = False, pwr_controller = None):
        self.flash = None                       # Assume flash is unused
        try:
            self.intside = {'x':1, 'X':1, 'y':0,'Y':0, 'l':0, 'L':0, 'r':1, 'R':1}[side]
        except KeyError:
            raise ValueError("Side must be 'L' or 'R'")
        self.pwr_controller = pwr_controller

        self.epd = EPD(self.intside, pwr_controller)
        self.font = Font()
        self.locate(0, 0)                       # Text cursor: default top left

        self.mounted = False                    # umountflash() not to sync
        if use_flash:
            from flash import FlashClass
            self.flash = FlashClass(self.intside, pwr_controller)
            self.umountflash()                  # In case mounted by prior tests.
            if self.pwr_controller is None:     # Normal operation: flash is mounted continuously
                self.mountflash()

    def mountflash(self):
        if self.flash is None:                  # Not being used
            return
        self.flash.begin()                      # Turn on power if under control. Initialise.
        pyb.mount(self.flash, self.flash.mountpoint)
        self.mounted = True

    def umountflash(self):                      # Unmount flash and power it down
        if self.flash is None:
            return
        if self.mounted:
            self.flash.sync()
        try:
            pyb.mount(None, self.flash.mountpoint)
        except OSError:
            pass                                # Don't care if it wasn't mounted
        self.flash.end()                        # Shut down, turn off power if under control
        self.mounted = False                    # flag unmounted to prevent spurious syncs

    def show(self):
        self.umountflash()                      # sync, umount flash, shut it down and disable SPI
                                                # EPD functions which access the display electronics must be
        with self.epd as epd:                   # called from a with block to ensure proper startup & shutdown
            epd.showdata()

        if self.pwr_controller is None:         # Normal operation without power control: remount
            self.mountflash()

    @property
    def temperature(self):                      # return temperature as integer in Celsius
        return self.epd.temperature

    def clear_screen(self, show = True):
        self.locate(0, 0)                       # Reset text cursor
        self.epd.clear_data()
        if show:
            self.show()

    @micropython.native
    def setpixel(self, x, y, black):            # 41uS. Clips to borders
        if y < 0 or y >= LINES_PER_DISPLAY or x < 0 or x >= BITS_PER_LINE :
            return
        image = self.epd.image
        omask = 1 << (x & 0x07)
        index = (x >> 3) + y *BYTES_PER_LINE
        if black:
            image[index] |= omask
        else:
            image[index] &= (omask ^ 0xff)

    @micropython.viper
    def setpixelfast(self, x: int, y: int, black: int): # 27uS. Caller checks bounds
        image = ptr8(self.epd.image)
        omask = 1 << (x & 0x07)
        index = (x >> 3) + y * 33 #BYTES_PER_LINE
        if black:
            image[index] |= omask
        else:
            image[index] &= (omask ^ 0xff)

# ****** Simple graphics support ******

    def _line(self, x0, y0, x1, y1, black = True): # Sinle pixel line
        dx = x1 -x0
        dy = y1 -y0
        dx_sym = 1 if dx > 0 else -1
        dy_sym = 1 if dy > 0 else -1

        dx = dx_sym*dx
        dy = dy_sym*dy
        dx_x2 = dx*2
        dy_x2 = dy*2
        if (dx >= dy):
            di = dy_x2 - dx
            while (x0 != x1):
                self.setpixel(x0, y0, black)
                x0 += dx_sym
                if (di<0):
                    di += dy_x2
                else :
                    di += dy_x2 - dx_x2
                    y0 += dy_sym
            self.setpixel(x0, y0, black)
        else:
            di = dx_x2 - dy
            while (y0 != y1):
                self.setpixel(x0, y0, black)
                y0 += dy_sym
                if (di < 0):
                    di += dx_x2
                else:
                    di += dx_x2 - dy_x2
                    x0 += dx_sym
            self.setpixel(x0, y0, black)

    def line(self, x0, y0, x1, y1, width =1, black = True): # Draw line
        if abs(x1 - x0) > abs(y1 - y0): # < 45 degrees
            for w in range(-width//2 +1, width//2 +1):
                self._line(x0, y0 +w, x1, y1 +w, black)
        else:
            for w in range(-width//2 +1, width//2 +1):
                self._line(x0 +w, y0, x1 +w, y1, black)

    def _rect(self, x0, y0, x1, y1, black): # Draw rectangle
        self.line(x0, y0, x1, y0, 1, black)
        self.line(x0, y0, x0, y1, 1, black)
        self.line(x0, y1, x1, y1, 1, black)
        self.line(x1, y0, x1, y1, 1, black)

    def rect(self, x0, y0, x1, y1, width =1, black = True): # Draw rectangle
        x0, x1 = (x0, x1) if x1 > x0 else (x1, x0) # x0, y0 is top left, x1, y1 is bottom right
        y0, y1 = (y0, y1) if y1 > y0 else (y1, y0)
        for w in range(width):
            self._rect(x0 +w, y0 +w, x1 -w, y1 -w, black)

    def fillrect(self, x0, y0, x1, y1, black = True): # Draw filled rectangle
        x0, x1 = (x0, x1) if x1 > x0 else (x1, x0)
        y0, y1 = (y0, y1) if y1 > y0 else (y1, y0)
        for x in range(x0, x1):
            for y in range(y0, y1):
                self.setpixel(x, y, black)

    def _circle(self, x0, y0, r, black = True): # Single pixel circle
        x = -r
        y = 0
        err = 2 -2*r
        while x <= 0:
            self.setpixel(x0 -x, y0 +y, black)
            self.setpixel(x0 +x, y0 +y, black)
            self.setpixel(x0 +x, y0 -y, black)
            self.setpixel(x0 -x, y0 -y, black)
            e2 = err
            if (e2 <= y):
                y += 1
                err += y*2 +1
                if (-x == y and e2 <= x):
                    e2 = 0
            if (e2 > x):
                x += 1
                err += x*2 +1

    def circle(self, x0, y0, r, width =1, black = True): # Draw circle
        for r in range(r, r -width, -1):
            self._circle(x0, y0, r, black)

    def fillcircle(self, x0, y0, r, black = True): # Draw filled circle
        x = -r
        y = 0
        err = 2 -2*r
        while x <= 0:
            self._line(x0 -x, y0 -y, x0 -x, y0 +y, black)
            self._line(x0 +x, y0 -y, x0 +x, y0 +y, black)
            e2 = err
            if (e2 <= y):
                y +=1
                err += y*2 +1
                if (-x == y and e2 <= x):
                    e2 = 0
            if (e2 > x):
                x += 1
                err += x*2 +1

# ****** Image display ******

    def load_xbm(self, sourcefile, x = 0, y = 0):
        g = get_xbm_data(sourcefile)
        width = next(g)
        height = next(g)
        self.loadgfx(g, width, height, x, y)

# Load a rectangular region with a bitmap supplied by a generator. This must supply bytes for each line in turn. These
# are displyed left to right, LSB of the 1st byte being at the top LH corner. Unused bits at the end of the line are
# ignored with a  new line starting on the next byte.

    def loadgfx(self, gen, width, height, x0, y0):
        byteoffset = x0 >> 3
        bitshift = x0 & 7   # Offset of image relative to byte boundary
        bytes_per_line = width >> 3
        if width & 7 > 0:
            bytes_per_line += 1
        for line in range(height):
            y = y0 + line
            if y >= LINES_PER_DISPLAY:
                break
            index = y * BYTES_PER_LINE + byteoffset
            bitsleft = width
            x = x0
            for byte in range(bytes_per_line):
                val = next(gen)
                bits_to_write = min(bitsleft, 8)
                x += bits_to_write
                if x <= BITS_PER_LINE:
                    if bitshift == 0 and bits_to_write == 8:
                        self.epd.image[index] = val
                        index += 1
                    else:
                        mask = ((1 << bitshift) -1) # Bits in current byte to preserve
                        bitsused = bitshift + bits_to_write
                        overflow = max(0, bitsused -8)
                        underflow = max(0, 8 -bitsused)
                        if underflow:               # Underflow in current byte
                            mask = (mask | ~((1 << bitsused) -1)) & 0xff
                        nmask = ~mask & 0xff        # Bits to overwrite
                        self.epd.image[index] = (self.epd.image[index] & mask) | ((val << bitshift) & nmask)
                        index += 1
                        if overflow :               # Bits to write to next byte
                            mask = ~((1 << overflow) -1) & 0xff    # Preserve
                            self.epd.image[index] = (self.epd.image[index] & mask) | (val >> (8 - bitshift))
                bitsleft -= bits_to_write

# ****** Text support ******

    def locate(self, x, y):                     # set cursor position
        self.char_x = x                         # Text input cursor to (x, y)
        self.char_y = y

    def _character(self, c):
        font = self.font                        # Cache for speed
        ff = font.fontfile
        bv = font.bits_vert
        ff.seek(self.FONT_HEADER_LENGTH + (c -32) * font.bytes_per_ch)
        fontbuf = ff.read(font.bytes_per_ch)
        bh = font.bits_horiz if font.monospaced else fontbuf[0] # Char width

        if (self.char_x + bh) > BITS_PER_LINE :
            self.char_x = 0
            self.char_y += bv
            if self.char_y >= (LINES_PER_DISPLAY - bv):
                self.char_y = 0
                                                # write out the character
        for bit_vert in range(bv):   # for each vertical line
            bytenum = bit_vert >> 3
            bit = 1 << (bit_vert & 0x07)        # Faster than divmod
            for bit_horiz in range(bh): #  horizontal line
                fontbyte = fontbuf[font.bytes_vert * bit_horiz + bytenum +1]
                self.setpixelfast(self.char_x +bit_horiz, self.char_y +bit_vert, (fontbyte & bit) > 0)
        self.char_x += bh                       # width of current char

    def _putc(self, value):                     # print char
        if (value == NEWLINE):
            self.char_x = 0
            self.char_y += self.font.bits_vert
            if (self.char_y >= LINES_PER_DISPLAY - self.font.bits_vert):
                self.char_y = 0
        else: 
            self._character(value)
        return value

    def puts(self, s):                          # Output a string at cursor
        if self.font.exists:
            for char in s:
                c = ord(char)
                if (c > 31 and c < 128) or c == NEWLINE:
                    self._putc(c)
        else:
             raise FontFileError("There is no current font")
class Display(object):
    FONT_HEADER_LENGTH = 4
    def __init__(self, side='L',*, mode=NORMAL, model=EMBEDDED_ARTISTS, use_flash=False, up_time=None):
        self.flash = None                       # Assume flash is unused
        self.in_context = False
        try:
            intside = {'l':0, 'r':1}[side.lower()]
        except (KeyError, AttributeError):
            raise ValueError("Side must be 'L' or 'R'")
        if model not in (EMBEDDED_ARTISTS, ADAFRUIT):
            raise ValueError('Unsupported model')
        if mode == FAST and use_flash:
            raise ValueError('Flash memory unavailable in fast mode')
        if mode == NORMAL and up_time is not None:
            raise ValueError('Cannot set up_time in normal mode')
        if mode == NORMAL:
            from epd import EPD
            self.epd = EPD(intside, model)
        elif mode == FAST:
            from epdpart import EPD
            self.epd = EPD(intside, model, up_time)
        else:
            raise ValueError('Unsupported mode {}'.format(mode))
        self.mode = mode
        self.font = Font()
        gc.collect()
        self.locate(0, 0)                       # Text cursor: default top left

        self.mounted = False                    # umountflash() not to sync
        if use_flash:
            from flash import FlashClass
            self.flash = FlashClass(intside)
            self.umountflash()                  # In case mounted by prior tests.
            self.mountflash()
        gc.collect()

    def checkcm(self):
        if not (self.mode == NORMAL or self.in_context):
            raise EPDError('Fast mode must be run using a context manager')

    def __enter__(self):                        # Power up
        checkstate(self.mode == FAST, "In normal mode, can't use context manager")
        self.in_context = True
        self.epd.enter()
        return self

    def __exit__(self, *_):                     # shut down
        self.in_context = False
        self.epd.exit()
        pass

    def mountflash(self):
        if self.flash is None:                  # Not being used
            return
        self.flash.begin()                      # Initialise.
        pyb.mount(self.flash, self.flash.mountpoint)
        self.mounted = True

    def umountflash(self):                      # Unmount flash
        if self.flash is None:
            return
        if self.mounted:
            self.flash.sync()
        try:
            pyb.mount(None, self.flash.mountpoint)
        except OSError:
            pass                                # Don't care if it wasn't mounted
        self.flash.end()                        # Shut down
        self.mounted = False                    # flag unmounted to prevent spurious syncs

    def show(self):
        self.checkcm()
        self.umountflash()                      # sync, umount flash, shut it down and disable SPI
        if self.mode == NORMAL:                 # EPD functions which access the display electronics must be
            with self.epd as epd:               # called from a with block to ensure proper startup & shutdown
                epd.showdata()
        else:                                   # Fast mode: already in context manager
            self.epd.showdata()
        self.mountflash()

    def clear_screen(self, show=True):
        self.checkcm()
        self.locate(0, 0)                       # Reset text cursor
        self.epd.clear_data()
        if show:
            if self.mode == NORMAL:
                self.show()
            else:
                self.epd.EPD_clear()

    def refresh(self, fast =True):              # Fast mode only functions
        checkstate(self.mode == FAST, 'refresh() invalid in normal mode')
        self.checkcm()
        self.epd.refresh(fast)

    def exchange(self, clear_data):
        checkstate(self.mode == FAST, 'exchange() invalid in normal mode')
        self.checkcm()
        self.epd.exchange(clear_data)

    @property
    def temperature(self):                      # return temperature as integer in Celsius
        return self.epd.temperature

    @property
    def location(self):
        return self.char_x, self.char_y

    @micropython.native
    def setpixel(self, x, y, black):            # 41uS. Clips to borders. x, y must be integer
        if y < 0 or y >= LINES_PER_DISPLAY or x < 0 or x >= BITS_PER_LINE :
            return
        image = self.epd.image
        omask = 1 << (x & 0x07)
        index = (x >> 3) + y *BYTES_PER_LINE
        if black:
            image[index] |= omask
        else:
            image[index] &= (omask ^ 0xff)

    @micropython.viper
    def setpixelfast(self, x: int, y: int, black: int): # 27uS. Caller checks bounds
        image = ptr8(self.epd.image)
        omask = 1 << (x & 0x07)
        index = (x >> 3) + y * 33 #BYTES_PER_LINE
        if black:
            image[index] |= omask
        else:
            image[index] &= (omask ^ 0xff)

# ****** Simple graphics support ******

    def _line(self, x0, y0, x1, y1, black = True): # Sinle pixel line
        dx = x1 -x0
        dy = y1 -y0
        dx_sym = 1 if dx > 0 else -1
        dy_sym = 1 if dy > 0 else -1

        dx = dx_sym*dx
        dy = dy_sym*dy
        dx_x2 = dx*2
        dy_x2 = dy*2
        if (dx >= dy):
            di = dy_x2 - dx
            while (x0 != x1):
                self.setpixel(x0, y0, black)
                x0 += dx_sym
                if (di<0):
                    di += dy_x2
                else :
                    di += dy_x2 - dx_x2
                    y0 += dy_sym
            self.setpixel(x0, y0, black)
        else:
            di = dx_x2 - dy
            while (y0 != y1):
                self.setpixel(x0, y0, black)
                y0 += dy_sym
                if (di < 0):
                    di += dx_x2
                else:
                    di += dx_x2 - dy_x2
                    x0 += dx_sym
            self.setpixel(x0, y0, black)

    def line(self, x0, y0, x1, y1, width =1, black = True): # Draw line
        x0, y0, x1, y1 = int(x0), int(y0), int(x1), int(y1)
        if abs(x1 - x0) > abs(y1 - y0): # < 45 degrees
            for w in range(-width//2 +1, width//2 +1):
                self._line(x0, y0 +w, x1, y1 +w, black)
        else:
            for w in range(-width//2 +1, width//2 +1):
                self._line(x0 +w, y0, x1 +w, y1, black)

    def _rect(self, x0, y0, x1, y1, black): # Draw rectangle
        self.line(x0, y0, x1, y0, 1, black)
        self.line(x0, y0, x0, y1, 1, black)
        self.line(x0, y1, x1, y1, 1, black)
        self.line(x1, y0, x1, y1, 1, black)

    def rect(self, x0, y0, x1, y1, width =1, black = True): # Draw rectangle
        x0, y0, x1, y1 = int(x0), int(y0), int(x1), int(y1)
        x0, x1 = (x0, x1) if x1 > x0 else (x1, x0) # x0, y0 is top left, x1, y1 is bottom right
        y0, y1 = (y0, y1) if y1 > y0 else (y1, y0)
        for w in range(width):
            self._rect(x0 +w, y0 +w, x1 -w, y1 -w, black)

    def fillrect(self, x0, y0, x1, y1, black = True): # Draw filled rectangle
        x0, y0, x1, y1 = int(x0), int(y0), int(x1), int(y1)
        x0, x1 = (x0, x1) if x1 > x0 else (x1, x0)
        y0, y1 = (y0, y1) if y1 > y0 else (y1, y0)
        for x in range(x0, x1):
            for y in range(y0, y1):
                self.setpixel(x, y, black)

    def _circle(self, x0, y0, r, black = True): # Single pixel circle
        x = -r
        y = 0
        err = 2 -2*r
        while x <= 0:
            self.setpixel(x0 -x, y0 +y, black)
            self.setpixel(x0 +x, y0 +y, black)
            self.setpixel(x0 +x, y0 -y, black)
            self.setpixel(x0 -x, y0 -y, black)
            e2 = err
            if (e2 <= y):
                y += 1
                err += y*2 +1
                if (-x == y and e2 <= x):
                    e2 = 0
            if (e2 > x):
                x += 1
                err += x*2 +1

    def circle(self, x0, y0, r, width =1, black = True): # Draw circle
        x0, y0, r = int(x0), int(y0), int(r)
        for r in range(r, r -width, -1):
            self._circle(x0, y0, r, black)

    def fillcircle(self, x0, y0, r, black = True): # Draw filled circle
        x0, y0, r = int(x0), int(y0), int(r)
        x = -r
        y = 0
        err = 2 -2*r
        while x <= 0:
            self._line(x0 -x, y0 -y, x0 -x, y0 +y, black)
            self._line(x0 +x, y0 -y, x0 +x, y0 +y, black)
            e2 = err
            if (e2 <= y):
                y +=1
                err += y*2 +1
                if (-x == y and e2 <= x):
                    e2 = 0
            if (e2 > x):
                x += 1
                err += x*2 +1

# ****** Image display ******

    def load_xbm(self, sourcefile, x = 0, y = 0):
        g = get_xbm_data(sourcefile)
        width = next(g)
        height = next(g)
        self.loadgfx(g, width, height, x, y)

# Load a rectangular region with a bitmap supplied by a generator.

    def loadgfx(self, gen, width, height, x0, y0):
        byteoffset = x0 >> 3
        bitshift = x0 & 7   # Offset of image relative to byte boundary
        bytes_per_line = width >> 3
        if width & 7 > 0:
            bytes_per_line += 1
        for line in range(height):
            y = y0 + line
            if y >= LINES_PER_DISPLAY:
                break
            index = y * BYTES_PER_LINE + byteoffset
            bitsleft = width
            x = x0
            for byte in range(bytes_per_line):
                val = next(gen)
                bits_to_write = min(bitsleft, 8)
                x += bits_to_write
                if x <= BITS_PER_LINE:
                    if bitshift == 0 and bits_to_write == 8:
                        self.epd.image[index] = val
                        index += 1
                    else:
                        mask = ((1 << bitshift) -1) # Bits in current byte to preserve
                        bitsused = bitshift + bits_to_write
                        overflow = max(0, bitsused -8)
                        underflow = max(0, 8 -bitsused)
                        if underflow:               # Underflow in current byte
                            mask = (mask | ~((1 << bitsused) -1)) & 0xff
                        nmask = ~mask & 0xff        # Bits to overwrite
                        self.epd.image[index] = (self.epd.image[index] & mask) | ((val << bitshift) & nmask)
                        index += 1
                        if overflow :               # Bits to write to next byte
                            mask = ~((1 << overflow) -1) & 0xff    # Preserve
                            self.epd.image[index] = (self.epd.image[index] & mask) | (val >> (8 - bitshift))
                bitsleft -= bits_to_write

# ****** Text support ******

    def locate(self, x, y):                     # set cursor position
        self.char_x = x                         # Text input cursor to (x, y)
        self.char_y = y

# font.bytes_horiz
# In cse of font file it's the pysical width of every character as stored in file
# In case of Python font it's the value of max_width converted to bytes
    def _character(self, c, usefile):
        font = self.font                        # Cache for speed
        bits_vert = font.bits_vert
        if usefile:
            ff = font.fontfile
            ff.seek(self.FONT_HEADER_LENGTH + (c -32) * (font.bytes_per_ch + 1))
            buf = ff.read(font.bytes_per_ch + 1)
            # Characters are stored as constant width.
            bytes_horiz = font.bytes_horiz      # No. of bytes before next row
            # Advance = bits_horiz if variable pitch else font.bits_horiz
            bits_horiz = buf[0]
            offset = 1
        else:
            modfont = font.modfont
            buf, height, bits_horiz = modfont.get_ch(chr(c))
            # Width varies between characters
            bytes_horiz = (bits_horiz + 7) // 8
            offset = 0

        if (self.char_x + bytes_horiz * 8) > BITS_PER_LINE :
            self.char_x = 0
            self.char_y += bits_vert
            if self.char_y >= (LINES_PER_DISPLAY - bits_vert):
                self.char_y = 0

        image = self.epd.image
        y = self.char_y                         # x, y are pixel coordinates
        for bit_vert in range(bits_vert):       # for each vertical line
            x = self.char_x
            for byte_horiz in range(bytes_horiz):
                fontbyte = buf[bit_vert * bytes_horiz + byte_horiz + offset]
                index = (x >> 3) + y * BYTES_PER_LINE
                nbits = x & 0x07
                if nbits == 0:
                    image[index] = fontbyte
                else:
                    image[index] &= (0xff >> (8 - nbits))
                    image[index] |= (fontbyte << nbits)
                    image[index + 1] &= (0xff << nbits)
                    image[index + 1] |= (fontbyte >> (8 - nbits))
                x += 8
            y += 1
        self.char_x += font.bits_horiz if font.monospaced else bits_horiz

    def _putc(self, value, usefile):            # print char
        if (value == NEWLINE):
            self.char_x = 0
            self.char_y += self.font.bits_vert
            if (self.char_y >= LINES_PER_DISPLAY - self.font.bits_vert):
                self.char_y = 0
        else:
            self._character(value, usefile)
        return value

    def puts(self, s):                          # Output a string at cursor
        if self.font.exists:
            usefile = self.font.modfont is None # No font module
            for char in s:
                c = ord(char)
                if (c > 31 and c < 127) or c == NEWLINE:
                    self._putc(c, usefile)
        else:
             raise FontFileError("There is no current font")
Beispiel #9
0
            self.c1.set_text(self.sdate, x=10)

        if self.stime != ttime:
            self.stime = ttime
            self.c2.set_text(self.stime, x=4)


if __name__ == '__main__':

    from epd import EPD

    # Display layout instance
    L1 = Layout_1()

    # E-Paper Display instance
    epd = EPD(True, L1)

    for i in range(5):
        L1.inc_water(1)
        L1.inc_gas(0.01)
        L1.set_date_time()
        epd.update()

    L1.clear_all()
    epd.show()

    for i in range(5):
        L1.inc_water(1)
        L1.inc_gas(0.01)
        L1.set_date_time()
        epd.update()
Beispiel #10
0
class Display(object):
    IMG_DIR = '/flash/imgs'

    def __init__(self, debug=False):
        self.cfg = None
        self.rtc = RTC()
        self.debug = debug
        self.battery = Battery()

        # use this pin for debug
        self.wifi_pin = Pin("GP24", mode=Pin.IN, pull=Pin.PULL_UP)

        # Empty WDT object
        self.wdt = None

        if not debug:
            if not self.wifi_pin():
                self.wdt = WDT(timeout=20000)
            self.sd = None
        else:
            from machine import SD
            try:
                self.sd = SD()
                mount(self.sd, '/sd')
                self.logfile = open("/sd/display.log", "a")
            except OSError:
                self.sd = None
                self.logfile = None

        self.epd = EPD()

        self.log("Time left on the alarm: %dms" % self.rtc.alarm_left())

        # Don't flash when we're awake outside of debug
        heartbeat(self.debug)

    def log(self, msg, end='\n'):
        time = "%d, %d, %d, %d, %d, %d" % self.rtc.now()[:-2]
        msg = time + ", " + msg
        if self.logfile:
            self.logfile.write(msg + end)
        print(msg, end=end)

    def feed_wdt(self):
        if self.wdt:
            self.wdt.feed()

    def connect_wifi(self):
        from network import WLAN

        if not self.cfg:
            raise ValueError("Can't initialise wifi, no config")

        self.log('Starting WLAN, attempting to connect to ' + ','.join(self.cfg.wifi.keys()))
        wlan = WLAN(0, WLAN.STA)
        wlan.ifconfig(config='dhcp')
        while not wlan.isconnected():
            nets = wlan.scan()
            for network in nets:
                if network.ssid in self.cfg.wifi.keys():
                    self.log('Connecting to ' + network.ssid)
                    self.feed_wdt() # just in case
                    wlan.connect(ssid=network.ssid, auth=(network.sec, self.cfg.wifi[network.ssid]))
                    while not wlan.isconnected():
                        idle()
                    break

            self.feed_wdt() # just in case
            sleep_ms(2000)

        self.log('Connected as %s' % wlan.ifconfig()[0])

    @staticmethod
    def reset_cause():
        import machine
        val = machine.reset_cause()
        if val == machine.POWER_ON:
            return "power"
        elif val == machine.HARD_RESET:
            return "hard"
        elif val == machine.WDT_RESET:
            return "wdt"
        elif val == machine.DEEPSLEEP_RESET:
            return "sleep"
        elif val == machine.SOFT_RESET:
            return "soft"

    def set_alarm(self, now, json_metadata):
        import json
        json_dict = json.loads(json_metadata)

        # Now we know the time too
        self.rtc = RTC(datetime=now)
        list_int = json_dict["wakeup"][:6]
        time_str = ",".join([str(x) for x in list_int])

        self.log("Setting alarm for " + time_str)
        self.rtc.alarm(time=tuple(list_int))

        if self.rtc.alarm_left() == 0:
            self.log("Alarm failed, setting for +1 hour")
            self.rtc.alarm(time=3600000)

        del json

    def display_file_image(self, file_obj):
        towrite = 15016
        max_chunk = 250
        while towrite > 0:
            c = max_chunk if towrite > max_chunk else towrite
            buff = file_obj.read(c)
            self.epd.upload_image_data(buff, delay_us=2000)
            self.feed_wdt()
            towrite -= c

        self.epd.display_update()

    def display_no_config(self):
        self.log("Displaying no config msg")
        with open(Display.IMG_DIR + '/no_config.bin', 'rb') as pic:
            self.display_file_image(pic)

    def display_low_battery(self):
        self.log("Displaying low battery msg")
        with open(Display.IMG_DIR + '/low_battery.bin', 'rb') as pic:
            self.display_file_image(pic)

    def display_cannot_connect(self):
        self.log("Displaying no server comms msg")
        with open(Display.IMG_DIR + '/no_server.bin', 'rb') as pic:
            self.display_file_image(pic)

    def display_no_wifi(self):
        self.log("Displaying no wifi msg")
        with open(Display.IMG_DIR + '/no_wifi.bin', 'rb') as pic:
            self.display_file_image(pic)

    def check_battery_level(self):
        now_batt = 200
        last_batt = self.battery.battery_raw()
        while now_batt > last_batt:
            sleep_ms(50)
            last_batt = now_batt
            self.feed_wdt()
            now_batt = self.battery.battery_raw()
            self.log("Battery value: %d (%d)" % (self.battery.value(), self.battery.battery_raw()))

        if not self.battery.safe():
            self.log("Battery voltage (%d) low! Turning off" % self.battery.battery_raw())
            self.feed_wdt()
            self.display_low_battery()
            return False
        else:
            self.log("Battery value: %d (%d)" % (self.battery.value(), self.battery.battery_raw()))
        return True

    def run_deepsleep(self):

        if not self.run():
            # RTC wasn't set, try to sleep forever
            self.rtc.alarm(time=2000000000)

        # Set the wakeup (why do it earlier?)
        rtc_i = self.rtc.irq(trigger=RTC.ALARM0, wake=DEEPSLEEP)

        self.log("Going to sleep, waking in %dms" % self.rtc.alarm_left())

        # Close files on the SD card
        if self.sd:
            self.logfile.close()
            self.logfile = None
            unmount('/sd')
            self.sd.deinit()

        # Turn the screen off
        self.epd.disable()

        if not self.wifi_pin():
            # Basically turn off
            deepsleep()
        else:
            self.log("DEBUG MODE: Staying awake")
            pass
            # Do nothing, allow network connections in

    def run(self):

        woken = self.wifi_pin()
        self.epd.enable()

        if not self.check_battery_level():
            return False

        try:
            self.epd.get_sensor_data()
        except ValueError:
            self.log("Can't communicate with display, flashing light and giving up")
            heartbeat(True)
            sleep_ms(15000)
            return True

        if self.rtc.alarm_left() > 0:
            self.log("Woken up but the timer is still running, refreshing screen only")
            self.epd.display_update()
            self.feed_wdt()
            return True

        try:
            self.cfg = Config.load(sd=self.sd)
            self.log("Loaded config")
        except (OSError, ValueError) as e:
            self.log("Failed to load config: " + str(e))
            self.display_no_config()
            try:
                self.connect_wifi()
            except:
                pass # everything

            while True:
                sleep_ms(10)
                self.feed_wdt()

        self.feed_wdt()

        self.connect_wifi()

        content = b''
        try:
            self.log("Connecting to server %s:%d" % (self.cfg.host, self.cfg.port))
            c = Connect(self.cfg.host, self.cfg.port, debug=self.debug)

            self.feed_wdt()

            cause = Display.reset_cause()
            if woken:
                cause = "user"

            self.log("Reset cause: " + cause)

            if len(self.cfg.upload_path) > 0:
                temp = self.epd.get_sensor_data() # we read this already
                c.post(self.cfg.upload_path,
                       battery=self.battery.value(),
                       reset=cause,
                       screen=temp)

            self.log("Fetching metadata from " + self.cfg.metadata_path)
            metadata = c.get_quick(self.cfg.metadata_path, max_length=1024, path_type='json')

            # This will set the time to GMT, not localtime
            self.set_alarm(c.last_fetch_time, metadata)

            self.feed_wdt()
            del metadata
            del self.battery
            self.log("Fetching image from " + self.cfg.image_path)
            self.epd.image_erase_frame_buffer()
            self.feed_wdt()

            length, socket = c.get_object(self.cfg.image_path)

            if length != 15016:
                raise ValueError("Wrong data size for image: %d" % length)

            self.feed_wdt()

        except (RuntimeError, ValueError, OSError) as e:
            self.log("Failed to get remote info: " + str(e))
            self.display_cannot_connect()
            self.rtc.alarm(time=3600000)
            return True

        sleep_ms(1000) # How do we make the write to display more reliable?
        self.feed_wdt()
        self.log("Uploading to display")
        self.display_file_image(socket)
        c.get_object_done() # close off socket

        if self.cfg.src == "sd":
            # If we've got a working config from SD instead of flash
            self.log("Transferring working config")
            Config.transfer()
            self.log("SUCCESS")

        self.log("Finished. Mem free: %d" % gc.mem_free())
        return True
Beispiel #11
0
        self.set_value_1(0)
        self.set_value_2(0)
        self.set_value_3(0)
        self.set_value_4(0)
        self.set_value_5(0)


if __name__ == '__main__':

    from epd import EPD

    # Display Layout instance
    L1 = Escale()

    # E-Paper Display instance
    epd = EPD(True, L1)  # TODO
    #    epd = EPD(True)
    #    epd.add( L1.components )
    #    epd.show()

    val = 123
    for i in range(10):
        val += .22
        val_25 = L1.round_to(val, 0.25)
        val_50 = L1.round_to(val, 0.5)
        val_1 = L1.round_to(val, 1.0)

        L1.set_value_1(val_25)
        L1.set_value_2(val_25)
        L1.set_value_3(val_50)
        L1.set_value_4(val_50)
Beispiel #12
0
            self.cdate.set_text(self.sdate, align=1)

        if self.stime != ttime:
            self.stime = ttime
            self.ctime.set_text(self.stime, x=3)


if __name__ == '__main__':

    from epd import EPD

    # Display Layout instance
    L2 = Layout_2()

    # E-Paper Display instance
    epd = EPD(False, L2)

    # Random values for test
    L2.water = 890
    L2.gas = 2.64
    L2.electricity = 0
    L2.day_electricity = 12.3

    L2.eur_water = 0.23
    L2.eur_gas = 0.66
    L2.eur_electricity = 1.79
    L2.eur_total = L2.eur_water + L2.eur_gas + L2.eur_electricity

    for i in range(5):
        L2.inc_water(1)
        L2.inc_gas(0.01)
Beispiel #13
0
            self.cdate.set_text(self.sdate, align=1)

        if self.stime != ttime:
            self.stime = ttime
            self.ctime.set_text(self.stime, x=5)


if __name__ == '__main__':

    from epd import EPD

    # Display Layout instance
    L2 = Layout_2()

    # E-Paper Display instance
    epd = EPD(False, L2, partial_update = True)
    
    # Random values for test
    L2.water           = 890
    L2.gas             = 2.64
    L2.electricity     = 0
    L2.day_electricity = 12.3

    L2.eur_water       = 0.23
    L2.eur_gas         = 0.66
    L2.eur_electricity = 1.79
    L2.eur_total       = L2.eur_water + L2.eur_gas + L2.eur_electricity

    for i in range(18):
        L2.egraph.set_bar(i, i+1)