From d419a7ec0a02be03dd5813cc1d02cda75fffb6a4 Mon Sep 17 00:00:00 2001 From: Till Date: Tue, 30 Jan 2024 20:35:32 +0100 Subject: [PATCH] Add continuous integration (#2) * Standardize code style * Add continuous integration workflow --- .clang-format | 10 ++ .github/workflows/ci.yaml | 129 +++++++++++++++++++ .pre-commit-config.yaml | 17 +++ .yamllint | 2 + README.md | 2 +- components/LD2450/LD2450.cpp | 2 +- components/LD2450/LD2450.h | 2 +- components/LD2450/__init__.py | 28 ++-- components/LD2450/baud_rate_select.cpp | 2 +- components/LD2450/baud_rate_select.h | 2 +- components/LD2450/bluetooth_switch.cpp | 2 +- components/LD2450/bluetooth_switch.h | 2 +- components/LD2450/max_detection_number.cpp | 2 +- components/LD2450/max_detection_number.h | 2 +- components/LD2450/polling_sensor.h | 2 +- components/LD2450/target.cpp | 2 +- components/LD2450/target.h | 2 +- components/LD2450/tracking_mode_switch.cpp | 2 +- components/LD2450/tracking_mode_switch.h | 2 +- components/LD2450/zone.cpp | 2 +- components/LD2450/zone.h | 12 +- pyproject.toml | 4 + requirements.txt | 1 + tests/base.yaml | 33 +++++ tests/full.yaml | 143 +++++++++++++++++++++ 25 files changed, 377 insertions(+), 32 deletions(-) create mode 100644 .clang-format create mode 100644 .github/workflows/ci.yaml create mode 100644 .pre-commit-config.yaml create mode 100644 .yamllint create mode 100644 pyproject.toml create mode 100644 requirements.txt create mode 100644 tests/base.yaml create mode 100644 tests/full.yaml diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..d3c185d --- /dev/null +++ b/.clang-format @@ -0,0 +1,10 @@ +UseTab: Never +IndentWidth: 4 +NamespaceIndentation: All +AccessModifierOffset: -4 +BreakBeforeBraces: Allman +AllowShortIfStatementsOnASingleLine: false +AllowShortFunctionsOnASingleLine: false +IndentCaseLabels: false +SortIncludes: false +ColumnLimit: 0 diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..cd48f18 --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,129 @@ +name: CI + +# yamllint disable-line rule:truthy +on: + workflow_dispatch: + inputs: + esphome_version: + description: "ESPHome PyPi Package version to use" + required: false + type: string + push: + branches: [main, dev] + + pull_request: + merge_group: + +permissions: + contents: read + +concurrency: + # yamllint disable-line rule:line-length + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + ci: + name: ${{ matrix.name }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + max-parallel: 5 + matrix: + include: + - id: test + file: tests/full.yaml + name: Test tests/full.yaml + pio_cache_key: full + - id: test + file: tests/base.yaml + name: Test tests/base.yaml + pio_cache_key: base + - id: clang-format + name: Run clang-format + - id: yamllint + name: Run yamllint + - id: black-format + name: Run black-format + - id: isort + name: Run isort + + steps: + - uses: actions/checkout@v3 + - name: Set up Python + uses: actions/setup-python@v4 + id: python + with: + python-version: "3.9" + + - name: Cache virtualenv + uses: actions/cache@v3 + with: + path: .venv + # yamllint disable-line rule:line-length + key: venv-${{ steps.python.outputs.python-version }} + restore-keys: | + venv-${{ steps.python.outputs.python-version }} + - name: Set up virtualenv + # yamllint disable rule:line-length + run: | + python -m venv .venv + source .venv/bin/activate + pip install -U pip + pip install -r requirements.txt + if [ ${{ github.event.inputs.esphome_version != '' }} == true ]; then pip install ESPHome==${{ github.event.inputs.esphome_version }}; else pip install -U ESPHome; fi + echo "$GITHUB_WORKSPACE/.venv/bin" >> $GITHUB_PATH + echo "VIRTUAL_ENV=$GITHUB_WORKSPACE/.venv" >> $GITHUB_ENV + # yamllint enable rule:line-length + + # Use per check platformio cache because checks use different parts + - name: Cache platformio + uses: actions/cache@v3 + with: + path: ~/.platformio + # yamllint disable-line rule:line-length + key: platformio-${{ matrix.pio_cache_key }}-${{ hashFiles('platformio.ini') }} + if: matrix.id == 'test' + + - run: esphome compile ${{ matrix.file }} + if: matrix.id == 'test' + env: + # Also cache libdeps, store them in a ~/.platformio subfolder + PLATFORMIO_LIBDEPS_DIR: ~/.platformio/libdeps + + - name: Run clang-format + uses: jidicula/clang-format-action@v4.11.0 + with: + clang-format-version: "13" + check-path: "components" + if: matrix.id == 'clang-format' + + - name: Run yamllint + if: matrix.id == 'yamllint' + uses: frenck/action-yamllint@v1.4.0 + + - name: Run black-format + if: matrix.id == 'black-format' + uses: psf/black@stable + with: + options: "--check --verbose" + version: "~= 24.1" + + - name: Run isort + if: matrix.id == 'isort' + uses: isort/isort-action@master + with: + requirementsFiles: "requirements.txt" + + ci-status: + name: CI Status + runs-on: ubuntu-latest + needs: [ci] + if: always() + steps: + - name: Successful deploy + if: ${{ !(contains(needs.*.result, 'failure')) }} + run: exit 0 + - name: Failing deploy + if: ${{ contains(needs.*.result, 'failure') }} + run: exit 1 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..aa93c90 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,17 @@ +repos: + - repo: https://github.com/psf/black-pre-commit-mirror + rev: 24.1.0 + hooks: + - id: black + language_version: python3.11 + + - repo: https://github.com/pycqa/isort + rev: 5.13.2 + hooks: + - id: isort + name: isort (python) + + - repo: https://github.com/pre-commit/mirrors-clang-format + rev: v17.0.6 + hooks: + - id: clang-format diff --git a/.yamllint b/.yamllint new file mode 100644 index 0000000..3a07442 --- /dev/null +++ b/.yamllint @@ -0,0 +1,2 @@ +ignore: | + venv/ diff --git a/README.md b/README.md index b94d44d..13ebc12 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# ESPHome Hi-Link HKL-LD2450 +# ESPHome Hi-Link HKL-LD2450 [![CI](https://github.com/TillFleisch/ESPHome-HLK-LD2450/actions/workflows/ci.yaml/badge.svg?branch=main)](https://github.com/TillFleisch/ESPHome-HLK-LD2450/actions/workflows/ci.yaml) This external [ESPHome](https://esphome.io) component adds support for the [Hi-Link HKL-LD2450](https://www.hlktech.net/index.php?id=1157) Human presence sensor to ESPHome. In addition to a basic binary presence sensor, this component adds various different sensors for each detected target and supports custom presence detection Zones. diff --git a/components/LD2450/LD2450.cpp b/components/LD2450/LD2450.cpp index 942ef32..51ba722 100644 --- a/components/LD2450/LD2450.cpp +++ b/components/LD2450/LD2450.cpp @@ -406,4 +406,4 @@ namespace esphome::ld2450 flush(); } -} \ No newline at end of file +} // namespace esphome::ld2450 \ No newline at end of file diff --git a/components/LD2450/LD2450.h b/components/LD2450/LD2450.h index 1327da2..a014f72 100644 --- a/components/LD2450/LD2450.h +++ b/components/LD2450/LD2450.h @@ -348,4 +348,4 @@ namespace esphome::ld2450 /// @brief Select options used for setting the sensors baud rate BaudRateSelect *baud_rate_select_ = nullptr; }; -} \ No newline at end of file +} // namespace esphome::ld2450 \ No newline at end of file diff --git a/components/LD2450/__init__.py b/components/LD2450/__init__.py index 433340b..1c54b77 100644 --- a/components/LD2450/__init__.py +++ b/components/LD2450/__init__.py @@ -1,34 +1,34 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import ( - uart, binary_sensor, + button, number, + select, sensor, - button, switch, - select, + uart, ) from esphome.components.uart import UARTComponent from esphome.const import ( CONF_ID, + CONF_INITIAL_VALUE, CONF_NAME, - CONF_STEP, CONF_RESTORE_VALUE, - CONF_INITIAL_VALUE, + CONF_STEP, CONF_UNIT_OF_MEASUREMENT, - UNIT_METER, - UNIT_CENTIMETER, - UNIT_DEGREES, - DEVICE_CLASS_OCCUPANCY, DEVICE_CLASS_DISTANCE, - DEVICE_CLASS_SPEED, + DEVICE_CLASS_OCCUPANCY, DEVICE_CLASS_RESTART, - STATE_CLASS_MEASUREMENT, - ICON_RESTART_ALERT, - ICON_BLUETOOTH, - ENTITY_CATEGORY_DIAGNOSTIC, + DEVICE_CLASS_SPEED, ENTITY_CATEGORY_CONFIG, + ENTITY_CATEGORY_DIAGNOSTIC, + ICON_BLUETOOTH, + ICON_RESTART_ALERT, + STATE_CLASS_MEASUREMENT, + UNIT_CENTIMETER, + UNIT_DEGREES, + UNIT_METER, ) AUTO_LOAD = ["binary_sensor", "number", "sensor", "button", "switch", "select"] diff --git a/components/LD2450/baud_rate_select.cpp b/components/LD2450/baud_rate_select.cpp index 0bf164f..9db87a4 100644 --- a/components/LD2450/baud_rate_select.cpp +++ b/components/LD2450/baud_rate_select.cpp @@ -6,4 +6,4 @@ namespace esphome::ld2450 { parent_->set_baud_rate(BAUD_STRING_TO_ENUM.at(value)); } -} \ No newline at end of file +} // namespace esphome::ld2450 \ No newline at end of file diff --git a/components/LD2450/baud_rate_select.h b/components/LD2450/baud_rate_select.h index 765a176..79e2224 100644 --- a/components/LD2450/baud_rate_select.h +++ b/components/LD2450/baud_rate_select.h @@ -16,4 +16,4 @@ namespace esphome::ld2450 void control(const std::string &value); }; -} \ No newline at end of file +} // namespace esphome::ld2450 \ No newline at end of file diff --git a/components/LD2450/bluetooth_switch.cpp b/components/LD2450/bluetooth_switch.cpp index 81c18ca..aa2d45b 100644 --- a/components/LD2450/bluetooth_switch.cpp +++ b/components/LD2450/bluetooth_switch.cpp @@ -6,4 +6,4 @@ namespace esphome::ld2450 { parent_->set_bluetooth_state(state); } -} \ No newline at end of file +} // namespace esphome::ld2450 \ No newline at end of file diff --git a/components/LD2450/bluetooth_switch.h b/components/LD2450/bluetooth_switch.h index a7fe2c3..b375493 100644 --- a/components/LD2450/bluetooth_switch.h +++ b/components/LD2450/bluetooth_switch.h @@ -16,4 +16,4 @@ namespace esphome::ld2450 void write_state(bool state) override; }; -} \ No newline at end of file +} // namespace esphome::ld2450 \ No newline at end of file diff --git a/components/LD2450/max_detection_number.cpp b/components/LD2450/max_detection_number.cpp index 43216eb..a82a61c 100644 --- a/components/LD2450/max_detection_number.cpp +++ b/components/LD2450/max_detection_number.cpp @@ -27,4 +27,4 @@ namespace esphome::ld2450 if (this->restore_value_) this->pref_.save(&value); } -} \ No newline at end of file +} // namespace esphome::ld2450 \ No newline at end of file diff --git a/components/LD2450/max_detection_number.h b/components/LD2450/max_detection_number.h index caf647f..ef67e90 100644 --- a/components/LD2450/max_detection_number.h +++ b/components/LD2450/max_detection_number.h @@ -50,4 +50,4 @@ namespace esphome::ld2450 ESPPreferenceObject pref_; }; -} \ No newline at end of file +} // namespace esphome::ld2450 \ No newline at end of file diff --git a/components/LD2450/polling_sensor.h b/components/LD2450/polling_sensor.h index 8adebba..d002e3c 100644 --- a/components/LD2450/polling_sensor.h +++ b/components/LD2450/polling_sensor.h @@ -46,4 +46,4 @@ namespace esphome::ld2450 /// @brief Value of this sensor (un-published) float value_ = 0; }; -} \ No newline at end of file +} // namespace esphome::ld2450 \ No newline at end of file diff --git a/components/LD2450/target.cpp b/components/LD2450/target.cpp index 457f090..3160018 100644 --- a/components/LD2450/target.cpp +++ b/components/LD2450/target.cpp @@ -72,4 +72,4 @@ namespace esphome::ld2450 return resolution_ != 0 && (!fast_off_detection_ || millis() - last_change_ <= FAST_OFF_THRESHOLD); } -} \ No newline at end of file +} // namespace esphome::ld2450 \ No newline at end of file diff --git a/components/LD2450/target.h b/components/LD2450/target.h index 111629b..d44adcc 100644 --- a/components/LD2450/target.h +++ b/components/LD2450/target.h @@ -229,4 +229,4 @@ namespace esphome::ld2450 /// @brief sensor reference of the distance sensor PollingSensor *distance_sensor_ = nullptr; }; -} \ No newline at end of file +} // namespace esphome::ld2450 \ No newline at end of file diff --git a/components/LD2450/tracking_mode_switch.cpp b/components/LD2450/tracking_mode_switch.cpp index 340e301..b98bedb 100644 --- a/components/LD2450/tracking_mode_switch.cpp +++ b/components/LD2450/tracking_mode_switch.cpp @@ -6,4 +6,4 @@ namespace esphome::ld2450 { parent_->set_tracking_mode(state); } -} \ No newline at end of file +} // namespace esphome::ld2450 \ No newline at end of file diff --git a/components/LD2450/tracking_mode_switch.h b/components/LD2450/tracking_mode_switch.h index e1a1fdf..a36ccba 100644 --- a/components/LD2450/tracking_mode_switch.h +++ b/components/LD2450/tracking_mode_switch.h @@ -16,4 +16,4 @@ namespace esphome::ld2450 void write_state(bool state) override; }; -} \ No newline at end of file +} // namespace esphome::ld2450 \ No newline at end of file diff --git a/components/LD2450/zone.cpp b/components/LD2450/zone.cpp index bd5d2f3..ab59e64 100644 --- a/components/LD2450/zone.cpp +++ b/components/LD2450/zone.cpp @@ -159,4 +159,4 @@ namespace esphome::ld2450 } return true; } -} \ No newline at end of file +} // namespace esphome::ld2450 \ No newline at end of file diff --git a/components/LD2450/zone.h b/components/LD2450/zone.h index 389a77d..50e0b1b 100644 --- a/components/LD2450/zone.h +++ b/components/LD2450/zone.h @@ -15,8 +15,14 @@ namespace esphome::ld2450 class Point { public: - Point() : x(0), y(0) {} - Point(int x, int y) : x(x), y(y) {} + Point() + : x(0), y(0) + { + } + Point(int x, int y) + : x(x), y(y) + { + } int x, y; }; @@ -138,4 +144,4 @@ namespace esphome::ld2450 /// @brief Map of targets which are currently tracked inside of this polygon with their last seen timestamp std::map tracked_targets_{}; }; -} +} // namespace esphome::ld2450 diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..b7d2ace --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,4 @@ +[tool.black] +target-version = ["py311"] +[tool.isort] +profile = "black" \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..c3c0b83 --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +esphome \ No newline at end of file diff --git a/tests/base.yaml b/tests/base.yaml new file mode 100644 index 0000000..d2c7d07 --- /dev/null +++ b/tests/base.yaml @@ -0,0 +1,33 @@ +esphome: + name: ld2450 + +esp32: + board: esp32dev + +external_components: + - source: + type: local + path: ../components + +logger: + baud_rate: 0 + +uart: + id: uart_bus + rx_pin: + number: GPIO16 + mode: + input: true + pullup: true + tx_pin: + number: GPIO17 + mode: + input: true + pullup: true + baud_rate: 256000 + parity: NONE + stop_bits: 1 + data_bits: 8 + +LD2450: + uart_id: uart_bus diff --git a/tests/full.yaml b/tests/full.yaml new file mode 100644 index 0000000..fe1c6ee --- /dev/null +++ b/tests/full.yaml @@ -0,0 +1,143 @@ +esphome: + name: ld2450 + +esp32: + board: esp32dev + +external_components: + - source: + type: local + path: ../components + +logger: + baud_rate: 0 + +uart: + id: uart_bus + rx_pin: + number: GPIO16 + mode: + input: true + pullup: true + tx_pin: + number: GPIO17 + mode: + input: true + pullup: true + baud_rate: 256000 + parity: NONE + stop_bits: 1 + data_bits: 8 + +LD2450: + uart_id: uart_bus + flip_x_axis: true + fast_off_detection: true + max_detection_distance: + name: "Max Distance" + initial_value: 4m + max_distance_margin: 30cm + + restart_button: + name: "Restart Sensor" + factory_reset_button: + name: "Factory Reset Sensor" + + tracking_mode_switch: + name: "Multiple Target Tracking" + bluetooth_switch: + name: "Sensor Bluetooth" + + baud_rate_select: + name: "Sensor Baud Rate" + + occupancy: + name: Occupancy + target_count: + name: Target Count + + targets: + - target: + name: "T1" + id: t1 + debug: true + x_position: + id: t1_xpos + y_position: + id: t1_ypos + speed: + id: t1_speed + distance_resolution: + id: t1_res + angle: + id: t1_angle + distance: + id: t1_distance + - target: + id: t2 + x_position: + id: t2_xpos + y_position: + id: t2_ypos + speed: + id: t2_speed + distance_resolution: + id: t2_res + angle: + id: t2_angle + distance: + id: t2_distance + - target: + id: t3 + x_position: + id: t3_xpos + y_position: + id: t3_ypos + speed: + id: t3_speed + distance_resolution: + id: t3_res + angle: + id: t3_angle + distance: + id: t3_distance + zones: + - zone: + name: "Office Right" + polygon: + - point: + x: 0m + y: 0m + - point: + x: 0m + y: 600cm + - point: + x: 6m + y: 6m + - point: + x: 6m + y: 0m + occupancy: + id: z1_occupancy + target_count: + id: z1_target_count + - zone: + name: "Office Left" + margin: 0.4m + polygon: + - point: + x: -0m + y: 0m + - point: + x: -0m + y: 6m + - point: + x: -6m + y: 6m + - point: + x: -6m + y: 0m + occupancy: + id: z2_occupancy + target_count: + id: z2_target_count