ioBroker.javascript
Inhaltsverzeichnis
- Blockly
- Benutzung
- JavaScript-Referenz (nur auf Englisch verfügbar)
- Upgrade-Anleitung (nur auf Englisch verfügbar)
KI-Codegenerator - Unterstützung eigener API-Endpunkte
Der integrierte KI-Codegenerator unterstützt nicht nur die OpenAI-API, sondern auch jeden OpenAI-kompatiblen API-Endpunkt. So können alternative Anbieter genutzt werden, z.B.:
- Google Gemini (kostenlos verfügbar, empfohlen)
- DeepSeek (sehr günstig)
- OpenRouter (Multi-Provider-Gateway)
- Ollama (lokale LLMs)
- LM Studio (lokale LLMs)
- Anthropic (über OpenAI-kompatiblen Proxy)
- Jeder andere Anbieter mit einem OpenAI-kompatiblen
/v1/chat/completions-Endpunkt
Empfohlene Anbieter
Google Gemini (kostenlos, empfohlen)
Google bietet ein großzügiges kostenloses Kontingent mit einem OpenAI-kompatiblen Endpunkt — ideal für die ioBroker-Skript-Generierung:
| Modell | Anfragen/Min | Anfragen/Tag | Qualität |
|---|---|---|---|
| Gemini 2.5 Flash | 10 | 500 | Sehr gut für Code |
| Gemini 2.5 Pro | 5 | 25 | Ausgezeichnet |
| Gemini 2.0 Flash | 15 | 1500 | Gut |
Einrichtung:
- Kostenlosen API-Key holen: https://aistudio.google.com/apikey
- Base-URL auf
https://generativelanguage.googleapis.com/v1beta/openaisetzen - Ein Gemini-Modell wählen (z.B.
gemini-2.5-flash)
DeepSeek (sehr günstig)
DeepSeek bietet hervorragende Code-Generierung zu sehr niedrigen Kosten (~0,001€ pro Anfrage):
- API-Key holen: https://platform.deepseek.com/
- Base-URL auf
https://api.deepseek.com/v1setzen - Empfohlenes Modell:
deepseek-chat
Lokale Modelle (Ollama / LM Studio)
Lokale Modelle laufen auf eigener Hardware ohne Internet.
Mindestanforderung: 14B-Parameter-Modelle (z.B. qwen2.5-coder:14b). Kleinere Modelle (7B/9B) erzeugen unzuverlässigen Code mit falschen API-Aufrufen. Eine GPU mit mindestens 12GB VRAM (z.B. RTX 3060) wird für 14B-Modelle empfohlen.
Getestete und empfohlene Modelle:
qwen2.5-coder:14b- Gute Codequalität, läuft auf 12GB VRAMqwen2.5-coder:32b- Bessere Qualität, erfordert 24GB+ VRAM
Einrichtung:
- Ollama: Base-URL auf
http://localhost:11434/v1setzen, API-Key leer lassen - LM Studio: Base-URL auf
http://localhost:1234/v1setzen, API-Key leer lassen
Hinweis: Die kostenlose Version der OpenAI-API (ChatGPT) bietet keinen API-Zugang mehr für Code-Generierung. Google Gemini (kostenlos) oder DeepSeek (sehr günstig) sind empfohlene Alternativen.
Konfiguration
In den Adapter-Einstellungen unter "KI-Einstellungen" befinden sich API-Key-Felder für jeden Anbieter:
| Einstellung | Beschreibung |
|---|---|
| ChatGPT API-Schlüssel | API-Key für OpenAI (platform.openai.com) |
| Anthropic API-Schlüssel | API-Key für Claude (console.anthropic.com) |
| Gemini API-Schlüssel | API-Key für Google Gemini (aistudio.google.com) |
| DeepSeek API-Schlüssel | API-Key für DeepSeek (platform.deepseek.com) |
| Eigene API Base-URL | Base-URL für eigene Anbieter (z.B. http://localhost:11434/v1 für Ollama) |
| Eigener API-Schlüssel | Optionaler API-Key für eigene Anbieter (Ollama benötigt keinen) |
Alle API-Key-Felder werden als Passwortfelder dargestellt (maskiert). Es müssen nur die Keys der gewünschten Anbieter eingetragen werden. Jeder Anbieter hat einen eigenen Test-Button.
Sicherheit der API-Schlüssel
Die API-Keys werden durch zwei von der ioBroker-Plattform bereitgestellte Schutzebenen abgesichert:
encryptedNative— Die Keys werden vor dem Schreiben in die Object-Datenbank automatisch mit dem System-Secret verschlüsselt. Datenbank-Dumps oder Object-Backups enthalten die Keys nicht mehr im Klartext.protectedNative— Die Keys werden niemals an Admin-Oberflächen oder fremde Adapter übertragen. Nur diejavascript-Instanz selbst kann sie überthis.configlesen (die ioBroker-Runtime liefert sie dort transparent entschlüsselt).
Daraus folgt: Das KI-Chat-Panel, die Inline-Completion und alle anderen Frontend-Komponenten greifen nicht mehr direkt auf die Keys zu. Stattdessen wird jede KI-Anfrage per sendTo an den Adapter geschickt, und das Backend setzt den passenden Key ein:
Frontend Backend (this.config, entschlüsselt)
──────── ─────────────────────────────────────
sendTo('chatCompletion', { → wählt Provider → nimmt gptKey/claudeKey/…
provider: 'openai', → schickt HTTP-Request an Anbieter
model: 'gpt-4o', → liefert Antwort zurück
messages: [...]
})
Für die Anzeige steht ein eigener sendTo-Befehl zur Verfügung:
| Befehl | Payload | Antwort |
|---|---|---|
getAvailableAiProviders | {} | { providers: [{ provider: 'openai' }, { provider: 'custom', baseUrl: '…' }, …] } |
Die Antwort teilt dem Frontend nur mit, welche Provider konfiguriert sind — der eigentliche Schlüssel ist darin nie enthalten. So lassen sich im Editor die richtigen Provider-Icons anzeigen und das Modell-Dropdown korrekt befüllen, ohne Secrets in den Browser zu laden.
Hinweis zum Upgrade: Nach dem Upgrade von einer älteren Version bleiben vorhandene (unverschlüsselte) Keys so lange gültig, bis die Adapter-Einstellungen das erste Mal gespeichert werden. Beim Speichern verschlüsselt die Runtime die Werte. Sollte ein Schlüssel nach dem Upgrade leer erscheinen, genügt es, ihn einmal neu einzutragen und zu speichern.
API-Verbindung testen
Jeder Anbieter hat einen eigenen Test-Button neben seinem API-Key-Feld. Es werden zwei Fälle unterschieden:
- Test mit Formular-Wert — Unmittelbar nach dem Eintragen oder Ändern eines Keys im Einstellungsdialog nutzt der
Test-Button den aktuellen Formularwert (der liegt vor dem Speichern noch lokal im Browser). So kann ein neuer Key vor dem Persistieren geprüft werden. - Test mit gespeichertem Schlüssel — Wird der Test aus Kontexten ohne Formular-Wert aufgerufen (z.B. beim Modell-Abruf im Skript-Editor), löst das Backend den Key über
this.configanhand des gewählten Providers auf.
Der Test:
- Verbindet sich mit dem API-Endpunkt des Anbieters
- Validiert den API-Schlüssel
- Gibt die Anzahl der verfügbaren Chat-Modelle zurück
Die Icons der Test-Buttons sind als Inline-SVG-Data-URIs mit fill="currentColor" eingebettet. Dadurch folgt ihre Farbe automatisch dem aktiven Theme (Light/Dark-Mode).
Dynamisches Laden der Modelle
Beim Öffnen des KI-Codegenerator-Dialogs im Skript-Editor werden die verfügbaren Modelle automatisch von jedem konfigurierten Provider abgerufen. Das Modell-Dropdown wird dynamisch befüllt — es gibt keine fest hinterlegte Modellliste.
Filter für nicht-Chat-Modelle
Die Modelllisten, die OpenAI, Anthropic, Gemini, DeepSeek und Custom-Endpunkte (Ollama/LM Studio/OpenRouter) zurückliefern, enthalten viele Modelle, die nicht für Chat-Completion geeignet sind. Der Adapter filtert diese automatisch heraus, sodass im Dropdown nur Modelle erscheinen, die für die ioBroker-Skript-Generierung taugen.
Folgende Kategorien werden ausgeschlossen:
| Kategorie | Beispiel-Schlüsselwörter |
|---|---|
| Embeddings | embedding, text-embedding, embeddinggemma, bge-, nomic-embed, mxbai-embed, arctic-embed, all-minilm, voyage-, gecko, paraphrase-multilingual |
| Bild-Generierung / -Bearbeitung | dall-e, gpt-image, image-edit, -image-preview, -image-latest, flash-image, nano-banana, stable-diffusion, sdxl, midjourney, flux-, imagen |
| Video-Generierung | sora, veo-, cogvideo, runway-, lumiere |
| Musik-Generierung | lyria |
| Audio / Sprache / Transkription / Realtime | whisper, tts-, -tts, speech-, audio-preview, -transcribe, native-audio, flash-live, gpt-audio, realtime, bark-, xtts, voicebox |
| Moderation / Safety-Klassifikatoren | moderation, omni-moderation, llama-guard, shieldgemma, prompt-guard, -guardian, safeguard |
| Reranker | rerank, reranker |
| Legacy-Completion (OpenAI GPT-3-Ära) | babbage-, davinci-, curie-, text-davinci, instructgpt, code-davinci, code-cushman, -turbo-instruct |
| Web-Suche / Browsing-Endpoints | -search-preview, -search-api |
| Legacy-Suche / Similarity | code-search, text-search, similarity- |
| Spezial / Single-Task | computer-use-preview, deep-research, robotics, aqa, reader-lm (HTML→Markdown), -nsql (Text-zu-SQL), minicheck (Fact-Check), claude-1, claude-instant |
Der Filter verwendet eine Substring-Prüfung ohne Beachtung der Groß-/Kleinschreibung. Wenn ein Provider künftig eine weitere Nicht-Chat-Familie einführt, lässt sich die Liste in src-editor/src/AiChat/AiChatService.ts (NON_CHAT_KEYWORDS) erweitern.
Fehlerbehandlung
Wenn der API-Endpunkt nicht erreichbar ist oder einen Fehler zurückgibt, werden benutzerfreundliche Meldungen angezeigt:
- Verbindungsfehler (Endpunkt nicht erreichbar)
- Ungültiger API-Schlüssel (401)
- Zugriff verweigert (403)
- Modell nicht gefunden (404)
Bei fehlgeschlagenem Modellabruf wird ein Erneut versuchen-Button angezeigt, sodass ein erneuter Versuch ohne Schließen des Dialogs möglich ist.
Changelog
10.2.4 (2026-09-14)
- (@GermanBluefox) Rules: selection of state fixed
- (@GermanBluefox) Fixed debugger
10.2.0 (2026-09-11)
- (@GermanBluefox) Rules: an empty "and" band folds down to its heading. A rule without conditions runs its actions on every trigger, but that band was still the tallest thing in the rule - a drop area with a 64px floor, the "just check" selector and an "or" row per group, 292px for nothing. It is 41px now and says "without condition", clicking the heading opens it again, dragging a condition over it opens it by itself, and a band that has conditions in it never folds
- (@GermanBluefox) Rules: the block palette takes half the room it did. An entry carried 24px of padding around a 30px icon, which left 66px of sidebar for one line of text - so four blocks filled the whole height and everything else was behind a scrollbar. Entries are 31px apart now, the icon-only tabs above them no longer reserve the height of a label they do not have, and the sidebar is 168px instead of 200px wide. A name too long for that gets the full text as its tooltip. The button that folds the palette away also sits on the palette's line now instead of one pixel to the left of it, where it hung over the edge of the window once the palette was folded away
- (@GermanBluefox) Rules: picking the state of a trigger took the editor down with "n.replace is not a function" when a condition on a string state had no value entered yet. Choosing a state compiles the whole rule again, and the empty value arrived at the comparison as the boolean
false. A condition without a value now compares against an empty text, and a number entered for a state that is a string is used as its text - (@GermanBluefox) The script editor now tells the adapter every 10 seconds that it is open, and the adapter keeps the type definitions and the compiler hot while that is the case, so saving a script does not wait for them to be built again. 30 seconds after the last sign of life the GUI counts as gone and everything is given back - about 100 MB. A tab in the background does not count as open, so a forgotten browser tab cannot keep the memory alive for days (#2373)
- (@GermanBluefox) The type definitions of Node.js, ioBroker and the configured libraries were read at every start, whether anything wanted them or not. Only two things do - compiling a TypeScript script and the built-in editor - and they add about 90 MB to the compiler, so they are now read when one of those actually asks. An instance that runs plain JavaScript and is edited elsewhere (mirror directory, external editor) never reads them; the declarations of global JavaScripts are generated without them and come out the same. They can also be switched off for good ("Load type definitions", TypeScript tab) - the editor then loses its autocompletion and TypeScript scripts no longer compile, which the adapter warns about in the log (#2373)
- (@GermanBluefox) Every instance kept two TypeScript language services alive whether it needed them or not, and each one held on to about 95 MB once it had compiled anything. They are now built on the first compilation only, and the declarations of global JavaScripts are stored on the script object the same way compiled TypeScript sources already were - so a restart no longer regenerates them. What a language service does end up building is released again a minute after the last compilation and rebuilt on demand. On a test system this took an instance from 241 MB to 127 MB heap (352 MB to 233 MB RSS) (#2373)
- (@GermanBluefox) The helpers that the script editor draws on its own - the "Explain / Refactor / Test" row above every function, the tooltips for object IDs and CRON expressions, and the inline code suggestions - can be switched off. The instance setting "Show AI helpers in the script editor" (AI settings) does it; it is on by default, so nothing changes for anyone who is happy with them.
Alt+Istill shows the value of the object ID under the cursor when they are off - (@GermanBluefox) The reasoning of an OpenAI-compatible endpoint was switched off unconditionally:
reasoning_effort: "none"went out with every request as soon as a custom base URL was configured. That is right for a small local model and wrong for everything else - behind a proxy it turns off the reasoning of the very model one is paying for, or is rejected. It is a setting now ("Reasoning effort"), and the default leaves the parameter out and lets the endpoint decide - (@GermanBluefox) The AI editor told the adapter how long it was willing to wait, and the adapter never read it: a stuck inline completion held its slot for the full ten minutes instead of the fifteen seconds it asked for
- (@GermanBluefox) The inline completion took the model chosen in the AI chat but picked the provider itself, so a model of one provider could be requested with the credentials and at the endpoint of another. Model and provider are now remembered and used together
- (@GermanBluefox) When two providers offer a model of the same name - a proxy and the vendor behind it, for instance - which of them served it was decided by whichever answered first, and could change from one reload to the next. The provider configured first wins now, so the direct route is preferred over a proxy
10.1.4 (2026-09-03)
- (@GermanBluefox) Rules: the text of an action can round the trigger value with
%.1s- any number of digits after the decimal point, also%.2oldfor the old value - formatted with the decimal separator of the system, soKühlschrank zu warm (%.1s°C)gives29,4°Cwhere%sgave29.400000000000002°C - (@GermanBluefox) Corrected the function block in blockly
- (@GermanBluefox) A custom OpenAI-compatible AI endpoint answered "Invalid API key" in the inline completion and while loading the model list, although the test button in the settings said "ok": both asked the adapter for the provider
openai, and the adapter picks the key by that name, so they used the "OpenAI API key" instead of the "Custom API key". The custom endpoint is now addressed as what it is, everywhere (#2369) - (@GermanBluefox) A configured "Custom API Base URL" also redirected every request meant for OpenAI itself to that address - with the OpenAI key attached and no way to switch it off. The base URL now belongs to the custom endpoint alone, so both can be used side by side. If the key of your custom endpoint is in the "OpenAI API key" field, move it to the "Custom API key" field; the adapter writes a warning in the log if it finds such a setup (#2369)
- (@GermanBluefox) A folded "or"/"else" section of a rule still occupied the 64px every section reserves as a drop target, and showed the top 64px of the very cards it was supposed to hide - clipped, and out of reach of the scrollbar. Being the last thing in the rule, that looked like a rule that could not be scrolled to its end
- (@GermanBluefox) The 1px line between the script tabs and the toolbar stopped 10px short of the left edge and 40px short of the right one: the tab row carried a margin and a
calc(100% - 50px)width to leave room for the "close all but current" button. Both are padding on the tab strip now, so the line reaches the edges of the pane - (@GermanBluefox) Blockly was grey in every dark theme - workspace, toolbox and flyout were hard-coded colours, which left a grey block sitting in the middle of, for instance, the navy "modernDark" admin. They follow the colours of the active ioBroker theme now, in light themes as well. The blocks themselves keep the colour of their category
10.1.3 (2026-08-30)
- (@GermanBluefox) The plain text export named its files after the script ID instead of the script name, so every dot of a name came out as an underscore -
HK-Balkontuer_v0.1was exported asHK-Balkontuer_v0_1.js, and importing it back renamed the script to that. The files are now named after the script (#2364) - (@GermanBluefox) Importing a plain text export treated a dot inside a file name as a folder level, so
PW-TV-Control_v0.6.jscreated a folderPW-TV-Control_v0containing a script named6. Only the directories of the ZIP are folders now (#2364) - (@GermanBluefox) The folder icons in the script tree were drawn at less than half the size of the script icons next to them: they spaced themselves with a padding, and since
CssBaselinesetsbox-sizing: border-boxthat padding was subtracted from their 20px instead of being added to them. They use a margin now, like the script icons always did (#2360) - (@GermanBluefox) The log below the editor could not be resized while a script was open: the editor area guessed its height from the height the tabs and the toolbar were expected to have, hung over the bottom edge of its pane and covered the 8px splitter with the horizontal scrollbar of the editor, which swallowed the mouse click. The three parts now share the height as a flex column (#2351)
- (@GermanBluefox) The script list cut off long names, although there was still free space next to them: the space for the buttons at the end of a row was a fixed 185px, which is more than the three buttons occupy, and it did not account for the icon column
- (@GermanBluefox) Fixed the Blockly comment block: the text was written in white on the yellow block and could not be read, the editor opened somewhere else on the page instead of over the block, and on a smartphone or tablet it did not open at all and left the whole workspace unusable until the page was reloaded (#2348)
- (@GermanBluefox) Fixed the script mirror for folder names containing regular expression characters: a folder called e.g.
Lampen (Fluraborted the synchronization with aSyntaxError, a folder called e.g.[ab]silently synchronized the scripts of another folder (#2239) - (@GermanBluefox) The Blockly block "http (POST)" got a "content type" selector, so an API that insists on
Content-Type: application/jsonno longer needs anexecblock. "automatic" is the default and behaves exactly as before, "own" allows any other type (#1983) - (@GermanBluefox)
getSchedules()returned the schedules of the time wizard of all scripts, even without the argumenttrue. Now only the schedules of the own script are returned (#2164) - (@GermanBluefox)
clearSchedule()did not accept the objects thatgetSchedules()returns for schedules of the time wizard, so such a schedule stayed in the script and in the schedule counter (#2164) - (@GermanBluefox)
clearSchedule()can now clear the CRON jobs of other scripts too, as documented forgetSchedules(true)(#2164) - (@GermanBluefox)
getSchedules()no longer lists the already canceled schedules of the own script in anonStopcallback (#2164)
10.1.2 (2026-08-24)
- (@GermanBluefox) Added new rule blocks
- (@krobipd) Fixed saving of Blockly scripts under Blockly 13: a script containing a named timeout, interval or schedule could not be saved anymore - the save button did not appear (#2349)
- (@krobipd) Fixed saving of Blockly scripts containing a function with a return value and no statements (#1958)
- (@krobipd) The Blockly regression tests now also cover saving: every block is serialized the way the editor does it and reloaded to the same code
- (@krobipd) When a block fails while the script is regenerated after a change, the editor now shows the error instead of silently never offering the save button; a failing export shows its error too
License
The MIT License (MIT)
Copyright (c) 2014-2026 bluefox dogafox@gmail.com,
Copyright (c) 2014 hobbyquaker
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.