Initial commit
This commit is contained in:
commit
016dbb5406
5
README.md
Normal file
5
README.md
Normal file
@ -0,0 +1,5 @@
|
||||
# Rhasspy visual conversation helper
|
||||
|
||||
This application is supposed to work as a visual helper for Rhasspy conversations on setups that have a screen or even a touchscreen.
|
||||
|
||||
See more information and detailed instructions on https://server47.de/rhasspy/
|
26
RhasspyVisualConversationTool/.classpath
Normal file
26
RhasspyVisualConversationTool/.classpath
Normal file
@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER">
|
||||
<attributes>
|
||||
<attribute name="module" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<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">
|
||||
<attributes>
|
||||
<attribute name="module" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<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">
|
||||
<attributes>
|
||||
<attribute name="module" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="lib" path="lib/commons-lang3-3.9.jar">
|
||||
<attributes>
|
||||
<attribute name="module" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="lib" path="lib/org.eclipse.paho.client.mqttv3-1.2.1.jar"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
77
RhasspyVisualConversationTool/.gitignore
vendored
Normal file
77
RhasspyVisualConversationTool/.gitignore
vendored
Normal file
@ -0,0 +1,77 @@
|
||||
|
||||
# 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
|
||||
|
||||
RhasspyVisualConversationTool*8883
|
||||
RhasspyVisualConversationTool*1883
|
||||
keystore.jks
|
||||
res
|
||||
RhasspyVisualConversationTool-settings.ini
|
17
RhasspyVisualConversationTool/.project
Normal file
17
RhasspyVisualConversationTool/.project
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>RhasspyVisualConversationTool</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>
|
BIN
RhasspyVisualConversationTool/lib/commons-lang3-3.9.jar
Normal file
BIN
RhasspyVisualConversationTool/lib/commons-lang3-3.9.jar
Normal file
Binary file not shown.
Binary file not shown.
@ -0,0 +1,308 @@
|
||||
package com.jens.rhasspy.visualtool;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Font;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseListener;
|
||||
import java.util.ArrayList;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollBar;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTextArea;
|
||||
import javax.swing.border.Border;
|
||||
import javax.swing.border.CompoundBorder;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
|
||||
import org.eclipse.paho.client.mqttv3.MqttMessage;
|
||||
import org.eclipse.paho.client.mqttv3.MqttTopic;
|
||||
|
||||
import com.jens.rhasspy.visualtool.lib.JSONObject;
|
||||
|
||||
/*
|
||||
* Layout types
|
||||
* https://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html
|
||||
*/
|
||||
|
||||
public class GUI
|
||||
{
|
||||
static JFrame mainFrame = new JFrame(Settings.programName);
|
||||
static JLabel connectionStatusTextField = new JLabel();
|
||||
static JTextArea mainTextField = new JTextArea();
|
||||
static JScrollPane mainTextFieldHolder = new JScrollPane(mainTextField);
|
||||
static JPanel optionsFrame = new JPanel();
|
||||
static GUI instance = null;
|
||||
Font defaultFont = new Font(Font.SANS_SERIF, Font.PLAIN, 20);
|
||||
|
||||
static Dimension defaultContainerDim = new Dimension(700, 250);
|
||||
static Dimension zeroDim = new Dimension(0, 0);
|
||||
|
||||
ArrayList<String> textEntriesList = new ArrayList<>();
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
if(Settings.readSettings())
|
||||
{
|
||||
getInstance().openWindow();
|
||||
|
||||
// Subscribe to MQTT topics
|
||||
|
||||
MQTT.getInstance().subscribeToTopic(Settings.topicNameWakewordRecognized);
|
||||
MQTT.getInstance().subscribeToTopic(Settings.topicNameDisplayText);
|
||||
MQTT.getInstance().subscribeToTopic(Settings.topicNameDisplayOptions);
|
||||
MQTT.getInstance().subscribeToTopic(Settings.topicNameIntentsRecognized);
|
||||
MQTT.getInstance().subscribeToTopic(Settings.topicNameSayText);
|
||||
MQTT.getInstance().subscribeToTopic(Settings.topicNamePlaySoundFinished);
|
||||
MQTT.getInstance().subscribeToTopic(Settings.topicNameSessionEnded);
|
||||
}
|
||||
}
|
||||
|
||||
public static GUI getInstance()
|
||||
{
|
||||
if(instance == null)
|
||||
instance = new GUI();
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void openWindow()
|
||||
{
|
||||
mainFrame.setLayout(new BoxLayout(mainFrame.getContentPane(), BoxLayout.Y_AXIS));
|
||||
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
mainFrame.setSize(700, 320);
|
||||
mainFrame.setLocation(50, 50);
|
||||
|
||||
try
|
||||
{
|
||||
Thread.sleep(1000);
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
Miscellaneous.logEvent(Miscellaneous.getStackTraceAsString(e), 1);
|
||||
}
|
||||
|
||||
connectionStatusTextField.setText("Connected: " + String.valueOf(MQTT.getInstance().getClient().isConnected()));
|
||||
Border border = connectionStatusTextField.getBorder();
|
||||
Border margin = new EmptyBorder(10,10,10,10);
|
||||
connectionStatusTextField.setBorder(new CompoundBorder(border, margin));
|
||||
|
||||
mainTextField.setText("Waiting for session...");
|
||||
mainTextField.setFont(defaultFont);
|
||||
if(mainTextField.isEditable())
|
||||
mainTextField.setEditable(false);
|
||||
Border borderMainTextField = mainTextField.getBorder();
|
||||
Border marginMainTextField = new EmptyBorder(10,10,10,10);
|
||||
mainTextField.setBorder(new CompoundBorder(borderMainTextField, marginMainTextField));
|
||||
|
||||
mainTextFieldHolder.setPreferredSize(defaultContainerDim);
|
||||
mainTextFieldHolder.setVisible(true);
|
||||
optionsFrame.setPreferredSize(defaultContainerDim);
|
||||
optionsFrame.setVisible(false);
|
||||
optionsFrame.setLayout(new BoxLayout(optionsFrame, BoxLayout.Y_AXIS));
|
||||
|
||||
mainFrame.add(connectionStatusTextField);
|
||||
mainFrame.add(mainTextFieldHolder);
|
||||
mainFrame.add(optionsFrame);
|
||||
|
||||
mainFrame.setVisible(true);
|
||||
}
|
||||
|
||||
public void updateConnectionStatus(boolean connected)
|
||||
{
|
||||
if(connected)
|
||||
connectionStatusTextField.setText("Connected to: " + Settings.mqttClientServerHostname);
|
||||
else
|
||||
connectionStatusTextField.setText("Not connected");
|
||||
}
|
||||
|
||||
public void updateWindow()
|
||||
{
|
||||
if(mainTextField.isEditable())
|
||||
mainTextField.setEditable(false);
|
||||
|
||||
mainTextField.setText(Miscellaneous.arrayImplode(Miscellaneous.lineSeparator, textEntriesList));
|
||||
|
||||
JScrollBar vertical = mainTextFieldHolder.getVerticalScrollBar();
|
||||
vertical.setValue(vertical.getMaximum());
|
||||
|
||||
mainFrame.pack();
|
||||
|
||||
mainTextFieldHolder.setVisible(true);
|
||||
optionsFrame.setVisible(false);
|
||||
|
||||
mainFrame.repaint();
|
||||
}
|
||||
|
||||
public void displayOptions(String[] options)
|
||||
{
|
||||
optionsFrame.removeAll();
|
||||
|
||||
JLabel infoLabel = new JLabel("Select an option:");
|
||||
infoLabel.setFont(defaultFont);
|
||||
optionsFrame.add(infoLabel);
|
||||
Border labelBorder = optionsFrame.getBorder();
|
||||
Border labelMargin = new EmptyBorder(10,10,10,10);
|
||||
optionsFrame.setBorder(new CompoundBorder(labelBorder, labelMargin));
|
||||
|
||||
for(String option : options)
|
||||
{
|
||||
JLabel optionTf = new JLabel(option);
|
||||
optionTf.setFont(defaultFont);
|
||||
Border border = optionTf.getBorder();
|
||||
Border margin = new EmptyBorder(10,10,10,10);
|
||||
optionTf.setBorder(new CompoundBorder(border, margin));
|
||||
|
||||
optionTf.addMouseListener(new MouseListener()
|
||||
{
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent e)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExited(MouseEvent e)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseEntered(MouseEvent e)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e)
|
||||
{
|
||||
JOptionPane.showMessageDialog(mainFrame, "Option " + option + " selected.");
|
||||
}
|
||||
});
|
||||
optionsFrame.add(optionTf);
|
||||
}
|
||||
|
||||
// mainTextFieldHolder.setPreferredSize(zeroDim);
|
||||
// optionsFrame.setPreferredSize(defaultContainerDim);
|
||||
|
||||
mainFrame.pack();
|
||||
|
||||
optionsFrame.setVisible(true);
|
||||
mainTextFieldHolder.setVisible(false);
|
||||
|
||||
mainFrame.repaint();
|
||||
}
|
||||
|
||||
public void handleNewMessage(Object[] messageArray)
|
||||
{
|
||||
/*
|
||||
* Object[] object = new Object[3];
|
||||
object[0] = message;
|
||||
object[1] = topic;
|
||||
object[2] = Calendar.getInstance();
|
||||
*/
|
||||
|
||||
String payload = new String(((MqttMessage)messageArray[0]).getPayload());
|
||||
|
||||
String topic = (String)messageArray[1];
|
||||
|
||||
if(MqttTopic.isMatched(Settings.topicNameWakewordRecognized, topic))
|
||||
{
|
||||
// Turn on screen....
|
||||
|
||||
textEntriesList.add(getMeString() + "Hello! What can I do for you?");
|
||||
updateWindow();
|
||||
}
|
||||
else if(MqttTopic.isMatched(Settings.topicNameIntentsRecognized, topic))
|
||||
{
|
||||
JSONObject jo = new JSONObject(payload);
|
||||
textEntriesList.add(getYouString() + jo.getString("input"));
|
||||
updateWindow();
|
||||
}
|
||||
else if(MqttTopic.isMatched(Settings.topicNameDisplayText, topic))
|
||||
{
|
||||
JSONObject jo = new JSONObject(payload);
|
||||
/*
|
||||
* This is deactivated only for test purposes.
|
||||
* Afterwards for a conversation flow sayText needs to be used.
|
||||
*/
|
||||
// textEntriesList.clear();
|
||||
|
||||
textEntriesList.add(getMeString() + jo.getString("text"));
|
||||
updateWindow();
|
||||
}
|
||||
else if(MqttTopic.isMatched(Settings.topicNameDisplayOptions, topic))
|
||||
{
|
||||
JSONObject jo = new JSONObject(payload);
|
||||
/*
|
||||
* This is deactivated only for test purposes.
|
||||
* Afterwards for a conversation flow sayText needs to be used.
|
||||
*/
|
||||
// textEntriesList.clear();
|
||||
|
||||
String[] options = jo.getString("text").split(";");
|
||||
displayOptions(options);
|
||||
|
||||
}
|
||||
else if(MqttTopic.isMatched(Settings.topicNameSayText, topic))
|
||||
{
|
||||
JSONObject jo = new JSONObject(payload);
|
||||
textEntriesList.add(getMeString() + jo.getString("text"));
|
||||
updateWindow();
|
||||
}
|
||||
else if(MqttTopic.isMatched(Settings.topicNameSessionEnded, topic))
|
||||
{
|
||||
textEntriesList.clear();
|
||||
updateWindow();
|
||||
}
|
||||
}
|
||||
|
||||
static String getYouString()
|
||||
{
|
||||
return "You: \t";
|
||||
}
|
||||
|
||||
static String getMeString()
|
||||
{
|
||||
return "Me: \t";
|
||||
}
|
||||
|
||||
static void turnOnScreen()
|
||||
{
|
||||
/*
|
||||
* pi@raspberrypi11:~ $ DISPLAY=:0 xset q
|
||||
Keyboard Control:
|
||||
auto repeat: on key click percent: 0 LED mask: 00000000
|
||||
XKB indicators:
|
||||
00: Caps Lock: off 01: Num Lock: off 02: Scroll Lock: off
|
||||
03: Compose: off 04: Kana: off 05: Sleep: off
|
||||
06: Suspend: off 07: Mute: off 08: Misc: off
|
||||
09: Mail: off 10: Charging: off 11: Shift Lock: off
|
||||
12: Group 2: off 13: Mouse Keys: off
|
||||
auto repeat delay: 500 repeat rate: 33
|
||||
auto repeating keys: 00ffffffdffffbbf
|
||||
fadfffefffedffff
|
||||
9fffffffffffffff
|
||||
fff7ffffffffffff
|
||||
bell percent: 50 bell pitch: 400 bell duration: 100
|
||||
Pointer Control:
|
||||
acceleration: 20/10 threshold: 10
|
||||
Screen Saver:
|
||||
prefer blanking: yes allow exposures: yes
|
||||
timeout: 600 cycle: 600
|
||||
Colors:
|
||||
default colormap: 0x20 BlackPixel: 0x0 WhitePixel: 0xffffff
|
||||
Font Path:
|
||||
built-ins
|
||||
DPMS (Energy Star):
|
||||
Standby: 600 Suspend: 600 Off: 600
|
||||
DPMS is Enabled
|
||||
Monitor is Off
|
||||
pi@raspberrypi11:~ $
|
||||
*/
|
||||
}
|
||||
}
|
@ -0,0 +1,250 @@
|
||||
package com.jens.rhasspy.visualtool;
|
||||
|
||||
import java.util.Calendar;
|
||||
|
||||
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 com.jens.rhasspy.visualtool.lib.JSONObject;
|
||||
|
||||
public class MQTT implements MqttCallbackExtended
|
||||
{
|
||||
/*
|
||||
* Connect to server
|
||||
*
|
||||
* raspberrypi1:1883
|
||||
*
|
||||
* Subscribe to topic
|
||||
*
|
||||
* Topic: zigbee2mqtt/0x00158d0002d72e58
|
||||
* Payload: {"contact":true,"linkquality":84}
|
||||
*
|
||||
* Configuration file:
|
||||
* /opt/zigbee2mqtt/data/configuration.yaml
|
||||
*/
|
||||
|
||||
final static String clientId = "RhasspyVisualConversationTool";
|
||||
final static int maximumReconnectionAttempts = -1;
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@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);
|
||||
|
||||
GUI.getInstance().updateConnectionStatus(false);
|
||||
|
||||
// Currently set to autoreconnect, but that doesn't always seem to work
|
||||
|
||||
// reconnectManually();
|
||||
}
|
||||
|
||||
@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);
|
||||
|
||||
MqttMessageDistributor mmd = new MqttMessageDistributor(topic, message);
|
||||
Thread worker = new Thread(mmd);
|
||||
worker.start();
|
||||
}
|
||||
|
||||
class MqttMessageDistributor implements Runnable
|
||||
{
|
||||
String topic;
|
||||
MqttMessage message;
|
||||
|
||||
public MqttMessageDistributor(String topic, MqttMessage message)
|
||||
{
|
||||
this.topic = topic;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
Thread.setDefaultUncaughtExceptionHandler(Miscellaneous.getUncaughtExceptionHandler(3));
|
||||
|
||||
try
|
||||
{
|
||||
Object[] object = new Object[3];
|
||||
object[0] = message;
|
||||
object[1] = topic;
|
||||
object[2] = Calendar.getInstance();
|
||||
|
||||
Miscellaneous.logEvent("New message received on topic " + object[1] + Miscellaneous.lineSeparator + object[0], 2);
|
||||
|
||||
String message = new String(((MqttMessage)object[0]).getPayload());
|
||||
// if(!StringUtils.isEmpty(message))
|
||||
if(message != null && message.length() > 0)
|
||||
{
|
||||
JSONObject jo = new JSONObject(message);
|
||||
if(jo.has(Settings.jsonObjectStringSiteId))
|
||||
{
|
||||
for(String ignoredSite : Settings.ignoredSatellites.split(";"))
|
||||
{
|
||||
if(ignoredSite.equalsIgnoreCase(jo.getString(Settings.jsonObjectStringSiteId)))
|
||||
{
|
||||
Miscellaneous.logEvent("Ignoring message as it's targeted to " + ignoredSite, 3);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GUI.getInstance().handleNewMessage(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);
|
||||
else
|
||||
Miscellaneous.logEvent("Connected to MQTT server " + serverURI, 3);
|
||||
|
||||
GUI.getInstance().updateConnectionStatus(true);
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,187 @@
|
||||
package com.jens.rhasspy.visualtool;
|
||||
|
||||
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 = "RhasspyVisualConversationTool";
|
||||
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;
|
||||
|
||||
public final static String jsonObjectStringSiteId = "siteId";
|
||||
public final static String jsonObjectStringSessionId = "sessionId";
|
||||
|
||||
public final static String topicNameWakewordRecognized = "hermes/hotword/+/detected";
|
||||
public final static String topicNameDisplayText = "hermes/tts/displayText";
|
||||
public final static String topicNameDisplayOptions = "hermes/tts/displayOptions";
|
||||
public final static String topicNameIntentsRecognized = "hermes/intent/#";
|
||||
public final static String topicNameSayText = "hermes/tts/say";
|
||||
public final static String topicNameSayFinished = "hermes/tts/sayFinished";
|
||||
public static String topicNamePlaySoundFinished = "hermes/audioServer/" + jsonObjectStringSiteId + "/playFinished";
|
||||
public final static String topicNameSessionEnded = "hermes/dialogueManager/sessionEnded";
|
||||
|
||||
/*
|
||||
* 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_ignoredSatellites = "master";
|
||||
public static final String default_siteId = "unknown";
|
||||
|
||||
|
||||
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 String siteId;
|
||||
|
||||
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)));
|
||||
|
||||
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);
|
||||
|
||||
siteId = prop.getProperty("siteId", default_siteId);
|
||||
|
||||
topicNamePlaySoundFinished = topicNamePlaySoundFinished.replace(jsonObjectStringSiteId, siteId);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,45 @@
|
||||
package com.jens.rhasspy.visualtool.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.visualtool.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) {
|
||||
return newja;
|
||||
}
|
||||
return newjo;
|
||||
}
|
||||
|
||||
// Content, between <...> and </...>
|
||||
|
||||
} else {
|
||||
if (token != XML.GT) {
|
||||
throw x.syntaxError("Misshaped tag");
|
||||
}
|
||||
closeTag = (String)parse(x, arrayForm, newja, keepStrings);
|
||||
if (closeTag != null) {
|
||||
if (!closeTag.equals(tagName)) {
|
||||
throw x.syntaxError("Mismatched '" + tagName +
|
||||
"' and '" + closeTag + "'");
|
||||
}
|
||||
tagName = null;
|
||||
if (!arrayForm && newja.length() > 0) {
|
||||
newjo.put("childNodes", newja);
|
||||
}
|
||||
if (ja == null) {
|
||||
if (arrayForm) {
|
||||
return newja;
|
||||
}
|
||||
return newjo;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (ja != null) {
|
||||
ja.put(token instanceof String
|
||||
? keepStrings ? XML.unescape((String)token) :XML.stringToValue((String)token)
|
||||
: token);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert a well-formed (but not necessarily valid) XML string into a
|
||||
* JSONArray using the JsonML transform. Each XML tag is represented as
|
||||
* a JSONArray in which the first element is the tag name. If the tag has
|
||||
* attributes, then the second element will be JSONObject containing the
|
||||
* name/value pairs. If the tag contains children, then strings and
|
||||
* JSONArrays will represent the child tags.
|
||||
* Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored.
|
||||
* @param string The source string.
|
||||
* @return A JSONArray containing the structured data from the XML string.
|
||||
* @throws JSONException Thrown on error converting to a JSONArray
|
||||
*/
|
||||
public static JSONArray toJSONArray(String string) throws JSONException {
|
||||
return (JSONArray)parse(new XMLTokener(string), true, null, false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert a well-formed (but not necessarily valid) XML string into a
|
||||
* JSONArray using the JsonML transform. Each XML tag is represented as
|
||||
* a JSONArray in which the first element is the tag name. If the tag has
|
||||
* attributes, then the second element will be JSONObject containing the
|
||||
* name/value pairs. If the tag contains children, then strings and
|
||||
* JSONArrays will represent the child tags.
|
||||
* As opposed to toJSONArray this method does not attempt to convert
|
||||
* any text node or attribute value to any type
|
||||
* but just leaves it as a string.
|
||||
* Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored.
|
||||
* @param string The source string.
|
||||
* @param keepStrings If true, then values will not be coerced into boolean
|
||||
* or numeric values and will instead be left as strings
|
||||
* @return A JSONArray containing the structured data from the XML string.
|
||||
* @throws JSONException Thrown on error converting to a JSONArray
|
||||
*/
|
||||
public static JSONArray toJSONArray(String string, boolean keepStrings) throws JSONException {
|
||||
return (JSONArray)parse(new XMLTokener(string), true, null, keepStrings);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert a well-formed (but not necessarily valid) XML string into a
|
||||
* JSONArray using the JsonML transform. Each XML tag is represented as
|
||||
* a JSONArray in which the first element is the tag name. If the tag has
|
||||
* attributes, then the second element will be JSONObject containing the
|
||||
* name/value pairs. If the tag contains children, then strings and
|
||||
* JSONArrays will represent the child content and tags.
|
||||
* As opposed to toJSONArray this method does not attempt to convert
|
||||
* any text node or attribute value to any type
|
||||
* but just leaves it as a string.
|
||||
* Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored.
|
||||
* @param x An XMLTokener.
|
||||
* @param keepStrings If true, then values will not be coerced into boolean
|
||||
* or numeric values and will instead be left as strings
|
||||
* @return A JSONArray containing the structured data from the XML string.
|
||||
* @throws JSONException Thrown on error converting to a JSONArray
|
||||
*/
|
||||
public static JSONArray toJSONArray(XMLTokener x, boolean keepStrings) throws JSONException {
|
||||
return (JSONArray)parse(x, true, null, keepStrings);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert a well-formed (but not necessarily valid) XML string into a
|
||||
* JSONArray using the JsonML transform. Each XML tag is represented as
|
||||
* a JSONArray in which the first element is the tag name. If the tag has
|
||||
* attributes, then the second element will be JSONObject containing the
|
||||
* name/value pairs. If the tag contains children, then strings and
|
||||
* JSONArrays will represent the child content and tags.
|
||||
* Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored.
|
||||
* @param x An XMLTokener.
|
||||
* @return A JSONArray containing the structured data from the XML string.
|
||||
* @throws JSONException Thrown on error converting to a JSONArray
|
||||
*/
|
||||
public static JSONArray toJSONArray(XMLTokener x) throws JSONException {
|
||||
return (JSONArray)parse(x, true, null, false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert a well-formed (but not necessarily valid) XML string into a
|
||||
* JSONObject using the JsonML transform. Each XML tag is represented as
|
||||
* a JSONObject with a "tagName" property. If the tag has attributes, then
|
||||
* the attributes will be in the JSONObject as properties. If the tag
|
||||
* contains children, the object will have a "childNodes" property which
|
||||
* will be an array of strings and JsonML JSONObjects.
|
||||
|
||||
* Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored.
|
||||
* @param string The XML source text.
|
||||
* @return A JSONObject containing the structured data from the XML string.
|
||||
* @throws JSONException Thrown on error converting to a JSONObject
|
||||
*/
|
||||
public static JSONObject toJSONObject(String string) throws JSONException {
|
||||
return (JSONObject)parse(new XMLTokener(string), false, null, false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert a well-formed (but not necessarily valid) XML string into a
|
||||
* JSONObject using the JsonML transform. Each XML tag is represented as
|
||||
* a JSONObject with a "tagName" property. If the tag has attributes, then
|
||||
* the attributes will be in the JSONObject as properties. If the tag
|
||||
* contains children, the object will have a "childNodes" property which
|
||||
* will be an array of strings and JsonML JSONObjects.
|
||||
|
||||
* Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored.
|
||||
* @param string The XML source text.
|
||||
* @param keepStrings If true, then values will not be coerced into boolean
|
||||
* or numeric values and will instead be left as strings
|
||||
* @return A JSONObject containing the structured data from the XML string.
|
||||
* @throws JSONException Thrown on error converting to a JSONObject
|
||||
*/
|
||||
public static JSONObject toJSONObject(String string, boolean keepStrings) throws JSONException {
|
||||
return (JSONObject)parse(new XMLTokener(string), false, null, keepStrings);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert a well-formed (but not necessarily valid) XML string into a
|
||||
* JSONObject using the JsonML transform. Each XML tag is represented as
|
||||
* a JSONObject with a "tagName" property. If the tag has attributes, then
|
||||
* the attributes will be in the JSONObject as properties. If the tag
|
||||
* contains children, the object will have a "childNodes" property which
|
||||
* will be an array of strings and JsonML JSONObjects.
|
||||
|
||||
* Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored.
|
||||
* @param x An XMLTokener of the XML source text.
|
||||
* @return A JSONObject containing the structured data from the XML string.
|
||||
* @throws JSONException Thrown on error converting to a JSONObject
|
||||
*/
|
||||
public static JSONObject toJSONObject(XMLTokener x) throws JSONException {
|
||||
return (JSONObject)parse(x, false, null, false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert a well-formed (but not necessarily valid) XML string into a
|
||||
* JSONObject using the JsonML transform. Each XML tag is represented as
|
||||
* a JSONObject with a "tagName" property. If the tag has attributes, then
|
||||
* the attributes will be in the JSONObject as properties. If the tag
|
||||
* contains children, the object will have a "childNodes" property which
|
||||
* will be an array of strings and JsonML JSONObjects.
|
||||
|
||||
* Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored.
|
||||
* @param x An XMLTokener of the XML source text.
|
||||
* @param keepStrings If true, then values will not be coerced into boolean
|
||||