Initial commit.
commit
bbfc5cba1b
|
@ -0,0 +1,80 @@
|
|||
# Created by https://www.toptal.com/developers/gitignore/api/eclipse
|
||||
# Edit at https://www.toptal.com/developers/gitignore?templates=eclipse
|
||||
|
||||
### Eclipse ###
|
||||
.metadata
|
||||
bin/
|
||||
tmp/
|
||||
*.tmp
|
||||
*.bak
|
||||
*.swp
|
||||
*~.nib
|
||||
local.properties
|
||||
.settings/
|
||||
.loadpath
|
||||
.recommenders
|
||||
|
||||
# External tool builders
|
||||
.externalToolBuilders/
|
||||
|
||||
# Locally stored "Eclipse launch configurations"
|
||||
*.launch
|
||||
|
||||
# PyDev specific (Python IDE for Eclipse)
|
||||
*.pydevproject
|
||||
|
||||
# CDT-specific (C/C++ Development Tooling)
|
||||
.cproject
|
||||
|
||||
# CDT- autotools
|
||||
.autotools
|
||||
|
||||
# Java annotation processor (APT)
|
||||
.factorypath
|
||||
|
||||
# PDT-specific (PHP Development Tools)
|
||||
.buildpath
|
||||
|
||||
# sbteclipse plugin
|
||||
.target
|
||||
|
||||
# Tern plugin
|
||||
.tern-project
|
||||
|
||||
# TeXlipse plugin
|
||||
.texlipse
|
||||
|
||||
# STS (Spring Tool Suite)
|
||||
.springBeans
|
||||
|
||||
# Code Recommenders
|
||||
.recommenders/
|
||||
|
||||
# Annotation Processing
|
||||
.apt_generated/
|
||||
.apt_generated_test/
|
||||
|
||||
# Scala IDE specific (Scala & Java development for Eclipse)
|
||||
.cache-main
|
||||
.scala_dependencies
|
||||
.worksheet
|
||||
|
||||
# Uncomment this line if you wish to ignore the project description file.
|
||||
# Typically, this file would be tracked if it contains build/dependency configurations:
|
||||
#.project
|
||||
|
||||
### Eclipse Patch ###
|
||||
# Spring Boot Tooling
|
||||
.sts4-cache/
|
||||
|
||||
# End of https://www.toptal.com/developers/gitignore/api/eclipse
|
||||
|
||||
|
||||
/hc_scripts/
|
||||
hc_scripts
|
||||
hcsound
|
||||
RhasspyIntentLauncher*8883
|
||||
RhasspyIntentLauncher*1883
|
||||
keystore.jks
|
||||
res
|
||||
RhasspyIntentLauncher-settings.ini
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="lib" path="lib/activation-1.1.1.wso2v2.jar"/>
|
||||
<classpathentry kind="lib" path="lib/commons-lang3-3.9.jar"/>
|
||||
<classpathentry kind="lib" path="lib/commons-logging-1.2.jar"/>
|
||||
<classpathentry kind="lib" path="lib/httpclient_4.5.6.jar"/>
|
||||
<classpathentry kind="lib" path="lib/java-json.jar"/>
|
||||
<classpathentry kind="lib" path="lib/jcommon-1.0.23.jar"/>
|
||||
<classpathentry kind="lib" path="lib/org.eclipse.paho.client.mqttv3-1.2.1.jar"/>
|
||||
<classpathentry kind="lib" path="C:/Program Files/Java/jdk1.8.0_191/lib/missioncontrol/plugins/com.jrockit.mc.rjmx_5.5.2.174165/lib/mailapi.jar"/>
|
||||
<classpathentry kind="lib" path="C:/Program Files/Java/jdk1.8.0_191/lib/missioncontrol/plugins/com.jrockit.mc.rjmx_5.5.2.174165/lib/smtp.jar"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>RhasspyIntentLauncher</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,302 @@
|
|||
package com.jens.rhasspy.intentlauncher;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
|
||||
import org.eclipse.paho.client.mqttv3.MqttCallbackExtended;
|
||||
import org.eclipse.paho.client.mqttv3.MqttClient;
|
||||
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
|
||||
import org.eclipse.paho.client.mqttv3.MqttException;
|
||||
import org.eclipse.paho.client.mqttv3.MqttMessage;
|
||||
import org.eclipse.paho.client.mqttv3.MqttPersistenceException;
|
||||
import org.eclipse.paho.client.mqttv3.MqttSecurityException;
|
||||
import org.eclipse.paho.client.mqttv3.MqttTopic;
|
||||
|
||||
public class MQTT implements MqttCallbackExtended
|
||||
{
|
||||
final static String clientId = Settings.programName;
|
||||
final static int maximumReconnectionAttempts = -1;
|
||||
protected static ArrayList<String> subscribedTopics = new ArrayList<>();
|
||||
protected static boolean forceReconnection = false;
|
||||
|
||||
static String getServerUri()
|
||||
{
|
||||
if(Settings.mqttClientUseSsl)
|
||||
return "ssl://" + Settings.mqttClientServerHostname + ":" + String.valueOf(Settings.mqttClientServerPort);
|
||||
else
|
||||
return "tcp://" + Settings.mqttClientServerHostname + ":" + String.valueOf(Settings.mqttClientServerPort);
|
||||
}
|
||||
|
||||
static MQTT instance = null;
|
||||
static MqttClient client = null;
|
||||
|
||||
public static MQTT getInstance()
|
||||
{
|
||||
if(instance == null)
|
||||
instance = new MQTT();
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
public MqttClient getClient()
|
||||
{
|
||||
if(client == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
/*
|
||||
* Documentation of options:
|
||||
* https://www.ibm.com/support/knowledgecenter/SSFKSJ_7.5.0/com.ibm.mq.javadoc.doc/WMQMQxrClasses/org/eclipse/paho/client/mqttv3/MqttConnectOptions.html#setKeepAliveInterval(int)
|
||||
*/
|
||||
|
||||
MqttConnectOptions options = new MqttConnectOptions();
|
||||
options.setCleanSession(true);
|
||||
options.setAutomaticReconnect(true);
|
||||
|
||||
if(Settings.mqttClientUseSsl)
|
||||
{
|
||||
// Properties props = new Properties();
|
||||
// props.put("secureProtocol", "TLSv1_method");
|
||||
// options.setSSLProperties(props);
|
||||
// options.setSSLProperties(props);
|
||||
options.setHttpsHostnameVerificationEnabled(true);
|
||||
}
|
||||
|
||||
if(Settings.mqttClientUseAuthentication)
|
||||
{
|
||||
options.setUserName(Settings.mqttClientUsername);
|
||||
options.setPassword(Settings.mqttClientPassword.toCharArray());
|
||||
}
|
||||
client = new MqttClient(getServerUri(), clientId);
|
||||
client.setCallback(this);
|
||||
}
|
||||
catch (MqttException e)
|
||||
{
|
||||
Miscellaneous.logEvent(Miscellaneous.getStackTraceAsString(e), 1);
|
||||
}
|
||||
}
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
public static boolean isTopicSubscribed(String topic)
|
||||
{
|
||||
return subscribedTopics.contains(topic);
|
||||
}
|
||||
|
||||
public static synchronized void subscribe(String topic, boolean force)
|
||||
{
|
||||
// startUpSensorListener();
|
||||
|
||||
if(!subscribedTopics.contains(topic))
|
||||
{
|
||||
if(getInstance().subscribeToTopic(topic))
|
||||
subscribedTopics.add(topic);
|
||||
}
|
||||
else if(force)
|
||||
{
|
||||
if(getInstance().subscribeToTopic(topic))
|
||||
{
|
||||
if(!subscribedTopics.contains(topic))
|
||||
subscribedTopics.add(topic);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static synchronized void unSubscribe(String topic)
|
||||
{
|
||||
if(subscribedTopics.contains(topic))
|
||||
{
|
||||
if(subscribedTopics.contains(topic))
|
||||
{
|
||||
if(getInstance().unsubscribeFromTopic(topic))
|
||||
subscribedTopics.remove(topic);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean subscribeToTopic(String topic)
|
||||
{
|
||||
Miscellaneous.logEvent("Subscribing to topic " + topic, 3);
|
||||
|
||||
try
|
||||
{
|
||||
if(!getClient().isConnected())
|
||||
{
|
||||
Miscellaneous.logEvent("Connecting to MQTT server " + Settings.mqttClientServerHostname + " on port " + String.valueOf(Settings.mqttClientServerPort) + ".", 3);
|
||||
// getClient().setCallback(this);
|
||||
getClient().connect();
|
||||
}
|
||||
|
||||
getClient().subscribe(topic);
|
||||
return true;
|
||||
}
|
||||
catch (MqttException e)
|
||||
{
|
||||
Miscellaneous.logEvent("Error subscribing to topic " + topic + ": " + Miscellaneous.getStackTraceAsString(e), 1);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean unsubscribeFromTopic(String topic)
|
||||
{
|
||||
Miscellaneous.logEvent("Unsubscribing from topic " + topic, 3);
|
||||
|
||||
try
|
||||
{
|
||||
if(getClient().isConnected())
|
||||
{
|
||||
getClient().unsubscribe(topic);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (MqttException e)
|
||||
{
|
||||
Miscellaneous.logEvent(Miscellaneous.getStackTraceAsString(e), 1);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void resubscribeToAll()
|
||||
{
|
||||
Miscellaneous.logEvent("Resubscribing to all topics.", 3);
|
||||
|
||||
unsubscribeFromTopic(Settings.intentMqttPath);
|
||||
subscribeToTopic(Settings.intentMqttPath);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connectionLost(Throwable arg0)
|
||||
{
|
||||
Miscellaneous.logEvent("Connection to MQTT server lost.", 3);
|
||||
Miscellaneous.logEvent("Reason for loss of MQTT connection: " + Miscellaneous.getStackTraceAsString(arg0), 5);
|
||||
|
||||
// Currently set to autoreconnect, but that doesn't always seem to work
|
||||
|
||||
// reconnectManually();
|
||||
}
|
||||
|
||||
synchronized void reconnectManually()
|
||||
{
|
||||
int reconnectionCounter = 1;
|
||||
|
||||
while(!getClient().isConnected())
|
||||
{
|
||||
try
|
||||
{
|
||||
Thread.sleep(10000);
|
||||
}
|
||||
catch(Exception e)
|
||||
{}
|
||||
|
||||
if(!getClient().isConnected())
|
||||
{
|
||||
System.out.println("Trying to reestablish connection to MQTT server. This is attempt number: " + String.valueOf(reconnectionCounter));
|
||||
|
||||
try
|
||||
{
|
||||
if(reconnectionCounter < 20)
|
||||
{
|
||||
// getClient().setCallback(this);
|
||||
getClient().reconnect();
|
||||
}
|
||||
else if((reconnectionCounter >= 20 && reconnectionCounter < maximumReconnectionAttempts) | maximumReconnectionAttempts == -1)
|
||||
{
|
||||
Miscellaneous.logEvent("More than 20 reconnection attempts so far (" + String.valueOf(reconnectionCounter) +"). Doing hard reconnect.", 1);
|
||||
|
||||
forceReconnection = true;
|
||||
|
||||
getClient().disconnectForcibly();
|
||||
client = getClient();
|
||||
getClient().connect();
|
||||
|
||||
resubscribeToAll();
|
||||
}
|
||||
else
|
||||
{
|
||||
String notificationText = "Maximum amount of reconnection attempts to MQTT server reached (" + String.valueOf(maximumReconnectionAttempts) + ") . Aborting.";
|
||||
Miscellaneous.logEvent(notificationText, 2);
|
||||
Miscellaneous.notifyAdminViaEmail(notificationText, false, 2);
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (MqttSecurityException e)
|
||||
{
|
||||
Miscellaneous.logEvent("Reconnection to MQTT server failed: " + Miscellaneous.getStackTraceAsString(e), 1);
|
||||
}
|
||||
catch (MqttException e)
|
||||
{
|
||||
Miscellaneous.logEvent("Reconnection to MQTT server failed: " + Miscellaneous.getStackTraceAsString(e), 1);
|
||||
}
|
||||
}
|
||||
|
||||
reconnectionCounter++;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deliveryComplete(IMqttDeliveryToken arg0)
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void messageArrived(String topic, MqttMessage message) throws Exception
|
||||
{
|
||||
Miscellaneous.logEvent("Received MQTT message from topic: " + topic + ", message: " + message, 3);
|
||||
|
||||
try
|
||||
{
|
||||
Object[] object = new Object[2];
|
||||
object[0] = message;
|
||||
object[1] = topic;
|
||||
|
||||
RhasspyIntentWorker.getInstance().notifyOfNewValues(object);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Miscellaneous.logEvent("Error after receiving MQTT message: " + Miscellaneous.getStackTraceAsString(e), 1);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean publish(String topic, String message)
|
||||
{
|
||||
try
|
||||
{
|
||||
getClient().publish(topic, new MqttMessage(message.getBytes()));
|
||||
return true;
|
||||
}
|
||||
catch (MqttPersistenceException e)
|
||||
{
|
||||
Miscellaneous.logEvent(Miscellaneous.getStackTraceAsString(e), 1);
|
||||
}
|
||||
catch (MqttException e)
|
||||
{
|
||||
Miscellaneous.logEvent(Miscellaneous.getStackTraceAsString(e), 1);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connectComplete(boolean reconnect, String serverURI)
|
||||
{
|
||||
if(reconnect)
|
||||
{
|
||||
Miscellaneous.logEvent("Reconnected to MQTT server " + serverURI, 3);
|
||||
resubscribeToAll();
|
||||
}
|
||||
else
|
||||
{
|
||||
Miscellaneous.logEvent("Connected to MQTT server " + serverURI, 3);
|
||||
if(forceReconnection)
|
||||
{
|
||||
resubscribeToAll();
|
||||
forceReconnection = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,72 @@
|
|||
package com.jens.rhasspy.intentlauncher;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.Socket;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.KeyStore;
|
||||
import java.security.Principal;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.cert.X509Certificate;
|
||||
|
||||
import javax.net.ssl.X509KeyManager;
|
||||
|
||||
public class MyKeyManager implements X509KeyManager {
|
||||
private KeyStore keyStore;
|
||||
private String alias;
|
||||
private char[] password;
|
||||
|
||||
MyKeyManager(String keyStoreFile, char[] password, String alias)
|
||||
throws IOException, GeneralSecurityException
|
||||
{
|
||||
this.alias = alias;
|
||||
this.password = password;
|
||||
InputStream stream = new FileInputStream(keyStoreFile);
|
||||
keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||
keyStore.load(stream, password);
|
||||
}
|
||||
|
||||
public PrivateKey getPrivateKey(String alias) {
|
||||
try {
|
||||
return (PrivateKey) keyStore.getKey(alias, password);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public X509Certificate[] getCertificateChain(String alias) {
|
||||
try {
|
||||
java.security.cert.Certificate[] certs = keyStore.getCertificateChain(alias);
|
||||
if (certs == null || certs.length == 0)
|
||||
return null;
|
||||
X509Certificate[] x509 = new X509Certificate[certs.length];
|
||||
for (int i = 0; i < certs.length; i++)
|
||||
x509[i] = (X509Certificate)certs[i];
|
||||
return x509;
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public String chooseServerAlias(String keyType, Principal[] issuers,
|
||||
Socket socket) {
|
||||
return alias;
|
||||
}
|
||||
|
||||
public String[] getClientAliases(String parm1, Principal[] parm2) {
|
||||
throw new UnsupportedOperationException("Method getClientAliases() not yet implemented.");
|
||||
}
|
||||
|
||||
public String chooseClientAlias(String keyTypes[], Principal[] issuers, Socket socket) {
|
||||
throw new UnsupportedOperationException("Method chooseClientAlias() not yet implemented.");
|
||||
}
|
||||
|
||||
public String[] getServerAliases(String parm1, Principal[] parm2) {
|
||||
return new String[] { alias };
|
||||
}
|
||||
|
||||
public String chooseServerAlias(String parm1, Principal[] parm2) {
|
||||
return alias;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,129 @@
|
|||
package com.jens.rhasspy.intentlauncher;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.cert.CertificateException;
|
||||
|
||||
import javax.net.SocketFactory;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
//import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
|
||||
public class MySSLSocketFactory extends SSLSocketFactory
|
||||
{
|
||||
// private static SSLSocketFactory sf;
|
||||
private static SSLContext context = null;
|
||||
|
||||
public MySSLSocketFactory() throws KeyManagementException, KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException
|
||||
{
|
||||
init();
|
||||
|
||||
}
|
||||
|
||||
private static void init() throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException, CertificateException, IOException
|
||||
{
|
||||
// Security.addProvider(new BouncyCastleProvider());
|
||||
KeyStore keyStore = KeyStore.getInstance("BKS");
|
||||
InputStream is = new FileInputStream(new File("keystore.ks"));
|
||||
char[] keystorePass="insecure".toCharArray();
|
||||
keyStore.load(is,keystorePass);
|
||||
TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
|
||||
tmf.init(keyStore);
|
||||
SSLContext ctx = SSLContext.getInstance("TLS");
|
||||
|
||||
|
||||
ctx.init(null, tmf.getTrustManagers(), null);
|
||||
// sf = ctx.getSocketFactory();
|
||||
|
||||
final SSLContext context = SSLContext.getInstance("SSL");
|
||||
context.init(null, tmf.getTrustManagers(), new SecureRandom());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(Socket arg0, String arg1, int arg2, boolean arg3) throws IOException
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getDefaultCipherSuites()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getSupportedCipherSuites()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(String arg0, int arg1) throws IOException, UnknownHostException
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(InetAddress arg0, int arg1) throws IOException
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(String arg0, int arg1, InetAddress arg2, int arg3) throws IOException, UnknownHostException
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(InetAddress arg0, int arg1, InetAddress arg2, int arg3) throws IOException
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public static SocketFactory getDefault()
|
||||
{
|
||||
if(context == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
init();
|
||||
}
|
||||
catch (KeyManagementException e)
|
||||
{
|
||||
Miscellaneous.logEvent(Miscellaneous.getStackTraceAsString(e), 1);
|
||||
}
|
||||
catch (KeyStoreException e)
|
||||
{
|
||||
Miscellaneous.logEvent(Miscellaneous.getStackTraceAsString(e), 1);
|
||||
}
|
||||
catch (NoSuchAlgorithmException e)
|
||||
{
|
||||
Miscellaneous.logEvent(Miscellaneous.getStackTraceAsString(e), 1);
|
||||
}
|
||||
catch (CertificateException e)
|
||||
{
|
||||
Miscellaneous.logEvent(Miscellaneous.getStackTraceAsString(e), 1);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
Miscellaneous.logEvent(Miscellaneous.getStackTraceAsString(e), 1);
|
||||
}
|
||||
}
|
||||
|
||||
return context.getSocketFactory();
|
||||
}
|
||||
/* delegate SSLSocketFactory public methods to sf */
|
||||
// ssf.setHostnameVerifier(MySSLSocketFactory.STRICT_HOSTNAME_VERIFIER);
|
||||
}
|
|
@ -0,0 +1,392 @@
|
|||
package com.jens.rhasspy.intentlauncher;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.eclipse.paho.client.mqttv3.MqttMessage;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import jdk.nashorn.internal.parser.JSONParser;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
|
||||
public class RhasspyIntentWorker implements Runnable
|
||||
{
|
||||
protected static final int silentRcCode = 99;
|
||||
protected static final String siteIdString = "siteId";
|
||||
protected static final String topicNameSpeakCommand = "hermes/tts/say";
|
||||
protected static final String topicNameEndSession = "hermes/dialogueManager/endSession";
|
||||
|
||||
protected static RhasspyIntentWorker instance;
|
||||
|
||||
public boolean requestUpdates()
|
||||
{
|
||||
// MQTT.subscribe(this, topicToSubscribeTo);
|
||||
return true;
|
||||
}
|
||||
|
||||
public RhasspyIntentWorker()
|
||||
{
|
||||
instance = this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
Thread.setDefaultUncaughtExceptionHandler(Miscellaneous.getUncaughtExceptionHandler(3));
|
||||
|
||||
try
|
||||
{
|
||||
Miscellaneous.logEvent("Subscribing to MQTT topic " + Settings.intentMqttPath + "...", 3);
|
||||
MQTT.subscribe(Settings.intentMqttPath, false);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Miscellaneous.logEvent("Unknown error in sensor: " + e.getMessage(), 1);
|
||||
Miscellaneous.logEvent(Miscellaneous.getStackTraceAsString(e), 1);
|
||||
}
|
||||
}
|
||||
|
||||
/*public static boolean switchMatrixLeds(String scriptPath, String stateString)
|
||||
{
|
||||
long speakTimeOut = 10000;
|
||||
|
||||
Miscellaneous.logEvent("Running led script \"" + scriptPath + "\"", 5);
|
||||
String commandToExecute = Settings.voiceInterfaceLedScriptPath.replace(Settings.settingsTtsLedStateVariable, stateString);
|
||||
|
||||
Object[] returnObject = Miscellaneous.runExternalApplication(commandToExecute, speakTimeOut, null, null);
|
||||
|
||||
int rc = (int)returnObject[0];
|
||||
String output = (String)returnObject[1];
|
||||
|
||||
if(returnObject != null)
|
||||
Miscellaneous.logEvent("Result of external execution: Command=" + commandToExecute + ", RC=" + String.valueOf(rc) + ", output: " + Miscellaneous.lineSeparator + output, 3);
|
||||
|
||||
return rc==0;
|
||||
}
|
||||
|
||||
public static boolean playSoundFile(String targetSystem, String soundFilePath)
|
||||
{
|
||||
long speakTimeOut = 10000;
|
||||
|
||||
Miscellaneous.logEvent("Playing sound file \"" + soundFilePath + "\" using command " + Settings.voiceInterfacePlaySoundPath, 5);
|
||||
|
||||
String commandToExecute = Settings.voiceInterfacePlaySoundPath.replace("<targetSystem>", targetSystem);
|
||||
commandToExecute = Settings.voiceInterfacePlaySoundPath.replace(Settings.settingsTtsSoundFileVariable, "\"" + soundFilePath + "\"");
|
||||
|
||||
Object[] returnObject = Miscellaneous.runExternalApplication(commandToExecute, speakTimeOut, null, null);
|
||||
|
||||
int rc = (int)returnObject[0];
|
||||
String output = (String)returnObject[1];
|
||||
|
||||
if(returnObject != null)
|
||||
Miscellaneous.logEvent("Result of external execution: Command=" + commandToExecute + ", RC=" + String.valueOf(rc) + ", output: " + Miscellaneous.lineSeparator + output, 3);
|
||||
|
||||
return rc==0;
|
||||
}*/
|
||||
|
||||
/*
|
||||
*
|
||||
RHASSPY FORMAT:
|
||||
|
||||
Topic: rhasspy/intent/SwitchDevice OR hermes/intent/SwitchDevice
|
||||
|
||||
Payload:
|
||||
{
|
||||
"sessionId": "",
|
||||
"siteId": "default",
|
||||
"input": "stern aus schalten",
|
||||
"intent": {"intentName": "SwitchDevice", "confidenceScore": 1.0},
|
||||
"slots":
|
||||
[
|
||||
{
|
||||
"slotName": "deviceName", "confidence": 1,
|
||||
"value": {"kind": "deviceName", "value": "stern"},
|
||||
"rawValue": "stern"
|
||||
},
|
||||
{
|
||||
"slotName": "onOffState", "confidence": 1,
|
||||
"value": {"kind": "onOffState", "value": "aus"},
|
||||
"rawValue": "aus"
|
||||
}
|
||||
],
|
||||
"asrTokens": [],
|
||||
"asrConfidence": 1
|
||||
}
|
||||
|
||||
|
||||
NEW
|
||||
|
||||
{
|
||||
"input": "sag mir die uhrzeit",
|
||||
"intent":
|
||||
{
|
||||
"intentName": "GetTime",
|
||||
"confidenceScore": 1.0
|
||||
},
|
||||
"siteId": "satellite02",
|
||||
"id": null,
|
||||
"slots": [],
|
||||
"sessionId": "satellite02-porcupine-e1c9281b-9e0b-4524-b24e-132046bf8a6f",
|
||||
"customData": null,
|
||||
"asrTokens": [
|
||||
[
|
||||
{
|
||||
"value": "sag",
|
||||
"confidence": 1.0,
|
||||
"rangeStart": 0,
|
||||
"rangeEnd": 3,
|
||||
"time": null
|
||||
},
|
||||
{
|
||||
"value": "mir",
|
||||
"confidence": 1.0,
|
||||
"rangeStart": 4,
|
||||
"rangeEnd": 7,
|
||||
"time": null
|
||||
},
|
||||
{
|
||||
"value": "die",
|
||||
"confidence": 1.0,
|
||||
"rangeStart": 8,
|
||||
"rangeEnd": 11,
|
||||
"time": null
|
||||
},
|
||||
{
|
||||
"value": "uhrzeit",
|
||||
"confidence": 1.0,
|
||||
"rangeStart": 12,
|
||||
"rangeEnd": 19,
|
||||
"time": null
|
||||
}
|
||||
]
|
||||
],
|
||||
"asrConfidence": null,
|
||||
"rawInput": "sag mir die uhrzeit",
|
||||
"wakewordId": "porcupine",
|
||||
"lang": null
|
||||
}
|
||||
*/
|
||||
|
||||
public void notifyOfNewValues(Object result)
|
||||
{
|
||||
/*
|
||||
* object[0] = message;
|
||||
* object[1] = topic;
|
||||
*/
|
||||
|
||||
Object[] results = (Object[])result;
|
||||
|
||||
String siteId = null;
|
||||
|
||||
MqttMessage message = (MqttMessage)results[0];
|
||||
String topic = (String)results[1];
|
||||
|
||||
Miscellaneous.logEvent("New MQTT message on topic " + topic, 3);
|
||||
|
||||
try
|
||||
{
|
||||
Map<String,String> slotMap = new HashMap<>();
|
||||
String payloadString = new String(message.getPayload());
|
||||
if(!StringUtils.isEmpty(payloadString) && (!payloadString.trim().startsWith("{") || !payloadString.trim().endsWith("}")))
|
||||
Miscellaneous.logEvent("Empty or invalid payload", 1);
|
||||
else
|
||||
{
|
||||
// EXTRACT PARAMATERS
|
||||
JSONObject jsonObject = new JSONObject(new String(message.getPayload(), StandardCharsets.UTF_8));
|
||||
|
||||
if(jsonObject.has(siteIdString))
|
||||
{
|
||||
siteId = jsonObject.getString(siteIdString);
|
||||
slotMap.put(siteIdString, siteId);
|
||||
}
|
||||
|
||||
if(jsonObject.has("slots"))
|
||||
{
|
||||
JSONArray jsonArray = jsonObject.getJSONArray("slots");
|
||||
for(int i = 0; i < jsonArray.length(); i++)
|
||||
{
|
||||
JSONObject ob = jsonArray.getJSONObject(i);
|
||||
String sn = ob.getString("slotName");
|
||||
String val = ob.getJSONObject("value").getString("value");
|
||||
Miscellaneous.logEvent("Found slot " + sn + " with value " + val, 5);
|
||||
slotMap.put(sn, val);
|
||||
}
|
||||
}
|
||||
|
||||
// CHECK INTENT
|
||||
if(slotMap.containsKey(siteIdString))
|
||||
{
|
||||
for(String is : Settings.ignoredSatellites.split(","))
|
||||
if(slotMap.get(siteIdString).equals(is)) //ignore the requests, currently master always cc'd
|
||||
return;
|
||||
}
|
||||
|
||||
String subtopic = topic.substring(topic.lastIndexOf("/") + 1);
|
||||
|
||||
/*
|
||||
* Check if there is an external script under the name of the topic
|
||||
*/
|
||||
boolean scriptFound = false;
|
||||
File scriptsFolder = new File(Settings.scriptsPath);
|
||||
if(scriptsFolder.exists() && scriptsFolder.isDirectory())
|
||||
{
|
||||
for(File script : scriptsFolder.listFiles())
|
||||
{
|
||||
Miscellaneous.logEvent("Checking if scripts file " + script.getAbsolutePath() + " applies for " + subtopic, 5);
|
||||
boolean applies = false;
|
||||
|
||||
if(script.getName().equalsIgnoreCase(subtopic))
|
||||
applies = true;
|
||||
else
|
||||
{
|
||||
if(script.getName().contains("."))
|
||||
{
|
||||
String nameWithoutSuffix = script.getName().substring(0, script.getName().lastIndexOf("."));
|
||||
if(nameWithoutSuffix.equalsIgnoreCase(subtopic))
|
||||
applies = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(applies) // name matches -> run it
|
||||
{
|
||||
scriptFound = true;
|
||||
String executionPath = script.getAbsolutePath();
|
||||
if(script.getAbsolutePath().endsWith(".jar"))
|
||||
executionPath = "java -jar " + executionPath;
|
||||
|
||||
File wd = new File(script.getParent());
|
||||
Miscellaneous.logEvent("Running script " + script.getAbsolutePath() + " to respond to voice command.", 3);
|
||||
|
||||
Object[] response = Miscellaneous.runExternalApplication(executionPath, 10000, wd, slotMap);
|
||||
int rc = (int)response[0];
|
||||
Miscellaneous.logEvent("Execution finished. RC=" + String.valueOf(rc), 3);
|
||||
String output = ((String)response[1]).trim();
|
||||
|
||||
if(rc == 0)
|
||||
playRandomSound(siteId, 0);
|
||||
else if(rc == silentRcCode)
|
||||
; // shut up
|
||||
else
|
||||
playRandomSound(siteId, 1);
|
||||
|
||||
if(!StringUtils.isBlank(output)) // Script returns some command line output
|
||||
{
|
||||
boolean execResult = speak(siteId, output);
|
||||
|
||||
// if(!execResult)
|
||||
// playRandomSound(siteId, 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
Miscellaneous.logEvent(subtopic + " cannot be found in file name " + script.getName(), 5);
|
||||
}
|
||||
|
||||
if(!scriptFound)
|
||||
{
|
||||
Miscellaneous.logEvent("No matching script found in directory.", 3);
|
||||
// Currently deactivated. If we're here an entirely different application my have successfully handled the request already.
|
||||
// playRandomSound(siteId, 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Miscellaneous.logEvent("Scripts folder " + scriptsFolder.getAbsolutePath() + " not found.", 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Miscellaneous.logEvent("Error while processing voice command: " + Miscellaneous.getStackTraceAsString(e), 1);
|
||||
playRandomSound(siteId, 1);
|
||||
}
|
||||
|
||||
//TODO: close session somehow
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
public static RhasspyIntentWorker getInstance()
|
||||
{
|
||||
return instance;
|
||||
}
|
||||
|
||||
public boolean speak(String siteId, String text)
|
||||
{
|
||||
/*
|
||||
* {
|
||||
"text":"dies ist eine testnachricht",
|
||||
"siteId":"default",
|
||||
"lang":"de-DE",
|
||||
"id":"cf9320fc-f5d4-4436-8347-cbbb552c4722",
|
||||
"session_id": "",
|
||||
"volume":"1.0"
|
||||
}
|
||||
*/
|
||||
|
||||
String fullMessage = "{\r\n\"text\":\"" + text + "\",\r\n" +
|
||||
" \"siteId\":\"" + siteId + "\",\r\n" +
|
||||
" \"lang\":\"" + Settings.language + "\",\r\n" +
|
||||
" \"id\":\"cf9320fc-f5d4-4436-8347-cbbb552c4722\",\r\n" +
|
||||
" \"session_id\": \"\",\r\n" +
|
||||
" \"volume\":\"1.0\"\r\n}";
|
||||
|
||||
|
||||
return MQTT.getInstance().publish(topicNameSpeakCommand, fullMessage);
|
||||
}
|
||||
|
||||
void playRandomSound(String targetSystem, int type)
|
||||
{
|
||||
String topic = "hermes/audioServer/" + targetSystem + "/playBytes/0";
|
||||
|
||||
File soundDir;
|
||||
switch(type)
|
||||
{
|
||||
case 0:
|
||||
soundDir = new File("./sound/confirm");
|
||||
break;
|
||||
case 1:
|
||||
soundDir = new File("./sound/error");
|
||||
break;
|
||||
default:
|
||||
soundDir = new File("./sound/other");
|
||||
break;
|
||||
}
|
||||
|
||||
if(soundDir.exists() && soundDir.isDirectory() && soundDir.listFiles().length > 0)
|
||||
{
|
||||
File[] sounds = soundDir.listFiles();
|
||||
int rnd = new Random().nextInt(sounds.length);
|
||||
// switchMatrixLeds(Settings.voiceInterfaceLedScriptPath, stateString);
|
||||
|
||||
File soundToPlay = sounds[rnd];
|
||||
|
||||
Miscellaneous.logEvent("Playing sound file \"" + soundToPlay.getAbsolutePath() + "\" using MQTT to topic " + topic + ".", 4);
|
||||
|
||||
try
|
||||
{
|
||||
byte[] fileContent = Files.readAllBytes(soundToPlay.toPath());
|
||||
|
||||
MqttMessage message = new MqttMessage(fileContent);
|
||||
MQTT.getInstance().getClient().publish(topic, message);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Miscellaneous.logEvent(Miscellaneous.getStackTraceAsString(e), 1);
|
||||
}
|
||||
|
||||
Miscellaneous.logEvent("Done playing sound file \"" + soundToPlay.getAbsolutePath() + "\" using MQTT to topic " + topic + ".", 4);
|
||||
}
|
||||
else
|
||||
Miscellaneous.logEvent("No sound file found to play at " + soundDir.getAbsolutePath() + ".", 3);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,170 @@
|
|||
package com.jens.rhasspy.intentlauncher;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.util.Properties;
|
||||
|
||||
public class Settings
|
||||
{
|
||||
/*
|
||||
* Unchangable stuff:
|
||||
*/
|
||||
public static final String programName = "RhasspyIntentLauncher";
|
||||
final static String logFileName = programName + "LogFile.txt";
|
||||
final static int logFilesAmount = 1;
|
||||
final static int maxLogSize = Settings.logMaxSize * 1024 * 1024;
|
||||
final static boolean logAppend = true;
|
||||
public static final String settingsFileName = programName + "-settings.ini";
|
||||
public final static String settingsTtsLedStateVariable = "<state>";
|
||||
public final static String settingsTtsSoundFileVariable = "<soundFilePath>";
|
||||
public final static long notificationWaitPeriod = 60*60*24;
|
||||
public final static int programVersion = 1;
|
||||
/*
|
||||
* Unchangable stuff:
|
||||
*/
|
||||
|
||||
public static final boolean default_sslDebug = false;
|
||||
public static final String default_keystoreFilename = "keystore.jks";
|
||||
public static final String default_keystorePassword = "keystorePassword";
|
||||
public static final String default_dateFormat = "dd.MM.yyyy HH:mm:ss:SSSS";
|
||||
public static final boolean default_logFileEnabled = false;
|
||||
public static final String default_logFolderPath = "/var/log/homecontrol";
|
||||
public static final int default_logLevel = 3;
|
||||
public static final int default_logMaxSize = 5;
|
||||
public static final String default_encryptionKey="choose_a_password";
|
||||
public static final String default_language = "en-US";
|
||||
public static final String default_intentMqttPath = "hermes/intent/#";
|
||||
public static final boolean default_notificationsEnabled = true;
|
||||
public static final int default_notificationVerbosity = 2;
|
||||
public static final String default_notificationFromAddress = "admin@localhost.com";
|
||||
public static final String default_notificationToAddress = "admin@localhost.com";
|
||||
public static final String default_notificationMailServer = "smtp.host.com";
|
||||
public static final int default_notificationMailServerPort = 25;
|
||||
public static final String default_notificationEncryptionType = "starttls";
|
||||
public static final boolean default_notificationAuthenticate = false;
|
||||
public static final String default_notificationUsername = "smtpUsername";
|
||||
public static final String default_notificationPassword = "smtpPassword";
|
||||
public static final String default_mqttClientServerHostname = "";
|
||||
public static final int default_mqttClientServerPort = 1883;
|
||||
public static final boolean default_mqttClientUseSsl = false;
|
||||
public static final boolean default_mqttClientUseAuthentication = false;
|
||||
public static final String default_mqttClientUsername = "";
|
||||
public static final String default_mqttClientPassword = "";
|
||||
public static final String default_voiceInterfaceLedScriptPath = "/home/pi/lite_js/ledPattern.js";
|
||||
public static final String default_scriptsPath = "/home/pi/rhasspy-scripts";
|
||||
public static final String default_ignoredSatellites = "master";
|
||||
|
||||
public static String intentMqttPath;
|
||||
public static String language;
|
||||
public static boolean sslDebug;
|
||||
public static String keystoreFilename;
|
||||
public static String keystorePassword;
|
||||
|
||||
public static String dateFormat = default_dateFormat;
|
||||
|
||||
public static boolean logFileEnabled;
|
||||
public static String logFolderPath;
|
||||
public static int logLevel = 5; // Set a default value as logging is performed before settings can be loaded.
|
||||
public static int logMaxSize = 5; // Set a default value as logging is performed before settings can be loaded.
|
||||
|
||||
public static String scriptsPath;
|
||||
|
||||
public static boolean notificationsEnabled;
|
||||
public static int notificationVerbosity;
|
||||
public static String notificationFromAddress;
|
||||
public static String notificationToAddress;
|
||||
public static String notificationMailServer;
|
||||
public static int notificationMailServerPort;
|
||||
public static String notificationEncryptionType;
|
||||
public static boolean notificationAuthenticate;
|
||||
public static String notificationUsername;
|
||||
public static String notificationPassword;
|
||||
|
||||
public static String mqttClientServerHostname;
|
||||
public static int mqttClientServerPort;
|
||||
public static boolean mqttClientUseSsl;
|
||||
public static boolean mqttClientUseAuthentication;
|
||||
public static String mqttClientUsername;
|
||||
public static String mqttClientPassword;
|
||||
|
||||
public static String ignoredSatellites;
|
||||
|
||||
public static boolean readSettings()
|
||||
{
|
||||
File sFile = new File(settingsFileName);
|
||||
Miscellaneous.logEvent("Loading settings from " + sFile.getAbsolutePath(), 3);
|
||||
|
||||
Properties prop = new Properties();
|
||||
|
||||
try
|
||||
{
|
||||
// Local settings from settings file
|
||||
prop.load(new FileInputStream(sFile));
|
||||
|
||||
intentMqttPath = prop.getProperty("intentMqttPath", default_intentMqttPath);
|
||||
language = prop.getProperty("language", default_language);
|
||||
sslDebug = Boolean.parseBoolean(prop.getProperty("sslDebug", String.valueOf(default_sslDebug)));
|
||||
keystoreFilename = prop.getProperty("keystoreFilename", default_keystoreFilename);
|
||||
keystorePassword = prop.getProperty("keystorePassword", default_keystorePassword);
|
||||
|
||||
logFileEnabled = Boolean.parseBoolean(prop.getProperty("logFileEnabled", String.valueOf(default_logFileEnabled)));
|
||||
logFolderPath = prop.getProperty("logFolderPath", String.valueOf(default_logFolderPath));
|
||||
logLevel = Integer.parseInt(prop.getProperty("logLevel", String.valueOf(default_logLevel)));
|
||||
logMaxSize = Integer.parseInt(prop.getProperty("logMaxSize", String.valueOf(default_logMaxSize)));
|
||||
|
||||
scriptsPath = prop.getProperty("scriptsPath", default_scriptsPath);
|
||||
|
||||
notificationsEnabled = Boolean.parseBoolean(prop.getProperty("notificationsEnabled", String.valueOf(default_notificationsEnabled)));
|
||||
notificationVerbosity = Integer.parseInt(prop.getProperty("notificationVerbosity", String.valueOf(default_notificationVerbosity)));
|
||||
notificationFromAddress = prop.getProperty("notificationFromAddress", default_notificationFromAddress);
|
||||
notificationToAddress = prop.getProperty("notificationToAddress", default_notificationToAddress);
|
||||
notificationMailServer = prop.getProperty("notificationMailServer", default_notificationMailServer);
|
||||
notificationMailServerPort = Integer.parseInt(prop.getProperty("notificationMailServerPort", String.valueOf(default_notificationMailServerPort)));
|
||||
notificationEncryptionType = prop.getProperty("notificationEncryptionType", default_notificationEncryptionType);
|
||||
notificationAuthenticate = Boolean.parseBoolean(prop.getProperty("notificationAuthenticate", String.valueOf(default_notificationAuthenticate)));
|
||||
notificationUsername = prop.getProperty("notificationUsername", default_notificationUsername);
|
||||
notificationPassword = prop.getProperty("notificationPassword", default_notificationPassword);
|
||||
|
||||
mqttClientServerHostname = prop.getProperty("mqttClientServerHostname", default_mqttClientServerHostname);
|
||||
mqttClientServerPort = Integer.parseInt(prop.getProperty("mqttClientServerPort", String.valueOf(default_mqttClientServerPort)));
|
||||
mqttClientUseSsl = Boolean.parseBoolean(prop.getProperty("mqttClientUseSsl", String.valueOf(default_mqttClientUseSsl)));
|
||||
mqttClientUseAuthentication = Boolean.parseBoolean(prop.getProperty("mqttClientUseAuthentication", String.valueOf(default_mqttClientUseAuthentication)));
|
||||
mqttClientUsername = prop.getProperty("mqttClientUsername", default_mqttClientUsername);
|
||||
mqttClientPassword = prop.getProperty("mqttClientPassword", default_mqttClientPassword);
|
||||
ignoredSatellites = prop.getProperty("ignoredSatellites", default_ignoredSatellites);
|
||||
|
||||
if(mqttClientUseSsl)
|
||||
loadKeystore();
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
Miscellaneous.logEvent(Miscellaneous.getStackTraceAsString(e), 1);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
Miscellaneous.logEvent(Miscellaneous.getStackTraceAsString(e), 1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void loadKeystore()
|
||||
{
|
||||
if((new File(Settings.keystoreFilename).exists()))
|
||||
{
|
||||
Miscellaneous.logEvent("Loading keystore " + Settings.keystoreFilename, 3);
|
||||
System.setProperty("javax.net.ssl.keyStore", Settings.keystoreFilename);
|
||||
System.setProperty("javax.net.ssl.keyStorePassword", Settings.keystorePassword);
|
||||
System.setProperty("javax.net.ssl.trustStore", Settings.keystoreFilename);
|
||||
System.setProperty("javax.net.ssl.trustStorePassword", Settings.keystorePassword);
|
||||
// System.setProperty("javax.net.ssl.trustStoreType","JCEKS");
|
||||
}
|
||||
else
|
||||
{
|
||||
Miscellaneous.logEvent("Could not load keystore, file does not exist.", 3);
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
package com.jens.rhasspy.intentlauncher;
|
||||
|
||||
public class Starter
|
||||
{
|
||||
public static void main(String[] args)
|
||||
{
|
||||
if(!Settings.readSettings())
|
||||
{
|
||||
System.out.println("Settings could not be loaded.");
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
if(args.length == 0)
|
||||
{
|
||||
// Start daemon
|
||||
RhasspyIntentWorker server = new RhasspyIntentWorker();
|
||||
Thread t = new Thread(server);
|
||||
t.start();
|
||||
|
||||
/*
|
||||
* We just need to stay alive here. The thread just opened will do the actual work.
|
||||
*/
|
||||
/*while(true)
|
||||
{
|
||||
try
|
||||
{
|
||||
Thread.sleep(5000);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
|
||||
}
|
||||
}*/
|
||||
}
|
||||
else
|
||||
{
|
||||
// for(int i=0; i<args.length; i++)
|
||||
// System.out.println("Args " + String.valueOf(i) + ": " + args[i]);
|
||||
|
||||
switch(args[0])
|
||||
{
|
||||
case "-testEmailNotification":
|
||||
testEmailNotification();
|
||||
break;
|
||||
case "-getVersion":
|
||||
System.out.println(Settings.programVersion);
|
||||
break;
|
||||
default:
|
||||
System.out.println("Unknown parameters.");
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void testEmailNotification()
|
||||
{
|
||||
Settings.readSettings();
|
||||
|
||||
if(Miscellaneous.notifyAdminViaEmail("Test notification from " + Settings.programName + ".", true, 1))
|
||||
{
|
||||
System.out.println("Mail notification successfull.");
|
||||
System.exit(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
System.out.println("Mail notification failed.");
|
||||
}
|
||||
|
||||
System.exit(7);
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,45 @@
|
|||
package com.jens.rhasspy.lib;
|
||||
|
||||
/**
|
||||
* The JSONException is thrown by the JSON.org classes when things are amiss.
|
||||
*
|
||||
* @author JSON.org
|
||||
* @version 2015-12-09
|
||||
*/
|
||||
public class JSONException extends RuntimeException {
|
||||
/** Serialization ID */
|
||||
private static final long serialVersionUID = 0;
|
||||
|
||||
/**
|
||||
* Constructs a JSONException with an explanatory message.
|
||||
*
|
||||
* @param message
|
||||
* Detail about the reason for the exception.
|
||||
*/
|
||||
public JSONException(final String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a JSONException with an explanatory message and cause.
|
||||
*
|
||||
* @param message
|
||||
* Detail about the reason for the exception.
|
||||
* @param cause
|
||||
* The cause.
|
||||
*/
|
||||
public JSONException(final String message, final Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new JSONException with the specified cause.
|
||||
*
|
||||
* @param cause
|
||||
* The cause.
|
||||
*/
|
||||
public JSONException(final Throwable cause) {
|
||||
super(cause.getMessage(), cause);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,542 @@
|
|||
package com.jens.rhasspy.lib;
|
||||
|
||||
/*
|
||||
Copyright (c) 2008 JSON.org
|
||||
|
||||
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 shall be used for Good, not Evil.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This provides static methods to convert an XML text into a JSONArray or
|
||||
* JSONObject, and to covert a JSONArray or JSONObject into an XML text using
|
||||
* the JsonML transform.
|
||||
*
|
||||
* @author JSON.org
|
||||
* @version 2016-01-30
|
||||
*/
|
||||
public class JSONML {
|
||||
/**
|
||||
* Parse XML values and store them in a JSONArray.
|
||||
* @param x The XMLTokener containing the source string.
|
||||
* @param arrayForm true if array form, false if object form.
|
||||
* @param ja The JSONArray that is containing the current tag or null
|
||||
* if we are at the outermost level.
|
||||
* @param keepStrings Don't type-convert text nodes and attribute values
|
||||
* @return A JSONArray if the value is the outermost tag, otherwise null.
|
||||
* @throws JSONException
|
||||
*/
|
||||
private static Object parse(
|
||||
XMLTokener x,
|
||||
boolean arrayForm,
|
||||
JSONArray ja,
|
||||
boolean keepStrings
|
||||
) throws JSONException {
|
||||
String attribute;
|
||||
char c;
|
||||
String closeTag = null;
|
||||
int i;
|
||||
JSONArray newja = null;
|
||||
JSONObject newjo = null;
|
||||
Object token;
|
||||
String tagName = null;
|
||||
|
||||
// Test for and skip past these forms:
|
||||
// <!-- ... -->
|
||||
// <![ ... ]]>
|
||||
// <! ... >
|
||||
// <? ... ?>
|
||||
|
||||
while (true) {
|
||||
if (!x.more()) {
|
||||
throw x.syntaxError("Bad XML");
|
||||
}
|
||||
token = x.nextContent();
|
||||
if (token == XML.LT) {
|
||||
token = x.nextToken();
|
||||
if (token instanceof Character) {
|
||||
if (token == XML.SLASH) {
|
||||
|
||||
// Close tag </
|
||||
|
||||
token = x.nextToken();
|
||||
if (!(token instanceof String)) {
|
||||
throw new JSONException(
|
||||
"Expected a closing name instead of '" +
|
||||
token + "'.");
|
||||
}
|
||||
if (x.nextToken() != XML.GT) {
|
||||
throw x.syntaxError("Misshaped close tag");
|
||||
}
|
||||
return token;
|
||||
} else if (token == XML.BANG) {
|
||||
|
||||
// <!
|
||||
|
||||
c = x.next();
|
||||
if (c == '-') {
|
||||
if (x.next() == '-') {
|
||||
x.skipPast("-->");
|
||||
} else {
|
||||
x.back();
|
||||
}
|
||||
} else if (c == '[') {
|
||||
token = x.nextToken();
|
||||
if (token.equals("CDATA") && x.next() == '[') {
|
||||
if (ja != null) {
|
||||
ja.put(x.nextCDATA());
|
||||
}
|
||||
} else {
|
||||
throw x.syntaxError("Expected 'CDATA['");
|
||||
}
|
||||
} else {
|
||||
i = 1;
|
||||
do {
|
||||
token = x.nextMeta();
|
||||
if (token == null) {
|
||||
throw x.syntaxError("Missing '>' after '<!'.");
|
||||
} else if (token == XML.LT) {
|
||||
i += 1;
|
||||
} else if (token == XML.GT) {
|
||||
i -= 1;
|
||||
}
|
||||
} while (i > 0);
|
||||
}
|
||||
} else if (token == XML.QUEST) {
|
||||
|
||||
// <?
|
||||
|
||||
x.skipPast("?>");
|
||||
} else {
|
||||
throw x.syntaxError("Misshaped tag");
|
||||
}
|
||||
|
||||
// Open tag <
|
||||
|
||||
} else {
|
||||
if (!(token instanceof String)) {
|
||||
throw x.syntaxError("Bad tagName '" + token + "'.");
|
||||
}
|
||||
tagName = (String)token;
|
||||
newja = new JSONArray();
|
||||
newjo = new JSONObject();
|
||||
if (arrayForm) {
|
||||
newja.put(tagName);
|
||||
if (ja != null) {
|
||||
ja.put(newja);
|
||||
}
|
||||
} else {
|
||||
newjo.put("tagName", tagName);
|
||||
if (ja != null) {
|
||||
ja.put(newjo);
|
||||
}
|
||||
}
|
||||
token = null;
|
||||
for (;;) {
|
||||
if (token == null) {
|
||||
token = x.nextToken();
|
||||
}
|
||||
if (token == null) {
|
||||
throw x.syntaxError("Misshaped tag");
|
||||
}
|
||||
if (!(token instanceof String)) {
|
||||
break;
|
||||
}
|
||||
|
||||
// attribute = value
|
||||
|
||||
attribute = (String)token;
|
||||
if (!arrayForm && ("tagName".equals(attribute) || "childNode".equals(attribute))) {
|
||||
throw x.syntaxError("Reserved attribute.");
|
||||
}
|
||||
token = x.nextToken();
|
||||
if (token == XML.EQ) {
|
||||
token = x.nextToken();
|
||||
if (!(token instanceof String)) {
|
||||
throw x.syntaxError("Missing value");
|
||||
}
|
||||
newjo.accumulate(attribute, keepStrings ? ((String)token) :XML.stringToValue((String)token));
|
||||
token = null;
|
||||
} else {
|
||||
newjo.accumulate(attribute, "");
|
||||
}
|
||||
}
|
||||
if (arrayForm && newjo.length() > 0) {
|
||||
newja.put(newjo);
|
||||
}
|
||||
|
||||
// Empty tag <.../>
|
||||
|
||||
if (token == XML.SLASH) {
|
||||
if (x.nextToken() != XML.GT) {
|
||||
throw x.syntaxError("Misshaped tag");
|
||||
}
|
||||
if (ja == null) {
|
||||
if (arrayForm |