-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor handling of points for openstudio
- Loading branch information
1 parent
9fad399
commit 9fb7bc0
Showing
5 changed files
with
211 additions
and
185 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
89 changes: 89 additions & 0 deletions
89
alfalfa_worker/jobs/openstudio/lib/openstudio_component.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
|
||
from dataclasses import dataclass | ||
from enum import Enum | ||
from typing import Callable | ||
|
||
from alfalfa_worker.lib.job_exception import JobException | ||
|
||
# import pyenergyplus | ||
|
||
|
||
class OpenStudioComponentType(Enum): | ||
ACTUATOR = "Actuator" | ||
CONSTANT = "Constant" | ||
OUTPUT_VARIABLE = "OutputVariable" | ||
GLOBAL_VARIABLE = "GlobalVariable" | ||
METER = "Meter" | ||
|
||
|
||
@dataclass | ||
class OpenStudioComponent: | ||
type: OpenStudioComponentType | ||
parameters: dict | ||
handle: int = None | ||
|
||
def __init__(self, type: str, parameters: dict, handle: int = None, converter: Callable[[float], float] = None): | ||
self.type = OpenStudioComponentType(type) | ||
self.parameters = parameters | ||
self.handle = handle | ||
|
||
if converter: | ||
self.converter = converter | ||
else: | ||
self.converter = lambda x: x | ||
|
||
if self.type == OpenStudioComponentType.ACTUATOR: | ||
self.reset = False | ||
|
||
def pre_initialize(self, api, state): | ||
if self.type == OpenStudioComponentType.OUTPUT_VARIABLE: | ||
api.exchange.request_variable(state, **self.parameters) | ||
|
||
def initialize(self, api, state): | ||
if self.type == OpenStudioComponentType.GLOBAL_VARIABLE: | ||
self.handle = api.exchange.get_ems_global_handle(state, var_name=self.parameters["variable_name"]) | ||
elif self.type == OpenStudioComponentType.OUTPUT_VARIABLE: | ||
self.handle = api.exchange.get_variable_handle(state, **self.parameters) | ||
elif self.type == OpenStudioComponentType.METER: | ||
self.handle = api.exchange.get_meter_handle(state, **self.parameters) | ||
elif self.type == OpenStudioComponentType.ACTUATOR: | ||
self.handle = api.exchange.get_actuator_handle(state, | ||
component_type=self.parameters["component_type"], | ||
control_type=self.parameters["control_type"], | ||
actuator_key=self.parameters["component_name"]) | ||
elif self.type == OpenStudioComponentType.CONSTANT: | ||
return | ||
else: | ||
raise JobException(f"Unknown point type: {self.type}") | ||
|
||
if self.handle == -1: | ||
raise JobException(f"Handle not found for point of type: {self.type} and parameters: {self.parameters}") | ||
|
||
def read_value(self, api, state): | ||
if self.handle == -1 or self.handle is None: | ||
return None | ||
if self.type == OpenStudioComponentType.OUTPUT_VARIABLE: | ||
value = api.exchange.get_variable_value(state, self.handle) | ||
elif self.type == OpenStudioComponentType.GLOBAL_VARIABLE: | ||
value = api.exchange.get_ems_global_value(state, self.handle) | ||
elif self.type == OpenStudioComponentType.METER: | ||
value = api.exchange.get_meter_value(state, self.handle) | ||
elif self.type == OpenStudioComponentType.ACTUATOR: | ||
value = api.exchange.get_actuator_value(state, self.handle) | ||
elif self.type == OpenStudioComponentType.CONSTANT: | ||
value = self.parameters["value"] | ||
|
||
return self.converter(value) | ||
|
||
def write_value(self, api, state, value): | ||
if self.handle == -1 or self.handle is None: | ||
return None | ||
if self.type == OpenStudioComponentType.GLOBAL_VARIABLE and value is not None: | ||
api.exchange.set_ems_global_value(state, self.handle, value) | ||
if self.type == OpenStudioComponentType.ACTUATOR: | ||
if value is not None: | ||
api.exchange.set_actuator_value(state, self.handle, value) | ||
self.reset = False | ||
elif self.reset is False: | ||
api.exchange.reset_actuator(state, self.handle) | ||
self.reset = True |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
from dataclasses import dataclass | ||
|
||
from alfalfa_worker.jobs.openstudio.lib.openstudio_component import ( | ||
OpenStudioComponent | ||
) | ||
from alfalfa_worker.lib.enums import PointType | ||
from alfalfa_worker.lib.job_exception import JobException | ||
from alfalfa_worker.lib.models import Point, Run | ||
|
||
|
||
@dataclass | ||
class OpenStudioPoint: | ||
id: str | ||
name: str | ||
optional: bool = False | ||
units: str = None | ||
input: OpenStudioComponent = None | ||
output: OpenStudioComponent = None | ||
point: Point = None | ||
|
||
def __init__(self, id: str, name: str, optional: bool = False, units: str = None, input: dict = None, output: dict = None): | ||
self.id = id | ||
self.name = name | ||
self.optional = optional | ||
self.units = units | ||
self.input = OpenStudioComponent(**input) if input else None | ||
self.output = OpenStudioComponent(**output) if output else None | ||
|
||
def create_point(self): | ||
point_type = PointType.OUTPUT | ||
if self.input is not None: | ||
if self.output is not None: | ||
point_type = PointType.BIDIRECTIONAL | ||
else: | ||
point_type = PointType.INPUT | ||
|
||
self.point = Point(ref_id=self.id, point_type=point_type, name=self.name) | ||
if self.units is not None: | ||
self.point.units = self.units | ||
|
||
def attach_run(self, run: Run): | ||
if self.point is None: | ||
self.create_point() | ||
|
||
conflicting_points = Point.objects(ref_id=self.point.ref_id, run=run) | ||
needs_rename = len(conflicting_points) > 0 | ||
if len(conflicting_points) == 1: | ||
needs_rename = not (conflicting_points[0] == self.point) | ||
|
||
if needs_rename: | ||
self.point.ref_id = self.point.ref_id + "_1" | ||
return self.attach_run(run) | ||
else: | ||
run.add_point(self.point) | ||
|
||
def pre_initialize(self, api, state): | ||
if self.input: | ||
self.input.pre_initialize(api, state) | ||
|
||
if self.output: | ||
self.output.pre_initialize(api, state) | ||
|
||
def initialize(self, api, state): | ||
try: | ||
if self.input: | ||
self.input.initialize(api, state) | ||
|
||
if self.output: | ||
self.output.initialize(api, state) | ||
except JobException as e: | ||
if self.optional: | ||
self.disable() | ||
else: | ||
raise e | ||
|
||
def disable(self): | ||
if self.point: | ||
if self.point.run: | ||
self.point.run = None | ||
|
||
def update_input(self, api, state): | ||
if self.input: | ||
self.input.write_value(api, state, self.point.value) | ||
|
||
def update_output(self, api, state) -> float: | ||
if self.output: | ||
value = self.output.read_value(api, state) | ||
if self.point: | ||
self.point.value = value | ||
return value | ||
return None |
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.