> ## Documentation Index
> Fetch the complete documentation index at: https://docs.directenergypartners.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Main Script

The main entry point for your custom application is the `app/main.py` file inside the `dep-ppl-app` repository. This
script handles the NATS connection to the PPL controller, sets up logging, and runs a continuous control loop where you
implement your custom logic.

You should edit this file directly to build your application. As your application grows, you can create additional modules
and a full folder structure inside the `app` folder to organize your code.

### The Main Script

Below is the default `main.py` script included in the repository:

```python app/main.py icon="python" theme={null}
"""
Main entry point for the app.
"""

import logging
import os
import sys
import time
from dotenv import load_dotenv

sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

from pplapp import Pplapp

# -- Configuration ------------------------------------------------------------
STARTUP_DELAY_S = 5
CONTROL_LOOP_INTERVAL_S = 5

# -- Logging ------------------------------------------------------------------
log = logging.getLogger("app")
log.setLevel(logging.INFO)
formatter = logging.Formatter(
    fmt="[%(asctime)s] %(levelname)s %(name)s %(message)s",
    datefmt="%d.%m.%Y %H:%M:%S",
)
_project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
fileHandler = logging.FileHandler(os.path.join(_project_root, "app.log"))
fileHandler.setFormatter(formatter)
log.addHandler(fileHandler)

consoleHandler = logging.StreamHandler()
consoleHandler.setFormatter(formatter)
log.addHandler(consoleHandler)

# -- Main Application Logic ---------------------------------------------------
def ems(app):
    # TODO: Implement energy management system logic
    pass

def main() -> None:
    load_dotenv()

    ipAddress = os.getenv("IP_ADDRESS")
    username = os.getenv("NATS_USERNAME")
    password = os.getenv("NATS_PASSWORD")

    if not ipAddress or not username or not password:
        log.error("IP_ADDRESS, NATS_USERNAME, and NATS_PASSWORD must be set in .env")
        sys.exit(1)

    log.info("Connecting to PPL controller at %s", ipAddress)
    app = Pplapp(ipAddress, username, password)

    time.sleep(STARTUP_DELAY_S)

    try:
        while True:
            try:
                ems(app)
            except Exception as e:
                log.exception("Error in control loop: %s", e)
            time.sleep(CONTROL_LOOP_INTERVAL_S)

    except KeyboardInterrupt:
        log.info("Shutdown requested")
        app.stop()
        log.info("Clean shutdown complete")


if __name__ == "__main__":
    main()
```

### How It Works

The script does the following:

* **Loads environment variables** from the `.env` file (`IP_ADDRESS`, `NATS_USERNAME`, `NATS_PASSWORD`).
* **Sets up logging** to both the console and a file (`app.log` in the project root).
* **Connects to the controller** using the `pplapp` module.
* **Runs a continuous control loop** that calls the `ems()` function at a configurable interval.
* **Handles errors gracefully** — exceptions in the loop are logged without crashing the application, and a keyboard interrupt triggers a clean shutdown.

The `ems()` function is where you implement your custom logic. The `app` parameter gives you access to all `pplapp`
module functions for reading data from and sending commands to the controller.

### Extending Your Application

The `app` folder is your workspace. As your application grows beyond a single file, you can create a full folder structure
inside it. For example:

```example App Folder Structure theme={null}
app/
├── __main__.py          # Allows running the app with python -m app
├── main.py              # Main entry point – edit this to implement your application
├── helpers/
│   ├── __init__.py
│   └── calculations.py
└── strategies/
    ├── __init__.py
    └── peak_shaving.py
```

Import your modules in `main.py` and call them from the `ems()` function. This keeps your code modular and maintainable.
