221 lines
9.1 KiB
R
221 lines
9.1 KiB
R
|
#setup ----
|
||
|
library(tidyverse)
|
||
|
library(lubridate)
|
||
|
library(httr)
|
||
|
library(jsonlite)
|
||
|
library(plotly)
|
||
|
library(scales)
|
||
|
|
||
|
setwd("~/Documents/dataProjects/ecobee")
|
||
|
|
||
|
pause = function()
|
||
|
{
|
||
|
if (interactive())
|
||
|
{
|
||
|
invisible(readline(prompt = "Press <Enter> to continue..."))
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
cat("Press <Enter> to continue...")
|
||
|
invisible(readLines(file("stdin"), 1))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#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-13')
|
||
|
|
||
|
enddate <- Sys.Date()
|
||
|
columns <- c('zoneClimate',
|
||
|
'compHeat1',
|
||
|
'auxHeat1',
|
||
|
'compCool1',
|
||
|
'fan',
|
||
|
'outdoorTemp',
|
||
|
'outdoorHumidity',
|
||
|
'zoneAveTemp',
|
||
|
'zoneHeatTemp',
|
||
|
'zoneCoolTemp',
|
||
|
'zoneHumidity',
|
||
|
'zoneHvacMode')
|
||
|
|
||
|
months <- data.frame(start = seq(floor_date(startdate, unit = "months"),
|
||
|
floor_date(enddate, unit = "months"),
|
||
|
length.out = interval(floor_date(startdate, unit = "months"), enddate) %/% months(1) + 1))
|
||
|
months <- months %>%
|
||
|
mutate(end = start + months(1) - 1)
|
||
|
|
||
|
ecobee_new <- list(NULL)
|
||
|
for(i in 1:nrow(months)){
|
||
|
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_new[[i]] <- 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())
|
||
|
}
|
||
|
ecobee <- bind_rows(ecobee_new)
|
||
|
|
||
|
save(ecobee, file = 'data/ecobee.Rda')
|
||
|
|
||
|
daterange <- data.frame(start = min(ecobee$date), end = max(ecobee$date))
|
||
|
|
||
|
# 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), 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)')
|
||
|
|
||
|
ggplot() +
|
||
|
geom_line(data = ecobee %>% filter(date > Sys.Date() - 3) %>% 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() - 3) %>% pivot_longer(cols = c(compHeat1, auxHeat1, compCool1), 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)')
|
||
|
|
||
|
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')
|
||
|
|
||
|
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)"))
|
||
|
|
||
|
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)) %>%
|
||
|
pivot_longer(cols = c(compHeat1, compCool1, auxHeat1), 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)')
|
||
|
|