IaNode.java
Go to the documentation of this file.
00001 
00009 package com.rosalfred.core.ia;
00010 
00011 import java.beans.XMLDecoder;
00012 import java.beans.XMLEncoder;
00013 import java.io.File;
00014 import java.io.FileInputStream;
00015 import java.io.FileNotFoundException;
00016 import java.io.FileOutputStream;
00017 import java.io.IOException;
00018 
00019 import org.ros.dynamic_reconfigure.server.Server;
00020 import org.ros.dynamic_reconfigure.server.Server.ReconfigureListener;
00021 import org.ros.message.MessageListener;
00022 import org.ros.namespace.GraphName;
00023 import org.ros.node.AbstractNodeMain;
00024 import org.ros.node.ConnectedNode;
00025 import org.ros.node.Node;
00026 import org.ros.node.topic.Publisher;
00027 import org.ros.node.topic.Subscriber;
00028 import org.rosbuilding.common.media.CommandUtil;
00029 
00030 import com.google.common.base.Joiner;
00031 import com.google.common.base.Strings;
00032 import com.rivescript.ClientManager;
00033 import com.rosalfred.core.ia.rivescript.BotReply;
00034 import com.rosalfred.core.ia.rivescript.RiveScript;
00035 import com.rosalfred.core.ia.rivescript.lang.Echo;
00036 import com.rosalfred.core.ia.rivescript.lang.Java;
00037 
00038 import smarthome_comm_msgs.Command;
00039 
00046 public class IaNode extends AbstractNodeMain implements MessageListener<Command>, ReconfigureListener<IaConfig> {
00047 
00048     public static final String VAR_CONTEXT_WHERE    = "context-where";
00049     private static final String SUB_CMD             = "speech";
00050     private static final String PUB_STATE           = "robotsay";
00051     private static final String PERSITE_FILE        = "saveContext.xml";
00052 
00053     public static String botname = "Alfred";
00054 
00055     protected String prefix;
00056     protected String path;
00057 
00058     protected ConnectedNode connectedNode;
00059     protected Server<IaConfig> reconfigServer;
00060     protected Publisher<Command> publisherSay;
00061     protected Subscriber<Command> subscriberListen;
00062 
00063     protected RosRiveScript bot;
00064 
00065     @Override
00066     public GraphName getDefaultNodeName() {
00067         return GraphName.of("local_ia");
00068     }
00069 
00070     @Override
00071     public void onStart(ConnectedNode connectedNode) {
00072         super.onStart(connectedNode);
00073         this.connectedNode = connectedNode;
00074 
00075         this.path = this.getPath();
00076 
00077         this.loadParameters();
00078 
00079         this.initTopics();
00080         this.initBot();
00081 
00082         this.sayWelcome();
00083     }
00084 
00085     protected String getPath() {
00086         return IaNode.class.getProtectionDomain().getCodeSource()
00087                 .getLocation().getPath().replace("bin/", "") + "/res";
00088     }
00089 
00090     private void initBot() {
00091         this.sayReload();
00092         this.bot = this.getRiveScript();
00093 
00094         // TODO learning
00095 
00096         this.loadHandlers();
00097         this.reloadBot();
00098     }
00099 
00100     protected RosRiveScript getRiveScript() {
00101         return new RosRiveScript(this, false);
00102     }
00103 
00104     protected void loadHandlers() {
00105         // RiveScript
00106         this.logI("\tLoad engine...");
00107         this.bot.setHandler(RiveScript.TYPE_PERL, new Echo(this.bot)); // new
00108                                                          // com.rivescript.lang.Perl(rs,
00109                                                          // "./lang/rsp4j.pl"));
00110         this.bot.setHandler(RiveScript.TYPE_PYTHON, new Echo(this.bot));
00111         this.bot.setHandler(RiveScript.TYPE_JAVA, new Java(this.bot, this.path + "/src"));
00112     }
00113 
00114     private void reloadBot() {
00115         if (this.bot != null) {
00116             this.logI(String.format("\tLoad rules... in %s", this.path));
00117             this.bot.loadDirectory(this.path);
00118 
00119             this.bot.sortReplies();
00120             this.reloadBotState();
00121 
00122             try {
00123                 Thread.sleep(1);
00124             } catch (InterruptedException e) {
00125                 e.printStackTrace();
00126             }
00127         }
00128     }
00129 
00135     public void persistBotState() {
00136         if (this.bot != null) {
00137             XMLEncoder encoder = null;
00138             String path = this.getFolderPersist();
00139 
00140             File file = new File(path + "/" + PERSITE_FILE);
00141             try {
00142                 if (!file.exists() && !file.createNewFile()) {
00143                     this.logE("File couldn't be created...");
00144                 }
00145                 encoder = new XMLEncoder(new FileOutputStream(file));
00146                 encoder.writeObject(this.bot.getUservars());
00147                 encoder.flush();
00148             } catch (FileNotFoundException e) {
00149                 this.logE(e);
00150             } catch (IOException e) {
00151                 this.logE(e);
00152             } finally {
00153                 if (encoder != null)
00154                     encoder.close();
00155             }
00156         }
00157     }
00158 
00162     protected String getFolderPersist() {
00163         String path = System.getProperty("user.home") + "/.ros";
00164         if (System.getenv().containsKey("ROS_HOME")) {
00165             path = System.getenv("ROS_HOME");
00166         }
00167         return path;
00168     }
00169 
00173     public void reloadBotState() {
00174         if (this.bot != null) {
00175             Object object = null;
00176             XMLDecoder decoder = null;
00177             ClientManager clientManager;
00178             String path = this.getFolderPersist();
00179 
00180             File file = new File(path + "/" + PERSITE_FILE);
00181             if (file.exists()) {
00182                 try {
00183                     decoder = new XMLDecoder(new FileInputStream(file));
00184                     object = decoder.readObject();
00185                     clientManager = (ClientManager) object;
00186                     this.bot.setUservars(clientManager);
00187                 } catch (Exception e) {
00188                     this.logI(e.getMessage());
00189                 } finally {
00190                     if (decoder != null)
00191                         decoder.close();
00192                 }
00193             }
00194         }
00195     }
00196 
00197     protected void initTopics() {
00198         this.logI("Start Topics (publishers/subscribers)...");
00199 
00200         // Create publishers
00201         this.publisherSay = this.connectedNode.newPublisher(
00202                 this.prefix + PUB_STATE, Command._TYPE);
00203 
00204         // Create subscribers
00205         this.subscriberListen = this.connectedNode.newSubscriber(
00206                 this.prefix + SUB_CMD, Command._TYPE);
00207         this.subscriberListen.addMessageListener(this);
00208     }
00209 
00210     private Command makeSay() {
00211         Command command = this.connectedNode.getTopicMessageFactory().newFromType(Command._TYPE);
00212         command.getContext().setWho(IaNode.botname);
00213         command.setAction(CommandUtil.Action.SAY.getValue());
00214         return command;
00215     }
00216 
00217     private void sayReload() {
00218         Command command = this.makeSay();
00219         command.setSubject("Chargement de ma base de donnée...");
00220         this.publisherSay.publish(command);
00221     }
00222 
00223     private void sayGoodbye() {
00224         Command command = this.makeSay();
00225         command.setSubject("Arrêt du système...");
00226         this.publisherSay.publish(command);
00227     }
00228 
00229     private void sayWelcome() {
00230         Command command = this.makeSay();
00231         command.setSubject("Système prêt!");
00232         this.publisherSay.publish(command);
00233     }
00234 
00238     private void loadParameters() {
00239         // Prefix
00240         this.prefix = String.format("/%s/", this.connectedNode
00241                 .getParameterTree().getString("~tf_prefix", ""));
00242 
00243         if (this.prefix.equals("//")) // Hack
00244             this.prefix = "/";
00245 
00246         // Path resources
00247         this.path = this.connectedNode.getParameterTree()
00248                 .getString("~" + IaConfig.RES_PATH, this.path);
00249         this.connectedNode.getParameterTree().set("~" + IaConfig.RES_PATH, this.path);
00250 
00251         this.logI(String.format("prefix : %s", this.prefix));
00252 
00253         // Connect to dynamic reconfigure
00254         this.reconfigServer = new Server<IaConfig>(
00255                 this.connectedNode, new IaConfig(this.connectedNode), this);
00256     }
00257 
00261     @Override
00262     public void onNewMessage(Command command) {
00263         String user = command.getContext().getWho();
00264         String where = command.getContext().getWhere();
00265 
00266         if (this.bot != null) {
00267             String speech = command.getSubject();
00268             this.logI(String.format("from %s : %s", user, speech));
00269 
00270             this.bot.setUservar(user, VAR_CONTEXT_WHERE, where);
00271 
00272             // TODO move now to Rive workflow
00273             switch (speech) {
00274             case "/reload":
00275                 this.initBot();
00276                 break;
00277             case "/save":
00278                 this.persistBotState();
00279                 break;
00280             case "/load":
00281                 this.reloadBotState();
00282                 break;
00283             case "/status":
00284                 this.reloadBotState();
00285                 break;
00286             default:
00287                 if (!user.equals(IaNode.botname)) {
00288                     String escapeString = speech.replaceAll("-:", " "); // ignore
00289                     String[] res = escapeString.split("[.!?;]+\\s*");
00290 
00291                     BotReply responce = new BotReply("ERR: Sentence not work !!");
00292                     for (String sentence : res) {
00293                         responce = this.bot.reply(user, sentence);
00294                     }
00295                     command.getContext().setWho(IaNode.botname);
00296 
00297                     if (!Strings.isNullOrEmpty(responce.getReply())
00298                             && !responce.getReply().startsWith("ERR:")) {
00299 
00300                         command.setSubject(responce.getReply());
00301                         this.publisherSay.publish(command);
00302 
00303                         this.logI(String.format("from %s to %s : %s",
00304                                 command.getContext().getWho(),
00305                                 user,
00306                                 command.getSubject()));
00307 
00308                         if (!responce.getIntents().isEmpty()) {
00309                             String content = String.format("[%s]",
00310                                     Joiner.on(",").join(responce.getIntents()));
00311 
00312                             command = this.publisherSay.newMessage();
00313                             command.getContext().setWhere(where);
00314                             command.getContext().setWho(IaNode.botname);
00315                             command.setAction("show");
00316                             command.setSubject(content);
00317 
00318                             this.publisherSay.publish(command);
00319                         }
00320 
00321                     } else {
00322                         if (Strings.isNullOrEmpty(responce.getReply())
00323                                 || responce.getReply().contains("ERR: No Reply Matched")) {
00324                             // TODO Learn...
00325                         } else if (responce.getReply().startsWith("ERR:")) {
00326                             this.logE(String.format("bot error : %s", responce));
00327                         } else {
00328                             this.logI(String.format("bot command : %s", responce));
00329                         }
00330                     }
00331                 }
00332             }
00333         } else {
00334             command.setSubject("IA loading...");
00335             this.publisherSay.publish(command);
00336             this.logI(String.format("from %s to %s : %s",
00337                     command.getContext().getWho(), user, command.getSubject()));
00338         }
00339     }
00340 
00344     @Override
00345     public void onShutdown(Node node) {
00346         this.persistBotState();
00347         this.sayGoodbye();
00348 
00349         this.reconfigServer.close();
00350         super.onShutdown(node);
00351         try {
00352             Thread.sleep(1);
00353         } catch (InterruptedException e) {
00354         }
00355     }
00356 
00357     @Override
00358     public IaConfig onReconfigure(IaConfig config, int level) {
00359         this.path = config.getString(IaConfig.RES_PATH, this.path);
00360 
00361         // TODO DELETE : For test
00362         config.setString(IaConfig.RES_PATH, this.path);
00363 
00364         this.reloadBot();
00365         return config;
00366     }
00367 
00373     public void logD(Object message) {
00374         this.connectedNode.getLog().debug(message);
00375     }
00376 
00382     public void logI(Object message) {
00383         this.connectedNode.getLog().info(message);
00384     }
00385 
00391     public void logE(Object message) {
00392         this.connectedNode.getLog().error(message);
00393     }
00394 
00400     public void logE(Exception message) {
00401         this.connectedNode.getLog().error(message.getStackTrace());
00402     }
00403 
00404 }


alfred_bot
Author(s): Mickael Gaillard , Erwan Le Huitouze
autogenerated on Tue Jun 14 2016 01:34:50