Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/too long #260

Merged
merged 5 commits into from
Jul 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,11 @@ private fun embeddedWebServer(
imageBin()
imagePng()

// Callable from ZeFlasher only?
adminCreateUser(users, ai)
adminListUsers(users)
adminDeleteUser(users)
adminCreateUserBadge(users)

// TODO: Check if callable from ZeBadge (no ssl)
updateUser(users)
getUser(users)
getUserProfileImageBinary(users)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ import io.ktor.server.application.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import java.awt.image.BufferedImage
import java.io.File
import java.util.*
import javax.imageio.ImageIO


fun Route.adminCreateUser(users: UserRepository, ai: AI) =
Expand Down Expand Up @@ -46,6 +48,41 @@ fun Route.adminCreateUser(users: UserRepository, ai: AI) =
}
}

fun Route.adminCreateUserBadge(users: UserRepository) =
get("/api/user/{uuid}/badge") {
runCatching {
ifAuthorized {
withParameter("uuid") { uuid ->
val user = users.getUser(uuid)
if (user != null) {
val baseBadgeResource = javaClass.classLoader.getResource("zeAlternativeBadge.bmp")
val baseBadge = ImageIO.read(baseBadgeResource)
val resultBadge = BufferedImage(baseBadge.width, baseBadge.height, BufferedImage.TYPE_INT_RGB)

val profileImageFile = File("./profiles/${uuid}.png")
val profile = ImageIO.read(profileImageFile)

val g = resultBadge.graphics
g.drawImage(baseBadge, 0, 0, 296, 128, null)
g.drawImage(profile, 16, 16, 128 - 32, 128 - 32, null)

g.font = g.font.deriveFont(34f)
user.name.split(' ').forEachIndexed { index, part ->
g.drawString(part, 124, 54 + index * 40)
}

call.respondOutputStream {
ImageIO.write(resultBadge, "bmp", this)
}
}
}
}
}.onFailure {
it.printStackTrace()
call.respondText("Error: ${it.message}.")
}
}

fun Route.adminListUsers(users: UserRepository) =
get("/api/user") {
runCatching {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ class ZePassRepository private constructor(
}

fun getOptimizedPosts(users: UserRepository): List<OptimizedPosts> {
return posts.map {
return posts.takeLast(8).map {
OptimizedPosts(
message = it.message,
profileB64 = users.getUser(it.posterUUID)?.profileB64,
Expand Down
Binary file not shown.
Binary file added zeassets/zeAlternativeBadge.bmp
Binary file not shown.
Binary file added zeassets/zeAlternativeBadge.xcf
Binary file not shown.
34 changes: 34 additions & 0 deletions zehardware/src/app_zealterego.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import displayio

import zeos
from message import Message
from ui import MessageKey as UIKeys


class ZeAlterEgoApp:
def __init__(self, os: zeos.ZeBadgeOs):
self.os = os
self.subscription_ids = []

def run(self):
self.subscription_ids += [
self.os.subscribe(
zeos.MessageKey.BUTTON_CHANGED,
lambda os, message: self._show()
),
]

self._show()

def unrun(self):
for subscription in self.subscription_ids:
self.os.unsubscribe(subscription)

def _show(self):
odb = displayio.OnDiskBitmap("zeAlternative.bmp")
self.os.messages.append(
Message(
UIKeys.SHOW_BITMAP,
(odb, odb.pixel_shader)
)
)
27 changes: 15 additions & 12 deletions zehardware/src/app_zepass.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,33 +113,36 @@ def _update_all_posts(self, raw_posts):

try:
posts = json.loads(raw_posts)
except ValueError:
if "+IPD" in raw_posts:
posts = json.loads(raw_posts.split(':', 1)[1])
else:
print(f'Could not parse response: {raw_posts}')
return
except ValueError as e:
print(f'Could not parse response: {raw_posts}')
return

for index, post in enumerate(posts):
# TODO: ADD FANCY USER LOGO HERE
post_area = label.Label(
font,
scale=2,
text=post['message'],
background_color=0x000000,
color=0xFFFFFF,
)
x_offset =(index % 2) * 16
post_area.x = x_offset + 40
post_area.y = 16 + index * 32
if index % 2 == 0:
post_area.x = 40
else:
post_area.x = int(296 / 2)

post_area.y = 16 + index * 16

group.append(post_area)
if 'profileB64' in post and post['profileB64']:
profile = post['profileB64']
bitmap, palette = ui.decode_serialized_bitmap(profile, 32, 32)
profile_grid = displayio.TileGrid(bitmap, pixel_shader=palette)
profile_grid.x = x_offset
profile_grid.y = index * 32
if index % 2 == 0:
profile_grid.x = 0
else:
profile_grid.x = 296 - 32

profile_grid.y = index * 16
group.append(profile_grid)
else:
print(f'no profile for message {index}.')
Expand Down
76 changes: 45 additions & 31 deletions zehardware/src/wifi.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import re
import time

import board
Expand Down Expand Up @@ -45,7 +46,8 @@ class ZeWifi:
# The module attached needs to speak AT commands, and this class encapsulates those
# into nice little methods.

def __init__(self):
def __init__(self, verbose=False):
self.verbose = verbose
self.uart = busio.UART(
microcontroller.pin.GPIO4,
microcontroller.pin.GPIO5,
Expand All @@ -56,6 +58,10 @@ def __init__(self):
def deinit(self):
self.uart.deinit()

def log(self, message):
if self.verbose:
print(message)

def scan(self) -> map[str:list[Network]] | None:
self.uart.write('AT+CWLAP\r\n')
response = self.uart.read()
Expand Down Expand Up @@ -134,7 +140,7 @@ def _http_method(self, method: str, ip: str, url: str, host: str = "", port: int
response = self.uart.read()

if len(response) >= 0:
response = _parse_response(response.decode())
response = self._parse_response(response.decode())
else:
response = None

Expand All @@ -144,6 +150,43 @@ def _http_method(self, method: str, ip: str, url: str, host: str = "", port: int

return response

def _parse_response(self, response: str) -> HttpResponse | None:
# replace / ignore length statements
response = re.sub(r'\+IPD,[0-9]+:', '', response)

parts = response.replace('\r\n', '\n').splitlines()
self.log(f'parts: ')
for i, p in enumerate(parts):
self.log(f' {i:02d}: {p}')

meta_parts = parts[:5]
self.log(f'meta: {meta_parts}')

http_parts = parts[5:]
http_code, status_code = http_parts.pop(0).strip().split()

status_code = int(status_code)
self.log(f'code {status_code}')

headers = {}
header_separator_index = -1
for index, header in enumerate(http_parts):
if header == '':
header_separator_index = index
break

key, value = header.split(":", 1)
key = key.strip()
value = value.strip()

# nope, keep iterating through headers
headers[key] = value.strip()

body = "".join(http_parts[header_separator_index:])
response = HttpResponse(status_code, headers, body)
self.log(response)
return response

def http_get(self, ip: str, url: str, host: str = "", port: int = 80) -> HttpResponse | None:
return self._http_method("GET", ip, url, host, port)

Expand Down Expand Up @@ -208,32 +251,3 @@ def init(os) -> bool:
return True
else:
return False


def _parse_response(response: str) -> HttpResponse | None:
parts = response.replace('\r\n', '\n').splitlines()[5:]

status_code = parts.pop(0)
if status_code.startswith('+IPD'):
_, code = status_code.split(':')
_, status_code, _ = code.split(' ')
status_code = int(status_code)
else:
status_code = 444

headers = {}
for index, header in enumerate(parts):
try:
key, value = header.split(":", 1)
except ValueError:
break

key = key.strip()
value = value.strip()

# nope, keep iterating through headers
headers[key] = value.strip()

body = parts[-1]
response = HttpResponse(status_code, headers, body)
return response
5 changes: 2 additions & 3 deletions zehardware/src/zeos.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import ui
from app_developer_idle_clicker import DeveloperIdleClickerApp
from app_zepass import ZePassApp
from app_zealterego import ZeAlterEgoApp
from app_store_and_show import StoreAndShowApp
from config import fields_to_str
from config import load_config
Expand Down Expand Up @@ -191,15 +192,13 @@ def _init_interfaces(self):

def _init_apps(self):
self._app_a = StoreAndShowApp(self)
self._app_b = ZeAlterEgoApp(self)

if self.config["wifi.attached"]:
self._app_b = None
self._app_c = ZePassApp(self)
elif self.config['keyboard.attached']:
self._app_b = None
self._app_c = DeveloperIdleClickerApp(self)
else:
self._app_b = None
self._app_c = DeveloperIdleClickerApp(self)

self._start_app(self._app_a)
Expand Down
16 changes: 13 additions & 3 deletions zehardware/zefirmware/zeflash.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
#
# FLASH ME IF YOU CAN!!
#
import datetime
import os
import requests
import subprocess
import shutil
import subprocess
import time

import requests

OPEN_AI_TOKEN = os.getenv("OPEN_AI_TOKEN")
SERVER_TOKEN = os.getenv("ZESERVER_AUTH_TOKEN")
BASE_URL = "https://zebadge.app/"
Expand Down Expand Up @@ -267,6 +267,16 @@ def inject_user(user):
user_config
)

open(circuit + "/zeAlternative.bmp", "w").write(
requests.get(
url=f"{BASE_URL}/api/user/{user['uuid']}/badge",
headers={
'Content-Type': 'application/json',
'ZeAuth': SERVER_TOKEN
},
).content.decode()
)


if __name__ == '__main__':
badge_path = find_base_badge_path()
Expand Down
Loading