#! /usr/bin/env python # python imports import argparse import logging import math import datetime import os import os.path # 3rd party imports from escpos.printer import Usb, Dummy, File import feedparser from PIL import Image import re import requests from config import config # Enable logging logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO) logger = logging.getLogger(__name__) def initialize(): """ Initializes the printer and returns a printer object to generate the print """ printer_id = config.get("PRINTER_USB_ID") if not printer_id: logger.error("Please configure your printer") prid1, prid2 = printer_id.split(":") printer_interface = config.get("PRINTER_INTERFACE") or 0 printer_endpoint = config.get("PRINTER_ENDPOINT") or 0x01 # return Usb(prid1, prid2, printer_interface, printer_endpoint) return File("/dev/usb/lp0") def reset_defaults(printer): """ Reset the printer to the defaults """ printer.set(align='left', font='a', width=1, text_type="normal", height=1, density=9, invert=False, smooth=False, flip=False) def print_weather(printer): reset_defaults(printer) appkey = config.get("OWM") if not appkey: logger.error("Open Weather key not set!") return city = config.get("CITY") if not city: logger.error("No city set") params = {"q": city, "APPID": appkey, "units": "metric"} weatherdata = requests.get('http://api.openweathermap.org/data/2.5/weather', params=params) if "weather" in weatherdata.json(): weather = weatherdata.json() today = datetime.datetime.now() current_day = today.strftime("%a, %d %b, %Y") printer.set(align="center", font="a", text_type="b") printer.text(f"{current_day}\n\n{city}\n") reset_defaults(printer) printer.set(align="center", font="b") description = weather['weather'][0]['description'] printer.text(f"{description}\n\n") icon_code = weather['weather'][0]['icon'] if not os.path.exists(f"icons/weather/{icon_code}.png"): icon_path = "icons/weather/any.png" else: icon_path = f"icons/weather/{icon_code}.png" # TODO: The image impl should be an option printer.image(icon_path, impl="bitImageColumn") printer.text("\n") # TODO: Print a nice icon based on the codes here: https://openweathermap.org/weather-conditions temperature = weather['main']['temp'] humidity = weather['main']['humidity'] wind = weather['wind']['speed'] printer.text(f"Temperature: {temperature}C\n") printer.text(f"Humidity: {humidity}%\n") printer.text(f"Wind: {wind}km\\h\n") else: logger.error("No weather info available") def print_rss(printer, link, news=1): """ Given an RSS link and a printer, prints the news from it """ reset_defaults(printer) feed = feedparser.parse(link) title = feed["channel"]["title"] printer.set(align="center", text_type="BU", width=2, height=2, smooth=True) printer.text(f"{title}\n\n") reset_defaults(printer) items = feed["items"][:news] for item in items: _print_rss_item(item) def _print_rss_item(item): title = item["title"] date = item["published"] text = clear_html(item["summary"]) link = item["link"] printer.set(align="left", text_type="BU", smooth=True) printer.text(f"{title}\n") reset_defaults(printer) printer.set(align="right", font="b") printer.text(f"{date}\n\n") printer.text(text) printer.text("\n") printer.qr(link, size=6) printer.text("\n") def print_text(printer, text): """ Prints a text in the smallest form possible """ reset_defaults(printer) # Set the font to a small one and align to # the left printer.set(align="left", text_type="NORMAL", font="b", smooth=True) printer.text("\n") printer.text(text) def print_file(printer, file): """ Prints a file """ reset_defaults(printer) # Set the font to a small one and align to # the left printer.set(align="left", text_type="NORMAL", font="b", smooth=True) printer.text("\n") for line in file: printer.text(line) file.close() def print_image(printer, image): """ Prints an image """ # Load the image to adjust it im = Image.open(image) ratio = float(im.size[0]) / float(im.size[1]) if im.size[0] > im.size[1]: # The image needs to be rotated width = math.floor(384 * ratio) im = im.resize((width, 384)) im = im.transpose(Image.ROTATE_90) else: height = math.floor(384.0 * ratio) im = im.resize((384, height)) im.save("temp.png") printer.hw("INIT") printer.image("temp.png") os.remove("temp.png") def clear_html(text): cleanr = re.compile('<.*?>|&([a-z0-9]+|#[0-9]{1,6}|#x[0-9a-f]{1,6});') cleantext = re.sub(cleanr, '', text) return cleantext def create_parser(): """ Create an argpaser for command line interaction """ parser = argparse.ArgumentParser() parser.add_argument("--weather", default=False) parser.add_argument("--news", default=False) parser.add_argument("--text", nargs=1, default=None) parser.add_argument("--file", default=None, type=open) parser.add_argument("--image", nargs=1, default=None) return parser if __name__ == "__main__": printer = initialize() parser = create_parser() args = parser.parse_args() if args.text: print_text(printer, args.text[0]) printer.text("\n\n") if args.file: print_file(printer, args.file) printer.text("\n\n") if args.weather: print_weather(printer) printer.text("\n\n") if args.news: print_rss(printer, "https://victorhckinthefreeworld.com/feed/") printer.text("\n\n") print_rss(printer, "https://pedalibre.org/feed/") printer.text("\n\n") print_rss(printer, "https://skyandtelescope.org/observing/sky-at-a-glance/feed/") printer.text("\n\n") print_rss(printer, "https://www.space.com/feeds/all", news=2) printer.text("\n\n") if args.image: print_image(printer, args.image[0]) printer.text("\n\n")