nocin.eu

Homelab, Linux, JS & ABAP (~˘▾˘)~
 

[HR] OM – Besetzungsplan (Struktur)

Da ich nur selten mit dem OM arbeite, vergessen ich immer wieder, wie man das OM “umdreht”, wenn man eine Person ausgewählt hat. Also die Anzeige von P – S – O umkehrt auf O – S – P.
Dabei ist es total einfach! Die Org. Einheit markieren und links oben in der Toolbar auf den Dropdown Button (Springen) gehen und Besetzungsplan (Struktur) auswählen und man erhält die gewünschte Ansicht.

[Android] Upgrading LineageOS 20.0 to 21.0 on my Xiaomi Mi 8 (dipper)

Install the Android Debug Bridge (ADB)

https://wiki.lineageos.org/adb_fastboot_guide.html
https://github.com/M0Rf30/android-udev-rules#installation

# check if device is found
adb devices
# reboot into sideload modus
adb reboot sideload

Or manually boot into recovery, holding Volume Up + Power when the phone is off. Navigate to AdvancedADB Sideload.


Update MIUI Firmware

Following the docs, I first had to check the Firmware version. V12.0.3.0.QEAMIXM was required, and I already had it installed.
If you’re on an older version, download the right MIUI Firmware for your device from https://xiaomifirmwareupdater.com/firmware/dipper/.
Flash the new Firmware via TWRP or via ADB sideload.

adb sideload fw_dipper_miui_MI8Global_V12.0.3.0.QEAMIXM_7619340f8c_10.0.zip

Flash latest recovery

Since I follow the LineageOS subreddit, I have already seen posts with problems with the latest update. Check here: https://www.reddit.com/r/LineageOS/comments/1fxlmtq/regular_ota_update_20241005_on_xiaomi_mi8_dipper/
There it is recommended to flash the latest recovery to prevent any issues. Although this is step 1 in the upgrade guide, I skipped updating the recovery the last years, because I was using TWRP instead of the LineageOS recovery. But to be on the safe side, this time I flashed the LineageOS recovery (which meant loosing/removing TWRP). To flash the recovery, you must first boot into fastboot by using adb or Volume Down + Power when the phone is off, like it is described here.

# boot into fastboot
adb -d reboot bootloader
# flash recovery
fastboot flash recovery lineage-21.0-20241208-microG-dipper-recovery.img

Download and flash new LineageOS image

I’m using the LineageOS fork LineageOS for microG. Download it from here: https://download.lineage.microg.org/dipper/ (MI 8 = dipper)
The upgrade steps are the same as for the official rom: https://wiki.lineageos.org/devices/dipper/upgrade. As I’ve already flashed the latest recovery, I only had to flash the new LineageOS image.

# reboot again into recovery
adb reboot sideload
# flash again new image
adb sideload lineage-21.0-20241208-microG-dipper.zip

[HR] A1-Meldeverfahren

Übersicht

Gute Zusammenfassung: https://www.iprocon.de/abbildung-des-a1-meldeverfahrens-in-sap-hcm/

2682093 – Informationen zur Umsetzung des A1-Meldeverfahrens im SAP-System (siehe auch das PDF im Hinweis)

2730927 – A1-Verfahren: Hilfestellung zum Customizing

2833850 – A1-Verfahren: Archivierung der A1-Bescheinigung und Erweiterung für das BAdI HRPAYDE_A1_EMAIL

2841779 – A1-Verfahren: ESS-Szenario (Web-Dynpro ABAP) (Paket PAOC_ESS_A1_DE)

Die Datenerfassung der Antragsdaten erfolgt im Infotyp: 0700 (Elektronischer Datenaustausch)
Subtypen:

  • DXA1 (A1: Antrag Entsendebescheinigung)
  • DXAV (A1: Antrag Ausnahmevereinbarung)

Reports zur Erstellung der Meldungen und der Meldedateien:

  • Personal → Personalabrechnung → Europa → Deutschland → Folgeaktivitäten → Periodenunabhängig → Abrechnungszusatz → A1-Meldeverfahren → Ausgangsmeldungen

Reports zur Verarbeitung der Eingangsmeldungen:

  • Personal → Personalabrechnung → Europa → Deutschland → Folgeaktivitäten → Periodenunabhängig → Abrechnungszusatz → A1-Meldeverfahren → Eingangsmeldungen

Behördenkommunikation (B2A): Transaktion PB2A

  • Personal → Personalabrechnung → Europa → Deutschland → Folgeaktivitäten → Periodenunabhängig → Behördenkommunikation (B2A) → B2A-Manager

Hilfreiche Entwicklungsobjekte

Paket: P01S

Reports:

Klassen:

Für mich hilfreich waren folgenden Klassen:

  • CL_HRPAYDE_A1_NOTIF (Klasse für A1-Meldungen)
  • CL_HRPAYDE_A1_NOTIF_DISPLAYER (ALV-Ausgabe für A1-Meldungen)
  • CL_HRPAYDE_A1_ALV_EVNT_HANDLER (Ereignisbehandler für A1-spezifische Ereignisse)

PDFs der A1-Meldungen von Datenbank lesen

*&---------------------------------------------------------------------*
*& Tabellen A1-Meldeverfahren:
*& P01A1_STAT    - A1-Verfahren: Verwaltungstabelle
*& P01A1_RAWDATA - A1-Verfahren: Rohdaten einer Meldung
*&---------------------------------------------------------------------*

GET peras.

  SELECT * INTO TABLE @DATA(lt_p01a1_stat) FROM p01a1_stat
    WHERE pernr  = @pernr-pernr
      AND mdtyp  = '2'
      AND status = '23'
      AND mzbeg <= @pn-endda
      AND mzbeg >= @pn-begda.

  LOOP AT lt_p01a1_stat INTO DATA(ls_p01a1_stat).

    SELECT SINGLE * INTO @DATA(ls_p01a1_rawdata) FROM p01a1_rawdata
      WHERE guid = @ls_p01a1_stat-guid
        AND lfdnr = ( SELECT MAX( lfdnr ) FROM p01a1_rawdata WHERE guid = @ls_p01a1_stat-guid ). "höchste lfdnr nehmen

    DATA(pdf_xstring) = ls_p01a1_rawdata-rawdata.

  ENDLOOP.

[Home Assistant] Combine Adaptive Lightning, motion activated light and lights turned on by sunset

In my home, I have some motion activated lights, for example in the kitchen. During daytime, the kitchen light should simply be turned on and off by the motion sensor. But when the sun sets, I like to turn on most of the lights in the house to 1% brightness, so that you never walk into a completely dark room. In this case, the motion sensor should not turn the kitchen light on and off, but instead should increase the brightness and afterward go back to the previous state of 1% brightness. And with “increase the brightness”, I don’t mean a fix value, but instead it should set the right brightness provided by the Adaptive Lightning integration. When it’s late, and the sleep mode is tuned on for the house, the kitchen light of course should be turned off, and when it is turned on, it should respect the configured sleep values from Adaptive Lightning settings.

Most things turned out to be quite easy by using Scenes to store the current light state and of course by using the great Adaptive Lightning features. But my automation had one important gap. When someone was is the kitchen, means kitchen light was turned on by the motion sensor, and we had sunset in this exact moment, it would always turn down the brightness to 1%, because the automation which turns on all lights to 1% brightness when the sun sets got triggered. Also, when the person left the kitchen, the previous stored scene was loaded, which was created before sunset, means it turned off the kitchen light, instead of the now required 1% brightness. This was of course really confusing for people in the kitchen…

I needed a way, to only activate the 1% sunset brightness, when no one is currently in the kitchen. The solution was a wait_template which checks if currently a motion automation is running in the kitchen. I could have also used the wait check on motion sensor directly, but I wanted to be able to use timeouts in my automation, which can be longer than the actual motion detection.

The important snippet is this one, which checks if no automation is currently running:

{{ is_state_attr('automation.bewegungsmelder_kuche', 'current', 0) }}

And this is the whole part I have added to my sunset automation (and also for the sleep automation similarly) for every room, which has a motion activated light:

sequence:
  - wait_template: "{{ is_state_attr('automation.bewegungsmelder_kuche', 'current', 0) }}"
    continue_on_timeout: true
  - action: adaptive_lighting.set_manual_control
    metadata: {}
    data:
      manual_control: true
      lights:
        - light.kueche
  - action: light.turn_on
    metadata: {}
    data:
      brightness_pct: 1
      kelvin: 2000
    target:
      entity_id: light.kueche
enabled: true

It simply waits until the motion sensor automation is done, then turns on the manual_control flag in Adaptive Lightning, so it does not adjust the light automatically, as it should stay at 1%, and finally turns on the light with 1% brightness. The only drawback is, that there is a millisecond where the light is turned off by the motion automation and until this wait_template fires and turns the light back on to 1% brightness. But as in this case no one should be in the room anymore, I can live with that.

And this is my motion sensor automation for the kitchen:

alias: Bewegungsmelder Küche
description: ""
mode: single
triggers:
  - entity_id:
      - binary_sensor.0xb4e3f9fffeb689d4_occupancy
    to: "on"
    trigger: state
conditions: []
actions:
  - data:
      scene_id: zustand_kueche_alt
      snapshot_entities:
        - light.kueche
    action: scene.create
  - action: adaptive_lighting.set_manual_control
    metadata: {}
    data:
      manual_control: false
      lights:
        - light.kueche
  - target:
      entity_id:
        - light.kueche
    data:
      transition: 5
    action: light.turn_on
    enabled: true
  - wait_for_trigger:
      - entity_id:
          - binary_sensor.0xb4e3f9fffeb689d4_occupancy
        to: "off"
        for:
          hours: 0
          minutes: 0
          seconds: 10
        trigger: state
  - target:
      entity_id: scene.zustand_kueche_alt
    data:
      transition: 5
    action: scene.turn_on

Before turning on the kitchen light, it stores the current state in a scene, then always disables the manual_control flag (in case the sunset automation turned it on), so that when in the next step the light is turned on, it automatically adjusts the brightness to the right value. When no motion is detected for 10 seconds, it restores the previous scene.

[ABAP] Read attendance/absence quotas

DATA pernr TYPE pernr_d VALUE 1.

DATA(time_accounts) = cl_hcmfab_att_abs_bl_apis=>get_instance( )->read_time_accounts( iv_pernr = pernr
                                                                                      iv_begda = sy-datum
                                                                                      iv_endda = sy-datum ). "iv_endda is never used!

cl_demo_output=>display( time_accounts ).

Although there is an obligatory iv_endda parameter, it is never used inside of method read_time_accounts. Instead, there is some logic which checks for a T77S0 Parameter, and it will use either highdate or begda as endda value.

IMO, it would have made sense to mark iv_endda as optional, so it would be downward compatible and the parameter could be omitted on newer releases. Now it is a bit misleading.

[ABAP] REDUCE as an alternative to line_exists for the use of other comparison operators such as >, <, >=, <=, CS, CN

By using line_exists you can check if a line exists or not exists, but it is not possible to use other comparison operators. A workaround can be REDUCE in that case.

In the following snippet, we want to check if there is a flight that costs more than $1000,

SELECT * FROM sflight INTO TABLE @DATA(flights).

* Check if flight with price > 1000 exist
IF REDUCE abap_bool( INIT price_gt_1000 = abap_false
                     FOR  line IN flights WHERE ( price > 1000 )
                     NEXT price_gt_1000 = abap_true ) EQ abap_true.
  " flight with price > 1000 exists
ENDIF.

[Blog] Umzug von Strato zu Netcup

Mein letzter Blog-Umzug war im Juli 2020 von DigitalOcean zu Strato (siehe hier). Nun war es mal wieder Zeit.

Der Blog und alle meine weiteren Docker Container sind nun endlich nach über 4 Jahren von einem Strato VPS zu einem Netcup VPS auf ARM Basis umgezogen. Obwohl ich schon viele schlechte Erfahrungen mit Strato gemacht hatte, habe ich trotzdem damals den VPS bei Strato abgeschlossen, da dieser mit 1TB SSD Speichern zu der Zeit konkurrenzlos viel Speicher für 15 € im Monat bot. Das war für den Betrieb einer Nextcloud für mich entscheidend. Aber meine schlechten Erfahrungen setzten sich fort. Ich kann gar nicht aufzählen, wie viele Performanceprobleme und Ausfälle es gab. Manchmal nur ein paar Minuten oder Stunden. Manchmal auch einfach mehrere Tage. Anfangs habe ich noch Tickets aufgemacht, aber irgendwann hatte ich darauf auch keine Lust mehr. Warum ich trotzdem so lange bei Strato war? Wohl einfach aus faulheit… Aber als Strato diesem Sommer auch noch den Preis für den V40-16 von 15€ auf 17,70€ angehoben hat, vermutlich primär um die Altkunden loszuwerden bzw. diese zu drängen von der Virtuozzo auf die neue KVM Virtualisierungsplattform zu wechseln, war es endgültig genug. Hab mich einige Wochen nach VPS Anbietern umgeschaut, die einen VPS mit viel Speicher anbieten und wurde Ende Oktober bei Netcup fündig, als es eine Angebotsaktion gab, bei der für bestimmte VPS der Speicher verdoppelt wurde. Die Aktionsproduktseite gibt es nicht mehr, aber es handelt sich quasi um dieses Produkt mit doppeltem Speicher:
https://www.netcup.com/de/server/arm-server/vps-3000-arm-g11-mnz#vps-3000-arm-g11-vie
In meinem Fall also: VPS 3000 ARM G11 SE VIE SPS24 mit 1536 GB NVMe Speicher für 16,95 €

Das ganze auch noch monatlich kündbar und nicht mehr wie bei Strato jährlich. Für quasi das gleiche Geld gab es hier also erheblich mehr Leistung. Einziger “Knackpunkt”, der neue Server bedeutete auch ein Wechsel der CPU Architektur von x86 auf ARM. Ich habe daher sicherheitshalber erstmal für meine aktuell genutzten Anwendungen

  • WordPress
  • Nginx Proxy Manager
  • Nextcloud
  • OnlyOffice
  • Collabora
  • Vaultwarden
  • SMTP
  • Portainer
  • TeamSpeak3

geprüft, ob auch Docker Images für ARM bereitgestellt werden. Lediglich bei zwei Anwendungen war das nicht der Fall. Der Teamspeak3 Server, sowie der SMTP Container. Nach kurze Recherche habe ich aber direkt Ersatz gefunden (TS3 & SMTP). Wirklich neu aufsetzen musste ich daher lediglich den TeamSpeak3 Server, aber der Aufwand hielt sich in Grenzen.

Die ganze Migration verlief erheblich einfacher als erwartet. Mit dem folgenden Befehl habe ich jeden Ordner meiner Docker Anwendungen (praktischerweise hab ich damals alles ohne Docker Volumes aufgesetzt, alle Daten liegen also direkt in dem gleichen Ordner wie die docker-compose.yml) nacheinander auf den neuen Server übertragen. Bis auf die Nextcloud, eine Sache von wenigen Minuten.

sudo rsync -azP /opt/containers/nextcloud/ root@ip-address:/opt/containers/nextcloud

Danach noch die DNS Einträge angepasst und gewartet, bis diese sich aktualisieren. Bei der Nextcloud und Vaultwarden gingen komischerweise die User:Group Zuordnungen zum Teil nicht sauber rüber. Da musste ich daher noch kurz etwas nacharbeiten. Im Nginx Proxy Manager habe ich noch alle Zertifikate einmal aktualisiert und nach wenigen Stunden waren dann alle Container wieder über alte URL erreichbar.

Hätte ich geahnt, dass der Serverumzug so reibungslos verläuft, hätte ich das auf jeden Fall schon vor Jahren gemacht. Mit Netcup bin ich vollkommen zufrieden und mein Uptime Kuma konnte bisher kein einziges Erreichbarkeitsproblem des VPS feststellen, im Gegensatz zum Strato VPS, der immer mal wieder für einige Minuten nicht auf den Ping Test reagiert. Ich kann daher nur nochmals von den Strato VPS Produkten abraten.