-
Notifications
You must be signed in to change notification settings - Fork 6
feat: Allow passing external aiohttp.ClientSession to OpenEVSE #508
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
firstof9
wants to merge
12
commits into
main
Choose a base branch
from
external-session
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
e17b1c1
feat: Allow passing external aiohttp.ClientSession to OpenEVSE and Op…
firstof9 aa50672
formatting
firstof9 1f4e38c
formatting again
firstof9 5b86d67
update test config
firstof9 860afb8
update tests
firstof9 60969e2
update doc
firstof9 b67e12a
update tests again
firstof9 d38eb84
formatting
firstof9 41b2925
update tests and suggested changes
firstof9 5723212
formatting
firstof9 8a3076a
recommended update
firstof9 3493778
formatting and linting
firstof9 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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,141 @@ | ||
| # External Session Management | ||
|
|
||
| ## Overview | ||
|
|
||
| The `python-openevse-http` library now supports passing an external `aiohttp.ClientSession` to the `OpenEVSE` class. This allows you to manage the session lifecycle yourself and share sessions across multiple API clients. | ||
|
|
||
| ## Benefits | ||
|
|
||
| - **Session Reuse**: Share a single session across multiple OpenEVSE instances or other aiohttp-based clients | ||
| - **Custom Configuration**: Configure session settings like timeouts, connectors, and SSL verification | ||
| - **Resource Management**: Better control over connection pooling and resource cleanup | ||
| - **Integration**: Easier integration with existing applications that already manage aiohttp sessions | ||
|
|
||
| ## Usage | ||
|
|
||
| ### With External Session | ||
|
|
||
| ```python | ||
| import aiohttp | ||
| from openevsehttp import OpenEVSE | ||
|
|
||
| async def main(): | ||
| # Create your own session with custom settings | ||
| timeout = aiohttp.ClientTimeout(total=30) | ||
| async with aiohttp.ClientSession(timeout=timeout) as session: | ||
| # Pass the session to OpenEVSE | ||
| charger = OpenEVSE("openevse.local", session=session) | ||
|
|
||
| # Use the charger normally | ||
| await charger.update() | ||
| print(f"Status: {charger.status}") | ||
|
|
||
| # Clean up | ||
| await charger.ws_disconnect() | ||
| # Session will be closed by the context manager | ||
| ``` | ||
|
|
||
| ### Without External Session (Backward Compatible) | ||
|
|
||
| ```python | ||
| from openevsehttp import OpenEVSE | ||
|
|
||
| async def main(): | ||
| # The library creates and manages its own sessions | ||
| charger = OpenEVSE("openevse.local") | ||
|
|
||
| # Use the charger normally | ||
| await charger.update() | ||
| print(f"Status: {charger.status}") | ||
|
|
||
| await charger.ws_disconnect() | ||
| ``` | ||
|
|
||
| ### Sharing a Session | ||
|
|
||
| ```python | ||
| import aiohttp | ||
| from openevsehttp import OpenEVSE | ||
|
|
||
| async def main(): | ||
| async with aiohttp.ClientSession() as session: | ||
| # Use the same session for multiple chargers | ||
| charger1 = OpenEVSE("charger1.local", session=session) | ||
| charger2 = OpenEVSE("charger2.local", session=session) | ||
|
|
||
| # Both chargers use the same session | ||
| await charger1.update() | ||
| await charger2.update() | ||
|
|
||
| await charger1.ws_disconnect() | ||
| await charger2.ws_disconnect() | ||
| ``` | ||
|
|
||
| ## API Changes | ||
|
|
||
| ### `OpenEVSE.__init__()` | ||
|
|
||
| ```python | ||
| def __init__( | ||
| self, | ||
| host: str, | ||
| user: str = "", | ||
| pwd: str = "", | ||
| session: aiohttp.ClientSession | None = None, | ||
| ) -> None: | ||
| ``` | ||
|
|
||
| **Parameters:** | ||
| - `host` (str): The hostname or IP address of the OpenEVSE charger | ||
| - `user` (str, optional): Username for authentication | ||
| - `pwd` (str, optional): Password for authentication | ||
| - `session` (aiohttp.ClientSession | None, optional): External session to use for HTTP requests. If not provided, the library will create temporary sessions as needed. | ||
|
|
||
| ### `OpenEVSEWebsocket.__init__()` | ||
|
|
||
| ```python | ||
| def __init__( | ||
| self, | ||
| server, | ||
| callback, | ||
| user=None, | ||
| password=None, | ||
| session: aiohttp.ClientSession | None = None, | ||
| ): | ||
| ``` | ||
|
|
||
| **Parameters:** | ||
| - `server`: The server URL | ||
| - `callback`: Callback function for websocket events | ||
| - `user` (optional): Username for authentication | ||
| - `password` (optional): Password for authentication | ||
| - `session` (aiohttp.ClientSession | None, optional): External session to use for websocket connections. If not provided, a new session will be created. | ||
|
|
||
| ## Important Notes | ||
|
|
||
| 1. **Session Lifecycle**: When you provide an external session, you are responsible for closing it. The library will NOT close externally provided sessions. | ||
|
|
||
| 2. **Backward Compatibility**: This change is fully backward compatible. Existing code that doesn't provide a session will continue to work exactly as before. | ||
|
|
||
| 3. **Websocket Sessions**: The websocket connection will also use the provided session, ensuring consistent session management across all HTTP and WebSocket operations. | ||
|
|
||
| 4. **Thread Safety**: If you're using the same session across multiple OpenEVSE instances, ensure you're following aiohttp's thread safety guidelines. | ||
|
|
||
| ## Migration Guide | ||
|
|
||
| If you want to migrate existing code to use external sessions: | ||
|
|
||
| **Before:** | ||
| ```python | ||
| charger = OpenEVSE("openevse.local") | ||
| await charger.update() | ||
| ``` | ||
|
|
||
| **After:** | ||
| ```python | ||
| async with aiohttp.ClientSession() as session: | ||
| charger = OpenEVSE("openevse.local", session=session) | ||
| await charger.update() | ||
| ``` | ||
|
|
||
| No other changes are required! | ||
This file contains hidden or 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,67 @@ | ||
| """Example of using python-openevse-http with an external aiohttp.ClientSession. | ||
|
|
||
| This demonstrates how to pass your own session to the library, which is useful when: | ||
| - You want to manage the session lifecycle yourself | ||
| - You need to share a session across multiple API clients | ||
| - You want to configure custom session settings (timeouts, connectors, etc.) | ||
| """ | ||
|
|
||
| import asyncio | ||
|
|
||
| import aiohttp | ||
|
|
||
| from openevsehttp.__main__ import OpenEVSE | ||
firstof9 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
|
|
||
| async def example_with_external_session(): | ||
| """Example using an external session.""" | ||
| # Create your own session with custom settings | ||
| timeout = aiohttp.ClientTimeout(total=30) | ||
| async with aiohttp.ClientSession(timeout=timeout) as session: | ||
| # Pass the session to OpenEVSE | ||
| charger = OpenEVSE("openevse.local", session=session) | ||
|
|
||
| # Use the charger normally | ||
| await charger.update() | ||
| print(f"Status: {charger.status}") | ||
| print(f"Current: {charger.charging_current}A") | ||
|
|
||
| # The session will be closed when the context manager exits | ||
| # but OpenEVSE won't close it (since it's externally managed) | ||
| await charger.ws_disconnect() | ||
|
|
||
|
|
||
| async def example_without_external_session(): | ||
| """Example without external session (backward compatible).""" | ||
| # The library will create and manage its own sessions | ||
| charger = OpenEVSE("openevse.local") | ||
|
|
||
| # Use the charger normally | ||
| await charger.update() | ||
| print(f"Status: {charger.status}") | ||
| print(f"Current: {charger.charging_current}A") | ||
|
|
||
| await charger.ws_disconnect() | ||
|
|
||
|
|
||
| async def example_shared_session(): | ||
| """Example sharing a session between multiple clients.""" | ||
| async with aiohttp.ClientSession() as session: | ||
| # Use the same session for multiple chargers | ||
| charger1 = OpenEVSE("charger1.local", session=session) | ||
| charger2 = OpenEVSE("charger2.local", session=session) | ||
|
|
||
| # Both chargers use the same session | ||
| await charger1.update() | ||
| await charger2.update() | ||
|
|
||
| print(f"Charger 1 Status: {charger1.status}") | ||
| print(f"Charger 2 Status: {charger2.status}") | ||
|
|
||
| await charger1.ws_disconnect() | ||
| await charger2.ws_disconnect() | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| # Run one of the examples | ||
| asyncio.run(example_with_external_session()) | ||
This file contains hidden or 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 hidden or 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 hidden or 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
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.