-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #23 from cern-vc/develop
Add support for Zoom Rooms
- Loading branch information
Showing
12 changed files
with
344 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import logging | ||
|
||
from zoom_python_client.client_components.rooms.rooms_component import ( | ||
RoomsListDict, | ||
RoomType, | ||
) | ||
from zoom_python_client.utils.logger import setup_logs | ||
from zoom_python_client.zoom_api_client import ZoomApiClient | ||
|
||
logger = setup_logs(log_level=logging.DEBUG) | ||
|
||
zoom_client = ZoomApiClient.init_from_dotenv(use_path=".") | ||
|
||
parameters = RoomsListDict( | ||
type=RoomType.ZOOM_ROOM, | ||
) | ||
|
||
result = zoom_client.rooms.get_rooms(parameters) | ||
|
||
logger.info("Found %d rooms:", len(result["rooms"])) | ||
|
||
for room in result["rooms"]: | ||
print("\t- %s - %s - %s", room["name"], room["room_id"], room["status"]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import datetime | ||
import logging | ||
import os | ||
import sys | ||
|
||
import pytz | ||
|
||
from zoom_python_client.client_components.rooms.rooms_component import ( | ||
RoomsSensorDataDict, | ||
) | ||
from zoom_python_client.utils.logger import setup_logs | ||
from zoom_python_client.zoom_api_client import ZoomApiClient | ||
|
||
logger = setup_logs(log_level=logging.DEBUG) | ||
|
||
zoom_client = ZoomApiClient.init_from_dotenv(use_path=".") | ||
|
||
ROOM_ID = os.getenv("ROOM_ID") | ||
|
||
if ROOM_ID is None: | ||
logger.error("ROOM_ID not found in environment variables") | ||
sys.exit(1) | ||
|
||
|
||
all_sensor_data = [] | ||
|
||
from_date = (datetime.datetime.now() - datetime.timedelta(hours=12)).isoformat( | ||
timespec="seconds" | ||
) + "Z" | ||
to_date = datetime.datetime.now().isoformat(timespec="seconds") + "Z" | ||
|
||
room_params = RoomsSensorDataDict( | ||
from_date=from_date, | ||
to_date=to_date, | ||
) | ||
|
||
while True: | ||
result = zoom_client.rooms.get_room_sensor_data(ROOM_ID, data=room_params) | ||
all_sensor_data.extend(result["sensor_data"]) | ||
if not result["next_page_token"]: | ||
break | ||
room_params["next_page_token"] = result["next_page_token"] | ||
|
||
logger.info("Found %d sensor data points:", len(all_sensor_data)) | ||
|
||
for data in all_sensor_data: | ||
date = datetime.datetime.strptime( | ||
data["date_time"], "%Y-%m-%dT%H:%M:%SZ" | ||
).astimezone(pytz.timezone("Europe/Zurich")) | ||
logger.info("\t-%s - %d", date, data["sensor_value"]) |
Empty file.
83 changes: 83 additions & 0 deletions
83
tests/zoom_python_client/client_components/rooms/test_rooms_component.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
import pytest | ||
import responses | ||
|
||
from tests.zoom_python_client.base_test_case import TestCaseWithAuth | ||
from zoom_python_client.client_components.rooms.rooms_component import ( | ||
RoomsComponent, | ||
RoomsSensorDataDict, | ||
) | ||
from zoom_python_client.zoom_api_client import ZoomApiClient | ||
|
||
|
||
class TestRoomsComponent(TestCaseWithAuth): | ||
def setUp(self): | ||
super().setUp() | ||
zoom_client = ZoomApiClient("aaa", "bbb", "ccc", "http://localhost") | ||
self.rooms_component = RoomsComponent(zoom_client) | ||
|
||
@responses.activate | ||
def test_get_rooms(self): | ||
responses.add( | ||
responses.GET, | ||
"http://localhost/rooms", | ||
json={"response": "ok"}, | ||
status=200, | ||
) | ||
rooms = self.rooms_component.get_rooms({}) | ||
assert rooms == {"response": "ok"} | ||
|
||
@responses.activate | ||
def test_get_room(self): | ||
responses.add( | ||
responses.GET, | ||
"http://localhost/rooms/12345", | ||
json={"response": "ok"}, | ||
status=200, | ||
) | ||
room = self.rooms_component.get_room("12345") | ||
assert room == {"response": "ok"} | ||
|
||
@responses.activate | ||
def test_get_room_sensor_data_0(self): | ||
responses.add( | ||
responses.GET, | ||
"http://localhost/rooms/12345/sensor_data", | ||
json={"response": "ok"}, | ||
status=200, | ||
) | ||
parameters = RoomsSensorDataDict( | ||
from_date="2020-01-01", | ||
to_date="2023-07-10T08:27:46Z", | ||
) | ||
with pytest.raises(ValueError): | ||
self.rooms_component.get_room_sensor_data("12345", parameters) | ||
|
||
@responses.activate | ||
def test_get_room_sensor_data_1(self): | ||
responses.add( | ||
responses.GET, | ||
"http://localhost/rooms/12345/sensor_data", | ||
json={"response": "ok"}, | ||
status=200, | ||
) | ||
parameters = RoomsSensorDataDict( | ||
from_date="2023-07-10T08:27:46Z", | ||
to_date="2020-01-01", | ||
) | ||
with pytest.raises(ValueError): | ||
self.rooms_component.get_room_sensor_data("12345", parameters) | ||
|
||
@responses.activate | ||
def test_get_room_sensor_data_2(self): | ||
responses.add( | ||
responses.GET, | ||
"http://localhost/rooms/12345/sensor_data", | ||
json={"response": "ok"}, | ||
status=200, | ||
) | ||
parameters = RoomsSensorDataDict( | ||
from_date="2023-07-10T08:27:46Z", | ||
to_date="2023-07-10T10:27:46Z", | ||
) | ||
result = self.rooms_component.get_room_sensor_data("12345", parameters) | ||
assert result == {"response": "ok"} |
30 changes: 30 additions & 0 deletions
30
tests/zoom_python_client/utils/test_typed_dict_parameters.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
from typing_extensions import NotRequired, TypedDict | ||
|
||
from zoom_python_client.utils.typed_dict_parameters import generate_parameters_dict | ||
|
||
|
||
class _TestListDict(TypedDict): | ||
type: NotRequired[str] | ||
page_size: NotRequired[int] | ||
next_page_token: NotRequired[str] | ||
page_number: NotRequired[int] | ||
from_date: NotRequired[str] | ||
to_date: NotRequired[str] | ||
|
||
|
||
def test_generate_params_dict(): | ||
data = _TestListDict(type="test", page_number=1, page_size=10) | ||
parameters = generate_parameters_dict(data) | ||
assert parameters == {"type": "test", "page_size": 10, "page_number": 1} | ||
|
||
|
||
def test_generate_params_dict_with_to_date(): | ||
data = _TestListDict(to_date="2021-01-01T00:00:00Z") | ||
parameters = generate_parameters_dict(data) | ||
assert parameters == {"to": "2021-01-01T00:00:00Z"} | ||
|
||
|
||
def test_generate_params_dict_with_from_date(): | ||
data = _TestListDict(from_date="2021-01-01T00:00:00Z") | ||
parameters = generate_parameters_dict(data) | ||
assert parameters == {"from": "2021-01-01T00:00:00Z"} |
Empty file.
100 changes: 100 additions & 0 deletions
100
zoom_python_client/client_components/rooms/rooms_component.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
import re | ||
from enum import Enum | ||
|
||
from typing_extensions import NotRequired, TypedDict | ||
|
||
from zoom_python_client.utils.typed_dict_parameters import generate_parameters_dict | ||
from zoom_python_client.zoom_client_interface import ZoomClientInterface | ||
|
||
|
||
class RoomStatus(Enum): | ||
OFFLINE = "Offline" | ||
AVAILABLE = "Available" | ||
IN_MEETING = "InMeeting" | ||
UNDER_CONSTRUCTION = "UnderConstruction" | ||
|
||
|
||
class RoomType(Enum): | ||
KIOSK = "Kiosk" | ||
ZOOM_ROOM = "ZoomRoom" | ||
STANDALONE_WHITEBOARD = "StandaloneWhiteboard" | ||
SCHEDULING_DISPLAY_ONLY = "SchedulingDisplayOnly" | ||
DIGITAL_SIGNAGE_ONLY = "DigitalSignageOnly" | ||
|
||
|
||
class NewPageToken(TypedDict): | ||
"""The parameters for queries that return paginated results. | ||
Args: | ||
next_page_token (str): The token for the next page of results. | ||
page_size (int): The number of records returned with a single API call. | ||
""" | ||
|
||
next_page_token: NotRequired[str] | ||
page_size: NotRequired[int] | ||
|
||
|
||
class RoomsListDict(NewPageToken): | ||
"""The parameters for the get_rooms method. | ||
Args: | ||
status (Status): The status of the room. | ||
type (Type): The type of the room. | ||
unassigned_rooms (bool): Whether or not to include unassigned rooms. | ||
location_id (str): The location ID of the room. | ||
query_name (str): The name of the room. | ||
""" | ||
|
||
status: NotRequired[RoomStatus] | ||
type: NotRequired[RoomType] | ||
unassigned_rooms: NotRequired[bool] | ||
location_id: NotRequired[str] | ||
query_name: NotRequired[str] | ||
|
||
|
||
class RoomsSensorDataDict(NewPageToken): | ||
"""The parameters for the get_sensor_data method. | ||
Args: | ||
from_date (str): The start date and time for the query, should be in yyyy-MM-ddTHH:dd:ssZ format | ||
to_date (str): The end date and time for the query, should be in yyyy-MM-ddTHH:dd:ssZ format | ||
""" | ||
|
||
from_date: str | ||
to_date: str | ||
|
||
|
||
class RoomsComponent: | ||
def __init__(self, client: ZoomClientInterface) -> None: | ||
self.client = client | ||
|
||
def get_rooms(self, data: RoomsListDict) -> dict: | ||
api_path = "/rooms" | ||
parameters = generate_parameters_dict(data) | ||
|
||
response = self.client.make_get_request(api_path, parameters=parameters) | ||
result = response.json() | ||
return result | ||
|
||
def get_room(self, room_id: str) -> dict: | ||
api_path = f"/rooms/{room_id}" | ||
|
||
response = self.client.make_get_request(api_path) | ||
result = response.json() | ||
return result | ||
|
||
def get_room_sensor_data(self, room_id: str, data: RoomsSensorDataDict) -> dict: | ||
api_path = f"/rooms/{room_id}/sensor_data" | ||
|
||
# Validate the date format | ||
regex = r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$" # yyyy-MM-ddTHH:dd:ssZ | ||
if not ( | ||
re.match(regex, data["from_date"]) and re.match(regex, data["to_date"]) | ||
): | ||
raise ValueError("The date format should be in yyyy-MM-ddTHH:dd:ssZ format") | ||
|
||
parameters = generate_parameters_dict(data) | ||
|
||
response = self.client.make_get_request(api_path, parameters=parameters) | ||
result = response.json() | ||
return result |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,5 @@ | ||
import os | ||
from pathlib import Path | ||
|
||
|
||
def get_project_dir(): | ||
current_dir = os.path.abspath(os.path.dirname(__file__)) | ||
path = Path(current_dir) | ||
project_dir = path.parent.absolute().parent | ||
return project_dir | ||
return Path(__file__).resolve().parents[2] |
Oops, something went wrong.