-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* remove temp excel * Add test depencencies * Remove reference to deleted config * fix path to sql init files * fix missing parameter in db test
- Loading branch information
Showing
33 changed files
with
963 additions
and
832 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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -163,4 +163,5 @@ cython_debug/ | |
*.pbix | ||
|
||
#project specific ignores | ||
em_cache.json | ||
em_cache.json | ||
*.csv |
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,16 @@ | ||
{ | ||
// Use IntelliSense to learn about possible attributes. | ||
// Hover to view descriptions of existing attributes. | ||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 | ||
"version": "0.2.0", | ||
"configurations": [ | ||
{ | ||
"name": "Python: Current File", | ||
"type": "python", | ||
"request": "launch", | ||
"program": "${file}", | ||
"console": "integratedTerminal", | ||
"justMyCode": true | ||
} | ||
] | ||
} |
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,2 +1,52 @@ | ||
# kasa_carbon | ||
Show CO2 emissions of devices connected to a Kasa energy meter. | ||
[![PyPI version](https://badge.fury.io/py/kasa-carbon.svg)](https://badge.fury.io/py/kasa-carbon) | ||
|
||
# kasa_carbon | ||
Show CO2 emissions of devices connected to a Kasa energy meter. This project depends on and extends the python-kasa project which you can see here: https://python-kasa.readthedocs.io/en/stable/. It requires a supported Kasa brand plug. | ||
|
||
# Quickstart instructions (file mode) | ||
This utility is installed as a python module. Its recommended to install within a python virtual environment such as conda. For the example below I'll be using conda. | ||
|
||
Currently the application supports getting carbon intensity data from Electricity Maps and you'll need an api key here https://www.electricitymaps.com/pricing. The plan for personal non-commercial use is what has been tested. | ||
|
||
```bash | ||
conda create -n kasa python=3.12 | ||
conda activate kasa | ||
pip install kasa-carbon | ||
kasa-carbon --storage=file --em_api_key=<your electricty maps api key> --em_cache_expiry_mins=30 --local_lat=<latitiude of the device under test> --local_lon=<longitude of the device under test> | ||
``` | ||
|
||
You will see console output like the following: | ||
``` | ||
The energy monitoring task is still running. | ||
['TP-LINK_Power Strip_D581-Orange pi 1,2023-12-05 00:24:39.716662+00:00,1.387,3.0513999999999997e-06,528.0\n', 'TP-LINK_Power Strip_D581-Plug 1,2024-01-01 16:53:37.793121+00:00,3.11,6.2588749999999994e-06,483.0\n', 'TP-LINK_Power Strip_D581-Plug 2,2024-01-01 16:53:37.794128+00:00,0.0,0.0,483.0\n', 'TP-LINK_Power Strip_D581-Plug 3,2024-01-01 16:53:37.794128+00:00,8.009,1.61181125e-05,483.0\n', 'TP-LINK_Power Strip_D581-Plug 4,2024-01-01 16:53:37.794128+00:00,1.5,3.01875e-06,483.0\n', 'TP-LINK_Power Strip_D581-Plug 5,2024-01-01 16:53:37.794128+00:00,1.707,3.4353375e-06,483.0\n', 'TP-LINK_Power Strip_D581-Orange pi 1,2024-01-01 16:53:37.795126+00:00,1.624,3.2683e-06,483.0\n'] | ||
``` | ||
|
||
The monitoring task will run until killed while appending the readings to the output file. | ||
|
||
# Database mode | ||
There is also a more advanced database mode. You can deploy the required postgres databased to a docker container using the provided docker-compose.yml file in the source. | ||
There are several parameters which are required for this which can be read from environment variables. Here are some recommended values. | ||
```python | ||
DB_HOST=host.docker.internal | ||
DB_PORT=5432 | ||
DB_USER=postgres | ||
DB_PASSWORD=<create an admin password> | ||
DB_NAME=kasa_carbon | ||
DB_VIEW_USER=energy_view_user | ||
DB_VIEW_USER_PASSWORD=<create readonly a password> | ||
``` | ||
|
||
With the database running in the docker container you can launch the application using the relevant database parameters like: | ||
'kasa-carbon --db_host=host.docker.internal --db_port=5432 --db_user=postgres --db_password=<admin password> --db_name=kasa_carbon --db_view_user=energy_view_user --em_api_key=<your electricity maps api key> --em_cache_expiry_mins=30 --local_lat=39.633971 --local_lon=-105.329563 | ||
|
||
# Example output | ||
Here is an example of using excel to graph the output obtained while running two instances of the Phoronix Apache Benchmark across both a Orange Pi and an Intel NUC. I've only plotted mgCO2e on this chart but watts is also an available reading. I live in a place with relatively low veraibility in our grid carbon intensity but had the co2/kwhr changed in the local grid during the course of this test it would have impacted the co2 data but not the power data. | ||
![Example Graph](visualization/apachebenchmarkexample.jpg) | ||
The full example table is also available at (visualization/energy_usage.xlsx) | ||
|
||
# Development instructions | ||
You can run the project from source as | ||
'python -m kasa_carbon.kasa_carbon_main | ||
|
||
more instructions coming . . . | ||
|
This file was deleted.
Oops, something went wrong.
File renamed without changes.
File renamed without changes.
File renamed without changes.
4 changes: 2 additions & 2 deletions
4
interfaces/datastore_api.py → kasa_carbon/interfaces/datastore_api.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
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 @@ | ||
#!/usr/bin/env python3 | ||
|
||
import asyncio | ||
import argparse | ||
import os | ||
from kasa_carbon.modules import kasa_monitor, database, file_storage | ||
from dotenv import load_dotenv, find_dotenv | ||
|
||
async def main(): | ||
load_dotenv(find_dotenv()) | ||
|
||
parser = argparse.ArgumentParser(description='kasa-carbon arguments') | ||
parser.add_argument('--storage', choices=['database', 'file'], default='database', help='Storage method') | ||
parser.add_argument('--file-path', default='energy_usage.csv', help='File path for file storage') | ||
parser.add_argument('--file-mode', choices=['append', 'overwrite'], default='append', help='File mode for file storage append will continuously append and overwrite will only keep the most recent value') | ||
parser.add_argument("--db_host", default=os.getenv("DB_HOST"), help="Database host") | ||
parser.add_argument("--db_port", default=os.getenv("DB_PORT"), type=int, help="Database port") | ||
parser.add_argument("--db_user", default=os.getenv("DB_USER"), help="Database user") | ||
parser.add_argument("--db_password", default=os.getenv("DB_PASSWORD"), help="Database password") | ||
parser.add_argument("--db_name", default=os.getenv("DB_NAME"), help="Database name") | ||
parser.add_argument("--db_view_user", default=os.getenv("DB_VIEW_USER"), help="Database view user") | ||
parser.add_argument("--em_api_key", default=os.getenv("EM_API_KEY"), help="API key") | ||
parser.add_argument("--em_cache_expiry_mins", default=os.getenv("EM_CACHE_EXPIRY_MINS"), type=int, help="Carbon Data cache expiry in minutes") | ||
parser.add_argument("--local_lat", default=os.getenv("LOCAL_LAT"), type=float, help="Local latitude") | ||
parser.add_argument("--local_lon", default=os.getenv("LOCAL_LON"), type=float, help="Local longitude") | ||
parser.add_argument("--update_interval_sec", default=15, type=int, help="Update interval in seconds") | ||
|
||
|
||
args = parser.parse_args() | ||
|
||
# Set the values as global constants | ||
DB_HOST = args.db_host | ||
DB_PORT = args.db_port | ||
DB_USER = args.db_user | ||
DB_NAME = args.db_name | ||
DB_VIEW_USER = args.db_view_user | ||
EM_API_KEY = args.em_api_key | ||
EM_CACHE_EXPIRY_MINS = args.em_cache_expiry_mins | ||
LOCAL_LAT = args.local_lat | ||
LOCAL_LON = args.local_lon | ||
|
||
# Configuration for General API | ||
API_KEY = EM_API_KEY | ||
API_TYPE = "ElectricityMaps" # or "watttime" | ||
|
||
# Update interval in seconds | ||
UPDATE_INTERVAL_SEC = args.update_interval_sec | ||
|
||
# database connection information | ||
db_config = { | ||
"user": args.db_user, | ||
"password": args.db_password, | ||
"database": args.db_name, | ||
"host": args.db_host, | ||
"port": args.db_port, | ||
} | ||
kasa = kasa_monitor.KasaMonitor(api_key = API_KEY, local_lon=LOCAL_LON, local_lat=LOCAL_LAT, co2_api_provider=API_TYPE, em_cache_expiry_mins=EM_CACHE_EXPIRY_MINS) | ||
|
||
if args.storage == 'file': | ||
storage = file_storage.FileStorage(args.file_path, args.file_mode) | ||
else: #database is default | ||
storage = database.Database(db_config) | ||
|
||
# Monitor energy use continuously in a subthread to avoid blocking the main thread | ||
energy_use_task = asyncio.create_task(kasa.monitor_energy_use_continuously(storage, delay=UPDATE_INTERVAL_SEC)) | ||
|
||
while True: | ||
if energy_use_task.done(): | ||
print("The energy monitoring task has completed.") | ||
else: | ||
print("The energy monitoring task is still running.") | ||
|
||
# view the current database values | ||
print(await storage.read_usage()) | ||
|
||
# Wait for next update | ||
await asyncio.sleep(UPDATE_INTERVAL_SEC) | ||
|
||
def main_wrapper(): | ||
asyncio.run(main()) | ||
|
||
if __name__ == "__main__": | ||
main_wrapper() |
File renamed without changes.
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
File renamed without changes.
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
Empty file.
23 changes: 10 additions & 13 deletions
23
modules/kasa_monitor.py → kasa_carbon/modules/kasa_monitor.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
Empty file.
Oops, something went wrong.