Required packages

# Load Libraries ----------------------------------------------------------
library(tidyverse); library(dplyr); library(plyr); library(lubridate);  library(scales);
library(httr); library(jsonlite)
library(cowplot); library(RColorBrewer); library(ggpubr)

Import data from a .csv file which contains IMEIs and associated school information

setwd(dirname(rstudioapi::getActiveDocumentContext()$path))
lookup <- read.csv('lookupTable.csv', header=TRUE)
names(lookup) <- c("imei","barcode","school","district")

allData <- data.frame(timestamp = as.POSIXct("2024-04-01 01:00:00"),
                      volume = 0, barcode = 0, school = 0, dailyVolume = 0)

Authentication credentials (masked here)

This assigns values to variables userName and password for API access

Import data from MUX (multiplexed) units

i <- 0 #Keeps track of row number
#Loop through the installed DIGI sensors and download data
for(imei in lookup$imei){
  i <- i + 1; print(i) #Show the row being processed
  url <- paste("http://remotemanager.digi.com/ws/v1/streams/history/",
               imei,"/din1/val",sep="")
  barcode <- lookup$barcode[match(imei,lookup$imei)]
  digiData <- GET(url, authenticate(userName, password))
  data = fromJSON(rawToChar(digiData$content))
  data$list$timestamp = strptime(data$list$timestamp, tz = "MST", "%Y-%m-%dT%H:%M:%OSZ")
  rawData = data.frame(data$list$timestamp,as.numeric(data$list$value))
  
  names(rawData) <- c("timestamp","value")
  schoolName <- lookup$school[match(imei,lookup$imei)]
  
  startDate <- as.POSIXct("2024-04-01 00:00:00")
  endDate <- max(rawData$timestamp)
  
  #Write raw data to Historical Data folder
  setwd(paste(getwd(),"/Historical Data V2",sep=""))
  fileName <- paste(barcode,schoolName,date(startDate),date(endDate),".csv")
  write.csv(rawData,file=fileName)
  setwd(dirname(rstudioapi::getActiveDocumentContext()$path))
  
  rawData<-rawData[rawData$timestamp > startDate & rawData$timestamp < endDate,]
  rawData <- rawData[order(rawData$timestamp),] #Order ascending
  
  ####Find Events####
  rawData$event <- "None"
  rawData$event[lag(rawData$value)==1 & rawData$value == 0] <- "Start"
  rawData$event[lag(rawData$value)==0 & rawData$value == 1] <- "End"
  
  if(nrow(rawData[rawData$event != "None",])==0){
    allEvents<-data.frame(timestamp=min(rawData$timestamp),volume=0,barcode=barcode,
                          school=schoolName,dailyVolume=0)} else{
  
  events <- rawData[rawData$event != "None",]
  
  #If we start with an "end" event, cut that out
  if(events$event[1]=="End"){events <- events[-1,]}
  
  #throw an error if there is a time when "start" doesn't follow "end
  errors <- events[lag(events$event)=="Start" & events$event=="Start" |
                     lag(events$event)=="End" & events$event=="End" ,]
  if(is.na(errors[1])){} else{print("ERROR")}
  
  #Turn into an events dataframe
  events$timestamp <- as.POSIXct(events$timestamp)
  events$endtime <- as.POSIXct(lead(events$timestamp))
  events <- events[events$event=="Start",]
  events$durationHours <- as.numeric(difftime(events$endtime,events$timestamp,
                                              units="hours"))
  
  # Convert hours of duration to volume estimates ---------------------------
  offset = 0.16; slope = 5.76
  events$volumeLiters <- offset + (slope*events$durationHours)
  events$endVolume <- cumsum(events$volumeLiters)
  events$startVolume <- lag(events$endVolume); events$startVolume[1] <- 0
  events$barcode <- barcode
  
  #Create dataframe for tracking cumulative volume
  allEvents <- rbind(data.frame(timestamp = events$timestamp, 
                                volume = events$startVolume),
                     data.frame(timestamp = events$endtime, 
                                volume = events$endVolume))
  
  #allEvents[nrow(allEvents),]$timestamp <- endDate
  #allEvents[nrow(allEvents),]$volume <- allEvents[nrow(allEvents)-1,]$volume
  
  firstUseDate <- min(events$timestamp) #Get a starting date for flow rate
  dailyVolume <- 
    max(na.omit(allEvents$volume))/as.numeric(difftime(endDate,firstUseDate,units="day"))
  
  allEvents$barcode <- barcode
  allEvents$school <- paste(schoolName,", ",round(dailyVolume,1)," L/day", sep="")
  allEvents$dailyVolume <- dailyVolume
  
  }
  
  #Add to larger dataframe
  allData <- rbind(allData, allEvents)
  
  # Graph events and total volume -------------------------------------------
  rawData$value <- as.factor(rawData$value)
  rawPlot <- ggplot(data=rawData, aes(timestamp, value)) +
    geom_point(color="darkred") + theme_bw() + xlab("") +
    ylab("Float Switch State") + xlim(startDate, endDate) + 
    ggtitle(paste(barcode,", ", schoolName, ", ",
                  round(dailyVolume,1)," L/day",sep=""))
  
  cummPlot <- ggplot(data=allEvents, aes(timestamp, volume)) +
    geom_area(color="darkblue", fill="lightblue", linewidth=1.5) + theme_bw() + xlab("") + 
    ylab("Cumulative Volume (L)") + xlim(startDate, endDate)
  
  #Combine the plots
  combPlot <- ggarrange(rawPlot, cummPlot, nrow=2, ncol=1, heights=c(1,2),
            align = "hv")
  
  show(combPlot) #Output the plot to the console
}
## [1] 1

## [1] 2

## [1] 3

## [1] 4

## [1] 5

## [1] 6

## [1] 7

## [1] 8

## [1] 9

## [1] 10

## [1] 11

## [1] 12

## [1] 13

## [1] 14

## [1] 15

## [1] 16

## [1] 17

## [1] 18

## [1] 19

## [1] 20

## [1] 21

## [1] 22

## [1] 23

## [1] 24

## [1] 25

## [1] 26

## [1] 27

## [1] 28

## [1] 29

## [1] 30

## [1] 31

## [1] 32

## [1] 33

## [1] 34

## [1] 35

## [1] 36

## [1] 37

## [1] 38

## [1] 39

## [1] 40

## [1] 41

## [1] 42

## [1] 43

## [1] 44

## [1] 45

Collected Volume Plots

allData <- allData[-1,] #Delete initializing row
allData$barcode <- as.factor(allData$barcode); allData$school <- as.factor(allData$school)
allData$district <- as.factor(lookup$district[match(allData$barcode,
                                                    lookup$barcode)])

allVolumes <- ggplot(data=allData, aes(timestamp, volume)) +
  geom_area(color="darkblue", fill="lightblue", linewidth=1.5) + theme_bw() + 
  xlab("") +
  ylab("Cumulative Volume (L)") + facet_wrap(~ school, scales="free_y")

show(allVolumes)