For over ten years, the only way I have had of knowing what our solar
panels are doing has been an impulse monitor on the generation meter,
counting the flashes of its LED. It has always been a bit flaky due
to battery changes or loose connections, and there has never been a
way to see solar generation alongside the energy used by the rest of
the house. This week I have fixed that, by building a small ESPHome
sensor which talks directly to the inverter. I am still reeling
slightly: with AI assistance, it took under a week from idea to
working implementation, and it is a project I would certainly never
have attempted otherwise. The result is
zeversolar-esphome.
The inverter is a Zeversolar Zeverlution 3680, which has an RS485 port
but no Wi-Fi or Ethernet module. It doesnβt speak Modbus; it uses
Eversolarβs own master/slave protocol, which nobody has officially
documented but which several people have reverse-engineered over the
years (credit to
eversolar-monitor,
Heliograph and
others).
Manufacturer support for Eversolar/Zeversolar inverters apparently
ended in December 2019 when the company went out of business.
The rating plate on my inverter.
A while ago I had looked into what ports were available on this
inverter with a view to connecting some sort of monitoring, but I had
abandoned it as βtoo hardβ. While working on some Home Assistant
configuration, Claude suggested the idea again, but similarly wrote it
off initially. I encouraged it to explore a bit further, and supplied
the model number of the inverter, at which point the picture got a lot
more promising. After a bit of back-and-forth about hardware, we
settled on an M5Stack Atom Lite on an Atomic RS485
Base. The
main attraction was that it already comes in a case, so I didnβt need
to design (or, more likely, bodge) an enclosure.
While I waited for the parts to arrive, Claude wrote the firmware: an
ESPHome external
component built
around a small, dependency-free C++ driver, with host-side unit tests
against byte captures that other people had published from other
models. I found it slightly surreal to have a tested protocol driver
before owning any hardware to run it on.
Cables
The parts came before the tools I needed to get into the inverter
safely (a DC clamp meter and a T25 screwdriver bit), so in the
meantime I made up an RS485 cable - this uses an RJ45 connection at
one end, and some custom wiring at the other. My first attempt was
with some CAT 6, but (as Claude had pointed out and I had ignored) its
solid-core conductors are much harder to twist together. So I gave up
and sacrificed an old CAT 5e patch lead instead, which went much
better.
The custom end of the cable, before being taped up.
The risky bit
On a Zeverlution, the RJ45 sockets are inside the wiring compartment,
which means taking the cover off to install the monitor. The manual
addresses this part to qualified electricians. So the step I was most
nervous about was not the software at all, but safely isolating the
inverter.
Inside the inverter, with the cover off.
I did this with appropriate caution, following the instructions from
the manual carefully, and also waiting until after dark just in case.
Now that I understand how the DC clips from the panels work, I can see
how to do this safely during daytime too β but hopefully this wonβt
be necessary.
Plugged in, and threaded through the cable gland.
Warning: if youβre not confident, I would always advise to get an
electrician to do this bit. Do what I say, not what I do.
Debugging over Wi-Fi
Once the device was installed, the nice thing about ESPHome is that I
never need to go back in the loft again to update it β it reflashes
over Wi-Fi. Iβve taken full advantage of this for debugging, and for
reading the wire protocol directly from the logs.
The finished device. Green means generating.
Separately, Iβve used Claude to integrate the new sensors into Home
Assistant. Solar generation finally sits in the Energy dashboard
next to the rest of the houseβs usage, which was the whole point.
Reflections
This was a fun, quick project, and it solved a problem that has eluded
me for a decade. I want to be honest about how much of that is down
to the AI: I would not have attempted any of this on my own. I could
not have told you the protocol existed, never mind implemented it. My
contribution was everything involving a screwdriver, and ordering some
hardware.
A brand new release 0.1.16 of the RcppSimdJson
package is now on CRAN, has
been built for r2u,
and is updated on r-universe.
RcppSimdJson
wraps the fantastic and genuinely impressive simdjson library by Daniel Lemire and collaborators. Via
very clever algorithmic engineering to obtain largely branch-free code,
coupled with modern C++ and newer compiler instructions, it results in
parsing gigabytes of JSON parsed per second which is quite
mindboggling. The best-case performance is βfaster than CPU speedβ as
use of parallel SIMD instructions and careful branch avoidance can lead
to less than one cpu cycle per byte parsed; see the video of the talk by Daniel Lemire
at QCon.
This version updates to the recent 5.0.2 upstream release with
improved performance. Given the strong focus on performance, this
release also alters some of the R and C++ interfaces to be more direct.
Rcpp generally aims for a balance between readable / maintainable code
and good performance; this moves the dial closer to strong performance
gains. As Daniel noted in a table in
the (main) PR for this release, this now consistently beats yyjsonr, and
improves considerably over the previous release of this package. I had
made some smaller interim upgrades earlier (without a CRAN releases),
and made a number of minor standard packaging updates.
The short NEWS entry for this release follows.
Changes in version 0.1.16
(2026-10-09)
simdjson was upgraded to versions 4.6.1
and 4.6.3 (Dirk in #100
and #102
fixing #99
and #101)
simdjson was upgraded to version 5.0.2
(Daniel in #104)
A number of small tweaks to the Rcpp
interface were made too (Daniel in #104)
Diagnostics for gcc and clang are not
suppressed per CRAN Policy (Dirk in #106
closing #105)
The continuous integration matrix was extended to
g++ version 15 and 16 (Dirk in #108
closing #107)
A few minor packaging nags were address (Dirk in #109)
A few days ago, a colleague reached out to me, asking if I could help draft a
resolution on digital autonomy and free software for the upcoming renewal of
our collective bargaining agreement. Although she's very politicised and
generally a great individual, she is not a techie and we never really talked
about these issues before.
This took me by surprise. I should have been rejoicing; no, I should have been
the one who brought up this topic in our union. Wasn't I the technical expert
on these issues? But alas, my first reaction when she came to me was to snicker
and tell myself: "That's cute, but nothing's ever gonna change, Big Tech is too
strong and our governments don't give a damn."
How sad and cynical is that? That's not the person I want to be.
Something in the Quebecois political landscape has shifted in the last few
years with regards to tech. More and more "regular" people seem to be talking
about the importance of digital autonomy, how government services shouldn't
rely on Big Tech and how we should be using FOSS on hardware we actually
control.
I first fell for Free Software for its political ideals: Knowledge Should Be
Free, Cooperation Is More Efficient Than Competition, Centralisation Should Be
Avoided When Possible, etc. I still believe in all of this, but somehow, after
years of fighting for change in the tech world, I have retreated into technical
work. I maintain Debian packages as a hobby and to scratch my own itch. I run
services for myself and a few friends. I organise Debian User Group meetings.
To be clear, I haven't generally given up. I'm very politically active in my
union and at work, I'm a good member of my housing cooperative and I'm still
fighting against the industrialisation of natural spaces in my
neighborhood. But when it comes time to defend freedom in the tech
world, lately, I've just been shrugging and accepting I should use Microsoft
Teams like every one else does. I want this to change and to do so, I need to
free some time.
Lintian
Two years ago, I added myself to Lintian's Uploaders list. Up until
then1, I enjoyed fixing little issues here and there and liked creating
new tags to help out the Python Team, where most of my Debian time was spent.
Lintian was badly in need of a new maintainer and as I felt it was an important
project, I decided to step in. 37 releases and about 160 closed bugs
later2, I'm done.
To be honest, I haven't had much fun maintaining Lintian lately. Bugs keep
piling on the BTS, so much so I have mostly been ignoring them for the past few
months. In fact, most of the actual work triaging, writing code and fixing bug
has been done by Nilesh Patra for a while now.
All this to say, if you care about Lintian, you should consider adding yourself
to the Uploaders list, as I'm out and Nilesh can't do all the work by himself.
He's a great person to work with and since I don't want to suddenly leave him
all alone, I'll be sticking around for a few more weeks in the hope someone
else will volunteer to help out. A smooth transition with a new co-maintainer
would really be nice!
If you're interested, don't hesitate to reach out to me on IRC or by email.