Christians Tagebuch

The latest posts in full-text for feed readers.


Windows 11 setup: Media driver missing

When trying to reinstall Windows 11 on a new laptop, I got the following error during setup:

A media driver your computer needs is missing, this could be a DVD/ USB/ Hard Disk driver. If you have a CD/ DVD/ USB flash drive with driver on it, please insert it now.

and in German

Ein vom Computer benötigter Medientreiber fehlt. Dies kann ein DVD-, USB- oder Festplattentreiber sein. Wenn Sie über eine CD, DVD oder ein USB-Speicherstick mit dem Treiber verfügen, legen Sie sie jetzt ein.

The drivers Asus offers on support website for its Vivobook X1704VA-AU774 are installer .exe files that cannot be used during Windows setup.

Problem cause

I downloaded the Win11_25H2_German_x64.iso from Microsoft's official Windows 11 download page and the copied the file on my Debian 13 Linux computer onto the USB flash drive:

cp /home/cweiske/Downloads/Win11_25H2_German_x64.iso /dev/sdb

This is the problem: Not all parts of the iso file are available to the setup, and so it fails with missing drivers.

Solution

Instead of directly copying the iso file to the flash drive, I used WoeUSB to create a proper bootable flash drive from the .iso file.

On Debian 13, I had to install wimtools and grub-pc-bin to get WoeUSB 5.2.4 working.

I also used the unattended installation generator to create a autounattend.xml file that let me setup Windows without internet connection and with a local account.

Asus Vivobook 17 X1704VA

I can't recommend the laptop. It feels very cheap and the CPU fan always spins - even if no application is running.

Published on 2025-10-17 in


composer does not find branch in forked repository

At work I forked the git repository of a TYPO3 extension, created a branch and tried to install it in my project - but composer failed to find it.

At first I added a repositories section with my forked github repo as vcs repository:

"repositories": [
    {
        "type": "vcs",
        "url": "https://github.com/mogic-le/aus_driver_amazon_s3"
    }
],

Then I tried to install my branch:

$ composer require andersundsehr/aus-driver-amazon-s3:dev-mogic-v13
./composer.json has been updated
Running composer update andersundsehr/aus-driver-amazon-s3
Loading composer repositories with package information
Updating dependencies
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - Root composer.json requires andersundsehr/aus-driver-amazon-s3 dev-mogic-v13, found andersundsehr/aus-driver-amazon-s3[dev-feature/unbundle-sdk, dev-feature/matrix-tests, dev-functional-tests-alternative, dev-task/fixTests, dev-master, dev-TYPO3v13, dev-bugfix/clear-transient-file, 1.3.2, ..., 1.13.5, 2.0.0] but it does not match the constraint.


Installation failed, reverting ./composer.json to its original content.

After half an hour I finally found the reason:

$ composer validate
./composer.json is valid, but with a few warnings
See https://getcomposer.org/doc/04-schema.md for details on the schema
# General warnings
- Key repositories is a duplicate in ./composer.json at line 68

My composer.json already had a "repositories" section at the end, but I added a new section near the beginning. The section at the end overwrote the one at the beginning, and so composer never saw my custom repository.

Published on 2025-10-10 in


Spamming with Google groups

Today I noticed a new way to send spam to many people: Google Groups, a mailing list platform.

In the last days I got many automatic replies from people and companies I don't know and never contacted: out-of-office reminders and "thank you, we will take care" mails.

The mails were sent to support@gh.onlinebildunchkeiten.de and all contained mailing list headers:

Precedence: list
Mailing-list: list phn@gh.onlinebildunchkeiten.de; contact phn+owners@gh.onlinebildunchkeiten.de
List-ID: <phn.gh.onlinebildunchkeiten.de>
X-Spam-Checked-In-Group: suppsdhsdksdhee@gh.onlinebildunchkeiten.de
X-Google-Group-Id: 320817839263
List-Post: <https://groups.google.com/a/gh.onlinebildunchkeiten.de/group/phn/post>,
    <mailto:phn@gh.onlinebildunchkeiten.de>
List-Help: <https://support.google.com/a/gh.onlinebildunchkeiten.de/bin/topic.py?topic=25838>,
    <mailto:phn+help@gh.onlinebildunchkeiten.de>
List-Archive: <https://groups.google.com/a/gh.onlinebildunchkeiten.de/group/phn/>
List-Subscribe: <https://groups.google.com/a/gh.onlinebildunchkeiten.de/group/support/subscribe>,
    <mailto:support+subscribe@gh.onlinebildunchkeiten.de>
List-Unsubscribe: <mailto:googlegroups-manage+320817839263+unsubscribe@googlegroups.com>,
    <https://groups.google.com/a/gh.onlinebildunchkeiten.de/group/phn/subscribe>

This was a Google group mailing list! And as usual with Google things, there was no way to report spam or abuse.

I imagine the process to be as follows:

  1. Spammer creates Google group and marks it as private
  2. Spammer adds hundreds of e-mail addresses to the list
  3. Spammer sends spam e-mails to the list
  4. People get the spam, and some mail servers send automated replies to the list - which all subscribed people receive as well.

The nice thing for spammers is that Google servers have good reputation and won't be blocked by administrators. This spam mails have a high chance of passing mail filters.

It is possible to unsubscribe from this spam list by sending an e-mail to a personalized e-mail address that you can find in the e-mail's List-Unsubscribe header. Make sure you send it from the same e-mail address it is sent to; that can be found in one of the Received headers :(

Unsubscribing

When sending an e-mail to the unsubscription address, a confirmation comes back with an image:

Unsubscription footer image from https://www.google.com/a/cpanel/vay.xylontrix.cfd/images/logo.gif?service=groups2

The text is written in thai (according to ChatGPT):

โรงเรียนบ้านปางสุด - Ban Pang Sut School
สพป.นครสวรรค์ เขต 2 - Nakhon Sawan Primary Educational Service Area Office 2

At least the text part is signed with vay.xylontrix.cfd admins. cfd is a valid top-level domain, and xylontrix.cfd is registered, according to the ICANN lookup tool.

Published on 2025-10-09 in ,


PHP: Laravel job dispatch magic

Today I reviewed code written by a co-worker and I saw the following:

$job = ProductSync::dispatch();
if ($later) {
    $job->delay(now()->addMinutes(1));
}

That's it. There is no later code that actually commits it into the queue.

I did not understand it: If the job is indeed put into the queue when ::dispatch() is called, then there is a time window in which a queue worker could take the job, even before the delay is added. That would be a race condition, which I couldn't believe would exist in this framework.

That code is correct; that usage is documented.

How does it work?

Tasks that may be put into the queue use the Dispatchable trait. Running dispatch() returns a PendingDispatch object.

This PendingDispatch class is where the magic happens: In its __destruct method the task is put into the queue!

As soon as the PHP garbage collector notices that the $job variable is not used anymore, it will call the destructor that puts the job into the queue. This won't happen as long as the variable is held somewhere, which makes it a perfectly safe way to allow developers to call additional methods on the job later in the code - and you don't need a final commit() that actually puts the job into the queue.

An indeed magical way to use this magic method.

Published on 2025-10-09 in


OpenWrt support for Zyxel NWA90AX

The 2nd floor needed an additional wifi access point, and so I purchased a used Zyxel NWA90AX for 60€ on kleinanzeigen.de.

Before buying I checked that it is supported by OpenWrt and found that NWA90AX Pro is supported, but it uses a totally different chipset. The NWA50AX is also supported and has the same hardware as the NWA90AX:

NWA90AX: Identical hardware as in NWA50AX, but with added features like Captive portal for Guest access and WPA Enterprise for AD/Radius (Credential) authentication.

I followed the NWA50AX instructions (especially flashing the vendor firmware to get the Current Image to 1), but then flashing failed with:

errno: -25007
errmsg: Firmware content error!

I immediately suspected that the firmware contains a list of compatible models, but needed 5 days and many detours to - accidentially - find the model code 77 e1 of the NWA90AX.

Now the access point provides beautiful 5 + 2.4 GHz wireless lan with the latest OpenWrt firmware. The patch that adds support is awaiting review.

Zyxel NWA90AX

Accidental discovery

I downloaded every available NWA50AX and NWA90AX firmware to check which 50 version I can flash over the same 90 version.

Version NWA50AX NWA90AX
6.25(8) NWA50AX_6.25(ABYW.8)C0.zip
6.27(2) - NWA90AX_6.27(ACCV.2)C0.zip
6.29(3) NWA50AX_6.29(ABYW.3)C0.zip NWA90AX_6.29(ACCV.3)C0.zip
6.29(4) NWA50AX_6.29(ABYW.4)C0.zip NWA90AX_6.29(ACCV.4)C0.zip
7.00(1) - NWA90AX_7.00(ACCV.1)C0.zip
7.00(2) NWA50AX_7.00(ABYW.2)C0.zip NWA90AX_7.00(ACCV.2)C0.zip
7.10(1) - NWA90AX_7.10(ACCV.1)C0.zip
7.10(3) NWA50AX_7.10(ABYW.3)C0.zip NWA90AX_7.10(ACCV.3)C0.zip

Only the latest V7.10(3) was the one whose 50 version I could flash onto my 90 hardware.

While installing the firmware versions, I had the browser developer console's network tab open and saw the following:

## Checking hash(es) for FIT Image at 752a9000 ...
   Hash(es) for Image 0 (script): sha256+

   Hash(es) for Image 1 (Bootloader): sha256+

   Hash(es) for Image 2 (firmware): sha256+

   Hash(es) for Image 3 (rootfs_data): sha256+

   Hash(es) for Image 4 (logs): sha256+

   Hash(es) for Image 5 (myzyxel): sha256+

   Hash(es) for Image 6 (bootconfig): sha256+

   Hash(es) for Image 7 (mrd): sha256+

Content-Type: text/html

<html><head></head><body>
var zyshdata0=[{'_model':'NWA90AX','_firmware_version':'V6.29(ACCV.4)','_build_date':'2024-01-10 14:37:56'}];
var errno0=0;
var errmsg0='OK';
</body></html>
Upgrade started
Current time: Sat Sep 27 15:54:56 DGMT 2025
----- kernel cmdline -----
console=ttyS0,115200 loglevel=1 bootImage=1 bootVer=V1.03 rootfstype=squashfs,jffs2
------- FW version -------
FIRMWARE_VER=6.29(ACCV.4)
BUILD_DATE=2024-01-10 14:37:56
MODEL_ID=NWA90AX
COMPATIBLE_PRODUCT_MODEL_0=77E1
COMPATIBLE_PRODUCT_MODEL_1=FFFF
COMPATIBLE_PRODUCT_MODEL_2=FFFF
COMPATIBLE_PRODUCT_MODEL_3=FFFF
COMPATIBLE_PRODUCT_MODEL_4=FFFF

I don't know if that was a bug in this specific firmware, but the upgrade log was sent to the browser - not only the part within the <html>. But this was where I found the NWA90AX's model code.

Published on 2025-10-05 in


Conexa 3.0 Smart Meter in Volkszähler einbinden

Mit dem Gesetz zur Digitalisierung der Energiewende vom August 2016 wurden Messstellenbetreiber dazu verpflichtet, daß

[...] ab 2017 innerhalb von acht Jahren alle Messstellen an Zählpunkten mit einem Jahresstromverbrauch über 10 000 bis einschließlich 20 000 Kilowattstunden mit einem intelligenten Messsystem ausgestattet werden [...]

Gesetz über den Messstellenbetrieb und die Datenkommunikation in intelligenten Energienetzen - §31, Punkt 1.4

Da meine Wärmepumpe bei ~11.000 kWh pro Jahr liegt, hätte ich bis 2025 angeschlossen werden müssen. Ende August 2025 habe ich von einem Subauftragnehmer der Mitnetz ein intelligentes Messystem installiert bekommen, d.h. einen digitaler Stromzähler mit angeschlossenem Smart Meter Gateway, der den Stromverbrauch alle 15 Minuten nach Hause sendet.

Die Zählerdaten wollte ich lokal abrufen und in meine Volkszähler-Instanz einspeisen - dort landen auch schon die Daten des Hausstromzählers, der schaltbaren Steckdosen und der Waschmaschine.

Theben Conexa 3.0

Der digitale Stromzähler ist ein Landis Gyr E320 Zweirichtungszähler, an den ein Smart Meter Gateway (SMGW) vom Typ Theben Conexa 3.0 angeschlossen ist. Da es im Zählerschrank nicht so guten Empfang gibt, hat der Installateur zusätzlich eine LTE-Antenne angeschlossen.

Das eigentlich schöne ist aber, daß es einen RJ45-Netzwerkanschluss gibt, der mit "HAN" - Home Area Network - betitelt ist.

Stromzähler + Smart Meter Gateway im Schaltschrank. Rechts ist die LTE-Antenne zu sehen.

IP-Adresse

Meine Kommunikationsversuche mit ihm schlugen aber alle fehl; ein Ping-Scan brachte keine Ergebnisse. Über die Netzwerkschnittstelle kamen keine Daten - nicht mal eine DHCP-Anfrage nach einer IP-Adresse. Im Handbuch steht dann folgendes:

Die IP-Adresse der HAN-Schnittstelle wird durch den Betreiber/Verwender zur Verfügung gestellt.

Portale, Portale

Da wir in digitalen Zeiten leben dachte ich mir, daß man die Zugangsdaten bestimmt online einsehen kann und registrierte mich im Kundenportal für Netzkunden - nur um festzustellen, daß es dort keine Zugangsdaten gibt.

Die restlichen Portale auf der Portale & Services-Seite der Mitnetz klangen nicht so, als sind sie für mich geeignet.

Dann las ich den Brief von der Mitnetz nochmal:

Ihr neuer Zähler ist mit dem Messdatenportal der MITNETZ STROM verbunden. Das hat für Sie den Vorteil, dass Sie Ihre Messdaten jederzeit genau im Blick haben können. Was ist dafür zu tun? Melden Sie sich nach dem Einbau einfach im Kundenportal der MITNETZ STROM unter meine.mitnetz-strom.de für diesen kostenfreien Service an.

Das "Kundenportal" unter dieser Adresse ist die AppC App im Online-ANA & Extranet für Installateure und Planungsbüros , für das ich mich natürlich neu registrieren musste. Dort gibt es einen Punkt Meine Apps > Messdaten, hinter dem ein Formular hängt: Sie möchten die Verbrauchswerte Ihres intelligenten Messsystems einsehen?.

Nachdem ich das abgeschickt hatte, bekam ich 2 Tage später 3 E-Mails: Eine mit dem Benutzernamen, eine zweite mit dem Passwort, und die dritte mit der URL für das dritte Kundenportal: Das "Ecount Webportal" unter edm.mitnetz-strom.de.

HAN-Passwort

Im Ecount-Webportal gibt es - neben der Anzeige der aktuellen Verbrauchsdaten - auch einen Menüpunkt "HAN", unter dem man Benutzernamen des Stromzählers sieht und das Passwort setzen kann.

Das Formular war bei mir deaktiviert, weil meinem Account das Smart Meter Gateway nicht zugeordnet war:

Es wurde kein zugeordnetes SMGW gefunden.

Ich schrieb eine E-Mail an den Support, und 2 Wochen später konnte ich den Benutzernamen sehen (004747572657_ECPR0000476734) und ein Passwort setzen. Nach ca. 45 Minuten war das Passwort dann auf das SMGW übertragen. Vorher stand da:

Das HAN-Passwort wird in Kürze gesetzt.

und

Das HAN-Passwort kann nicht gesetzt werden. Ein Auftrag zum Setzen des Passwortes liegt bereits vor.

Es werden sogar für das SMGW komplexe Passwörter verlangt:

Passwortrichtlinien

  • Mindestens 10 und maximal 32 Zeichen
  • Mindestens einen Kleinbuchstaben
  • Mindestens einen Großbuchstaben
  • Mindestens eine Ziffer
  • Mindestens ein Sonderzeichen. Zulässig sind: !/()=?+*~#',;.:-_

IP!

Initial hatte ich per E-Mail um die Zugangsdaten zum SMGW gebeten, nur um dann per Post die PIN für den digitalen Stromzähler zu bekommen.

Um das abzukürzen, hatte ich dann den Support angerufen (am Sonnabend - das ist noch Service!) und daraufhin eine E-Mail mit Hinweisen zum Zugriff erhalten:

Um die HAN-Schnittstelle des Gateways zu nutzen und die auf dem Gateway gespeicherten Daten abrufen können, stehen Ihnen zwei Möglichkeiten zur Verfügung.

Bitte beachten Sie, dass die IP-Adresse für die HAN-Schnittstelle des Gateways mit 192.168.1.200 fest vorgegeben ist.

1. Möglichkeit:

Eine vom Hersteller entwickelte Oberfläche, wo die abgespeicherten Messwerte abrufbar sind.

https://192.168.1.200/cgi-bin/hanservice.cgi

Für die Anmeldung nutzen Sie bitte folgende Nutzerdaten:

1. Der Benutzername ist voreingestellt und wird Ihnen im Visualisierungsportal unter dem Reiter "HAN" angezeigt.

2. Das Kennwort vergeben Sie sich bitte im Visualisierungsportal unter dem Reiter "HAN".

2. Möglichkeit

Über die sogenannte TruDi (transparent- und Display-Software) können Sie sich ebenfalls die im Gateway gespeicherten Messwerte über die HAN-Schnittstelle ansehen. Der Vollständigkeit halber erhalten Sie den Link zur Seite der Physikalisch Technischen Bundesanstalt (PTB), wo neben der Software TruDi auch die Bedienungsanleitung heruntergeladen werden kann.

https://www.ptb.de/cms/de/ptb/fachabteilungen/abt2/fb-23/ag-234/info-center-234/trudi.html

Für die Anmeldung benötigen Sie neben den oben benannten, folgende Informationen:

3. IP-Adresse: 192.168.1.200,

4. Port: 443.

Es gibt keine Möglichkeit, die IP-Adresse anzupassen.

Da auch die Subnetzmaske des SMGW nicht änderbar ist, kommt man mit der Änderung der eigenen Subnetzmaske auch nicht weit - die Pakete kommen dann zwar zum SMGW, aber nicht zurück. Man muss deshalb unbedingt eine Adresse im 192.168.1.x-er Netz haben, um auf das Gateway zugreifen zu können.

Mein Heimnetz liegt im Bereich 192.168.3.x, deshalb musste ich meinem Homeserver eine zweite IPv4-Adresse geben.

Conexa Web-Interface

Jetzt war der Weg frei, um an den aktuellen Stromverbrauch der Wärmepumpen zu kommen! Ich öffnete https://192.168.1.200/ im Browser, tippte Benutzernamen und Passwort ein und ... sah das:

Conexa Web-Interface Seite 1 Conexa Web-Interface Seite 2

Das wars! Keine Messdaten, keine Netzwerkinformationen, nichts. Nicht einmal das Ergebnis des Selbsttests kann man über das Interface abrufen.

Pfui, Theben Smart Energy.

Auch der versprochene hanservice.cgi ist nicht verfügbar.

API

Glücklicherweise sind die Geräte mit einer API ausgestattet, die auch von der TRuDi-Software genutzt wird. Mit dieser Software war es möglich, die Zählerdaten abzurufen.

Ich fand das smgw-theben-conexa-Projekt auf GitHub, welches eine Kopie der API-Dokumentation Schnittstellenbeschreibung IF_GW_CON.pdf enthält. Damit hatte ich alle notwendigen Informationen.

Smart Meter Gateway-Informationen

Den URL-Pfadteil ecpr0000476738.sm habe ich aus der URL des Web-Interface kopiert.

$ curl -s --digest -k --user "username:passwort"\
  -XPOST -H 'Content-type: application/json'\
  https://192.168.1.200/smgw/m2m/ecpr0000476738.sm/json\
  --data '{"method":"smgw-info"}'\
  | jq .
{
  "elapsed-time": "28 miliseconds",
  "method": "smgw-info",
  "smgw-info": {
    "certificates": {
      "han": {
        "tls": "2d2d2d2d2[...]"
      },
      "wan": [
        {
          "cert-index": "0",
          "sig": "308203be[...]",
          "sub-ca": "308204373[...]"
        },
        {
          "cert-index": "1",
          "sig": "308203c130[...]",
          "sub-ca": "3082042b3[..]"
        }
      ]
    },
    "firmware-info": {
      "component": "Firmware",
      "hash": "bff7b08c0b6669be02fece905da7acc7c92b73a53c992893d1e19673e7dd1cfd",
      "version": "v3.80.3-cc"
    },
    "smgw-id": "ethe0300427561",
    "smgw-state": "a0000000",
    "smgw-time": "2025-10-03T11:21:57"
  },
  "version": "1.3.0"
}

Logmeldungen

$ curl -s --digest -k --user "username:password"\
  -XPOST -H 'Content-type: application/json'\
  https://192.168.1.200/smgw/m2m/ecpr0000476738.sm/json\
  --data '{"method":"log","fromtime":"2025-10-03T11:20:00"}'\
  | jq .
{
  "elapsed-time": "19 miliseconds",
  "log": {
    "entries": [
      {
        "event-id": "13003",
        "event-sub-id": "0",
        "index": "2439",
        "level": "6",
        "message": "Die Systemzeit wurde mit der gesetzlichen Zeit synchronisiert. Die neue Zeit ist 2025-10-03T11:20:49+02:00. Die alte Zeit war 2025-10-03T11:20:49+02:00. Die Differenz betrug 22 Millisekunden.",
        "outcome": "0",
        "subject-identity": "01005e3180a0.ethe0300427561.sm",
        "time": "2025-10-03T09:20:50Z",
        "user-identity": "01005e318011.ecpr0000476738.sm",
        "vendor-id": "PTB",
        "version": "1"
      }
    ],
    "records": "1"
  },
  "method": "log",
  "version": "1.3.0"
}

Vertragsinformationen

Hier wird es interessant, weil wir für das Auslesen die usage-point-id benötigen. Bei mir gibt es 2 "usage points": Der erste gruppiert monatlich und deshalb wenig "billing-Periods"; der zweite gruppiert nach Tagen:

$ curl -s --digest -k --user "username:password"\
  -XPOST -H 'Content-type: application/json'\
  https://192.168.1.200/smgw/m2m/ecpr0000476738.sm/json\
  --data '{"method":"user-info"}'\
  | jq .
{
  "elapsed-time": "781 miliseconds",
  "method": "user-info",
  "user-info": {
    "usage-points": [
      {
        "billing-Periods": [
          {
            "end-time": "2025-08-31T22:00:00Z",
            "start-time": "2025-08-29T10:30:01Z"
          },
          {
            "end-time": "2025-09-30T22:00:00Z",
            "start-time": "2025-08-31T22:00:00Z"
          },
          {
            "start-time": "2025-09-30T22:00:00Z"
          }
        ],
        "capture-time": "00:00:00",
        "delivery-id": "ecpr0000476735",
        "end-time": "",
        "meter": [
          {
            "meter-id": "1lgz0082488485"
          }
        ],
        "metering-point-id": "DE0010810480800000000000000088119",
        "on-demand-profile-configured": "true",
        "start-time": "2025-08-29T10:30:01Z",
        "taf-number": "1",
        "taf-state": "running",
        "usage-point-id": "01005e318021.taf014042805000706de0010810480800000000000000088119000000305185.sm",
        "usage-point-name": "IM4G_TAF01_15MI_MON_MON"
      },
      {
        "billing-Periods": [
          {
            "end-time": "2025-08-29T22:00:00Z",
            "start-time": "2025-08-29T10:30:01Z"
          },
          [...]
          {
            "end-time": "2025-10-01T22:00:00Z",
            "start-time": "2025-09-30T22:00:00Z"
          },
          {
            "end-time": "2025-10-02T22:00:00Z",
            "start-time": "2025-10-01T22:00:00Z"
          },
          {
            "start-time": "2025-10-02T22:00:00Z"
          }
        ],
        "capture-time": "00:00:00",
        "delivery-id": "ecpr0000476735",
        "end-time": "",
        "meter": [
          {
            "meter-id": "1lgz0082488485"
          }
        ],
        "metering-point-id": "DE0010810480800000000000000088119",
        "on-demand-profile-configured": "true",
        "start-time": "2025-08-29T10:30:01Z",
        "taf-number": "7",
        "taf-state": "running",
        "usage-point-id": "01005e318027.taf074042805000706de0010810480800000000000000088119000000305184.sm",
        "usage-point-name": "IM4G_TAF07_15MI_15MI_DAY"
      }
    ]
  },
  "version": "1.3.0"
}

Ich hab mir "usage point" mit der täglichen Gruppierung ausgesucht.

Daten!

Mit der usage-point-id kann man sich Verbrauchsdaten über einen Zeitraum abholen, oder aber nur den letzten Zählerwert:

$ curl -s --digest -k --user "username:password"\
  -XPOST -H 'Content-type: application/json'\
  https://192.168.1.200/smgw/m2m/ecpr0000476738.sm/json\
  --data '{"method":"readings","database":"origin","last-reading":true,"usage-point-id":"01005e318027.taf074042805000706de0010810480800000000000000088119000000305184.sm"}'\
  | jq .
{
  "elapsed-time": "26 miliseconds",
  "method": "readings",
  "readings": {
    "channels": [
      {
        "obis": "0100010800ff",
        "readings": [
          {
            "capture-time": "2025-10-03T09:29:57Z",
            "cosem-status": "a000000020803800",
            "meter-status": "20803800",
            "owner-number": "1lgz0082488485.sm",
            "signature": "91ba8abd883[...]",
            "smgw-status": "a0000000",
            "target-time": "2025-10-03T09:30:00Z",
            "value": "4075668"
          }
        ]
      }
    ],
    "records": "1"
  },
  "version": "1.3.0"
}

Die 4075668 sind 407,5668 kWh.

Volkszähler-Integration

Der Smart Meter Gateway wird auf dieselbe Weise eingebunden, wie ich es schon mit den Shelly Plug S gemacht hatte.

Zuerst im Webinterface des Volkszählers einen neuen Kanal anlegen:

Typ
El. Energie (Zählerstände)
Auflösung
10000
Stil
Stufen

Nach dem Anlegen wird eine Kanal-ID angezeigt; diese braucht man jetzt bei der vzlogger-Konfiguration im meters-Abschnitt:

//wärmepumpen
{
    "protocol": "exec",
    "enabled": true,
    "allowskip": true,
    "interval": 300,
    "command": "curl -s --digest -k --user \"username:password\" -XPOST -H 'Content-type: application/json' https://192.168.1.200/smgw/m2m/ecpr0000476738.sm/json --data '{\"method\":\"readings\",\"usage-point-id\":\"01005e318027.taf074042805000706de0010810480800000000000000088119000000305184.sm\",\"database\":\"origin\",\"last-reading\":true}' | jq -r '[\"total\", .readings.channels[].readings[].value] | join(\" \")'",
    "format": "$i $v",
    "channels": [
	{
            "uuid": "a9cc7410-a01f-11f0-bd17-a9f5d1d0316e",
            "middleware": "http://strom.home.cweiske.de/middleware.php",
            "identifier": "total",
	    "aggmode": "max"
	}
    ]
},

Jetzt den vzlogger neustarten und die Daten fließen alle 5 Minuten in die Datenbank.

Rupert schrieb auf volkszaehler-users, daß das SMGW die Daten nur alle 15 Minuten abliest. Wenn man sich die Graphen genauer anschaut, dann stimmt das auch :( Das interval kann deshalb auf 900 geändert werden.

Screenshot vom Volkszähler-Webinterface mit den Daten

Published on 2025-10-03 in ,


Why learn when AI does everything better?

In the 2012 Hydrogen Sonata culture novel, Iain M. Banks lets the main character lose interest in learning a musical instrument when the artificial intelligence of a star ship plays the instrument perfectly - just because it is jealous of her:

She duly lost the desire to play the elevenstring; misplaced it for about fifteen years following that performance by the carelessly perfect cobbled-together artificial version of an absurd-looking alien.

What was the point of taking the time learning to play anything as well as you could, when a machine could use something it would think of as little better than its hand puppet to play so achingly, immaculately, ravishingly well, exactly as though it was the creature that had spent a lifetime studying, understanding and empathising with the instrument and all that it signified and meant?

That was 10 years before ChatGPT.


In Use of weapons from 1990 he answers the question:

"Can't machines build these faster?" he asked the woman, looking around the starship shell.

"Why, of course!" she laughed.

"Then why do you do it?"

"It's fun. You see one of these big monsters sail out those doors for the first time, heading for deep space, three hundred people on board, everything working, the Mind quite happy, and you think; I helped build that.
The fact a machine could have done it faster doesn't alter the fact that it was you who actually did it."

Published on 2025-09-27 in ,


Spammers ruin: websub

A week ago I noticed a high CPU load on my web server and found that 4 CPUs were busy executing tasks created by my WebSub server implementation phubb.

Spam info

Upon further investigation I found that there were ~1500 remote IP addresses sending ~3500 ping requests per minute to my server. Each request spawned a background process, leading to the high server load.

The source IPs were split geographically across a couple dozen of countries, the top 5 being:

59IR, Iran, Islamic Republic of
64RO, Romania
311GB, United Kingdom
123UA, Ukraine
1000US, United States

The feed URLs for which update pings were sent to my server were e.g. http://romareis.nl/atom320756.xml and many more domains.

When opening the URLs listed inside the feed with a browser, they redirected to bt-fr-cl.com and some subpath. This seems to be a tracking service that counts link clicks, which might give an explanation for the spam attack: Get links to those URLs visible to many eyes and have people click on them, to get ad revenue or even getting paid per click.

Mitigation

I added a whitelist to phubb and now only allow pings and subscriptions for cweiske.de.

Fuck you, spammers. I wish you a slow and painful death.

CPU load
CPU load drop

Published on 2025-09-19 in ,


Bester Loginfail

Das Wurzener Gymnasium nutzt beste.schule als digitales Notenbuch. Mit Beginn des Schuljahres 2025/26 wollte ich mich dort anmelden um zu sehen, ob es schon irgendetwas Neues gibt.

Auf https://beste.schule/login funktionierten meine Zugangsdaten nicht mehr; ich bekam den Fehler

Diese Kombination aus Zugangsdaten wurde nicht in unserer Datenbank gefunden.

Der Support verwies mich an die Admins des Gymasiums, die mir antworteten, daß es eine technische Panne gab durch die wir die Schlüssel neu vergeben müssen. Auf Nachfrage wurde mir mitgeteilt, daß es zur leider endgültigen Entknüpfung von Konten und Nutzern gekommen ist.

Das Magnus-Gottfried-Lichtwer-Gymnasium hat ~700 Schüler und genauso viele Eltern. Mindestens 1400 Personen benötigten also neue Codes, um ihren beste.schule-Account mit den Schülerdaten zu verknüpfen.

Die Verteilung der vielen Zettel mit den Codes war - im Vergleich mit dem Einspielen von Backups - der offenbar einfachere Weg. Hier muss beste.schule besser werden.

Published on 2025-09-19 in


GameStick server HTML interface

After several months of work the community GameStick server has a HTML interface that lets you browse all the 188 games available for the GameStick.

On a desktop browser, the UI looks like the original marmalade-based GameStick interface. Use a smart phone or tablet device and the website looks a like a typical modern mobile web page.

The web interface has a couple of improvements over the old UI: You may filter games by genre and features - it's easy to find games for 2 players for some couch co-op, or platformer or racing games.

Featured games list List of all games Game details Achievement list

Also on: Mastodon, Twitter.

Published on 2025-09-03 in , ,