Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resolve Issue #38 Nighttime CW #50

Draft
wants to merge 8 commits into
base: dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions py_src/night_cw/nightCW_handler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# python_template/handler.py
from datetime import datetime, timedelta
from requests.exceptions import ConnectionError, HTTPError
import numpy as np
from scipy.stats import norm
from python_lib.utils import parse_event, fetch_trends
import json


def run(event, context):
# start out with blank response
response = {"statusCode": 200, "body": ""}
now = datetime.now()
# print(f"testTemplate run at {now} with event {event}")
# parse event and ensure timeStamp and pointName are present
params = parse_event(event)
end_time = params.get("timeStamp")
start_time = end_time - timedelta(30)
point_name = params.get("pointName")
try:
# fetch the trends
trend_response = fetch_trends(
point=point_name, start_time=start_time, end_time=end_time
)
# at this point, status_code must be 200 or an exception would be raised
# data should always be there, but just to be on the safe side, make an if statement
datapoints = trend_response[0]["datapoints"]
target_range = 7
#target_range is the number of back from today that are being considered
threshhold = 0.3
#threshhold is the cumulative distribution percentage that is the baseline
for i in range(target_range):
datapoints.pop()
#removes the target data from the data that will be used to create the baseline
baseload = datapoints.ppf(threshhold)
#.ppf function returns the value at the cumulative distribution threshhold
target = trend_response[0]["datapoints"][(len(datapoints)-1):]
#extracts the target points from the trend response
if target.ppf(threshhold) > baseload:
response[
"body"
] = f"""{point_name} has a baseload {target.ppf(threshhold)} which is greater than the previous baseload{baseload}
for the period {start_time:%Y-%m-%d %H:%M} to {end_time:%Y-%m-%d %H:%M}"""
#returns the response when the target baseload has increased.
except ConnectionError as err:
response[
"body"
] = f"{point_name} ConnectionError: {err.response.text} {start_time:%Y-%m-%d %H:%M} to {end_time:%Y-%m-%d %H:%M}"
except HTTPError as err:
response[
"body"
] = f"{point_name} {err.response.text} for the period {start_time:%Y-%m-%d %H:%M} to {end_time:%Y-%m-%d %H:%M}"
if err.response.status_code == 400:
try: # have to try decoding json
if err.response.json()["error"] == "No data":
response[
"body"
] = f"{point_name} has no data for the period {start_time:%Y-%m-%d %H:%M} to {end_time:%Y-%m-%d %H:%M}"
except ValueError as e:
pass
return response
118 changes: 118 additions & 0 deletions py_src/night_cw/nightCW_spec.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
from python_template.handler import run
from requests.exceptions import HTTPError
from requests.models import Response
import json


anom_case = open('night_cw/testcases/decrease.json')
"""
decrease.json contains the reponse from the following JSON request body:
{
"range": {
"from": "2024-02-01T19:38:47.334Z",
"to": "2024-05-30T19:38:47.334Z"
},
"interval": "30s",
"intervalMs": 5500,
"maxDataPoints": 50,
"targets": [
{
"target": "BakerLab.CW.FP/TONS"
}

]
}
"""

noanom_case = open('night_cw/testcases/increase.json')
"""
increase.json contains the reponse from the following JSON request body:
{
"range": {
"from": "2022-03-01 20:06:08",
"to": "2022-04-04 20:06:08"
},

"targets": [
{
"target": "BiotechnologyBuilding.CW.FP/TONS"
}
]
}
"""
def test_nobarf(mocker):
event = {
"body": {
"pointName": "KlarmanHall.Elec.Solar.PowerScout3037/kW_System",
"timeStamp": "2022-10-05T23:58:47.390Z",
}
}
mocker.patch(
"python_template.handler.fetch_trends",
return_value= [{"datapoints": []}],
)

result = run(event, None)
assert "statusCode" in result
assert "missing more than 10%" in result.get("body")


def test_handle400(mocker):
r = Response()
r.status_code = 400
r._content = b'{"error":"No data"}'
mocker.patch(
"python_template.handler.fetch_trends", side_effect=HTTPError(response=r)
)
event = {"body": {"pointName": "foo"}}
result = run(event, None)
assert "statusCode" in result
assert "no data" in result.get("body")


def test_barf(mocker):
r = Response()
r.status_code = 400
r._content = b"qwerty"
mocker.patch(
"python_template.handler.fetch_trends", side_effect=HTTPError(response=r)
)
event = {"body": {"pointName": "foo"}}
result = run(event, None)
assert "statusCode" in result
assert "qwerty" in result.get("body")




def test_CW_decrease(mocker):
event = {
"body": {
"pointName": "KlarmanHall.Elec.Solar.PowerScout3037/kW_System",
"timeStamp": "2022-10-05T23:58:47.390Z",
}
}
data = json.load(noanom_case)
mocker.patch(
"python_template.handler.fetch_trends",
return_value = data,
)
result = run(event, None)
assert "statusCode" in result
assert "" == result.get("body")

def test_CW_increase(mocker):
event = {
"body": {
"pointName": "KlarmanHall.Elec.Solar.PowerScout3037/kW_System",
"timeStamp": "2022-10-05T23:58:47.390Z",
}
}
data = json.load(anom_case)
mocker.patch(
"python_template.handler.fetch_trends",
return_value = data,
)
result = run(event, None)
assert "statusCode" in result
assert "baseload" in result.get("body")
Loading
Loading