diff --git a/CODEOWNERS b/CODEOWNERS
index 887b51cf72a8c..29ecd123a232d 100644
--- a/CODEOWNERS
+++ b/CODEOWNERS
@@ -427,7 +427,6 @@
/bundles/org.openhab.voice.mimictts/ @dalgwen
/bundles/org.openhab.voice.picotts/ @FlorianSW
/bundles/org.openhab.voice.pollytts/ @openhab/add-ons-maintainers
-/bundles/org.openhab.voice.porcupineks/ @GiviMAD
/bundles/org.openhab.voice.rustpotterks/ @GiviMAD
/bundles/org.openhab.voice.voicerss/ @lolodomo
/bundles/org.openhab.voice.voskstt/ @GiviMAD
diff --git a/bom/openhab-addons/pom.xml b/bom/openhab-addons/pom.xml
index 306356a673c3e..bbb3a0b1d2e8e 100644
--- a/bom/openhab-addons/pom.xml
+++ b/bom/openhab-addons/pom.xml
@@ -2121,11 +2121,6 @@
org.openhab.voice.pollytts${project.version}
-
- org.openhab.addons.bundles
- org.openhab.voice.porcupineks
- ${project.version}
- org.openhab.addons.bundlesorg.openhab.voice.rustpotterks
diff --git a/bundles/org.openhab.voice.porcupineks/NOTICE b/bundles/org.openhab.voice.porcupineks/NOTICE
deleted file mode 100644
index 6ccccccb03adb..0000000000000
--- a/bundles/org.openhab.voice.porcupineks/NOTICE
+++ /dev/null
@@ -1,20 +0,0 @@
-This content is produced and maintained by the openHAB project.
-
-* Project home: https://www.openhab.org
-
-== Declared Project Licenses
-
-This program and the accompanying materials are made available under the terms
-of the Eclipse Public License 2.0 which is available at
-https://www.eclipse.org/legal/epl-2.0/.
-
-== Source Code
-
-https://github.com/openhab/openhab-addons
-
-== Third-party Content
-
-ai.picovoice: porcupine-java
-* License: Apache 2.0 License
-* Project: https://github.com/Picovoice/porcupine
-* Source: https://github.com/Picovoice/porcupine/tree/v2.1/binding/java
diff --git a/bundles/org.openhab.voice.porcupineks/README.md b/bundles/org.openhab.voice.porcupineks/README.md
deleted file mode 100644
index 7411fd217ab04..0000000000000
--- a/bundles/org.openhab.voice.porcupineks/README.md
+++ /dev/null
@@ -1,86 +0,0 @@
-# Porcupine Keyword Spotter
-
-This voice service allows you to use the PicoVoice product Porcupine as your keyword spotter in openHAB.
-
-Porcupine provides on-device wake word detection powered by deep learning.
-This add-on should work on all the platforms supported by Porcupine, if you encounter a problem you can try to run one of the Porcupine java demos on your machine.
-
-Important: No voice data listened by this service will be uploaded to the Cloud.
-The voice data is processed offline, locally on your openHAB server by Porcupine.
-Once in a while, access keys are validated to stay active and this requires an Internet connection.
-
-## Configuration
-
-After installing, you will be able to access the service options through the openHAB configuration page in UI (**Settings / Other Services - Porcupine Keyword Spotter**) to edit them:
-
-* **Pico Voice API Key** - API key from PicoVoice, required to use Porcupine.
-
-* **Sensitivity** - Spot sensitivity, a higher sensitivity reduces miss rate at cost of increased false alarm rate.
-
-In case you would like to setup the service via a text file, create a new file in `$OPENHAB_ROOT/conf/services` named `porcupineks.cfg`
-
-Its contents should look similar to:
-
-```
-org.openhab.voice.porcupineks:apiKey=KEY
-org.openhab.voice.porcupineks:sensitivity=0.5
-```
-
-## Magic Word Configuration
-
-The magic word to spot is gathered from your 'Voice' configuration.
-The default english keyword models are loaded in the addon (also the english language model) so you can use those without adding anything else.
-
-Note that you can use the pico voice platform to generate your own keyword models.
-To use them, you should place the generated file under '\/porcupine' and configure your magic word to match the file name replacing spaces with '_' and adding the extension '.ppn'.
-As an example, the file generated for the keyword "ok openhab" will be named 'ok_openhab.ppn'.
-
-The service will only work if it's able to find the correct ppn for your magic word configuration.
-
-#### Build-in keywords
-
-Remember that they only work with the English language model. (read bellow section)
-
-* alexa
-* americano
-* blueberry
-* bumblebee
-* computer
-* grapefruits
-* grasshopper
-* hey google
-* hey siri
-* jarvis
-* ok google
-* picovoice
-* porcupine
-* terminator
-
-
-## Language support
-
-This service currently supports English, German, French and Spanish.
-
-Only the English model binary is included with the addon and will be used if the one for your configured language is not found under '\/porcupine'.
-
-To get the language model files, go to the [Porcupine repo](https://github.com/Picovoice/porcupine/tree/v2.1/lib/common).
-
-Note that the keyword model you use should match the language model.
-
-## Default Keyword Spotter and Magic Word Configuration
-
-You can setup your preferred default keyword spotter and default magic word in the UI:
-
-* Go to **Settings**.
-* Edit **System Services - Voice**.
-* Set **Porcupine Keyword Spotter** as **Default Keyword Spotter**.
-* Choose your preferred **Magic Word** for your setup.
-* Choose optionally your **Listening Switch** item that will be switch ON during the period when the dialog processor has spotted the keyword and is listening for commands.
-
-In case you would like to setup these settings via a text file, you can edit the file `runtime.cfg` in `$OPENHAB_ROOT/conf/services` and set the following entries:
-
-```
-org.openhab.voice:defaultKS=porcupineks
-org.openhab.voice:keyword=picovoice
-org.openhab.voice:listeningItem=myItemForDialog
-```
diff --git a/bundles/org.openhab.voice.porcupineks/pom.xml b/bundles/org.openhab.voice.porcupineks/pom.xml
deleted file mode 100644
index 124dc1d1cc812..0000000000000
--- a/bundles/org.openhab.voice.porcupineks/pom.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
- 4.0.0
-
-
- org.openhab.addons.bundles
- org.openhab.addons.reactor.bundles
- 4.1.0-SNAPSHOT
-
-
- org.openhab.voice.porcupineks
-
- openHAB Add-ons :: Bundles :: Voice :: Porcupine Keyword Spotter
-
-
- ai.picovoice
- porcupine-java
- 2.1.0
- compile
-
-
-
diff --git a/bundles/org.openhab.voice.porcupineks/src/main/feature/feature.xml b/bundles/org.openhab.voice.porcupineks/src/main/feature/feature.xml
deleted file mode 100644
index 4f1689ea872a1..0000000000000
--- a/bundles/org.openhab.voice.porcupineks/src/main/feature/feature.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
- mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features
-
-
- openhab-runtime-base
- mvn:org.openhab.addons.bundles/org.openhab.voice.porcupineks/${project.version}
-
-
diff --git a/bundles/org.openhab.voice.porcupineks/src/main/java/org/openhab/voice/porcupineks/internal/PorcupineKSConfiguration.java b/bundles/org.openhab.voice.porcupineks/src/main/java/org/openhab/voice/porcupineks/internal/PorcupineKSConfiguration.java
deleted file mode 100644
index d1ae58f9a498d..0000000000000
--- a/bundles/org.openhab.voice.porcupineks/src/main/java/org/openhab/voice/porcupineks/internal/PorcupineKSConfiguration.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/**
- * Copyright (c) 2010-2023 Contributors to the openHAB project
- *
- * See the NOTICE file(s) distributed with this work for additional
- * information.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0
- *
- * SPDX-License-Identifier: EPL-2.0
- */
-package org.openhab.voice.porcupineks.internal;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-
-/**
- * The {@link PorcupineKSConfiguration} class contains fields mapping thing configuration parameters.
- *
- * @author Miguel Álvarez - Initial contribution
- */
-@NonNullByDefault
-public class PorcupineKSConfiguration {
-
- /**
- * Api key to use porcupine
- */
- public String apiKey = "";
- /**
- * A higher sensitivity reduces miss rate at cost of increased false alarm rate
- */
- public float sensitivity = 0.5f;
-}
diff --git a/bundles/org.openhab.voice.porcupineks/src/main/java/org/openhab/voice/porcupineks/internal/PorcupineKSConstants.java b/bundles/org.openhab.voice.porcupineks/src/main/java/org/openhab/voice/porcupineks/internal/PorcupineKSConstants.java
deleted file mode 100644
index 57ec3252e5c04..0000000000000
--- a/bundles/org.openhab.voice.porcupineks/src/main/java/org/openhab/voice/porcupineks/internal/PorcupineKSConstants.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/**
- * Copyright (c) 2010-2023 Contributors to the openHAB project
- *
- * See the NOTICE file(s) distributed with this work for additional
- * information.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0
- *
- * SPDX-License-Identifier: EPL-2.0
- */
-package org.openhab.voice.porcupineks.internal;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-
-/**
- * The {@link PorcupineKSConstants} class defines common constants, which are
- * used across the whole binding.
- *
- * @author Miguel Álvarez - Initial contribution
- */
-@NonNullByDefault
-public class PorcupineKSConstants {
- /**
- * Service name
- */
- public static final String SERVICE_NAME = "Porcupine";
-
- /**
- * Service id
- */
- public static final String SERVICE_ID = "porcupineks";
-
- /**
- * Service category
- */
- public static final String SERVICE_CATEGORY = "voice";
-
- /**
- * Service pid
- */
- public static final String SERVICE_PID = "org.openhab." + SERVICE_CATEGORY + "." + SERVICE_ID;
-}
diff --git a/bundles/org.openhab.voice.porcupineks/src/main/java/org/openhab/voice/porcupineks/internal/PorcupineKSService.java b/bundles/org.openhab.voice.porcupineks/src/main/java/org/openhab/voice/porcupineks/internal/PorcupineKSService.java
deleted file mode 100644
index e9caf264a5ae4..0000000000000
--- a/bundles/org.openhab.voice.porcupineks/src/main/java/org/openhab/voice/porcupineks/internal/PorcupineKSService.java
+++ /dev/null
@@ -1,346 +0,0 @@
-/**
- * Copyright (c) 2010-2023 Contributors to the openHAB project
- *
- * See the NOTICE file(s) distributed with this work for additional
- * information.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0
- *
- * SPDX-License-Identifier: EPL-2.0
- */
-package org.openhab.voice.porcupineks.internal;
-
-import static org.openhab.voice.porcupineks.internal.PorcupineKSConstants.SERVICE_CATEGORY;
-import static org.openhab.voice.porcupineks.internal.PorcupineKSConstants.SERVICE_ID;
-import static org.openhab.voice.porcupineks.internal.PorcupineKSConstants.SERVICE_NAME;
-import static org.openhab.voice.porcupineks.internal.PorcupineKSConstants.SERVICE_PID;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.URL;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.Future;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.logging.Level;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.core.OpenHAB;
-import org.openhab.core.audio.AudioFormat;
-import org.openhab.core.audio.AudioStream;
-import org.openhab.core.common.ThreadPoolManager;
-import org.openhab.core.config.core.ConfigurableService;
-import org.openhab.core.config.core.Configuration;
-import org.openhab.core.voice.KSErrorEvent;
-import org.openhab.core.voice.KSException;
-import org.openhab.core.voice.KSListener;
-import org.openhab.core.voice.KSService;
-import org.openhab.core.voice.KSServiceHandle;
-import org.openhab.core.voice.KSpottedEvent;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
-import org.osgi.service.component.ComponentContext;
-import org.osgi.service.component.annotations.Activate;
-import org.osgi.service.component.annotations.Component;
-import org.osgi.service.component.annotations.Modified;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import ai.picovoice.porcupine.Porcupine;
-import ai.picovoice.porcupine.PorcupineException;
-
-/**
- * The {@link PorcupineKSService} is a keyword spotting implementation based on porcupine.
- *
- * @author Miguel Álvarez - Initial contribution
- */
-@NonNullByDefault
-@Component(configurationPid = SERVICE_PID, property = Constants.SERVICE_PID + "=" + SERVICE_PID)
-@ConfigurableService(category = SERVICE_CATEGORY, label = SERVICE_NAME
- + " Keyword Spotter", description_uri = SERVICE_CATEGORY + ":" + SERVICE_ID)
-public class PorcupineKSService implements KSService {
- private static final String PORCUPINE_FOLDER = Path.of(OpenHAB.getUserDataFolder(), "porcupine").toString();
- private static final String EXTRACTION_FOLDER = Path.of(OpenHAB.getUserDataFolder(), "porcupine", "extracted")
- .toString();
- private final Logger logger = LoggerFactory.getLogger(PorcupineKSService.class);
- private final ScheduledExecutorService executor = ThreadPoolManager.getScheduledPool("OH-voice-porcupineks");
- private PorcupineKSConfiguration config = new PorcupineKSConfiguration();
- private @Nullable BundleContext bundleContext;
-
- static {
- Logger logger = LoggerFactory.getLogger(PorcupineKSService.class);
- File directory = new File(PORCUPINE_FOLDER);
- if (!directory.exists()) {
- if (directory.mkdir()) {
- logger.info("porcupine dir created {}", PORCUPINE_FOLDER);
- }
- }
- File childDirectory = new File(EXTRACTION_FOLDER);
- if (!childDirectory.exists()) {
- if (childDirectory.mkdir()) {
- logger.info("porcupine extraction file dir created {}", EXTRACTION_FOLDER);
- }
- }
- }
-
- @Activate
- protected void activate(ComponentContext componentContext, Map config) {
- this.bundleContext = componentContext.getBundleContext();
- modified(config);
- }
-
- @Modified
- protected void modified(Map config) {
- this.config = new Configuration(config).as(PorcupineKSConfiguration.class);
- if (this.config.apiKey.isBlank()) {
- logger.warn("Missing pico voice api key to use Porcupine Keyword Spotter");
- }
- }
-
- private String prepareLib(BundleContext bundleContext, String path) throws IOException {
- if (!path.contains("porcupine" + File.separator)) {
- // this should never happen
- throw new IOException("Path is not pointing to porcupine bundle files " + path);
- }
- // get a path relative to the porcupine bundle folder
- String relativePath;
- if (path.startsWith("porcupine" + File.separator)) {
- relativePath = path;
- } else {
- relativePath = path.substring(path.lastIndexOf(File.separator + "porcupine" + File.separator) + 1);
- }
- File localFile = new File(EXTRACTION_FOLDER,
- relativePath.substring(relativePath.lastIndexOf(File.separator) + 1));
- if (!localFile.exists()) {
- if ("\\".equals(File.separator)) {
- // bundle requires unix path separator
- logger.debug("use unix path separator");
- relativePath = relativePath.replace("\\", "/");
- }
- URL porcupineResource = bundleContext.getBundle().getEntry(relativePath);
- logger.debug("extracting binary {} from bundle to extraction folder", relativePath);
- if (porcupineResource == null) {
- throw new IOException("Missing bundle file: " + relativePath);
- }
- extractFromBundle(porcupineResource, localFile);
- } else {
- logger.debug("binary {} already extracted", relativePath);
- }
- return localFile.toString();
- }
-
- private void extractFromBundle(URL resourceUrl, File targetFile) throws IOException {
- InputStream in = new BufferedInputStream(resourceUrl.openStream());
- OutputStream out = new BufferedOutputStream(new FileOutputStream(targetFile));
- byte[] buffer = new byte[1024];
- int lengthRead;
- while ((lengthRead = in.read(buffer)) > 0) {
- out.write(buffer, 0, lengthRead);
- out.flush();
- }
- in.close();
- out.close();
- }
-
- @Override
- public String getId() {
- return SERVICE_ID;
- }
-
- @Override
- public String getLabel(@Nullable Locale locale) {
- return SERVICE_NAME;
- }
-
- @Override
- public Set getSupportedLocales() {
- return Set.of(Locale.ENGLISH, new Locale("es"), Locale.FRENCH, Locale.GERMAN);
- }
-
- @Override
- public Set getSupportedFormats() {
- return Set
- .of(new AudioFormat(AudioFormat.CONTAINER_WAVE, AudioFormat.CODEC_PCM_SIGNED, false, 16, null, 16000L));
- }
-
- @Override
- public KSServiceHandle spot(KSListener ksListener, AudioStream audioStream, Locale locale, String keyword)
- throws KSException {
- Porcupine porcupine;
- if (config.apiKey.isBlank()) {
- throw new KSException("Missing pico voice api key");
- }
- BundleContext bundleContext = this.bundleContext;
- if (bundleContext == null) {
- throw new KSException("Missing bundle context");
- }
- try {
- porcupine = initPorcupine(bundleContext, locale, keyword);
- } catch (PorcupineException | IOException e) {
- throw new KSException(e);
- }
- final AtomicBoolean aborted = new AtomicBoolean(false);
- Future> scheduledTask = executor
- .submit(() -> processInBackground(porcupine, ksListener, audioStream, aborted));
- return new KSServiceHandle() {
- @Override
- public void abort() {
- logger.debug("stopping service");
- aborted.set(true);
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- }
- scheduledTask.cancel(true);
- }
- };
- }
-
- private Porcupine initPorcupine(BundleContext bundleContext, Locale locale, String keyword)
- throws IOException, PorcupineException {
- // Suppress library logs
- java.util.logging.Logger globalJavaLogger = java.util.logging.Logger
- .getLogger(java.util.logging.Logger.GLOBAL_LOGGER_NAME);
- Level currentGlobalLogLevel = globalJavaLogger.getLevel();
- globalJavaLogger.setLevel(java.util.logging.Level.OFF);
- String bundleLibraryPath = Porcupine.LIBRARY_PATH;
- if (bundleLibraryPath == null) {
- throw new PorcupineException("Unsupported environment, ensure Porcupine is supported by your system");
- }
- String libraryPath = prepareLib(bundleContext, bundleLibraryPath);
- String alternativeModelPath = getAlternativeModelPath(bundleContext, locale);
- String modelPath = alternativeModelPath != null ? alternativeModelPath
- : prepareLib(bundleContext, Porcupine.MODEL_PATH);
- String keywordPath = getKeywordResourcePath(bundleContext, keyword, alternativeModelPath == null);
- logger.debug("Porcupine library path: {}", libraryPath);
- logger.debug("Porcupine model path: {}", modelPath);
- logger.debug("Porcupine keyword path: {}", keywordPath);
- logger.debug("Porcupine sensitivity: {}", config.sensitivity);
- try {
- return new Porcupine(config.apiKey, libraryPath, modelPath, new String[] { keywordPath },
- new float[] { config.sensitivity });
- } finally {
- // restore log level
- globalJavaLogger.setLevel(currentGlobalLogLevel);
- }
- }
-
- private String getPorcupineEnv() {
- // get porcupine env from resolved library path
- String searchTerm = "lib" + File.separator + "java" + File.separator;
- String env = Porcupine.LIBRARY_PATH.substring(Porcupine.LIBRARY_PATH.indexOf(searchTerm) + searchTerm.length());
- env = env.substring(0, env.indexOf(File.separator));
- return env;
- }
-
- private @Nullable String getAlternativeModelPath(BundleContext bundleContext, Locale locale) throws IOException {
- String modelPath = null;
- if (locale.getLanguage().equals(Locale.GERMAN.getLanguage())) {
- Path dePath = Path.of(PORCUPINE_FOLDER, "porcupine_params_de.pv");
- if (Files.exists(dePath)) {
- modelPath = dePath.toString();
- } else {
- logger.warn(
- "You can provide a specific model for de language in {}, english language model will be used",
- PORCUPINE_FOLDER);
- }
- } else if (locale.getLanguage().equals(Locale.FRENCH.getLanguage())) {
- Path frPath = Path.of(PORCUPINE_FOLDER, "porcupine_params_fr.pv");
- if (Files.exists(frPath)) {
- modelPath = frPath.toString();
- } else {
- logger.warn(
- "You can provide a specific model for fr language in {}, english language model will be used",
- PORCUPINE_FOLDER);
- }
- } else if ("es".equals(locale.getLanguage())) {
- Path esPath = Path.of(PORCUPINE_FOLDER, "porcupine_params_es.pv");
- if (Files.exists(esPath)) {
- modelPath = esPath.toString();
- } else {
- logger.warn(
- "You can provide a specific model for es language in {}, english language model will be used",
- PORCUPINE_FOLDER);
- }
- }
- return modelPath;
- }
-
- private String getKeywordResourcePath(BundleContext bundleContext, String keyWord, boolean allowBuildIn)
- throws IOException {
- String localKeywordFile = keyWord.toLowerCase().replace(" ", "_") + ".ppn";
- Path localKeywordPath = Path.of(PORCUPINE_FOLDER, localKeywordFile);
- if (Files.exists(localKeywordPath)) {
- return localKeywordPath.toString();
- }
- if (allowBuildIn) {
- try {
- Porcupine.BuiltInKeyword.valueOf(keyWord.toUpperCase().replace(" ", "_"));
- } catch (IllegalArgumentException e) {
- throw new IllegalArgumentException(
- "Unable to find model file for configured wake word neither is build-in. Should be at "
- + localKeywordPath);
- }
- String env = getPorcupineEnv();
- String keywordPath = Path
- .of("porcupine", "resources", "keyword_files", env, keyWord.replace(" ", "_") + "_" + env + ".ppn")
- .toString();
- return prepareLib(bundleContext, keywordPath);
- } else {
- throw new IllegalArgumentException(
- "Unable to find model file for configured wake word; there are no build-in wake words for your language. Should be at "
- + localKeywordPath);
- }
- }
-
- private void processInBackground(Porcupine porcupine, KSListener ksListener, AudioStream audioStream,
- AtomicBoolean aborted) {
- int numBytesRead;
- // buffers for processing audio
- int frameLength = porcupine.getFrameLength();
- ByteBuffer captureBuffer = ByteBuffer.allocate(frameLength * 2);
- captureBuffer.order(ByteOrder.LITTLE_ENDIAN);
- short[] porcupineBuffer = new short[frameLength];
- while (!aborted.get()) {
- try {
- // read a buffer of audio
- numBytesRead = audioStream.read(captureBuffer.array(), 0, captureBuffer.capacity());
- if (aborted.get()) {
- break;
- }
- // don't pass to porcupine if we don't have a full buffer
- if (numBytesRead != frameLength * 2) {
- Thread.sleep(100);
- continue;
- }
- // copy into 16-bit buffer
- captureBuffer.asShortBuffer().get(porcupineBuffer);
- // process with porcupine
- int result = porcupine.process(porcupineBuffer);
- if (result >= 0) {
- logger.debug("keyword detected!");
- ksListener.ksEventReceived(new KSpottedEvent());
- }
- } catch (IOException | PorcupineException | InterruptedException e) {
- String errorMessage = e.getMessage();
- ksListener.ksEventReceived(new KSErrorEvent(errorMessage != null ? errorMessage : "Unexpected error"));
- }
- }
- porcupine.delete();
- logger.debug("Porcupine stopped");
- }
-}
diff --git a/bundles/org.openhab.voice.porcupineks/src/main/resources/OH-INF/addon/addon.xml b/bundles/org.openhab.voice.porcupineks/src/main/resources/OH-INF/addon/addon.xml
deleted file mode 100644
index 8106ed9e0ecb0..0000000000000
--- a/bundles/org.openhab.voice.porcupineks/src/main/resources/OH-INF/addon/addon.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
- voice
- Porcupine Keyword Spotter
- This voice service allows you to use the PicoVoice product Porcupine as your keyword spotter in openHAB.
- hybrid
-
- org.openhab.voice.procupineks
-
-
-
-
diff --git a/bundles/org.openhab.voice.porcupineks/src/main/resources/OH-INF/config/config.xml b/bundles/org.openhab.voice.porcupineks/src/main/resources/OH-INF/config/config.xml
deleted file mode 100644
index 1022deaceb239..0000000000000
--- a/bundles/org.openhab.voice.porcupineks/src/main/resources/OH-INF/config/config.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
-
-
- API key from PicoVoice, required to use Porcupine.
-
-
-
- Spot sensitivity, a higher sensitivity reduces miss rate at the cost of increased false detection rate.
- 0.5
-
-
-
-
diff --git a/bundles/org.openhab.voice.porcupineks/src/main/resources/OH-INF/i18n/porcupineks.properties b/bundles/org.openhab.voice.porcupineks/src/main/resources/OH-INF/i18n/porcupineks.properties
deleted file mode 100644
index 1cad397549e68..0000000000000
--- a/bundles/org.openhab.voice.porcupineks/src/main/resources/OH-INF/i18n/porcupineks.properties
+++ /dev/null
@@ -1,8 +0,0 @@
-voice.config.porcupineks.apiKey.label = Pico Voice API Key
-voice.config.porcupineks.apiKey.description = API key from PicoVoice, required to use Porcupine.
-voice.config.porcupineks.sensitivity.label = Sensitivity
-voice.config.porcupineks.sensitivity.description = Spot sensitivity, a higher sensitivity reduces miss rate at the cost of increased false detection rate.
-
-# service
-
-service.voice.porcupineks.label = Porcupine Keyword Spotter
diff --git a/bundles/org.openhab.voice.porcupineks/src/main/resources/OH-INF/i18n/porcupineks_de.properties b/bundles/org.openhab.voice.porcupineks/src/main/resources/OH-INF/i18n/porcupineks_de.properties
deleted file mode 100644
index ae077da701c13..0000000000000
--- a/bundles/org.openhab.voice.porcupineks/src/main/resources/OH-INF/i18n/porcupineks_de.properties
+++ /dev/null
@@ -1,8 +0,0 @@
-voice.config.porcupineks.apiKey.label = Pico Voice API Key
-voice.config.porcupineks.apiKey.description = API-Schlüssel von PicoVoice, erfordert die Nutzung von Porcupine.
-voice.config.porcupineks.sensitivity.label = Empfindlichkeit
-voice.config.porcupineks.sensitivity.description = Spot-Sensitivität\: Eine höhere Sensitivität verringert die Fehlerquote auf Kosten einer höheren Falscherkennungsrate.
-
-# service
-
-service.voice.porcupineks.label = Porcupine Schlüsselwort-Erkennung
diff --git a/bundles/org.openhab.voice.porcupineks/src/main/resources/OH-INF/i18n/porcupineks_fi.properties b/bundles/org.openhab.voice.porcupineks/src/main/resources/OH-INF/i18n/porcupineks_fi.properties
deleted file mode 100644
index d47bd7e7af8a7..0000000000000
--- a/bundles/org.openhab.voice.porcupineks/src/main/resources/OH-INF/i18n/porcupineks_fi.properties
+++ /dev/null
@@ -1,8 +0,0 @@
-voice.config.porcupineks.apiKey.label = Pico Voice API-avain
-voice.config.porcupineks.apiKey.description = PicoVoicen API-avain, jota tarvitaan Porcupinen käyttöön.
-voice.config.porcupineks.sensitivity.label = Herkkyys
-voice.config.porcupineks.sensitivity.description = Pisteherkkyys, korkeampi arvo vähentää ohimenneitä osumia mutta lisää vääriä vastaavasti vääriä osumia.
-
-# service
-
-service.voice.porcupineks.label = Porcupine avainsanan havaitsija
diff --git a/bundles/org.openhab.voice.porcupineks/src/main/resources/OH-INF/i18n/porcupineks_fr.properties b/bundles/org.openhab.voice.porcupineks/src/main/resources/OH-INF/i18n/porcupineks_fr.properties
deleted file mode 100644
index c86279c8a4d7d..0000000000000
--- a/bundles/org.openhab.voice.porcupineks/src/main/resources/OH-INF/i18n/porcupineks_fr.properties
+++ /dev/null
@@ -1,8 +0,0 @@
-voice.config.porcupineks.apiKey.label = Clé API Pico Voice
-voice.config.porcupineks.apiKey.description = Clé API de PicoVoice, nécessaire pour utiliser Porcupine.
-voice.config.porcupineks.sensitivity.label = Sensibilité
-voice.config.porcupineks.sensitivity.description = Sensibilité de la détection, une sensibilité plus élevée réduit le taux d'échec au prix d'un taux de fausse détection accru.
-
-# service
-
-service.voice.porcupineks.label = Détecteur de mot clé Porcupine
diff --git a/bundles/pom.xml b/bundles/pom.xml
index 3e89512ab55c4..52757f290b5ad 100644
--- a/bundles/pom.xml
+++ b/bundles/pom.xml
@@ -445,7 +445,6 @@
org.openhab.voice.mimicttsorg.openhab.voice.picottsorg.openhab.voice.pollytts
- org.openhab.voice.porcupineksorg.openhab.voice.rustpotterksorg.openhab.voice.voicerssorg.openhab.voice.voskstt