LCOV - code coverage report
Current view: top level - EnergyPlus/api - datatransfer.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 29.4 % 805 237
Test Date: 2025-06-02 12:03:30 Functions: 31.8 % 88 28

            Line data    Source code
       1              : // EnergyPlus, Copyright (c) 1996-2025, The Board of Trustees of the University of Illinois,
       2              : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
       3              : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
       4              : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
       5              : // contributors. All rights reserved.
       6              : //
       7              : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
       8              : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
       9              : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
      10              : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
      11              : // derivative works, and perform publicly and display publicly, and to permit others to do so.
      12              : //
      13              : // Redistribution and use in source and binary forms, with or without modification, are permitted
      14              : // provided that the following conditions are met:
      15              : //
      16              : // (1) Redistributions of source code must retain the above copyright notice, this list of
      17              : //     conditions and the following disclaimer.
      18              : //
      19              : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
      20              : //     conditions and the following disclaimer in the documentation and/or other materials
      21              : //     provided with the distribution.
      22              : //
      23              : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
      24              : //     the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
      25              : //     used to endorse or promote products derived from this software without specific prior
      26              : //     written permission.
      27              : //
      28              : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
      29              : //     without changes from the version obtained under this License, or (ii) Licensee makes a
      30              : //     reference solely to the software portion of its product, Licensee must refer to the
      31              : //     software as "EnergyPlus version X" software, where "X" is the version number Licensee
      32              : //     obtained under this License and may not use a different name for the software. Except as
      33              : //     specifically required in this Section (4), Licensee shall not use in a company name, a
      34              : //     product name, in advertising, publicity, or other promotional activities any name, trade
      35              : //     name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
      36              : //     similar designation, without the U.S. Department of Energy's prior written consent.
      37              : //
      38              : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
      39              : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
      40              : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
      41              : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      42              : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
      43              : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      44              : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
      45              : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      46              : // POSSIBILITY OF SUCH DAMAGE.
      47              : 
      48              : #include <cmath>
      49              : 
      50              : #include <ObjexxFCL/ArrayS.functions.hh>
      51              : #include <ObjexxFCL/time.hh>
      52              : 
      53              : #include <EnergyPlus/Construction.hh>
      54              : #include <EnergyPlus/Data/EnergyPlusData.hh>
      55              : #include <EnergyPlus/DataEnvironment.hh>
      56              : #include <EnergyPlus/DataGlobalConstants.hh>
      57              : #include <EnergyPlus/DataHVACGlobals.hh>
      58              : #include <EnergyPlus/DataRuntimeLanguage.hh>
      59              : #include <EnergyPlus/DataStringGlobals.hh>
      60              : #include <EnergyPlus/HeatBalFiniteDiffManager.hh>
      61              : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      62              : #include <EnergyPlus/OutputProcessor.hh>
      63              : #include <EnergyPlus/PluginManager.hh>
      64              : #include <EnergyPlus/UtilityRoutines.hh>
      65              : #include <EnergyPlus/WeatherManager.hh>
      66              : #include <EnergyPlus/api/datatransfer.h>
      67              : #include <EnergyPlus/api/runtime.h>
      68              : 
      69              : using namespace EnergyPlus;
      70              : 
      71            2 : APIDataEntry *getAPIData(EnergyPlusState state, unsigned int *resultingSize)
      72              : {
      73              :     struct LocalAPIDataEntry
      74              :     {
      75              :         std::string what;
      76              :         std::string name;
      77              :         std::string type;
      78              :         std::string key;
      79              :         std::string unit;
      80              : 
      81          294 :         LocalAPIDataEntry(std::string _what, std::string _name, std::string _type, std::string _key, std::string _unit)
      82          294 :             : what(std::move(_what)), name(std::move(_name)), type(std::move(_type)), key(std::move(_key)), unit(std::move(_unit))
      83              :         {
      84          294 :         }
      85              :     };
      86            2 :     std::vector<LocalAPIDataEntry> localDataEntries;
      87            2 :     auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
      88          136 :     for (auto const &availActuator : thisState->dataRuntimeLang->EMSActuatorAvailable) {
      89          136 :         if (availActuator.ComponentTypeName.empty() && availActuator.UniqueIDName.empty() && availActuator.ControlTypeName.empty()) {
      90            2 :             break;
      91              :         }
      92          134 :         localDataEntries.emplace_back(
      93          134 :             "Actuator", availActuator.ComponentTypeName, availActuator.ControlTypeName, availActuator.UniqueIDName, availActuator.Units);
      94              :     }
      95           14 :     for (auto const &availVariable : thisState->dataRuntimeLang->EMSInternalVarsAvailable) {
      96           14 :         if (availVariable.DataTypeName.empty() && availVariable.UniqueIDName.empty()) {
      97            2 :             break;
      98              :         }
      99           12 :         localDataEntries.emplace_back("InternalVariable", availVariable.DataTypeName, "", availVariable.UniqueIDName, availVariable.Units);
     100              :     }
     101            2 :     for (auto const &gVarName : thisState->dataPluginManager->globalVariableNames) {
     102            0 :         localDataEntries.emplace_back("PluginGlobalVariable", "", "", gVarName, "");
     103            2 :     }
     104            2 :     for (auto const &trend : thisState->dataPluginManager->trends) {
     105            0 :         localDataEntries.emplace_back("PluginTrendVariable,", "", "", trend.name, "");
     106            2 :     }
     107           58 :     for (auto const *meter : thisState->dataOutputProcessor->meters) {
     108           56 :         if (meter->Name.empty()) {
     109            0 :             break;
     110              :         }
     111           56 :         localDataEntries.emplace_back("OutputMeter", "", "", meter->Name, format("{}", EnergyPlus::Constant::unitNames[(int)meter->units]));
     112            2 :     }
     113           98 :     for (auto const *variable : thisState->dataOutputProcessor->outVars) {
     114           96 :         if (variable->varType != EnergyPlus::OutputProcessor::VariableType::Real) {
     115            4 :             continue;
     116              :         }
     117           92 :         if (variable->name.empty() && variable->keyUC.empty()) {
     118            0 :             break;
     119              :         }
     120           92 :         localDataEntries.emplace_back("OutputVariable",
     121           92 :                                       variable->name,
     122              :                                       "",
     123           92 :                                       variable->keyUC,
     124           92 :                                       variable->units == EnergyPlus::Constant::Units::customEMS
     125          276 :                                           ? variable->unitNameCustomEMS
     126           92 :                                           : format("{}", EnergyPlus::Constant::unitNames[(int)variable->units]));
     127            2 :     }
     128            2 :     *resultingSize = localDataEntries.size();
     129            2 :     auto *data = new APIDataEntry[*resultingSize];
     130          296 :     for (unsigned int i = 0; i < *resultingSize; i++) {
     131          294 :         data[i].what = new char[std::strlen(localDataEntries[i].what.c_str()) + 1];
     132          294 :         std::strcpy(data[i].what, localDataEntries[i].what.c_str());
     133          294 :         data[i].name = new char[std::strlen(localDataEntries[i].name.c_str()) + 1];
     134          294 :         std::strcpy(data[i].name, localDataEntries[i].name.c_str());
     135          294 :         data[i].key = new char[std::strlen(localDataEntries[i].key.c_str()) + 1];
     136          294 :         std::strcpy(data[i].key, localDataEntries[i].key.c_str());
     137          294 :         data[i].type = new char[std::strlen(localDataEntries[i].type.c_str()) + 1];
     138          294 :         std::strcpy(data[i].type, localDataEntries[i].type.c_str());
     139          294 :         data[i].unit = new char[std::strlen(localDataEntries[i].unit.c_str()) + 1];
     140          294 :         std::strcpy(data[i].unit, localDataEntries[i].unit.c_str());
     141              :     }
     142            2 :     return data;
     143            2 : }
     144              : 
     145            2 : void freeAPIData(const APIDataEntry *data, const unsigned int arraySize)
     146              : {
     147          155 :     for (unsigned int i = 0; i < arraySize; i++) {
     148          153 :         delete[] data[i].what;
     149          153 :         delete[] data[i].name;
     150          153 :         delete[] data[i].key;
     151          153 :         delete[] data[i].type;
     152          153 :         delete[] data[i].unit;
     153              :     }
     154            2 :     delete[] data;
     155            2 : }
     156              : 
     157            0 : char *listAllAPIDataCSV(EnergyPlusState state)
     158              : {
     159            0 :     auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
     160            0 :     std::string output = "**ACTUATORS**\n";
     161            0 :     for (auto const &availActuator : thisState->dataRuntimeLang->EMSActuatorAvailable) {
     162            0 :         if (availActuator.ComponentTypeName.empty() && availActuator.UniqueIDName.empty() && availActuator.ControlTypeName.empty()) {
     163            0 :             break;
     164              :         }
     165            0 :         output.append("Actuator,");
     166            0 :         output.append(availActuator.ComponentTypeName).append(",");
     167            0 :         output.append(availActuator.ControlTypeName).append(",");
     168            0 :         output.append(availActuator.UniqueIDName).append(",");
     169            0 :         output.append(availActuator.Units).append("\n");
     170              :     }
     171            0 :     output.append("**INTERNAL_VARIABLES**\n");
     172            0 :     for (auto const &availVariable : thisState->dataRuntimeLang->EMSInternalVarsAvailable) {
     173            0 :         if (availVariable.DataTypeName.empty() && availVariable.UniqueIDName.empty()) {
     174            0 :             break;
     175              :         }
     176            0 :         output.append("InternalVariable,");
     177            0 :         output.append(availVariable.DataTypeName).append(",");
     178            0 :         output.append(availVariable.UniqueIDName).append(",");
     179            0 :         output.append(availVariable.Units).append("\n");
     180              :     }
     181            0 :     output.append("**PLUGIN_GLOBAL_VARIABLES**\n");
     182            0 :     for (auto const &gVarName : thisState->dataPluginManager->globalVariableNames) {
     183            0 :         output.append("PluginGlobalVariable,");
     184            0 :         output.append(gVarName).append("\n");
     185            0 :     }
     186            0 :     output.append("**TRENDS**\n");
     187            0 :     for (auto const &trend : thisState->dataPluginManager->trends) {
     188            0 :         output.append("PluginTrendVariable,");
     189            0 :         output.append(trend.name).append("\n");
     190            0 :     }
     191            0 :     output.append("**METERS**\n");
     192            0 :     for (auto const *meter : thisState->dataOutputProcessor->meters) {
     193            0 :         if (meter->Name.empty()) {
     194            0 :             break;
     195              :         }
     196            0 :         output.append("OutputMeter").append(","); // This multiple append thing is not good
     197            0 :         output.append(meter->Name).append(",");
     198            0 :         output.append(format("{}\n", EnergyPlus::Constant::unitNames[(int)meter->units]));
     199            0 :     }
     200            0 :     output.append("**VARIABLES**\n");
     201            0 :     for (auto const *variable : thisState->dataOutputProcessor->outVars) {
     202            0 :         if (variable->varType != EnergyPlus::OutputProcessor::VariableType::Real) {
     203            0 :             continue;
     204              :         }
     205            0 :         if (variable->name.empty() && variable->keyUC.empty()) {
     206            0 :             break;
     207              :         }
     208            0 :         output.append("OutputVariable,");
     209            0 :         output.append(variable->name).append(",");
     210            0 :         output.append(variable->keyUC).append(",");
     211            0 :         output.append(format("{}\n",
     212            0 :                              variable->units == EnergyPlus::Constant::Units::customEMS ? variable->unitNameCustomEMS
     213            0 :                                                                                        : EnergyPlus::Constant::unitNames[(int)variable->units]));
     214            0 :     }
     215              :     // note that we cannot just return a c_str to the local string, as the string will be destructed upon leaving
     216              :     // this function, and undefined behavior will occur.
     217              :     // instead make a deep copy, and the user must manage the new char * pointer
     218              :     // strcpy copies including the null-terminator, strlen doesn't include it
     219            0 :     char *p = new char[std::strlen(output.c_str()) + 1];
     220            0 :     std::strcpy(p, output.c_str());
     221            0 :     return p;
     222            0 : }
     223              : 
     224         2883 : int apiDataFullyReady(EnergyPlusState state)
     225              : {
     226         2883 :     const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
     227         2883 :     if (thisState->dataPluginManager->fullyReady) {
     228         2883 :         return 1;
     229              :     }
     230            0 :     return 0;
     231              : }
     232              : 
     233            0 : int apiErrorFlag(EnergyPlusState state)
     234              : {
     235            0 :     const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
     236            0 :     if (thisState->dataPluginManager->apiErrorFlag) {
     237            0 :         return 1;
     238              :     }
     239            0 :     return 0;
     240              : }
     241              : 
     242            0 : void resetErrorFlag(EnergyPlusState state)
     243              : {
     244            0 :     const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
     245            0 :     thisState->dataPluginManager->apiErrorFlag = false;
     246            0 : }
     247              : 
     248            2 : char *inputFilePath(EnergyPlusState state)
     249              : {
     250            2 :     const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
     251            2 :     std::string const path_utf8 = EnergyPlus::FileSystem::toGenericString(thisState->dataStrGlobals->inputFilePath);
     252            2 :     char *p = new char[std::strlen(path_utf8.c_str()) + 1];
     253            2 :     std::strcpy(p, path_utf8.c_str());
     254            2 :     return p;
     255            2 : }
     256              : 
     257            2 : char *epwFilePath(EnergyPlusState state)
     258              : {
     259            2 :     const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
     260            2 :     std::string const path_utf8 = EnergyPlus::FileSystem::toGenericString(thisState->files.inputWeatherFilePath.filePath);
     261            2 :     char *p = new char[std::strlen(path_utf8.c_str()) + 1];
     262            2 :     std::strcpy(p, path_utf8.c_str());
     263            2 :     return p;
     264            2 : }
     265              : 
     266            2 : char **getObjectNames(EnergyPlusState state, const char *objectType, unsigned int *resultingSize)
     267              : {
     268            2 :     const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
     269            2 :     auto &epjson = thisState->dataInputProcessing->inputProcessor->epJSON;
     270            2 :     const auto instances = epjson.find(objectType);
     271            2 :     if (instances == epjson.end()) {
     272            0 :         *resultingSize = 0;
     273            0 :         return nullptr;
     274              :     }
     275            2 :     auto &instancesValue = instances.value();
     276            2 :     *resultingSize = instancesValue.size();
     277            2 :     char **data = new char *[*resultingSize];
     278            2 :     unsigned int i = -1;
     279           14 :     for (auto instance = instancesValue.begin(); instance != instancesValue.end(); ++instance) {
     280           12 :         i++;
     281           12 :         std::string s = std::string(instance.key());
     282           12 :         data[i] = new char[std::strlen(instance.key().data()) + 1];
     283           12 :         std::strcpy(data[i], instance.key().data());
     284           14 :     }
     285            2 :     return data;
     286            2 : }
     287              : 
     288            2 : void freeObjectNames(char **objectNames, unsigned int arraySize)
     289              : {
     290              :     // as of right now we don't actually need to free the underlying strings, they exist in the epJSON instance, so just delete our array of pointers
     291              :     (void)arraySize;
     292              :     // no op to avoid compiler warning that this variable is unused, in the future, this may be needed so keeping it in the API now
     293            2 :     delete[] objectNames;
     294            2 : }
     295              : 
     296           26 : int getNumNodesInCondFDSurfaceLayer(EnergyPlusState state, const char *surfName, const char *matName)
     297              : {
     298           26 :     auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
     299           26 :     std::string UCsurfName = EnergyPlus::Util::makeUPPER(surfName);
     300           26 :     std::string UCmatName = EnergyPlus::Util::makeUPPER(matName);
     301           52 :     return EnergyPlus::HeatBalFiniteDiffManager::numNodesInMaterialLayer(*thisState, UCsurfName, UCmatName);
     302           26 : }
     303              : 
     304            4 : void requestVariable(EnergyPlusState state, const char *type, const char *key)
     305              : {
     306              :     // allow specifying a request for an output variable, so that E+ does not have to keep all of them in memory
     307              :     // should be called before energyplus is run!
     308              :     // note that the variable request array is cleared during clear_state, so if you run multiple E+ runs, these must be requested again each time.
     309            4 :     const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
     310            4 :     EnergyPlus::OutputProcessor::APIOutputVariableRequest request;
     311            4 :     request.varName = type;
     312            4 :     request.varKey = key;
     313            4 :     thisState->dataOutputProcessor->apiVarRequests.push_back(request);
     314            4 : }
     315              : 
     316           11 : int getVariableHandle(EnergyPlusState state, const char *type, const char *key)
     317              : {
     318              :     // Variables are accessed through a single integer ID, but there are multiple internal types: real and integer.
     319              :     // I am going to make the integer handle span all both types, by carefully defining the handle.
     320              :     // basically, the handles are contiguous, with:
     321              :     //  - index 1 being the first real variable handle
     322              :     //  - index N being the highest real variable handle
     323              :     //  - index N+1 being the first integer variable handle
     324              :     //  - index N+M being the highest integer variable handle
     325              :     // In this function, it is as simple as looping over both types and continuing to increment
     326              :     // the handle carefully.  In the getValue function it is just a matter of checking array sizes.
     327           11 :     const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
     328           11 :     std::string const typeUC = EnergyPlus::Util::makeUPPER(type);
     329           11 :     std::string const keyUC = EnergyPlus::Util::makeUPPER(key);
     330          329 :     for (int i = 0; i < thisState->dataOutputProcessor->outVars.size(); i++) {
     331          329 :         auto const *var = thisState->dataOutputProcessor->outVars[i];
     332          329 :         if (typeUC == var->nameUC && keyUC == var->keyUC) {
     333           11 :             return i;
     334              :         }
     335              :     }
     336            0 :     return -1; // return -1 if it wasn't found
     337           11 : }
     338              : 
     339       119635 : Real64 getVariableValue(EnergyPlusState state, const int handle)
     340              : {
     341              :     // this function works in conjunction with the plan set up in getVariableHandle
     342              :     // basically, the handles are contiguous, with:
     343              :     //  - index 1 being the first real variable handle
     344              :     //  - index N being the highest real variable handle
     345              :     //  - index N+1 being the first integer variable handle
     346              :     //  - index N+M being the highest integer variable handle
     347              :     // note that this function will return -1 if it cannot
     348       119635 :     auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
     349       119635 :     if (handle >= 0 && handle < thisState->dataOutputProcessor->outVars.size()) {
     350       119634 :         auto const *thisOutputVar = thisState->dataOutputProcessor->outVars[handle];
     351       119634 :         if (thisOutputVar->varType == EnergyPlus::OutputProcessor::VariableType::Real) {
     352       119634 :             return *(dynamic_cast<EnergyPlus::OutputProcessor::OutVarReal const *>(thisOutputVar))->Which;
     353              :         }
     354            0 :         if (thisOutputVar->varType == EnergyPlus::OutputProcessor::VariableType::Integer) {
     355            0 :             return (Real64) * (dynamic_cast<EnergyPlus::OutputProcessor::OutVarInt const *>(thisOutputVar))->Which;
     356              :         }
     357            0 :         if (thisState->dataGlobal->errorCallback) {
     358            0 :             std::cout << "ERROR: Variable at handle has type other than Real or Integer, returning zero but caller should take note and likely abort."
     359            0 :                       << std::endl;
     360              :         } else {
     361              :             // must be running from python plugin, need to fatal out once the plugin is done
     362              :             // throw an error, set the fatal flag, and then return zero
     363            0 :             ShowSevereError(*thisState, fmt::format("Data Exchange API: Error in getVariableValue; received handle: {}", handle));
     364            0 :             ShowContinueError(*thisState,
     365              :                               "The getVariableValue function will return 0 for now to allow the plugin to finish, then EnergyPlus will abort");
     366              :         }
     367            0 :         thisState->dataPluginManager->apiErrorFlag = true;
     368            0 :         return 0;
     369              :     }
     370            1 :     if (thisState->dataGlobal->errorCallback) {
     371            0 :         std::cout << "ERROR: Variable handle out of range in getVariableValue, returning zero but caller should take note and likely abort."
     372            0 :                   << std::endl;
     373              :     } else {
     374              :         // must be running from python plugin, need to fatal out once the plugin is done
     375              :         // throw an error, set the fatal flag, and then return zero
     376            2 :         ShowSevereError(*thisState, fmt::format("Data Exchange API: Index error in getVariableValue; received handle: {}", handle));
     377            3 :         ShowContinueError(*thisState,
     378              :                           "The getVariableValue function will return 0 for now to allow the plugin to finish, then EnergyPlus will abort");
     379              :     }
     380            1 :     thisState->dataPluginManager->apiErrorFlag = true;
     381            1 :     return 0;
     382              : }
     383              : 
     384            0 : int getMeterHandle(EnergyPlusState state, const char *meterName)
     385              : {
     386            0 :     auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
     387            0 :     std::string const meterNameUC = EnergyPlus::Util::makeUPPER(meterName);
     388            0 :     const int i = EnergyPlus::GetMeterIndex(*thisState, meterNameUC);
     389            0 :     if (i == 0) {
     390              :         // inside E+, zero is meaningful, but through the API, I want to use negative one as a signal of a bad lookup
     391            0 :         return -1;
     392              :     }
     393            0 :     return i;
     394            0 : }
     395              : 
     396            0 : Real64 getMeterValue(EnergyPlusState state, int handle)
     397              : {
     398            0 :     auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
     399            0 :     if (handle >= 0 && handle < thisState->dataOutputProcessor->meters.size()) {
     400            0 :         return EnergyPlus::GetCurrentMeterValue(*thisState, handle);
     401              :     }
     402            0 :     if (thisState->dataGlobal->errorCallback) {
     403            0 :         std::cout << "ERROR: Meter handle out of range in getMeterValue, returning zero but caller should take note and likely abort." << std::endl;
     404              :     } else {
     405              :         // must be running from python plugin, need to fatal out once the plugin is done
     406              :         // throw an error, set the fatal flag, and then return zero
     407            0 :         ShowSevereError(*thisState, fmt::format("Data Exchange API: Index error in getMeterValue; received handle: {}", handle));
     408            0 :         ShowContinueError(*thisState, "The getMeterValue function will return 0 for now to allow the plugin to finish, then EnergyPlus will abort");
     409              :     }
     410            0 :     thisState->dataPluginManager->apiErrorFlag = true;
     411            0 :     return 0;
     412              : }
     413              : 
     414           88 : int getActuatorHandle(EnergyPlusState state, const char *componentType, const char *controlType, const char *uniqueKey)
     415              : {
     416           88 :     int handle = 0;
     417           88 :     std::string const typeUC = EnergyPlus::Util::makeUPPER(componentType);
     418           88 :     std::string const keyUC = EnergyPlus::Util::makeUPPER(uniqueKey);
     419           88 :     std::string const controlUC = EnergyPlus::Util::makeUPPER(controlType);
     420           88 :     auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
     421         9382 :     for (int ActuatorLoop = 1; ActuatorLoop <= thisState->dataRuntimeLang->numEMSActuatorsAvailable; ++ActuatorLoop) {
     422         9375 :         auto &availActuator = thisState->dataRuntimeLang->EMSActuatorAvailable(ActuatorLoop);
     423         9375 :         handle++;
     424         9375 :         std::string const actuatorTypeUC = EnergyPlus::Util::makeUPPER(availActuator.ComponentTypeName);
     425         9375 :         std::string const actuatorIDUC = EnergyPlus::Util::makeUPPER(availActuator.UniqueIDName);
     426         9375 :         std::string const actuatorControlUC = EnergyPlus::Util::makeUPPER(availActuator.ControlTypeName);
     427         9375 :         if (typeUC == actuatorTypeUC && keyUC == actuatorIDUC && controlUC == actuatorControlUC) {
     428           81 :             if (availActuator.handleCount > 0) {
     429              :                 // If the handle is already used by an IDF EnergyManagementSystem:Actuator, we should warn the user
     430            0 :                 bool foundActuator = false;
     431            0 :                 for (auto const &usedActuator : thisState->dataRuntimeLang->EMSActuatorUsed) {
     432            0 :                     if (usedActuator.ActuatorVariableNum == handle) {
     433            0 :                         ShowWarningError(
     434              :                             *thisState,
     435            0 :                             "Data Exchange API: An EnergyManagementSystem:Actuator seems to be already defined in the EnergyPlus File and named '" +
     436            0 :                                 usedActuator.Name + "'.");
     437            0 :                         ShowContinueError(
     438            0 :                             *thisState, fmt::format("Occurred for componentType='{}', controlType='{}', uniqueKey='{}'.", typeUC, controlUC, keyUC));
     439            0 :                         ShowContinueError(*thisState,
     440            0 :                                           fmt::format("The getActuatorHandle function will still return the handle (= {}) but caller "
     441              :                                                       "should take note that there is a risk of overwritting.",
     442              :                                                       handle));
     443            0 :                         foundActuator = true;
     444            0 :                         break;
     445              :                     }
     446              :                 }
     447            0 :                 if (!foundActuator) {
     448            0 :                     ShowWarningError(*thisState, "Data Exchange API: You seem to already have tried to get an Actuator Handle on this one.");
     449            0 :                     ShowContinueError(*thisState,
     450            0 :                                       fmt::format("Occurred for componentType='{}', controlType='{}', uniqueKey='{}'.", typeUC, controlUC, keyUC));
     451            0 :                     ShowContinueError(*thisState,
     452            0 :                                       fmt::format("The getActuatorHandle function will still return the handle (= {}) but caller should "
     453              :                                                   "take note that there is a risk of overwritting.",
     454              :                                                   handle));
     455              :                 }
     456              :             }
     457           81 :             ++availActuator.handleCount;
     458              : 
     459           81 :             return handle;
     460              :         }
     461         9537 :     }
     462            7 :     return -1;
     463           88 : }
     464              : 
     465            0 : void resetActuator(EnergyPlusState state, int handle)
     466              : {
     467              :     // resets the actuator so that E+ will use the internally calculated value again
     468            0 :     auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
     469            0 :     if (handle >= 1 && handle <= thisState->dataRuntimeLang->numEMSActuatorsAvailable) {
     470            0 :         const auto &theActuator(thisState->dataRuntimeLang->EMSActuatorAvailable(handle));
     471            0 :         *theActuator.Actuated = false;
     472              :     } else {
     473            0 :         if (thisState->dataGlobal->errorCallback) {
     474            0 :             std::cout << "ERROR: Actuator handle out of range in resetActuator, returning but caller should take note and likely abort." << std::endl;
     475              :         } else {
     476              :             // must be running from python plugin, need to fatal out once the plugin is done
     477              :             // throw an error, set the fatal flag, and then return
     478            0 :             ShowSevereError(*thisState, fmt::format("Data Exchange API: index error in resetActuator; received handle: {}", handle));
     479            0 :             ShowContinueError(*thisState, "The resetActuator function will return to allow the plugin to finish, then EnergyPlus will abort");
     480              :         }
     481            0 :         thisState->dataPluginManager->apiErrorFlag = true;
     482              :     }
     483            0 : }
     484              : 
     485       374655 : void setActuatorValue(EnergyPlusState state, const int handle, const Real64 value)
     486              : {
     487       374655 :     auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
     488       374655 :     if (handle >= 1 && handle <= thisState->dataRuntimeLang->numEMSActuatorsAvailable) {
     489       374655 :         auto &theActuator(thisState->dataRuntimeLang->EMSActuatorAvailable(handle));
     490       374655 :         if (theActuator.RealValue) {
     491       368895 :             *theActuator.RealValue = value;
     492         5760 :         } else if (theActuator.IntValue) {
     493         5760 :             *theActuator.IntValue = static_cast<int>(std::lround(value));
     494              :         } else {
     495              :             // follow protocol from EMS manager, where 1.0 is true, 0.0 is false, and anything else is also false
     496            0 :             *theActuator.LogValue = value > 0.99999 && value < 1.00001;
     497              :             // allow small tolerance while passing between languages and types
     498              :         }
     499       374655 :         *theActuator.Actuated = true;
     500              :     } else {
     501            0 :         if (thisState->dataGlobal->errorCallback) {
     502            0 :             std::cout << "ERROR: Actuator handle out of range in setActuatorValue, returning but caller should take note and likely abort."
     503            0 :                       << std::endl;
     504              :         } else {
     505              :             // must be running from python plugin, need to fatal out once the plugin is done
     506              :             // throw an error, set the fatal flag, and then return
     507            0 :             ShowSevereError(*thisState, fmt::format("Data Exchange API: index error in setActuatorValue; received handle: {}", handle));
     508            0 :             ShowContinueError(*thisState, "The setActuatorValue function will return to allow the plugin to finish, then EnergyPlus will abort");
     509              :         }
     510            0 :         thisState->dataPluginManager->apiErrorFlag = true;
     511              :     }
     512       374655 : }
     513              : 
     514            0 : Real64 getActuatorValue(EnergyPlusState state, const int handle)
     515              : {
     516            0 :     auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
     517            0 :     if (handle >= 1 && handle <= thisState->dataRuntimeLang->numEMSActuatorsAvailable) {
     518            0 :         const auto &theActuator(thisState->dataRuntimeLang->EMSActuatorAvailable(handle));
     519            0 :         if (theActuator.RealValue) {
     520            0 :             return *theActuator.RealValue;
     521              :         }
     522            0 :         if (theActuator.IntValue) {
     523            0 :             return static_cast<float>(*theActuator.IntValue);
     524              :         }
     525              :         // follow protocol from EMS manager, where 1.0 is true, 0.0 is false, and anything else is also false
     526            0 :         if (*theActuator.LogValue) {
     527            0 :             return 1;
     528              :         }
     529            0 :         return 0;
     530              :     }
     531            0 :     if (thisState->dataGlobal->errorCallback) {
     532            0 :         std::cout << "ERROR: Actuator handle out of range in getActuatorValue, returning zero but caller should take note and likely abort."
     533            0 :                   << std::endl;
     534              :     } else {
     535              :         // must be running from python plugin, need to fatal out once the plugin is done
     536              :         // throw an error, set the fatal flag, and then return 0
     537            0 :         ShowSevereError(*thisState, fmt::format("Data Exchange API: index error in getActuatorValue; received handle: {}", handle));
     538            0 :         ShowContinueError(*thisState,
     539              :                           "The getActuatorValue function will return 0 for now to allow the plugin to finish, then EnergyPlus will abort");
     540              :     }
     541            0 :     thisState->dataPluginManager->apiErrorFlag = true;
     542            0 :     return 0;
     543              : }
     544              : 
     545            9 : int getInternalVariableHandle(EnergyPlusState state, const char *type, const char *key)
     546              : {
     547            9 :     int handle = 0;
     548            9 :     std::string const typeUC = EnergyPlus::Util::makeUPPER(type);
     549            9 :     std::string const keyUC = EnergyPlus::Util::makeUPPER(key);
     550            9 :     const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
     551          561 :     for (auto const &availVariable : thisState->dataRuntimeLang->EMSInternalVarsAvailable) {
     552              :         // TODO: this should stop at numEMSInternalVarsAvailable
     553          561 :         handle++;
     554          561 :         std::string const variableTypeUC = EnergyPlus::Util::makeUPPER(availVariable.DataTypeName);
     555          561 :         std::string const variableIDUC = EnergyPlus::Util::makeUPPER(availVariable.UniqueIDName);
     556          561 :         if (typeUC == variableTypeUC && keyUC == variableIDUC) {
     557            9 :             return handle;
     558              :         }
     559          570 :     }
     560            0 :     return -1;
     561            9 : }
     562              : 
     563        36747 : Real64 getInternalVariableValue(EnergyPlusState state, int handle)
     564              : {
     565        36747 :     auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
     566        36747 :     if (handle >= 1 && handle <= (int)thisState->dataRuntimeLang->numEMSInternalVarsAvailable) {
     567        36747 :         auto const &thisVar = thisState->dataRuntimeLang->EMSInternalVarsAvailable(handle);
     568        36747 :         if (thisVar.PntrVarTypeUsed == EnergyPlus::DataRuntimeLanguage::PtrDataType::Real) {
     569        36747 :             return *thisVar.RealValue;
     570              :         }
     571            0 :         if (thisVar.PntrVarTypeUsed == EnergyPlus::DataRuntimeLanguage::PtrDataType::Integer) {
     572            0 :             return (Real64)(*thisVar.IntValue);
     573              :         }
     574              :         // Doesn't look like this struct actually has a logical member type, so uh, throw here?
     575            0 :         std::cout << "ERROR: Invalid internal variable type here, developer issue., returning zero but caller should take note and likely abort."
     576            0 :                   << std::endl;
     577            0 :         thisState->dataPluginManager->apiErrorFlag = true;
     578            0 :         return 0;
     579              :     }
     580            0 :     if (thisState->dataGlobal->errorCallback) {
     581              :         std::cout << "ERROR: Internal variable handle out of range in getInternalVariableValue, returning zero but caller should take note and "
     582            0 :                      "likely abort."
     583            0 :                   << std::endl;
     584              :     } else {
     585              :         // must be running from python plugin, need to fatal out once the plugin is done
     586              :         // throw an error, set the fatal flag, and then return 0
     587            0 :         ShowSevereError(*thisState, fmt::format("Data Exchange API: index error in getInternalVariableValue; received handle: {}", handle));
     588            0 :         ShowContinueError(*thisState,
     589              :                           "The getInternalVariableValue function will return 0 for now to allow the plugin to finish, then EnergyPlus will abort");
     590              :     }
     591            0 :     thisState->dataPluginManager->apiErrorFlag = true;
     592            0 :     return 0;
     593              : }
     594              : 
     595            6 : int getEMSGlobalVariableHandle(EnergyPlusState state, const char *name)
     596              : {
     597            6 :     auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
     598            6 :     int index = 0;
     599          172 :     for (auto const &erlVar : thisState->dataRuntimeLang->ErlVariable) {
     600          168 :         index++;
     601              :         // only respond if we are outside of the built-in EMS var range
     602          168 :         if (index < thisState->dataRuntimeLang->emsVarBuiltInStart || index > thisState->dataRuntimeLang->emsVarBuiltInEnd) {
     603            6 :             if (EnergyPlus::Util::SameString(name, erlVar.Name)) {
     604            2 :                 return index;
     605              :             }
     606              :         }
     607              :     }
     608            4 :     return 0;
     609              : }
     610              : 
     611            2 : Real64 getEMSGlobalVariableValue(EnergyPlusState state, int handle)
     612              : {
     613            2 :     auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
     614            2 :     auto const &erl = thisState->dataRuntimeLang;
     615            2 :     bool const insideBuiltInRange = handle >= erl->emsVarBuiltInStart && handle <= erl->emsVarBuiltInEnd;
     616            2 :     if (insideBuiltInRange || handle > thisState->dataRuntimeLang->NumErlVariables) {
     617              :         // need to fatal out once the process is done
     618              :         // throw an error, set the fatal flag, and then return 0
     619            0 :         EnergyPlus::ShowSevereError(
     620            0 :             *thisState, fmt::format("Data Exchange API: Problem -- index error in getEMSGlobalVariableValue; received handle: {}", handle));
     621            0 :         EnergyPlus::ShowContinueError(
     622              :             *thisState, "The getEMSGlobalVariableValue function will return 0 for now to allow the process to finish, then EnergyPlus will abort");
     623            0 :         thisState->dataPluginManager->apiErrorFlag = true;
     624            0 :         return 0;
     625              :     }
     626            2 :     return erl->ErlVariable(handle).Value.Number;
     627              : }
     628              : 
     629            2 : void setEMSGlobalVariableValue(EnergyPlusState state, int handle, Real64 value)
     630              : {
     631            2 :     auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
     632            2 :     auto const &erl = thisState->dataRuntimeLang;
     633            2 :     bool const insideBuiltInRange = handle >= erl->emsVarBuiltInStart && handle <= erl->emsVarBuiltInEnd;
     634            2 :     if (insideBuiltInRange || handle > erl->NumErlVariables) {
     635              :         // need to fatal out once the plugin is done
     636              :         // throw an error, set the fatal flag, and then return
     637            0 :         EnergyPlus::ShowSevereError(
     638            0 :             *thisState, fmt::format("Data Exchange API: Problem -- index error in setEMSGlobalVariableValue; received handle: {}", handle));
     639            0 :         EnergyPlus::ShowContinueError(*thisState,
     640              :                                       "The setEMSGlobalVariableValue function will return to allow the plugin to finish, then EnergyPlus will abort");
     641            0 :         thisState->dataPluginManager->apiErrorFlag = true;
     642              :     }
     643            2 :     erl->ErlVariable(handle).Value.Number = value;
     644            2 : }
     645              : 
     646            0 : int getPluginGlobalVariableHandle(EnergyPlusState state, const char *name)
     647              : {
     648            0 :     auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
     649            0 :     return thisState->dataPluginManager->pluginManager->getGlobalVariableHandle(*thisState, name);
     650              : }
     651              : 
     652            0 : Real64 getPluginGlobalVariableValue(EnergyPlusState state, int handle)
     653              : {
     654            0 :     auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
     655            0 :     if (handle < 0 || handle > thisState->dataPluginManager->pluginManager->maxGlobalVariableIndex) {
     656              :         // need to fatal out once the plugin is done
     657              :         // throw an error, set the fatal flag, and then return 0
     658            0 :         ShowSevereError(*thisState,
     659            0 :                         fmt::format("Data Exchange API: Problem -- index error in getPluginGlobalVariableValue; received handle: {}", handle));
     660            0 :         ShowContinueError(
     661              :             *thisState, "The getPluginGlobalVariableValue function will return 0 for now to allow the plugin to finish, then EnergyPlus will abort");
     662            0 :         thisState->dataPluginManager->apiErrorFlag = true;
     663            0 :         return 0;
     664              :     }
     665            0 :     return thisState->dataPluginManager->pluginManager->getGlobalVariableValue(*thisState, handle);
     666              : }
     667              : 
     668            0 : void setPluginGlobalVariableValue(EnergyPlusState state, int handle, Real64 value)
     669              : {
     670            0 :     auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
     671            0 :     if (handle < 0 || handle > thisState->dataPluginManager->pluginManager->maxGlobalVariableIndex) {
     672              :         // need to fatal out once the plugin is done
     673              :         // throw an error, set the fatal flag, and then return
     674            0 :         ShowSevereError(*thisState,
     675            0 :                         fmt::format("Data Exchange API: Problem -- index error in setPluginGlobalVariableValue; received handle: {}", handle));
     676            0 :         ShowContinueError(*thisState,
     677              :                           "The getPluginGlobalVariableValue function will return to allow the plugin to finish, then EnergyPlus will abort");
     678            0 :         thisState->dataPluginManager->apiErrorFlag = true;
     679              :     }
     680            0 :     thisState->dataPluginManager->pluginManager->setGlobalVariableValue(*thisState, handle, value);
     681            0 : }
     682              : 
     683            0 : int getPluginTrendVariableHandle(EnergyPlusState state, const char *name)
     684              : {
     685            0 :     auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
     686            0 :     return EnergyPlus::PluginManagement::PluginManager::getTrendVariableHandle(*thisState, name);
     687              : }
     688              : 
     689            0 : Real64 getPluginTrendVariableValue(EnergyPlusState state, int handle, int timeIndex)
     690              : {
     691            0 :     auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
     692            0 :     if (handle < 0 || handle > thisState->dataPluginManager->pluginManager->maxTrendVariableIndex) {
     693              :         // need to fatal out once the plugin is done
     694              :         // throw an error, set the fatal flag, and then return
     695            0 :         ShowSevereError(*thisState,
     696            0 :                         fmt::format("Data Exchange API: Problem -- index error in getPluginTrendVariableValue; received handle: {}", handle));
     697            0 :         ShowContinueError(*thisState,
     698              :                           "The getPluginTrendVariableValue function will return 0 to allow the plugin to finish, then EnergyPlus will abort");
     699            0 :         thisState->dataPluginManager->apiErrorFlag = true;
     700            0 :         return 0;
     701              :     }
     702            0 :     if (timeIndex < 1 || timeIndex > EnergyPlus::PluginManagement::PluginManager::getTrendVariableHistorySize(*thisState, handle)) {
     703              :         // need to fatal out once the plugin is done
     704              :         // throw an error, set the fatal flag, and then return
     705            0 :         ShowSevereError(
     706              :             *thisState,
     707            0 :             fmt::format("Data Exchange API: Problem -- trend history count argument out of range in getPluginTrendVariableValue; received value: {}",
     708              :                         timeIndex));
     709            0 :         ShowContinueError(*thisState,
     710              :                           "The getPluginTrendVariableValue function will return 0 to allow the plugin to finish, then EnergyPlus will abort");
     711            0 :         thisState->dataPluginManager->apiErrorFlag = true;
     712            0 :         return 0;
     713              :     }
     714            0 :     return EnergyPlus::PluginManagement::PluginManager::getTrendVariableValue(*thisState, handle, timeIndex);
     715              : }
     716              : 
     717            0 : Real64 getPluginTrendVariableAverage(EnergyPlusState state, int handle, int count)
     718              : {
     719            0 :     auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
     720            0 :     if (handle < 0 || handle > thisState->dataPluginManager->pluginManager->maxTrendVariableIndex) {
     721              :         // need to fatal out once the plugin is done
     722              :         // throw an error, set the fatal flag, and then return
     723            0 :         ShowSevereError(*thisState,
     724            0 :                         fmt::format("Data Exchange API: Problem -- index error in getPluginTrendVariableAverage; received handle: {}", handle));
     725            0 :         ShowContinueError(*thisState,
     726              :                           "The getPluginTrendVariableAverage function will return 0 to allow the plugin to finish, then EnergyPlus will abort");
     727            0 :         thisState->dataPluginManager->apiErrorFlag = true;
     728            0 :         return 0;
     729              :     }
     730            0 :     if (count < 2 || count > EnergyPlus::PluginManagement::PluginManager::getTrendVariableHistorySize(*thisState, handle)) {
     731              :         // need to fatal out once the plugin is done
     732              :         // throw an error, set the fatal flag, and then return
     733            0 :         ShowSevereError(
     734              :             *thisState,
     735            0 :             fmt::format(
     736              :                 "Data Exchange API: Problem -- trend history count argument out of range in getPluginTrendVariableAverage; received value: {}",
     737              :                 count));
     738            0 :         ShowContinueError(*thisState,
     739              :                           "The getPluginTrendVariableAverage function will return 0 to allow the plugin to finish, then EnergyPlus will abort");
     740            0 :         thisState->dataPluginManager->apiErrorFlag = true;
     741            0 :         return 0;
     742              :     }
     743            0 :     return EnergyPlus::PluginManagement::PluginManager::getTrendVariableAverage(*thisState, handle, count);
     744              : }
     745              : 
     746            0 : Real64 getPluginTrendVariableMin(EnergyPlusState state, int handle, int count)
     747              : {
     748            0 :     auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
     749            0 :     if (handle < 0 || handle > thisState->dataPluginManager->pluginManager->maxTrendVariableIndex) {
     750              :         // need to fatal out once the plugin is done
     751              :         // throw an error, set the fatal flag, and then return
     752            0 :         ShowSevereError(*thisState,
     753            0 :                         fmt::format("Data Exchange API: Problem -- index error in getPluginTrendVariableMin; received handle: {}", handle));
     754            0 :         ShowContinueError(*thisState,
     755              :                           "The getPluginTrendVariableMin function will return 0 to allow the plugin to finish, then EnergyPlus will abort");
     756            0 :         thisState->dataPluginManager->apiErrorFlag = true;
     757            0 :         return 0;
     758              :     }
     759            0 :     if (count < 2 || count > EnergyPlus::PluginManagement::PluginManager::getTrendVariableHistorySize(*thisState, handle)) {
     760              :         // need to fatal out once the plugin is done
     761              :         // throw an error, set the fatal flag, and then return
     762            0 :         ShowSevereError(
     763              :             *thisState,
     764            0 :             fmt::format("Data Exchange API: Problem -- trend history count argument out of range in getPluginTrendVariableMin; received value: {}",
     765              :                         count));
     766            0 :         ShowContinueError(*thisState,
     767              :                           "The getPluginTrendVariableMin function will return 0 to allow the plugin to finish, then EnergyPlus will abort");
     768            0 :         thisState->dataPluginManager->apiErrorFlag = true;
     769            0 :         return 0;
     770              :     }
     771            0 :     return EnergyPlus::PluginManagement::PluginManager::getTrendVariableMin(*thisState, handle, count);
     772              : }
     773              : 
     774            0 : Real64 getPluginTrendVariableMax(EnergyPlusState state, int handle, int count)
     775              : {
     776            0 :     auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
     777            0 :     if (handle < 0 || handle > thisState->dataPluginManager->pluginManager->maxTrendVariableIndex) {
     778              :         // need to fatal out once the plugin is done
     779              :         // throw an error, set the fatal flag, and then return
     780            0 :         ShowSevereError(*thisState,
     781            0 :                         fmt::format("Data Exchange API: Problem -- index error in getPluginTrendVariableMax; received handle: {}", handle));
     782            0 :         ShowContinueError(*thisState,
     783              :                           "The getPluginTrendVariableMax function will return 0 to allow the plugin to finish, then EnergyPlus will abort");
     784            0 :         thisState->dataPluginManager->apiErrorFlag = true;
     785            0 :         return 0;
     786              :     }
     787            0 :     if (count < 2 || count > EnergyPlus::PluginManagement::PluginManager::getTrendVariableHistorySize(*thisState, handle)) {
     788              :         // need to fatal out once the plugin is done
     789              :         // throw an error, set the fatal flag, and then return
     790            0 :         ShowSevereError(
     791              :             *thisState,
     792            0 :             fmt::format("Data Exchange API: Problem -- trend history count argument out of range in getPluginTrendVariableMax; received value: {}",
     793              :                         count));
     794            0 :         ShowContinueError(*thisState,
     795              :                           "The getPluginTrendVariableMax function will return 0 to allow the plugin to finish, then EnergyPlus will abort");
     796            0 :         thisState->dataPluginManager->apiErrorFlag = true;
     797            0 :         return 0;
     798              :     }
     799            0 :     return EnergyPlus::PluginManagement::PluginManager::getTrendVariableMax(*thisState, handle, count);
     800              : }
     801              : 
     802            0 : Real64 getPluginTrendVariableSum(EnergyPlusState state, int handle, int count)
     803              : {
     804            0 :     auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
     805            0 :     if (handle < 0 || handle > thisState->dataPluginManager->pluginManager->maxTrendVariableIndex) {
     806              :         // need to fatal out once the plugin is done
     807              :         // throw an error, set the fatal flag, and then return
     808            0 :         ShowSevereError(*thisState,
     809            0 :                         fmt::format("Data Exchange API: Problem -- index error in getPluginTrendVariableSum; received handle: {}", handle));
     810            0 :         ShowContinueError(*thisState,
     811              :                           "The getPluginTrendVariableSum function will return 0 to allow the plugin to finish, then EnergyPlus will abort");
     812            0 :         thisState->dataPluginManager->apiErrorFlag = true;
     813            0 :         return 0;
     814              :     }
     815            0 :     if (count < 2 || count > EnergyPlus::PluginManagement::PluginManager::getTrendVariableHistorySize(*thisState, handle)) {
     816              :         // need to fatal out once the plugin is done
     817              :         // throw an error, set the fatal flag, and then return
     818            0 :         ShowSevereError(
     819              :             *thisState,
     820            0 :             fmt::format("Data Exchange API: Problem -- trend history count argument out of range in getPluginTrendVariableSum; received value: {}",
     821              :                         count));
     822            0 :         ShowContinueError(*thisState,
     823              :                           "The getPluginTrendVariableSum function will return 0 to allow the plugin to finish, then EnergyPlus will abort");
     824            0 :         thisState->dataPluginManager->apiErrorFlag = true;
     825            0 :         return 0;
     826              :     }
     827            0 :     return EnergyPlus::PluginManagement::PluginManager::getTrendVariableSum(*thisState, handle, count);
     828              : }
     829              : 
     830            0 : Real64 getPluginTrendVariableDirection(EnergyPlusState state, int handle, int count)
     831              : {
     832            0 :     auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
     833            0 :     if (handle < 0 || handle > thisState->dataPluginManager->pluginManager->maxTrendVariableIndex) {
     834              :         // need to fatal out once the plugin is done
     835              :         // throw an error, set the fatal flag, and then return
     836            0 :         ShowSevereError(*thisState,
     837            0 :                         fmt::format("Data Exchange API: Problem -- index error in getPluginTrendVariableDirection; received handle: {}", handle));
     838            0 :         ShowContinueError(*thisState,
     839              :                           "The getPluginTrendVariableDirection function will return 0 to allow the plugin to finish, then EnergyPlus will abort");
     840            0 :         thisState->dataPluginManager->apiErrorFlag = true;
     841            0 :         return 0;
     842              :     }
     843            0 :     if (count < 2 || count > EnergyPlus::PluginManagement::PluginManager::getTrendVariableHistorySize(*thisState, handle)) {
     844              :         // need to fatal out once the plugin is done
     845              :         // throw an error, set the fatal flag, and then return
     846            0 :         ShowSevereError(
     847              :             *thisState,
     848            0 :             fmt::format(
     849              :                 "Data Exchange API: Problem -- trend history count argument out of range in getPluginTrendVariableDirection; received value: {}",
     850              :                 count));
     851            0 :         ShowContinueError(*thisState,
     852              :                           "The getPluginTrendVariableDirection function will return 0 to allow the plugin to finish, then EnergyPlus will abort");
     853            0 :         thisState->dataPluginManager->apiErrorFlag = true;
     854            0 :         return 0;
     855              :     }
     856            0 :     return EnergyPlus::PluginManagement::PluginManager::getTrendVariableDirection(*thisState, handle, count);
     857              : }
     858              : 
     859         5760 : int year(EnergyPlusState state)
     860              : {
     861         5760 :     const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
     862         5760 :     return thisState->dataEnvrn->Year;
     863              : }
     864              : 
     865         5760 : int calendarYear(EnergyPlusState state)
     866              : {
     867         5760 :     const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
     868         5760 :     return thisState->dataGlobal->CalendarYear;
     869              : }
     870              : 
     871            0 : int month(EnergyPlusState state)
     872              : {
     873            0 :     const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
     874            0 :     return thisState->dataEnvrn->Month;
     875              : }
     876              : 
     877            0 : int dayOfMonth(EnergyPlusState state)
     878              : {
     879            0 :     const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
     880            0 :     return thisState->dataEnvrn->DayOfMonth;
     881              : }
     882              : 
     883            0 : int dayOfWeek(EnergyPlusState state)
     884              : {
     885            0 :     const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
     886            0 :     return thisState->dataEnvrn->DayOfWeek;
     887              : }
     888              : 
     889            0 : int dayOfYear(EnergyPlusState state)
     890              : {
     891            0 :     const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
     892            0 :     return thisState->dataEnvrn->DayOfYear;
     893              : }
     894              : 
     895            0 : int daylightSavingsTimeIndicator(EnergyPlusState state)
     896              : {
     897            0 :     const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
     898            0 :     return thisState->dataEnvrn->DSTIndicator;
     899              : }
     900              : 
     901            0 : int hour(EnergyPlusState state)
     902              : {
     903            0 :     const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
     904            0 :     return thisState->dataGlobal->HourOfDay - 1;
     905              :     // no, just stay on 0..23+ DSTadjust ! offset by 1 and daylight savings time
     906              : }
     907              : 
     908         5760 : Real64 currentTime(EnergyPlusState state)
     909              : {
     910         5760 :     const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
     911         5760 :     if (thisState->dataHVACGlobal->TimeStepSys < thisState->dataGlobal->TimeStepZone) {
     912              :         // CurrentTime is for end of zone timestep, need to move back to beginning of current zone timestep, then add on system time elapsed already
     913              :         // plus current system timestep
     914         1042 :         return thisState->dataGlobal->CurrentTime - thisState->dataGlobal->TimeStepZone + thisState->dataHVACGlobal->SysTimeElapsed +
     915         1042 :                thisState->dataHVACGlobal->TimeStepSys;
     916              :     }
     917         4718 :     return thisState->dataGlobal->CurrentTime;
     918              : }
     919              : 
     920            0 : int minutes(EnergyPlusState state)
     921              : {
     922              :     // the -1 is to push us to the right minute, but this should be handled cautiously because if we are inside the HVAC iteration loop,
     923              :     // currentTime() returns a floating point fractional hour, so truncation could put this a few seconds from the expected minute.
     924            0 :     const Real64 currentTimeVal = currentTime(state);
     925            0 :     const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
     926            0 :     const Real64 fractionalHoursIntoTheDay = currentTimeVal - static_cast<double>(thisState->dataGlobal->HourOfDay - 1);
     927            0 :     const Real64 fractionalMinutesIntoTheDay = std::round(fractionalHoursIntoTheDay * 60.0);
     928            0 :     return static_cast<int>(fractionalMinutesIntoTheDay);
     929              : }
     930              : 
     931          720 : int numTimeStepsInHour([[maybe_unused]] EnergyPlusState state)
     932              : {
     933          720 :     const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
     934          720 :     return thisState->dataGlobal->TimeStepsInHour;
     935              : }
     936              : 
     937         2880 : int zoneTimeStepNum([[maybe_unused]] EnergyPlusState state)
     938              : {
     939         2880 :     const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
     940         2880 :     return thisState->dataGlobal->TimeStep;
     941              : }
     942              : 
     943            0 : int holidayIndex(EnergyPlusState state)
     944              : {
     945            0 :     const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
     946            0 :     return thisState->dataEnvrn->HolidayIndex;
     947              : }
     948              : 
     949            0 : int sunIsUp(EnergyPlusState state)
     950              : {
     951              :     // maintain response convention from previous (EMS) implementation
     952            0 :     const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
     953            0 :     return (int)thisState->dataEnvrn->SunIsUp;
     954              : }
     955              : 
     956            0 : int isRaining(EnergyPlusState state)
     957              : {
     958            0 :     const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
     959            0 :     return (int)thisState->dataEnvrn->IsRain;
     960              : }
     961              : 
     962            0 : int warmupFlag(EnergyPlusState state)
     963              : {
     964            0 :     const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
     965            0 :     return (int)thisState->dataGlobal->WarmupFlag;
     966              : }
     967              : 
     968            0 : Real64 zoneTimeStep(EnergyPlusState state)
     969              : {
     970            0 :     const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
     971            0 :     return thisState->dataGlobal->TimeStepZone;
     972              : }
     973              : 
     974         2028 : Real64 systemTimeStep(EnergyPlusState state)
     975              : {
     976         2028 :     const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
     977         2028 :     return thisState->dataHVACGlobal->TimeStepSys;
     978              : }
     979              : 
     980            0 : int currentEnvironmentNum(EnergyPlusState state)
     981              : {
     982            0 :     const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
     983            0 :     return thisState->dataEnvrn->CurEnvirNum;
     984              : }
     985              : 
     986            0 : int kindOfSim(EnergyPlusState state)
     987              : {
     988            0 :     const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
     989            0 :     return static_cast<int>(thisState->dataGlobal->KindOfSim);
     990              : }
     991              : 
     992            4 : int getConstructionHandle(EnergyPlusState state, const char *constructionName)
     993              : {
     994            4 :     int handle = 0;
     995            4 :     std::string const nameUC = EnergyPlus::Util::makeUPPER(constructionName);
     996            4 :     const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
     997            6 :     for (auto const &construct : thisState->dataConstruction->Construct) {
     998            6 :         handle++;
     999            6 :         if (nameUC == EnergyPlus::Util::makeUPPER(construct.Name)) {
    1000            4 :             return handle;
    1001              :         }
    1002              :     }
    1003            0 :     return -1; // return -1 if it wasn't found
    1004            4 : }
    1005              : 
    1006            0 : int actualTime(EnergyPlusState)
    1007              : {
    1008            0 :     const std::string datestring;
    1009            0 :     Array1D_int datevalues(8);
    1010            0 :     ObjexxFCL::date_and_time(datestring, _, _, datevalues);
    1011            0 :     return sum(datevalues({5, 8}));
    1012            0 : }
    1013              : 
    1014            0 : int actualDateTime(EnergyPlusState)
    1015              : {
    1016            0 :     const std::string datestring;
    1017            0 :     const Array1D_int datevalues(8);
    1018            0 :     ObjexxFCL::date_and_time(datestring, _, _, datevalues);
    1019            0 :     return sum(datevalues);
    1020            0 : }
    1021              : 
    1022            0 : int todayWeatherIsRainAtTime(EnergyPlusState state, int hour, int timeStepNum)
    1023              : {
    1024            0 :     auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
    1025              : 
    1026            0 :     const int iHour = hour + 1;
    1027            0 :     if ((iHour > 0) && (iHour <= EnergyPlus::Constant::iHoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->TimeStepsInHour)) {
    1028            0 :         return (int)thisState->dataWeather->wvarsHrTsToday(timeStepNum, iHour).IsRain;
    1029              :     }
    1030            0 :     ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
    1031            0 :     thisState->dataPluginManager->apiErrorFlag = true;
    1032            0 :     return 0;
    1033              : }
    1034              : 
    1035            0 : int todayWeatherIsSnowAtTime(EnergyPlusState state, int hour, int timeStepNum)
    1036              : {
    1037            0 :     auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
    1038              : 
    1039            0 :     const int iHour = hour + 1;
    1040            0 :     if ((iHour > 0) && (iHour <= EnergyPlus::Constant::iHoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->TimeStepsInHour)) {
    1041            0 :         return (int)thisState->dataWeather->wvarsHrTsToday(timeStepNum, iHour).IsSnow;
    1042              :     }
    1043            0 :     ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
    1044            0 :     thisState->dataPluginManager->apiErrorFlag = true;
    1045            0 :     return 0;
    1046              : }
    1047              : 
    1048            0 : Real64 todayWeatherOutDryBulbAtTime(EnergyPlusState state, int hour, int timeStepNum)
    1049              : {
    1050            0 :     auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
    1051              : 
    1052            0 :     const int iHour = hour + 1;
    1053            0 :     if ((iHour > 0) && (iHour <= EnergyPlus::Constant::iHoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->TimeStepsInHour)) {
    1054            0 :         return thisState->dataWeather->wvarsHrTsToday(timeStepNum, iHour).OutDryBulbTemp;
    1055              :     }
    1056            0 :     ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
    1057            0 :     thisState->dataPluginManager->apiErrorFlag = true;
    1058            0 :     return 0.0;
    1059              : }
    1060              : 
    1061            0 : Real64 todayWeatherOutDewPointAtTime(EnergyPlusState state, int hour, int timeStepNum)
    1062              : {
    1063            0 :     auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
    1064            0 :     int iHour = hour + 1;
    1065            0 :     if ((iHour > 0) && (iHour <= EnergyPlus::Constant::iHoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->TimeStepsInHour)) {
    1066            0 :         return thisState->dataWeather->wvarsHrTsToday(timeStepNum, iHour).OutDewPointTemp;
    1067              :     }
    1068            0 :     ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
    1069            0 :     thisState->dataPluginManager->apiErrorFlag = true;
    1070            0 :     return 0.0;
    1071              : }
    1072              : 
    1073            0 : Real64 todayWeatherOutBarometricPressureAtTime(EnergyPlusState state, int hour, int timeStepNum)
    1074              : {
    1075            0 :     auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
    1076            0 :     int iHour = hour + 1;
    1077            0 :     if ((iHour > 0) && (iHour <= EnergyPlus::Constant::iHoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->TimeStepsInHour)) {
    1078            0 :         return thisState->dataWeather->wvarsHrTsToday(timeStepNum, iHour).OutBaroPress;
    1079              :     }
    1080            0 :     ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
    1081            0 :     thisState->dataPluginManager->apiErrorFlag = true;
    1082            0 :     return 0.0;
    1083              : }
    1084              : 
    1085            0 : Real64 todayWeatherOutRelativeHumidityAtTime(EnergyPlusState state, int hour, int timeStepNum)
    1086              : {
    1087            0 :     auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
    1088            0 :     const int iHour = hour + 1;
    1089            0 :     if ((iHour > 0) && (iHour <= EnergyPlus::Constant::iHoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->TimeStepsInHour)) {
    1090            0 :         return thisState->dataWeather->wvarsHrTsToday(timeStepNum, iHour).OutRelHum;
    1091              :     }
    1092            0 :     ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
    1093            0 :     thisState->dataPluginManager->apiErrorFlag = true;
    1094            0 :     return 0.0;
    1095              : }
    1096              : 
    1097            0 : Real64 todayWeatherWindSpeedAtTime(EnergyPlusState state, int hour, int timeStepNum)
    1098              : {
    1099            0 :     auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
    1100            0 :     const int iHour = hour + 1;
    1101            0 :     if ((iHour > 0) && (iHour <= EnergyPlus::Constant::iHoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->TimeStepsInHour)) {
    1102            0 :         return thisState->dataWeather->wvarsHrTsToday(timeStepNum, iHour).WindSpeed;
    1103              :     }
    1104            0 :     ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
    1105            0 :     thisState->dataPluginManager->apiErrorFlag = true;
    1106            0 :     return 0.0;
    1107              : }
    1108              : 
    1109            0 : Real64 todayWeatherWindDirectionAtTime(EnergyPlusState state, int hour, int timeStepNum)
    1110              : {
    1111            0 :     auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
    1112            0 :     const int iHour = hour + 1;
    1113            0 :     if ((iHour > 0) && (iHour <= EnergyPlus::Constant::iHoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->TimeStepsInHour)) {
    1114            0 :         return thisState->dataWeather->wvarsHrTsToday(timeStepNum, iHour).WindDir;
    1115              :     }
    1116            0 :     ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
    1117            0 :     thisState->dataPluginManager->apiErrorFlag = true;
    1118            0 :     return 0.0;
    1119              : }
    1120              : 
    1121            0 : Real64 todayWeatherSkyTemperatureAtTime(EnergyPlusState state, int hour, int timeStepNum)
    1122              : {
    1123            0 :     auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
    1124            0 :     const int iHour = hour + 1;
    1125            0 :     if ((iHour > 0) && (iHour <= EnergyPlus::Constant::iHoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->TimeStepsInHour)) {
    1126            0 :         return thisState->dataWeather->wvarsHrTsToday(timeStepNum, iHour).SkyTemp;
    1127              :     }
    1128            0 :     ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
    1129            0 :     thisState->dataPluginManager->apiErrorFlag = true;
    1130            0 :     return 0.0;
    1131              : }
    1132              : 
    1133            0 : Real64 todayWeatherHorizontalIRSkyAtTime(EnergyPlusState state, int hour, int timeStepNum)
    1134              : {
    1135            0 :     auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
    1136            0 :     const int iHour = hour + 1;
    1137            0 :     if ((iHour > 0) && (iHour <= EnergyPlus::Constant::iHoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->TimeStepsInHour)) {
    1138            0 :         return thisState->dataWeather->wvarsHrTsToday(timeStepNum, iHour).HorizIRSky;
    1139              :     }
    1140            0 :     ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
    1141            0 :     thisState->dataPluginManager->apiErrorFlag = true;
    1142            0 :     return 0.0;
    1143              : }
    1144              : 
    1145            0 : Real64 todayWeatherBeamSolarRadiationAtTime(EnergyPlusState state, int hour, int timeStepNum)
    1146              : {
    1147            0 :     auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
    1148            0 :     const int iHour = hour + 1;
    1149            0 :     if ((iHour > 0) && (iHour <= EnergyPlus::Constant::iHoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->TimeStepsInHour)) {
    1150            0 :         return thisState->dataWeather->wvarsHrTsToday(timeStepNum, iHour).BeamSolarRad;
    1151              :     }
    1152            0 :     ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
    1153            0 :     thisState->dataPluginManager->apiErrorFlag = true;
    1154            0 :     return 0.0;
    1155              : }
    1156              : 
    1157            0 : Real64 todayWeatherDiffuseSolarRadiationAtTime(EnergyPlusState state, int hour, int timeStepNum)
    1158              : {
    1159            0 :     auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
    1160            0 :     const int iHour = hour + 1;
    1161            0 :     if ((iHour > 0) && (iHour <= EnergyPlus::Constant::iHoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->TimeStepsInHour)) {
    1162            0 :         return thisState->dataWeather->wvarsHrTsToday(timeStepNum, iHour).DifSolarRad;
    1163              :     }
    1164            0 :     ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
    1165            0 :     thisState->dataPluginManager->apiErrorFlag = true;
    1166            0 :     return 0.0;
    1167              : }
    1168              : 
    1169            0 : Real64 todayWeatherAlbedoAtTime(EnergyPlusState state, int hour, int timeStepNum)
    1170              : {
    1171            0 :     auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
    1172            0 :     const int iHour = hour + 1;
    1173            0 :     if ((iHour > 0) && (iHour <= EnergyPlus::Constant::iHoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->TimeStepsInHour)) {
    1174            0 :         return thisState->dataWeather->wvarsHrTsToday(timeStepNum, iHour).Albedo;
    1175              :     }
    1176            0 :     ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
    1177            0 :     thisState->dataPluginManager->apiErrorFlag = true;
    1178            0 :     return 0.0;
    1179              : }
    1180              : 
    1181            0 : Real64 todayWeatherLiquidPrecipitationAtTime(EnergyPlusState state, int hour, int timeStepNum)
    1182              : {
    1183            0 :     auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
    1184            0 :     const int iHour = hour + 1;
    1185            0 :     if ((iHour > 0) && (iHour <= EnergyPlus::Constant::iHoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->TimeStepsInHour)) {
    1186            0 :         return thisState->dataWeather->wvarsHrTsToday(timeStepNum, iHour).LiquidPrecip;
    1187              :     }
    1188            0 :     ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
    1189            0 :     thisState->dataPluginManager->apiErrorFlag = true;
    1190            0 :     return 0.0;
    1191              : }
    1192              : 
    1193            0 : int tomorrowWeatherIsRainAtTime(EnergyPlusState state, int hour, int timeStepNum)
    1194              : {
    1195            0 :     auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
    1196            0 :     const int iHour = hour + 1;
    1197            0 :     if ((iHour > 0) && (iHour <= EnergyPlus::Constant::iHoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->TimeStepsInHour)) {
    1198            0 :         return (int)thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).IsRain;
    1199              :     }
    1200            0 :     ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
    1201            0 :     thisState->dataPluginManager->apiErrorFlag = true;
    1202            0 :     return 0;
    1203              : }
    1204              : 
    1205            0 : int tomorrowWeatherIsSnowAtTime(EnergyPlusState state, int hour, int timeStepNum)
    1206              : {
    1207            0 :     auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
    1208            0 :     const int iHour = hour + 1;
    1209            0 :     if ((iHour > 0) && (iHour <= EnergyPlus::Constant::iHoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->TimeStepsInHour)) {
    1210            0 :         return (int)thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).IsSnow;
    1211              :     }
    1212            0 :     ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
    1213            0 :     thisState->dataPluginManager->apiErrorFlag = true;
    1214            0 :     return 0;
    1215              : }
    1216              : 
    1217          720 : Real64 tomorrowWeatherOutDryBulbAtTime(EnergyPlusState state, int hour, int timeStepNum)
    1218              : {
    1219          720 :     auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
    1220          720 :     const int iHour = hour + 1;
    1221          720 :     if ((iHour > 0) && (iHour <= EnergyPlus::Constant::iHoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->TimeStepsInHour)) {
    1222          720 :         return thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).OutDryBulbTemp;
    1223              :     }
    1224            0 :     ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
    1225            0 :     thisState->dataPluginManager->apiErrorFlag = true;
    1226            0 :     return 0.0;
    1227              : }
    1228              : 
    1229            0 : Real64 tomorrowWeatherOutDewPointAtTime(EnergyPlusState state, int hour, int timeStepNum)
    1230              : {
    1231            0 :     auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
    1232            0 :     const int iHour = hour + 1;
    1233            0 :     if ((iHour > 0) && (iHour <= EnergyPlus::Constant::iHoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->TimeStepsInHour)) {
    1234            0 :         return thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).OutDewPointTemp;
    1235              :     }
    1236            0 :     ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
    1237            0 :     thisState->dataPluginManager->apiErrorFlag = true;
    1238            0 :     return 0.0;
    1239              : }
    1240              : 
    1241            0 : Real64 tomorrowWeatherOutBarometricPressureAtTime(EnergyPlusState state, int hour, int timeStepNum)
    1242              : {
    1243            0 :     auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
    1244            0 :     const int iHour = hour + 1;
    1245            0 :     if ((iHour > 0) && (iHour <= EnergyPlus::Constant::iHoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->TimeStepsInHour)) {
    1246            0 :         return thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).OutBaroPress;
    1247              :     }
    1248            0 :     ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
    1249            0 :     thisState->dataPluginManager->apiErrorFlag = true;
    1250            0 :     return 0.0;
    1251              : }
    1252              : 
    1253            0 : Real64 tomorrowWeatherOutRelativeHumidityAtTime(EnergyPlusState state, int hour, int timeStepNum)
    1254              : {
    1255            0 :     auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
    1256            0 :     const int iHour = hour + 1;
    1257            0 :     if ((iHour > 0) && (iHour <= EnergyPlus::Constant::iHoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->TimeStepsInHour)) {
    1258            0 :         return thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).OutRelHum;
    1259              :     }
    1260            0 :     ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
    1261            0 :     thisState->dataPluginManager->apiErrorFlag = true;
    1262            0 :     return 0.0;
    1263              : }
    1264              : 
    1265            0 : Real64 tomorrowWeatherWindSpeedAtTime(EnergyPlusState state, int hour, int timeStepNum)
    1266              : {
    1267            0 :     auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
    1268            0 :     const int iHour = hour + 1;
    1269            0 :     if ((iHour > 0) && (iHour <= EnergyPlus::Constant::iHoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->TimeStepsInHour)) {
    1270            0 :         return thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).WindSpeed;
    1271              :     }
    1272            0 :     ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
    1273            0 :     thisState->dataPluginManager->apiErrorFlag = true;
    1274            0 :     return 0.0;
    1275              : }
    1276              : 
    1277            0 : Real64 tomorrowWeatherWindDirectionAtTime(EnergyPlusState state, int hour, int timeStepNum)
    1278              : {
    1279            0 :     auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
    1280            0 :     const int iHour = hour + 1;
    1281            0 :     if ((iHour > 0) && (iHour <= EnergyPlus::Constant::iHoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->TimeStepsInHour)) {
    1282            0 :         return thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).WindDir;
    1283              :     }
    1284            0 :     ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
    1285            0 :     thisState->dataPluginManager->apiErrorFlag = true;
    1286            0 :     return 0.0;
    1287              : }
    1288              : 
    1289            0 : Real64 tomorrowWeatherSkyTemperatureAtTime(EnergyPlusState state, int hour, int timeStepNum)
    1290              : {
    1291            0 :     auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
    1292            0 :     const int iHour = hour + 1;
    1293            0 :     if ((iHour > 0) && (iHour <= EnergyPlus::Constant::iHoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->TimeStepsInHour)) {
    1294            0 :         return thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).SkyTemp;
    1295              :     }
    1296            0 :     ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
    1297            0 :     thisState->dataPluginManager->apiErrorFlag = true;
    1298            0 :     return 0.0;
    1299              : }
    1300              : 
    1301            0 : Real64 tomorrowWeatherHorizontalIRSkyAtTime(EnergyPlusState state, int hour, int timeStepNum)
    1302              : {
    1303            0 :     auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
    1304            0 :     const int iHour = hour + 1;
    1305            0 :     if ((iHour > 0) && (iHour <= EnergyPlus::Constant::iHoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->TimeStepsInHour)) {
    1306            0 :         return thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).HorizIRSky;
    1307              :     }
    1308            0 :     ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
    1309            0 :     thisState->dataPluginManager->apiErrorFlag = true;
    1310            0 :     return 0.0;
    1311              : }
    1312              : 
    1313            0 : Real64 tomorrowWeatherBeamSolarRadiationAtTime(EnergyPlusState state, int hour, int timeStepNum)
    1314              : {
    1315            0 :     auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
    1316            0 :     const int iHour = hour + 1;
    1317            0 :     if ((iHour > 0) && (iHour <= EnergyPlus::Constant::iHoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->TimeStepsInHour)) {
    1318            0 :         return thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).BeamSolarRad;
    1319              :     }
    1320            0 :     ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
    1321            0 :     thisState->dataPluginManager->apiErrorFlag = true;
    1322            0 :     return 0.0;
    1323              : }
    1324              : 
    1325            0 : Real64 tomorrowWeatherDiffuseSolarRadiationAtTime(EnergyPlusState state, int hour, int timeStepNum)
    1326              : {
    1327            0 :     auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
    1328            0 :     const int iHour = hour + 1;
    1329            0 :     if ((iHour > 0) && (iHour <= EnergyPlus::Constant::iHoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->TimeStepsInHour)) {
    1330            0 :         return thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).DifSolarRad;
    1331              :     }
    1332            0 :     ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
    1333            0 :     thisState->dataPluginManager->apiErrorFlag = true;
    1334            0 :     return 0.0;
    1335              : }
    1336              : 
    1337            0 : Real64 tomorrowWeatherAlbedoAtTime(EnergyPlusState state, int hour, int timeStepNum)
    1338              : {
    1339            0 :     auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
    1340            0 :     const int iHour = hour + 1;
    1341            0 :     if ((iHour > 0) && (iHour <= EnergyPlus::Constant::iHoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->TimeStepsInHour)) {
    1342            0 :         return thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).Albedo;
    1343              :     }
    1344            0 :     ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
    1345            0 :     thisState->dataPluginManager->apiErrorFlag = true;
    1346            0 :     return 0.0;
    1347              : }
    1348              : 
    1349            0 : Real64 tomorrowWeatherLiquidPrecipitationAtTime(EnergyPlusState state, const int hour, const int timeStepNum)
    1350              : {
    1351            0 :     auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
    1352            0 :     const int iHour = hour + 1;
    1353            0 :     if ((iHour > 0) && (iHour <= EnergyPlus::Constant::iHoursInDay) && (timeStepNum > 0) && (timeStepNum <= thisState->dataGlobal->TimeStepsInHour)) {
    1354            0 :         return thisState->dataWeather->wvarsHrTsTomorrow(timeStepNum, iHour).LiquidPrecip;
    1355              :     }
    1356            0 :     ShowSevereError(*thisState, "Invalid return from weather lookup, check hour and time step argument values are in range.");
    1357            0 :     thisState->dataPluginManager->apiErrorFlag = true;
    1358            0 :     return 0.0;
    1359              : }
    1360              : 
    1361         5760 : Real64 currentSimTime(EnergyPlusState state)
    1362              : {
    1363         5760 :     const auto *thisState = static_cast<EnergyPlus::EnergyPlusData *>(state);
    1364         5760 :     return (thisState->dataGlobal->DayOfSim - 1) * EnergyPlus::Constant::iHoursInDay + currentTime(state);
    1365              : }
        

Generated by: LCOV version 2.0-1