Giter Site home page Giter Site logo

frameos / frameos Goto Github PK

View Code? Open in Web Editor NEW
320.0 5.0 8.0 5.35 MB

Operating system for single function smart frames

Home Page: https://frameos.net/

License: Apache License 2.0

Python 9.58% HTML 0.47% JavaScript 0.72% Procfile 0.01% CSS 0.05% TypeScript 14.53% Mako 0.02% Dockerfile 0.13% Shell 0.01% Makefile 0.17% Nim 28.01% C 46.31%
framebuffer hdmi inky inkyimpression pimoroni raspberry-pi waveshare waveshare-epaper

frameos's Introduction

FrameOS

FrameOS is an operating system for single function smart frames.

It's meant to be deployed on a Raspberry Pi, and can be used with a variety of e-ink and traditional displays. It's designed for both screens that update 60 seconds per frame, and for screens that update 60 frames per second.

Think smart home calendars, meeting room displays, thermostats, industrial dashboards, public advertisement screens, and more.

To get started:

  1. Install the FrameOS controller, a dockerized python app, which is used to deploy apps onto individual frames via SSH.

  2. Read the device hardware guide for your screen type. Typically you'll just need to connect the display to a Raspberry Pi, install the OS, and make sure it's reachable over the network.

  3. Once connected, deploy our prebuilt apps, or code your own directly inside the controller.

  4. Finally, for a professional look, 3d print a case around your frame.

Supported platforms

Supported are all the most common e-ink displays out there.

  • Pimoroni e-ink frames
  • Waveshare e-ink
  • Framebuffer HDMI output
  • Web server kiosk mode

See the full list here!

FrameOS controller

The FrameOS controller is where you set up your frames. You can run it continuously on a server, or locally on your computer when needed. You'll just miss out on log aggregation if the controller is offline. The frames run independently.

Read more in the documentation.

Docker quickstart

# running the latest release
SECRET_KEY=$(openssl rand -base64 32)
docker run -d -p 8989:8989 -v ./db:/app/db --name frameos --restart always -e SECRET_KEY="$SECRET_KEY" frameos/frameos

# update daily to the latest release
docker run -d \
    --name watchtower \
    -v /var/run/docker.sock:/var/run/docker.sock \
    containrrr/watchtower \
    --interval 86400 \
    frameos

# one time update
docker run \
    -v /var/run/docker.sock:/var/run/docker.sock \
    containrrr/watchtower \
    --run-once \
    frameos

# running a local dev build via docker
SECRET_KEY=$(openssl rand -base64 32)
docker build -t frameos .
docker run -d -p 8989:8989 -v ./db:/app/db --name frameos --restart always -e SECRET_KEY="$SECRET_KEY" frameos

frameos's People

Contributors

alexrudd2 avatar danielhoherd avatar mariusandra avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

frameos's Issues

Parse error in frameos/src/drivers/waveshare/driver.nim using waveshare.EPD_4in2_V2 device

Hi there, this project looks powerful!

I'm trying to get the default FrameOS app up and running through my Pi Zero 2 W and a Waveshare 4in2 V2. Happy to help implement and test, but I have a basic question first...

On deploy, I get the below parse error in one of the base auto-generated Waveshare driver files. I understand that 4in2V2 isn't tested yet, but should I be getting the below error in the base files?

Another thing I noticed in driver.nim is that the base driver explicitly pulls width and height from the 2in13 V3.

Thanks! Logs below contains reference to the parse error

2024-01-12 18:40:25 Connecting via SSH to XXX (password)
2024-01-12 18:40:29 Connected via SSH to XXX
2024-01-12 18:40:29 - Getting target architecture
2024-01-12 18:40:29 > uname -m
2024-01-12 18:40:29 armv6l
2024-01-12 18:40:30 - Copying build folders
2024-01-12 18:40:30 - Applying local modifications
2024-01-12 18:40:30 - Generating scene: default
2024-01-12 18:40:30 - Generating app: 4ed62ec9-3b11-4a3a-9d3e-844b137240b1 (frameOSGallery)
2024-01-12 18:40:30 - Creating build archive
2024-01-12 18:40:30 - No cross compilation. Generating source code for compilation on frame.
2024-01-12 18:40:30 $ cd /tmp/tmpmw2dv5jz/frameos && nimble assets -y && nim compile --os:linux --cpu:arm --compileOnly --genScript --nimcache:/tmp/tmpmw2dv5jz/build_wbgvmccqmczf src/frameos.nim 2>&1
2024-01-12 18:40:30 Executing task assets in /tmp/tmpmw2dv5jz/frameos/frameos.nimble
2024-01-12 18:40:30 assets/web/index.html ... ok
2024-01-12 18:40:30 assets/fonts/Ubuntu-Regular_1.ttf ... ok
2024-01-12 18:40:30 Hint: used config file '/opt/nim/config/nim.cfg' [Conf]
2024-01-12 18:40:30 Hint: used config file '/opt/nim/config/config.nims' [Conf]
2024-01-12 18:40:30 Hint: used config file '/tmp/tmpmw2dv5jz/frameos/nim.cfg' [Conf]
2024-01-12 18:40:30 Hint: used config file '/tmp/tmpmw2dv5jz/frameos/config.nims' [Conf]
2024-01-12 18:40:31 .......................................................................................................................................................................................................................................................................
2024-01-12 18:40:31 /tmp/tmpmw2dv5jz/frameos/src/drivers/waveshare/driver.nim(10, 34) Error: invalid token: no whitespace between number and identifier
2024-01-12 18:40:32 The command exited with status 1
2024-01-12 18:40:32 'NoneType' object has no attribute 'split'
2024-01-12 18:40:32 SSH connection closed

Error: cannot open file: pixie

I've prepared a RPi Zero W as instructed by the documentation, with a HyperPixel 2.1 Round display (the Linux console works on the round display).

When deploying, I get the following error:

2024-01-08 10:11:02 Deploying frame Frame 1 with build id qsgcfayzctos
2024-01-08 10:11:02 Connecting via SSH to [email protected] (keypair)
2024-01-08 10:11:03 Connected via SSH to [email protected]
2024-01-08 10:11:03 - Getting target architecture
2024-01-08 10:11:03 > uname -m
2024-01-08 10:11:05 armv6l
2024-01-08 10:11:05 - Copying build folders
2024-01-08 10:11:06 - Applying local modifications
2024-01-08 10:11:06 - Generating scene: default
2024-01-08 10:11:06 - Generating app: a5c68f1a-e3c2-452e-b4f1-85ebc3ad703a (unsplash)
2024-01-08 10:11:06 - Creating build archive
2024-01-08 10:11:06 - No cross compilation. Generating source code for compilation on frame.
2024-01-08 10:11:06 $ cd /tmp/tmpw7z8cfa_/frameos && nimble assets -y && nim compile --os:linux --cpu:arm --compileOnly --genScript --nimcache:/tmp/tmpw7z8cfa_/build_qsgcfayzctos src/frameos.nim 2>&1
2024-01-08 10:11:07 ..................................................................................................................................................
2024-01-08 10:11:07 /tmp/tmpw7z8cfa_/frameos/src/frameos/frameos.nim(1, 29) Error: cannot open file: pixie
2024-01-08 10:11:07 The command exited with status 1
2024-01-08 10:11:07 'NoneType' object has no attribute 'split'
2024-01-08 10:11:07 SSH connection closed

Is there anything I can do to include the pixie nimble package in the archive?

503 when adding new frames

Setup the docker container, and tried to add my first frame only to receive a 503, how does one enable debug logging?

Fails to find/compile pixie

ac2e102 on Linux (no docker)

CONTROLLER

>nim --version
Nim Compiler Version 2.0.2 [Linux: amd64]
Compiled at 2023-12-15
Copyright (c) 2006-2023 by Andreas Rumpf

git hash: c4c44d10df8a14204a75c34e499def200589cb7c
active boot switches: -d:release

>nimble list --installed

asynctools  [(version: 0.1.1, checksum: 54314dceabb06b20908ecb0f2c007e9ff3aaa054)]
bumpy  [(version: 1.1.2, checksum: acc789c4e31b3ee969a13dd0c238d808f39b19c7)]
chroma  [(version: 0.2.7, checksum: f873f4b97e87a82e27e0b85bf9130fe3e320a2b8)]
crunchy  [(version: 0.1.10, checksum: 49e365a8a558293137dc333f25337be4fd033b37), (version: 0.1.9, checksum: 3afda170fbe40158cd78e00375e34690f1fae263)]
flatty  [(version: 0.3.4, checksum: 5775e6ea6ca339efc5bd37b082b8294342d49dc5)]
httpbeast  [(version: 0.4.2, checksum: ceacc8345c9513bd69c4bdb36dd2cb270e8614c4), (version: 0.4.1, checksum: b23e57a401057dcb9b7fae1fb8279a6a2ce1d0b8)]
jester  [(version: 0.6.0, checksum: a5120cfff525e23be29bb2ff47b6ba2f4b2674a3), (version: 0.6.0, checksum: 4834f85e61ae39f6b6acfb74d3bbba62d8779b66)]
linuxfb  [(version: 0.1.0, checksum: 8e639fafa952f3e9d0315f181aa05e0694603bfc)]
nimassets  [(version: 0.2.4, checksum: 71d5510ad86a323fc0ad5dc6b774261e80fe0361)]
nimsimd  [(version: 1.2.6, checksum: a371cce59834c8d56091f5c891fd182e2eb9b3c4)]
pixie  [(version: 5.0.6, checksum: fd4c5d12bba41aac760fc86c2de820e1a367dbfd)]
psutil  [(version: 0.6.1, checksum: 137403c200c58c6cd566ab5fbfd597b535303fc6)]
unpack  [(version: 0.4.0, checksum: d65465ca8e74e9fcb590255491c8fe7763e38c42)]
vmath  [(version: 2.0.0, checksum: c90a664f3425d26219e1262ed9a888b859b3127c)]
wiringPiNim  [(version: 0.1.0, checksum: 88e1225a806aae76fd4de1d08570c44986a30f00)]
ws  [(version: 0.5.0, checksum: ae4daf4ae302d0431f3c2d385ae9d2fe767a3246)]
zippy  [(version: 0.10.11, checksum: 12e761e18ccc0a1b0e931c74dd02bb4b74544d56)]
zstd  [(version: 0.9.0, checksum: 20b23158e94f01ea0c4bf419a21b0feabe70bf31)]

> printenv | grep PATH

PATH=/home/alex/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/home/alex/.local/bin:/home/alex/.local/bin:/home/alex/.nimble/bin

> which nimble

/home/alex/.nimble/bin/nimble

FRAME

2024-01-17 02:07:19
Hint: used config file '/tmp/tmpxp4v2no8/frameos/nim.cfg' [Conf]
2024-01-17 02:07:19
Hint: used config file '/tmp/tmpxp4v2no8/frameos/config.nims' [Conf]
2024-01-17 02:07:19
..................................................................................................................................................
2024-01-17 02:07:19
/tmp/tmpxp4v2no8/frameos/src/frameos/frameos.nim(1, 29) Error: cannot open file: pixie
2024-01-17 02:07:19
The command exited with status 1
2024-01-17 02:07:19
Error in src/frameos/frameos.nim:1:29
2024-01-17 02:07:19
Line 1: import json, asyncdispatch, pixie, chroma, strutils
2024-01-17 02:07:19
....................................^
2024-01-17 02:07:19
Failed to generate frameos sources
2024-01-17 02:07:19
SSH connection closed

Unknown waveshare driver variant epd2in13[.*]

Trying with this board: https://www.aliexpress.us/item/2251832623543336.html. Picked every variant of the 2.13" 250x122 Waveshare device.

2024-01-03 23:16:20
- Generating app: 351b3071-4b50-4471-b0f7-a94b4d94ba56 (unsplash)
2024-01-03 23:16:20
Unknown waveshare driver variant epd2in13

[...]

2024-01-03 23:17:24
- Generating app: 351b3071-4b50-4471-b0f7-a94b4d94ba56 (unsplash)
2024-01-03 23:17:24
Unknown waveshare driver variant epd2in13g

[...]

- Generating app: 351b3071-4b50-4471-b0f7-a94b4d94ba56 (unsplash)
2024-01-03 23:17:39
Unknown waveshare driver variant epd2in13_V2

[...]

- Generating app: 351b3071-4b50-4471-b0f7-a94b4d94ba56 (unsplash)
2024-01-03 23:17:50
Unknown waveshare driver variant epd2in13_V4

The fact that it doesn't know about the "driver variant" suggests the problem is not a mismatch with the hardware, but rather a problem with the software toolchain. But that's just speculation.

Overlay clock - Wrong time display on startup

When the overlay clock starts from cold state, it picks up and displays the cached value. Only after the first refresh, the correct time show.

Example:

  • Start-up shows: 10:17 Real time ~10:48
  • After one minute (refresh period): 10:49 Real time ~10:49
  • After few mins, restart the Pi, the time now show: 10:17 again
  • After one minute 10:51 Real time ~10:51

Cannot delete frames

{
  "error": "Internal Server Error",
  "message": "(sqlite3.IntegrityError) NOT NULL constraint failed: metrics.frame_id\n[SQL: UPDATE metrics SET frame_id=? WHERE metrics.id = ?]\n[parameters: <snip>(Background on this error at: https://sqlalche.me/e/20/gkpj)"
}

Share your frames

Post here all the cool projects you've built using FrameOS.

Please share:

  • The name/model of the display
  • Which raspberry are you using
  • How did you make the case.
  • What's the function of the frame
  • Share the exported scenes .zip if possible

Please note that by sharing an image here, you're giving me explicit permission to use it on the frameos.net site, for example in device guides, galleries or other promotional materials / illustrations.

Cannot create frames

When I start frameOS and login, in the console I get these errors:

Failed to load resource: the server responded with a status of 500 (INTERNAL SERVER ERROR)
index-7VBMPZJU.js:37 Error: Failed to fetch frames
at loadFrames (index-7VBMPZJU.js:37:64698)

Everytime I click on ADD FRAME i get those errors and nothing happens.

I tried deploying from github and compiling locally from git.

In the console of the docker I get these errors:

(the first lines are truncated)

return _process_result(sub_ctx.command.invoke(sub_ctx))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/click/core.py", line 1434, in invoke
return ctx.invoke(self.callback, **ctx.params)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/click/core.py", line 783, in invoke
return __callback(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/click/decorators.py", line 33, in new_func
return f(get_current_context(), *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/flask/cli.py", line 357, in decorator
return __ctx.invoke(f, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/click/core.py", line 783, in invoke
return __callback(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/flask_migrate/cli.py", line 150, in upgrade
_upgrade(directory, revision, sql, tag, x_arg)
File "/usr/local/lib/python3.11/site-packages/flask_migrate/init.py", line 111, in wrapped
f(*args, **kwargs)
File "/usr/local/lib/python3.11/site-packages/flask_migrate/init.py", line 200, in upgrade
command.upgrade(config, revision, sql=sql, tag=tag)
File "/usr/local/lib/python3.11/site-packages/alembic/command.py", line 385, in upgrade
script.run_env()
File "/usr/local/lib/python3.11/site-packages/alembic/script/base.py", line 578, in run_env
util.load_python_file(self.dir, "env.py")
File "/usr/local/lib/python3.11/site-packages/alembic/util/pyfiles.py", line 93, in load_python_file
module = load_module_py(module_id, path)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/alembic/util/pyfiles.py", line 109, in load_module_py
spec.loader.exec_module(module) # type: ignore
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "", line 940, in exec_module
File "", line 241, in _call_with_frames_removed
File "/app/backend/migrations/env.py", line 110, in
run_migrations_online()
File "/app/backend/migrations/env.py", line 104, in run_migrations_online
context.run_migrations()
File "", line 8, in run_migrations
File "/usr/local/lib/python3.11/site-packages/alembic/runtime/environment.py", line 927, in run_migrations
self.get_context().run_migrations(**kw)
File "/usr/local/lib/python3.11/site-packages/alembic/runtime/migration.py", line 626, in run_migrations
step.migration_fn(**kw)
File "/app/backend/migrations/versions/f4fafd71db11_migrate_node_id.py", line 21, in upgrade
frames = Frame.query.all()
^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/sqlalchemy/orm/query.py", line 2692, in all
return self._iter().all() # type: ignore
^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/sqlalchemy/orm/query.py", line 2846, in _iter
result: Union[ScalarResult[_T], Result[_T]] = self.session.execute(
^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/sqlalchemy/orm/session.py", line 2246, in execute
return self._execute_internal(
^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/sqlalchemy/orm/session.py", line 2141, in _execute_internal
result: Result[Any] = compile_state_cls.orm_execute_statement(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/sqlalchemy/orm/context.py", line 293, in orm_execute_statement
result = conn.execute(
^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/sqlalchemy/engine/base.py", line 1412, in execute
return meth(
^^^^^
File "/usr/local/lib/python3.11/site-packages/sqlalchemy/sql/elements.py", line 483, in _execute_on_connection
return connection._execute_clauseelement(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/sqlalchemy/engine/base.py", line 1635, in _execute_clauseelement
ret = self._execute_context(
^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/sqlalchemy/engine/base.py", line 1844, in _execute_context
return self._exec_single_context(
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/sqlalchemy/engine/base.py", line 1984, in _exec_single_context
self._handle_dbapi_exception(
File "/usr/local/lib/python3.11/site-packages/sqlalchemy/engine/base.py", line 2339, in _handle_dbapi_exception
raise sqlalchemy_exception.with_traceback(exc_info[2]) from e
File "/usr/local/lib/python3.11/site-packages/sqlalchemy/engine/base.py", line 1965, in _exec_single_context
self.dialect.do_execute(
File "/usr/local/lib/python3.11/site-packages/sqlalchemy/engine/default.py", line 921, in do_execute
cursor.execute(statement, parameters)
sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such column: frame.debug
[SQL: SELECT frame.id AS frame_id, frame.name AS frame_name, frame.frame_host AS frame_frame_host, frame.frame_port AS frame_frame_port, frame.ssh_user AS frame_ssh_user, frame.ssh_pass AS frame_ssh_pass, frame.ssh_port AS frame_ssh_port, frame.server_host AS frame_server_host, frame.server_port AS frame_server_port, frame.server_api_key AS frame_server_api_key, frame.status AS frame_status, frame.version AS frame_version, frame.width AS frame_width, frame.height AS frame_height, frame.device AS frame_device, frame.color AS frame_color, frame.interval AS frame_interval, frame.metrics_interval AS frame_metrics_interval, frame.scaling_mode AS frame_scaling_mode, frame.background_color AS frame_background_color, frame.rotate AS frame_rotate, frame.debug AS frame_debug, frame.last_log_at AS frame_last_log_at, frame.apps AS frame_apps, frame.scenes AS frame_scenes, frame.image_url AS frame_image_url
FROM frame]
(Background on this error at: https://sqlalche.me/e/20/e3q8)

  • Debugger is active!

Am I doing something wrong?

DEV_Config.h:66:18: fatal error: lgpio.h: No such file or directory

RPi 3 Model B, standard 64-bit Raspberry Pi OS Lite image. Waveshare 7.5 connected. This happened on the initial deployment attempt.

2024-01-03 21:39:05
Processing triggers for man-db (2.11.2-2) ...
2024-01-03 21:39:30
Processing triggers for dbus (1.14.10-1~deb12u1) ...
2024-01-03 21:39:32
2024-01-03 21:39:32
WARNING: apt does not have a stable CLI interface. Use with caution in scripts.
2024-01-03 21:39:32
2024-01-03 21:39:32
debconf: unable to initialize frontend: Dialog
2024-01-03 21:39:33
debconf: (Dialog frontend will not work on a dumb terminal, an emacs shell buffer, or without a controlling terminal.)
2024-01-03 21:39:33
debconf: falling back to frontend: Readline
2024-01-03 21:39:33
debconf: unable to initialize frontend: Readline
2024-01-03 21:39:33
debconf: (This frontend requires a controlling tty.)
2024-01-03 21:39:33
debconf: falling back to frontend: Teletype
2024-01-03 21:39:33
dpkg-preconfigure: unable to re-open stdin:
2024-01-03 21:39:36
> cd /srv/frameos/build/build_ffqqahjwqjia && sh ./compile_frameos.sh
2024-01-03 21:39:37
[1/134] Compiling on device: DEV_Config.c
2024-01-03 21:39:38
In file included from DEV_Config.c:30:
2024-01-03 21:39:39
DEV_Config.h:66:18: fatal error: lgpio.h: No such file or directory
2024-01-03 21:39:39
66 | #include <lgpio.h>
2024-01-03 21:39:39
| ^~~~~~~~~
2024-01-03 21:39:39
compilation terminated.
2024-01-03 21:39:39
The command exited with status 1
2024-01-03 21:39:40
> mkdir -p /srv/frameos/releases/release_ffqqahjwqjia
2024-01-03 21:39:40
> cp /srv/frameos/build/build_ffqqahjwqjia/frameos /srv/frameos/releases/release_ffqqahjwqjia/frameos
2024-01-03 21:39:40
cp: cannot stat '/srv/frameos/build/build_ffqqahjwqjia/frameos': No such file or directory
2024-01-03 21:39:40
The command exited with status 1

I'm unsure what I could have done that is deviating from the instructions.

KeyError with SSH connections

File "/home/alex/git/frameos/backend/app/utils/ssh_utils.py", line 34, in remove_ssh_connection
17:24:49 huey.1  |     ssh_connections.remove(ssh)
17:24:49 huey.1  | KeyError: None

I'm pretty sure this is an under-indented line in restart_frame.py.

except Exception as e:
log(id, "stderr", str(e))
frame.status = 'uninitialized'
update_frame(frame)
finally:
if ssh is not None:
ssh.close()
log(id, "stdinfo", "SSH connection closed")
remove_ssh_connection(ssh)

remove_ssh_connection(ssh) should be in the finally: block like in reset_frame.py

except Exception as e:
log(id, "stderr", str(e))
frame.status = 'uninitialized'
update_frame(frame)
finally:
if ssh is not None:
ssh.close()
log(frame.id, "stdinfo", "SSH connection closed")
remove_ssh_connection(ssh)

Frame stuck at `uninitialized`

Thanks for this project! (coming from HN)

I've been unable to get a frame to initialize. After adding a frame in the web UI it says uninitialized forever, and I don't see any relevant logs to suggest what's wrong. The Pi sshd logs don't show any attempt to connect to the frame.

This occurs with either the docker image or running manually.
The RPi4 running Raspbian 64bit (bookworm) is accessible on blackberrypi.local
My Linux Mint laptop is accessible on antorak.local.
They can ping each other fine, and SSH with keyfile works.
I have added the FrameOS keyfile to ~/.ssh/authorized_users on the Pi.

// GET frames returns status 200
{
  "frames": [
    {
      "background_color": "white",
      "color": null,
      "device": "web_only",
      "frame_host": "blackberrypi.local",
      "frame_port": 8787,
      "height": null,
      "id": 1,
      "interval": 300.0,
      "metrics_interval": 60.0,
      "name": "Inky",
      "rotate": 0,
      "scaling_mode": "cover",
      "scenes": [
        {
          "edges": [
            {
              "id": "d8ea5451-6154-4f91-9416-c4bf75f90d1e",
              "source": "65ece135-83a4-4103-a9ae-d83dec627e90",
              "sourceHandle": "next",
              "target": "db5f595d-2b15-4506-b7c1-d03bbf5e0e37",
              "targetHandle": "prev"
            }
          ],
          "id": "default",
          "nodes": [
            {
              "data": {
                "keyword": "render"
              },
              "height": 72,
              "id": "65ece135-83a4-4103-a9ae-d83dec627e90",
              "position": {
                "x": 259.18108974358967,
                "y": 379.3192307692308
              },
              "type": "event",
              "width": 132
            },
            {
              "data": {
                "config": {},
                "keyword": "unsplash"
              },
              "height": 102,
              "id": "db5f595d-2b15-4506-b7c1-d03bbf5e0e37",
              "position": {
                "x": 598.6810897435896,
                "y": 412.8192307692308
              },
              "type": "app",
              "width": 133
            }
          ]
        }
      ],
      "server_api_key": "92de851735332deb545b5471ba7d0061bce528bdb13efef6bdae9a49a8754132",
      "server_host": "antorak.local",
      "server_port": 8989,
      "ssh_pass": null,
      "ssh_port": 22,
      "ssh_user": "pi",
      "status": "uninitialized",
      "version": null,
      "width": null
    }
  ]
}
huey_consumer.py app.huey.huey --worker-type=greenlet --workers=10 --flush-locks
[2024-01-03 14:31:58,518] INFO:huey.consumer:MainThread:Huey consumer started with 10 greenlet, PID 225691 at 2024-01-03 20:31:58.518966
[2024-01-03 14:31:58,519] INFO:huey.consumer:MainThread:Scheduler runs every 1 second(s).
[2024-01-03 14:31:58,519] INFO:huey.consumer:MainThread:Periodic tasks are enabled.
[2024-01-03 14:31:58,519] INFO:huey.consumer:MainThread:The following commands are available:
+ app.tasks.deploy_frame.deploy_frame
+ app.tasks.reset_frame.reset_frame
+ app.tasks.restart_frame.restart_frame
(env) alex@antorak:~/git/frameos/backend$ python3 run.py
Starting server
 * Restarting with stat
Starting server
 * Debugger is active!
 * Debugger PIN: 354-832-218

Cannot find nimbase.h with all installs

The compiler is unable to find nimbase.h on Linux Mint with choosenim.

The detection logic is here:

# Try to get paths from 'nim dump'
try:
nim_dump_output = subprocess.check_output([nim_executable, "dump"], text=True)
# Extract paths that might contain 'nimbase.h'
nimbase_paths.extend(line for line in nim_dump_output.splitlines() if 'lib' in line)
except subprocess.CalledProcessError as e:
print(f"Error running 'nim dump': {e}")

The intention is to use the output of nim dump, which prints (1) defined symbols (uninteresting) and (2) library paths (interesting).

Running it in a shell appears to work. However, (1) and (2) are printed differently.
Running nim dump > nim_dump_stdout.txt 2> nim_dump_stderr.txt we can see that (1) goes to stdout and (2) to stderr.

This means that capture_output is only capturing the uninteresting (1) but not (2). Hence, the code fails to find nimbase.h

(For some package managers there is code further down that works, disguising the problem).

PR incoming.

Not all Pimoroni inky displays support saturation kwarg

The Python code calls inky with a kwarg saturation

inky.set_image(image, saturation=1)

This is not always possible.
See the various drivers in https://github.com/pimoroni/inky/tree/main/library/inky. Not all of them support saturation as a keyword arg, and the ones that don't aren't e.g. accepting **kwargs as a catch-all.

In particular, the Inky wHAT (Red/Black/White) only works if the argument is deleted.
Smarter detection of the inky model is necessary, I think.

Seriously struggling to figure out making my own scenes?

I have tried and tried again and I cant even get a simple text example

I have never used node stuff before a video tutorial of showing home assistant sensors. etc would be a god send

The project looks exactly perfect for what I want but the lack of explanation for people with low level understanding of the interface

Tasklist

If you'd like to give a helping hand, pick any of the unfinished items and submit a PR. Don't ask for permission, everything is available and there are no issues to assign.

Phase 1: Python MVP

Completed by November 2023
  • Backend + frontend for control panel running
  • SSH connection to frames
  • Deploy and launch client software
  • Launch as a daemon (via tmux for now)
  • API connection back
  • Streaming SSH logs to client
  • UI to add frames
  • Get live images back
  • Reload button in FCP UI
  • Show image as it's updating
  • Sync frame updating state to control panel
  • Sync button presses to control panel
  • Add migrations
  • Send logs sequentially
  • Configure image via UI
  • Kiosk mode URL
  • Create new frame installation instructions (from rpi)
  • Add apps
  • Draw stuff on images
  • OpenAI DallE2
  • Rotate images
  • Scaling mode as part of the frame, not app
  • App for scaling with cover modes
  • Edit via a diagram UI
  • Require user/pass to see interface
  • Close a tab, fix bugs with tabs
  • Handle saving modified apps
  • Virtualize logs (list gets too big)
  • Settings page with credential storage (HA, OpenAI, Github)
  • Save scenes (one or many) as templates
  • Template .zip export
  • Template .zip import
  • Github template repositories
  • Support making screenshots of web pages (on 64bit devices only)
  • Apps/devices must preselect the settings/secrets they are using, only those are copied over
  • SSH keys
  • Python and JSON errors inline in editor (red if file is obviously wrong)
  • Editing text in app config jumps to end
  • Document the coding environment and the available apps
  • Get CPU, temp and other metrics from the frames
  • Add Sentry support
  • Better login screen
  • If/else branches in diagram editor
  • Horizontal/vertical split (grid mode)

By the end of August 2013, the MVP was essentially complete. I could deploy custom code from a library of building blocks over SSH onto a raspberry pi.

Phase 2: Nim rewrite

Can we 10x the efficiency? This might completely change the way apps are built, so best to explore it now instead of polishing more.

Completed January 2024
  • Explore migrating from PIL to pixie-python make sense? We'd get great font rendering for free, minus emoji support sadly. --> Might be great, but putting energy into the next point instead.
  • Experiment if it makes any sense to rewrite the FrameOS on-device part in a compiled language. Conclusion: yes it does. We're doing real time graphics on low power devices. A compiled language brings 10x improvements in speed and/or performance. Migrating some parts to a compiled language is inevitable. After looking around a lot, nim seems like the best choice. People praise it. It's friendlier than rust/zig/go ("If you imagine native-compiled type-annotated Python where nearly 100% of your code is business logic with no cruft, you're getting close to the Nim experience."), it's easy to pick up from examples, fast, it's used for games (it's fast), and comes with an amazing image handling library and other goodies. None of the other languages hit this sweet spot, so let's go.
  • Rewrite FrameOS in nim.
    • Proof of concept in the nim branch
    • Deploy the nim code onto a raspberry with on-device compilation
    • Caching for on device compilation
    • Support for apps and the execution context
    • Support numbers, color and other types of fields
    • Support template strings in config -> inline code nodes for vars
    • Support edited custom apps
    • Convert to async server with schedules, etc
    • Scheduler
    • Inky impression display support? No C bindings? Only python available. Will call python code for now.
    • Rotated display support
    • System of hardware specific drivers, and devices that group them
    • Port over the main apps
      • Unsplash
      • Text
      • Code
      • Clock
      • Download URL
      • FrameOS Gallery
      • Color
      • Gradient
      • HA Sensor
      • If
      • Split
      • Resize
      • Rotate
      • OpenAI
      • Break if rendering
    • Log batching in a separate thread
    • Rendering in a separate thread
    • HDMI support (double buffering, frame info, different color modes)
    • Sanitize app fields
    • Display on/off controls
    • Skip most logs in high fps mode
    • Metrics logger
    • Waveshare eink support (using C libraries!)
    • Touch and click handlers
    • Ignore render when rendering, run all events after
  • 60fps mode (max 2fps with Python now) -> got 60fps+ (more like 100) on a rpi5 with a 720p display (pikvm). So it's possible, even with simple "software rendering". Once we have the basics covered, I can investigate something like boxy to increase performance even more.
  • Stability and hours of use (been running an inky impression + rpi zero w 1 and a hyperpixel round + zero w 2 at 24fps for days now without downtime)
  • Show errors when editing nim apps in the interface
  • Update docs FrameOS/frameos-docs#1
  • Update the Dockerfile
  • Merge the PR: #5
  • Add B/W and B/W/R waveshare drivers
  • Full screen mode in web server

Read the blog post or the HN thread.

Phase 3: Work continues

January 2024. Improve driver support, stability and other fixes.
  • Investigate timeouts hanging the logger
  • Delete old build folders on deploy
  • Any way to lock/secure dependencies
  • Global last image lock
  • Cache deps in docker
  • Show frame metric charts
  • Memory hole?? Memory is not freed when requesting the image over http.
  • Add dithering for 2-color waveshare devices
  • Add dithering for the rest
  • Add waveshare drivers
    • Black/White
    • 4-Grayscale
    • 7-color
    • 4-color Black/White/Red/Yellow
    • Black/White/Yellow
    • Black/White/Red
  • Compile lgpio from scratch if no package
  • Swap from string node ID-s in compiled scenes to integers (should speed it up a bit and reduce memory usage)
  • GPIO button handlers
  • Outgoing event nodes
  • Disable swap (saves SD card from death if we have a memory leak) --> revert? messes up compilation on W2
  • Faster compilation (was: local buildchains. Decided against it for now)
  • Inky impressions native driver. Went with faster python redeploys instead. The driver itself works fine as is, so not replacing today.
  • Logger crashes again, and takes its thread to 100%. Let's try again...
  • Debug toggle
  • Double check all the gcsafe hacks
  • General polish
February to April 2024. Multiple scenes, apps, regression tests and other completed tasks.
  • App: QR code
  • App: GitHub star count
  • App: GPT text
  • Scene state
  • Scene state updates and persistence
  • Scene state updates with built in web server
  • Auth for frame API access
  • Don't drag from within textfields
  • Sometimes 404 error when opening frame and clicking back only during rebuilds in dev
  • Multiple scenes
  • Move parts of frame config to scene config/state
  • Revamped scenes and templates
  • New default repository, easier sharing of scenes via repositories
  • Visual regression tests for apps and scenes
  • Tests for scene generation
  • Update docs and screenshots
  • Update docs about building apps
  • Easier split tool
  • Initial scene wizard when setting up a new frame
  • Improve path dragging/removing in the editor

Next things:

  • Persist last open scene for restarts
  • Schedule a restart
  • Faster frontend builds
  • Code nodes with arguments
  • Universal caching controls
  • Async data nodes (download url)
  • Data apps WIP
  • Images as data (?)
  • New nodes by dragging to the diagram
  • Rework all apps to be image/data/logic apps
  • Multiple files per app
  • iCal support
  • Logger leaks memory (workaround: nightly restarts)
  • Calendar & Agenda apps
  • Cross compilation
  • Google Photos support
  • From control URL, set different scene with custom state in one operation, not two
  • Past logs with correct timestamps if controller is down

All the other ideas

Here's a list of things that have come to mind. Not in order of priority.

  • Scenes in scenes & special "Layout" scene
  • Static assets
  • Graphs and charts
  • Tests for server
  • Tests for metrics
  • Tests for drivers
  • Community forums and device guides
  • CI for all supported raspberry OS versions
  • Tests for scene runners
  • Video intro
  • Release 1.0
  • Copy/paste json
  • Standardise font and position controls
  • Drag to empty space -> new node
  • Backups
  • Image transitions / screensavers
  • Assets for apps (upload images to display)
  • Config for drivers (choose which pins are buttons, etc)
  • Kindle support
  • ESP32 support
  • Font with emoji support
  • Better sharing/import/export of apps
  • Apps can export data
  • Verify support for all other inky frames
  • Unified background data fetching to not slow down real time mode
  • Throttle if CPU is hot
  • Slow down or turn off rendering if display is off
  • HTTPS access between frames and controllers
  • 404 on frame that is not there
  • Scheduler as an event you can drag onto the scene
  • RTSP snapshot app
  • SSH terminal
  • Multiple SSH keys
  • Package as a home assistant or Hacs addon
  • GPIO buttons as home assistant events
  • Boot splash screen for hdmi devices
  • UI polish, design system work, etc
  • Visual, grid, layout, placement, etc editor
  • Hyperpixel native driver (screen turn on/off is via python now)
  • Investigate GPU rendering via boxy
  • Pallette support for type="color" node config on dithered displays

Cases and devices

  • Create a modular, easy, and semi-compatible 3d printed case system for all these different frames and raspberries.
  • Update the device guides with a lot more info and images
  • Clean system for adding frames/drivers/capabilities

Sporadic "Nim executable not found"

2024-01-05 06:16:56
Deploying frame Inky with build id bjzqmketgrsj
2024-01-05 06:16:56
Nim executable not found

Save & Redeploy a frame does not always work. Sometimes it works first try, sometimes it takes repeated clicking. I have not been able to determine a pattern.

alex@antorak:~$ cat /etc/os-release
NAME="Linux Mint"
VERSION="21.2 (Victoria)"
ID=linuxmint
ID_LIKE="ubuntu debian"
VERSION_ID="21.2"
VERSION_CODENAME=victoria
UBUNTU_CODENAME=jammy

alex@antorak:~$ which nim
/home/alex/.nimble/bin/nim

alex@antorak:~$ nim --version
Nim Compiler Version 2.0.2 [Linux: amd64]

Folder gallery

It would be nice to have a template for just displaying photos from a folder in a selectable order (sorted alphabetically by path or random).
I want to use FrameOS just for displaying some photos on a (mostly) offline device from a folder on a flash drive (not some cloud) but haven't had time to learn Nim just yet to write my own app.

I imagine that exact use case is probably very common (e.g. gifting grandma who does not have internet a frame preloaded with family pictures changing once a day) hence I'm suggesting adding it as a template.

No such file: nimassets.nim (Error: unknown CPU: 'x86_64')

I'm following the setup instructions. I ran into the issue that the controller's generated RSA keys don't work, but I manually worked around it. When I tried to deploy to my RPi 3 Model B with a Waveshare 7.5 display, I got this in the logs:

2024-01-03 20:30:54
Connected via SSH to miket@waveshare75
2024-01-03 20:30:55
- Getting target architecture
2024-01-03 20:30:55
> uname -m
2024-01-03 20:30:55
armv7l
2024-01-03 20:30:56
- Copying build folders
2024-01-03 20:30:56
- Applying local modifications
2024-01-03 20:30:56
- Generating scene: default
2024-01-03 20:30:56
- Generating app: a6e58819-3524-46cf-a0f6-e394a81854cb (unsplash)
2024-01-03 20:30:56
- Creating build archive
2024-01-03 20:30:57
- No cross compilation. Generating source code for compilation on frame.
2024-01-03 20:30:57
$ cd /tmp/tmpsy0pgjpp/frameos && nimble assets -y && nim compile --os:linux --cpu:x86_64 --compileOnly --genScript --nimcache:/tmp/tmpsy0pgjpp/build_wmlmllvponcg src/frameos.nim 2>&1

[...]

2024-01-03 20:32:18
Installing [email protected]
2024-01-03 20:32:18
Building nimassets/nimassets using c backend
2024-01-03 20:33:30
Success: nimassets installed successfully.
2024-01-03 20:33:31
Executing task assets in /tmp/tmpsy0pgjpp/frameos/frameos.nimble
2024-01-03 20:33:33
assets/web/index.html ... ok
2024-01-03 20:33:33
assets/fonts/Ubuntu-Regular_1.ttf ... ok
2024-01-03 20:33:34
command line(1, 2) Error: unknown CPU: 'x86_64'. Available options are: i386, m68k, alpha, powerpc, powerpc64, powerpc64el, sparc, vm, hppa, ia64, amd64, mips, mipsel, arm, arm64, js, nimvm, avr, msp430, sparc64, mips64, mips64el, riscv32, riscv64, esp, wasm32, e2k, loongarch64
2024-01-03 20:33:34
�[1m/tmp/nimble_56/githubcom_xmonadernimassets_0.2.4/src/nimassets.nim(3, 8) �[0m�[33mWarning: �[0muse the nimble packages `malebolgia`, `taskpools` or `weave` instead; threadpool is deprecated�[36m [Deprecated]�[0m�[0m
2024-01-03 20:33:35
The command exited with status 1
2024-01-03 20:33:35
[Errno 2] No such file or directory: '/tmp/tmpsy0pgjpp/frameos/\x1b[1m/tmp/nimble_56/githubcom_xmonadernimassets_0.2.4/src/nimassets.nim'

As you can see, things go off the rails at Error: unknown CPU: 'x86_64', or maybe earlier when it sends the nim compile --os:linux --cpu:x86_64 command, which doesn't seem to make sense if it's compiling on the rpi for the rpi.

Is this because I am using a Raspberry Pi 3 Model B?

Clock overlay time not update

I followed the demo instruction and add the clock overlay as follow:

Event rendering --> Vanilla boilerplate "Code" --> Clock overlay

Actual behavior
The vanilla log message was printed with a period, however, the clock time rendered in the e-ink panel isn't updated.

Expected behavior:
Time is updated every now and then when rendering event happens.

No compiling

Thanks for creating this tool, so far I could not get it compiled.

Host used: I tried using host via Unraid Docker. I also tried using standalone Docker on my MacBook using the latest image.

Display used: Raspberry Pi Zero W with Waveshare 7.5 800x480 b&w e-Ink display attached to it.

Creating a single scene to just display time, using a template on both host systems results in the same issue:

2024-06-05 08:11:18
/tmp/tmpg_54cb4q/frameos/src/lib/httpclient.nim(345, 35) Hint: 'code' cannot raise 'OverflowDefect' [XCannotRaiseY]
2024-06-05 08:11:18
/tmp/tmpg_54cb4q/frameos/src/lib/httpclient.nim(345, 35) Hint: 'code' cannot raise 'OverflowDefect' [XCannotRaiseY]
2024-06-05 08:11:18
/opt/nim/lib/pure/asyncmacro.nim(361, 14) Hint: 'await' is declared but not used [XDeclaredButNotUsed]
2024-06-05 08:11:18
..........................
2024-06-05 08:11:18
/tmp/tmpg_54cb4q/frameos/src/scenes/scene_f4d9654c6963478ebb658aee63f90ca5.nim(104, 9) Error: expected: ')', but got: 'size'
2024-06-05 08:11:18
The command exited with status 1
2024-06-05 08:11:18
Error in src/scenes/scene_f4d9654c6963478ebb658aee63f90ca5.nim:104:9
2024-06-05 08:11:18
Line 104: size: 2.0
2024-06-05 08:11:18
..................^
2024-06-05 08:11:18
Failed to generate frameos sources
2024-06-05 08:11:18
SSH connection closed

Can't create frame

Hi !
First of all, thank you for your work !
I installed FrameOS using Docker Compose on an arm64 server running Ubuntu 24.04, and I get an error in the logs when the container starts. I can still connect on the web ui, but I can't create a new frame. I tried with Docker Run and I even tried building the image locally, but the same error appears. Here's the log :

INFO  [alembic.runtime.migration] Context impl SQLiteImpl.
INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
 * Restarting with stat
INFO  [alembic.runtime.migration] Running upgrade 7f2a8719a009 -> f8db11069084, frame access
Traceback (most recent call last):
  File "/app/backend/.venv/lib/python3.11/site-packages/sqlalchemy/engine/base.py", line 1965, in _exec_single_context
    self.dialect.do_execute(
  File "/app/backend/.venv/lib/python3.11/site-packages/sqlalchemy/engine/default.py", line 921, in do_execute
    cursor.execute(statement, parameters)
sqlite3.OperationalError: duplicate column name: frame_access

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/app/backend/.venv/bin/flask", line 8, in <module>
    sys.exit(main())
             ^^^^^^
  File "/app/backend/.venv/lib/python3.11/site-packages/flask/cli.py", line 1063, in main
    cli.main()
  File "/app/backend/.venv/lib/python3.11/site-packages/click/core.py", line 1078, in main
    rv = self.invoke(ctx)
         ^^^^^^^^^^^^^^^^
  File "/app/backend/.venv/lib/python3.11/site-packages/click/core.py", line 1688, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/backend/.venv/lib/python3.11/site-packages/click/core.py", line 1688, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/backend/.venv/lib/python3.11/site-packages/click/core.py", line 1434, in invoke
    return ctx.invoke(self.callback, **ctx.params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/backend/.venv/lib/python3.11/site-packages/click/core.py", line 783, in invoke
    return __callback(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/backend/.venv/lib/python3.11/site-packages/click/decorators.py", line 33, in new_func
    return f(get_current_context(), *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/backend/.venv/lib/python3.11/site-packages/flask/cli.py", line 357, in decorator
    return __ctx.invoke(f, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/backend/.venv/lib/python3.11/site-packages/click/core.py", line 783, in invoke
    return __callback(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/backend/.venv/lib/python3.11/site-packages/flask_migrate/cli.py", line 150, in upgrade
    _upgrade(directory, revision, sql, tag, x_arg)
  File "/app/backend/.venv/lib/python3.11/site-packages/flask_migrate/__init__.py", line 111, in wrapped
    f(*args, **kwargs)
  File "/app/backend/.venv/lib/python3.11/site-packages/flask_migrate/__init__.py", line 200, in upgrade
    command.upgrade(config, revision, sql=sql, tag=tag)
  File "/app/backend/.venv/lib/python3.11/site-packages/alembic/command.py", line 385, in upgrade
    script.run_env()
  File "/app/backend/.venv/lib/python3.11/site-packages/alembic/script/base.py", line 578, in run_env
    util.load_python_file(self.dir, "env.py")
  File "/app/backend/.venv/lib/python3.11/site-packages/alembic/util/pyfiles.py", line 93, in load_python_file
    module = load_module_py(module_id, path)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/backend/.venv/lib/python3.11/site-packages/alembic/util/pyfiles.py", line 109, in load_module_py
    spec.loader.exec_module(module)  # type: ignore
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<frozen importlib._bootstrap_external>", line 940, in exec_module
  File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
  File "/app/backend/migrations/env.py", line 110, in <module>
    run_migrations_online()
  File "/app/backend/migrations/env.py", line 104, in run_migrations_online
    context.run_migrations()
  File "<string>", line 8, in run_migrations
  File "/app/backend/.venv/lib/python3.11/site-packages/alembic/runtime/environment.py", line 927, in run_migrations
    self.get_context().run_migrations(**kw)
  File "/app/backend/.venv/lib/python3.11/site-packages/alembic/runtime/migration.py", line 626, in run_migrations
    step.migration_fn(**kw)
  File "/app/backend/migrations/versions/f8db11069084_frame_access.py", line 22, in upgrade
    with op.batch_alter_table('frame', schema=None) as batch_op:
  File "/usr/local/lib/python3.11/contextlib.py", line 144, in __exit__
    next(self.gen)
  File "/app/backend/.venv/lib/python3.11/site-packages/alembic/operations/base.py", line 377, in batch_alter_table
    impl.flush()
  File "/app/backend/.venv/lib/python3.11/site-packages/alembic/operations/batch.py", line 113, in flush
    fn(*arg, **kw)
  File "/app/backend/.venv/lib/python3.11/site-packages/alembic/ddl/impl.py", line 322, in add_column
    self._exec(base.AddColumn(table_name, column, schema=schema))
  File "/app/backend/.venv/lib/python3.11/site-packages/alembic/ddl/impl.py", line 193, in _exec
    return conn.execute(  # type: ignore[call-overload]
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/backend/.venv/lib/python3.11/site-packages/sqlalchemy/engine/base.py", line 1412, in execute
    return meth(
           ^^^^^
  File "/app/backend/.venv/lib/python3.11/site-packages/sqlalchemy/sql/ddl.py", line 181, in _execute_on_connection
    return connection._execute_ddl(
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/backend/.venv/lib/python3.11/site-packages/sqlalchemy/engine/base.py", line 1524, in _execute_ddl
    ret = self._execute_context(
          ^^^^^^^^^^^^^^^^^^^^^^
  File "/app/backend/.venv/lib/python3.11/site-packages/sqlalchemy/engine/base.py", line 1844, in _execute_context
    return self._exec_single_context(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/backend/.venv/lib/python3.11/site-packages/sqlalchemy/engine/base.py", line 1984, in _exec_single_context
    self._handle_dbapi_exception(
  File "/app/backend/.venv/lib/python3.11/site-packages/sqlalchemy/engine/base.py", line 2339, in _handle_dbapi_exception
    raise sqlalchemy_exception.with_traceback(exc_info[2]) from e
  File "/app/backend/.venv/lib/python3.11/site-packages/sqlalchemy/engine/base.py", line 1965, in _exec_single_context
    self.dialect.do_execute(
  File "/app/backend/.venv/lib/python3.11/site-packages/sqlalchemy/engine/default.py", line 921, in do_execute
    cursor.execute(statement, parameters)
sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) duplicate column name: frame_access
[SQL: ALTER TABLE frame ADD COLUMN frame_access VARCHAR(50)]
(Background on this error at: https://sqlalche.me/e/20/e3q8)

Generated SSH keypair not working

Struggled a little bit setting FrameOS up.

For reference, I have a Pi Zero set up with the ~5 inch Pimoroni inky screen. I've deployed the controller on a separate server and trying to set the connection up.

I do not have passwords enabled for SSH, so I was happy to see that SSH keypairs are supported in settings. Generating a keypair and adding the public key to .ssh/authorized_keys on the Pi Zero fails to connect because the key doesn't seem to be a valid RSA key

2024-01-03 17:22:09 Deploying frame <name> with build id mkjdapkjexeb
2024-01-03 17:22:09 Connecting via SSH to <user>@192.168.86.45 (keypair)
2024-01-03 17:22:09 not a valid RSA private key file

I tried creating my own SSH keys (using ed25519) and saving that directly in settings, which gives me a different error

2024-01-03 17:21:02 Deploying frame <name> with build id tqfnsxmojkfk
2024-01-03 17:21:02 Connecting via SSH to <user>@192.168.86.45 (keypair)
2024-01-03 17:21:02 unpack requires a buffer of 4 bytes

I then finally created a RSA keypair with ssh-keygen -t rsa and was able to get that working. If the generated SSH keypairs work on your end, then I'm happy to provide any further information for troubleshooting.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.