CarbCam – Kohlenhydrate direkt in den AAPS 3.4.x.x und iAPS Bolus-Wizard übernehmen

Kohlenhydrate aus CarbCam direkt in den AAPS 3.4.x.x/aaps4/iAPS Bolus-Wizard übernehmen

Stand: AAPS 3.4.2.2 branch. AAPS 4 (DEV), iAPS


Worum geht’s

Wer Kohlenhydrate per Foto schätzt (CarbCam) oder aus einer Lebensmittel-Datenbank zieht, muss den Wert bisher abtippen oder über Nightscout-Treatments umweglos hineinpumpen. Beides ist umständlich. Der hier beschriebene Patch fügt AAPS einen kleinen, definierten Eingang hinzu:

Eine andere App wie z.b. CarbCam sendet einen Android Intent an AAPS mit Aktion info.nightscout.androidaps.action.OPEN_BOLUS_WIZARD und einem Carbs-Wert. AAPS öffnet daraufhin denselben Bolus-Wizard wie bei manueller Eingabe, mit dem Carbs-Feld bereits ausgefüllt. Der Benutzer prüft, drückt OK, sieht den Standard-AAPS-Bestätigungsdialog und gibt den Bolus frei. Es gibt keine Möglichkeit, Insulin ohne Bestätigung abzugeben.

CarbCam (de.be10.carbcam)
    │
    │  Intent: OPEN_BOLUS_WIZARD
    │  extras: carbs=42, notes="Pizza Margherita"
    ▼
WizardLaunchActivity (exported, Caller-Whitelist)
    │
    │  prüft: callingPackage, Range 1–80
    │  leitet weiter: open_wizard_carbs, open_wizard_notes
    ▼
MainActivity (singleTask)
    │
    │  liest Extras, zeigt WizardDialog
    ▼
WizardDialog (Standard-Bolus-Wizard, vorbefüllt)
    │
    │  Benutzer bestätigt
    ▼
AAPS-Standard-Bestätigungsdialog → Bolus

Sicherheits-Design

Vier Schichten, alle aktiv:

  1. Whitelist — Nur explizit erlaubte Caller-Packages (z.B. de.be10.carbcam) können den Wizard öffnen. Andere Apps werden vom Launcher kommentarlos abgewiesen.
  2. Range-Check — Carbs außerhalb 1–80 g werden verworfen. Wer mehr braucht, hebt den Wert anschließend im Wizard manuell an.
  3. Kein automatischer Bolus — Der Patch öffnet nur den Wizard. Der Benutzer durchläuft denselben Bestätigungsflow wie bei manueller Eingabe.
  4. Source-Anzeige — Der source-Parameter erscheint im Wizard-Notes-Feld („via CarbCam“), wird aber nicht als Vertrauensbeweis gewertet.

Voraussetzungen

  • AAPS 3.4.2.2 branch, lokal oder GitHub geklont und mit Android Studio oder BrowserBuild baubar
  • Kotlin/Android Grundkenntnisse (vi reicht zum Editieren)

WICHTIG! Falls du eigene Anpassungen in AAPS gemacht hast, können die Zeilennummer anders sein.

 

Patchfiles für iaps (ungetestet), AndroidAPS 3.4.2.2 und AAPS DEV 4:

https://github.com/zehnBE/aaps3.4.2.2-carbcam-patches/blob/main/README.md

 

 

Patch — 5 Änderungen

1. Neue Datei anlegen

Datei: app/src/main/kotlin/app/aaps/activities/WizardLaunchActivity.kt

mit folgendem Inhalt:

package app.aaps.activities

import android.content.Intent
import android.os.Bundle
import app.aaps.MainActivity
import app.aaps.plugins.configuration.activities.DaggerAppCompatActivityWithResult

class WizardLaunchActivity : DaggerAppCompatActivityWithResult() {

    companion object {
        const val EXTRA_CARBS = "carbs"
        const val EXTRA_NOTES = "notes"
        const val EXTRA_SOURCE = "source"

        // Whitelist: nur CarbCam darf den Wizard externe öffnen
        private val ALLOWED_CALLERS = setOf(
            "de.be10.carbcam",
            "de.be10.carbcam.debug"
        )
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val caller = callingPackage ?: referrer?.host
        if (caller !in ALLOWED_CALLERS) {
            finish()
            return
        }

        val carbs = intent.getIntExtra(EXTRA_CARBS, 0)
        val notes = intent.getStringExtra(EXTRA_NOTES) ?: ""

        if (carbs <= 0 || carbs > 80) {
            finish()
            return
        }

        startActivity(Intent(this, MainActivity::class.java).apply {
            addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT or Intent.FLAG_ACTIVITY_SINGLE_TOP)
            putExtra("open_wizard_carbs", carbs)
            putExtra("open_wizard_notes", notes)
        })
        finish()
    }
}

 

 

2. AndroidManifest.xml ergänzen

Datei: app/src/main/AndroidManifest.xml

Innerhalb des <application>-Blocks, neben den anderen Activities:

<activity
    android:name="app.aaps.activities.WizardLaunchActivity"
    android:exported="true"
    android:excludeFromRecents="true"
    android:launchMode="singleInstance"
    android:theme="@style/AppTheme.NoActionBar">
    <intent-filter>
        <action android:name="info.nightscout.androidaps.action.OPEN_BOLUS_WIZARD" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>

exported="true" ist nötig, weil eine andere App die Activity ansprechen können muss. excludeFromRecents und singleInstance sorgen dafür, dass die Launcher-Activity im Recents-Switcher nicht auftaucht und keine eigene Task-History anlegt.

 

3. Dagger-Registrierung

Datei: app/src/main/kotlin/app/aaps/di/ActivitiesModule.kt

Import ergänzen:

import app.aaps.activities.WizardLaunchActivity

Innerhalb der ActivitiesModule-Klasse eine Zeile dazu:

@ContributesAndroidInjector
abstract fun contributesWizardLaunchActivity(): WizardLaunchActivity

Ohne diesen Eintrag bekommt die Activity beim Start IllegalArgumentException: No injector factory bound for Class.

 

4. MainActivity erweitern

Datei: app/src/main/kotlin/app/aaps/MainActivity.kt

Am Ende von onCreate() einfügen:

handleExternalWizardIntent(intent)

Neue Override und private Methode in derselben Klasse ergänzen:

override fun onNewIntent(intent: Intent) {
    super.onNewIntent(intent)
    setIntent(intent)
    handleExternalWizardIntent(intent)
}

private fun handleExternalWizardIntent(intent: Intent?) {
    val carbs = intent?.getIntExtra("open_wizard_carbs", 0) ?: 0
    if (carbs <= 0) return

    val notes = intent.getStringExtra("open_wizard_notes") ?: ""

    // Extras "verbrauchen", damit sie beim nächsten Lifecycle nicht erneut feuern
    intent.removeExtra("open_wizard_carbs")
    intent.removeExtra("open_wizard_notes")

    val wizard = app.aaps.ui.dialogs.WizardDialog()
    wizard.arguments = Bundle().apply {
        putDouble("carbs_input", carbs.toDouble())
        putString("notes_input", notes)
    }
    wizard.show(supportFragmentManager, "WizardDialog")
}

Den vollqualifizierten Pfad app.aaps.ui.dialogs.WizardDialog nicht durch app.aaps.plugins.main.dialogs.WizardDialog ersetzen — der WizardDialog im aktuellen dev-Branch liegt im Modul :ui, nicht in :plugins:main.

 

5. WizardDialog argumentfähig machen (optional)

Datei: ui/src/main/kotlin/app/aaps/ui/dialogs/WizardDialog.kt

Wenn der Wizard die Carbs aus den arguments lesen soll (sonst öffnet er sich leer), in onViewCreated den Aufruf binding.carbsInput.setParams(...) ergänzen:

val initialCarbs = savedInstanceState?.getDouble("carbs_input")
    ?: arguments?.getDouble("carbs_input", 0.0)?.takeIf { it > 0.0 }
    ?: 0.0

binding.carbsInput.setParams(
    initialCarbs,
    0.0,
    maxCarbs.toDouble(),
    1.0,
    DecimalFormat("0"),
    false,
    binding.okcancel.ok,
    textWatcher
)

 

 

Alternativ per patch file:

Eine PatchFile um aaps3.4.2.2, AndroidAPS4 (dev) und Iphone iAPS für CarbCam kompatible zu machen gibt es hier:

https://github.com/zehnBE/aaps3.4.2.2-carbcam-patches/

Anzuwenden mit:

git am pfad/zur/datei\0001-xxxxxxxxxx.patch

 

Bauen

Wie sonst auch, die App AndroidAPS bauen und auf dem Handy aktualisieren.
Dann kannst du per CarbCam die ermittelten Kohlenhydrate an AAPS an den Boluzwizard senden lassen, spritzen und danach in CarbCam die Daten speichern.

Den AAPS-Package-Namen an die jeweilige Variante anpassen — Stock-info.nightscout.androidaps, .full, .pumpcontrol oder der individuelle Build mit eigener applicationId.

 

 

[UPDATE]

Im Repro sind auch die Patchfiles für iPhone Loop, iAPS (da übernimmt es auch fett, eiweiss usw.), trio….:

 

aaps3.4.2.2-carbcam-patches

To Patch aaps3.4.2.2 that it allowed external carbs directly in BolusWizard from CarbCam: https://CarbCam.app

Details: https://ns.10be.de/blog/2026/06/01/carbcam-kohlenhydrate-direkt-in-den-aaps-bolus-wizard-uebernehmen

iphone iAPS Patches:

To Patch iAPS that it allowed external carbs directly in BolusWizard from CarbCam: https://github.com/zehnBE/aaps3.4.2.2-carbcam-patches/blob/main/0001-iaps-carbcam-integration.patch

iphone Loop Patches:

To Patch iphone Loop to allow carbs directly from CarbCam.app: https://github.com/zehnBE/aaps3.4.2.2-carbcam-patches/blob/main/0001-loop-carbcam-integration.patch

iphone trio Patches:

To Patch trio that it allowed eternal carbs directly into Boluswizard from CarbCam.app: https://github.com/zehnBE/aaps3.4.2.2-carbcam-patches/blob/main/0001-trio-carbcam-integration.patch

AAPS 4 (DEV) Stand 7734facd Milos Kozak m.kozak@sysop.cz on 01.06.2026 at 23:02

https://github.com/zehnBE/aaps3.4.2.2-carbcam-patches/blob/main/0001-aaps-v4-carbcam-integration.patch

 

Artikelserie: Closed Loop; 3. Wie ermittle ich die benötigten Faktoren?

3. Wie ermittel ich die benötigten Faktoren?

Also als erstes müssen wir erst mal einige Zeit lang, zu jeder Tageszeit verifizieren, das die #Basalrate richtig ist.

Wie man einen richtigen Basalraten-Test/Auslasversuch macht, solltest du bei diesem Punkt bereits wissen. Wenn nicht, schau mal hier nach:

https://mysugr.com/de/tipps-fur-einen-erfolgreichen-basalratentest/

http://www.mein-diabetes-blog.com/wie-mache-ich-einen-basalratentest-pimp-your-basal/

 

Wenn die Basalrate stimmt, dann können wir die anderen Faktoren ermitteln.

Das wäre einmal der DIA, dann ISF (KF), dann die IC (KHF), dann hat man es auch schon 🙂

 

Wie immer gilt, wenn man zu niedrig kommt oder sonst etwas nicht passt: ABBRECHEN! Und dann am nächsten Tag erneut versuchen.

Den ISF (Insulin Sensitivity Factor) kann man mit einem höheren Start-Blutzucker testen.

Ich lasse dabei z.B. den BZ auf 180-200 mg/dl ansteigen. Da sollte das Basal aber schon wieder 1 Stunde laufen, das er stabil bei 180-200 bleibt.

Dann spritze ich 2 Einheiten. Hier ist es wichtig, das man sich gegen ein Unterzucker gewaptnet hat, falls man nicht weiß wie viel eine Einheit senkt. Man sollte lieber mit 50 mg/dl rechnen. Bei Kindern, kann 1 Einheit auch locker 300 mg/dl oder noch mehr senken!

1 Einheit senkt bei mir bei Humalog den BZ um 40-50mg/dl. Bei Fiasp jetzt nur noch 25-35 mg/dl.

Dabei kann man auch schön sehen, ab wann der Zucker dann langsam und ab wann er stark fällt. Diesen Abstand kann man dann nutzen um zu der jeweiligen Zeit einen entsprechenden Spritzt-Ess-Abstand (SEA) einzuplanen.

Je nach Insulin, ist die Wirkdauer ca. 4-6 Stunden. Wenn also nach 3-5 Stunden der Blutzucker nicht mehr fällt und dann über eine Stunde stabil ist, wissen wir wie weit uns die 2 Einheiten runter bringen. Das geteilt durch 2, dann hat man den ISF.

 

Beispiel:

 

1. BZ steigt. 1,4ie zum Abfangen gegeben.

2. BZ wurde abgefangen. 4ie gegeben um den ISF zu testen.

3. BZ fängt sich. Ist also von 230 mg/dl auf 80 mg/dl gesunken:

230 mg/dl – 80 mg/dl = 150 mg/dl

150 mg/dl / 4ie = 37,5 mg/dl pro 1ie

4. DIA ist wahrscheinlich vorbei.

 

Da hier der BZ davor viel zu stark angestiegen ist und ich noch 1,4ie davor gegeben hatte, die man mit ein berechnen muss, kann das hier nicht als gutes Beispiel genommen werden. Aber man kann sehen, wie der Test ungefähr abläuft.

Natürlich hätte ich bereits ohne Insulin bei 230 mg/dl angekommen müssen und hätte dann nur die 4ie gegeben. Dann wäre es aussagekräftiger. Dazu hätte auch AAPS nicht die BR noch anpassen dürfen 🙁

 

Nach dem nun der BZ nicht mehr weiter sinkt und über eine Stunde stabil war, weiß man, auch grob wie lange der DIA ist. Hierbei gilt aber, das auch wenn man keine Änderung mehr sieht, das Insulin trotzdem noch vorhanden sein kann:

http://www.diabettech.com/insulin/why-we-are-regularly-wrong-in-the-duration-of-insulin-action-dia-times-we-use-and-why-it-matters/

http://www.ema.europa.eu/docs/en_GB/document_library/EPAR_-_Product_Information/human/004046/WC500220890.pdf

 

 

Nun zum dritten Faktor, dem IC, bzw. KohlenhydrateFaktor oder Essensbolus-Faktor oder oder oder….

Am besten isst man eine genaue BE/KE (also wieder ein BR-Test) und schaut wie weit diese mich bis zu 3 Stunden nach dem essen nach oben bringt.

Wenn der BZ von 100 auf 170 gestiegen ist, so bringen 10KHg eine Steigung von 70mg/dl.

Eine Einheit senkt bei mir bei Fiasp den BZ um 30-37 mg/dl. Um die 70 mg/dl also abzufangen, brauche ich 2ie.

1 BE/KE = +70 mg/dl

1 IE = -37 mg/dl

70 mg/dl – 37 mg/dl = 1,89ie pro BE/KE/10gkh

Somit habe ich meinen IC/KHF: 5,2KH pro IE

Oder anders herum KHF/IC: 1,89ie pro BE/KE

 

Und diese Schritte muss man dann für jede Zeit entsprechend wiederholen.

 

Es gibt bestimmt auch mathematische Formeln dafür. Diese sind mir aber dann nicht bekannt 🙂 und so ermittele ICH die Werte. Wenn jemand andere Techniken hat, bitte gerne kommentieren!

 

Vorheriger Artikel:  2. Was braucht man (Hardware/Software/Faktoren)?          |             Übersicht Artikelserie          |             Nächster Artikel: 4. Installation/Nutzung von Nightscout.

Häufig benutzte Abkürzungen in den sozialen Medien (FB, Twitter usw.) im Bezug auf Diabetes

Hier einmal häufige Abkürzungen, die in Foren, Twitter, Blogs, Facebook usw. vorkommen und wenn sie im Zusammenhang mit Diabetes vorkommen.

Falls welche fehlen, gerne rein kommentieren 🙂

 

Abkürzung Ausgeschrieben
KK KrankenKasse
KV Kassenärztliche Vereinigungen
BZ/BZW BlutZucker/BlutZuckerWert
GZ GewebeZucker
BG BloodGlucose
CGM Continues Glugose Monitoring
FGM Flash Glucose Monitoring
FSL FreeStyle Libre
KF KorrekturFaktor
KHF KohlenhydrateFaktor
CR CarbRatio (entspricht KHF)
COB Carbs On Board (noch wirkende Kohlenhydrate)
ISF (auch KF) Insulin Sensitivity Factor
DIA Duration of Insulin Activity http://www.diabettech.com/insulin/why-we-are-regularly-wrong-in-the-duration-of-insulin-action-dia-times-we-use-and-why-it-matters/
IAT Insulin Action Time
IOB Insulin On Board (noch wirkendes Insulin)
BE Broteinheit (12g KH)
KE KohlenhydratEinheit (10g KH)
KH Kohlenhydrate
FPE FettProteinEinheit
IE InsulinEinheit
U Unit (Einheit)
SAGE SensorAge (SensorAlter)
IAGE InsulinAge (InsulinAlter)
CAGE CatheterAge (KatheterAlter)
SEA Spritz-Ess-Abstand (dea)
DEA Drück-Ess-Abstand (sea)
LO Low (zu niedrig, meist unter 40 mg/dl)
HI High (zu hoch, meist über 400 oder 500 mg/dl)
UZ UnterZucker (< 50 oder < 70 mg/dl), einfach zu niedrig
ÜZ ÜberZucker (> 200 oder 250 mg/dl), einfach zu hoch
T1D Typ 1 Diabetes
DT1 Diabetes Typ 1
DIA DIA (siehe weiter oben) oder Diabetes
BR BasalRate
Keto Ketoazidose
MDK Medizinischer Dienst der Krankenkassen
KH KH (siehe weiter oben) oder KrankenHaus
NS NightScout
 RTW RettungsWagen
 TIR  Time In Range (wie lange man im Zielbereich war/ist)
LOOP Steht für „Closed Loop/Hybrid Closed Loop“, bedeutet geschlossener Kreislauf.
Open Loop Wie closed Loop, nur das man die Vorschläge manuell in er Pumpe eingeben/umsetzten muss.