Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: Firmware Build

on:
pull_request:
branches: [develop, main]
push:
branches: [develop]

jobs:
platformio-build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"

- name: Install PlatformIO
run: python -m pip install platformio

- name: Compile firmware
run: python scripts/compile_check.py
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ See [docs/STATUS.md](docs/STATUS.md) for the current project state.

The firmware expects a local `src/config.h` file that is not committed. Start from [src/config_template.h](src/config_template.h) and adjust the values for your network and MQTT broker.

For compile-only validation, the repository now supports a temporary-config path:

```bash
python scripts/compile_check.py
```

If `src/config.h` is missing, the script copies `src/config_template.h`, runs `platformio run`, and removes the temporary file again.

Additional operating context now lives in:

- [docs/hardware.md](docs/hardware.md)
Expand All @@ -42,6 +50,6 @@ Additional operating context now lives in:
## Immediate Next Steps

1. Replace the legacy `config.h` flow with a clearer credentials/config separation.
2. Add a repeatable local build check that uses placeholder config for compile-only validation.
2. Add a real hardware smoke-test routine after the new compile-only validation path.
3. Decide which parts should remain standalone versus moving into `SkySentinel`.
4. Add hive-specific telemetry beyond the current BME280 baseline once the hardware scope is stable.
4 changes: 3 additions & 1 deletion docs/STATUS.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ HiveTech is an ESP32 firmware prototype for live beehive monitoring. It reads BM
- Public again by explicit portfolio decision
- Still uses a legacy `config.h` include path
- PlatformIO/IoT profile context is now committed in `anr.profile.yaml` plus focused hardware and operations docs
- No modern CI/build validation yet
- Compile-only validation now works via `python scripts/compile_check.py`
- CI build validation is defined in `.github/workflows/build.yml`
- Local developer deployment settings are still present outside committed templates

## Known Gaps
Expand All @@ -19,6 +20,7 @@ HiveTech is an ESP32 firmware prototype for live beehive monitoring. It reads BM
- Hardware wiring is documented only to the level visible in current firmware assumptions
- Deployment is still local and OTA-target specific
- MQTT contract is documented but still topic-only, without retained/availability semantics
- Real hardware smoke validation is still manual

## Next Milestone

Expand Down
6 changes: 6 additions & 0 deletions docs/operations.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ Current runtime flow:

`platformio.ini` currently contains a developer-local `upload_port`. Treat that as local machine state, not as committed team-wide truth.

## Build And Validation

- `python scripts/compile_check.py` is the default compile-only validation path
- the script creates a temporary `src/config.h` from `src/config_template.h` when needed
- CI uses the same path so local and remote validation stay aligned

## Safety Rules

- separate local credentials from committed templates
Expand Down
6 changes: 3 additions & 3 deletions docs/verification.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ Keep firmware changes reproducible and separate "compiles locally" from "works o

## Minimum Checks

1. Copy `src/config_template.h` to local `src/config.h` or provide an equivalent local config file.
2. Run `platformio run` for `env:esp32dev`.
1. Run `python scripts/compile_check.py` for a compile-only check.
2. If you need device-specific validation, provide a real local `src/config.h`.
3. Flash or OTA-update the node using the local deployment path from `platformio.ini`.
4. Confirm serial boot output reaches:
- Wi-Fi connect
Expand All @@ -22,5 +22,5 @@ Keep firmware changes reproducible and separate "compiles locally" from "works o

## Separation Of Checks

- Compile-only validation is useful for refactors and dependency changes.
- Compile-only validation is now available via `python scripts/compile_check.py`.
- Real hardware validation is still mandatory after sensor, networking, OTA, or sleep-logic changes.
4 changes: 4 additions & 0 deletions platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
platform = espressif32
board = esp32dev
framework = arduino
upload_protocol = espota
lib_deps =
knolleary/PubSubClient @ ^2.8
sparkfun/SparkFun BME280 @ ^2.0.9

upload_port = 192.168.178.135
;upload_port = COM5
Expand Down
37 changes: 37 additions & 0 deletions scripts/compile_check.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
from __future__ import annotations

import shutil
import subprocess
import sys
from pathlib import Path


def main() -> int:
repo_root = Path(__file__).resolve().parent.parent
src_dir = repo_root / "src"
config_path = src_dir / "config.h"
template_path = src_dir / "config_template.h"

created_temp_config = False
if not config_path.exists():
shutil.copyfile(template_path, config_path)
created_temp_config = True
print(f"created temporary config: {config_path}")
else:
print(f"using existing local config: {config_path}")

try:
result = subprocess.run(
[sys.executable, "-m", "platformio", "run"],
cwd=repo_root,
check=False,
)
return result.returncode
finally:
if created_temp_config and config_path.exists():
config_path.unlink()
print(f"removed temporary config: {config_path}")
Comment on lines +9 to +33
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The script doesn't handle the case where src/config_template.h is missing and will crash with a FileNotFoundError. It would be more robust to add an explicit check for the template file at the beginning of the function and exit with a user-friendly error message. This improves the script's robustness and user experience in a clear failure scenario.

def main() -> int:
    repo_root = Path(__file__).resolve().parent.parent
    src_dir = repo_root / "src"
    config_path = src_dir / "config.h"
    template_path = src_dir / "config_template.h"

    if not template_path.exists():
        print(f"error: template config not found: {template_path}", file=sys.stderr)
        return 1

    created_temp_config = False
    if not config_path.exists():
        shutil.copyfile(template_path, config_path)
        created_temp_config = True
        print(f"created temporary config: {config_path}")
    else:
        print(f"using existing local config: {config_path}")

    try:
        result = subprocess.run(
            [sys.executable, "-m", "platformio", "run"],
            cwd=repo_root,
            check=False,
        )
        return result.returncode
    finally:
        if created_temp_config and config_path.exists():
            config_path.unlink()
            print(f"removed temporary config: {config_path}")



if __name__ == "__main__":
raise SystemExit(main())
2 changes: 1 addition & 1 deletion src/HiveTech.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#include <ArduinoOTA.h>
#include <PubSubClient.h>

#include "esp_deep_sleep.h"
#include <esp_sleep.h>

#include <Wire.h>

Expand Down
6 changes: 3 additions & 3 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ Method to print the reason by which ESP32
has been awaken from sleep
*/
void print_wakeup_reason(){
esp_deep_sleep_wakeup_cause_t wakeup_reason;
esp_sleep_wakeup_cause_t wakeup_reason;

wakeup_reason = esp_deep_sleep_get_wakeup_cause();
wakeup_reason = esp_sleep_get_wakeup_cause();

switch(wakeup_reason)
{
Expand Down Expand Up @@ -85,7 +85,7 @@ void setup() {
First we configure the wake up source
We set our ESP32 to wake up every 15 seconds
*/
esp_deep_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
//Serial.println("Setup ESP32 to sleep for every " + String(TIME_TO_SLEEP) + " Seconds");

/*
Expand Down
Loading