diff --git a/RTC-Hat-Examples/RTCreboot/prtc.py b/RTC-Hat-Examples/RTCreboot/prtc.py index 3745706..65fdfcb 100644 --- a/RTC-Hat-Examples/RTCreboot/prtc.py +++ b/RTC-Hat-Examples/RTCreboot/prtc.py @@ -4,28 +4,29 @@ from datetime import datetime from calendar import isleap -from smbusf import SMBus RTCADR = 0x6f STBIT = 0x80 -LPYR = 0x20 +LPYR = 0x20 almbase = [0xa, 0x11] + def tobcd(val): return (val % 10) | (val // 10) << 4 + def writertc(i2cbus, dt): sec = dt.second min = dt.minute hour = dt.hour # rtc-ds1307 uses weekday convention Sun = 1, Sat = 7 - wkday = (dt.weekday() + 1)%7 + 1 + wkday = (dt.weekday() + 1) % 7 + 1 day = dt.day month = dt.month year = dt.year leap = isleap(year) - data = [0,0,0,0,0,0,0] + data = [0, 0, 0, 0, 0, 0, 0] data[0] = tobcd(sec) | STBIT data[1] = tobcd(min) data[2] = tobcd(hour) @@ -39,6 +40,7 @@ def writertc(i2cbus, dt): i2cbus.write_i2c_block_data(RTCADR, 0, data) + def writealm(i2cbus, alm, dt): if alm > 0: alm = 1 @@ -48,13 +50,13 @@ def writealm(i2cbus, alm, dt): min = dt.minute hour = dt.hour # rtc-ds1307 uses weekday convention Sun = 1, Sat = 7 - # wkday in alarm has to match the wkday of rtc time for the alarm to trigger - wkday = (dt.weekday() + 1)%7 + 1 + # wkday in alarm has to match the wkday of rtc time + # for the alarm to trigger + wkday = (dt.weekday() + 1) % 7 + 1 day = dt.day month = dt.month - year = dt.year - - data = [0,0,0,0,0,0] + + data = [0, 0, 0, 0, 0, 0] data[0] = tobcd(sec) data[1] = tobcd(min) data[2] = tobcd(hour) @@ -64,18 +66,20 @@ def writealm(i2cbus, alm, dt): i2cbus.write_i2c_block_data(RTCADR, almbase[alm], data) + def readrtc(i2cbus): - data=i2cbus.read_i2c_block_data(RTCADR, 0, 7) + data = i2cbus.read_i2c_block_data(RTCADR, 0, 7) - sec = (data[0] & 0x7f) // 16 * 10 + (data[0] & 0x0f) - min = data[1] // 16 * 10 + (data[1] & 0x0f) - hour = data[2] // 16 * 10 + (data[2] & 0x0f) - day = data[4] // 16 * 10 + (data[4] & 0x0f) + sec = (data[0] & 0x7f) // 16 * 10 + (data[0] & 0x0f) + min = data[1] // 16 * 10 + (data[1] & 0x0f) + hour = data[2] // 16 * 10 + (data[2] & 0x0f) + day = data[4] // 16 * 10 + (data[4] & 0x0f) month = (data[5] & 0x10) // 16 * 10 + (data[5] & 0x0f) - year = data[6] // 16 * 10 + (data[6] & 0x0f) + year = data[6] // 16 * 10 + (data[6] & 0x0f) dt = datetime(2000+year, month, day, hour, min, sec) return dt + def readalm(i2cbus, alm): if alm > 0: alm = 1 @@ -83,47 +87,56 @@ def readalm(i2cbus, alm): alm = 0 data = i2cbus.read_i2c_block_data(RTCADR, almbase[alm], 6) - sec = data[0] // 16 * 10 + (data[0] & 0x0f) - min = data[1] // 16 * 10 + (data[1] & 0x0f) - hour = data[2] // 16 * 10 + (data[2] & 0x0f) - day = data[4] // 16 * 10 + (data[4] & 0x0f) + sec = data[0] // 16 * 10 + (data[0] & 0x0f) + min = data[1] // 16 * 10 + (data[1] & 0x0f) + hour = data[2] // 16 * 10 + (data[2] & 0x0f) + day = data[4] // 16 * 10 + (data[4] & 0x0f) month = data[5] // 16 * 10 + (data[5] & 0x0f) # year not used in alarm time dt = datetime(2000, month, day, hour, min, sec) return dt + def enablealm0(i2cbus): data = i2cbus.read_byte_data(RTCADR, 7) data |= 0x10 i2cbus.write_byte_data(RTCADR, 7, data) + def enablealm1(i2cbus): data = i2cbus.read_byte_data(RTCADR, 7) data |= 0x20 i2cbus.write_byte_data(RTCADR, 7, data) + def disablealm0(i2cbus): - # When disabling the alarm, keep the mfp output high (otherwise we'll get an immediate reboot) + # When disabling the alarm, keep the mfp output high + # (otherwise we'll get an immediate reboot) data = i2cbus.read_byte_data(RTCADR, 7) data &= 0xef data |= 0x80 i2cbus.write_byte_data(RTCADR, 7, data) + def disablealm1(i2cbus): - # When disabling the alarm, keep the mfp output high (otherwise we'll get an immediate reboot) + # When disabling the alarm, keep the mfp output high + # (otherwise we'll get an immediate reboot) data = i2cbus.read_byte_data(RTCADR, 7) data &= 0xdf data |= 0x80 i2cbus.write_byte_data(RTCADR, 7, data) + def enablesqw(i2cbus): # Set 1 Hz square wave output i2cbus.write_byte_data(RTCADR, 7, 0x40) + def disablesqw(i2cbus): # Disable square wave and set ouput high i2cbus.write_byte_data(RTCADR, 7, 0x80) + def mfpoutput(i2cbus, val): # set MFP output directly if val == 0: @@ -131,4 +144,3 @@ def mfpoutput(i2cbus, val): else: data = 0x80 i2cbus.write_byte_data(RTCADR, 7, data) - diff --git a/RTC-Hat-Examples/RTCreboot/pwrite_text.py b/RTC-Hat-Examples/RTCreboot/pwrite_text.py index 4579a43..bd607c3 100644 --- a/RTC-Hat-Examples/RTCreboot/pwrite_text.py +++ b/RTC-Hat-Examples/RTCreboot/pwrite_text.py @@ -4,7 +4,6 @@ from PIL import Image from PIL import ImageDraw from PIL import ImageFont -from smbusf import SMBus import os WHITE = 1 @@ -13,28 +12,32 @@ lock = False + def main(): papirus = Papirus() - i2cbus=SMBus(1) write_text(papirus, 'Line 1', save=True) write_text(papirus, 'Line 2', y=20, load=True, ldfile='save.bmp') -def write_text(papirus, text, x=0, y=0, size=20, load=False, ldfile=' ', save=False, file='save.bmp'): + +def write_text(papirus, text, x=0, y=0, + size=20, load=False, ldfile=' ', + save=False, file='save.bmp'): global image, draw, font - if os.path.isfile(ldfile): - image = Image.open(ldfile) - image.load() - os.remove(ldfile) + if load and os.path.isfile(ldfile): + image = Image.open(ldfile) + image.load() + os.remove(ldfile) else: - # set all white background - image = Image.new('1', papirus.size, WHITE) + # set all white background + image = Image.new('1', papirus.size, WHITE) # prepare for drawing draw = ImageDraw.Draw(image) - font = ImageFont.truetype('/usr/share/fonts/truetype/freefont/FreeMonoBold.ttf', size) + font = ImageFont.truetype('/usr/share/fonts/truetype' + '/freefont/FreeMonoBold.ttf', size) # Calculate the max number of char to fit on line line_size = ((papirus.width - x) / (size*0.65)) @@ -54,8 +57,8 @@ def write_text(papirus, text, x=0, y=0, size=20, load=False, ldfile=' ', save=Fa text_lines[current_line] += " " + word current_line = 0 - for l in text_lines: - draw.text( (x, (size*current_line + y)), l, font=font, fill=BLACK) + for line in text_lines: + draw.text((x, (size*current_line + y)), line, font=font, fill=BLACK) current_line += 1 papirus.display(image) @@ -63,6 +66,7 @@ def write_text(papirus, text, x=0, y=0, size=20, load=False, ldfile=' ', save=Fa if (save): image.save(file) + def replace_line(papirus, x, y, text, size=20): global image, draw, font, lock @@ -73,11 +77,12 @@ def replace_line(papirus, x, y, text, size=20): draw.text((x, y), text, font=font, fill=BLACK) lock = False + def update_lines(papirus): global image papirus.display(image) papirus.partial_update() + if __name__ == '__main__': main() - diff --git a/RTC-Hat-Examples/py-smbusf/setup.py b/RTC-Hat-Examples/py-smbusf/setup.py index f26deeb..f4163ca 100644 --- a/RTC-Hat-Examples/py-smbusf/setup.py +++ b/RTC-Hat-Examples/py-smbusf/setup.py @@ -2,13 +2,15 @@ from distutils.core import setup, Extension -setup( name="smbusf", - version="1.1", - description="Python bindings for Linux SMBus access through i2c-dev, forced access version", - author="Mark M. Hoffman", - author_email="mhoffman@lightlink.com", - maintainer="Mark M. Hoffman", - maintainer_email="linux-i2c@vger.kernel.org", - license="GPLv2", - url="http://lm-sensors.org/", - ext_modules=[Extension("smbusf", ["smbusmodule.c"])]) +setup( + name="smbusf", + version="1.1", + description=("Python bindings for Linux SMBus access through i2c-dev, " + "forced access version"), + author="Mark M. Hoffman", + author_email="mhoffman@lightlink.com", + maintainer="Mark M. Hoffman", + maintainer_email="linux-i2c@vger.kernel.org", + license="GPLv2", + url="http://lm-sensors.org/", + ext_modules=[Extension("smbusf", ["smbusmodule.c"])]) diff --git a/papirus/__init__.py b/papirus/__init__.py index 0719624..a8575cb 100644 --- a/papirus/__init__.py +++ b/papirus/__init__.py @@ -5,4 +5,3 @@ from papirus.textpos import PapirusTextPos from papirus.composite import PapirusComposite from papirus.readrtc import get_hwclock - diff --git a/papirus/composite.py b/papirus/composite.py index 6ebe17c..8c0a5bf 100644 --- a/papirus/composite.py +++ b/papirus/composite.py @@ -1,15 +1,13 @@ -import os -import sys +import uuid from PIL import Image from PIL import ImageOps -from papirus import Papirus from papirus import PapirusTextPos -import uuid WHITE = 1 BLACK = 0 + # Class for holding the details of the img class DispImg(object): def __init__(self, image, x, y, size): @@ -20,6 +18,7 @@ def __init__(self, image, x, y, size): self.endx = 0 self.endy = 0 + class PapirusComposite(PapirusTextPos): def __init__(self, autoUpdate=True, rotation=0): @@ -27,7 +26,7 @@ def __init__(self, autoUpdate=True, rotation=0): self.allImg = dict() self.image = Image.new('1', self.papirus.size, WHITE) - def AddImg(self, image, x=0, y=0, size = (10,10), Id=None): + def AddImg(self, image, x=0, y=0, size=(10, 10), Id=None): # Create a new Id if none is supplied if Id is None: Id = str(uuid.uuid4()) @@ -42,7 +41,7 @@ def AddImg(self, image, x=0, y=0, size = (10,10), Id=None): self.allImg[Id] = DispImg(image, x, y, size) # add the img to the image self.addToImageImg(Id) - #Automatically show? + # Automatically show? if self.autoUpdate: self.WriteAll() @@ -56,12 +55,13 @@ def UpdateImg(self, Id, image): image = image.convert("1", dither=Image.FLOYDSTEINBERG) self.allImg[Id].image = image - - # Remove from the old img from the image (that doesn't use the actual img) + + # Remove from the old img from the image + # (that doesn't use the actual img) self.removeImageImg(Id) # Add the new img to the image self.addToImageImg(Id) - #Automatically show? + # Automatically show? if self.autoUpdate: self.WriteAll() @@ -71,7 +71,7 @@ def RemoveImg(self, Id): self.removeImageImg(Id) del self.allImg[Id] - #Automatically show? + # Automatically show? if self.autoUpdate: self.WriteAll() @@ -79,13 +79,12 @@ def removeImageImg(self, Id): # prepare for drawing filler = Image.new('1', self.allImg[Id].size, WHITE) # Draw over the top of the img with a rectangle to cover it - x = self.allImg[Id].x - y = self.allImg[Id].y - self.image.paste(filler,(x,y)) + x = self.allImg[Id].x + y = self.allImg[Id].y + self.image.paste(filler, (x, y)) def addToImageImg(self, Id): - x = self.allImg[Id].x - y = self.allImg[Id].y - - self.image.paste(self.allImg[Id].image,(x,y)) + x = self.allImg[Id].x + y = self.allImg[Id].y + self.image.paste(self.allImg[Id].image, (x, y)) diff --git a/papirus/epd.py b/papirus/epd.py index 4e0c204..19c5f10 100644 --- a/papirus/epd.py +++ b/papirus/epd.py @@ -1,4 +1,4 @@ -#qCopyright 2013-2015 Pervasive Displays, Inc. +# Copyright 2013-2015 Pervasive Displays, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -27,6 +27,7 @@ def b(x): def b(x): return x.encode('ISO-8859-1') + class EPDError(Exception): def __init__(self, value): self.value = value @@ -51,8 +52,8 @@ class EPD(object): epd.update() # refresh the panel image - not needed if auto=true """ - - PANEL_RE = re.compile('^([A-Za-z]+)\s+(\d+\.\d+)\s+(\d+)x(\d+)\s+COG\s+(\d+)\s+FILM\s+(\d+)\s*$', flags=0) + PANEL_RE = re.compile(r'^([A-Za-z]+)\s+(\d+\.\d+)\s+(\d+)x(\d+)\s+' + r'COG\s+(\d+)\s+FILM\s+(\d+)\s*$', flags=0) def __init__(self, *args, **kwargs): self._epd_path = '/dev/epd' @@ -163,10 +164,12 @@ def use_lm75b(self, flag): def error_status(self): with open(os.path.join(self._epd_path, 'error'), 'r') as f: - return(f.readline().rstrip('\n')) + return (f.readline().rstrip('\n')) def rotation_angle(self, rotation): - angles = { 90 : Image.ROTATE_90, 180 : Image.ROTATE_180, 270 : Image.ROTATE_270 } + angles = {90: Image.ROTATE_90, + 180: Image.ROTATE_180, + 270: Image.ROTATE_270} return angles[rotation] def display(self, image): @@ -175,7 +178,8 @@ def display(self, image): # better to do this before calling this if the image is to # be dispayed several times if image.mode != "1": - image = ImageOps.grayscale(image).convert("1", dither=Image.FLOYDSTEINBERG) + image = ImageOps.grayscale(image).convert( + "1", dither=Image.FLOYDSTEINBERG) if image.mode != "1": raise EPDError('only single bit images are supported') @@ -186,13 +190,13 @@ def display(self, image): if self._rotation != 0: image = image.transpose(self.rotation_angle(self._rotation)) - with open(os.path.join(self._epd_path, 'LE', 'display_inverse'), 'r+b') as f: + with open(os.path.join(self._epd_path, 'LE', + 'display_inverse'), 'r+b') as f: f.write(image.tobytes()) if self.auto: self.update() - def update(self): self._command('U') @@ -207,8 +211,8 @@ def clear(self): def _command(self, c): if self._uselm75b: - with open(os.path.join(self._epd_path, 'temperature'), 'wb') as f: + with open(os.path.join(self._epd_path, + 'temperature'), 'wb') as f: f.write(b(repr(self._lm75b.getTempC()))) with open(os.path.join(self._epd_path, 'command'), 'wb') as f: f.write(b(c)) - diff --git a/papirus/image.py b/papirus/image.py index 5cb3d03..75717ca 100644 --- a/papirus/image.py +++ b/papirus/image.py @@ -1,13 +1,11 @@ from __future__ import division -import os -import sys - from PIL import Image from papirus import Papirus WHITE = 1 + class PapirusImage(object): def __init__(self, rotation=0): @@ -16,13 +14,13 @@ def __init__(self, rotation=0): def write(self, imagefile): fileimg = Image.open(imagefile) - w,h = fileimg.size + w, h = fileimg.size rsimg = fileimg if w > self.papirus.width or h > self.papirus.height: rsimg.thumbnail(self.papirus.size) - xpadding = (self.papirus.width - rsimg.size[0]) // 2 + xpadding = (self.papirus.width - rsimg.size[0]) // 2 ypadding = (self.papirus.height - rsimg.size[1]) // 2 image = Image.new('1', self.papirus.size, WHITE) @@ -30,4 +28,3 @@ def write(self, imagefile): self.papirus.display(image) self.papirus.update() - diff --git a/papirus/lm75b.py b/papirus/lm75b.py index f3087f2..6af4bcb 100644 --- a/papirus/lm75b.py +++ b/papirus/lm75b.py @@ -1,31 +1,37 @@ -# Minimal support for LM75b temperature sensor on the Papirus HAT / Papirus Zero +# Minimal support for LM75b temperature sensor +# on the Papirus HAT / Papirus Zero. +# # This module allows you to read the temperature. -# The OS-output (Over-temperature Shutdown) connected to GPIO xx (pin 11) is not supported -# by this module +# +# The OS-output (Over-temperature Shutdown) connected to +# GPIO xx (pin 11) is not supported by this module # from __future__ import (print_function, division) import smbus -LM75B_ADDRESS = 0x48 +LM75B_ADDRESS = 0x48 + +LM75B_TEMP_REGISTER = 0 +LM75B_CONF_REGISTER = 1 +LM75B_THYST_REGISTER = 2 +LM75B_TOS_REGISTER = 3 -LM75B_TEMP_REGISTER = 0 -LM75B_CONF_REGISTER = 1 -LM75B_THYST_REGISTER = 2 -LM75B_TOS_REGISTER = 3 +LM75B_CONF_NORMAL = 0 -LM75B_CONF_NORMAL = 0 class LM75B(object): def __init__(self, address=LM75B_ADDRESS, busnum=1): self._address = address self._bus = smbus.SMBus(busnum) - self._bus.write_byte_data(self._address, LM75B_CONF_REGISTER, LM75B_CONF_NORMAL) + self._bus.write_byte_data(self._address, LM75B_CONF_REGISTER, + LM75B_CONF_NORMAL) def getTempCFloat(self): """Return temperature in degrees Celsius as float""" - raw = self._bus.read_word_data(self._address, LM75B_TEMP_REGISTER) & 0xFFFF + raw = self._bus.read_word_data(self._address, + LM75B_TEMP_REGISTER) & 0xFFFF raw = ((raw << 8) & 0xFF00) + (raw >> 8) return (raw / 32.0) / 8.0 @@ -36,11 +42,12 @@ def getTempFFloat(self): def getTempC(self): """Return temperature in degrees Celsius as integer, so it can be used to write to /dev/epd/temperature""" - raw = self._bus.read_word_data(self._address, LM75B_TEMP_REGISTER) & 0xFFFF + raw = self._bus.read_word_data(self._address, + LM75B_TEMP_REGISTER) & 0xFFFF raw = ((raw << 8) & 0xFF00) + (raw >> 8) - return (raw + 128) // 256 # round to nearest integer + return (raw + 128) // 256 # round to nearest integer + if __name__ == "__main__": sens = LM75B() print(sens.getTempC(), sens.getTempFFloat()) - diff --git a/papirus/readrtc.py b/papirus/readrtc.py index b12a2b8..5f8ba1a 100644 --- a/papirus/readrtc.py +++ b/papirus/readrtc.py @@ -29,24 +29,30 @@ _IOC_WRITE = 1 _IOC_READ = 2 + def _IOC(dir, type, nr, size): return ((dir << _IOC_DIRSHIFT) | (type << _IOC_TYPESHIFT) | (nr << _IOC_NRSHIFT) | (size << _IOC_SIZESHIFT)) + def _IOC_TYPECHECK(t): return len(t) + def _IO(type, nr): return _IOC(_IOC_NONE, type, nr, 0) + def _IOR(type, nr, size): return _IOC(_IOC_READ, type, nr, _IOC_TYPECHECK(size)) + def _IOW(type, nr, size): return _IOC(_IOC_WRITE, type, nr, _IOC_TYPECHECK(size)) + class RtcTime(namedtuple( # man(4) rtc "RtcTime", @@ -61,8 +67,8 @@ def __new__(cls, tm_sec=0, tm_min=0, tm_hour=0, tm_mday=0, tm_mon=0, tm_year=0, tm_wday=0, tm_yday=0, tm_isdst=0): return super(RtcTime, cls).__new__(cls, tm_sec, tm_min, tm_hour, - tm_mday, tm_mon, tm_year, - tm_wday, tm_yday, tm_isdst) + tm_mday, tm_mon, tm_year, + tm_wday, tm_yday, tm_isdst) def to_datetime(self): # From `hwclock.c`. @@ -78,17 +84,20 @@ def pack(self): def unpack(cls, buffer): return cls._make(struct.unpack(cls._fmt, buffer)) + # From /usr/include/linux/rtc.h rtc_time = RtcTime().pack() RTC_RD_TIME = _IOR(ord("p"), 0x09, rtc_time) # 0x80247009 RTC_SET_TIME = _IOW(ord("p"), 0x0a, rtc_time) # 0x4024700a del rtc_time + def get_hwclock(devrtc="/dev/rtc"): with open(devrtc) as rtc: ret = ioctl(rtc, RTC_RD_TIME, RtcTime().pack()) return RtcTime.unpack(ret).to_datetime() -if __name__ == "__main__": - print("Date/Time from RTC: {d:s}".format(d= get_hwclock().strftime("%A %d %B %Y - %H:%M:%S"))) +if __name__ == "__main__": + print("Date/Time from RTC: {d:s}".format( + d=get_hwclock().strftime("%A %d %B %Y - %H:%M:%S"))) diff --git a/papirus/text.py b/papirus/text.py index 81943b9..43457d9 100644 --- a/papirus/text.py +++ b/papirus/text.py @@ -1,27 +1,26 @@ -import os -import sys - from PIL import Image, ImageDraw, ImageFont from papirus import Papirus -import random WHITE = 1 BLACK = 0 + class PapirusText(object): def __init__(self, rotation=0): self.papirus = Papirus(rotation=rotation) - def write(self, text, size=20, fontPath='/usr/share/fonts/truetype/freefont/FreeMono.ttf', maxLines=100): - + def write(self, text, size=20, + fontpath='/usr/share/fonts/truetype/freefont/FreeMono.ttf', + maxlines=100): + # initially set all white background image = Image.new('1', self.papirus.size, WHITE) # prepare for drawing draw = ImageDraw.Draw(image) - font = ImageFont.truetype(fontPath, size) + font = ImageFont.truetype(fontpath, size) # Calculate the max number of char to fit on line lineSize = (self.papirus.width / (size*0.65)) @@ -35,20 +34,20 @@ def write(self, text, size=20, fontPath='/usr/share/fonts/truetype/freefont/Free # Always add first word (even when it is too long) if len(textLines[currentLine]) == 0: textLines[currentLine] += word - elif (draw.textsize(textLines[currentLine] + " " + word, font=font)[0]) < self.papirus.width: + elif (draw.textsize(textLines[currentLine] + + " " + word, font=font)[0]) < self.papirus.width: textLines[currentLine] += " " + word else: # No space left on line so move to next one textLines.append(u"") - if currentLine < maxLines: + if currentLine < maxlines: currentLine += 1 textLines[currentLine] += word currentLine = 0 - for l in textLines: - draw.text( (0, size*currentLine) , l, font=font, fill=BLACK) + for line in textLines: + draw.text((0, size*currentLine), line, font=font, fill=BLACK) currentLine += 1 self.papirus.display(image) self.papirus.update() - diff --git a/papirus/textpos.py b/papirus/textpos.py index 531261d..ba7ed87 100644 --- a/papirus/textpos.py +++ b/papirus/textpos.py @@ -1,12 +1,11 @@ -import os -import sys - from PIL import Image, ImageDraw, ImageFont from papirus import Papirus import uuid WHITE = 1 BLACK = 0 +FONT_PATH = '/usr/share/fonts/truetype/freefont/FreeMono.ttf' + # Class for holding the details of the text class DispText(object): @@ -19,6 +18,7 @@ def __init__(self, text, x, y, size, invert): self.endy = 0 self.invert = invert + class PapirusTextPos(object): def __init__(self, autoUpdate=True, rotation=0): # Set up the PaPirus and dictionary for text @@ -28,60 +28,63 @@ def __init__(self, autoUpdate=True, rotation=0): self.autoUpdate = autoUpdate self.partialUpdates = False - def AddText(self, text, x=0, y=0, size=20, Id=None, invert=False, fontPath='/usr/share/fonts/truetype/freefont/FreeMono.ttf', maxLines=100): - # Create a new Id if none is supplied - if Id is None: - Id = str(uuid.uuid4()) + def AddText(self, text, x=0, y=0, size=20, + ident=None, invert=False, fontpath=FONT_PATH, maxlines=100): + # Create a new id if none is supplied + if ident is None: + ident = str(uuid.uuid4()) - # If the Id doesn't exist, add it to the dictionary - if Id not in self.allText: - self.allText[Id] = DispText(text, x, y, size, invert) + # If the id doesn't exist, add it to the dictionary + if ident not in self.allText: + self.allText[ident] = DispText(text, x, y, size, invert) # add the text to the image - self.addToImageText(Id, fontPath, maxLines) - #Automatically show? + self.addToImageText(ident, fontpath, maxlines) + # Automatically show? if self.autoUpdate: self.WriteAll() - def UpdateText(self, Id, newText, fontPath='/usr/share/fonts/truetype/freefont/FreeMono.ttf', maxLines=100): + def UpdateText(self, ident, newtext, fontpath=FONT_PATH, maxlines=100): # If the ID supplied is in the dictionary, update the text # Currently ONLY the text is update - if Id in self.allText: - self.allText[Id].text = newText + if ident in self.allText: + self.allText[ident].text = newtext - # Remove from the old text from the image (that doesn't use the actual text) - self.removeImageText(Id) + # Remove from the old text from the image + # (that doesn't use the actual text) + self.removeImageText(ident) # Add the new text to the image - self.addToImageText(Id, fontPath, maxLines) - #Automatically show? + self.addToImageText(ident, fontpath, maxlines) + # Automatically show? if self.autoUpdate: self.WriteAll() - def RemoveText(self, Id): + def RemoveText(self, ident): # If the ID supplied is in the dictionary, remove it. - if Id in self.allText: - self.removeImageText(Id) - del self.allText[Id] + if id in self.allText: + self.removeImageText(ident) + del self.allText[ident] - #Automatically show? + # Automatically show? if self.autoUpdate: self.WriteAll() - def removeImageText(self, Id): + def removeImageText(self, ident): # prepare for drawing draw = ImageDraw.Draw(self.image) # Draw over the top of the text with a rectangle to cover it - draw.rectangle([self.allText[Id].x, self.allText[Id].y, self.allText[Id].endx, self.allText[Id].endy], fill="white") + draw.rectangle([self.allText[ident].x, self.allText[ident].y, + self.allText[ident].endx, self.allText[ident].endy], + fill="white") - - def addToImageText(self, Id, fontPath='/usr/share/fonts/truetype/freefont/FreeMono.ttf', maxLines=100): + def addToImageText(self, ident, fontpath=FONT_PATH, maxlines=100): # Break the text item back in to parts - size = self.allText[Id].size - x = self.allText[Id].x - y = self.allText[Id].y + size = self.allText[ident].size + x = self.allText[ident].x + y = self.allText[ident].y fontColor = BLACK backgroundColor = WHITE - if self.allText[Id].invert: + if self.allText[ident].invert: fontColor = WHITE backgroundColor = BLACK @@ -89,7 +92,7 @@ def addToImageText(self, Id, fontPath='/usr/share/fonts/truetype/freefont/FreeMo draw = ImageDraw.Draw(self.image) # Grab the font to use, fixed at the moment - font = ImageFont.truetype(fontPath, size) + font = ImageFont.truetype(fontpath, size) # Calculate the max number of char to fit on line # Taking in to account the X starting position @@ -101,10 +104,10 @@ def addToImageText(self, Id, fontPath='/usr/share/fonts/truetype/freefont/FreeMo textLines = [u""] # Split the text by \n first - toProcess = self.allText[Id].text.splitlines() + to_process = self.allText[ident].text.splitlines() # Go through the lines and add them - for line in toProcess: + for line in to_process: # Add in a line to add the words to textLines.append(u"") currentLine += 1 @@ -113,12 +116,13 @@ def addToImageText(self, Id, fontPath='/usr/share/fonts/truetype/freefont/FreeMo # Always add first word (even it is too long) if len(textLines[currentLine]) == 0: textLines[currentLine] += word - elif (draw.textsize(textLines[currentLine] + " " + word, font=font)[0]) < lineWidth: + elif (draw.textsize(textLines[currentLine] + + " " + word, font=font)[0]) < lineWidth: textLines[currentLine] += " " + word else: # No space left on line so move to next one textLines.append(u"") - if currentLine < maxLines: + if currentLine < maxlines: currentLine += 1 textLines[currentLine] += word @@ -129,45 +133,47 @@ def addToImageText(self, Id, fontPath='/usr/share/fonts/truetype/freefont/FreeMo # Go through all the lines as needed, drawing them on to the image # Reset the ending position of the text - self.allText[Id].endy = y - self.allText[Id].endx = x + self.allText[ident].endy = y + self.allText[ident].endx = x # Start at the beginning, calc all the end locations currentLine = 0 - for l in textLines: + for line in textLines: # Find out the size of the line to be drawn - textSize = draw.textsize(l, font=font) + textSize = draw.textsize(line, font=font) # Adjust the x end point if needed - if textSize[0]+x > self.allText[Id].endx: - self.allText[Id].endx = textSize[0] + x + if textSize[0]+x > self.allText[ident].endx: + self.allText[ident].endx = textSize[0] + x # Add on the y end point - self.allText[Id].endy += size + self.allText[ident].endy += size # If next line does not fit, quit currentLine += 1 - if self.allText[Id].endy > (self.papirus.height - size - 3): + if self.allText[ident].endy > (self.papirus.height - size - 3): del textLines[currentLine:] break # Little adjustment to make sure the text gets covered - self.allText[Id].endy += 3 + self.allText[ident].endy += 3 # If the text is wanted inverted, put a rectangle down first - if self.allText[Id].invert: - draw.rectangle([self.allText[Id].x, self.allText[Id].y, self.allText[Id].endx, self.allText[Id].endy], fill=backgroundColor) + if self.allText[ident].invert: + draw.rectangle([self.allText[ident].x, self.allText[ident].y, + self.allText[ident].endx, self.allText[ident].endy], + fill=backgroundColor) # Start at the beginning, add all the lines to the image currentLine = 0 - for l in textLines: + for line in textLines: # Draw the text to the image yline = y + size*currentLine - draw.text( (x, yline), l, font=font, fill=fontColor) + draw.text((x, yline), line, font=font, fill=fontColor) currentLine += 1 - def WriteAll(self, partialUpdate=False): + def WriteAll(self, partialupdate=False): # Push the image to the PaPiRus device, and update only what's needed # (unless asked to do a full update) self.papirus.display(self.image) - if partialUpdate or self.partialUpdates: + if partialupdate or self.partialUpdates: self.papirus.partial_update() else: self.papirus.update() @@ -177,4 +183,3 @@ def Clear(self): self.image = Image.new('1', self.papirus.size, WHITE) self.allText = dict() self.papirus.clear() - diff --git a/projects/twitter_feed.py b/projects/twitter_feed.py index e4bea8c..3417a4d 100644 --- a/projects/twitter_feed.py +++ b/projects/twitter_feed.py @@ -1,9 +1,9 @@ -import sys,twitter -import datetime +import sys +import twitter import RPi.GPIO as GPIO from time import sleep -from papirus import PapirusText from papirus import Papirus +from papirus import PapirusText from papirus import PapirusTextPos api = twitter.Api() @@ -33,23 +33,26 @@ access_token_secret=access_token_secret ) tweet_index = 0 -text = PapirusTextPos(False, rotation = 0) +text = PapirusTextPos(False, rotation=0) statuses = api.GetHomeTimeline(count=20) + def home_timeline(Home): - name = statuses[tweet_index].user.screen_name - status = statuses[tweet_index].text - return status, name; + name = statuses[tweet_index].user.screen_name + status = statuses[tweet_index].text + return status, name + def next_tweet(): - status, name = home_timeline(sys.argv[1] if len(sys.argv) > 1 else 0) - twitter_name = "@" + name + status, name = home_timeline(sys.argv[1] if len(sys.argv) > 1 else 0) + twitter_name = "@" + name + + text.UpdateText("start", twitter_name) + text.UpdateText("tweet", status) + text.WriteAll() - text.UpdateText("start", twitter_name) - text.UpdateText("tweet", status) - text.WriteAll() -#Display first tweet +# Display first tweet status, name = home_timeline(sys.argv[1] if len(sys.argv) > 1 else 0) twitter_name = "@" + name @@ -58,20 +61,20 @@ def next_tweet(): text.WriteAll() while True: - if (GPIO.input(SW1) == False) and (GPIO.input(SW2) == False) : - write_text(papirus, "Exiting ...", SIZE) - sleep(0.2) - papirus.clear() - sys.exit() + if (GPIO.input(SW1) is False) and (GPIO.input(SW2) is False): + write_text(papirus, "Exiting ...", SIZE) + sleep(0.2) + papirus.clear() + sys.exit() - if GPIO.input(SW4) == False and tweet_index < 19: - tweet_index = tweet_index + 1 - next_tweet() - if GPIO.input(SW3) == False and tweet_index > 0: - tweet_index = tweet_index - 1 - next_tweet() - if GPIO.input(SW1) == False: - statuses = api.GetHomeTimeline(count=20) - tweet_index = 0 - next_tweet() - sleep(0.1) + if GPIO.input(SW4) is False and tweet_index < 19: + tweet_index = tweet_index + 1 + next_tweet() + if GPIO.input(SW3) is False and tweet_index > 0: + tweet_index = tweet_index - 1 + next_tweet() + if GPIO.input(SW1) is False: + statuses = api.GetHomeTimeline(count=20) + tweet_index = 0 + next_tweet() + sleep(0.1) diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..80676bc --- /dev/null +++ b/setup.cfg @@ -0,0 +1,2 @@ +[flake8] +per-file-ignores = __init__.py:F401 diff --git a/setup.py b/setup.py index 494f5ad..c6324a2 100644 --- a/setup.py +++ b/setup.py @@ -1,14 +1,48 @@ #! /usr/bin/env python -from distutils.core import setup +from setuptools import setup +from os.path import join, dirname setup(name='papirus', version='1.0.0', - description="PaPiRus API", + description='PaPiRus API', + long_description=open(join(dirname(__file__), 'README.md')).read(), + long_description_content_type='text/markdown', author='PiSupply', author_email='sales@pi-supply.com', - url='pi-supply.com', + url='https://pi-supply.com', packages=['papirus'], - scripts=['bin/papirus-animation','bin/papirus-buttons', 'bin/papirus-cam', 'bin/papirus-clear', 'bin/papirus-clock', 'bin/papirus-composite-write', 'bin/papirus-config', 'bin/papirus-draw', 'bin/papirus-gol', 'bin/papirus-radar', 'bin/papirus-set', 'bin/papirus-setup', 'bin/papirus-temp', 'bin/papirus-test', 'bin/papirus-system', 'bin/papirus-textfill', 'bin/papirus-twitter', 'bin/papirus-write', 'bin/papirus-snake', 'bin/papirus-fbcopy'], - data_files=[('bitmaps', ['bitmaps/papirus-logo.bmp', 'bitmaps/0.gif', 'bitmaps/1.gif', 'bitmaps/2.gif', 'bitmaps/3.gif', 'bitmaps/4.gif', 'bitmaps/5.gif', 'bitmaps/6.gif', 'bitmaps/7.gif', 'bitmaps/8.gif', 'bitmaps/9.gif', 'bitmaps/10.gif', 'bitmaps/11.gif', 'bitmaps/12.gif', 'bitmaps/13.gif', 'bitmaps/14.gif', 'bitmaps/15.gif', 'bitmaps/papirus-cam-intro.jpg', 'bitmaps/python.png'])] - ) + project_urls={ + "Bug Tracker": "https://github.com/PiSupply/PaPiRus/issues", + }, + scripts=[ + 'bin/papirus-animation', + 'bin/papirus-buttons', + 'bin/papirus-cam', + 'bin/papirus-clear', + 'bin/papirus-clock', + 'bin/papirus-composite-write', + 'bin/papirus-config', + 'bin/papirus-draw', + 'bin/papirus-gol', + 'bin/papirus-radar', + 'bin/papirus-set', + 'bin/papirus-setup', + 'bin/papirus-temp', + 'bin/papirus-test', + 'bin/papirus-system', + 'bin/papirus-textfill', + 'bin/papirus-twitter', + 'bin/papirus-write', + 'bin/papirus-snake', + 'bin/papirus-fbcopy' + ], + data_files=[ + ('bitmaps', [ + 'bitmaps/papirus-logo.bmp', 'bitmaps/0.gif', + 'bitmaps/1.gif', 'bitmaps/2.gif', 'bitmaps/3.gif', + 'bitmaps/4.gif', 'bitmaps/5.gif', 'bitmaps/6.gif', + 'bitmaps/7.gif', 'bitmaps/8.gif', 'bitmaps/9.gif', + 'bitmaps/10.gif', 'bitmaps/11.gif', 'bitmaps/12.gif', + 'bitmaps/13.gif', 'bitmaps/14.gif', 'bitmaps/15.gif', + 'bitmaps/papirus-cam-intro.jpg', 'bitmaps/python.png'])])