Skip to content

Commit

Permalink
Add Room Media API Calls
Browse files Browse the repository at this point in the history
  • Loading branch information
kdkavanagh authored and nalin29 committed Feb 11, 2023
1 parent 065485f commit f224e95
Show file tree
Hide file tree
Showing 8 changed files with 178 additions and 48 deletions.
11 changes: 11 additions & 0 deletions pyControl4/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
class C4Entity:
def __init__(self, C4Director, item_id):
"""Creates a Control4 object.
Parameters:
`C4Director` - A `pyControl4.director.C4Director` object that corresponds to the Control4 Director that the device is connected to.
`item_id` - The Control4 item ID.
"""
self.director = C4Director
self.item_id = int(item_id)
14 changes: 2 additions & 12 deletions pyControl4/alarm.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,10 @@
"""Controls Control4 security panel and contact sensor (door, window, motion) devices.
"""
import json
from pyControl4 import C4Entity


class C4SecurityPanel:
def __init__(self, C4Director, item_id):
"""Creates a Control4 Security Panel object.
Parameters:
`C4Director` - A `pyControl4.director.C4Director` object that corresponds to the Control4 Director that the security panel is connected to.
`item_id` - The Control4 item ID of the security panel partition.
"""
self.director = C4Director
self.item_id = item_id

class C4SecurityPanel(C4Entity):
async def getArmState(self):
"""Returns the arm state of the security panel as "DISARMED", "ARMED_HOME", or "ARMED_AWAY"."""
disarmed = await self.director.getItemVariableValue(
Expand Down
18 changes: 6 additions & 12 deletions pyControl4/blind.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,19 @@
"""


class C4Blind:
def __init__(self, C4Director, item_id):
"""Creates a Control4 Blind object.
from pyControl4 import C4Entity

Parameters:
`C4Director` - A `pyControl4.director.C4Director` object that corresponds to the Control4 Director that the blind is connected to.
`item_id` - The Control4 item ID of the blind.
"""
self.director = C4Director
self.item_id = item_id

class C4Blind(C4Entity):
async def getBatteryLevel(self):
"""Returns the battery of a blind. We currently don't know the range or meaning."""
value = await self.director.getItemVariableValue(self.item_id, "Battery Level")
return int(value)

async def getClosing(self):
"""Returns an indication of whether the blind is moving in the closed direction as a boolean
(True=closing, False=opening). If the blind is stopped, reports the direction it last moved."""
(True=closing, False=opening). If the blind is stopped, reports the direction it last moved.
"""
value = await self.director.getItemVariableValue(self.item_id, "Closing")
return bool(value)

Expand Down Expand Up @@ -52,7 +45,8 @@ async def getOpen(self):

async def getOpening(self):
"""Returns an indication of whether the blind is moving in the open direction as a boolean
(True=opening, False=closing). If the blind is stopped, reports the direction it last moved."""
(True=opening, False=closing). If the blind is stopped, reports the direction it last moved.
"""
value = await self.director.getItemVariableValue(self.item_id, "Opening")
return bool(value)

Expand Down
15 changes: 13 additions & 2 deletions pyControl4/director.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,12 @@ async def getItemVariableValue(self, item_id, var_name):
Parameters:
`item_id` - The Control4 item ID.
`var_name` - The Control4 variable name.
`var_name` - The Control4 variable name or names.
"""

if isinstance(var_name, (tuple, list, set)):
var_name = ",".join(var_name)

data = await self.sendGetRequest(
"/api/v1/items/{}/variables?varnames={}".format(item_id, var_name)
)
Expand All @@ -171,8 +175,11 @@ async def getAllItemVariableValue(self, var_name):
for all items that have it.
Parameters:
`var_name` - The Control4 variable name.
`var_name` - The Control4 variable name or names.
"""
if isinstance(var_name, (tuple, list, set)):
var_name = ",".join(var_name)

data = await self.sendGetRequest(
"/api/v1/items/variables?varnames={}".format(var_name)
)
Expand Down Expand Up @@ -209,3 +216,7 @@ async def getItemBindings(self, item_id):
`item_id` - The Control4 item ID.
"""
return await self.sendGetRequest("/api/v1/items/{}/bindings".format(item_id))

async def getUiConfiguration(self):
"""Get the JSON Control4 App UI Configuration enumerating rooms and capabilities"""
return await self.sendGetRequest("/api/v1/agents/ui_configuration")
12 changes: 2 additions & 10 deletions pyControl4/light.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,10 @@
"""


class C4Light:
def __init__(self, C4Director, item_id):
"""Creates a Control4 Light object.
from pyControl4 import C4Entity

Parameters:
`C4Director` - A `pyControl4.director.C4Director` object that corresponds to the Control4 Director that the light is connected to.
`item_id` - The Control4 item ID of the light.
"""
self.director = C4Director
self.item_id = item_id

class C4Light(C4Entity):
async def getLevel(self):
"""Returns the level of a dimming-capable light as an int 0-100.
Will cause an error if called on a non-dimmer switch. Use `getState()` instead.
Expand Down
13 changes: 2 additions & 11 deletions pyControl4/relay.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,10 @@
"""


class C4Relay:
def __init__(self, C4Director, item_id):
"""Creates a Control4 Relay object.
from pyControl4 import C4Entity

Parameters:
`C4Director` - A `pyControl4.director.C4Director` object that
corresponds to the Control4 Director that the Relay is connected to.
`item_id` - The Control4 item ID of the Relay.
"""
self.director = C4Director
self.item_id = item_id

class C4Relay(C4Entity):
async def getRelayState(self):
"""Returns the current state of the relay.
Expand Down
140 changes: 140 additions & 0 deletions pyControl4/room.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
"""Controls Control4 Room devices.
"""


from pyControl4 import C4Entity


class C4Room(C4Entity):
"""
A media-oriented view of a Control4 Room, supporting items of type="room"
"""

async def isRoomHidden(self) -> bool:
"""Returns True if the room is hidden from the end-user"""
value = await self.director.getItemVariableValue(self.item_id, "ROOM_HIDDEN")
return int(value) != 0

async def isOn(self) -> bool:
"""Returns True/False if the room is "ON" from the director's perspective"""
value = await self.director.getItemVariableValue(self.item_id, "POWER_STATE")
return int(value) != 0

async def setRoomOff(self):
"""Turn the room "OFF" """
await self.director.sendPostRequest(
"/api/v1/items/{}/commands".format(self.item_id),
"ROOM_OFF",
{},
)

async def _setSource(self, source_id: int, audio_only: bool):
"""
Sets the room source, turning on the room if necessary.
If audio_only, only the current audio device is changed
"""
await self.director.sendPostRequest(
f"/api/v1/items/{self.item_id}/commands",
"SELECT_AUDIO_DEVICE" if audio_only else "SELECT_VIDEO_DEVICE",
{"deviceid": source_id},
)

async def setAudioSource(self, source_id: int):
"""Sets the current audio source for the room"""
await self._setSource(source_id, audio_only=True)

async def setVideoAndAudioSource(self, source_id: int):
"""Sets the current audio and video source for the room"""
await self._setSource(source_id, audio_only=False)

async def getVolume(self) -> int:
"""Returns the current volume for the room from 0-100"""
value = await self.director.getItemVariableValue(self.item_id, "CURRENT_VOLUME")
return int(value)

async def isMuted(self) -> bool:
"""Returns True if the room is muted"""
value = await self.director.getItemVariableValue(self.item_id, "IS_MUTED")
return int(value) != 0

async def setMute(self, muted: bool):
"""Mute/Unmute the room"""
await self.director.sendPostRequest(
"/api/v1/items/{}/commands".format(self.item_id),
"MUTE_ON" if muted else "MUTE_OFF",
{},
)

async def toggleMute(self):
"""Toggle the current mute state for the room"""
await self.director.sendPostRequest(
"/api/v1/items/{}/commands".format(self.item_id),
"MUTE_TOGGLE",
{},
)

async def setVolume(self, volume: int):
"""Set the room volume, 0-100"""
await self.director.sendPostRequest(
"/api/v1/items/{}/commands".format(self.item_id),
"SET_VOLUME_LEVEL",
{"LEVEL": volume},
)

async def setIncrementOrDecrementVolume(self, increase: bool):
"""Increase/Decrease volume by 1"""
await self.director.sendPostRequest(
"/api/v1/items/{}/commands".format(self.item_id),
"PULSE_VOL_UP" if increase else "PULSE_VOL_DOWN",
{},
)

async def setPlay(self):
await self.director.sendPostRequest(
"/api/v1/items/{}/commands".format(self.item_id),
"PLAY",
{},
)

async def setPause(self):
await self.director.sendPostRequest(
"/api/v1/items/{}/commands".format(self.item_id),
"PAUSE",
{},
)

async def setStop(self):
"""Stops the currently playing media but does not turn off the room"""
await self.director.sendPostRequest(
"/api/v1/items/{}/commands".format(self.item_id),
"STOP",
{},
)

async def getAudioDevices(self):
"""
Get the audio devices located in the room.
Note that this is literally the devices in the room,
not necessarily all devices _playable_ in the room.
See C4Director.getUiConfiguration for a more accurate list
"""
await self.director.sendGetRequest(
"/api/v1/locations/rooms/{}/audio_devices".format(self.item_id)
)

async def getVideoDevices(self):
"""
Get the video devices located in the room.
Note that this is literally the devices in the room,
not necessarily all devices _playable_ in the room.
See C4Director.getUiConfiguration for a more accurate list
"""
await self.director.sendGetRequest(
"/api/v1/locations/rooms/{}/video_devices".format(self.item_id)
)
3 changes: 2 additions & 1 deletion pyControl4/websocket.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,8 @@ def __init__(
def item_callbacks(self):
"""Returns a dictionary of registered item ids (key) and their callbacks (value).
item_callbacks cannot be modified directly. Use add_item_callback() and remove_item_callback() instead."""
item_callbacks cannot be modified directly. Use add_item_callback() and remove_item_callback() instead.
"""
return self._item_callbacks

def add_item_callback(self, item_id, callback):
Expand Down

0 comments on commit f224e95

Please sign in to comment.