{"id":842,"date":"2026-06-01T16:48:15","date_gmt":"2026-06-01T14:48:15","guid":{"rendered":"https:\/\/zehn.be\/?p=842"},"modified":"2026-06-07T21:43:26","modified_gmt":"2026-06-07T19:43:26","slug":"carbcam-kohlenhydrate-direkt-in-den-aaps-bolus-wizard-uebernehmen","status":"publish","type":"post","link":"https:\/\/zehn.be\/2026\/06\/01\/carbcam-kohlenhydrate-direkt-in-den-aaps-bolus-wizard-uebernehmen\/","title":{"rendered":"CarbCam &#8211; Kohlenhydrate direkt in den AAPS 3.4.x.x und iAPS Bolus-Wizard \u00fcbernehmen"},"content":{"rendered":"<h1>Kohlenhydrate aus <a href=\"https:\/\/CarbCam.app\" target=\"_blank\" rel=\"noopener\">CarbCam<\/a> direkt in den AAPS 3.4.x.x\/aaps4\/iAPS Bolus-Wizard \u00fcbernehmen<\/h1>\n<p><strong>Stand:<\/strong> AAPS 3.4.2.2 branch. AAPS 4 (DEV), iAPS<\/p>\n<hr \/>\n<h2>Worum geht&#8217;s<\/h2>\n<p>Wer Kohlenhydrate per Foto sch\u00e4tzt (<a href=\"https:\/\/CarbCam.APP\" target=\"_blank\" rel=\"noopener\">CarbCam<\/a>) oder aus einer Lebensmittel-Datenbank zieht, muss den Wert bisher abtippen oder \u00fcber Nightscout-Treatments umweglos hineinpumpen. Beides ist umst\u00e4ndlich. Der hier beschriebene Patch f\u00fcgt AAPS einen kleinen, definierten Eingang hinzu:<\/p>\n<p>Eine andere App wie z.b. CarbCam sendet einen <strong>Android Intent<\/strong> an AAPS mit Aktion <code>info.nightscout.androidaps.action.OPEN_BOLUS_WIZARD<\/code> und einem Carbs-Wert. AAPS \u00f6ffnet daraufhin <strong>denselben Bolus-Wizard wie bei manueller Eingabe<\/strong>, mit dem Carbs-Feld bereits ausgef\u00fcllt. Der Benutzer pr\u00fcft, dr\u00fcckt OK, sieht den Standard-AAPS-Best\u00e4tigungsdialog und gibt den Bolus frei. Es gibt <strong>keine<\/strong> M\u00f6glichkeit, Insulin ohne Best\u00e4tigung abzugeben.<\/p>\n<pre class=\"wp-block-code\">CarbCam (de.be10.carbcam)\r\n    \u2502\r\n    \u2502  Intent: OPEN_BOLUS_WIZARD\r\n    \u2502  extras: carbs=42, notes=\"Pizza Margherita\"\r\n    \u25bc\r\nWizardLaunchActivity (exported, Caller-Whitelist)\r\n    \u2502\r\n    \u2502  pr\u00fcft: callingPackage, Range 1\u201380\r\n    \u2502  leitet weiter: open_wizard_carbs, open_wizard_notes\r\n    \u25bc\r\nMainActivity (singleTask)\r\n    \u2502\r\n    \u2502  liest Extras, zeigt WizardDialog\r\n    \u25bc\r\nWizardDialog (Standard-Bolus-Wizard, vorbef\u00fcllt)\r\n    \u2502\r\n    \u2502  Benutzer best\u00e4tigt\r\n    \u25bc\r\nAAPS-Standard-Best\u00e4tigungsdialog \u2192 Bolus<\/pre>\n<h2>Sicherheits-Design<\/h2>\n<p>Vier Schichten, alle aktiv:<\/p>\n<ol>\n<li><strong>Whitelist<\/strong> \u2014 Nur explizit erlaubte Caller-Packages (z.B. <code>de.be10.carbcam<\/code>) k\u00f6nnen den Wizard \u00f6ffnen. Andere Apps werden vom Launcher kommentarlos abgewiesen.<\/li>\n<li><strong>Range-Check<\/strong> \u2014 Carbs au\u00dferhalb 1\u201380 g werden verworfen. Wer mehr braucht, hebt den Wert anschlie\u00dfend im Wizard manuell an.<\/li>\n<li><strong>Kein automatischer Bolus<\/strong> \u2014 Der Patch \u00f6ffnet nur den Wizard. Der Benutzer durchl\u00e4uft denselben Best\u00e4tigungsflow wie bei manueller Eingabe.<\/li>\n<li><strong>Source-Anzeige<\/strong> \u2014 Der <code>source<\/code>-Parameter erscheint im Wizard-Notes-Feld (\u201evia CarbCam&#8220;), wird aber nicht als Vertrauensbeweis gewertet.<\/li>\n<\/ol>\n<h2>Voraussetzungen<\/h2>\n<ul>\n<li>AAPS 3.4.2.2 branch, lokal oder GitHub geklont und mit Android Studio oder BrowserBuild baubar<\/li>\n<li>Kotlin\/Android Grundkenntnisse (vi reicht zum Editieren)<\/li>\n<\/ul>\n<h2><\/h2>\n<h1>WICHTIG! Falls du eigene Anpassungen in AAPS gemacht hast, k\u00f6nnen die Zeilennummer anders sein.<\/h1>\n<p>&nbsp;<\/p>\n<p>Patchfiles f\u00fcr iaps (ungetestet), AndroidAPS 3.4.2.2 und AAPS DEV 4:<\/p>\n<p><a href=\"https:\/\/github.com\/zehnBE\/aaps3.4.2.2-carbcam-patches\/blob\/main\/README.md\" target=\"_blank\" rel=\"noopener\">https:\/\/github.com\/zehnBE\/aaps3.4.2.2-carbcam-patches\/blob\/main\/README.md<\/a><\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<h2>Patch \u2014 5 \u00c4nderungen<\/h2>\n<h3>1. Neue Datei anlegen<\/h3>\n<p>Datei: <code>app\/src\/main\/kotlin\/app\/aaps\/activities\/WizardLaunchActivity.kt<\/code><\/p>\n<p>mit folgendem Inhalt:<\/p>\n<pre class=\"wp-block-code\">package app.aaps.activities\r\n\r\nimport android.content.Intent\r\nimport android.os.Bundle\r\nimport app.aaps.MainActivity\r\nimport app.aaps.plugins.configuration.activities.DaggerAppCompatActivityWithResult\r\n\r\nclass WizardLaunchActivity : DaggerAppCompatActivityWithResult() {\r\n\r\n    companion object {\r\n        const val EXTRA_CARBS = \"carbs\"\r\n        const val EXTRA_NOTES = \"notes\"\r\n        const val EXTRA_SOURCE = \"source\"\r\n\r\n        \/\/ Whitelist: nur CarbCam darf den Wizard externe \u00f6ffnen\r\n        private val ALLOWED_CALLERS = setOf(\r\n            \"de.be10.carbcam\",\r\n            \"de.be10.carbcam.debug\"\r\n        )\r\n    }\r\n\r\n    override fun onCreate(savedInstanceState: Bundle?) {\r\n        super.onCreate(savedInstanceState)\r\n\r\n        val caller = callingPackage ?: referrer?.host\r\n        if (caller !in ALLOWED_CALLERS) {\r\n            finish()\r\n            return\r\n        }\r\n\r\n        val carbs = intent.getIntExtra(EXTRA_CARBS, 0)\r\n        val notes = intent.getStringExtra(EXTRA_NOTES) ?: \"\"\r\n\r\n        if (carbs &lt;= 0 || carbs &gt; 80) {\r\n            finish()\r\n            return\r\n        }\r\n\r\n        startActivity(Intent(this, MainActivity::class.java).apply {\r\n            addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT or Intent.FLAG_ACTIVITY_SINGLE_TOP)\r\n            putExtra(\"open_wizard_carbs\", carbs)\r\n            putExtra(\"open_wizard_notes\", notes)\r\n        })\r\n        finish()\r\n    }\r\n}<\/pre>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<h3>2. AndroidManifest.xml erg\u00e4nzen<\/h3>\n<p>Datei: <code>app\/src\/main\/AndroidManifest.xml<\/code><\/p>\n<p>Innerhalb des <code>&lt;application&gt;<\/code>-Blocks, neben den anderen Activities:<\/p>\n<pre class=\"wp-block-code\">&lt;activity\r\n    android:name=\"app.aaps.activities.WizardLaunchActivity\"\r\n    android:exported=\"true\"\r\n    android:excludeFromRecents=\"true\"\r\n    android:launchMode=\"singleInstance\"\r\n    android:theme=\"@style\/AppTheme.NoActionBar\"&gt;\r\n    &lt;intent-filter&gt;\r\n        &lt;action android:name=\"info.nightscout.androidaps.action.OPEN_BOLUS_WIZARD\" \/&gt;\r\n        &lt;category android:name=\"android.intent.category.DEFAULT\" \/&gt;\r\n    &lt;\/intent-filter&gt;\r\n&lt;\/activity&gt;<\/pre>\n<p><code>exported=\"true\"<\/code> ist n\u00f6tig, weil eine andere App die Activity ansprechen k\u00f6nnen muss. <code>excludeFromRecents<\/code> und <code>singleInstance<\/code> sorgen daf\u00fcr, dass die Launcher-Activity im Recents-Switcher nicht auftaucht und keine eigene Task-History anlegt.<\/p>\n<p>&nbsp;<\/p>\n<h3>3. Dagger-Registrierung<\/h3>\n<p>Datei: <code>app\/src\/main\/kotlin\/app\/aaps\/di\/ActivitiesModule.kt<\/code><\/p>\n<p>Import erg\u00e4nzen:<\/p>\n<pre class=\"wp-block-code\">import app.aaps.activities.WizardLaunchActivity\r\n<\/pre>\n<p>Innerhalb der <code>ActivitiesModule<\/code>-Klasse eine Zeile dazu:<\/p>\n<pre class=\"wp-block-code\">@ContributesAndroidInjector\r\nabstract fun contributesWizardLaunchActivity(): WizardLaunchActivity<\/pre>\n<p>Ohne diesen Eintrag bekommt die Activity beim Start <code>IllegalArgumentException: No injector factory bound for Class<\/code>.<\/p>\n<p>&nbsp;<\/p>\n<h3>4. MainActivity erweitern<\/h3>\n<p>Datei: <code>app\/src\/main\/kotlin\/app\/aaps\/MainActivity.kt<\/code><\/p>\n<p>Am Ende von <code>onCreate()<\/code> einf\u00fcgen:<\/p>\n<pre class=\"wp-block-code\"><code class=\"language-kotlin\">handleExternalWizardIntent(intent)<\/code><\/pre>\n<p>Neue Override und private Methode in derselben Klasse erg\u00e4nzen:<\/p>\n<pre class=\"wp-block-code\">override fun onNewIntent(intent: Intent) {\r\n    super.onNewIntent(intent)\r\n    setIntent(intent)\r\n    handleExternalWizardIntent(intent)\r\n}\r\n\r\nprivate fun handleExternalWizardIntent(intent: Intent?) {\r\n    val carbs = intent?.getIntExtra(\"open_wizard_carbs\", 0) ?: 0\r\n    if (carbs &lt;= 0) return\r\n\r\n    val notes = intent.getStringExtra(\"open_wizard_notes\") ?: \"\"\r\n\r\n    \/\/ Extras \"verbrauchen\", damit sie beim n\u00e4chsten Lifecycle nicht erneut feuern\r\n    intent.removeExtra(\"open_wizard_carbs\")\r\n    intent.removeExtra(\"open_wizard_notes\")\r\n\r\n    val wizard = app.aaps.ui.dialogs.WizardDialog()\r\n    wizard.arguments = Bundle().apply {\r\n        putDouble(\"carbs_input\", carbs.toDouble())\r\n        putString(\"notes_input\", notes)\r\n    }\r\n    wizard.show(supportFragmentManager, \"WizardDialog\")\r\n}<\/pre>\n<p>Den vollqualifizierten Pfad <code>app.aaps.ui.dialogs.WizardDialog<\/code> nicht durch <code>app.aaps.plugins.main.dialogs.WizardDialog<\/code> ersetzen \u2014 der WizardDialog im aktuellen dev-Branch liegt im Modul <code>:ui<\/code>, nicht in <code>:plugins:main<\/code>.<\/p>\n<p>&nbsp;<\/p>\n<h3>5. WizardDialog argumentf\u00e4hig machen (optional)<\/h3>\n<p>Datei: <code>ui\/src\/main\/kotlin\/app\/aaps\/ui\/dialogs\/WizardDialog.kt<\/code><\/p>\n<p>Wenn der Wizard die Carbs aus den <code>arguments<\/code> lesen soll (sonst \u00f6ffnet er sich leer), in <code>onViewCreated<\/code> den Aufruf <code>binding.carbsInput.setParams(...)<\/code> erg\u00e4nzen:<\/p>\n<pre class=\"wp-block-code\">val initialCarbs = savedInstanceState?.getDouble(\"carbs_input\")\r\n    ?: arguments?.getDouble(\"carbs_input\", 0.0)?.takeIf { it &gt; 0.0 }\r\n    ?: 0.0\r\n\r\nbinding.carbsInput.setParams(\r\n    initialCarbs,\r\n    0.0,\r\n    maxCarbs.toDouble(),\r\n    1.0,\r\n    DecimalFormat(\"0\"),\r\n    false,\r\n    binding.okcancel.ok,\r\n    textWatcher\r\n)<\/pre>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<h2>Alternativ per patch file:<\/h2>\n<p>Eine PatchFile um aaps3.4.2.2, AndroidAPS4 (dev) und Iphone iAPS f\u00fcr CarbCam kompatible zu machen gibt es hier:<\/p>\n<p><a href=\"https:\/\/github.com\/zehnBE\/aaps3.4.2.2-carbcam-patches\/\" target=\"_blank\" rel=\"noopener\">https:\/\/github.com\/zehnBE\/aaps3.4.2.2-carbcam-patches\/<\/a><\/p>\n<p>Anzuwenden mit:<\/p>\n<p><code>git am pfad\/zur\/datei\\0001-xxxxxxxxxx.patch<\/code><\/p>\n<p>&nbsp;<\/p>\n<h2>Bauen<\/h2>\n<p>Wie sonst auch, die App AndroidAPS bauen und auf dem Handy aktualisieren.<br \/>\nDann kannst du per <a href=\"https:\/\/carbcam.app\" target=\"_blank\" rel=\"noopener\">CarbCam<\/a> die ermittelten Kohlenhydrate an AAPS an den Boluzwizard senden lassen, spritzen und danach in CarbCam die Daten speichern.<\/p>\n<p>Den AAPS-Package-Namen an die jeweilige Variante anpassen \u2014 Stock-<code>info.nightscout.androidaps<\/code>, <code>.full<\/code>, <code>.pumpcontrol<\/code> oder der individuelle Build mit eigener <code>applicationId<\/code>.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>[UPDATE]<\/p>\n<p>Im Repro sind auch die Patchfiles f\u00fcr iPhone Loop, iAPS (da \u00fcbernimmt es auch fett, eiweiss usw.), trio&#8230;.:<\/p>\n<p>&nbsp;<\/p>\n<div class=\"markdown-heading\" dir=\"auto\">\n<h1 class=\"heading-element\" dir=\"auto\" tabindex=\"-1\">aaps3.4.2.2-carbcam-patches<\/h1>\n<p><a id=\"user-content-aaps3422-carbcam-patches\" class=\"anchor\" href=\"https:\/\/github.com\/zehnBE\/aaps3.4.2.2-carbcam-patches\/#aaps3422-carbcam-patches\" aria-label=\"Permalink: aaps3.4.2.2-carbcam-patches\" target=\"_blank\" rel=\"noopener\"><\/a><\/div>\n<p dir=\"auto\">To Patch aaps3.4.2.2 that it allowed external carbs directly in BolusWizard from CarbCam: <a href=\"https:\/\/CarbCam.app\" rel=\"nofollow noopener\" target=\"_blank\">https:\/\/CarbCam.app<\/a><\/p>\n<p dir=\"auto\">Details: <a href=\"https:\/\/zehn.be\/2026\/06\/01\/carbcam-kohlenhydrate-direkt-in-den-aaps-bolus-wizard-uebernehmen\" rel=\"nofollow\">https:\/\/zehn.be\/2026\/06\/01\/carbcam-kohlenhydrate-direkt-in-den-aaps-bolus-wizard-uebernehmen<\/a><\/p>\n<h1 dir=\"auto\"><\/h1>\n<div class=\"markdown-heading\" dir=\"auto\">\n<h1 class=\"heading-element\" dir=\"auto\" tabindex=\"-1\">iphone iAPS Patches:<\/h1>\n<p><a id=\"user-content-iphone-iaps-patches\" class=\"anchor\" href=\"https:\/\/github.com\/zehnBE\/aaps3.4.2.2-carbcam-patches\/#iphone-iaps-patches\" aria-label=\"Permalink: iphone iAPS Patches:\" target=\"_blank\" rel=\"noopener\"><\/a><\/div>\n<p dir=\"auto\">To Patch iAPS that it allowed external carbs directly in BolusWizard from CarbCam: <a href=\"https:\/\/github.com\/zehnBE\/aaps3.4.2.2-carbcam-patches\/blob\/main\/0001-iaps-carbcam-integration.patch\" target=\"_blank\" rel=\"noopener\">https:\/\/github.com\/zehnBE\/aaps3.4.2.2-carbcam-patches\/blob\/main\/0001-iaps-carbcam-integration.patch<\/a><\/p>\n<h1 dir=\"auto\"><\/h1>\n<div class=\"markdown-heading\" dir=\"auto\">\n<h1 class=\"heading-element\" dir=\"auto\" tabindex=\"-1\">iphone Loop Patches:<\/h1>\n<p><a id=\"user-content-iphone-loop-patches\" class=\"anchor\" href=\"https:\/\/github.com\/zehnBE\/aaps3.4.2.2-carbcam-patches\/#iphone-loop-patches\" aria-label=\"Permalink: iphone Loop Patches:\" target=\"_blank\" rel=\"noopener\"><\/a><\/div>\n<p dir=\"auto\">To Patch iphone Loop to allow carbs directly from CarbCam.app: <a href=\"https:\/\/github.com\/zehnBE\/aaps3.4.2.2-carbcam-patches\/blob\/main\/0001-loop-carbcam-integration.patch\" target=\"_blank\" rel=\"noopener\">https:\/\/github.com\/zehnBE\/aaps3.4.2.2-carbcam-patches\/blob\/main\/0001-loop-carbcam-integration.patch<\/a><\/p>\n<h1 dir=\"auto\"><\/h1>\n<div class=\"markdown-heading\" dir=\"auto\">\n<h1 class=\"heading-element\" dir=\"auto\" tabindex=\"-1\">iphone trio Patches:<\/h1>\n<p><a id=\"user-content-iphone-trio-patches\" class=\"anchor\" href=\"https:\/\/github.com\/zehnBE\/aaps3.4.2.2-carbcam-patches\/#iphone-trio-patches\" aria-label=\"Permalink: iphone trio Patches:\" target=\"_blank\" rel=\"noopener\"><\/a><\/div>\n<p dir=\"auto\">To Patch trio that it allowed eternal carbs directly into Boluswizard from CarbCam.app: <a href=\"https:\/\/github.com\/zehnBE\/aaps3.4.2.2-carbcam-patches\/blob\/main\/0001-trio-carbcam-integration.patch\" target=\"_blank\" rel=\"noopener\">https:\/\/github.com\/zehnBE\/aaps3.4.2.2-carbcam-patches\/blob\/main\/0001-trio-carbcam-integration.patch<\/a><\/p>\n<h1 dir=\"auto\"><\/h1>\n<div class=\"markdown-heading\" dir=\"auto\">\n<h1 class=\"heading-element\" dir=\"auto\" tabindex=\"-1\">AAPS 4 (DEV) Stand 7734facd Milos Kozak <a href=\"mailto:m.kozak@sysop.cz\">m.kozak@sysop.cz<\/a> on 01.06.2026 at 23:02<\/h1>\n<p><a id=\"user-content-aaps-4-dev-stand-7734facd-milos-kozak-mkozaksysopcz-on-01062026-at-2302\" class=\"anchor\" href=\"https:\/\/github.com\/zehnBE\/aaps3.4.2.2-carbcam-patches\/#aaps-4-dev-stand-7734facd-milos-kozak-mkozaksysopcz-on-01062026-at-2302\" aria-label=\"Permalink: AAPS 4 (DEV) Stand 7734facd Milos Kozak m.kozak@sysop.cz on 01.06.2026 at 23:02\" target=\"_blank\" rel=\"noopener\"><\/a><\/div>\n<p dir=\"auto\"><a href=\"https:\/\/github.com\/zehnBE\/aaps3.4.2.2-carbcam-patches\/blob\/main\/0001-aaps-v4-carbcam-integration.patch\" target=\"_blank\" rel=\"noopener\">https:\/\/github.com\/zehnBE\/aaps3.4.2.2-carbcam-patches\/blob\/main\/0001-aaps-v4-carbcam-integration.patch<\/a><\/p>\n<p dir=\"auto\">\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Kohlenhydrate aus CarbCam direkt in den AAPS 3.4.x.x\/aaps4\/iAPS Bolus-Wizard \u00fcbernehmen Stand: AAPS 3.4.2.2 branch. AAPS 4 (DEV), iAPS Worum geht&#8217;s Wer Kohlenhydrate per Foto sch\u00e4tzt (CarbCam) oder aus einer Lebensmittel-Datenbank zieht, muss den Wert bisher abtippen oder \u00fcber Nightscout-Treatments umweglos hineinpumpen. Beides ist umst\u00e4ndlich. Der hier beschriebene Patch f\u00fcgt AAPS einen kleinen, definierten Eingang hinzu: [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":852,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_links_to":"","_links_to_target":""},"categories":[5],"tags":[229,232,230,222,231,233,24],"class_list":["post-842","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-diy-technik-apps","tag-aaps3-4-2-2","tag-bolus","tag-boluzwizard","tag-carbcam","tag-carbcam-zu-aaps","tag-carbs","tag-kh"],"_links":{"self":[{"href":"https:\/\/zehn.be\/wp-json\/wp\/v2\/posts\/842","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/zehn.be\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/zehn.be\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/zehn.be\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/zehn.be\/wp-json\/wp\/v2\/comments?post=842"}],"version-history":[{"count":19,"href":"https:\/\/zehn.be\/wp-json\/wp\/v2\/posts\/842\/revisions"}],"predecessor-version":[{"id":863,"href":"https:\/\/zehn.be\/wp-json\/wp\/v2\/posts\/842\/revisions\/863"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/zehn.be\/wp-json\/wp\/v2\/media\/852"}],"wp:attachment":[{"href":"https:\/\/zehn.be\/wp-json\/wp\/v2\/media?parent=842"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/zehn.be\/wp-json\/wp\/v2\/categories?post=842"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/zehn.be\/wp-json\/wp\/v2\/tags?post=842"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}