/// <summary>
        /// modifies the device 3d type to "delete" and sends it to MQTT
        /// also tries to delete the WorldAnchors
        /// </summary>
        /// <param name="baseAdress"></param>
        public void sendDeleteOrderForWorldAnchorAndAppData(AppData.uniqueIDDevice device)
        {
            device.DeviceType3D = "delete";

            AppDataManager_MQTT.Instance.publishDeviceOverMQTT(device); //sends a device with the remove command to all active members in the network
            AppDataManager_MQTT.Instance.removeDeviceOverMQTT(device);  //sends a remove command to clean up the server


            var anchorInfo = WorldAnchorAvailableOnlineManager.Instance.getAnchorAvailableOnline(device.baseAdress);

            if (!anchorInfo.Equals(default(KeyValuePair <string, DateTime>)))//if there is an anchor available
            {
                AppDataExportManager.Instance.MQTTPublishMessage(AppDataExportManager.Instance.worldAnchorBaseSubscriptionPath +
                                                                 TimeMethodesForAnchors.getAnchorNameWithTimeFromKeyValuePair(anchorInfo),
                                                                 "");//deletion order for retained messages

                AppDataExportManager.Instance.MQTTPublishMessage(WorldAnchorAvailableOnlineManager.Instance.worldAnchorStatusSubscriptionPath +
                                                                 TimeMethodesForAnchors.getAnchorNameWithTimeFromKeyValuePair(anchorInfo),
                                                                 "");//deletion order for retained messages
            }


            //deletes wa info from the prefs
            PlayerPrefs.DeleteKey(device.baseAdress);

            //now remove the device locally
            removeDeviceFromAppDataAndDeleteFromHierarchie(device.baseAdress);
        }
        /// <summary>
        /// if found device in loadedData does not exist or
        /// is not the same as the deviceToCompare or
        /// the deviceToCompare /found device does not exist in hierarchie or
        /// the container data of the device is different
        /// return false
        /// </summary>
        /// <param name="deviceToCompare"></param>
        /// <returns></returns>
        private bool doesDeviceExistAndIsSame(AppData.uniqueIDDevice deviceToCompare)
        {
            if (loadedData == null)
            {
                return(false);
            }

            if (deviceToCompare == null || string.IsNullOrEmpty(deviceToCompare.baseAdress))
            {
                Debug.LogError("AppDataManager: error comparing state of the device");
                throw new ArgumentOutOfRangeException();
            }

            //if found device does not exist or is not the same as the new device or the device does not exist in hierarchie
            var foundDevice = loadedData.MqttDeviceData.Find(x => x.baseAdress == deviceToCompare.baseAdress);

            if (foundDevice == null ||
                !foundDevice.Equals(deviceToCompare) ||
                !DeviceManager.Instance.hasDeviceAttached(deviceToCompare.baseAdress) ||
                !checkUiContainerData(foundDevice.myUIContainerData, deviceToCompare.myUIContainerData)) //TODO: To test
            {
                return(false);
            }
            else
            {
                return(true);
            }
        }
        public void startmenuWithExistingItem(AppData.uniqueIDDevice existingItem)
        {
            prepare();

            currentMenuInformationState = (AppData.uniqueIDDevice)existingItem.Clone();
            generateMenu_Ressources();
        }
        private void appDataReceived(MqttNetClientAccess.mqttMessage message)
        {
            if (message.payload.Length == 0)
            {
                Debug.Log("AppDatamanager_MQTT received a device whith payload length 0");
                return;
                //this is a deletion message
            }

            string decodedMessage = System.Text.Encoding.UTF8.GetString(message.payload);

            AppData.uniqueIDDevice device = null;
            try
            {
                device = JsonConvert.DeserializeObject <AppData.uniqueIDDevice>(decodedMessage);
            }
            catch {
                Debug.Log("AppDatamanager_MQTT could not deserialize device " + message.topic);
            }

            //if device was not encoded
            if (device == null || string.IsNullOrEmpty(device.baseAdress))
            {
                return;
            }

            //tell others
            invokeOnAppDataReceived?.Invoke(device);
        }
        public void startmenuFresh()
        {
            prepare();

            currentMenuInformationState = new AppData.uniqueIDDevice();
            currentMenuInformationState.myUIContainerData = new List <AppData.uniqueIDDevice.UIContainerData>();
            generateMenu_Ressources();
        }
        /// <summary>
        /// sends an empty message to remove the device
        /// </summary>
        public void removeDeviceOverMQTT(AppData.uniqueIDDevice device)
        {
            if (device == null)
            {
                return;
            }

            StartCoroutine(publishRemoveDevice(device));
        }
        // in here come all received devices from mqtt
        private void newDeviceReceived(AppData.uniqueIDDevice receivedDevice)
        {
            //set up loaded data if there is none
            if (loadedData == null)
            {
                loadedData = new AppData();
                loadedData.MqttDeviceData = new List <AppData.uniqueIDDevice>();
            }

            if (receivedDevice == null || string.IsNullOrEmpty(receivedDevice.baseAdress))
            {
                Debug.LogError("AppDataManager: error Receiving device data over MQTT");
                return;
            }

            //The more devices we receive from the network, the more confident we are, that the network works properly
            NetworkWorkingConfidence++;
            if (NetworkWorkingConfidence == 1)
            {
                StartCoroutine(CompareNetworkDevicesTimer());
            }
            timerForNetworkDeviceCheck = timerForNetworkDeviceCheckDefault; //reset the timer when we receive devices


            //is is a delete order?
            if (receivedDevice.DeviceType3D == "delete")
            {
                removeDeviceFromAppDataAndDeleteFromHierarchie(receivedDevice.baseAdress);
            }
            else
            { //add stuff
                if (networkData != null)
                {
                    //add the device to the from network received device
                    networkData.MqttDeviceData.Add(receivedDevice);
                }

                if (doesDeviceExistAndIsSame(receivedDevice) == false)
                { //create or regenerate device
                  //we remove the existing device (if there is one in hierarchie)
                  //DeviceManager.Instance.RemoveDevice(receivedDevice.baseAdress);

                    //then wereplace the device in our loadedData
                    loadedData.MqttDeviceData.RemoveAll(x => x.baseAdress == receivedDevice.baseAdress);
                    loadedData.MqttDeviceData.Add(receivedDevice);

                    //then we save the loaded Data to file
                    saveLoadedDataToFile();

                    //uses existing device if there is one
                    generateOrRefreshDevice(receivedDevice, false, false, DeviceManager.Instance.getDevice(receivedDevice.baseAdress)?.GetComponent <Device>());
                }//else we have to do nothing
            }
        }
        public void onManipulationFinished(AppData.uniqueIDDevice deviceData)
        {
            //we need to force the data to be published over mqtt
            //this will only be called if the device was manipulated

            //we do not need to swap the data in loaded data, because we have a call by reference in the mqttDevice class

            //save the modified Data to file
            saveLoadedDataToFile();

            //now we can tell everyone over mqtt
            AppDataManager_MQTT.Instance.publishDeviceOverMQTT(deviceData);
        }
        /// <summary>
        /// the editor of a new device should call this
        /// </summary>
        /// <param name="finishedDevice">the device</param>
        public void onEditorFinished(AppData.uniqueIDDevice finishedDevice)
        {
            //set up loaded data if there is none
            if (loadedData == null)
            {
                loadedData = new AppData();
                loadedData.MqttDeviceData = new List <AppData.uniqueIDDevice>();
            }

            if (finishedDevice == null || string.IsNullOrEmpty(finishedDevice.baseAdress))
            {
                Debug.LogError("AppDataManager: error finalizing device data after Editor");
                return;
            }

            //we look, if the editor modifing or creating a device
            if (doesDeviceExistAndIsSame(finishedDevice))
            {
                return; //editor did not change anything so abort
            }
            //the device was modified or is new
            //we replace the device in our loadedData
            int devicesRemoved = loadedData.MqttDeviceData.RemoveAll(x => x.baseAdress == finishedDevice.baseAdress);

            loadedData.MqttDeviceData.Add(finishedDevice);

            //if more than
            bool IsNewDevice = devicesRemoved > 0 ? false : true;

            //then we save the modified Data to file
            saveLoadedDataToFile();

            //remove device fromHierarchie if it exists
            // DeviceManager.Instance.RemoveDevice(finishedDevice.baseAdress);

            //set the target of the container bar to device

            //refreshes the existing device, if there is one

            var existingDevice = DeviceManager.Instance.getDevice(finishedDevice.baseAdress);

            generateOrRefreshDevice(finishedDevice, IsNewDevice, IsNewDevice, existingDevice?.GetComponent <Device>());

            //refreshes the UI, so it will be saved properly
            existingDevice?.GetComponent <Device>()?.generateUI();



            //now we can tell everyone over mqtt
            AppDataManager_MQTT.Instance.publishDeviceOverMQTT(finishedDevice);
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="device"></param>
        /// <param name="isFreshlyAdded"></param>
        /// <param name="getsTargetFromAppBar">Tries to attach the app bar to the newly generated device</param>
        private void generateOrRefreshDevice(AppData.uniqueIDDevice device, bool isFreshlyAdded = false, bool getsTargetFromAppBar = false, Device oldDeviceToRefresh = null)
        {
            if (device == null || device.baseAdress == null)
            {
                Debug.LogError("Error generating the device");
                throw new ArgumentOutOfRangeException();
            }

            GameObject mqttDevice;

            //this instantiates a Prefab
            //the prefab is in the "Recources" folder
            try
            {
                if (oldDeviceToRefresh == null)
                {
                    //we have to figure first out, of there is already a device with the same name attached
                    if (DeviceManager.Instance.hasDeviceAttached(device.baseAdress))
                    {
                        Debug.LogError("There is already a Device with the same name attached. Remove that first bevore trying to generate a new one");
                        return;
                    }

                    //use resource path to access
                    mqttDevice = Instantiate(Resources.Load(ResourcePath + device.DeviceType3D), DeviceManager.Instance.transform) as GameObject;

                    //get the MqttDevice script from the instantiated prefab and give it the neccesary init
                    mqttDevice.GetComponent <Device>().initialize(device, isFreshlyAdded);

                    //tell the device manager, that a new device is attached
                    DeviceManager.Instance.newDeviceAttached(mqttDevice);
                }
                else
                {
                    //this prevents the scripts from the device to be reinitialized. Could be the solution tho world anchor problems
                    oldDeviceToRefresh.initialize(device, isFreshlyAdded, true);

                    mqttDevice = oldDeviceToRefresh.gameObject;
                }

                if (getsTargetFromAppBar)
                {
                    mqttDevice.GetComponent <Device>().attachAppBar();
                }
            }
            catch (Exception e)
            {
                //TODO: different error
                Debug.LogError("The Device " + device.DeviceType3D + " could not be generated. Error: " + e.Message);
            }
        }
        /// <summary>
        ///
        /// </summary>
        private IEnumerator publishRemoveDevice(AppData.uniqueIDDevice deviceToRemove)
        {
            //int counter = 3;

            //while (!AppDataExportManager.Instance.isConnected && counter > 0)
            //{//first try every 2 sec
            //    yield return new WaitForSeconds(2);
            //    counter--;
            //}


            //while (!AppDataExportManager.Instance.isConnected)
            //{
            //    //then every 20
            //    yield return new WaitForSeconds(20);
            //}

            yield return(new WaitForFixedUpdate());

            AppDataExportManager.Instance.MQTTPublishMessage(mqttPathForAppData + deviceToRemove.baseAdress, "");//empty message to remove
        }
        private IEnumerator publishDevice(AppData.uniqueIDDevice device)
        {
            //int counter = 3;

            //while (!AppDataExportManager.Instance.isConnected && counter > 0)
            //{//first try every 2 sec
            //    yield return new WaitForSeconds(2);
            //    counter--;
            //}


            //while (!AppDataExportManager.Instance.isConnected)
            //{
            //    //then every 20
            //    yield return new WaitForSeconds(20);
            //}

            yield return(new WaitForFixedUpdate());

            //publish app data in th baseAdress channel
            AppDataExportManager.Instance.MQTTPublishMessage(mqttPathForAppData + device.baseAdress, JsonConvert.SerializeObject(device, Formatting.Indented));
        }
Exemple #13
0
        public void initialize(AppData.uniqueIDDevice deviceData, bool freshlyAddedDevice = false, bool isDeviceRefresh = false)
        {
            this.deviceData = deviceData;


            //baseadress
            baseAdress = deviceData.baseAdress;
            //name
            this.name = deviceData.baseAdress;

            HoverOffsetZ = deviceData.HoverOffsetZ;

            //self manipulate
            selfManipulate = GetComponent <SelfManipulate>();

            //anchor
            worldAnchorUser = GetComponent <WorldAnchorUser>();

            if (!isDeviceRefresh)//if this script is refreshed, we do not need to run this again
            {
                //Manipulation Events:
                selfManipulate.onManipulationStart.AddListener(onManipulationStart);
                selfManipulate.onManipulationEnd.AddListener(onManipulationEnd);



                //worldAnchorUser.linkedAnchor = deviceData.linkedAnchor;

                //start the process of restoring an anchor
                worldAnchorUser.WorldAnchorOperations();
            }


            //set the properties of this mqtt device
            //the position will be set relative to the parent "AllDevices"
            //TODO: is the positioning idea right?


            if (freshlyAddedDevice)
            {
                //set the device infront of the user
                this.transform.position = Camera.main.transform.position + Camera.main.transform.forward * 2f;

                //editor mode must be on
                selfManipulate.active = true;
            }


            //transform.localPosition= new Vector3(deviceData.posX, deviceData.posY, deviceData.posZ);//we have 1 anchor per device and dont need that


            if (isDeviceRefresh)
            {
                //we need to move, so detach
                worldAnchorUser.detachWorldAnchor();
            }

            transform.localEulerAngles = new Vector3(deviceData.rotX, deviceData.rotY, deviceData.rotZ);

            transform.localScale = new Vector3(deviceData.scaleX, deviceData.scaleY, deviceData.scaleZ);

            if (isDeviceRefresh)
            {
                //we need to move, so detach
                worldAnchorUser.attachWorldAnchor();
            }


            if (isDeviceRefresh)
            {
                Debug.Log(name + " refreshed");
            }
            else
            {
                Debug.Log(name + " initialized");
            }
        }