// 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();
    }
Exemplo n.º 3
0
    /// <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);
    }
Exemplo n.º 5
0
    // 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();
    }