Initial commit - Support for Get Hydrometer and Get Fermentation Chamber
This commit is contained in:
commit
df1be4c144
162
.gitignore
vendored
Normal file
162
.gitignore
vendored
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
# ---> Python
|
||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
wheels/
|
||||||
|
share/python-wheels/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
MANIFEST
|
||||||
|
|
||||||
|
# PyInstaller
|
||||||
|
# Usually these files are written by a python script from a template
|
||||||
|
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||||
|
*.manifest
|
||||||
|
*.spec
|
||||||
|
|
||||||
|
# Installer logs
|
||||||
|
pip-log.txt
|
||||||
|
pip-delete-this-directory.txt
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.nox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*.cover
|
||||||
|
*.py,cover
|
||||||
|
.hypothesis/
|
||||||
|
.pytest_cache/
|
||||||
|
cover/
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
*.mo
|
||||||
|
*.pot
|
||||||
|
|
||||||
|
# Django stuff:
|
||||||
|
*.log
|
||||||
|
local_settings.py
|
||||||
|
db.sqlite3
|
||||||
|
db.sqlite3-journal
|
||||||
|
|
||||||
|
# Flask stuff:
|
||||||
|
instance/
|
||||||
|
.webassets-cache
|
||||||
|
|
||||||
|
# Scrapy stuff:
|
||||||
|
.scrapy
|
||||||
|
|
||||||
|
# Sphinx documentation
|
||||||
|
docs/_build/
|
||||||
|
|
||||||
|
# PyBuilder
|
||||||
|
.pybuilder/
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Jupyter Notebook
|
||||||
|
.ipynb_checkpoints
|
||||||
|
|
||||||
|
# IPython
|
||||||
|
profile_default/
|
||||||
|
ipython_config.py
|
||||||
|
|
||||||
|
# pyenv
|
||||||
|
# For a library or package, you might want to ignore these files since the code is
|
||||||
|
# intended to run in multiple environments; otherwise, check them in:
|
||||||
|
# .python-version
|
||||||
|
|
||||||
|
# pipenv
|
||||||
|
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||||
|
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||||
|
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||||
|
# install all needed dependencies.
|
||||||
|
#Pipfile.lock
|
||||||
|
|
||||||
|
# poetry
|
||||||
|
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
||||||
|
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||||
|
# commonly ignored for libraries.
|
||||||
|
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
||||||
|
#poetry.lock
|
||||||
|
|
||||||
|
# pdm
|
||||||
|
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
||||||
|
#pdm.lock
|
||||||
|
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
||||||
|
# in version control.
|
||||||
|
# https://pdm.fming.dev/#use-with-ide
|
||||||
|
.pdm.toml
|
||||||
|
|
||||||
|
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||||
|
__pypackages__/
|
||||||
|
|
||||||
|
# Celery stuff
|
||||||
|
celerybeat-schedule
|
||||||
|
celerybeat.pid
|
||||||
|
|
||||||
|
# SageMath parsed files
|
||||||
|
*.sage.py
|
||||||
|
|
||||||
|
# Environments
|
||||||
|
.env
|
||||||
|
.venv
|
||||||
|
env/
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
env.bak/
|
||||||
|
venv.bak/
|
||||||
|
|
||||||
|
# Spyder project settings
|
||||||
|
.spyderproject
|
||||||
|
.spyproject
|
||||||
|
|
||||||
|
# Rope project settings
|
||||||
|
.ropeproject
|
||||||
|
|
||||||
|
# mkdocs documentation
|
||||||
|
/site
|
||||||
|
|
||||||
|
# mypy
|
||||||
|
.mypy_cache/
|
||||||
|
.dmypy.json
|
||||||
|
dmypy.json
|
||||||
|
|
||||||
|
# Pyre type checker
|
||||||
|
.pyre/
|
||||||
|
|
||||||
|
# pytype static type analyzer
|
||||||
|
.pytype/
|
||||||
|
|
||||||
|
# Cython debug symbols
|
||||||
|
cython_debug/
|
||||||
|
|
||||||
|
# PyCharm
|
||||||
|
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
||||||
|
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||||
|
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||||
|
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||||
|
#t
|
||||||
|
Pipfile.lock
|
16
Pipfile
Normal file
16
Pipfile
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
[[source]]
|
||||||
|
url = "https://pypi.org/simple"
|
||||||
|
verify_ssl = true
|
||||||
|
name = "pypi"
|
||||||
|
|
||||||
|
[packages]
|
||||||
|
requests = "*"
|
||||||
|
pydantic = "*"
|
||||||
|
loguru = "*"
|
||||||
|
|
||||||
|
[dev-packages]
|
||||||
|
pytest = "*"
|
||||||
|
responses = "*"
|
||||||
|
|
||||||
|
[requires]
|
||||||
|
python_version = "3.13"
|
4
pytest.ini
Normal file
4
pytest.ini
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
[pytest]
|
||||||
|
pythonpath = src
|
||||||
|
testpaths = tests
|
||||||
|
addopts = -s
|
10
src/live_test_client.py
Normal file
10
src/live_test_client.py
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
from rapt.client import Client
|
||||||
|
from rapt.hydrometer import Hydrometer
|
||||||
|
|
||||||
|
client = Client("jfm@moerks.dk", "9OBkd5yv1xY8")
|
||||||
|
hydrometer = Hydrometer(client)
|
||||||
|
|
||||||
|
#hydrometer.get_hydrometers()
|
||||||
|
#hydrometer.get_hydrometer("2aa3b02c-78de-4715-8f5b-61bf7c3d1b62")
|
||||||
|
hydrometer.get_telemetry("2aa3b02c-78de-4715-8f5b-61bf7c3d1b62", "2025-10-07T12:51:07.3321557+00:00", "2025-10-08T12:51:07.3321557+00:00", "")
|
||||||
|
|
0
src/rapt/__init__.py
Normal file
0
src/rapt/__init__.py
Normal file
65
src/rapt/client.py
Normal file
65
src/rapt/client.py
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import requests
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
from loguru import logger
|
||||||
|
|
||||||
|
|
||||||
|
class ClientException(Exception):
|
||||||
|
def __init__(self, message):
|
||||||
|
self.message = message
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.message
|
||||||
|
|
||||||
|
class HttpClientException(ClientException):
|
||||||
|
def __init__(self, message, http_code):
|
||||||
|
self.message = message
|
||||||
|
self.http_code = http_code
|
||||||
|
logger.error(str(self))
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "["+str(self.http_code)+"] - " + self.message
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Client():
|
||||||
|
def __init__(self, username, api_key) -> None:
|
||||||
|
self.host = "https://api.rapt.io"
|
||||||
|
self.username = username
|
||||||
|
self.api_key = api_key
|
||||||
|
self.token = None
|
||||||
|
self.expires_seconds = None
|
||||||
|
self.expires = None
|
||||||
|
|
||||||
|
def get_jwt_token(self):
|
||||||
|
url = "https://id.rapt.io/connect/token"
|
||||||
|
response = requests.post(url, data={
|
||||||
|
"client_id": "rapt-user",
|
||||||
|
"grant_type": "password",
|
||||||
|
"username": self.username,
|
||||||
|
"password": self.api_key
|
||||||
|
})
|
||||||
|
|
||||||
|
if response.status_code == 200:
|
||||||
|
response_json = response.json()
|
||||||
|
self.token = response_json["access_token"]
|
||||||
|
self.expires_seconds = response_json["expires_in"]
|
||||||
|
self.expires = datetime.now() + timedelta(seconds=self.expires_seconds)
|
||||||
|
logger.trace("Expires: " + str(self.expires))
|
||||||
|
else:
|
||||||
|
raise HttpClientException(response.reason, response.status_code)
|
||||||
|
|
||||||
|
def get_auth_headers(self):
|
||||||
|
#TODO: Check expiry
|
||||||
|
if self.expires is None or self.expires <= datetime.now():
|
||||||
|
self.get_jwt_token()
|
||||||
|
|
||||||
|
return {"Authorization": "Bearer {}".format(self.token)}
|
||||||
|
|
||||||
|
def get_json(self, url, parameters):
|
||||||
|
headers = self.get_auth_headers()
|
||||||
|
response = requests.get(self.host+url, headers=headers, params=parameters)
|
||||||
|
logger.trace(response.request.url)
|
||||||
|
if response.status_code == 200:
|
||||||
|
return response.json()
|
||||||
|
else:
|
||||||
|
raise HttpClientException(response.reason, response.status_code)
|
53
src/rapt/fermentation_chamber.py
Normal file
53
src/rapt/fermentation_chamber.py
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
from rapt.client import ClientException
|
||||||
|
from rapt.model.fermentation_chamber import FermentationChamberModel, FermentationChamberTelemetryModel
|
||||||
|
from typing import Optional, List
|
||||||
|
from pydantic import TypeAdapter
|
||||||
|
from loguru import logger
|
||||||
|
|
||||||
|
|
||||||
|
class FermentationChamber():
|
||||||
|
def __init__(self, client) -> None:
|
||||||
|
self.client = client
|
||||||
|
|
||||||
|
def get_fermentation_chambers(self) -> Optional[List[FermentationChamberModel]]:
|
||||||
|
logger.debug("## GET FERMENTATION CHAMBERS ##")
|
||||||
|
try:
|
||||||
|
response_json = self.client.get_json("/api/fermentationchambers/getfermentationchambers", None)
|
||||||
|
logger.trace(response_json)
|
||||||
|
fermentation_chambers_adapter = TypeAdapter(list[FermentationChamberModel])
|
||||||
|
return fermentation_chambers_adapter.validate_python(response_json)
|
||||||
|
except ClientException:
|
||||||
|
#TODO: Handle Exception gracefully
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_fermentation_chamber(self, fermentation_chamber_id) -> Optional[FermentationChamberModel]:
|
||||||
|
logger.debug("## GET FERMENTATION CHAMBER ##")
|
||||||
|
params = {
|
||||||
|
"fermentationChamberId": fermentation_chamber_id
|
||||||
|
}
|
||||||
|
try:
|
||||||
|
response_json = self.client.get_json("/api/fermentationchambers/getfermentationchamber", params)
|
||||||
|
logger.trace(response_json)
|
||||||
|
return FermentationChamberModel.model_validate(response_json)
|
||||||
|
except ClientException:
|
||||||
|
#TODO: Handle Exception gracefully
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def get_telemetry(self, fermentation_chamber_id, start_date, end_date, profile_session_id) -> Optional[List[FermentationChamberTelemetryModel]]:
|
||||||
|
logger.debug("## GET TELEMETRY ##")
|
||||||
|
params = {
|
||||||
|
"fermentationChamberId": fermentation_chamber_id,
|
||||||
|
"startDate": start_date,
|
||||||
|
"endDate": end_date,
|
||||||
|
"profileSessionId": profile_session_id
|
||||||
|
}
|
||||||
|
try:
|
||||||
|
response_json = self.client.get_json("/api/fermentationchambers/gettelemetry", params)
|
||||||
|
logger.trace(response_json)
|
||||||
|
fermentation_chambers_adapter = TypeAdapter(list[FermentationChamberTelemetryModel])
|
||||||
|
return fermentation_chambers_adapter.validate_python(response_json)
|
||||||
|
except ClientException:
|
||||||
|
#TODO: Handle Exception gracefully
|
||||||
|
return None
|
||||||
|
|
53
src/rapt/hydrometer.py
Normal file
53
src/rapt/hydrometer.py
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
from rapt.client import ClientException
|
||||||
|
from rapt.model.hydrometer import HydrometerModel, HydrometerTelemetryModel
|
||||||
|
from pydantic import TypeAdapter
|
||||||
|
from typing import Optional, List
|
||||||
|
from loguru import logger
|
||||||
|
|
||||||
|
|
||||||
|
class Hydrometer():
|
||||||
|
def __init__(self, client) -> None:
|
||||||
|
self.client = client
|
||||||
|
|
||||||
|
def get_hydrometers(self) -> Optional[List[HydrometerModel]]:
|
||||||
|
logger.debug("## GET HYDROMETERS ##")
|
||||||
|
try:
|
||||||
|
response_json = self.client.get_json("/api/hydrometers/gethydrometers", None)
|
||||||
|
logger.trace(response_json)
|
||||||
|
hydrometers_adapter = TypeAdapter(list[HydrometerModel])
|
||||||
|
return hydrometers_adapter.validate_python(response_json)
|
||||||
|
except ClientException:
|
||||||
|
#TODO: Handle Exception gracefully
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_hydrometer(self, hydrometer_id) -> Optional[HydrometerModel]:
|
||||||
|
logger.debug("## GET HYDROMETER ##")
|
||||||
|
params = {
|
||||||
|
"hydrometerId": hydrometer_id
|
||||||
|
}
|
||||||
|
try:
|
||||||
|
response_json = self.client.get_json("/api/hydrometers/gethydrometer", params)
|
||||||
|
logger.trace(response_json)
|
||||||
|
return HydrometerModel.model_validate(response_json)
|
||||||
|
except ClientException:
|
||||||
|
#TODO: Handle Exception gracefully
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def get_telemetry(self, hydrometer_id, start_date, end_date, profile_session_id) -> Optional[List[HydrometerTelemetryModel]]:
|
||||||
|
logger.debug("## GET TELEMETRY ##")
|
||||||
|
params = {
|
||||||
|
"hydrometerId": hydrometer_id,
|
||||||
|
"startDate": start_date,
|
||||||
|
"endDate": end_date,
|
||||||
|
"profileSessionId": profile_session_id
|
||||||
|
}
|
||||||
|
try:
|
||||||
|
response_json = self.client.get_json("/api/hydrometers/gettelemetry", params)
|
||||||
|
logger.trace(response_json)
|
||||||
|
hydrometers_adapter = TypeAdapter(list[HydrometerTelemetryModel])
|
||||||
|
return hydrometers_adapter.validate_python(response_json)
|
||||||
|
except ClientException:
|
||||||
|
#TODO: Handle Exception gracefully
|
||||||
|
return None
|
||||||
|
|
0
src/rapt/model/__init__.py
Normal file
0
src/rapt/model/__init__.py
Normal file
6
src/rapt/model/amount.py
Normal file
6
src/rapt/model/amount.py
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
class AmountTypes(str, Enum):
|
||||||
|
Weight = "Weight",
|
||||||
|
Volume = "Volume",
|
||||||
|
Units = "Units"
|
13
src/rapt/model/base.py
Normal file
13
src/rapt/model/base.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
from pydantic import BaseModel, Field
|
||||||
|
from datetime import datetime
|
||||||
|
from uuid import UUID
|
||||||
|
|
||||||
|
|
||||||
|
class RaptBaseModel(BaseModel):
|
||||||
|
id: UUID
|
||||||
|
deleted: bool
|
||||||
|
created_on: datetime = Field(alias="createdOn")
|
||||||
|
created_by: UUID = Field(alias="createdBy")
|
||||||
|
modified_on: datetime = Field(alias="modifiedOn")
|
||||||
|
modified_by: UUID = Field(alias="modifiedBy")
|
||||||
|
|
39
src/rapt/model/device.py
Normal file
39
src/rapt/model/device.py
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
|
||||||
|
class DeviceTypes(str, Enum):
|
||||||
|
FermentationChamber = "FermentationChamber",
|
||||||
|
TemperatureController = "TemperatureController",
|
||||||
|
Hydrometer = "Hydrometer",
|
||||||
|
GrainWeigh = "GrainWeigh",
|
||||||
|
BrewZilla = "BrewZilla",
|
||||||
|
CanFiller = "CanFiller",
|
||||||
|
GlycolChiller = "GlycolChiller",
|
||||||
|
Still = "Still",
|
||||||
|
BLETemperature = "BLETemperature",
|
||||||
|
BLEHumidity = "BLEHumidity",
|
||||||
|
BLETempHumidity = "BLETempHumidity",
|
||||||
|
BLEPressure = "BLEPressure",
|
||||||
|
External = "External",
|
||||||
|
Fridge = "Fridge",
|
||||||
|
GrainWeighDevice = "GrainWeighDevice",
|
||||||
|
Unknown = "Unknown"
|
||||||
|
|
||||||
|
class DeviceTypesNullable(str, Enum):
|
||||||
|
FermentationChamber = "FermentationChamber",
|
||||||
|
TemperatureController = "TemperatureController",
|
||||||
|
Hydrometer = "Hydrometer",
|
||||||
|
GrainWeigh = "GrainWeigh",
|
||||||
|
BrewZilla = "BrewZilla",
|
||||||
|
CanFiller = "CanFiller",
|
||||||
|
GlycolChiller = "GlycolChiller",
|
||||||
|
Still = "Still",
|
||||||
|
BLETemperature = "BLETemperature",
|
||||||
|
BLEHumidity = "BLEHumidity",
|
||||||
|
BLETempHumidity = "BLETempHumidity",
|
||||||
|
BLEPressure = "BLEPressure",
|
||||||
|
External = "External",
|
||||||
|
Fridge = "Fridge",
|
||||||
|
GrainWeighDevice = "GrainWeighDevice",
|
||||||
|
Unknown = "Unknown"
|
||||||
|
null = "null"
|
102
src/rapt/model/fermentation_chamber.py
Normal file
102
src/rapt/model/fermentation_chamber.py
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
from rapt.model.base import RaptBaseModel
|
||||||
|
from rapt.model.profile import ProfileSessionModel, ProfileSessionStatusModel
|
||||||
|
from rapt.model.device import DeviceTypes
|
||||||
|
from rapt.model.toggle import ToggleStates
|
||||||
|
from datetime import datetime
|
||||||
|
from uuid import UUID
|
||||||
|
from pydantic import BaseModel, Field
|
||||||
|
from typing import Optional, List
|
||||||
|
|
||||||
|
|
||||||
|
class FermentationChamberTelemetryModel(BaseModel):
|
||||||
|
id: UUID
|
||||||
|
row_key: Optional[str] = Field(alias="rowKey", default=None)
|
||||||
|
created_on: datetime = Field(alias="createdOn")
|
||||||
|
mac_address: Optional[str] = Field(alias="macAddress", default=None)
|
||||||
|
rssi: float
|
||||||
|
control_device_type: Optional[str] = Field(alias="controlDeviceType", default=None)
|
||||||
|
control_device_mac_address: Optional[str] = Field(alias="controlDeviceMacAddress", default=None)
|
||||||
|
control_device_temperature: Optional[float] = Field(alias="controlDeviceTemperature", default=None)
|
||||||
|
temperature: float
|
||||||
|
target_temperature: Optional[float] = Field(alias="targetTemperature", default=None)
|
||||||
|
min_target_temperature: Optional[float] = Field(alias="minTargetTemperature", default=None)
|
||||||
|
max_target_temperature: Optional[float] = Field(alias="maxTargetTemperature", default=None)
|
||||||
|
total_run_time: float = Field(alias="totalRunTime")
|
||||||
|
compressor_run_time: float = Field(alias="compressorRunTime")
|
||||||
|
compressor_starts: float = Field(alias="compressorStarts")
|
||||||
|
heating_run_time: float = Field(alias="heatingRunTime")
|
||||||
|
heating_starts: float = Field(alias="heatingStarts")
|
||||||
|
auxillary_run_time: float = Field(alias="auxillaryRunTime")
|
||||||
|
auxillary_starts: float = Field(alias="auxillaryStarts")
|
||||||
|
profile_id: Optional[UUID] = Field(alias="profileId", default=None)
|
||||||
|
profile_step_id: Optional[UUID] = Field(alias="profileStepId", default=None)
|
||||||
|
profile_session_start_date: Optional[datetime] = Field(alias="profileSessionStartDate", default=None)
|
||||||
|
profile_session_time: Optional[int] = Field(alias="profileSessionTime", default=None)
|
||||||
|
profile_step_progress: Optional[int] = Field(alias="profileStepProgress", default=None)
|
||||||
|
|
||||||
|
class FermentationChamberModel(RaptBaseModel):
|
||||||
|
name: str
|
||||||
|
serial_number: Optional[str] = Field(alias="serialNumber", default=None)
|
||||||
|
mac_address: str = Field(alias="macAddress")
|
||||||
|
device_type: DeviceTypes = Field(alias="deviceType")
|
||||||
|
active: bool
|
||||||
|
disabled: bool
|
||||||
|
username: Optional[str] = None
|
||||||
|
connection_state: Optional[str] = Field(alias="connectionState", default=None)
|
||||||
|
status: Optional[str] = None
|
||||||
|
error: Optional[str] = None
|
||||||
|
last_activity_time: Optional[datetime] = Field(alias="lastActivityTime", default=None)
|
||||||
|
rssi: float
|
||||||
|
firmware_version: Optional[str] = Field(alias="firmwareVersion", default=None)
|
||||||
|
is_latest_firmware: bool = Field(alias="isLatestFirmware")
|
||||||
|
active_profile_id: Optional[UUID] = Field(alias="activeProfileId", default=None)
|
||||||
|
active_profile_step_id: Optional[UUID] = Field(alias="activeProfileStepId", default=None)
|
||||||
|
active_profile_session: ProfileSessionStatusModel = Field(alias="activeProfileSession")
|
||||||
|
profile_sessions: Optional[List[ProfileSessionModel]] = Field(alias="profileSessions", default=None)
|
||||||
|
beta_updates: bool = Field(alias="betaUpdates")
|
||||||
|
bluetooth_enabled: bool = Field(alias="bluetoothEnabled")
|
||||||
|
graph_zoom_level: float = Field(alias="graphZoomLevel")
|
||||||
|
temperature: float
|
||||||
|
target_temperature: Optional[float] = Field(alias="targetTemperature", default=None)
|
||||||
|
min_target_temperature: Optional[float] = Field(alias="minTargetTemperature", default=None)
|
||||||
|
max_target_temperature: Optional[float] = Field(alias="maxTargetTemperature", default=None)
|
||||||
|
total_run_time: float = Field(alias="totalRunTime")
|
||||||
|
cooling_enabled: bool = Field(alias="coolingEnabled")
|
||||||
|
cooling_run_time: float = Field(alias="coolingRunTime")
|
||||||
|
cooling_starts: float = Field(alias="coolingStarts")
|
||||||
|
heating_enabled: bool = Field(alias="heatingEnabled")
|
||||||
|
heating_run_time: float = Field(alias="heatingRunTime")
|
||||||
|
heating_starts: float = Field(alias="heatingStarts")
|
||||||
|
heating_utilisation: float = Field(alias="heatingUtilisation")
|
||||||
|
high_temp_alarm: float = Field(alias="highTempAlarm")
|
||||||
|
low_temp_alarm: float = Field(alias="lowTempAlarm")
|
||||||
|
ntc_beta: float = Field(alias="ntcBeta")
|
||||||
|
ntc_ref_resistance: float = Field(alias="ntcRefResistance")
|
||||||
|
ntc_ref_temperature: float = Field(alias="ntcRefTemperature")
|
||||||
|
pid_cycle_time: float = Field(alias="pidCycleTime")
|
||||||
|
pid_enabled: bool = Field(alias="pidEnabled")
|
||||||
|
pid_proportional: float = Field(alias="pidProportional")
|
||||||
|
pid_integral: float = Field(alias="pidIntegral")
|
||||||
|
pid_derivative: float = Field(alias="pidDerivative")
|
||||||
|
sensor_differential: float = Field(alias="sensorDifferential")
|
||||||
|
sensor_timeout: float = Field(alias="sensorTimeout")
|
||||||
|
show_graph: bool = Field(alias="showGraph")
|
||||||
|
sounds_enabled: bool = Field(alias="soundsEnabled")
|
||||||
|
temp_unit: Optional[str] = Field(alias="tempUnit", default=None)
|
||||||
|
use_internal_sensor: bool = Field(alias="useInternalSensor")
|
||||||
|
control_device_type: Optional[str] = Field(alias="controlDeviceType", default=None)
|
||||||
|
control_device_mac_address: Optional[str] = Field(alias="controlDeviceMacAddress", default=None)
|
||||||
|
control_device_temperature: Optional[float] = Field(alias="controlDeviceTemperature", default=None)
|
||||||
|
customer_use: str = Field(alias="customerUse")
|
||||||
|
telemetry_frequency: int = Field(alias="telemetryFrequency")
|
||||||
|
compressor_delay: float = Field(alias="compressorDelay")
|
||||||
|
mode_switch_delay: float = Field(alias="modeSwitchDelay")
|
||||||
|
cooling_hysteresis: float = Field(alias="coolingHysteresis")
|
||||||
|
heating_hysteresis: float = Field(alias="heatingHysteresis")
|
||||||
|
telemetry: Optional[List[FermentationChamberTelemetryModel]] = None
|
||||||
|
compressor_run_time: float = Field(alias="compressorRunTime")
|
||||||
|
compressor_starts: float = Field(alias="compressorStarts")
|
||||||
|
auxillary_run_time: float = Field(alias="auxillaryRunTime")
|
||||||
|
auxillary_starts: float = Field(alias="auxillaryStarts")
|
||||||
|
fan_enabled: bool = Field(alias="fanEnabled")
|
||||||
|
light_enabled: ToggleStates = Field(alias="lightEnabled")
|
46
src/rapt/model/hydrometer.py
Normal file
46
src/rapt/model/hydrometer.py
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
from datetime import datetime
|
||||||
|
from uuid import UUID
|
||||||
|
from pydantic import BaseModel, Field
|
||||||
|
from typing import Optional, List
|
||||||
|
from rapt.model.base import RaptBaseModel
|
||||||
|
from rapt.model.device import DeviceTypes, DeviceTypesNullable
|
||||||
|
from rapt.model.profile import ProfileSessionStatusModel
|
||||||
|
|
||||||
|
|
||||||
|
class HydrometerTelemetryModel(BaseModel):
|
||||||
|
id: UUID
|
||||||
|
row_key: Optional[str] = Field(alias="rowKey")
|
||||||
|
created_on: datetime = Field(alias="createdOn")
|
||||||
|
mac_address: Optional[str] = Field(alias="macAddress")
|
||||||
|
rssi: float
|
||||||
|
temperature: float
|
||||||
|
gravity: float
|
||||||
|
gravity_velocity: float = Field(alias="gravityVelocity")
|
||||||
|
battery: float
|
||||||
|
version: Optional[str]
|
||||||
|
|
||||||
|
class HydrometerModel(RaptBaseModel):
|
||||||
|
name: str
|
||||||
|
serial_number: Optional[str] = Field(alias="serialNumber", default=None)
|
||||||
|
mac_address: str = Field(alias="macAddress")
|
||||||
|
device_type: DeviceTypes = Field(alias="deviceType")
|
||||||
|
active: bool
|
||||||
|
disabled: bool
|
||||||
|
username: Optional[str] = None
|
||||||
|
connection_state: Optional[str] = Field(alias="connectionState", default=None)
|
||||||
|
status: Optional[str] = None
|
||||||
|
error: Optional[str] = None
|
||||||
|
last_activity_time: Optional[datetime] = Field(alias="lastActivityTime")
|
||||||
|
rssi: float
|
||||||
|
firmware_version: Optional[str] = Field(alias="firmwareVersion")
|
||||||
|
is_latest_firmware: bool = Field(alias="isLatestFirmware")
|
||||||
|
active_profile_id: Optional[UUID] = Field(alias="activeProfileId", default=None)
|
||||||
|
active_profile_step: Optional[UUID] = Field(alias="activeProfileStepId", default=None)
|
||||||
|
active_profile_session: Optional[ProfileSessionStatusModel] = Field(alias="activeProfileSession", default=None)
|
||||||
|
telemetry: Optional[List[HydrometerTelemetryModel]]
|
||||||
|
paired_device_type: Optional[DeviceTypesNullable] = Field(alias="pairedDeviceType", default=None)
|
||||||
|
paired_device_id: Optional[UUID] = Field(alias="pairedDeviceId", default=None)
|
||||||
|
temperature: float
|
||||||
|
gravity: float
|
||||||
|
gravity_velocity: float = Field(alias="gravityVelocity")
|
||||||
|
battery: float
|
134
src/rapt/model/profile.py
Normal file
134
src/rapt/model/profile.py
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
from pydantic import Field
|
||||||
|
from typing import Optional, List
|
||||||
|
from enum import Enum
|
||||||
|
from datetime import datetime
|
||||||
|
from uuid import UUID
|
||||||
|
from rapt.model.base import RaptBaseModel
|
||||||
|
from rapt.model.yeast import YeastModel
|
||||||
|
|
||||||
|
|
||||||
|
class ProfileAlertTriggers(str, Enum):
|
||||||
|
StepStart = "StepStart",
|
||||||
|
StepEnd = "StepEnd",
|
||||||
|
Temperature = "Temperature",
|
||||||
|
Gravity = "Gravity",
|
||||||
|
GravityVelocity = "GravityVelocity",
|
||||||
|
Duration = "Duration"
|
||||||
|
|
||||||
|
class ProfileValueOperatorsNullable(str, Enum):
|
||||||
|
Equals = "Equals",
|
||||||
|
LessThan = "LessThan",
|
||||||
|
GreaterThan = "GreaterThan",
|
||||||
|
null = "null"
|
||||||
|
|
||||||
|
class ProfileStepControlTypes(str, Enum):
|
||||||
|
Target = "Target",
|
||||||
|
Ramp = "Ramp",
|
||||||
|
FreeRise = "FreeRise"
|
||||||
|
|
||||||
|
class ProfileStepEndTypes(str, Enum):
|
||||||
|
Duration = "Duration",
|
||||||
|
Temperature = "Temperature",
|
||||||
|
Gravity = "Gravity",
|
||||||
|
GravityVelocity = "GravityVelocity",
|
||||||
|
Manual = "Manual"
|
||||||
|
|
||||||
|
class ProfileStepDurationTypesNullable(str, Enum):
|
||||||
|
Start = "Start",
|
||||||
|
Temperature = "Temperature",
|
||||||
|
Gravity = "Gravity",
|
||||||
|
GravityVelocity = "GravityVelocity",
|
||||||
|
Manual = "Manual",
|
||||||
|
null = "null"
|
||||||
|
|
||||||
|
class ProfileAlertModel(RaptBaseModel):
|
||||||
|
alert_text: str = Field(alias="alertText")
|
||||||
|
trigger: ProfileAlertTriggers
|
||||||
|
operator: ProfileValueOperatorsNullable
|
||||||
|
temperature: float
|
||||||
|
gravity: float
|
||||||
|
profile_id: UUID = Field(alias="profileId")
|
||||||
|
|
||||||
|
class ProfileStepAlertModel(RaptBaseModel):
|
||||||
|
alert_text: Optional[str] = Field(alias="alertText")
|
||||||
|
trigger: ProfileAlertTriggers
|
||||||
|
operator: Optional[ProfileValueOperatorsNullable]
|
||||||
|
temperature: Optional[float]
|
||||||
|
gravity: Optional[float]
|
||||||
|
length: Optional[int]
|
||||||
|
profile_step_id: UUID = Field(alias="profileStepId")
|
||||||
|
|
||||||
|
class ProfileStepModel(RaptBaseModel):
|
||||||
|
name: Optional[str]
|
||||||
|
order: int
|
||||||
|
control_type: ProfileStepControlTypes = Field(alias="controlType")
|
||||||
|
end_type: ProfileStepEndTypes = Field(alias="endType")
|
||||||
|
duration_type: Optional[ProfileStepDurationTypesNullable] = Field(alias="durationType")
|
||||||
|
operator: Optional[ProfileValueOperatorsNullable]
|
||||||
|
length: Optional[int]
|
||||||
|
temperature: Optional[float]
|
||||||
|
min_temperature: Optional[float] = Field(alias="minTemperature")
|
||||||
|
max_temperature: Optional[float] = Field(alias="maxTemperature")
|
||||||
|
gravity: Optional[float]
|
||||||
|
pump_enabled: Optional[bool] = Field(alias="pumpEnabled")
|
||||||
|
pump_utilisation: Optional[float] = Field(alias="pumpUtilisation")
|
||||||
|
heating_utilisation: Optional[float] = Field(alias="heatingUtilisation")
|
||||||
|
pid_enabled: Optional[bool] = Field(alias="pidEnabled")
|
||||||
|
sensor_differential: Optional[float] = Field(alias="sensorDifferential")
|
||||||
|
profile_id: UUID = Field(alias="profileId")
|
||||||
|
alerts: Optional[List[ProfileStepAlertModel]]
|
||||||
|
|
||||||
|
class ProfileSessionModel(RaptBaseModel):
|
||||||
|
name: Optional[str]
|
||||||
|
description: Optional[str]
|
||||||
|
profile_id: Optional[UUID] = Field(alias="profileId")
|
||||||
|
# profile: ProfileModel
|
||||||
|
brewzilla_id: Optional[UUID] = Field(alias="brewZillaId")
|
||||||
|
fermentation_chamger_id: Optional[UUID] = Field(alias="fermentationChamberId")
|
||||||
|
hydrometer_id: Optional[UUID] = Field(alias="hydrometerId")
|
||||||
|
still_id: Optional[UUID] = Field(alias="stillId")
|
||||||
|
temperature_controller_id: Optional[UUID] = Field(alias="temperatureControllerId")
|
||||||
|
start_date: Optional[datetime] = Field(alias="startDate")
|
||||||
|
end_date: Optional[datetime] = Field(alias="endDate")
|
||||||
|
original_gravity: Optional[float] = Field(alias="originalGravity")
|
||||||
|
final_gravity: Optional[float] = Field(alias="finalGravity")
|
||||||
|
yeast_id: Optional[UUID] = Field(alias="yeastId")
|
||||||
|
yeast: YeastModel
|
||||||
|
sent_alerts: List[Optional[ProfileAlertModel]] = Field(alias="sentAlerts")
|
||||||
|
|
||||||
|
class ProfileModel(RaptBaseModel):
|
||||||
|
name: str
|
||||||
|
description: Optional[str]
|
||||||
|
public: bool
|
||||||
|
profile_name: Optional[str] = Field(alias="profileName")
|
||||||
|
rating: float
|
||||||
|
rating_count: int = Field(alias="ratingCount")
|
||||||
|
rating_score: float = Field(alias="ratingScore")
|
||||||
|
copy_count: float = Field(alias="copyCount")
|
||||||
|
view_count: float = Field(alias="viewCount")
|
||||||
|
profile_type_id: Optional[UUID] = Field(alias="profileTypeId")
|
||||||
|
alerts: Optional[List[ProfileAlertModel]]
|
||||||
|
steps: Optional[List[ProfileStepModel]]
|
||||||
|
profile_sessions: Optional[List[ProfileSessionModel]] = Field(alias="profileSessions")
|
||||||
|
|
||||||
|
class ProfileSessionStatusModel(RaptBaseModel):
|
||||||
|
name: Optional[str]
|
||||||
|
description: Optional[str]
|
||||||
|
profile_id: Optional[UUID] = Field(alias="profileId")
|
||||||
|
profile: ProfileModel
|
||||||
|
brewzilla_id: Optional[UUID] = Field(alias="brewZillaId")
|
||||||
|
fermentation_chamger_id: Optional[UUID] = Field(alias="fermentationChamberId")
|
||||||
|
hydrometer_id: Optional[UUID] = Field(alias="hydrometerId")
|
||||||
|
still_id: Optional[UUID] = Field(alias="stillId")
|
||||||
|
temperature_controller_id: Optional[UUID] = Field(alias="temperatureControllerId")
|
||||||
|
start_date: Optional[datetime] = Field(alias="startDate")
|
||||||
|
end_date: Optional[datetime] = Field(alias="endDate")
|
||||||
|
original_gravity: Optional[float] = Field(alias="originalGravity")
|
||||||
|
final_gravity: Optional[float] = Field(alias="finalGravity")
|
||||||
|
yeast_id: Optional[UUID] = Field(alias="yeastId")
|
||||||
|
yeast: YeastModel
|
||||||
|
sent_alerts: List[Optional[ProfileAlertModel]] = Field(alias="sentAlerts")
|
||||||
|
estimated_end_date: Optional[datetime] = Field(alias="estimatedEndDate")
|
||||||
|
profile_length: Optional[float] = Field(alias="profileLength")
|
||||||
|
current_profile_time: Optional[float] = Field(alias="currentProfileTime")
|
||||||
|
remaining_profile_time: Optional[float] = Field(alias="remainingProfileTime")
|
6
src/rapt/model/toggle.py
Normal file
6
src/rapt/model/toggle.py
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
class ToggleStates(str, Enum):
|
||||||
|
AlwaysOn = "AlwaysOn",
|
||||||
|
AlwaysOff = "AlwaysOff",
|
||||||
|
Automatic = "Automatic"
|
29
src/rapt/model/yeast.py
Normal file
29
src/rapt/model/yeast.py
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
from pydantic import Field
|
||||||
|
from typing import Optional
|
||||||
|
from uuid import UUID
|
||||||
|
from rapt.model.base import RaptBaseModel
|
||||||
|
from rapt.model.amount import AmountTypes
|
||||||
|
|
||||||
|
|
||||||
|
class YeastModel(RaptBaseModel):
|
||||||
|
name: Optional[str]
|
||||||
|
product_id: Optional[str] = Field(alias="productId")
|
||||||
|
laboratory: Optional[str]
|
||||||
|
supplier: Optional[str]
|
||||||
|
kegland_product_code: Optional[str] = Field(alias="keglandProductCode")
|
||||||
|
yeast_type: Optional[str] = Field(alias="type")
|
||||||
|
form: Optional[str]
|
||||||
|
min_temperature: float = Field(alias="minTemperature")
|
||||||
|
max_temperature: float = Field(alias="maxTemperature")
|
||||||
|
flocculation: Optional[str]
|
||||||
|
attenuation: float
|
||||||
|
notes: Optional[str]
|
||||||
|
best_for: Optional[str] = Field(alias="bestFor")
|
||||||
|
max_reuse: int = Field(alias="maxReuse")
|
||||||
|
add_to_secondary: bool = Field(alias="addToSecondary")
|
||||||
|
amount_types: AmountTypes = Field(alias="amountType")
|
||||||
|
inventory_amount: Optional[float] = Field(alias="inventoryAmount")
|
||||||
|
archived: bool
|
||||||
|
stock_level: float = Field(alias="stockLevel")
|
||||||
|
global_yeast_id: Optional[UUID] = Field(alias="globalYeastId")
|
||||||
|
is_global: bool = Field(alias="isGlobal")
|
384
tests/json/get_fermentation_chamber_response.json
Normal file
384
tests/json/get_fermentation_chamber_response.json
Normal file
@ -0,0 +1,384 @@
|
|||||||
|
{
|
||||||
|
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"deleted": true,
|
||||||
|
"createdOn": "2025-10-09T11:56:29.302Z",
|
||||||
|
"createdBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"modifiedOn": "2025-10-09T11:56:29.302Z",
|
||||||
|
"modifiedBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"name": "string",
|
||||||
|
"serialNumber": "string",
|
||||||
|
"macAddress": "string",
|
||||||
|
"deviceType": "FermentationChamber",
|
||||||
|
"active": true,
|
||||||
|
"disabled": true,
|
||||||
|
"username": "string",
|
||||||
|
"connectionState": "string",
|
||||||
|
"status": "string",
|
||||||
|
"error": "string",
|
||||||
|
"lastActivityTime": "2025-10-09T11:56:29.302Z",
|
||||||
|
"rssi": 0,
|
||||||
|
"firmwareVersion": "string",
|
||||||
|
"isLatestFirmware": true,
|
||||||
|
"activeProfileId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"activeProfileStepId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"activeProfileSession": {
|
||||||
|
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"deleted": true,
|
||||||
|
"createdOn": "2025-10-09T11:56:29.302Z",
|
||||||
|
"createdBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"modifiedOn": "2025-10-09T11:56:29.302Z",
|
||||||
|
"modifiedBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"name": "string",
|
||||||
|
"description": "string",
|
||||||
|
"profileId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"profile": {
|
||||||
|
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"deleted": true,
|
||||||
|
"createdOn": "2025-10-09T11:56:29.302Z",
|
||||||
|
"createdBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"modifiedOn": "2025-10-09T11:56:29.302Z",
|
||||||
|
"modifiedBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"name": "string",
|
||||||
|
"description": "string",
|
||||||
|
"public": true,
|
||||||
|
"profileName": "string",
|
||||||
|
"rating": 0,
|
||||||
|
"ratingCount": 0,
|
||||||
|
"ratingScore": 0,
|
||||||
|
"copyCount": 0,
|
||||||
|
"viewCount": 0,
|
||||||
|
"profileTypeId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"alerts": [
|
||||||
|
{
|
||||||
|
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"deleted": true,
|
||||||
|
"createdOn": "2025-10-09T11:56:29.302Z",
|
||||||
|
"createdBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"modifiedOn": "2025-10-09T11:56:29.302Z",
|
||||||
|
"modifiedBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"alertText": "string",
|
||||||
|
"trigger": "StepStart",
|
||||||
|
"operator": "Equals",
|
||||||
|
"temperature": 0,
|
||||||
|
"gravity": 0,
|
||||||
|
"profileId": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"deleted": true,
|
||||||
|
"createdOn": "2025-10-09T11:56:29.302Z",
|
||||||
|
"createdBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"modifiedOn": "2025-10-09T11:56:29.302Z",
|
||||||
|
"modifiedBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"name": "string",
|
||||||
|
"order": 0,
|
||||||
|
"controlType": "Target",
|
||||||
|
"endType": "Duration",
|
||||||
|
"durationType": "Start",
|
||||||
|
"operator": "Equals",
|
||||||
|
"length": 0,
|
||||||
|
"temperature": 0,
|
||||||
|
"minTemperature": 0,
|
||||||
|
"maxTemperature": 0,
|
||||||
|
"gravity": 0,
|
||||||
|
"pumpEnabled": true,
|
||||||
|
"pumpUtilisation": 0,
|
||||||
|
"heatingUtilisation": 0,
|
||||||
|
"pidEnabled": true,
|
||||||
|
"sensorDifferential": 0,
|
||||||
|
"profileId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"alerts": [
|
||||||
|
{
|
||||||
|
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"deleted": true,
|
||||||
|
"createdOn": "2025-10-09T11:56:29.302Z",
|
||||||
|
"createdBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"modifiedOn": "2025-10-09T11:56:29.302Z",
|
||||||
|
"modifiedBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"alertText": "string",
|
||||||
|
"trigger": "StepStart",
|
||||||
|
"operator": "Equals",
|
||||||
|
"temperature": 0,
|
||||||
|
"gravity": 0,
|
||||||
|
"length": 0,
|
||||||
|
"profileStepId": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"profileSessions": [
|
||||||
|
{
|
||||||
|
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"deleted": true,
|
||||||
|
"createdOn": "2025-10-09T11:56:29.302Z",
|
||||||
|
"createdBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"modifiedOn": "2025-10-09T11:56:29.302Z",
|
||||||
|
"modifiedBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"name": "string",
|
||||||
|
"description": "string",
|
||||||
|
"profileId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"profile": "string",
|
||||||
|
"brewZillaId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"fermentationChamberId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"hydrometerId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"stillId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"temperatureControllerId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"startDate": "2025-10-09T11:56:29.302Z",
|
||||||
|
"endDate": "2025-10-09T11:56:29.302Z",
|
||||||
|
"originalGravity": 0,
|
||||||
|
"finalGravity": 0,
|
||||||
|
"yeastId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"yeast": {
|
||||||
|
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"deleted": true,
|
||||||
|
"createdOn": "2025-10-09T11:56:29.302Z",
|
||||||
|
"createdBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"modifiedOn": "2025-10-09T11:56:29.302Z",
|
||||||
|
"modifiedBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"name": "string",
|
||||||
|
"productId": "string",
|
||||||
|
"laboratory": "string",
|
||||||
|
"supplier": "string",
|
||||||
|
"keglandProductCode": "string",
|
||||||
|
"type": "string",
|
||||||
|
"form": "string",
|
||||||
|
"minTemperature": 0,
|
||||||
|
"maxTemperature": 0,
|
||||||
|
"flocculation": "string",
|
||||||
|
"attenuation": 0,
|
||||||
|
"notes": "string",
|
||||||
|
"bestFor": "string",
|
||||||
|
"maxReuse": 0,
|
||||||
|
"addToSecondary": true,
|
||||||
|
"amountType": "Weight",
|
||||||
|
"inventoryAmount": 0,
|
||||||
|
"archived": true,
|
||||||
|
"stockLevel": 0,
|
||||||
|
"globalYeastId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"isGlobal": true
|
||||||
|
},
|
||||||
|
"sentAlerts": [
|
||||||
|
{
|
||||||
|
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"deleted": true,
|
||||||
|
"createdOn": "2025-10-09T11:56:29.302Z",
|
||||||
|
"createdBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"modifiedOn": "2025-10-09T11:56:29.302Z",
|
||||||
|
"modifiedBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"alertText": "string",
|
||||||
|
"trigger": "StepStart",
|
||||||
|
"operator": "Equals",
|
||||||
|
"temperature": 0,
|
||||||
|
"gravity": 0,
|
||||||
|
"profileId": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brewZillaId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"fermentationChamberId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"hydrometerId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"stillId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"temperatureControllerId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"startDate": "2025-10-09T11:56:29.302Z",
|
||||||
|
"endDate": "2025-10-09T11:56:29.302Z",
|
||||||
|
"originalGravity": 0,
|
||||||
|
"finalGravity": 0,
|
||||||
|
"yeastId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"yeast": {
|
||||||
|
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"deleted": true,
|
||||||
|
"createdOn": "2025-10-09T11:56:29.302Z",
|
||||||
|
"createdBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"modifiedOn": "2025-10-09T11:56:29.302Z",
|
||||||
|
"modifiedBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"name": "string",
|
||||||
|
"productId": "string",
|
||||||
|
"laboratory": "string",
|
||||||
|
"supplier": "string",
|
||||||
|
"keglandProductCode": "string",
|
||||||
|
"type": "string",
|
||||||
|
"form": "string",
|
||||||
|
"minTemperature": 0,
|
||||||
|
"maxTemperature": 0,
|
||||||
|
"flocculation": "string",
|
||||||
|
"attenuation": 0,
|
||||||
|
"notes": "string",
|
||||||
|
"bestFor": "string",
|
||||||
|
"maxReuse": 0,
|
||||||
|
"addToSecondary": true,
|
||||||
|
"amountType": "Weight",
|
||||||
|
"inventoryAmount": 0,
|
||||||
|
"archived": true,
|
||||||
|
"stockLevel": 0,
|
||||||
|
"globalYeastId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"isGlobal": true
|
||||||
|
},
|
||||||
|
"sentAlerts": [
|
||||||
|
{
|
||||||
|
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"deleted": true,
|
||||||
|
"createdOn": "2025-10-09T11:56:29.302Z",
|
||||||
|
"createdBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"modifiedOn": "2025-10-09T11:56:29.302Z",
|
||||||
|
"modifiedBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"alertText": "string",
|
||||||
|
"trigger": "StepStart",
|
||||||
|
"operator": "Equals",
|
||||||
|
"temperature": 0,
|
||||||
|
"gravity": 0,
|
||||||
|
"profileId": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"estimatedEndDate": "2025-10-09T11:56:29.302Z",
|
||||||
|
"profileLength": 0,
|
||||||
|
"currentProfileTime": 0,
|
||||||
|
"remainingProfileTime": 0
|
||||||
|
},
|
||||||
|
"profileSessions": [
|
||||||
|
{
|
||||||
|
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"deleted": true,
|
||||||
|
"createdOn": "2025-10-09T11:56:29.302Z",
|
||||||
|
"createdBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"modifiedOn": "2025-10-09T11:56:29.302Z",
|
||||||
|
"modifiedBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"name": "string",
|
||||||
|
"description": "string",
|
||||||
|
"profileId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"profile": "string",
|
||||||
|
"brewZillaId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"fermentationChamberId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"hydrometerId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"stillId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"temperatureControllerId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"startDate": "2025-10-09T11:56:29.302Z",
|
||||||
|
"endDate": "2025-10-09T11:56:29.302Z",
|
||||||
|
"originalGravity": 0,
|
||||||
|
"finalGravity": 0,
|
||||||
|
"yeastId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"yeast": {
|
||||||
|
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"deleted": true,
|
||||||
|
"createdOn": "2025-10-09T11:56:29.302Z",
|
||||||
|
"createdBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"modifiedOn": "2025-10-09T11:56:29.302Z",
|
||||||
|
"modifiedBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"name": "string",
|
||||||
|
"productId": "string",
|
||||||
|
"laboratory": "string",
|
||||||
|
"supplier": "string",
|
||||||
|
"keglandProductCode": "string",
|
||||||
|
"type": "string",
|
||||||
|
"form": "string",
|
||||||
|
"minTemperature": 0,
|
||||||
|
"maxTemperature": 0,
|
||||||
|
"flocculation": "string",
|
||||||
|
"attenuation": 0,
|
||||||
|
"notes": "string",
|
||||||
|
"bestFor": "string",
|
||||||
|
"maxReuse": 0,
|
||||||
|
"addToSecondary": true,
|
||||||
|
"amountType": "Weight",
|
||||||
|
"inventoryAmount": 0,
|
||||||
|
"archived": true,
|
||||||
|
"stockLevel": 0,
|
||||||
|
"globalYeastId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"isGlobal": true
|
||||||
|
},
|
||||||
|
"sentAlerts": [
|
||||||
|
{
|
||||||
|
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"deleted": true,
|
||||||
|
"createdOn": "2025-10-09T11:56:29.302Z",
|
||||||
|
"createdBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"modifiedOn": "2025-10-09T11:56:29.302Z",
|
||||||
|
"modifiedBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"alertText": "string",
|
||||||
|
"trigger": "StepStart",
|
||||||
|
"operator": "Equals",
|
||||||
|
"temperature": 0,
|
||||||
|
"gravity": 0,
|
||||||
|
"profileId": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"betaUpdates": true,
|
||||||
|
"bluetoothEnabled": true,
|
||||||
|
"graphZoomLevel": 0,
|
||||||
|
"temperature": 0,
|
||||||
|
"targetTemperature": 0,
|
||||||
|
"minTargetTemperature": 0,
|
||||||
|
"maxTargetTemperature": 0,
|
||||||
|
"totalRunTime": 0,
|
||||||
|
"coolingEnabled": true,
|
||||||
|
"coolingRunTime": 0,
|
||||||
|
"coolingStarts": 0,
|
||||||
|
"heatingEnabled": true,
|
||||||
|
"heatingRunTime": 0,
|
||||||
|
"heatingStarts": 0,
|
||||||
|
"heatingUtilisation": 0,
|
||||||
|
"highTempAlarm": 0,
|
||||||
|
"lowTempAlarm": 0,
|
||||||
|
"ntcBeta": 0,
|
||||||
|
"ntcRefResistance": 0,
|
||||||
|
"ntcRefTemperature": 0,
|
||||||
|
"pidCycleTime": 0,
|
||||||
|
"pidEnabled": true,
|
||||||
|
"pidProportional": 0,
|
||||||
|
"pidIntegral": 0,
|
||||||
|
"pidDerivative": 0,
|
||||||
|
"sensorDifferential": 0,
|
||||||
|
"sensorTimeout": 0,
|
||||||
|
"showGraph": true,
|
||||||
|
"soundsEnabled": true,
|
||||||
|
"tempUnit": "string",
|
||||||
|
"useInternalSensor": true,
|
||||||
|
"controlDeviceType": "string",
|
||||||
|
"controlDeviceMacAddress": "string",
|
||||||
|
"controlDeviceTemperature": 0,
|
||||||
|
"customerUse": "string",
|
||||||
|
"telemetryFrequency": 14440,
|
||||||
|
"compressorDelay": 10,
|
||||||
|
"modeSwitchDelay": 30,
|
||||||
|
"coolingHysteresis": 10,
|
||||||
|
"heatingHysteresis": 10,
|
||||||
|
"telemetry": [
|
||||||
|
{
|
||||||
|
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"rowKey": "string",
|
||||||
|
"createdOn": "2025-10-09T11:56:29.302Z",
|
||||||
|
"macAddress": "string",
|
||||||
|
"rssi": 0,
|
||||||
|
"controlDeviceType": "string",
|
||||||
|
"controlDeviceMacAddress": "string",
|
||||||
|
"controlDeviceTemperature": 0,
|
||||||
|
"temperature": 0,
|
||||||
|
"targetTemperature": 0,
|
||||||
|
"minTargetTemperature": 0,
|
||||||
|
"maxTargetTemperature": 0,
|
||||||
|
"totalRunTime": 0,
|
||||||
|
"compressorRunTime": 0,
|
||||||
|
"compressorStarts": 0,
|
||||||
|
"heatingRunTime": 0,
|
||||||
|
"heatingStarts": 0,
|
||||||
|
"auxillaryRunTime": 0,
|
||||||
|
"auxillaryStarts": 0,
|
||||||
|
"profileId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"profileStepId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"profileSessionStartDate": "2025-10-09T11:56:29.302Z",
|
||||||
|
"profileSessionTime": 0,
|
||||||
|
"profileStepProgress": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"compressorRunTime": 0,
|
||||||
|
"compressorStarts": 0,
|
||||||
|
"auxillaryRunTime": 0,
|
||||||
|
"auxillaryStarts": 0,
|
||||||
|
"fanEnabled": true,
|
||||||
|
"lightEnabled": "AlwaysOn"
|
||||||
|
}
|
28
tests/json/get_fermentation_chamber_telemetry_response.json
Normal file
28
tests/json/get_fermentation_chamber_telemetry_response.json
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"rowKey": "string",
|
||||||
|
"createdOn": "2025-10-09T09:29:04.638Z",
|
||||||
|
"macAddress": "string",
|
||||||
|
"rssi": 0,
|
||||||
|
"controlDeviceType": "string",
|
||||||
|
"controlDeviceMacAddress": "string",
|
||||||
|
"controlDeviceTemperature": 0,
|
||||||
|
"temperature": 0,
|
||||||
|
"targetTemperature": 0,
|
||||||
|
"minTargetTemperature": 0,
|
||||||
|
"maxTargetTemperature": 0,
|
||||||
|
"totalRunTime": 0,
|
||||||
|
"compressorRunTime": 0,
|
||||||
|
"compressorStarts": 0,
|
||||||
|
"heatingRunTime": 0,
|
||||||
|
"heatingStarts": 0,
|
||||||
|
"auxillaryRunTime": 0,
|
||||||
|
"auxillaryStarts": 0,
|
||||||
|
"profileId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"profileStepId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"profileSessionStartDate": "2025-10-09T09:29:04.638Z",
|
||||||
|
"profileSessionTime": 0,
|
||||||
|
"profileStepProgress": 0
|
||||||
|
}
|
||||||
|
]
|
386
tests/json/get_fermentation_chambers_response.json
Normal file
386
tests/json/get_fermentation_chambers_response.json
Normal file
@ -0,0 +1,386 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"deleted": true,
|
||||||
|
"createdOn": "2025-10-09T11:13:05.885Z",
|
||||||
|
"createdBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"modifiedOn": "2025-10-09T11:13:05.885Z",
|
||||||
|
"modifiedBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"name": "string",
|
||||||
|
"serialNumber": "string",
|
||||||
|
"macAddress": "string",
|
||||||
|
"deviceType": "FermentationChamber",
|
||||||
|
"active": true,
|
||||||
|
"disabled": true,
|
||||||
|
"username": "string",
|
||||||
|
"connectionState": "string",
|
||||||
|
"status": "string",
|
||||||
|
"error": "string",
|
||||||
|
"lastActivityTime": "2025-10-09T11:13:05.885Z",
|
||||||
|
"rssi": 0,
|
||||||
|
"firmwareVersion": "string",
|
||||||
|
"isLatestFirmware": true,
|
||||||
|
"activeProfileId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"activeProfileStepId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"activeProfileSession": {
|
||||||
|
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"deleted": true,
|
||||||
|
"createdOn": "2025-10-09T11:13:05.885Z",
|
||||||
|
"createdBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"modifiedOn": "2025-10-09T11:13:05.885Z",
|
||||||
|
"modifiedBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"name": "string",
|
||||||
|
"description": "string",
|
||||||
|
"profileId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"profile": {
|
||||||
|
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"deleted": true,
|
||||||
|
"createdOn": "2025-10-09T11:13:05.885Z",
|
||||||
|
"createdBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"modifiedOn": "2025-10-09T11:13:05.885Z",
|
||||||
|
"modifiedBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"name": "string",
|
||||||
|
"description": "string",
|
||||||
|
"public": true,
|
||||||
|
"profileName": "string",
|
||||||
|
"rating": 0,
|
||||||
|
"ratingCount": 0,
|
||||||
|
"ratingScore": 0,
|
||||||
|
"copyCount": 0,
|
||||||
|
"viewCount": 0,
|
||||||
|
"profileTypeId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"alerts": [
|
||||||
|
{
|
||||||
|
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"deleted": true,
|
||||||
|
"createdOn": "2025-10-09T11:13:05.885Z",
|
||||||
|
"createdBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"modifiedOn": "2025-10-09T11:13:05.885Z",
|
||||||
|
"modifiedBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"alertText": "string",
|
||||||
|
"trigger": "StepStart",
|
||||||
|
"operator": "Equals",
|
||||||
|
"temperature": 0,
|
||||||
|
"gravity": 0,
|
||||||
|
"profileId": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"deleted": true,
|
||||||
|
"createdOn": "2025-10-09T11:13:05.885Z",
|
||||||
|
"createdBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"modifiedOn": "2025-10-09T11:13:05.885Z",
|
||||||
|
"modifiedBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"name": "string",
|
||||||
|
"order": 0,
|
||||||
|
"controlType": "Target",
|
||||||
|
"endType": "Duration",
|
||||||
|
"durationType": "Start",
|
||||||
|
"operator": "Equals",
|
||||||
|
"length": 0,
|
||||||
|
"temperature": 0,
|
||||||
|
"minTemperature": 0,
|
||||||
|
"maxTemperature": 0,
|
||||||
|
"gravity": 0,
|
||||||
|
"pumpEnabled": true,
|
||||||
|
"pumpUtilisation": 0,
|
||||||
|
"heatingUtilisation": 0,
|
||||||
|
"pidEnabled": true,
|
||||||
|
"sensorDifferential": 0,
|
||||||
|
"profileId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"alerts": [
|
||||||
|
{
|
||||||
|
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"deleted": true,
|
||||||
|
"createdOn": "2025-10-09T11:13:05.885Z",
|
||||||
|
"createdBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"modifiedOn": "2025-10-09T11:13:05.885Z",
|
||||||
|
"modifiedBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"alertText": "string",
|
||||||
|
"trigger": "StepStart",
|
||||||
|
"operator": "Equals",
|
||||||
|
"temperature": 0,
|
||||||
|
"gravity": 0,
|
||||||
|
"length": 0,
|
||||||
|
"profileStepId": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"profileSessions": [
|
||||||
|
{
|
||||||
|
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"deleted": true,
|
||||||
|
"createdOn": "2025-10-09T11:13:05.885Z",
|
||||||
|
"createdBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"modifiedOn": "2025-10-09T11:13:05.885Z",
|
||||||
|
"modifiedBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"name": "string",
|
||||||
|
"description": "string",
|
||||||
|
"profileId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"profile": "string",
|
||||||
|
"brewZillaId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"fermentationChamberId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"hydrometerId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"stillId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"temperatureControllerId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"startDate": "2025-10-09T11:13:05.885Z",
|
||||||
|
"endDate": "2025-10-09T11:13:05.885Z",
|
||||||
|
"originalGravity": 0,
|
||||||
|
"finalGravity": 0,
|
||||||
|
"yeastId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"yeast": {
|
||||||
|
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"deleted": true,
|
||||||
|
"createdOn": "2025-10-09T11:13:05.885Z",
|
||||||
|
"createdBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"modifiedOn": "2025-10-09T11:13:05.885Z",
|
||||||
|
"modifiedBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"name": "string",
|
||||||
|
"productId": "string",
|
||||||
|
"laboratory": "string",
|
||||||
|
"supplier": "string",
|
||||||
|
"keglandProductCode": "string",
|
||||||
|
"type": "string",
|
||||||
|
"form": "string",
|
||||||
|
"minTemperature": 0,
|
||||||
|
"maxTemperature": 0,
|
||||||
|
"flocculation": "string",
|
||||||
|
"attenuation": 0,
|
||||||
|
"notes": "string",
|
||||||
|
"bestFor": "string",
|
||||||
|
"maxReuse": 0,
|
||||||
|
"addToSecondary": true,
|
||||||
|
"amountType": "Weight",
|
||||||
|
"inventoryAmount": 0,
|
||||||
|
"archived": true,
|
||||||
|
"stockLevel": 0,
|
||||||
|
"globalYeastId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"isGlobal": true
|
||||||
|
},
|
||||||
|
"sentAlerts": [
|
||||||
|
{
|
||||||
|
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"deleted": true,
|
||||||
|
"createdOn": "2025-10-09T11:13:05.885Z",
|
||||||
|
"createdBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"modifiedOn": "2025-10-09T11:13:05.885Z",
|
||||||
|
"modifiedBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"alertText": "string",
|
||||||
|
"trigger": "StepStart",
|
||||||
|
"operator": "Equals",
|
||||||
|
"temperature": 0,
|
||||||
|
"gravity": 0,
|
||||||
|
"profileId": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"brewZillaId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"fermentationChamberId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"hydrometerId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"stillId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"temperatureControllerId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"startDate": "2025-10-09T11:13:05.885Z",
|
||||||
|
"endDate": "2025-10-09T11:13:05.885Z",
|
||||||
|
"originalGravity": 0,
|
||||||
|
"finalGravity": 0,
|
||||||
|
"yeastId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"yeast": {
|
||||||
|
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"deleted": true,
|
||||||
|
"createdOn": "2025-10-09T11:13:05.885Z",
|
||||||
|
"createdBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"modifiedOn": "2025-10-09T11:13:05.885Z",
|
||||||
|
"modifiedBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"name": "string",
|
||||||
|
"productId": "string",
|
||||||
|
"laboratory": "string",
|
||||||
|
"supplier": "string",
|
||||||
|
"keglandProductCode": "string",
|
||||||
|
"type": "string",
|
||||||
|
"form": "string",
|
||||||
|
"minTemperature": 0,
|
||||||
|
"maxTemperature": 0,
|
||||||
|
"flocculation": "string",
|
||||||
|
"attenuation": 0,
|
||||||
|
"notes": "string",
|
||||||
|
"bestFor": "string",
|
||||||
|
"maxReuse": 0,
|
||||||
|
"addToSecondary": true,
|
||||||
|
"amountType": "Weight",
|
||||||
|
"inventoryAmount": 0,
|
||||||
|
"archived": true,
|
||||||
|
"stockLevel": 0,
|
||||||
|
"globalYeastId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"isGlobal": true
|
||||||
|
},
|
||||||
|
"sentAlerts": [
|
||||||
|
{
|
||||||
|
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"deleted": true,
|
||||||
|
"createdOn": "2025-10-09T11:13:05.885Z",
|
||||||
|
"createdBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"modifiedOn": "2025-10-09T11:13:05.885Z",
|
||||||
|
"modifiedBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"alertText": "string",
|
||||||
|
"trigger": "StepStart",
|
||||||
|
"operator": "Equals",
|
||||||
|
"temperature": 0,
|
||||||
|
"gravity": 0,
|
||||||
|
"profileId": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"estimatedEndDate": "2025-10-09T11:13:05.885Z",
|
||||||
|
"profileLength": 0,
|
||||||
|
"currentProfileTime": 0,
|
||||||
|
"remainingProfileTime": 0
|
||||||
|
},
|
||||||
|
"profileSessions": [
|
||||||
|
{
|
||||||
|
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"deleted": true,
|
||||||
|
"createdOn": "2025-10-09T11:13:05.885Z",
|
||||||
|
"createdBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"modifiedOn": "2025-10-09T11:13:05.885Z",
|
||||||
|
"modifiedBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"name": "string",
|
||||||
|
"description": "string",
|
||||||
|
"profileId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"profile": "string",
|
||||||
|
"brewZillaId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"fermentationChamberId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"hydrometerId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"stillId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"temperatureControllerId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"startDate": "2025-10-09T11:13:05.885Z",
|
||||||
|
"endDate": "2025-10-09T11:13:05.885Z",
|
||||||
|
"originalGravity": 0,
|
||||||
|
"finalGravity": 0,
|
||||||
|
"yeastId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"yeast": {
|
||||||
|
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"deleted": true,
|
||||||
|
"createdOn": "2025-10-09T11:13:05.885Z",
|
||||||
|
"createdBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"modifiedOn": "2025-10-09T11:13:05.885Z",
|
||||||
|
"modifiedBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"name": "string",
|
||||||
|
"productId": "string",
|
||||||
|
"laboratory": "string",
|
||||||
|
"supplier": "string",
|
||||||
|
"keglandProductCode": "string",
|
||||||
|
"type": "string",
|
||||||
|
"form": "string",
|
||||||
|
"minTemperature": 0,
|
||||||
|
"maxTemperature": 0,
|
||||||
|
"flocculation": "string",
|
||||||
|
"attenuation": 0,
|
||||||
|
"notes": "string",
|
||||||
|
"bestFor": "string",
|
||||||
|
"maxReuse": 0,
|
||||||
|
"addToSecondary": true,
|
||||||
|
"amountType": "Weight",
|
||||||
|
"inventoryAmount": 0,
|
||||||
|
"archived": true,
|
||||||
|
"stockLevel": 0,
|
||||||
|
"globalYeastId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"isGlobal": true
|
||||||
|
},
|
||||||
|
"sentAlerts": [
|
||||||
|
{
|
||||||
|
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"deleted": true,
|
||||||
|
"createdOn": "2025-10-09T11:13:05.885Z",
|
||||||
|
"createdBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"modifiedOn": "2025-10-09T11:13:05.885Z",
|
||||||
|
"modifiedBy": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"alertText": "string",
|
||||||
|
"trigger": "StepStart",
|
||||||
|
"operator": "Equals",
|
||||||
|
"temperature": 0,
|
||||||
|
"gravity": 0,
|
||||||
|
"profileId": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"betaUpdates": true,
|
||||||
|
"bluetoothEnabled": true,
|
||||||
|
"graphZoomLevel": 0,
|
||||||
|
"temperature": 0,
|
||||||
|
"targetTemperature": 0,
|
||||||
|
"minTargetTemperature": 0,
|
||||||
|
"maxTargetTemperature": 0,
|
||||||
|
"totalRunTime": 0,
|
||||||
|
"coolingEnabled": true,
|
||||||
|
"coolingRunTime": 0,
|
||||||
|
"coolingStarts": 0,
|
||||||
|
"heatingEnabled": true,
|
||||||
|
"heatingRunTime": 0,
|
||||||
|
"heatingStarts": 0,
|
||||||
|
"heatingUtilisation": 0,
|
||||||
|
"highTempAlarm": 0,
|
||||||
|
"lowTempAlarm": 0,
|
||||||
|
"ntcBeta": 0,
|
||||||
|
"ntcRefResistance": 0,
|
||||||
|
"ntcRefTemperature": 0,
|
||||||
|
"pidCycleTime": 0,
|
||||||
|
"pidEnabled": true,
|
||||||
|
"pidProportional": 0,
|
||||||
|
"pidIntegral": 0,
|
||||||
|
"pidDerivative": 0,
|
||||||
|
"sensorDifferential": 0,
|
||||||
|
"sensorTimeout": 0,
|
||||||
|
"showGraph": true,
|
||||||
|
"soundsEnabled": true,
|
||||||
|
"tempUnit": "string",
|
||||||
|
"useInternalSensor": true,
|
||||||
|
"controlDeviceType": "string",
|
||||||
|
"controlDeviceMacAddress": "string",
|
||||||
|
"controlDeviceTemperature": 0,
|
||||||
|
"customerUse": "string",
|
||||||
|
"telemetryFrequency": 14440,
|
||||||
|
"compressorDelay": 10,
|
||||||
|
"modeSwitchDelay": 30,
|
||||||
|
"coolingHysteresis": 10,
|
||||||
|
"heatingHysteresis": 10,
|
||||||
|
"telemetry": [
|
||||||
|
{
|
||||||
|
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"rowKey": "string",
|
||||||
|
"createdOn": "2025-10-09T11:13:05.885Z",
|
||||||
|
"macAddress": "string",
|
||||||
|
"rssi": 0,
|
||||||
|
"controlDeviceType": "string",
|
||||||
|
"controlDeviceMacAddress": "string",
|
||||||
|
"controlDeviceTemperature": 0,
|
||||||
|
"temperature": 0,
|
||||||
|
"targetTemperature": 0,
|
||||||
|
"minTargetTemperature": 0,
|
||||||
|
"maxTargetTemperature": 0,
|
||||||
|
"totalRunTime": 0,
|
||||||
|
"compressorRunTime": 0,
|
||||||
|
"compressorStarts": 0,
|
||||||
|
"heatingRunTime": 0,
|
||||||
|
"heatingStarts": 0,
|
||||||
|
"auxillaryRunTime": 0,
|
||||||
|
"auxillaryStarts": 0,
|
||||||
|
"profileId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"profileStepId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
|
"profileSessionStartDate": "2025-10-09T11:13:05.885Z",
|
||||||
|
"profileSessionTime": 0,
|
||||||
|
"profileStepProgress": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"compressorRunTime": 0,
|
||||||
|
"compressorStarts": 0,
|
||||||
|
"auxillaryRunTime": 0,
|
||||||
|
"auxillaryStarts": 0,
|
||||||
|
"fanEnabled": true,
|
||||||
|
"lightEnabled": "AlwaysOn"
|
||||||
|
}
|
||||||
|
]
|
35
tests/json/get_hydrometer_response.json
Normal file
35
tests/json/get_hydrometer_response.json
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"telemetry": [
|
||||||
|
{
|
||||||
|
"temperature": 17.5625,
|
||||||
|
"gravity": 1325.07,
|
||||||
|
"gravityVelocity": 0,
|
||||||
|
"battery": 0,
|
||||||
|
"version": "20250319_055542_b3788ba",
|
||||||
|
"id": "68423584-1a35-4341-b67c-78456f4ae9f3",
|
||||||
|
"rowKey": "2516424593326678442",
|
||||||
|
"createdOn": "2025-10-07T12:51:07.3321557+00:00",
|
||||||
|
"macAddress": "ac-15-18-df-84-94",
|
||||||
|
"rssi": -56
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"temperature": 17.5625,
|
||||||
|
"gravity": 1325.07,
|
||||||
|
"gravityVelocity": 0,
|
||||||
|
"battery": 0,
|
||||||
|
"name": "Hegnsgården Yellow",
|
||||||
|
"macAddress": "ac-15-18-df-84-94",
|
||||||
|
"deviceType": "Hydrometer",
|
||||||
|
"active": false,
|
||||||
|
"disabled": false,
|
||||||
|
"lastActivityTime": "2025-10-07T12:51:07.3321557+00:00",
|
||||||
|
"rssi": -56,
|
||||||
|
"firmwareVersion": "20250319_055542_b3788ba",
|
||||||
|
"isLatestFirmware": true,
|
||||||
|
"modifiedOn": "2025-10-07T12:51:07.3603727+00:00",
|
||||||
|
"modifiedBy": "00000000-0000-0000-0000-000000000000",
|
||||||
|
"id": "2aa3b02c-78de-4715-8f5b-61bf7c3d1b62",
|
||||||
|
"deleted": false,
|
||||||
|
"createdOn": "2025-10-07T09:44:01.1515163+00:00",
|
||||||
|
"createdBy": "475ebc33-8e90-4be5-2424-08ddfbe49482"
|
||||||
|
}
|
14
tests/json/get_hydrometer_telemetry_response.json
Normal file
14
tests/json/get_hydrometer_telemetry_response.json
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"temperature": 17.5625,
|
||||||
|
"gravity": 1325.07,
|
||||||
|
"gravityVelocity": 0,
|
||||||
|
"battery": 0,
|
||||||
|
"version": "20250319_055542_b3788ba",
|
||||||
|
"id": "50d5885c-b637-4343-bb47-cc76e9f3c0c1",
|
||||||
|
"rowKey": "2516424593326678442",
|
||||||
|
"createdOn": "2025-10-07T12:51:07.3321557+00:00",
|
||||||
|
"macAddress": "ac-15-18-df-84-94",
|
||||||
|
"rssi": -56
|
||||||
|
}
|
||||||
|
]
|
37
tests/json/get_hydrometers_response.json
Normal file
37
tests/json/get_hydrometers_response.json
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"telemetry": [
|
||||||
|
{
|
||||||
|
"temperature": 17.5625,
|
||||||
|
"gravity": 1325.07,
|
||||||
|
"gravityVelocity": 0,
|
||||||
|
"battery": 0,
|
||||||
|
"version": "20250319_055542_b3788ba",
|
||||||
|
"id": "55462886-4400-4608-b283-3ce4426dafd3",
|
||||||
|
"rowKey": "2516424593326678442",
|
||||||
|
"createdOn": "2025-10-07T12:51:07.3321557+00:00",
|
||||||
|
"macAddress": "ac-15-18-df-84-94",
|
||||||
|
"rssi": -56
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"temperature": 17.5625,
|
||||||
|
"gravity": 1325.07,
|
||||||
|
"gravityVelocity": 0,
|
||||||
|
"battery": 0,
|
||||||
|
"name": "Hegnsgården Yellow",
|
||||||
|
"macAddress": "ac-15-18-df-84-94",
|
||||||
|
"deviceType": "Hydrometer",
|
||||||
|
"active": false,
|
||||||
|
"disabled": false,
|
||||||
|
"lastActivityTime": "2025-10-07T12:51:07.3321557+00:00",
|
||||||
|
"rssi": -56,
|
||||||
|
"firmwareVersion": "20250319_055542_b3788ba",
|
||||||
|
"isLatestFirmware": false,
|
||||||
|
"modifiedOn": "2025-10-07T12:51:07.3603727+00:00",
|
||||||
|
"modifiedBy": "00000000-0000-0000-0000-000000000000",
|
||||||
|
"id": "2aa3b02c-78de-4715-8f5b-61bf7c3d1b62",
|
||||||
|
"deleted": false,
|
||||||
|
"createdOn": "2025-10-07T09:44:01.1515163+00:00",
|
||||||
|
"createdBy": "475ebc33-8e90-4be5-2424-08ddfbe49482"
|
||||||
|
}
|
||||||
|
]
|
6
tests/json/token_response.json
Normal file
6
tests/json/token_response.json
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"access_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IkYzM0E0QzYzNkZFOUE3RjBFNzVGQkRBQTQ1REIwOTdBQjUxRUVGMTlSUzI1NiIsIng1dCI6Ijh6cE1ZMl9wcF9Eblg3MnFSZHNKZXJVZTd4ayIsInR5cCI6ImF0K2p3dCJ9.eyJpc3MiOiJodHRwczovL2lkLnJhcHQuaW8iLCJuYmYiOjE3NTk5MjcyMjQsImlhdCI6MTc1OTkyNzIyNCwiZXhwIjoxNzU5OTMwODI0LCJhdWQiOiJyYXB0LWFwaSIsInNjb3BlIjpbIm9wZW5pZCIsInByb2ZpbGUiLCJyYXB0LWFwaSIsInJhcHQtYXBpLnB1YmxpYyJdLCJhbXIiOlsiY3VzdG9tIl0sImNsaWVudF9pZCI6InJhcHQtdXNlciIsInN1YiI6IjQ3NWViYzMzLThlOTAtNGJlNS0yNDI0LTA4ZGRmYmU0OTQ4MiIsImF1dGhfdGltZSI6MTc1OTkyNzIyNCwiaWRwIjoibG9jYWwiLCJmaXJzdG5hbWUiOiJKZXNwZXIiLCJsYXN0bmFtZSI6IkZ1c3NpbmcgTVx1MDBGOHJrIiwiY291bnRyeSI6IkRlbm1hcmsiLCJlbWFpbCI6ImpmbUBtb2Vya3MuZGsiLCJwcm9maWxlbmFtZSI6ImpmbSIsImVtYWlsY29uZmlybWVkIjoiZmFsc2UiLCJqdGkiOiI3RDM3QjcxMDNBMTc4QkQ0RkMwM0ZCRDNGNTBFMDY2MiJ9.HJtC6Cfps5rqsukMYFRi7S4awpz0KqJjSX1EdL1K6NMpxVEmqmiiA3LwXrsjCbu2FoLjswxyM7rCFqVBZnnQ71DcQJ9gJCe1Ddonj-l5SfA90KHjlvLPQOhvCLrYHc9ulDEi64Dz-WfH8V7WCy1fgl3lY8xmRstS8rjO-5jVwQFFlZvyOHoke09iMsRQmCyuiGYbqmn1i31VSK6L3fMuRfrc1o165T1Xts66vAupJ6nqEhHnAusvCM2gagEvAiXx3hH3xxid4K6zCQLvbg0jxKUHnKI9q2xVj30bW0C2_lKSDKpOOTLjWpjrwjVag5DYxYFggNVgTvF90f_hYddxFX8s9_dgY6EbTunSA1ki86r82Rw7Ebvfwy1phjNHllgu85Y73tIYADcQYxzjglNKPX1Dzed8liUOAXTHgL2Z9-4_q8bwmgNrGy9eH4K_PjyqEuuhDvy2GQxjhOojOXJOU-aSaE4KwaHTod1CZB-kaikMAKjsHDTi3cRspFU4sli665zgPZ2UKYsjTWSlqoKpA7wO3RrMKQiCrNEqyE0ldOi1ctCS-dBEBkuhc-THTwOqMDQTQ6Iqqk1dK72Nm8uB5TwPur-TP4YYxi1hY6w0jSOs0JzUVpaMGgAXg3CM_zhWgTE9S44R3gjxX6EsXayI5f5WtstxpHMbB3rO_DrZPjA",
|
||||||
|
"expires_in": 3600,
|
||||||
|
"token_type": "Bearer",
|
||||||
|
"scope": "openid profile rapt-api rapt-api.public"
|
||||||
|
}
|
83
tests/test_fermentation_chamber.py
Normal file
83
tests/test_fermentation_chamber.py
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
import pytest
|
||||||
|
import json
|
||||||
|
import responses
|
||||||
|
from rapt.client import Client
|
||||||
|
from rapt.fermentation_chamber import FermentationChamber
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def client():
|
||||||
|
yield Client("test", "test")
|
||||||
|
|
||||||
|
@responses.activate
|
||||||
|
def test_get_fermentation_chambers(client):
|
||||||
|
responses.post("https://id.rapt.io/connect/token", json=json_reader("./tests/json/token_response.json"))
|
||||||
|
responses.get("https://api.rapt.io/api/fermentationchambers/getfermentationchambers", json=json_reader("./tests/json/get_fermentation_chambers_response.json"))
|
||||||
|
fermentation_chamber = FermentationChamber(client)
|
||||||
|
ferms = fermentation_chamber.get_fermentation_chambers()
|
||||||
|
|
||||||
|
assert ferms is not None
|
||||||
|
assert len(ferms) == 1
|
||||||
|
|
||||||
|
@responses.activate
|
||||||
|
def test_get_fermentation_chambers_500(client):
|
||||||
|
responses.post("https://id.rapt.io/connect/token", json=json_reader("./tests/json/token_response.json"))
|
||||||
|
responses.add(
|
||||||
|
responses.GET,
|
||||||
|
"https://api.rapt.io/api/fermentationchambers/getfermentationchambers",
|
||||||
|
status=500,
|
||||||
|
)
|
||||||
|
fermentation_chamber = FermentationChamber(client)
|
||||||
|
ferms = fermentation_chamber.get_fermentation_chambers()
|
||||||
|
|
||||||
|
assert ferms is None
|
||||||
|
|
||||||
|
@responses.activate
|
||||||
|
def test_get_fermentation_chamber(client):
|
||||||
|
responses.post("https://id.rapt.io/connect/token", json=json_reader("./tests/json/token_response.json"))
|
||||||
|
responses.get("https://api.rapt.io/api/fermentationchambers/getfermentationchamber", json=json_reader("./tests/json/get_fermentation_chamber_response.json"))
|
||||||
|
fermentation_chamber = FermentationChamber(client)
|
||||||
|
ferms = fermentation_chamber.get_fermentation_chamber("")
|
||||||
|
|
||||||
|
assert ferms is not None
|
||||||
|
|
||||||
|
@responses.activate
|
||||||
|
def test_get_fermentation_chamber_500(client):
|
||||||
|
responses.post("https://id.rapt.io/connect/token", json=json_reader("./tests/json/token_response.json"))
|
||||||
|
responses.add(
|
||||||
|
responses.GET,
|
||||||
|
"https://api.rapt.io/api/fermentationchambers/getfermentationchamber",
|
||||||
|
status=500,
|
||||||
|
)
|
||||||
|
fermentation_chamber = FermentationChamber(client)
|
||||||
|
ferms = fermentation_chamber.get_fermentation_chamber("")
|
||||||
|
|
||||||
|
assert ferms is None
|
||||||
|
|
||||||
|
@responses.activate
|
||||||
|
def test_get_telemetry(client):
|
||||||
|
responses.post("https://id.rapt.io/connect/token", json=json_reader("./tests/json/token_response.json"))
|
||||||
|
responses.get("https://api.rapt.io/api/fermentationchambers/gettelemetry", json=json_reader("./tests/json/get_fermentation_chamber_telemetry_response.json"))
|
||||||
|
fermentation_chamber = FermentationChamber(client)
|
||||||
|
telemetry = fermentation_chamber.get_telemetry("", "", "", "")
|
||||||
|
|
||||||
|
assert telemetry is not None
|
||||||
|
assert len(telemetry) == 1
|
||||||
|
|
||||||
|
@responses.activate
|
||||||
|
def test_get_telemetry_500(client):
|
||||||
|
responses.post("https://id.rapt.io/connect/token", json=json_reader("./tests/json/token_response.json"))
|
||||||
|
responses.add(
|
||||||
|
responses.GET,
|
||||||
|
"https://api.rapt.io/api/fermentationchambers/gettelemetry",
|
||||||
|
status=500,
|
||||||
|
)
|
||||||
|
fermentation_chamber = FermentationChamber(client)
|
||||||
|
telemetry = fermentation_chamber.get_telemetry("", "", "", "")
|
||||||
|
|
||||||
|
assert telemetry is None
|
||||||
|
|
||||||
|
|
||||||
|
def json_reader(path):
|
||||||
|
with open(path) as f:
|
||||||
|
return json.load(f)
|
83
tests/test_hydrometer.py
Normal file
83
tests/test_hydrometer.py
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
import pytest
|
||||||
|
import json
|
||||||
|
import responses
|
||||||
|
from rapt.client import Client
|
||||||
|
from rapt.hydrometer import Hydrometer
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def client():
|
||||||
|
yield Client("test", "test")
|
||||||
|
|
||||||
|
@responses.activate
|
||||||
|
def test_get_hydrometers(client):
|
||||||
|
responses.post("https://id.rapt.io/connect/token", json=json_reader("./tests/json/token_response.json"))
|
||||||
|
responses.get("https://api.rapt.io/api/hydrometers/gethydrometers", json=json_reader("./tests/json/get_hydrometers_response.json"))
|
||||||
|
hydrometer = Hydrometer(client)
|
||||||
|
hydros = hydrometer.get_hydrometers()
|
||||||
|
|
||||||
|
assert hydros is not None
|
||||||
|
assert len(hydros) == 1
|
||||||
|
|
||||||
|
@responses.activate
|
||||||
|
def test_get_hydrometers_500(client):
|
||||||
|
responses.post("https://id.rapt.io/connect/token", json=json_reader("./tests/json/token_response.json"))
|
||||||
|
responses.add(
|
||||||
|
responses.GET,
|
||||||
|
"https://api.rapt.io/api/hydrometers/gethydrometers",
|
||||||
|
status=500,
|
||||||
|
)
|
||||||
|
hydrometer = Hydrometer(client)
|
||||||
|
hydros = hydrometer.get_hydrometers()
|
||||||
|
|
||||||
|
assert hydros is None
|
||||||
|
|
||||||
|
@responses.activate
|
||||||
|
def test_get_hydrometer(client):
|
||||||
|
responses.post("https://id.rapt.io/connect/token", json=json_reader("./tests/json/token_response.json"))
|
||||||
|
responses.get("https://api.rapt.io/api/hydrometers/gethydrometer", json=json_reader("./tests/json/get_hydrometer_response.json"))
|
||||||
|
hydrometer = Hydrometer(client)
|
||||||
|
hydros = hydrometer.get_hydrometer("")
|
||||||
|
|
||||||
|
assert hydros is not None
|
||||||
|
|
||||||
|
@responses.activate
|
||||||
|
def test_get_hydrometer_500(client):
|
||||||
|
responses.post("https://id.rapt.io/connect/token", json=json_reader("./tests/json/token_response.json"))
|
||||||
|
responses.add(
|
||||||
|
responses.GET,
|
||||||
|
"https://api.rapt.io/api/hydrometers/gethydrometer",
|
||||||
|
status=500,
|
||||||
|
)
|
||||||
|
hydrometer = Hydrometer(client)
|
||||||
|
hydros = hydrometer.get_hydrometer("")
|
||||||
|
|
||||||
|
assert hydros is None
|
||||||
|
|
||||||
|
|
||||||
|
@responses.activate
|
||||||
|
def test_get_telemetry(client):
|
||||||
|
responses.post("https://id.rapt.io/connect/token", json=json_reader("./tests/json/token_response.json"))
|
||||||
|
responses.get("https://api.rapt.io/api/hydrometers/gettelemetry", json=json_reader("./tests/json/get_hydrometer_telemetry_response.json"))
|
||||||
|
hydrometer = Hydrometer(client)
|
||||||
|
telemetry = hydrometer.get_telemetry("", "", "", "")
|
||||||
|
|
||||||
|
assert telemetry is not None
|
||||||
|
|
||||||
|
@responses.activate
|
||||||
|
def test_get_telemetry_500(client):
|
||||||
|
responses.post("https://id.rapt.io/connect/token", json=json_reader("./tests/json/token_response.json"))
|
||||||
|
responses.add(
|
||||||
|
responses.GET,
|
||||||
|
"https://api.rapt.io/api/hydrometers/gettelemetry",
|
||||||
|
status=500,
|
||||||
|
)
|
||||||
|
hydrometer = Hydrometer(client)
|
||||||
|
telemetry = hydrometer.get_telemetry("", "", "", "")
|
||||||
|
|
||||||
|
assert telemetry is None
|
||||||
|
|
||||||
|
|
||||||
|
def json_reader(path):
|
||||||
|
with open(path) as f:
|
||||||
|
return json.load(f)
|
Loading…
x
Reference in New Issue
Block a user