Skip to content

Commit b733215

Browse files
authored
Merge pull request adafruit#1884 from dherrada/oshwa_magtag_display
Added OSHWA MagTag project display
2 parents 1985550 + 2c3d9e0 commit b733215

File tree

4 files changed

+8925
-0
lines changed

4 files changed

+8925
-0
lines changed
5.13 KB
Binary file not shown.

oshwa_magtag_display/code.py

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
# SPDX-FileCopyrightText: 2021 Dylan Herrada for Adafruit Industries
2+
#
3+
# SPDX-License-Identifier: MIT
4+
5+
import random
6+
import ssl
7+
import gc
8+
import wifi
9+
import socketpool
10+
import adafruit_requests as requests
11+
from adafruit_magtag.magtag import MagTag
12+
13+
# Get wifi details and more from a secrets.py file
14+
try:
15+
from secrets import secrets
16+
except ImportError:
17+
print("WiFi secrets are kept in secrets.py, please add them there!")
18+
raise
19+
20+
# Initialize magtag object
21+
magtag = MagTag()
22+
23+
magtag.set_background("bmps/oshwa_full.bmp")
24+
25+
# Set up WiFi
26+
wifi.radio.connect(secrets["ssid"], secrets["password"])
27+
print(f"Connected to {secrets['ssid']}!")
28+
print("My IP address is", wifi.radio.ipv4_address)
29+
30+
socket = socketpool.SocketPool(wifi.radio)
31+
https = requests.Session(socket, ssl.create_default_context())
32+
33+
# Paste your API token below
34+
TOKEN = "YOUR_API_TOKEN"
35+
36+
def font_width_to_dict(font):
37+
# Reads the font file to determine how wide each character is
38+
# Used to avoid bad wrapping breaking the QR code
39+
chars = {}
40+
with open(font, "r") as file:
41+
for line in file:
42+
if "FONTBOUNDINGBOX" in line:
43+
size = int(line.split(" ")[1])
44+
if "ENCODING" in line and "_ENCODING" not in line:
45+
character = chr(int(line.split(" ")[1][:-1]))
46+
chars[character] = None
47+
if "SWIDTH" in line:
48+
swidth = (int(line.split(" ")[1]) / 1000) * size
49+
if "DWIDTH" in line:
50+
chars[character] = int(int(line.split(" ")[1]) + swidth)
51+
return chars
52+
53+
54+
def wrap(text, max_width, max_lines, font):
55+
# Used to wrap the title and description to avoid breaking the QR code
56+
lines = []
57+
ellipsis = 3 * font["."]
58+
line = ""
59+
line_width = 0
60+
for word in text.split(" "):
61+
for character in word:
62+
line_width += font[character]
63+
if (
64+
len(lines) + 1 != max_lines
65+
or sum(font[i] for i in word) + line_width <= max_width
66+
):
67+
if line_width > max_width:
68+
print(str(line_width) + line)
69+
line_width = sum(font[i] for i in word)
70+
lines.append(line.strip())
71+
line = word + " "
72+
break
73+
else:
74+
for char_1 in word:
75+
if line_width + ellipsis + font[char_1] > max_width:
76+
line = line + "..."
77+
print(str(line_width) + line)
78+
lines.append(line)
79+
return "\n".join(lines[:max_lines])
80+
line = line + char_1
81+
line_width += font[char_1]
82+
83+
else:
84+
line = line + word + " "
85+
86+
lines.append(line.strip())
87+
return "\n".join(lines[:max_lines])
88+
89+
90+
91+
# Get first 300 items, saving only the OSHWA UIDs. The first 300 are also used to find the
92+
# number of requests that will need to be made.
93+
# This was done this way since if the items themselves were all asked for and stored, the MagTag
94+
# would run out of memory. If we just got the number of total projects and chose a random number,
95+
# that also wouldn't work as you can only get individual projects with an OSHWA UID and these UIDs
96+
# are prefixed by the country they were registered in, thus making getting it with a simple number
97+
# in-between 1 and the total number of registered projects impossible.
98+
URL = "https://certificationapi.oshwa.org/api/projects?limit=300"
99+
100+
print(URL)
101+
102+
payload = {}
103+
headers = {"Content-Type": "application/json", "Authorization": f"Bearer {TOKEN}"}
104+
105+
oshwaID = []
106+
107+
print("Getting number of projects and first set of 300 projects")
108+
with https.get(URL, headers=headers, data=payload) as response:
109+
R_JSON = response.json()
110+
total = int(R_JSON["total"])
111+
print(f"{total} Projects")
112+
for i in R_JSON["items"]:
113+
oshwaID.append(i["oshwaUid"])
114+
R_JSON.clear()
115+
R_JSON = None
116+
gc.collect()
117+
118+
# Gets the rest of the OSHWA UIDs
119+
print(len(oshwaID))
120+
for i in range(int(total / 300)):
121+
print(f"Getting request {i+2}")
122+
url = (
123+
f"https://certificationapi.oshwa.org/api/projects?limit=300&offset={3*(i+1)}00"
124+
)
125+
with https.get(url, headers=headers, data=payload) as response:
126+
R_JSON = response.json()
127+
for item in R_JSON["items"]:
128+
oshwaID.append(item["oshwaUid"])
129+
R_JSON.clear()
130+
R_JSON = None
131+
gc.collect()
132+
print(f"{len(oshwaID)} IDs gathered")
133+
134+
# Select the UID that will be displayed
135+
selected = random.choice(oshwaID)
136+
137+
# Get the project that will be displayed
138+
url = f"https://certificationapi.oshwa.org/api/projects/{selected}"
139+
response = https.get(url, headers=headers, data=payload)
140+
141+
selected = response.json()[0]
142+
143+
# Filters out characters that the API or the MagTag itself isn't handling correctly
144+
for char in range(1, 32):
145+
selected["projectDescription"].replace(chr(char), "")
146+
147+
selected["projectDescription"] = (
148+
selected["projectDescription"]
149+
.replace("&#x27;", "'")
150+
.replace("&amp;#x27;", "'")
151+
.replace("&#x2F;", "/")
152+
.replace("&quot;", '"')
153+
.replace("’", "'")
154+
)
155+
156+
# Add the two text fields
157+
magtag.add_text(
158+
text_font="fonts/Arial-12.bdf",
159+
text_position=(5, -2),
160+
text_scale=1,
161+
line_spacing=0.6,
162+
text_anchor_point=(0, 0),
163+
)
164+
165+
magtag.add_text(
166+
text_font="fonts/ArialMT-9.bdf",
167+
text_position=(5, 30),
168+
text_scale=1,
169+
line_spacing=0.6,
170+
text_anchor_point=(0, 0),
171+
)
172+
173+
# Create the QR code
174+
url = f"https://certification.oshwa.org/{selected['oshwaUid'].lower()}.html"
175+
magtag.graphics.qrcode(url, qr_size=4, x=173, y=3)
176+
177+
# Prepare to wrap the text correctly by getting the width of each character for every font
178+
arial_12 = font_width_to_dict("fonts/Arial-12.bdf")
179+
arial_9 = font_width_to_dict("fonts/ArialMT-9.bdf")
180+
181+
# Set the text. On some characters, this fails. If so, run the whole file again in 5 seconds
182+
try:
183+
magtag.set_text(wrap(selected["projectName"], 530, 2, arial_12), 0, False)
184+
magtag.set_text(wrap(selected["projectDescription"], 530, 10, arial_9), 1)
185+
magtag.exit_and_deep_sleep(3600)
186+
except Exception: # pylint: disable=broad-except
187+
print("Could not set title or description: unsupported glyphs.")
188+
print("Trying again in 10 seconds.")
189+
magtag.exit_and_deep_sleep(10)

0 commit comments

Comments
 (0)