### Install pyowletapi Source: https://github.com/ryanbdclark/pyowletapi/blob/main/README.md Use pip to install the library. ```bash pip install pyowletapi ``` -------------------------------- ### Complete Monitoring Loop with Pyowletapi Source: https://context7.com/ryanbdclark/pyowletapi/llms.txt This example demonstrates a complete monitoring application that authenticates, retrieves devices, and continuously polls for updated vitals data while properly managing tokens and handling errors. Load credentials from a JSON file and run the asynchronous monitoring loop. ```python import asyncio import json from pyowletapi.api import OwletAPI from pyowletapi.sock import Sock from pyowletapi.exceptions import OwletError, OwletCredentialsError async def monitoring_loop(): # Load credentials from config file with open("login.json") as f: config = json.load(f) api = OwletAPI( region=config["region"], # "europe" or "world" user=config["username"], password=config["password"] ) stored_tokens = None try: # Initial authentication tokens = await api.authenticate() if tokens: stored_tokens = tokens print("Authentication successful, tokens stored") # Get all devices devices_response = await api.get_devices(versions=[2, 3]) # Create Sock objects socks = { device["device"]["dsn"]: Sock(api, device["device"]) for device in devices_response["response"] } print(f"Found {len(socks)} device(s)") # Monitoring loop while True: for dsn, sock in socks.items(): try: result = await sock.update_properties() props = result["properties"] print(f"\n[{sock.name}] ({dsn})") print(f" Heart Rate: {props.get('heart_rate', 'N/A')} BPM") print(f" Oxygen: {props.get('oxygen_saturation', 'N/A')}%") print(f" Battery: {props.get('battery_percentage', 'N/A')}%") print(f" Updated: {props.get('last_updated', 'N/A')}") # Check for alerts if props.get('low_oxygen_alert'): print(" WARNING: Low oxygen alert!") if props.get('low_heart_rate_alert'): print(" WARNING: Low heart rate alert!") if props.get('high_heart_rate_alert'): print(" WARNING: High heart rate alert!") if props.get('sock_off'): print(" INFO: Sock is off") # Handle token refresh if "tokens" in result: stored_tokens = result["tokens"] print(" Tokens refreshed and stored") except OwletError as e: print(f" Error updating {dsn}: {e}") # Poll every 30 seconds await asyncio.sleep(30) except OwletCredentialsError as e: print(f"Invalid credentials: {e}") except KeyboardInterrupt: print("\nMonitoring stopped") finally: await api.close() print("Session closed") # Run the monitoring loop if __name__ == "__main__": asyncio.run(monitoring_loop()) ``` -------------------------------- ### GET /api/devices Source: https://context7.com/ryanbdclark/pyowletapi/llms.txt Retrieves all Owlet sock devices associated with the authenticated account. It returns device metadata including serial number (DSN), model, firmware version, MAC address, and connection status. You can filter by sock version (2 or 3). ```APIDOC ## GET /api/devices ### Description Retrieves all Owlet sock devices associated with the authenticated account. It returns device metadata including serial number (DSN), model, firmware version, MAC address, and connection status. You can filter by sock version (2 or 3). ### Method GET ### Endpoint /api/devices ### Query Parameters - **versions** (array[int]) - Optional - Filter devices by sock version (e.g., [2, 3] for Sock 2 and Sock 3, or [3] for only Sock 3). ### Response #### Success Response (200) - **response** (object) - Contains a list of device wrappers. - **device** (object) - Device metadata. - **dsn** (string) - Device serial number. - **model** (string) - Device model. - **sw_version** (string) - Firmware version. - **mac** (string) - MAC address. - **connection_status** (string) - Connection status. - **lan_ip** (string) - LAN IP address. - **product_name** (string) - Product name. - **tokens** (object) - Optional - New authentication tokens if they were refreshed. #### Response Example { "response": [ { "device": { "product_name": "Owlet Sock", "dsn": "ABCDEF123456", "model": "sock_3", "sw_version": "3.2.1", "mac": "AA:BB:CC:DD:EE:FF", "connection_status": "connected", "lan_ip": "192.168.1.100" } } ], "tokens": { "access_token": "new_access_token", "refresh_token": "new_refresh_token" } } #### Error Response (400) - **error** (string) - Description of the error, e.g., "No devices found." ``` -------------------------------- ### Get Properties for a Specific Owlet Device Source: https://context7.com/ryanbdclark/pyowletapi/llms.txt Retrieves all current properties for a specific device using its serial number (DSN). This method automatically activates the device before fetching data. It provides access to vitals, alerts, battery, and status information, varying by sock version. ```python import asyncio from pyowletapi.api import OwletAPI async def get_properties_example(): api = OwletAPI("europe", "user@example.com", "password123") try: await api.authenticate() devices = await api.get_devices() # Get the first device's serial number dsn = devices["response"][0]["device"]["dsn"] # Fetch properties for this device properties_response = await api.get_properties(dsn) # Access the raw properties dictionary properties = properties_response["response"] # Example properties available (varies by sock version) if "REAL_TIME_VITALS" in properties: print("Sock 3 detected") vitals = properties["REAL_TIME_VITALS"]["value"] print(f"Real-time vitals JSON: {vitals}") if "HEART_RATE" in properties: print("Sock 2 detected") print(f"Heart Rate: {properties['HEART_RATE']['value']}") print(f"Oxygen Level: {properties['OXYGEN_LEVEL']['value']}") # Common properties if "LOW_BATT_ALRT" in properties: print(f"Low Battery Alert: {properties['LOW_BATT_ALRT']['value']}") if "SOCK_OFF" in properties: print(f"Sock Off: {properties['SOCK_OFF']['value']}") finally: await api.close() asyncio.run(get_properties_example()) ``` -------------------------------- ### Initialize OwletAPI Source: https://github.com/ryanbdclark/pyowletapi/blob/main/README.md Create an instance of OwletAPI with region, username, and password credentials. ```python api = OwletAPI('europe', username, password) ``` -------------------------------- ### Authenticate and create Sock objects Source: https://github.com/ryanbdclark/pyowletapi/blob/main/README.md Authenticate with the server and initialize a collection of Sock objects for connected devices. ```python await api.authenticate() socks = {device['device']['dsn']: Sock(api, device['device']) for device in devices} ``` -------------------------------- ### Initialize OwletAPI Connection Source: https://context7.com/ryanbdclark/pyowletapi/llms.txt Initialize the OwletAPI class with credentials or existing tokens. Supports custom aiohttp sessions. Use 'world' or 'europe' for the region. ```python import asyncio from pyowletapi.api import OwletAPI from pyowletapi.exceptions import OwletAuthenticationError, OwletCredentialsError async def initialize_api(): # Initialize with username and password api = OwletAPI( region="europe", # or "world" user="your_email@example.com", password="your_password" ) # Alternatively, initialize with existing tokens (for reconnection) api_with_tokens = OwletAPI( region="world", token="existing_auth_token", expiry=1699999999.0, refresh="existing_refresh_token" ) # Or use a custom aiohttp session import aiohttp custom_session = aiohttp.ClientSession() api_custom = OwletAPI( region="europe", user="your_email@example.com", password="your_password", session=custom_session ) return api # Run the async function api = asyncio.run(initialize_api()) ``` -------------------------------- ### Import API and Sock objects Source: https://github.com/ryanbdclark/pyowletapi/blob/main/README.md Import the necessary classes to begin interacting with the API. ```python from pyowletapi.api import OwletAPI from pyowlet.sock import Sock ``` -------------------------------- ### Fetch and Normalize Device Properties with Python Source: https://context7.com/ryanbdclark/pyowletapi/llms.txt Use update_properties to retrieve and parse current device data into a standardized format. Requires an authenticated OwletAPI instance and a valid Sock object. ```python import asyncio from pyowletapi.api import OwletAPI from pyowletapi.sock import Sock async def update_properties_example(): api = OwletAPI("world", "user@example.com", "password123") try: await api.authenticate() devices = await api.get_devices() # Create a Sock object device_data = devices["response"][0]["device"] sock = Sock(api, device_data) # Update and get properties result = await sock.update_properties() # Access normalized properties props = result["properties"] print(f"Heart Rate: {props.get('heart_rate')} BPM") print(f"Oxygen Saturation: {props.get('oxygen_saturation')}%") print(f"Battery: {props.get('battery_percentage')}%") print(f"Battery Minutes: {props.get('battery_minutes')} min") print(f"Signal Strength: {props.get('signal_strength')}") print(f"Skin Temperature: {props.get('skin_temperature')}") print(f"Movement: {props.get('movement')}") print(f"Sleep State: {props.get('sleep_state')}") print(f"Charging: {props.get('charging')}") print(f"Base Station On: {props.get('base_station_on')}") print(f"Last Updated: {props.get('last_updated')}") # Alert states print(f"Low Battery Alert: {props.get('low_battery_alert')}") print(f"Low Oxygen Alert: {props.get('low_oxygen_alert')}") print(f"High Heart Rate Alert: {props.get('high_heart_rate_alert')}") print(f"Low Heart Rate Alert: {props.get('low_heart_rate_alert')}") print(f"Sock Disconnected: {props.get('sock_disconnected')}") print(f"Sock Off: {props.get('sock_off')}") # Check sock version print(f"Sock Version: {sock.version}") # 2 or 3 print(f"Revision: {sock.revision}") # Sock 3 only # Access raw properties if needed raw = result["raw_properties"] print(f"Raw property count: {len(raw)}") # Check for refreshed tokens if "tokens" in result: print(f"New tokens available: {result['tokens']}") finally: await api.close() asyncio.run(update_properties_example()) ``` -------------------------------- ### POST /post_command Source: https://context7.com/ryanbdclark/pyowletapi/llms.txt Sends control commands to an Owlet device, such as toggling the base station state. ```APIDOC ## POST /post_command ### Description The post_command method sends control commands to a device, such as turning the base station on or off. ### Parameters #### Request Body - **device** (string) - Required - The device serial number (dsn). - **command** (string) - Required - The command name to execute (e.g., "BASE_STATION_ON_CMD"). - **data** (object) - Required - A dictionary containing the command payload, including metadata and the value string. ### Request Example { "device": "DSN12345", "command": "BASE_STATION_ON_CMD", "data": { "datapoint": { "metadata": {}, "value": "{\"ts\": 1625000000, \"val\": \"true\"}" } } } ``` -------------------------------- ### Control Owlet Base Station Power State Source: https://context7.com/ryanbdclark/pyowletapi/llms.txt Use the control_base_station method to remotely toggle the base station power. Requires an authenticated OwletAPI instance and a valid device object. ```python import asyncio from pyowletapi.api import OwletAPI from pyowletapi.sock import Sock async def control_base_station_example(): api = OwletAPI("world", "user@example.com", "password123") try: await api.authenticate() devices = await api.get_devices() sock = Sock(api, devices["response"][0]["device"]) # Turn base station ON success = await sock.control_base_station(on=True) if success: print("Base station turned ON successfully") else: print("Failed to turn on base station") # Wait a moment await asyncio.sleep(2) # Turn base station OFF success = await sock.control_base_station(on=False) if success: print("Base station turned OFF successfully") else: print("Failed to turn off base station") finally: await api.close() asyncio.run(control_base_station_example()) ``` -------------------------------- ### Send Command to Owlet Device Source: https://context7.com/ryanbdclark/pyowletapi/llms.txt Use this method to send control commands like turning the base station on or off. Requires device serial number, command name, and a data dictionary. ```python import asyncio import json import time from pyowletapi.api import OwletAPI async def post_command_example(): api = OwletAPI("europe", "user@example.com", "password123") try: await api.authenticate() devices = await api.get_devices() dsn = devices["response"][0]["device"]["dsn"] # Example: Send a command to turn base station on command_value = json.dumps({ "ts": int(time.time()), "val": "true" # "true" to turn on, "false" to turn off }) data = { "datapoint": { "metadata": {}, "value": command_value } } response = await api.post_command( device=dsn, command="BASE_STATION_ON_CMD", data=data ) print(f"Command response: {response}") finally: await api.close() asyncio.run(post_command_example()) ``` -------------------------------- ### Handle Pyowletapi Exceptions Source: https://context7.com/ryanbdclark/pyowletapi/llms.txt Implement specific exception handling to manage network, authentication, and device-related errors gracefully. ```python import asyncio from pyowletapi.api import OwletAPI from pyowletapi.sock import Sock from pyowletapi.exceptions import ( OwletError, # Base exception for all Owlet errors OwletConnectionError, # Network/connection issues OwletAuthenticationError, # Auth flow failures OwletCredentialsError, # Invalid username/password OwletDevicesError # No devices found ) async def exception_handling_example(): api = OwletAPI("europe", "user@example.com", "password123") try: await api.authenticate() devices = await api.get_devices() sock = Sock(api, devices["response"][0]["device"]) await sock.update_properties() print(f"Heart rate: {sock.properties.get('heart_rate')}") except OwletCredentialsError as e: # Invalid username or password print(f"Login failed - check credentials: {e}") except OwletAuthenticationError as e: # Other auth issues (too many attempts, invalid region, etc.) print(f"Authentication error: {e}") except OwletDevicesError as e: # No compatible devices found on account print(f"No devices: {e}") except OwletConnectionError as e: # Network/API request failed print(f"Connection error: {e}") except OwletError as e: # Catch-all for other Owlet errors print(f"Owlet error: {e}") finally: await api.close() asyncio.run(exception_handling_example()) ``` -------------------------------- ### Retrieve Connected Owlet Sock Devices Source: https://context7.com/ryanbdclark/pyowletapi/llms.txt Fetches all Owlet sock devices associated with the authenticated account. Supports filtering by sock version (2 or 3). Handles potential OwletDevicesError if no devices are found. ```python import asyncio from pyowletapi.api import OwletAPI from pyowletapi.exceptions import OwletDevicesError async def get_devices_example(): api = OwletAPI("world", "user@example.com", "password123") try: await api.authenticate() # Get all devices (Sock 2 and Sock 3) devices_response = await api.get_devices(versions=[2, 3]) # Get only Sock 3 devices sock3_devices = await api.get_devices(versions=[3]) # Process the response for device_wrapper in devices_response["response"]: device = device_wrapper["device"] print(f"Product Name: {device['product_name']}") print(f"Serial (DSN): {device['dsn']}") print(f"Model: {device['model']}") print(f"Software Version: {device['sw_version']}") print(f"MAC Address: {device['mac']}") print(f"Connection Status: {device['connection_status']}") print(f"LAN IP: {device['lan_ip']}") print("---") # Check if tokens were refreshed if "tokens" in devices_response: new_tokens = devices_response["tokens"] print(f"Tokens refreshed: {new_tokens}") except OwletDevicesError as e: print(f"No devices found: {e}") finally: await api.close() asyncio.run(get_devices_example()) ``` -------------------------------- ### Activate Owlet Device for Data Retrieval Source: https://context7.com/ryanbdclark/pyowletapi/llms.txt Manually activates a specific Owlet device by setting APP_ACTIVE to 1. This is a prerequisite for retrieving current property data and is automatically called by `get_properties()`. Ensure authentication is completed before calling. ```python import asyncio from pyowletapi.api import OwletAPI async def activate_example(): api = OwletAPI("world", "user@example.com", "password123") try: await api.authenticate() devices = await api.get_devices() dsn = devices["response"][0]["device"]["dsn"] # Manually activate the device await api.activate(dsn) print(f"Device {dsn} activated successfully") # Now you can make subsequent API calls # Note: get_properties() calls activate() automatically finally: await api.close() asyncio.run(activate_example()) ``` -------------------------------- ### POST /api/activate Source: https://context7.com/ryanbdclark/pyowletapi/llms.txt Sets APP_ACTIVE to 1 on the Owlet API, which is required before the API will return current property data. This is called automatically by get_properties() but can be called directly if needed. ```APIDOC ## POST /api/activate ### Description Sets APP_ACTIVE to 1 on the Owlet API, which is required before the API will return current property data. This is called automatically by get_properties() but can be called directly if needed. ### Method POST ### Endpoint /api/activate ### Parameters #### Query Parameters - **dsn** (string) - Required - The serial number (DSN) of the device to activate. ### Request Body (This endpoint does not explicitly define a request body in the provided text, but typically requires authentication credentials or a device identifier if not passed as a query parameter.) ### Response #### Success Response (200) - **message** (string) - Confirmation message, e.g., "Device activated successfully." #### Response Example { "message": "Device ABCDEF123456 activated successfully" } #### Error Response (400) - **error** (string) - Description of the error, e.g., "Device not found or already active." ``` -------------------------------- ### Owlet Sock Class - Device Object Wrapper Source: https://context7.com/ryanbdclark/pyowletapi/llms.txt The Sock class wraps individual Owlet sock devices, parsing metadata and normalizing properties. It automatically detects Sock 2 or Sock 3 models. ```python import asyncio from pyowletapi.api import OwletAPI from pyowletapi.sock import Sock async def sock_class_example(): api = OwletAPI("europe", "user@example.com", "password123") try: await api.authenticate() devices_response = await api.get_devices() # Create Sock objects for each device socks = {} for device_wrapper in devices_response["response"]: device_data = device_wrapper["device"] dsn = device_data["dsn"] socks[dsn] = Sock(api, device_data) # Access device metadata for dsn, sock in socks.items(): print(f"Name: {sock.name}") print(f"Serial: {sock.serial}") print(f"Model: {sock.model}") print(f"OEM Model: {sock.oem_model}") print(f"Software Version: {sock.sw_version}") print(f"MAC Address: {sock.mac}") print(f"LAN IP: {sock.lan_ip}") print(f"Connection Status: {sock.connection_status}") print(f"Device Type: {sock.device_type}") print(f"Manufacturer Model: {sock.manuf_model}") print("---") finally: await api.close() asyncio.run(sock_class_example()) ``` -------------------------------- ### Sock.update_properties() Source: https://context7.com/ryanbdclark/pyowletapi/llms.txt Fetches current device properties from the API and normalizes them into a structured format. ```APIDOC ## Sock.update_properties() ### Description Fetches current properties from the API and normalizes them into a user-friendly format. It returns both raw API response and parsed properties with standardized keys. ### Response #### Success Response (200) - **properties** (dict) - Normalized device data including heart_rate, oxygen_saturation, battery_percentage, battery_minutes, signal_strength, skin_temperature, movement, sleep_state, charging, base_station_on, last_updated, and various alert states. - **raw_properties** (dict) - The raw API response data. - **tokens** (dict, optional) - New authentication tokens if refreshed. ``` -------------------------------- ### Retrieve Specific Property Values with Python Source: https://context7.com/ryanbdclark/pyowletapi/llms.txt Use get_property to access individual normalized values after calling update_properties. This method provides a convenient way to extract specific metrics from the device state. ```python import asyncio from pyowletapi.api import OwletAPI from pyowletapi.sock import Sock async def get_property_example(): api = OwletAPI("europe", "user@example.com", "password123") try: await api.authenticate() devices = await api.get_devices() sock = Sock(api, devices["response"][0]["device"]) # First update properties await sock.update_properties() # Get specific properties heart_rate = sock.get_property("heart_rate") oxygen = sock.get_property("oxygen_saturation") battery = sock.get_property("battery_percentage") charging = sock.get_property("charging") low_oxygen_alert = sock.get_property("low_oxygen_alert") print(f"Heart Rate: {heart_rate}") print(f"Oxygen: {oxygen}") print(f"Battery: {battery}") print(f"Charging: {charging}") print(f"Low Oxygen Alert: {low_oxygen_alert}") # Access via properties dict directly all_props = sock.properties print(f"All properties: {all_props}") finally: await api.close() asyncio.run(get_property_example()) ``` -------------------------------- ### Authenticate with Owlet Servers Source: https://context7.com/ryanbdclark/pyowletapi/llms.txt Handles the full authentication flow, including token generation and refresh. Catches specific Owlet errors for credentials and authentication failures. Ensure to close the API session in a finally block. ```python import asyncio from pyowletapi.api import OwletAPI from pyowletapi.exceptions import ( OwletAuthenticationError, OwletCredentialsError, OwletError ) async def authenticate_example(): api = OwletAPI("europe", "user@example.com", "password123") try: # Authenticate and get tokens tokens = await api.authenticate() if tokens: # New tokens were generated print(f"API Token: {tokens['api_token']}") print(f"Expiry: {tokens['expiry']}") print(f"Refresh Token: {tokens['refresh']}") # Store these tokens for future reconnection else: # Existing tokens were still valid print("Using existing valid tokens") # Access current tokens anytime via property current_tokens = api.tokens print(f"Current token: {current_tokens['api_token'][:20]}...") except OwletCredentialsError as e: print(f"Invalid login credentials: {e}") except OwletAuthenticationError as e: print(f"Authentication failed: {e}") finally: await api.close() asyncio.run(authenticate_example()) ``` -------------------------------- ### Sock Class - Device Metadata Source: https://context7.com/ryanbdclark/pyowletapi/llms.txt The Sock class provides a high-level wrapper to parse and access device metadata and vitals for Sock 2 and Sock 3 devices. ```APIDOC ## Sock Class ### Description The Sock class provides a high-level wrapper around individual Owlet sock devices. It parses device metadata, normalizes properties, and provides access to vitals data. ### Properties - **name** (string) - Device name - **serial** (string) - Device serial number - **model** (string) - Device model - **oem_model** (string) - OEM model identifier - **sw_version** (string) - Software version - **mac** (string) - MAC address - **lan_ip** (string) - LAN IP address - **connection_status** (string) - Current connection status - **device_type** (string) - Type of device (e.g., Sock 2 or Sock 3) - **manuf_model** (string) - Manufacturer model ``` -------------------------------- ### POST /api/properties Source: https://context7.com/ryanbdclark/pyowletapi/llms.txt Retrieves all current properties for a specific device by its serial number (DSN). This includes vitals data, alert states, battery information, and device status. It automatically activates the device before fetching properties. ```APIDOC ## POST /api/properties ### Description Retrieves all current properties for a specific device by its serial number (DSN). This includes vitals data, alert states, battery information, and device status. It automatically activates the device before fetching properties. ### Method POST ### Endpoint /api/properties ### Parameters #### Query Parameters - **dsn** (string) - Required - The serial number (DSN) of the device. ### Request Body (This endpoint does not explicitly define a request body in the provided text, but typically requires authentication credentials or a device identifier if not passed as a query parameter.) ### Response #### Success Response (200) - **response** (object) - Contains the device properties. - **REAL_TIME_VITALS** (object) - Vitals data for Sock 3. - **value** (object) - JSON object containing real-time vitals. - **HEART_RATE** (object) - Heart rate data for Sock 2. - **value** (integer) - Heart rate value. - **OXYGEN_LEVEL** (object) - Oxygen level data for Sock 2. - **value** (integer) - Oxygen level value. - **LOW_BATT_ALRT** (object) - Low battery alert status. - **value** (boolean) - True if low battery alert is active. - **SOCK_OFF** (object) - Sock off status. - **value** (boolean) - True if the sock is off. #### Response Example { "response": { "REAL_TIME_VITALS": { "value": { "heartrate": 120, "oxygen": 98 } }, "HEART_RATE": { "value": 120 }, "OXYGEN_LEVEL": { "value": 98 }, "LOW_BATT_ALRT": { "value": false }, "SOCK_OFF": { "value": false } } } #### Error Response (400) - **error** (string) - Description of the error, e.g., "Device not found." ``` -------------------------------- ### Update device properties Source: https://github.com/ryanbdclark/pyowletapi/blob/main/README.md Retrieve the current readings from a specific sock object. ```python device.update_properties() ``` -------------------------------- ### Sock.get_property() Source: https://context7.com/ryanbdclark/pyowletapi/llms.txt Retrieves a specific property value from the previously updated normalized properties dictionary. ```APIDOC ## Sock.get_property() ### Description Retrieves a specific property value from the normalized properties dictionary. This method should be called after update_properties() has been executed. ### Parameters #### Query Parameters - **property_name** (string) - Required - The key of the property to retrieve (e.g., 'heart_rate', 'oxygen_saturation', 'battery_percentage'). ### Response #### Success Response (200) - **value** (any) - The value associated with the requested property key. ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.