#setup ---- library(tidyverse) library(lubridate) library(httr) library(jsonlite) library(plotly) library(scales) library(readODS) library(ggrepel) setwd("~/Documents/dataProjects/ecobee") #make a file called 'apiKey' in your working directory that has your api key for your ecobee if(file.exists('authTokens.Rda')) { #if the authToken file already exists, then refresh it load(file = "authTokens.Rda") url <- paste0("https://api.ecobee.com/token?grant_type=refresh_token&code=", authTokens$refreshToken, "&client_id=", read_file('apiKey')) res <- content(httr::GET(url = url)) authTokens <- data.frame(accessToken = res$access_token, refreshToken = res$refresh_token) save(authTokens, file = "authTokens.Rda") access_token <- authTokens$accessToken remove(res, url, authTokens) } else { #if the authToken file does not exist than set it up, this will require adding the app to your ecobee account permissions <- 'smartRead' url <- paste0('https://api.ecobee.com/authorize?response_type=ecobeePin&client_id=',read_file('apiKey'),'&scope=',permissions) res1 <- content(httr::GET(url = url)) message(paste("add a new app to your ecobee account and authorize it with this PIN -", res1$ecobeePin)) pause() url2 <- paste0("https://api.ecobee.com/token?grant_type=ecobeePin&code=",res1$code,"&client_id=",read_file('apiKey')) res2 <- content(httr::GET(url = url2)) authTokens <- data.frame(accessToken = res2$access_token, refreshToken = res2$refresh_token) save(authTokens, file = "authTokens.Rda") access_token <- authTokens$accessToken rm(permissions, url, res1, url2, res2) } # load data ---- startdate <- ymd('2021-11-01') enddate <- Sys.Date() columns <- c('zoneClimate', 'compHeat1', 'auxHeat1', 'compCool1', 'fan', 'outdoorTemp', 'outdoorHumidity', 'zoneAveTemp', 'zoneHeatTemp', 'zoneCoolTemp', 'zoneHumidity', 'zoneHvacMode') months <- data.frame(start = seq(startdate, enddate, by = "month")) months <- months %>% mutate(end = start + months(1) - 1) ecobee <- list(NULL) for(i in 1:nrow(months)){ if(file.exists(paste0('data/',months$start[i], '.Rda')) && Sys.Date() > months$end[i]){ message(paste("Loading", months$start[[i]], "to", months$end[[i]])) load(file=paste0('data/',months$start[i], '.Rda')) } else{ message(paste("Downloading", months$start[[i]], "to", months$end[[i]])) url <- paste0('https://api.ecobee.com/1/runtimeReport?format=json&body={"startDate":', paste0('\"',as.Date(months$start[i]),'\",'), '"endDate":', paste0('\"',as.Date(months$end[i]),'\",'), '"columns":', paste0('\"',paste0(columns, collapse = ","),'\"'), ',"selection":{"selectionType":"thermostats","selectionMatch":"413788899054"}}') ecobee_month <- httr::GET( url = url, add_headers('Content-Type' = 'application/json;charset=UTF-8', 'Authorization' = paste0('Bearer ', access_token) ) ) %>% httr::content() # parse data ---- ecobee_month <- tibble(ecobee_month[["reportList"]][[1]][["rowList"]]) %>% separate(sep = ",", col = 1, into = c('date', 'time', columns), convert=TRUE) %>% mutate("duration_sec" = 5*60, "dateTime" = ymd_hms(paste(date, time)), outdoortemp_bin = round(outdoorTemp)) %>% filter(ymd(date) <= Sys.Date()) if(Sys.Date() > months$end[i]){ save(ecobee_month, file = paste0('data/',months$start[i], '.Rda')) } } ecobee[[i]] <- ecobee_month } ecobee <- bind_rows(ecobee) daterange <- data.frame(start = min(ecobee$date), end = max(ecobee$date)) # import utility data ---- utility_data <- read_ods(path = "~/Documents/1333 E 6th St/Expenses.ods", sheet = 2) utility_data <- utility_data %>% mutate(start_date = mdy(`start date`), end_date = mdy(`end date`)) for(i in 1:nrow(utility_data)){ utility_data[i, "heat_pump_hours"] <- sum(ecobee %>% filter(dateTime > utility_data$start_date[i], dateTime <= utility_data$end_date[i]) %>% pull(compHeat1), na.rm = TRUE)/3600 utility_data[i, "heat_aux_hours"] <- sum(ecobee %>% filter(dateTime > utility_data$start_date[i], dateTime <= utility_data$end_date[i]) %>% pull(auxHeat1), na.rm = TRUE)/3600 utility_data[i, "cool_pump_hours"] <- sum(ecobee %>% filter(dateTime > utility_data$start_date[i], dateTime <= utility_data$end_date[i]) %>% pull(compCool1), na.rm = TRUE)/3600 } # color scale ---- temp_types <- data.frame(column = c('zoneAveTemp', 'zoneHeatTemp', 'zoneCoolTemp', 'outdoorTemp'), label = c('Indoor', 'Set (heat)', 'Set (cool)', 'Outdoor'), color = c('black', 'orange', 'blue', 'grey')) equipment_types <- data.frame(column = c('compHeat1', 'auxHeat1', 'compCool1', 'fan'), label = c('Heat pump (heat)', 'Aux heat', 'Heat pump (cool)', 'Fan'), color = c('orange', 'red', 'blue', 'grey'), offset = c(0,1,2,3)) equipment_y <- max(ecobee$zoneCoolTemp, ecobee$outdoorTemp, na.rm = TRUE) + 1 # make plots ---- ggplot() + geom_line(data = ecobee %>% pivot_longer(cols = c(zoneAveTemp, outdoorTemp, zoneHeatTemp, zoneCoolTemp), names_to = "temp_type", values_to = "temp"), aes(x = dateTime, y = temp, color = temp_type))+ geom_rect(data = ecobee %>% pivot_longer(cols = c(compHeat1, auxHeat1, compCool1, fan), names_to = "equipment", values_to = "active_sec") %>% filter(active_sec > 0), aes(xmin = dateTime, xmax = dateTime + active_sec, ymin = equipment_y + equipment_types[match(equipment, equipment_types$column), 4], ymax = equipment_y + equipment_types[match(equipment, equipment_types$column), 4] + 1, fill = equipment)) + scale_color_manual(labels = temp_types$label, values = temp_types %>% pull(color, column)) + scale_fill_manual(labels = equipment_types$label, values = equipment_types %>% pull(color, column)) + theme(legend.title = element_blank()) + labs(x = 'Date', y = 'Temperature (\u00B0F)') ggsave(filename = "temp_time_all.png" , path = paste(getwd(),"/figures/", sep = ""), device = "png", width = 11, height = 8.5, units = "in") ggplot() + geom_line(data = ecobee %>% filter(date > Sys.Date() - 7) %>% pivot_longer(cols = c(zoneAveTemp, outdoorTemp, zoneHeatTemp, zoneCoolTemp), names_to = "temp_type", values_to = "temp"), aes(x = dateTime, y = temp, color = temp_type))+ geom_rect(data = ecobee %>% filter(date > Sys.Date() - 7) %>% pivot_longer(cols = c(compHeat1, auxHeat1, compCool1, fan), names_to = "equipment", values_to = "active_sec") %>% filter(active_sec > 0), aes(xmin = dateTime, xmax = dateTime + active_sec, ymin = equipment_y + equipment_types[match(equipment, equipment_types$column), 4], ymax = equipment_y + equipment_types[match(equipment, equipment_types$column), 4] + 1, fill = equipment)) + scale_color_manual(labels = temp_types$label, values = temp_types %>% pull(color, column)) + scale_fill_manual(labels = equipment_types$label, values = equipment_types %>% pull(color, column)) + theme(legend.title = element_blank()) + labs(x = 'Date', y = 'Temperature (\u00B0F)') ggsave(filename = "temp_time_last_week.png" , path = paste(getwd(),"/figures/", sep = ""), device = "png", width = 11, height = 8.5, units = "in") ggplot(data = ecobee %>% filter(date != "2021-11-13", date != today()) %>% filter(zoneClimate != "") %>% pivot_longer(cols = c(compHeat1, auxHeat1, compCool1, fan), names_to = "equipment", values_to = "active_sec") %>% group_by(outdoortemp_bin, equipment, zoneClimate) %>% summarize(percent_active = sum(active_sec, na.rm = TRUE)/sum(duration_sec, na.rm = TRUE), n = n()), aes(x = outdoortemp_bin, y = percent_active, color = equipment, shape = zoneClimate)) + geom_point(aes(size = n)) + geom_smooth(aes(linetype = zoneClimate), se = FALSE) + scale_color_manual(labels = equipment_types$label, values = equipment_types %>% pull(color, column)) + scale_y_continuous(labels = label_percent(), expand = expansion(mult = c(0,0))) + labs(x = 'Outdoor Temperature (\u00B0F)', y = 'Percent of the time the equipment runs') ggsave(filename = "outdoorTemp_equipmentRun_zone.png" , path = paste(getwd(),"/figures/", sep = ""), device = "png", width = 11, height = 8.5, units = "in") ggplot() + geom_col(data = ecobee %>% pivot_longer(cols = c(compHeat1, auxHeat1, compCool1), names_to = "equipment", values_to = "active_sec"), aes(x = as.Date(dateTime) + hours(12), y = active_sec/60/60, fill = equipment)) + scale_fill_manual(labels = equipment_types$label, values = equipment_types %>% pull(color, column)) + geom_line(data = ecobee, aes(x = dateTime, y = outdoorTemp/5, color = 'Outdoor')) + labs(x = 'date', y = 'Time equipment runs (hours)') + scale_y_continuous(sec.axis = sec_axis(trans = ~ .x*5, name = "Temperature (\u00B0F)")) ggsave(filename = "dateDay_timeRunning.png" , path = paste(getwd(),"/figures/", sep = ""), device = "png", width = 11, height = 8.5, units = "in") ggplot() + geom_col(data = ecobee %>% pivot_longer(cols = c(compHeat1, auxHeat1, compCool1), names_to = "equipment", values_to = "active_sec"), aes(x = floor_date(dateTime, 'weeks'), y = active_sec/60/60, fill = equipment)) + scale_fill_manual(labels = equipment_types$label, values = equipment_types %>% pull(color, column)) + geom_line(data = ecobee, aes(x = dateTime, y = outdoorTemp/5*7, color = 'Outdoor')) + labs(x = 'date', y = 'Time equipment runs (hours)') + scale_y_continuous(sec.axis = sec_axis(trans = ~ .x*5/7, name = "Temperature (\u00B0F)")) ggsave(filename = "dateWeek_timeRunning.png" , path = paste(getwd(),"/figures/", sep = ""), device = "png", width = 11, height = 8.5, units = "in") ggplot(data = ecobee %>% filter(date != "2021-11-13", date != today()) %>% group_by(date) %>% summarise(outdoorTemp = mean(outdoorTemp), compHeat1 = sum(compHeat1, na.rm = TRUE), compCool1 = sum(compCool1, na.rm = TRUE), auxHeat1 = sum(auxHeat1, na.rm = TRUE), fan = sum(fan, na.rm = TRUE)) %>% pivot_longer(cols = c(compHeat1, compCool1, auxHeat1, fan), names_to = 'equipment', values_to = 'active_sec') %>% filter(active_sec > 0), aes(x = outdoorTemp, y = active_sec/60/60, color = equipment)) + geom_point() + geom_smooth(se = FALSE) + scale_y_continuous(limits = c(0, 24), expand = expansion(mult = c(0,0))) + scale_color_manual(labels = equipment_types$label, values = equipment_types %>% pull(color, column)) + labs(x = 'Outdoor Temperature (\u00B0F)', y = 'Time equipment runs (hours)') ggsave(filename = "outdoorTemp_equipmentRun.png" , path = paste(getwd(),"/figures/", sep = ""), device = "png", width = 11, height = 8.5, units = "in") ggplot(data = utility_data %>% filter(start_date>startdate)) + geom_point(aes(x = `Electricity (kWh)`, y = heat_pump_hours+heat_aux_hours+cool_pump_hours)) + geom_label_repel(aes(x = `Electricity (kWh)`, y = heat_pump_hours+heat_aux_hours+cool_pump_hours, label = `mid date`)) + scale_x_continuous(limits = c(0, NA), expand = expansion(mult = c(0,0.1))) + scale_y_continuous(limits = c(0, NA), expand = expansion(mult = c(0,0.1))) ggsave(filename = "equipmentRun_electicCost.png" , path = paste(getwd(),"/figures/", sep = ""), device = "png", width = 11, height = 8.5, units = "in")