/// <summary>
    /// Send an Augmenta OSC message
    /// </summary>
    /// <param name="messageType"></param>
    /// <param name="obj"></param>
    public void SendAugmentaMessage(AugmentaMessageType messageType, GameObject obj = null)
    {
        if (mute)
        {
            return;
        }

        // Craft and send a message that contains the event + extra info
        WebsocketManager.activeManager.SendAugmentaMessage(CreateAugmentaMessageJSON(messageType, obj));

        switch (ProtocolVersionManager.protocolVersion)
        {
        case ProtocolVersionManager.AugmentaProtocolVersion.V1:
            OSCManager.activeManager.SendAugmentaMessage(CreateAugmentaMessageV1(messageType, obj));
            break;

        case ProtocolVersionManager.AugmentaProtocolVersion.V2:
            OSCManager.activeManager.SendAugmentaMessage(CreateAugmentaMessageV2(messageType, obj));
            if (messageType != AugmentaMessageType.SceneUpdated)
            {
                //Send corresponding /extra message
                OSCManager.activeManager.SendAugmentaMessage(CreateAugmentaMessageV2((AugmentaMessageType)Enum.Parse(typeof(AugmentaMessageType), messageType.ToString() + "Extra"), obj));
            }
            break;
        }
    }
    /* Augmenta OSC Protocol v2.0
     *
     *  /object/enter arg0 arg1 ... argN
     *  /object/leave arg0 arg1 ... argN
     *  /object/update arg0 arg1 ... argN
     *
     *  where args are :
     *  0: frame(int)     // Frame number
     *  1: id(int)                        // id ex : 42th object to enter stage has pid=42
     *  2: oid(int)                        // Ordered id ex : if 3 objects on stage, 43th object might have oid=2
     *  3: age(float)                      // Alive time (in s)
     *  4: centroid.x(float 0:1)           // Position projected to the ground (normalised)
     *  5: centroid.y(float 0:1)
     *  6: velocity.x(float -1:1)           // Speed and direction vector (in unit.s-1) (normalised)
     *  7: velocity.y(float -1:1)
     *  8: orientation(float 0:360) // With respect to horizontal axis right (0° = (1,0)), rotate counterclockwise
     *                                              // Estimation of the object orientation from its rotation and velocity
     *  9: boundingRect.x(float 0:1)       // Bounding box center coord (normalised)
     *  10: boundingRect.y(float 0:1)
     *  11: boundingRect.width(float 0:1) // Bounding box width (normalised)
     *  12: boundingRect.height(float 0:1)
     *  13: boundingRect.rotation(float 0:360) // With respect to horizontal axis right counterclockwise
     *  14: height(float)           // Height of the object (in m) (absolute)
     *
     *  /scene   arg0 arg1 ... argN
     *  0: frame (int)                // Frame number
     *  1: objectCount (int)                  // Number of objects
     *  2: scene.width (float)             // Scene width in
     *  3: scene.height (float)
     *
     *  /fusion arg0 arg1 ... argN
     *
     *  0: videoOut.PixelWidth (int)      // VideoOut width in fusion
     *  1: videoOut.PixelHeight (int)
     *  2: videoOut.coord.x (int)          // top left coord in fusion
     *  3: videoOut.coord.y (int)
     *  4: scene.coord.x (float)          // Scene top left coord (0 for node by default)
     *  5: scene.coord.y (float)
     *
     */

    /// <summary>
    /// Create an Augmenta message with protocol V2.
    /// </summary>
    /// <param name="messageType"></param>
    /// <param name="obj"></param>
    /// <returns></returns>
    private OSCMessage CreateAugmentaMessageV2(AugmentaMessageType messageType, GameObject obj = null)
    {
        switch (messageType)
        {
        case AugmentaMessageType.AugmentaObjectEnter:
            return(CreateAugmentaObjectMessageV2("/object/enter", obj));

        case AugmentaMessageType.AugmentaObjectUpdate:
            return(CreateAugmentaObjectMessageV2("/object/update", obj));

        case AugmentaMessageType.AugmentaObjectLeave:
            return(CreateAugmentaObjectMessageV2("/object/leave", obj));

        case AugmentaMessageType.AugmentaObjectEnterExtra:
            return(CreateAugmentaObjectExtraMessageV2("/object/enter/extra", obj));

        case AugmentaMessageType.AugmentaObjectUpdateExtra:
            return(CreateAugmentaObjectExtraMessageV2("/object/update/extra", obj));

        case AugmentaMessageType.AugmentaObjectLeaveExtra:
            return(CreateAugmentaObjectExtraMessageV2("/object/leave/extra", obj));

        case AugmentaMessageType.SceneUpdated:
            return(CreateSceneMessageV2("/scene"));

        default:
            return(null);
        }
    }
    //OSC Protocol V1

    /*
     *  0: pid (int)                        // Personal ID ex : 42th person to enter stage has pid=42
     *  1: oid (int)                        // Ordered ID ex : if 3 person on stage, 43th person might have oid=2
     *  2: age (int)                        // Time on stage (in frame number)
     *  3: centroid.x (float 0:1)           // Position projected to the ground
     *  4: centroid.y (float 0:1)
     *  5: velocity.x (float -1:1)           // Speed and direction vector
     *  6: velocity.y (float -1:1)
     *  7: depth (float 0:1)                // Distance to sensor (in m) (not implemented)
     *  8: boundingRect.x (float 0:1)       // Top view bounding box
     *  9: boundingRect.y (float 0:1)
     *  10: boundingRect.width (float 0:1)
     *  11: boundingRect.height (float 0:1)
     *  12: highest.x (float 0:1)           // Highest point placement
     *  13: highest.y (float 0:1)
     *  14: highest.z (float 0:1)           // Height of the person
     *
     *  /au/scene   args0 arg1 ... argn
     *
     *  0: currentTime (int)                // Time (in frame number)
     *  1: percentCovered (float 0:1)       // Percent covered
     *  2: numPeople (int)                  // Number of person
     *  3: averageMotion.x (float 0:1)          // Average motion
     *  4: averageMotion.y (float 0:1)
     *  5: scene.width (int)                // Scene size
     *  6: scene.height (int)
     *  7: scene.depth (int)
     */

    /// <summary>
    /// Create an Augmenta message with protocol V1.
    /// </summary>
    /// <param name="messageType"></param>
    /// <param name="obj"></param>
    /// <returns></returns>
    private OSCMessage CreateAugmentaMessageV1(AugmentaMessageType messageType, GameObject obj = null)
    {
        switch (messageType)
        {
        case AugmentaMessageType.AugmentaObjectEnter:
            return(CreateAugmentaObjectMessageV1("/au/personEntered", obj));

        case AugmentaMessageType.AugmentaObjectUpdate:
            return(CreateAugmentaObjectMessageV1("/au/personUpdated", obj));

        case AugmentaMessageType.AugmentaObjectLeave:
            return(CreateAugmentaObjectMessageV1("/au/personWillLeave", obj));

        case AugmentaMessageType.SceneUpdated:
            return(CreateSceneMessageV1("/au/scene"));

        default:
            return(null);
        }
    }
    public String CreateAugmentaMessageJSON(AugmentaMessageType messageType, GameObject obj = null)
    {
        switch (messageType)
        {
        case AugmentaMessageType.AugmentaObjectEnter:
            return("{\n\"object\": {\n\"enter\": " + CreateAugmentaMessageJSONData(obj) + "\n}\n}");

        case AugmentaMessageType.AugmentaObjectUpdate:
            return("{\n\"object\": {\n\"update\": " + CreateAugmentaMessageJSONData(obj) + "\n}\n}");

        case AugmentaMessageType.AugmentaObjectLeave:
            return("{\n\"object\": {\n\"leave\": " + CreateAugmentaMessageJSONData(obj) + "\n}\n}");

        case AugmentaMessageType.SceneUpdated:
            return(CreateAugmentaMessageJSONScene());

        default:
            Debug.Log("Unsupported message type " + messageType.ToString());
            return(String.Empty);
        }
    }