Compare commits
7 Commits
3333871947
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 66837ea038 | |||
| 61eed0d0f9 | |||
| 018643dde9 | |||
| 8758248fea | |||
| 26cea15bdf | |||
| 9c60f7c37b | |||
| 69eacb4f17 |
1
.env.sample
Normal file
1
.env.sample
Normal file
@@ -0,0 +1 @@
|
||||
HAS_TOKEN=xxx
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -175,4 +175,7 @@ cython_debug/
|
||||
|
||||
|
||||
*.bmp
|
||||
*.png
|
||||
*.png
|
||||
credentials.json
|
||||
|
||||
.env
|
||||
BIN
Nunito-Bold.ttf
Normal file
BIN
Nunito-Bold.ttf
Normal file
Binary file not shown.
18
README.md
Normal file
18
README.md
Normal file
@@ -0,0 +1,18 @@
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
sudo apt update
|
||||
sudo apt install python3-pip
|
||||
|
||||
git clone https://github.com/pimoroni/inky
|
||||
cd inky
|
||||
./install.sh
|
||||
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
## Todo
|
||||
|
||||
- [ ] Accurate temp
|
||||
@@ -1,7 +1,10 @@
|
||||
from inky import InkyWHAT
|
||||
from inky.auto import auto
|
||||
from dotenv import load_dotenv
|
||||
from building import draw_image
|
||||
|
||||
load_dotenv()
|
||||
|
||||
display = auto(verbose = True)
|
||||
image = draw_image()
|
||||
display.set_image(image)
|
||||
|
||||
142
building.py
142
building.py
@@ -1,27 +1,38 @@
|
||||
from PIL import Image
|
||||
from PIL import ImageDraw
|
||||
from PIL import ImageFont
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timedelta
|
||||
from time import gmtime, strftime
|
||||
import time
|
||||
from itertools import groupby
|
||||
from hasApi import get_calendar_events, get_todo_items
|
||||
import dateutil.parser
|
||||
from dotenv import load_dotenv
|
||||
|
||||
black = '#000000'
|
||||
white = '#ffffff'
|
||||
black = "#000000"
|
||||
white = "#ffffff"
|
||||
|
||||
|
||||
fontSymbols = ImageFont.truetype("SymbolsNerdFont-Regular.ttf", 18)
|
||||
fontTitle = ImageFont.truetype("Nunito-SemiBold.ttf", 24)
|
||||
fontLarge = ImageFont.truetype ("Nunito-ExtraLight.ttf", 18)
|
||||
fontSmall = ImageFont.truetype ("Nunito-ExtraLight.ttf", 16)
|
||||
fontTitle = ImageFont.truetype("Nunito-Bold.ttf", 24)
|
||||
fontLarge = ImageFont.truetype("Nunito-ExtraLight.ttf", 18)
|
||||
fontLargeBold = ImageFont.truetype("Nunito-SemiBold.ttf", 18)
|
||||
fontSmall = ImageFont.truetype("Nunito-ExtraLight.ttf", 16)
|
||||
fontVerySmall = ImageFont.truetype("Nunito-ExtraLight.ttf", 10)
|
||||
|
||||
|
||||
class Space(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def getsize(font, text):
|
||||
_, _, right, bottom = font.getbbox(text)
|
||||
return (right, bottom)
|
||||
|
||||
|
||||
def reflow_quote(quote, width, font):
|
||||
words = quote.split(" ")
|
||||
reflowed = ''
|
||||
reflowed = ""
|
||||
line_length = 0
|
||||
|
||||
for i in range(len(words)):
|
||||
@@ -39,52 +50,125 @@ def reflow_quote(quote, width, font):
|
||||
|
||||
return reflowed
|
||||
|
||||
|
||||
def draw_image():
|
||||
image = Image.new("P", (400, 300))
|
||||
draw = ImageDraw.Draw(image)
|
||||
|
||||
# Draw the top bar
|
||||
topbar = 26
|
||||
draw.rectangle((0, 0, 400, 300), fill=white)
|
||||
draw.rectangle((0, 0, 400, 40), fill=black)
|
||||
draw.rectangle((0, 0, 400, topbar), fill=black)
|
||||
|
||||
# Add the clock
|
||||
timeStr = strftime("%H:%M", time.localtime())
|
||||
draw.text((10, 10), timeStr, white, fontSmall)
|
||||
draw.text((10, 3), timeStr, white, fontSmall)
|
||||
|
||||
# Add indoor tempriture
|
||||
draw.text((350, 10), "19c", white, fontSmall)
|
||||
# Add indoor temperature
|
||||
draw.text((350, 3), "19c", white, fontSmall)
|
||||
|
||||
# Add sections
|
||||
ep = 5
|
||||
draw.rounded_rectangle((ep, 40+ep, (400/2)-ep, 300-ep), 10, outline=black)
|
||||
draw.rounded_rectangle(((400/2) + ep, 40+ep, 400-ep, 300-ep), 10, outline=black)
|
||||
ep = 3
|
||||
margin = 5
|
||||
draw.rounded_rectangle(
|
||||
(margin, topbar + margin, (400 / 2) - margin, 300 - margin),
|
||||
10,
|
||||
outline=black,
|
||||
width=2,
|
||||
)
|
||||
draw.rounded_rectangle(
|
||||
((400 / 2) + margin, topbar + margin, 400 - margin, 300 - margin),
|
||||
10,
|
||||
outline=black,
|
||||
width=2,
|
||||
)
|
||||
|
||||
# Add tasks
|
||||
draw.text((15, 50), 'Tasks', black, fontTitle)
|
||||
draw.text((20, topbar + 7), "Tasks", black, fontTitle)
|
||||
draw.line((margin, 62, 200 - margin, 62), fill=black, width=1)
|
||||
|
||||
tasks = [
|
||||
{'done': False, 'title': 'Something'},
|
||||
{'done': True, 'title': 'Get the Modus and Audi MOTs organised'},
|
||||
{'done': False, 'title': 'Something else'},
|
||||
{'done': False, 'title': 'Call locksmith'},
|
||||
]
|
||||
tasks = get_todo_items()
|
||||
|
||||
taskStart = 90
|
||||
taskStart = 70
|
||||
for task in tasks:
|
||||
if task['done']:
|
||||
draw.text((15, taskStart), '', black, fontSymbols)
|
||||
if task["status"] == "completed":
|
||||
continue
|
||||
draw.text((15, taskStart - 2), "", black, fontSymbols)
|
||||
else:
|
||||
draw.text((15, taskStart), '', black, fontSymbols)
|
||||
draw.text((15, taskStart), "", black, fontSymbols)
|
||||
|
||||
reflowedTitle = reflow_quote(task['title'], 170, fontLarge)
|
||||
reflowedTitle = reflow_quote(task["summary"], 160, fontLarge)
|
||||
titleSizeW, titleSizeH = getsize(fontLarge, reflowedTitle)
|
||||
titleSizeH *= (reflowedTitle.count('\n') + 1)
|
||||
titleSizeH *= reflowedTitle.count("\n") + 1
|
||||
|
||||
draw.text((35, taskStart - 3), reflowedTitle, black, fontLarge)
|
||||
taskStart += titleSizeH + (2*ep)
|
||||
taskStart += titleSizeH + (2 * ep)
|
||||
|
||||
# Add cal
|
||||
draw.text((220, topbar + 7), "Calendar", black, fontTitle)
|
||||
draw.line(((400 / 2) + margin, 62, 400 - margin, 62), fill=black, width=1)
|
||||
events = get_calendar_events()
|
||||
|
||||
def get_start_date(x):
|
||||
start = x["start"]
|
||||
if "date" in start:
|
||||
startDate = datetime.strptime(start["date"], "%Y-%m-%d").date()
|
||||
elif "dateTime" in start:
|
||||
startDate = datetime.strptime(start["dateTime"][:10], "%Y-%m-%d").date()
|
||||
else:
|
||||
print("Error")
|
||||
print(start)
|
||||
return None
|
||||
if startDate < datetime.today().date():
|
||||
return datetime.today().date()
|
||||
else:
|
||||
return startDate
|
||||
|
||||
itemStart = 70
|
||||
for key, group in groupby(events, get_start_date):
|
||||
dayStart = itemStart
|
||||
# Calculate
|
||||
if key == datetime.today().date():
|
||||
dateStr = "Today"
|
||||
elif key == (datetime.today() + timedelta(days=1)).date():
|
||||
dateStr = "Tomorrow"
|
||||
else:
|
||||
dateStr = key.strftime("%d %b")
|
||||
|
||||
w, h = getsize(fontLarge, "Today")
|
||||
dayStart += h + (ep)
|
||||
|
||||
dayTasks = list(group)
|
||||
|
||||
for thing in dayTasks:
|
||||
reflowedItem = reflow_quote(thing["summary"], 170, fontSmall)
|
||||
w, h = getsize(fontLarge, "Today")
|
||||
h *= reflowedItem.count("\n") + 1
|
||||
dayStart += h + (ep)
|
||||
|
||||
dayStart + ep
|
||||
|
||||
if dayStart > 280:
|
||||
print()
|
||||
break
|
||||
|
||||
# Commit if possible
|
||||
draw.text((215, itemStart), dateStr, black, fontLargeBold)
|
||||
w, h = getsize(fontLargeBold, dateStr)
|
||||
itemStart += h + ep
|
||||
for thing in dayTasks:
|
||||
reflowedItem = reflow_quote(thing["summary"], 170, fontSmall)
|
||||
w, h = getsize(fontSmall, thing["summary"])
|
||||
h *= reflowedItem.count("\n") + 1
|
||||
draw.text((230, itemStart), reflowedItem, black, fontSmall)
|
||||
itemStart += h + ep
|
||||
|
||||
itemStart += ep
|
||||
|
||||
return image
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
load_dotenv()
|
||||
img = draw_image()
|
||||
img.save('built.bmp')
|
||||
img.save("built.bmp")
|
||||
|
||||
5
dev_reqs.txt
Normal file
5
dev_reqs.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
pillow
|
||||
imgkit
|
||||
requests
|
||||
python-dotenv
|
||||
python-dateutil
|
||||
48
hasApi.py
Normal file
48
hasApi.py
Normal file
@@ -0,0 +1,48 @@
|
||||
import requests
|
||||
import datetime
|
||||
from dotenv import load_dotenv
|
||||
import os
|
||||
|
||||
|
||||
def get_calendar_events():
|
||||
token = os.getenv("HAS_TOKEN")
|
||||
if not token:
|
||||
raise Exception("Missing HAS token")
|
||||
|
||||
headers = {"Authorization": f"Bearer {token}"}
|
||||
payload = {
|
||||
"start": datetime.datetime.now().strftime("%Y-%m-%d"),
|
||||
"end": (datetime.datetime.now() + datetime.timedelta(days=14)).strftime(
|
||||
"%Y-%m-%d"
|
||||
),
|
||||
}
|
||||
response = requests.get(
|
||||
"https://has.nozzy.online/api/calendars/calendar.romosborne_gmail_com",
|
||||
headers=headers,
|
||||
params=payload,
|
||||
)
|
||||
return response.json()
|
||||
|
||||
|
||||
def get_todo_items():
|
||||
token = os.getenv("HAS_TOKEN")
|
||||
if not token:
|
||||
raise Exception("Missing HAS token")
|
||||
headers = {"Authorization": f"Bearer {token}"}
|
||||
payload = {"entity_id": "todo.todo_2"}
|
||||
params = {"return_response": "null"}
|
||||
response = requests.post(
|
||||
"https://has.nozzy.online/api/services/todo/get_items",
|
||||
headers=headers,
|
||||
params=params,
|
||||
json=payload,
|
||||
)
|
||||
data = response.json()
|
||||
return data["service_response"]["todo.todo_2"]["items"]
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
load_dotenv()
|
||||
events = get_todo_items()
|
||||
for item in events:
|
||||
print(item["summary"])
|
||||
@@ -1,3 +1,6 @@
|
||||
pillow
|
||||
inky
|
||||
imgkit
|
||||
requests
|
||||
python-dotenv
|
||||
python-dateutil
|
||||
Reference in New Issue
Block a user