private string UpdateNestData(string type, string id, string data, string accessToken)
 {
     string r="";
     if (!accessToken.Equals(""))
     {
         string path = type + "/" + id;
         Log.Debug("about to send update to nest: path=" + path + ", value=" + data + "");
         var firebaseClient = new Firebase("https://developer-api.nest.com", accessToken);
         try
         {
             r = firebaseClient.Put(path, data);
         }
         catch (Exception e)
         {
             string[] lines = e.ToString().Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None);
             r = "Error updating firebase: " + lines[0];
         }
         firebaseClient.Dispose();
     }
     return r;
 }
        //returns true if data has changed (used to try to determine when data streaming has stopped working)
        private Boolean GetNestData(string accessToken)
        {
            bool datachanged = false;
            if (!accessToken.Equals(""))
            {
                var firebaseClient = new Firebase("https://developer-api.nest.com", accessToken);
                //get structure data
                try
                {
                    string structureData = firebaseClient.Get("structures");
                    dynamic data = JsonConvert.DeserializeObject<dynamic>(structureData);
                    var myStructures = new List<Structure>();
                    foreach (var itemDynamic in data)
                        myStructures.Add(JsonConvert.DeserializeObject<Structure>(((JProperty)itemDynamic).Value.ToString()));

                    foreach (Structure structure in myStructures)
                    {
                        //if structure does not exist then add it
                        if (!OSAEObjectManager.ObjectExists(structure.structure_id))
                        {
                            Log.Debug("about to add structure: " + structure.name + " address: " + structure.structure_id + ".");
                            OSAEObject _nameObject = OSAEObjectManager.GetObjectByName(structure.name);
                            //OSAEObjectManager.GetObjectByAddress(structure.structure_id)
                            if (_nameObject != null)
                                Log.Error("Object with name: " + _nameObject.Name + " exists but it's address doesn't match - objects address: " + _nameObject.Address + ". - device_id from nest:" + structure.structure_id + ".");

                            OSAEObjectManager.ObjectAdd(structure.name,"", structure.name, "NEST STRUCTURE", structure.structure_id, "",30, true);
                        }
                        string objectName = OSAEObjectManager.GetObjectByAddress(structure.structure_id).Name;
                        //load current data into structure object
                        Structure currentdata = new Structure();
                        currentdata.loadData(objectName);
                        //compare structure data to data we have
                        if (!structure.SameData(currentdata))
                        {
                            datachanged = true;
                            // list the changes temporarily to see how it is working
                            List<Variance> variances = structure.DetailedCompare(currentdata);
                            foreach (Variance v in variances)
                                Log.Debug(v.Prop + " value changed from " + v.valB.ToString() + " to " + v.valA.ToString());
                        }
                        //update structure data
                        OSAEObjectStateManager.ObjectStateSet(objectName, structure.away, pName);
                        OSAEObjectPropertyManager.ObjectPropertySet(objectName, "Id", structure.structure_id, pName);
                        OSAEObjectPropertyManager.ObjectPropertySet(objectName, "Name", structure.name, pName);
                        OSAEObjectPropertyManager.ObjectPropertySet(objectName, "Country Code", structure.country_code, pName);
                        OSAEObjectPropertyManager.ObjectPropertySet(objectName, "Postal Code", structure.postal_code, pName);
                        OSAEObjectPropertyManager.ObjectPropertySet(objectName, "Peak Start Time", structure.peak_period_start_time, pName);
                        OSAEObjectPropertyManager.ObjectPropertySet(objectName, "Peak End Time", structure.peak_period_end_time, pName);
                        OSAEObjectPropertyManager.ObjectPropertySet(objectName, "Time Zone", structure.time_zone, pName);
                    }
                }
                catch (Exception e)
                {
                    string[] lines = e.ToString().Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None);
                    Log.Error("error getting structure data. " + lines[0]);
                }

                //get thermostat data
                try
                {
                    string thermostatData = firebaseClient.Get("devices/thermostats");

                    dynamic data = JsonConvert.DeserializeObject<dynamic>(thermostatData);
                    var myThermostats = new List<Thermostat>();
                    foreach (var itemDynamic in data)
                        myThermostats.Add(JsonConvert.DeserializeObject<Thermostat>(((JProperty)itemDynamic).Value.ToString()));

                    foreach (Thermostat thermostat in myThermostats)
                    {
                        //if thermostat does not exist then add it
                        if (!OSAEObjectManager.ObjectExists(thermostat.device_id))
                        {
                            Log.Debug("about to add thermostat: " + thermostat.name_long + " address: " + thermostat.device_id);
                            OSAEObject _nameObject = OSAEObjectManager.GetObjectByName(thermostat.name);
                            if (_nameObject != null)
                                Log.Error("Object with name: " + _nameObject.Name + " exists but it's address doesn't match - objects address: " + _nameObject.Address + ". - device_id from nest:" + thermostat.structure_id + ".");

                            OSAEObjectManager.ObjectAdd(thermostat.name,"", thermostat.name_long, "NEST THERMOSTAT", thermostat.device_id, "", 30, true);
                        }
                        string objectName = OSAEObjectManager.GetObjectByAddress(thermostat.device_id).Name;

                        //load current data into thermostat object
                        Thermostat currentdata = new Thermostat();
                        currentdata.loadData(objectName);
                        //compare thermostat data to data we have
                        thermostat.tempToScale(); // set all temps to current scale for comparision since we don't save both in OSA object (will have to load current scale into both _c and _f fields)
                        thermostat.convertLastConnection(); //converts last connection to current time zone and to the same format that OSA will return for comaprison

                        if (!thermostat.SameData(currentdata))
                        {
                            datachanged = true;
                            // list the changes temporarily to see how it is working
                            List<Variance> variances = thermostat.DetailedCompare(currentdata);
                            Log.Debug("Number of fields changed: " + variances.Count);
                            foreach (Variance v in variances)
                                Log.Debug(v.Prop + " value changed from " + v.valB.ToString() + " to " + v.valA.ToString());
                        }

                        //update structure data
                        if (thermostat.is_online)
                            OSAEObjectStateManager.ObjectStateSet(objectName, thermostat.hvac_mode, pName);
                        else
                            OSAEObjectStateManager.ObjectStateSet(objectName, "Offline", pName);

                        OSAEObjectPropertyManager.ObjectPropertySet(objectName, "Id", thermostat.device_id, pName);
                        OSAEObjectPropertyManager.ObjectPropertySet(objectName, "Name", thermostat.name, pName);
                        OSAEObjectPropertyManager.ObjectPropertySet(objectName, "Name Long", thermostat.name_long, pName);
                        OSAEObjectPropertyManager.ObjectPropertySet(objectName, "Ambient Temperature", (thermostat.temperature_scale == "F") ? thermostat.ambient_temperature_f.ToString() : thermostat.ambient_temperature_c.ToString(), pName);
                        OSAEObjectPropertyManager.ObjectPropertySet(objectName, "Humidity", thermostat.humidity.ToString(), pName);
                        OSAEObjectPropertyManager.ObjectPropertySet(objectName, "Target Temperature", (thermostat.temperature_scale == "F") ? thermostat.target_temperature_f.ToString() : thermostat.target_temperature_c.ToString(), pName);
                        OSAEObjectPropertyManager.ObjectPropertySet(objectName, "Target Temperature High", (thermostat.temperature_scale == "F") ? thermostat.target_temperature_high_f.ToString() : thermostat.target_temperature_high_c.ToString(), pName);
                        OSAEObjectPropertyManager.ObjectPropertySet(objectName, "Target Temperature Low", (thermostat.temperature_scale == "F") ? thermostat.target_temperature_low_f.ToString() : thermostat.target_temperature_low_c.ToString(), pName);
                        OSAEObjectPropertyManager.ObjectPropertySet(objectName, "Away Temperature High", (thermostat.temperature_scale == "F") ? thermostat.away_temperature_high_f.ToString() : thermostat.away_temperature_high_c.ToString(), pName);
                        OSAEObjectPropertyManager.ObjectPropertySet(objectName, "Away Temperature Low", (thermostat.temperature_scale == "F") ? thermostat.away_temperature_low_f.ToString() : thermostat.away_temperature_low_c.ToString(), pName);
                        OSAEObjectPropertyManager.ObjectPropertySet(objectName, "Has Leaf", thermostat.has_leaf.ToString(), pName);
                        OSAEObjectPropertyManager.ObjectPropertySet(objectName, "Temperature Scale", thermostat.temperature_scale, pName);
                        OSAEObjectPropertyManager.ObjectPropertySet(objectName, "Locale", thermostat.locale, pName);
                        OSAEObjectPropertyManager.ObjectPropertySet(objectName, "Software Version", thermostat.software_version, pName);
                        OSAEObjectPropertyManager.ObjectPropertySet(objectName, "Structure ID", thermostat.structure_id, pName);
                        OSAEObjectPropertyManager.ObjectPropertySet(objectName, "Last Connection", thermostat.last_connection, pName);
                        OSAEObjectPropertyManager.ObjectPropertySet(objectName, "Is Online", thermostat.is_online.ToString(), pName);
                        OSAEObjectPropertyManager.ObjectPropertySet(objectName, "Can Cool", thermostat.can_cool.ToString(), pName);
                        OSAEObjectPropertyManager.ObjectPropertySet(objectName, "Can Heat", thermostat.can_heat.ToString(), pName);
                        OSAEObjectPropertyManager.ObjectPropertySet(objectName, "Using Emergency Heat", thermostat.is_using_emergency_heat.ToString(), pName);
                        OSAEObjectPropertyManager.ObjectPropertySet(objectName, "Has Fan", thermostat.has_fan.ToString(), pName);
                        OSAEObjectPropertyManager.ObjectPropertySet(objectName, "Fan Timer Active", thermostat.fan_timer_active.ToString(), pName);
                        OSAEObjectPropertyManager.ObjectPropertySet(objectName, "Fan Timer Timeout", thermostat.fan_timer_timeout, pName);
                    }
                }
                catch (Exception e)
                {
                    string[] lines = e.ToString().Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None);
                    Log.Error("error getting thermostat data. " + lines[0]);
                }

                //get smokealarm data
                try
                {
                    string smokeData = firebaseClient.Get("devices/smoke_co_alarms");

                    dynamic data = JsonConvert.DeserializeObject<dynamic>(smokeData);
                    var mySmokeAlarms = new List<SmokeAlarm>();
                    foreach (var itemDynamic in data)
                        mySmokeAlarms.Add(JsonConvert.DeserializeObject<SmokeAlarm>(((JProperty)itemDynamic).Value.ToString()));

                    foreach (SmokeAlarm smokealarm in mySmokeAlarms)
                    {
                        //if smokealarm does not exist then add it
                        if (!OSAEObjectManager.ObjectExists(smokealarm.device_id))
                        {
                            Log.Debug("about to add nest protect: " + smokealarm.name_long + " address: " + smokealarm.device_id);

                            OSAEObject _nameObject = OSAEObjectManager.GetObjectByName(smokealarm.name);
                            if (_nameObject != null)
                                Log.Error("Object with name: " + _nameObject.Name + " exists but it's address doesn't match - objects address: " + _nameObject.Address + ". - device_id from nest:" + smokealarm.structure_id + ".");

                            OSAEObjectManager.ObjectAdd(smokealarm.name,"", smokealarm.name_long, "NEST PROTECT", smokealarm.device_id, "", 30, true);
                        }
                        string objectName = OSAEObjectManager.GetObjectByAddress(smokealarm.device_id).Name;

                        //load current data into smokealarm object
                        SmokeAlarm currentdata = new SmokeAlarm();
                        smokealarm.convertLastConnection();
                        currentdata.loadData(objectName);
                        //compare smokealarm data to data we have
                        if (!smokealarm.SameData(currentdata))
                        {
                            datachanged = true;
                            // list the changes temporarily to see how it is working
                            List<Variance> variances = smokealarm.DetailedCompare(currentdata);
                            Log.Debug("Number of fields changed: " + variances.Count);
                            foreach (Variance v in variances)
                                Log.Debug(v.Prop + " value changed from " + v.valB.ToString() + " to " + v.valA.ToString());
                        }

                        //update structure data
                        if (smokealarm.is_online)
                        {
                            if (smokealarm.smoke_alarm_state.Equals("emergency"))
                                OSAEObjectStateManager.ObjectStateSet(objectName, "Smoke Emergency", pName);
                            else if (smokealarm.co_alarm_state.Equals("emergency"))
                                OSAEObjectStateManager.ObjectStateSet(objectName, "CO Emergency", pName);
                            else if (smokealarm.smoke_alarm_state.Equals("warning"))
                                OSAEObjectStateManager.ObjectStateSet(objectName, "Smoke Warning", pName);
                            else if (smokealarm.co_alarm_state.Equals("warning"))
                                OSAEObjectStateManager.ObjectStateSet(objectName, "CO Warning", pName);
                            else if (smokealarm.battery_health.Equals("replace"))
                                OSAEObjectStateManager.ObjectStateSet(objectName, "Battery Replace", pName);
                            else
                                OSAEObjectStateManager.ObjectStateSet(objectName, "Online", pName);
                        }
                        else
                            OSAEObjectStateManager.ObjectStateSet(objectName, "Offline", pName);

                        OSAEObjectPropertyManager.ObjectPropertySet(objectName, "Id", smokealarm.device_id, pName);
                        OSAEObjectPropertyManager.ObjectPropertySet(objectName, "Name", smokealarm.name, pName);
                        OSAEObjectPropertyManager.ObjectPropertySet(objectName, "Name Long", smokealarm.name_long, pName);
                        OSAEObjectPropertyManager.ObjectPropertySet(objectName, "Battery Health", smokealarm.battery_health, pName);
                        OSAEObjectPropertyManager.ObjectPropertySet(objectName, "CO Alarm State", smokealarm.co_alarm_state, pName);
                        OSAEObjectPropertyManager.ObjectPropertySet(objectName, "Smoke Alarm State", smokealarm.smoke_alarm_state, pName);
                        OSAEObjectPropertyManager.ObjectPropertySet(objectName, "Manual Test Active", smokealarm.is_manual_test_active.ToString(), pName);
                        OSAEObjectPropertyManager.ObjectPropertySet(objectName, "Last Manual Test", smokealarm.last_manual_test_time, pName);
                        OSAEObjectPropertyManager.ObjectPropertySet(objectName, "UI Color State", smokealarm.ui_color_state, pName);
                        OSAEObjectPropertyManager.ObjectPropertySet(objectName, "Locale", smokealarm.locale, pName);
                        OSAEObjectPropertyManager.ObjectPropertySet(objectName, "Software Version", smokealarm.software_version, pName);
                        OSAEObjectPropertyManager.ObjectPropertySet(objectName, "Structure ID", smokealarm.structure_id, pName);
                        OSAEObjectPropertyManager.ObjectPropertySet(objectName, "Last Connection", smokealarm.last_connection, pName);
                        OSAEObjectPropertyManager.ObjectPropertySet(objectName, "Is Online", smokealarm.is_online.ToString(), pName);
                    }
                }
                catch (Exception e)
                {
                    string[] lines = e.ToString().Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None);
                    Log.Debug("error getting smokealarm data. " + lines[0]);
                }
                firebaseClient.Dispose();
            }
            return datachanged;
        }