-
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.
Refactor into submodules, to selectively expose the API related functions rather than everything including utils functions. We now have: ``` edilkamin/ ├── api.py ├── constants.py ├── __init__.py ├── __main__.py └── utils.py ``` Document API functions with docstring and updated a few function def to return API response string rather than entire response object.
- Loading branch information
1 parent
62a0268
commit aa79531
Showing
6 changed files
with
139 additions
and
106 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,76 +1,16 @@ | ||
#!/usr/bin/env python | ||
import os | ||
import typing | ||
|
||
import requests | ||
from pycognito import Cognito | ||
|
||
from edilkamin import constants | ||
|
||
|
||
def sign_in(username, password): | ||
cognito = Cognito(constants.USER_POOL_ID, constants.CLIENT_ID, username=username) | ||
cognito.authenticate(password) | ||
user = cognito.get_user() | ||
return user._metadata["access_token"] | ||
|
||
|
||
def get_endpoint(url: str) -> str: | ||
return constants.BACKEND_URL + url | ||
|
||
|
||
def get_headers(token: str): | ||
return {"Authorization": f"Bearer {token}"} | ||
|
||
|
||
def device_info(token: str, mac: str): | ||
"""Retrieve device info for a given MAC address in the format `aabbccddeeff`.""" | ||
headers = get_headers(token) | ||
url = get_endpoint(f"device/{mac}/info") | ||
response = requests.get(url, headers=headers) | ||
response.raise_for_status() | ||
return response.json() | ||
|
||
|
||
def mqtt_command( | ||
token: str, mac_address: str, payload: typing.Dict | ||
) -> requests.models.Response: | ||
headers = get_headers(token) | ||
url = get_endpoint("mqtt/command") | ||
data = {"mac_address": mac_address, **payload} | ||
response = requests.put(url, json=data, headers=headers) | ||
response.raise_for_status() | ||
return response | ||
|
||
|
||
def set_power(token: str, mac_address: str, value: int) -> requests.models.Response: | ||
return mqtt_command(token, mac_address, {"name": "power", "value": value}) | ||
|
||
|
||
def set_power_on(token: str, mac_address: str): | ||
return set_power(token, mac_address, 1) | ||
|
||
|
||
def set_power_off(token: str, mac_address: str): | ||
return set_power(token, mac_address, 0) | ||
|
||
|
||
def assert_env(name: str) -> str: | ||
env = os.environ.get(name) | ||
assert env | ||
return env | ||
|
||
|
||
def main(): | ||
username = assert_env("USERNAME") | ||
password = assert_env("PASSWORD") | ||
mac_address = assert_env("MAC_ADDRESS") | ||
token = sign_in(username, password) | ||
info = device_info(token, mac_address) | ||
print(info) | ||
result = set_power_off(token, mac_address) | ||
print(result) | ||
|
||
|
||
if __name__ == "__main__": | ||
main() | ||
__all__ = [ | ||
"sign_in", | ||
"device_info", | ||
"mqtt_command", | ||
"set_power", | ||
"set_power_on", | ||
"set_power_off", | ||
] | ||
from edilkamin.api import ( | ||
device_info, | ||
mqtt_command, | ||
set_power, | ||
set_power_off, | ||
set_power_on, | ||
sign_in, | ||
) |
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,18 @@ | ||
#!/usr/bin/env python | ||
from edilkamin.api import device_info, set_power_off, sign_in | ||
from edilkamin.utils import assert_env | ||
|
||
|
||
def main(): | ||
username = assert_env("USERNAME") | ||
password = assert_env("PASSWORD") | ||
mac_address = assert_env("MAC_ADDRESS") | ||
token = sign_in(username, password) | ||
info = device_info(token, mac_address) | ||
print(info) | ||
result = set_power_off(token, mac_address) | ||
print(result) | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
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,55 @@ | ||
import typing | ||
|
||
import requests | ||
from pycognito import Cognito | ||
|
||
from edilkamin import constants | ||
from edilkamin.utils import get_endpoint, get_headers | ||
|
||
|
||
def sign_in(username: str, password: str) -> str: | ||
"""Sign in and return token.""" | ||
cognito = Cognito(constants.USER_POOL_ID, constants.CLIENT_ID, username=username) | ||
cognito.authenticate(password) | ||
user = cognito.get_user() | ||
return user._metadata["access_token"] | ||
|
||
|
||
def device_info(token: str, mac: str) -> typing.Dict: | ||
"""Retrieve device info for a given MAC address in the format `aabbccddeeff`.""" | ||
headers = get_headers(token) | ||
url = get_endpoint(f"device/{mac}/info") | ||
response = requests.get(url, headers=headers) | ||
response.raise_for_status() | ||
return response.json() | ||
|
||
|
||
def mqtt_command(token: str, mac_address: str, payload: typing.Dict) -> str: | ||
""" | ||
Send a MQTT command to the device identified with the MAC address. | ||
Return the response string. | ||
""" | ||
headers = get_headers(token) | ||
url = get_endpoint("mqtt/command") | ||
data = {"mac_address": mac_address, **payload} | ||
response = requests.put(url, json=data, headers=headers) | ||
response.raise_for_status() | ||
return response.json() | ||
|
||
|
||
def set_power(token: str, mac_address: str, value: int) -> str: | ||
""" | ||
Set device power on (1) or off (0). | ||
Return response string e.g. | ||
- "Value is already 0" | ||
- "Command 0123456789abcdef executed successfully" | ||
""" | ||
return mqtt_command(token, mac_address, {"name": "power", "value": value}) | ||
|
||
|
||
def set_power_on(token: str, mac_address: str) -> str: | ||
return set_power(token, mac_address, 1) | ||
|
||
|
||
def set_power_off(token: str, mac_address: str) -> str: | ||
return set_power(token, mac_address, 0) |
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,17 @@ | ||
import os | ||
|
||
from edilkamin import constants | ||
|
||
|
||
def get_endpoint(url: str) -> str: | ||
return constants.BACKEND_URL + url | ||
|
||
|
||
def get_headers(token: str): | ||
return {"Authorization": f"Bearer {token}"} | ||
|
||
|
||
def assert_env(name: str) -> str: | ||
env = os.environ.get(name) | ||
assert env | ||
return env |
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,21 @@ | ||
from unittest import mock | ||
|
||
from test_api import patch_cognito, patch_requests_get, patch_requests_put | ||
|
||
from edilkamin import __main__ | ||
|
||
|
||
def test_main(): | ||
access_token = "token" | ||
env = { | ||
"USERNAME": "username", | ||
"PASSWORD": "password", | ||
"MAC_ADDRESS": "mac_address", | ||
} | ||
with mock.patch.dict("os.environ", env), patch_cognito( | ||
access_token | ||
) as m_cognito, patch_requests_get() as m_get, patch_requests_put() as m_put: | ||
assert __main__.main() is None | ||
assert m_cognito.called is True | ||
assert m_get.called is True | ||
assert m_put.called is True |