class PapirusDisplay: def __init__(self): self.papirus = Papirus(rotation=180) self.papirus.clear() self.first_draw = True def update(self, im): self.papirus.display(im) if self.first_draw: self.papirus.update() self.first_draw = False else: self.papirus.partial_update()
class PapirusDisplay(Display.Display): def __init__(self, config, logFilename): self.my_papirus = Papirus(rotation=180) self.WHITE = 1 self.BLACK = 0 super().__init__(config, logFilename) while True: time.sleep(self.fullUpdateInterval*60) self.fullUpdate = True def getWidth(self): return self.my_papirus.width def getHeight(self): return self.my_papirus.height def display(self, image): self.my_papirus.display(image[0]) if self.fullUpdate: self.my_papirus.update() self.fullUpdate = False else: self.my_papirus.partial_update()
class PapirusTextPos(object): def __init__(self, autoUpdate=True, rotation=0): # Set up the PaPirus and dictionary for text self.papirus = Papirus(rotation=rotation) self.allText = dict() self.image = Image.new('1', self.papirus.size, WHITE) 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 == None: Id = 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) # add the text to the image self.addToImageText(Id, fontPath, maxLines) #Automatically show? if self.autoUpdate: self.WriteAll() def UpdateText(self, Id, newText, fontPath='/usr/share/fonts/truetype/freefont/FreeMono.ttf', 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 # Remove from the old text from the image (that doesn't use the actual text) self.removeImageText(Id) # Add the new text to the image self.addToImageText(Id, fontPath, maxLines) #Automatically show? if self.autoUpdate: self.WriteAll() def RemoveText(self, Id): # If the ID supplied is in the dictionary, remove it. if Id in self.allText: self.removeImageText(Id) del self.allText[Id] #Automatically show? if self.autoUpdate: self.WriteAll() def removeImageText(self, Id): # 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") def addToImageText( self, Id, fontPath='/usr/share/fonts/truetype/freefont/FreeMono.ttf', 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 fontColor = BLACK backgroundColor = WHITE if self.allText[Id].invert: fontColor = WHITE backgroundColor = BLACK # prepare for drawing draw = ImageDraw.Draw(self.image) # Grab the font to use, fixed at the moment font = ImageFont.truetype(fontPath, size) # Calculate the max number of char to fit on line # Taking in to account the X starting position lineWidth = self.papirus.width - x # Starting vars currentLine = 0 # Unicode by default textLines = [u""] # Split the text by \n first toProcess = self.allText[Id].text.splitlines() # Go through the lines and add them for line in toProcess: # Add in a line to add the words to textLines.append(u"") currentLine += 1 # Compute each line for word in line.split(): # 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: textLines[currentLine] += " " + word else: # No space left on line so move to next one textLines.append(u"") if currentLine < maxLines: currentLine += 1 textLines[currentLine] += word # Remove the first empty line if len(textLines) > 1: del textLines[0] # 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 # Start at the beginning, calc all the end locations currentLine = 0 for l in textLines: # Find out the size of the line to be drawn textSize = draw.textsize(l, font=font) # Adjust the x end point if needed if textSize[0] + x > self.allText[Id].endx: self.allText[Id].endx = textSize[0] + x # Add on the y end point self.allText[Id].endy += size # If next line does not fit, quit currentLine += 1 if self.allText[Id].endy > (self.papirus.height - size - 3): del textLines[currentLine:] break # Little adjustment to make sure the text gets covered self.allText[Id].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) # Start at the beginning, add all the lines to the image currentLine = 0 for l in textLines: # Draw the text to the image yline = y + size * currentLine draw.text((x, yline), l, font=font, fill=fontColor) currentLine += 1 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: self.papirus.partial_update() else: self.papirus.update() def Clear(self): # Clear the image, clear the text items, do a full update to the screen self.image = Image.new('1', self.papirus.size, WHITE) self.allText = dict() self.papirus.clear()
wakeface(True) while RUNNING: if (GPIO.input(16) == False) and (GPIO.input(21) == False): goodbye() print "bye" RUNNING = False break if not sleeping and (datetime.datetime.now() - lastinput).total_seconds() > 60: sleeping = True if sleeping: facevis = True path = apath + "face6.bmp" image = Image.open(path) papirus.display(image) papirus.partial_update() sleep(.5) path = apath + "face7.bmp" image = Image.open(path) papirus.display(image) papirus.partial_update() sleep(.5) if (GPIO.input(16) == False) or (GPIO.input(20) == False) or ( GPIO.input(21) == False) or (GPIO.input(26) == False): sleeping = False lastinput = datetime.datetime.now() path = apath + "face7.bmp" image = Image.open(path) papirus.display(image) papirus.update() sleep(.30)
class HomeHub(): def __init__(self): #button setup self.SW1 = 21 self.SW2 = 16 self.SW3 = 20 self.SW4 = 19 GPIO.setmode(GPIO.BCM) GPIO.setup(self.SW1, GPIO.IN) GPIO.setup(self.SW2, GPIO.IN) GPIO.setup(self.SW3, GPIO.IN) GPIO.setup(self.SW4, GPIO.IN) #config file self.Config = ConfigParser.ConfigParser() self.Config.read('./config.ini') rotation = int(self.Config.get('PAPIRUS', 'rotation')) fontPath = self.Config.get('PAPIRUS', 'fontPath') self.fontSize = int(self.Config.get('PAPIRUS', 'fontSize')) backgroundPath = self.Config.get('PAPIRUS', 'backgroundPath') self.defaultDisplayOption = self.Config.get('HOMEHUB', 'defaultDisplayOption') self.url = self.Config.get('HOMEHUB', 'url') self.currentLightGroup = 0 self.ResetLightGroups(True) #papirus setup self.initX = 15 self.initY = 40 self.papirusDisplay = Papirus(rotation=rotation) self.papirusDisplay.clear() #papirus screen setup rsimg = Image.open(backgroundPath) self.image = Image.new('1', self.papirusDisplay.size, 1) self.image.paste(rsimg, (0, 0)) self.draw = ImageDraw.Draw(self.image) self.font = ImageFont.truetype(fontPath, self.fontSize) self.CreateTextObject(self.lightGroups[self.currentLightGroup]) self.ButtonRead() def ResetLightGroups(self, init): print 'resetLightGroup' self.jsonLightGroups = self.QueryLightList(self.url) self.lightGroups = self.JsonLightToLightGroupNames( self.jsonLightGroups, self.defaultDisplayOption, init) print 'powerTest:' + str(self.jsonLightGroups[self.lightGroups[ self.currentLightGroup]][0]['power']) #initial homehub query to retrieve light list def QueryLightList(self, url): print 'QueryLightList' queryParams = { self.Config.get('HOMEHUB', 'queryValue'): self.Config.get('HOMEHUB', 'paramValue') } page = requests.get(url, queryParams) #light group setup return json.loads(page.text) def JsonLightToLightGroupNames(self, jsonObject, default, init): lightGroups = [] print 'jsonToNames' for key in jsonObject: lightGroups.append(key) if key == default and init: self.currentLightGroup = len(lightGroups) - 1 return lightGroups def CreateTextObject(self, textToDisplay): self.draw.text((self.initX, self.initY), textToDisplay, font=self.font, fill=0) self.papirusDisplay.display(self.image) self.papirusDisplay.update() self.TextCleanupForFutureDelete(textToDisplay) def TextCleanupForFutureDelete(self, textToDisplay): #calculate some text values for when we want to clear this object textSize = self.draw.textsize(textToDisplay, font=self.font) self.endX = self.initX + textSize[0] self.endY = self.initY + self.fontSize def ClearExistingTextNoUpdate(self): self.draw.rectangle([self.initX, self.initY, self.endX, self.endY], fill='white') def UpdateText(self, textToDisplay): self.ClearExistingTextNoUpdate() self.draw.text((self.initX, self.initY), textToDisplay, font=self.font, fill=0) self.papirusDisplay.display(self.image) self.papirusDisplay.partial_update() def ButtonRead(self): while True: if GPIO.input(self.SW1) == False and GPIO.input(self.SW2) == False: sleep(0.2) self.papirusDisplay.clear() break if GPIO.input(self.SW1) == False: self.currentLightGroup -= 1 if self.currentLightGroup < 0: self.currentLightGroup = len(self.lightGroups) - 1 self.UpdateText(self.lightGroups[self.currentLightGroup]) sleep(0.1) if GPIO.input(self.SW2) == False: self.currentLightGroup += 1 if self.currentLightGroup >= len(self.lightGroups): self.currentLightGroup = 0 self.UpdateText(self.lightGroups[self.currentLightGroup]) sleep(0.1) if GPIO.input(self.SW3) == False: sleep(0.1) if GPIO.input(self.SW4) == False: currentLightStatus = self.jsonLightGroups[self.lightGroups[ self.currentLightGroup]][0]['power'] newLightStatus = 'true' if currentLightStatus: newLightStatus = 'false' print 'lightStatus:' + newLightStatus updateParams = { self.Config.get('HOMEHUB', 'queryValue'): self.Config.get('HOMEHUB', 'updateParamValue'), self.Config.get('HOMEHUB', 'updateGroupQueryValue'): self.lightGroups[self.currentLightGroup], self.Config.get('HOMEHUB', 'updateStatusQueryValue'): newLightStatus } toggle = requests.get(self.url, updateParams, timeout=5) sleep(0.1) self.ResetLightGroups(False) sleep(0.1) sleep(0.1)
class PapirusTextPos(object): def __init__(self, autoUpdate = True, rotation = 0): # Set up the PaPirus and dictionary for text self.papirus = Papirus(rotation = rotation) self.allText = dict() self.image = Image.new('1', self.papirus.size, WHITE) self.autoUpdate = autoUpdate self.partial_updates = False def AddText(self, text, x=0, y=0, size = 20, Id = None, invert=False, font_path='/usr/share/fonts/truetype/freefont/FreeMono.ttf'): # Create a new Id if none is supplied if Id == None: Id = 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) # add the text to the image self.addToImageText(Id, font_path) #Automatically show? if self.autoUpdate: self.WriteAll() def UpdateText(self, Id, newText, font_path='/usr/share/fonts/truetype/freefont/FreeMono.ttf'): # 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 # Remove from the old text from the image (that doesn't use the actual text) self.removeImageText(Id) # Add the new text to the image self.addToImageText(Id, font_path) #Automatically show? if self.autoUpdate: self.WriteAll() def RemoveText(self, Id): # If the ID supplied is in the dictionary, remove it. if Id in self.allText: self.removeImageText(Id) del self.allText[Id] #Automatically show? if self.autoUpdate: self.WriteAll() def removeImageText(self, Id): # 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") def addToImageText(self, Id, font_path='/usr/share/fonts/truetype/freefont/FreeMono.ttf'): # Break the text item back in to parts size = self.allText[Id].size x = self.allText[Id].x y = self.allText[Id].y font_col = BLACK back_col = WHITE if self.allText[Id].invert: font_col = WHITE back_col = BLACK # prepare for drawing draw = ImageDraw.Draw(self.image) # Grab the font to use, fixed at the moment font = ImageFont.truetype(font_path, size) # Calculate the max number of char to fit on line # Taking in to account the X starting position line_size = ((self.papirus.width - x) / (size*0.65)) # Starting vars current_line = 0 # unicode by default text_lines = [u""] # Split the text by \n first toProcess = self.allText[Id].text.splitlines() # Go through the lines and add them for line in toProcess: # Add in a line to add the words to text_lines.append("") # Compute each line for word in line.split(): # If there is space on line add the word to it if (len(text_lines[current_line]) + len(word)) < line_size: # Only add a space if there`s something on the line if len(text_lines[current_line]) > 0: text_lines[current_line] += " " text_lines[current_line] += word else: # No space left on line so move to next one text_lines.append("") current_line += 1 text_lines[current_line] += " " + word # Move the pointer to next line current_line +=1 # 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 # Start at the beginning, calc all the end locations current_line = 0 for l in text_lines: current_line += 1 # Find out the size of the line to be drawn textSize = draw.textsize(l, font=font) # Adjust the x end point if needed if textSize[0]+x > self.allText[Id].endx: self.allText[Id].endx = textSize[0] + x # Add on the y end point self.allText[Id].endy += textSize[1] # Little adjustment to make sure the text gets covered self.allText[Id].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=back_col) # Start at the beginning, add all the lines to the image current_line = 0 for l in text_lines: current_line += 1 # Draw the text to the image draw.text( (x, ((size*current_line)-size) + y) , l, font=font, fill=font_col) def WriteAll(self, partial_update=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 partial_update or self.partial_updates: self.papirus.partial_update() else: self.papirus.update() def Clear(self): # Clear the image, clear the text items, do a full update to the screen self.image = Image.new('1', self.papirus.size, WHITE) self.allText = dict() self.papirus.clear()
class Screen: def __init__(self): # Check EPD_SIZE is defined EPD_SIZE = 0.0 if os.path.exists('/etc/default/epd-fuse'): exec(open('/etc/default/epd-fuse').read()) if EPD_SIZE == 0.0: print( "Please select your screen size by running 'papirus-config'.") self.papirus = Papirus(rotation=0) self.papirus.clear() # Setting the screen color self.BLACK = 0 self.WHITE = 1 # Initally set all white background self.image = Image.new('1', self.papirus.size, self.WHITE) # Prepare for drawing self.draw = ImageDraw.Draw(self.image) self.width, self.height = self.image.size # Setting the size/font for the name self.nameSize = int((self.width - 4) / (8 * 0.65)) self.nameFont = ImageFont.truetype(nameFont, self.nameSize) # Setting the size/font for the data self.dataSize = int( (self.width - MAX_DATA_SIZE) / (MAX_DATA_SIZE * 0.65)) self.dataFont = ImageFont.truetype(dataFont, self.dataSize) # Setting the size/font for time and date self.clockSize = int((self.width - 4) / (8 * 0.65)) self.clockFont = ImageFont.truetype( '/usr/share/fonts/truetype/freefont/FreeMonoOblique.ttf', self.clockSize) self.dateSize = int((self.width - 10) / (10 * 0.65)) self.dateFont = ImageFont.truetype( '/usr/share/fonts/truetype/freefont/FreeMono.ttf', self.dateSize) def updateScreen(self, n, d, s): self.image = Image.new('1', self.papirus.size, self.WHITE) self.draw = ImageDraw.Draw(self.image) # Display the data first self.draw.rectangle((0, 0, self.papirus.size[0], self.papirus.size[1]), fill=self.WHITE, outline=self.WHITE) self.draw.text((5, self.dataSize + MAX_DATA_SIZE), ('%s' % d), fill=self.BLACK, font=self.dataFont) # Display the name second self.draw.rectangle((3, 3, self.width - 3, self.nameSize), fill=self.WHITE, outline=self.WHITE) self.nameFont = ImageFont.truetype(nameFont, self.nameSize) self.draw.text((5, 5), ('%s:' % n), fill=self.BLACK, font=self.nameFont) if s: axis_y = self.dataSize + MAX_DATA_SIZE while axis_y > ((-96 * 2) + (len(d) / 2)): self.draw.text((5, axis_y), ('%s' % d), fill=self.BLACK, font=self.dataFont) self.displayScreen() if axis_y == self.dataSize + MAX_DATA_SIZE: sleep(3) axis_y -= 5 sleep(0.05) self.draw.rectangle( (0, 0, self.papirus.size[0], self.papirus.size[1]), fill=self.WHITE, outline=self.WHITE) self.displayScreen() sleep(3) # Update the screen def displayScreen(self): self.papirus.display(self.image) self.papirus.partial_update() # Display the time and date def displayTime(self): self.image = Image.new('1', self.papirus.size, self.WHITE) self.draw = ImageDraw.Draw(self.image) now = datetime.today() self.draw.text((10, self.dateSize + 10), '{d:02d}.{m:02d}.{y:04d}'.format(y=now.year, m=now.month, d=now.day), fill=self.BLACK, font=self.dateFont) self.draw.text((40, 10), '{h:02d}:{m:02d}'.format(h=now.hour, m=now.minute), fill=self.BLACK, font=self.clockFont) self.displayScreen() # Set the size of the name # Either 37 or 25 def setNameSize(self, ns): self.nameSize = ns def getNameSize(self): return self.nameSize def clearScreen(self): self.papirus.clear()