// Send a message representing storybook state to the controller. // Doesn't need to return Action because it's only used as a timer elapsed handler. private void sendStorybookState(object _, System.Timers.ElapsedEventArgs __) { Dictionary <string, object> publish = new Dictionary <string, object>(); publish.Add("topic", Constants.STORYBOOK_STATE_TOPIC); publish.Add("op", "publish"); // TODO: could devise a better scheme to make sure states are sent in order. // Can also use the sequence numbers provided in the header. Probably overkill. Dictionary <string, object> data = StorybookStateManager.GetRosMessageData(); data.Add("header", RosbridgeUtilities.GetROSHeader()); // Don't allow audio_file to be null, ROS will get upset. if (data["audio_file"] == null) { data["audio_file"] = ""; } publish.Add("msg", data); bool success = this.rosClient.SendMessage(Json.Serialize(publish)); if (!success) { // Logger.Log("Failed to send StorybookState message: " + Json.Serialize((publish))); } }
// Send a message representing new page info to the controller. // Typically will be called when the user presses previous or next. // Sends until success, in a new thread. public void SendStorybookPageInfoAction(StorybookPageInfo pageInfo) { Thread thread = new Thread(() => { Dictionary <string, object> publish = new Dictionary <string, object>(); publish.Add("topic", Constants.STORYBOOK_PAGE_INFO_TOPIC); publish.Add("op", "publish"); Dictionary <string, object> data = new Dictionary <string, object>(); data.Add("header", RosbridgeUtilities.GetROSHeader()); data.Add("story_name", pageInfo.storyName); data.Add("page_number", pageInfo.pageNumber); data.Add("sentences", pageInfo.sentences); List <Dictionary <string, object> > tinkerTexts = new List <Dictionary <string, object> > (); foreach (StorybookTinkerText t in pageInfo.tinkerTexts) { Dictionary <string, object> tinkerText = new Dictionary <string, object>(); tinkerText.Add("has_scene_object", t.hasSceneObject); tinkerText.Add("scene_object_id", t.sceneObjectId); tinkerText.Add("word", t.word); tinkerTexts.Add(tinkerText); } data.Add("tinkertexts", tinkerTexts); List <Dictionary <string, object> > sceneObjects = new List <Dictionary <string, object> >(); foreach (StorybookSceneObject o in pageInfo.sceneObjects) { Dictionary <string, object> sceneObject = new Dictionary <string, object>(); sceneObject.Add("id", o.id); sceneObject.Add("label", o.label); sceneObject.Add("in_text", o.inText); sceneObjects.Add(sceneObject); } data.Add("scene_objects", sceneObjects); List <Dictionary <string, object> > prompts = new List <Dictionary <string, object> >(); foreach (JiboPrompt p in pageInfo.prompts) { Dictionary <string, object> prompt = new Dictionary <string, object>(); prompt.Add("question", p.question); prompt.Add("response", p.response); prompt.Add("hint", p.hint); prompts.Add(prompt); } data.Add("prompts", prompts); publish.Add("msg", data); Logger.Log("Sending page info ROS message: " + Json.Serialize(publish)); bool sent = false; while (!sent) { sent = this.rosClient.SendMessage(Json.Serialize(publish)); } Logger.Log("Successfully sent page info ROS message."); }); thread.Start(); }
/// <summary> /// Handle OnMessage events, which occur when we receive a message /// </summary> /// <param name="sender">Sender.</param> /// <param name="e">E.</param> void HandleOnMessage(object sender, MessageEventArgs e) { // if the message is a string, we can parse it if (e.IsText) { Logger.Log("[websocket] Received message: " + e.Data); // use rosbridge utilities to decode and parse message int command = -1; object properties = null; RosbridgeUtilities.DecodeROSJsonCommand(e.Data, out command, out properties); // got a command! // we let the game controller sort out if it's a real command or not // as well as what to do with the extra properties, if any // fire event indicating that we received a message if (this.receivedMsgEvent != null) { // only send subset of msg that is actual message this.receivedMsgEvent(this, command, properties); } } else if (e.IsBinary) { Logger.LogWarning("[websocket] Received byte array in message but we " + "were expecting a string message."); } }
public bool Connect() { if (!this.rosClient.SetupSocket()) { Logger.Log("Failed to set up socket"); return(false); } string eventPubMessage = RosbridgeUtilities.GetROSJsonAdvertiseMsg( Constants.STORYBOOK_EVENT_TOPIC, Constants.STORYBOOK_EVENT_MESSAGE_TYPE); string pageInfoPubMessage = RosbridgeUtilities.GetROSJsonAdvertiseMsg( Constants.STORYBOOK_PAGE_INFO_TOPIC, Constants.STORYBOOK_PAGE_INFO_MESSAGE_TYPE); string statePubMessage = RosbridgeUtilities.GetROSJsonAdvertiseMsg( Constants.STORYBOOK_STATE_TOPIC, Constants.STORYBOOK_STATE_MESSAGE_TYPE); string subMessage = RosbridgeUtilities.GetROSJsonSubscribeMsg( Constants.STORYBOOK_COMMAND_TOPIC, Constants.STORYBOOK_COMMAND_MESSAGE_TYPE); // Send all advertisements to publish and subscribe to appropriate channels. this.connected = this.rosClient.SendMessage(eventPubMessage) && this.rosClient.SendMessage(pageInfoPubMessage) && this.rosClient.SendMessage(statePubMessage) && this.rosClient.SendMessage(subMessage); // If connection successful, begin sending state messages. if (this.connected) { Logger.Log("Starting to send state messages"); this.publishStateTimer.Elapsed += this.sendStorybookState; this.publishStateTimer.Start(); } return(this.connected); }
// Send a message representing storybook state to the controller, in a new thread. // Doesn't need to return Action because it's only used as a timer elapsed handler. private void sendStorybookState(object _, System.Timers.ElapsedEventArgs __) { Dictionary <string, object> publish = new Dictionary <string, object>(); publish.Add("topic", Constants.STORYBOOK_STATE_TOPIC); publish.Add("op", "publish"); // Note that this is protected by a lock, so although ROS messages could // send out of order, the information within them will be consistent. // And if the sending rate isn't too high, the likelihood of out of order messages // is low, and inconsequential for the controller anyway. // TODO: should devise a better scheme to make sure states are sent in order. // Can also use the sequence numbers provided in the header. // Or use a lock in this class so that only one state message can be sent at a time. Dictionary <string, object> data = StorybookStateManager.GetRosMessageData(); data.Add("header", RosbridgeUtilities.GetROSHeader()); // Don't allow audio_file to be null, ROS will get upset. if (data["audio_file"] == null) { data["audio_file"] = ""; } publish.Add("msg", data); bool success = this.rosClient.SendMessage(Json.Serialize(publish)); if (!success) { // Logger.Log("Failed to send StorybookState message: " + Json.Serialize((publish))); } }
private void setupPubSub() { Logger.Log("-- Setup Pub/Sub for Ros Manager --"); string eventPubMessage = RosbridgeUtilities.GetROSJsonAdvertiseMsg( Constants.STORYBOOK_EVENT_TOPIC, Constants.STORYBOOK_EVENT_MESSAGE_TYPE); string pageInfoPubMessage = RosbridgeUtilities.GetROSJsonAdvertiseMsg( Constants.STORYBOOK_PAGE_INFO_TOPIC, Constants.STORYBOOK_PAGE_INFO_MESSAGE_TYPE); string statePubMessage = RosbridgeUtilities.GetROSJsonAdvertiseMsg( Constants.STORYBOOK_STATE_TOPIC, Constants.STORYBOOK_STATE_MESSAGE_TYPE); string subMessage = RosbridgeUtilities.GetROSJsonSubscribeMsg( Constants.STORYBOOK_COMMAND_TOPIC, Constants.STORYBOOK_COMMAND_MESSAGE_TYPE); // Send all advertisements to publish and subscribe to appropriate channels. this.connected = this.rosClient.SendMessage(eventPubMessage) && this.rosClient.SendMessage(pageInfoPubMessage) && this.rosClient.SendMessage(statePubMessage) && this.rosClient.SendMessage(subMessage); }
// Send a message representing storybook state to the controller, in a new thread. // Doesn't need to return Action because it's only used as a timer elapsed handler. private void sendStorybookState(object sender, System.Timers.ElapsedEventArgs e) { Thread t = new Thread(() => { Dictionary <string, object> publish = new Dictionary <string, object>(); publish.Add("topic", Constants.STORYBOOK_STATE_TOPIC); publish.Add("op", "publish"); Dictionary <string, object> data = new Dictionary <string, object>(); // Note that this is protected by a lock, so although ROS messages could // send out of order, the information within them will be consistent. // And if the sending rate isn't too high, the likelihood of out of order messages // is low, and inconsequential for the controller anyway. // TODO: should devise a better scheme to make sure states are sent in order. // Can also use the sequence numbers provided in the header. // Or use a lock in this class so that only one state message can be sent at a time. StorybookState currentStorybookState = this.storybookStateManager.getCurrentState(); data.Add("header", RosbridgeUtilities.GetROSHeader()); data.Add("audio_playing", currentStorybookState.audioPlaying); // ROS freaks out if it gets a null value, so just fill it in with an empty string // if there is no provided audio file. string audioFile = currentStorybookState.audioFile; if (audioFile == null) { audioFile = ""; } data.Add("audio_file", audioFile); data.Add("storybook_mode", (int)currentStorybookState.storybookMode); data.Add("current_story", currentStorybookState.currentStory); data.Add("num_pages", currentStorybookState.numPages); data.Add("evaluating_stanza_index", currentStorybookState.evaluatingStanzaIndex); publish.Add("msg", data); bool success = this.rosClient.SendMessage(Json.Serialize(publish)); if (!success) { Logger.Log("Failed to send StorybookState message: " + Json.Serialize((publish))); } }); t.Start(); }
// Send StorybookEvent message until received, in a new thread. private void sendEventMessageToController(StorybookEventType messageType, string message) { Thread t = new Thread(() => { Dictionary <string, object> publish = new Dictionary <string, object>(); publish.Add("topic", Constants.STORYBOOK_EVENT_TOPIC); publish.Add("op", "publish"); // Build data to send. Dictionary <string, object> data = new Dictionary <string, object>(); data.Add("event_type", (int)messageType); data.Add("header", RosbridgeUtilities.GetROSHeader()); data.Add("message", message); publish.Add("msg", data); Logger.Log("Sending event ROS message: " + Json.Serialize(publish)); bool sent = false; while (!sent) { sent = this.rosClient.SendMessage(Json.Serialize(publish)); } }); t.Start(); }