HNHacker News
TopNewBestAskShowJobs

mariusandra

864 karma · joined May 23, 2010

submissionscomments
mariusandra··on Show HN: An e-ink frame that hears birds and draws them as 1800s illustrations
This is a very cool project!

When I first heard of it (through a community member in discord), I wanted to see if I could replicate it on FrameOS (my software for running anything on an e-ink panel), and sure enough, I got quite close: https://scenes.frameos.net/s/bird-field-journal

This is obviously nowhere as complicated as OP's project, but I thought I'd just share that your project inspired me to build something similar too.

mariusandra··on PostHog FOSS
um... we've had this posthog-foss repo for years now. No idea why it made front page. This is not news.

Source: I was there

To clarify: PostHog has been MIT licensed since day 1, with the exception of the `ee/` folder. This `posthog-foss` repo is a mirror of the main `posthog` repo with the `ee/` folder removed. We've had it for ages.

mariusandra··on Kea 3.0, our first LTS version
What is this? Kea 3.0 has been out for years already :D https://keajs.org/blog/kea-3.0

(I'm the author of a JS framework with the same name)

mariusandra··on E Ink’s color ePaper tech gets supersized for outdoor displays
Can't really complain cause there's nothing better right now.

Compared to the previous gen e-ink (7-color ACeP), the contrast and the colors are so much better. I also have a bunch of 3-color (black/white/red) panels - video and more pictures on https://frameos.net/ ) - and the contrast is similar, but the colors are obviously limited.

So yeah, I'm definitely happy.

mariusandra··on E Ink’s color ePaper tech gets supersized for outdoor displays
$250 is just part of the price.

I just went through the process and made this for myself: https://www.printables.com/model/1189455-waveshare-133e-6-co...

The total price was around $420. This includes shipping, taxes (to Belgium), a pi zero w2, a sd card, and printing a case.

mariusandra··on E Ink’s color ePaper tech gets supersized for outdoor displays
Having gone through such a search just recently:

- This 13.3" panel cost ~$420 to make https://www.printables.com/model/1189455-waveshare-133e-6-co...

- This 7.3" panel cost ~$150 to make https://www.printables.com/model/1189420-waveshare-73e-6-col...

This includes shipping the panel from waveshare.com, paying taxes, adding a raspberry pi zero w2 + a sd card, and printing a case

mariusandra··on Posthog – open-source analytics and UX research tool
The math didn't add up for us (I work at PostHog). At the rate we were scaling, we would have needed an entire call center's worth of highly trained Kubernetes support engineers to debug everyone's "my pods just died" / "Kafka just stopped" / "what is Zookeeper" problems.

This stack isn't straightforward to manage, and we couldn't crack the code of doing it at scale for other people without even having access to their systems. There was no malicious intent.

Read more here: https://posthog.com/blog/sunsetting-helm-support-posthog

mariusandra··on Show HN: FrameOS – operating system for single function smart frames
Re-reading, my tone in the first sentence sounds rather hostile. I apologise for that. I have no ill intent, the joke was likely funnier in my head.

FrameOS is also targeting 60+FPS LCD and other screens, which will be hard for ESP to run. Thus it's for the raspberry. I'd love to scale it down though, and deliberately chose Nim so that it would at least be theoretically possible.

I also need to get doom running on it...

mariusandra··on Show HN: FrameOS – operating system for single function smart frames
Yes, MP4, sorry for the typo :).

I believe in such places the cost of service and maintenance is many multiples the cost of the initial installation. A $20 "720p hdmi stick" from aliexpress vs a $300 mac mini is a no brainer. 100 mac minis will work reliably and predictably for years to come, whereas 100 random $20-$50 sticks sounds like something that needs constant supervision and maintenance.

That said, a RPi might be enough, depends on the software. That's why FrameOS has HDMI support, to work for such cases. It's still pretty far from being a turnkey solution today, but we could easily get there with some focus at the right time.

mariusandra··on Show HN: FrameOS – operating system for single function smart frames
I believe the OP here is not playing 1999s music formats on a TV, but referring to MK4 and similar _video_ formats that a portable music player definitely can't play.
mariusandra··on Show HN: FrameOS – operating system for single function smart frames
I apologize for the confusion, but you do not need to run FrameOS at all. You can just go about your merry day, and either just not use FrameOS, not post this comment, or, if you prefer, not read any of the comments addressing this question before posting yours.

On a serious note, yes, it's planned. The ESP is a very limited chip. If you want to display a BMP from a HTTP source, or a quick calendar, it's great. Try doing HTTPS, image downscaling or any serious processing though. Forget about things like browser screenshots, which you can't even do on 32bit linux anymore. Forget the 60fps mode over HDMI we can now do.

I'll try to get it working regardless, but it's but not a personal priority today over the other items in the todo list. You're free to lend a helping hand of course.

mariusandra··on Show HN: FrameOS – operating system for single function smart frames
Just found this project that could help: https://github.com/daniel-j/picostdlib
mariusandra··on Show HN: FrameOS – operating system for single function smart frames
Ha, nice to meet you.

I always say "if it's stupid and it works, it's not stupid". Your approach to get the dithering right sounds brilliant to me :D.

The current inky driver works great, and that fact that it's in Python is what made me develop the original FrameOS software in Python. However now that I rewrote it in Nim, the Python driver is a bit of a crutch. While I could use the C drivers for the Waveshare displays, I'm forced to install a python wrapper on the Pi as a workaround to get the Inky drivers working.

Do you have any idea if there are any C, or even Nim drivers available for the Inky Impression boards? The Python workaround works, but isn't really elegant. If not, I'm considering porting them myself at some point...

I'm also lurking on the Pimoroni discord, and was meaning to ask there about it as well.

mariusandra··on Show HN: FrameOS – operating system for single function smart frames
Absolutely! Just hook up your display with a HDMI port to a raspberry, and you're good to go.

If you're fine with just displaying an image from an URL, it'll work today. If you want nicer slideshows or rotating images, you'd have to write some code to make it work, but it's all possible today.

A nicer interface tailored specifically for shop windows slideshows is something that could come at a later date.

mariusandra··on Show HN: FrameOS – operating system for single function smart frames
I have gotten the new Nim-based FrameOS working with two different Waveshare displays. I have two other ones waiting to be tested. Check this folder [1] for the currently enabled drivers.

One of the next items on my todo list [2] is to add back support for all the different waveshare drivers out there. They all follow a similar pattern, so I should be able to generate "best guess" drivers for most of them.

Which display do you have?

[1] https://github.com/FrameOS/frameos/tree/main/frameos/src/dri... [2] https://github.com/FrameOS/frameos/issues/1

mariusandra··on Show HN: FrameOS – operating system for single function smart frames
Theoretically yes, but I have not yet investigated it.
mariusandra··on Show HN: FrameOS – operating system for single function smart frames
I was quite shocked at the amount of tiny and large display options out there. I might even make a YouTube video titled "Home dashboards have gotten cheap and easy" with everything I've learned so far.

Take a $15 Pi Zero W 2, and a screen costing anywhere between $50 to $200. 3d-print a case around them both, and for a third of the price of a new iPad, you'll have a simple and secure single function screen in your house...

mariusandra··on Show HN: FrameOS – operating system for single function smart frames
Very interesting. As replied here [1], I do eventually want to investigate "slimming down" the Linux distro below FrameOS.

However for now, the RPi imager, with its built in "enter your wifi credentials and SSH key" dialog was the best and easiest way to get started.

[1] https://news.ycombinator.com/item?id=38859572

mariusandra··on Show HN: FrameOS – operating system for single function smart frames
Oh it's real. When coding an app inside the web editor, you can click a button that effectively sends your code to the GPT4 API, along with some instructions on what it should be. It then displays back the response.

It's really basic, but has already been useful: https://frameos.net/blog/gpt4-support

mariusandra··on Show HN: FrameOS – operating system for single function smart frames
I used to have an iPad (3rd gen) on the wall, then it died. I bought the cheapest new one to replace it, but the old Android tablet I had around had better bluetooth reach, so it went on the wall instead.

Old android tablets are notoriously unpatched against all kinds of things. It's easy to be paranoid that some passing foot traffic will infect it with a bluetooth worm, and you'll be none the wiser.

I'm accepting the risk for now, as I do enjoy configuring Home Assistant on it, and looking at the rainmap, but there are times when when a full tablet is overkill. FrameOS is for those cases.

mariusandra··on Show HN: FrameOS – operating system for single function smart frames
You're technically right (the best kind?), but there's some nuance to the question.

FrameOS is a compiled binary that runs on top of Linux. At present you need to install the "Raspberry Pi OS Lite" (without the desktop environment) on a SD card before you can install FrameOS itself on top of that. So it's "just an application".

However, this is mostly because it's an early project, and this was the fastest way to get going. The next step is to see how much can be removed. Since FrameOS is a statically compiled single binary, it shouldn't need that much more than the Linux kernel? Will FrameOS be a true OS then? Android seems to be considered its own OS despite using the Linux kernel.

Once activated, FrameOS takes over your entire system, has its own `apps/` and `drivers/` folders, and in many ways already behaves like an Operating System. I'm also pondering about getting it running on an ESP32 (will need to add `drivers/wifi/`?). Without any OS below it, will it then be worthy of being called an OS? You all tell me. :shrug:

Thus is it an Operating System? It is to me, but you can choose to disagree.

At my actual job (PostHog), we sometimes call ourselves the "Product OS". This annoys me more, as a suite of webapps definitely isn't an "Operating System" in its traditional sense. I've seen -OS at the end of other things as well that aren't pure Operating Systems. It slightly bothers me, but mostly because I was around when "what OS you're using" was a defining question. Language is evolving, and "operating system" seems to describe more things to different people, than it does to you and me.

mariusandra··on Show HN: FrameOS – operating system for single function smart frames
I definitely do not want anyone to manually crop, dither and color index images. This should be done by the FrameOS software. It's already working if you use e.g. Inky Impression 7 color frames, but mostly because I just defer to their software/drivers, which already handle this...
mariusandra··on Show HN: FrameOS – operating system for single function smart frames
Hey, thanks for the feedback!

The editor/controller itself is just a React+Kea app using React Flow for the diagramming part, and Flask for the backend.

For now to test that the app you built works, you must deploy it on a frame. I have a fast RPi 5 for testing, and the feedback loop is typically ~30sec. It's about a minute with a Zero W2, and about 2min with a Zero W. This is not ideal, and I'd like to improve that.

Ideally I'd like to use Nim's JS backend to build a "frame" that can be run directly in the browser for testing.

As for the other questions, the FrameOS system runs at boot, and all the apps are compiled in to that one binary and run as the scene dictates. New frames get rendered when a render event is dispatched, which can happen automatically on an interval, or as requested. Frames send logs back to their controller, but can otherwise operate completely independently.

mariusandra··on Show HN: FrameOS – operating system for single function smart frames
I'd love it to work on the RP2040, and perhaps even an ESP32, but we're not there yet. Just yesterday I converted FrameOS from being an interpreted python app to a 3MB compiled binary, so we're half of the way there. I'm not sure what changes I must do to get it working (e.g. integrate a wifi driver, remove GC and threads, etc), but it's in the realm of the possible.
mariusandra··on Show HN: FrameOS – operating system for single function smart frames
There's nothing built in now, but a common technique would be to make the image e.g. ~10px larger in each direction, and then choose a random crop every other second.

It should be really easy to build a FrameOS app that does this. Add one node at the start of the render loop to increase the image accordingly, and one at the end to crop it back down. I was planning to use a similar technique to display smooth scrolling animations/slideshows, but it can definitely be used to prevent burnin.

mariusandra··on Show HN: FrameOS – operating system for single function smart frames
I'd love for FrameOS to support ESP32. Two days ago FrameOS was a slow and interpreted Python app. Today it's a 3MB statically linked binary. The margins are tight, and I'll likely need to cut out some features (e.g. threading), but theoretically it should be possible to get it to run. However I'm not planning on taking this on any time soon, as there's still a lot of work left to make the Raspberry version great. :)
mariusandra··on Kea 3.0 – State Management via Logic Builders
You're asking very good questions.

> I think you can map the example class I wrote to similar concepts - but instead of three+ different function calls to build a logic, you could do one, like `magical(classInstance)` - which would scan the instance and derive internal state machinery much the same way that kea’s `actions` and `reducers` iterate over their argument objects.

That's the magic of Kea: it gives you a framework you can use to get exactly the DSL that makes sense for your app.

This example code you posted:

    kea([
      actions({
        loadUsers: true,
        loadUsersSuccess: (users) => ({ users }),
        loadUsersFailure: (error) => ({ error }),
      }),
    
      reducers({
        users: [
          [],
          {
            loadUsersSuccess: (_, { users }) => users,
          },
        ],
        usersLoading: [
          false,
          {
            loadUsers: () => true,
            loadUsersSuccess: () => false,
            loadUsersFailure: () => false,
          },
        ],
        usersError: [
          null,
          {
            loadUsers: () => null,
            loadUsersFailure: (_, { error }) => error,
          },
        ],
      }),
    
      listeners(({ actions }) => ({
        loadUsers: async () => {
          try {
            const users = await api.get('users')
            actions.loadUsersSuccess(users)
          } catch (error) {
            actions.loadUsersFailure(error.message)
          }
        },
      })),
    ])
    
I'd personally write as this code:

  kea([
    loaders({
      users: { loadUsers: () => api.get('users') }
    })
  ])
and it would do exactly the same thing.

Well, almost, since the `usersError` message won't be saved. To get that you will need to add a reducer.

  kea([
    loaders({
      users: { loadUsers: () => api.get('users') }
    }),
    reducers({
      usersError: (_, { loadUsersFailure: (_, { error }) => error })
    }),
  ])
This is the magic Kea brings to the table, as you can use the core building blocks as frontend state management lego, creating an ever higher language with which to describe your application's logic.

Loading data is such a common pattern, that it makes sense to standardise on a framework level. Who knows what needs your app will have.

> But would it be less maintainable? No matter the framework - Redux, Redux Toolkit, Kea, this monstrosity I just cooked up - your team needs to invest in culture and training about the right way to do things.

You're hitting the nail on the head. I've worked with many developers using Kea over the last years, and while people get it quite quickly, you do need to actually read the docs to understand how it all works together. Otherwise you'll bring your old patterns to this new environment, and write bad (hard to maintain) code.

But this is the case no matter the framework, as you argue. If you don't put in the time in to learn the tooling, your output will be highly inefficient.

At work, I've spent quite a bit of time teaching colleagues how to write Kea the right way, and will now contribute most of this knowledge back in the form of screencasts and tutorials on keajs.org. My hope is that these will help future colleagues of mine level up faster, and the same would apply to all other teams using Kea.

> I guess the question I’m asking is, why is kea’s current position on the explicit-vs-magic spectrum the right global maximum for developer ergonomics & maintainability? kea advanced over raw Redux already, but why not go even further?

You need to draw lines somewhere, and I believe "base 3" (actions, reducers, selectors) is a good place for that. This is in contrast to "base 2" (get, set), which lures with its simplicity, but lead to abstractions that perform worse when you chunk concepts. That extra unit of reasoning within the core abstraction gives a lot. Think 3*3*3=27 vs 2*2*2*2=16.

I get this is going very philosophical/abstract, but we're discussing "magic", so I think we're good :D.

Having seen a lot of different ways to code frontend over the years, I believe a redux-like pattern is the best fit for frontend apps, all* things considered. Compared to "base 2" (get/set) through regular JS primitives, the big difference is that redux forces you to label each write operation with an action type. Every write. This enables a whole class of side effects and observability. These inherent benefits of actions can then be described as magic that comes for free with the abstraction, not as magic that comes from building clever code that hides a complex implementations. As a developer, the former is so much easier to truly and intuitively master, while the latter sounds like a bag of edge cases that you'll keep poking with a stick (see: apollo, based on what I've read on HN lately).

Add to that a global immutable state tree that you can just pass around in a variable (the store), a system of labelled data retrievers from this state tree (selectors), and a way to connect all of these pipes directly to React, an auxiliary system of props and keys to fork data and its operations, a standard library of utils for common operations (routing, forms), commitment to compact syntax, a great way to compose code, and an ever expanding set of learning materials.

The result is what is Kea now. I'm not forcing anyone to use it, but I do think it strikes very close to the global maximum of developer ergonomics and maintainability.

I'm always happy to improve it, and Kea 3.0 was an exercise to push that envelope even further.

mariusandra··on Kea 3.0 – State Management via Logic Builders
lol.

First, it's 2 rewrites. Second, those were all 98% backwards compatible for the users (might need to upgrade plugins), and just refactored the internals.

But sure, let's all write perfect code on day 0, taking into account all the ways libraries you depend on (React) can develop in the future. It's not like "frontend" is a moving target or anything...

/s

mariusandra··on Kea 3.0 – State Management via Logic Builders
Depends what you mean with "readable". It's always easy to make a contrived example, and call that readable because it's shorter. I'm talking about huge apps maintained by multiple remote teams, all working independently.

In this case I would argue that the end goal is "maintainability", not "readability", and Kea, thanks to forcing you to use an abstraction in the first place, leads to better maintainable code.

Piping all "writes" through actions, and all "reads" through selectors gives you complete observability over the entire system at any point in time. The immutable nature of this approach also works wonders in preventing React from wasting time with needless re-renders. Plus the syntax makes it that you can jump into any part of a system consisting of 200+ logic files, and immediately understand how each piece of data came about, and what are the only things that can change it.

Using "simple" and "readable" plain functions that go `this.something = "value"` is the antithesis of a maintainable system. You lose all observability, unless you integrate a lot of "magic", for example making every value secretly use "immer".

> There is a lot of non-linear control flow encoded implicitly in calls to `kea`, `actions`, `listeners` in this framework, and for what?

To build large applications that scale well, are easy to reason about, and can be maintained by whoever joins your team.

mariusandra··on Kea 3.0 – State Management via Logic Builders
Well, in PostHog (I'm a colleague of Twixes), we just decided here [1] to go with Kea, as I had more experience with it.

Had Redux Toolkit been around when I started with Redux in 2016, I probably wouldn't have needed to write Kea. However I'm glad I did, as I now do consider Kea to be the better toolkit for the same job. :D. I know you disagree, and that's all fine of course :).

In my mind Kea fills in all the missing parts from React, while Redux Toolkit is still a set of utility functions for state management. You still need to find another set of tools for data loading (I see this has improved), complex data or form management, app routing, scene handling, etc. Redux Toolkit doesn't bother with most of that, and I don't think it should.

Kea however comes with solutions for all of those. The only thing missing from being able to build a complete app is a JS module bundler. Just sit down and start writing your actual app with the least amount of syntax possible to explain things in a redux'y way. Many people have told me that with Kea, the framework basically gets out of the way and disappears.

Now with the Kea 3.0 Logic Builder syntax, Kea is suddenly like lego for state management. I'm curious to see if this picks up or not. I can't unfortunately link Kea from redux.js.org to drive traffic :).

[1] https://github.com/PostHog/posthog/issues/301 -- the magic of working in an open source company is that we can post stuff like this. We're hiring!

Page 1 of 4Next →