diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b86d00f2aae..412a678d02c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,7 +11,7 @@ ci: repos: - repo: https://github.com/astral-sh/ruff-pre-commit # Ruff version. - rev: v0.14.5 + rev: v0.14.7 hooks: # Run the linter. - id: ruff diff --git a/esphome/components/api/api.proto b/esphome/components/api/api.proto index 74a8e8ff7f8..5450c2536c5 100644 --- a/esphome/components/api/api.proto +++ b/esphome/components/api/api.proto @@ -589,6 +589,7 @@ enum SensorStateClass { STATE_CLASS_MEASUREMENT = 1; STATE_CLASS_TOTAL_INCREASING = 2; STATE_CLASS_TOTAL = 3; + STATE_CLASS_MEASUREMENT_ANGLE = 4; } // Deprecated in API version 1.5 diff --git a/esphome/components/api/api_pb2.h b/esphome/components/api/api_pb2.h index 93ece74d852..74d3834bf5f 100644 --- a/esphome/components/api/api_pb2.h +++ b/esphome/components/api/api_pb2.h @@ -51,6 +51,7 @@ enum SensorStateClass : uint32_t { STATE_CLASS_MEASUREMENT = 1, STATE_CLASS_TOTAL_INCREASING = 2, STATE_CLASS_TOTAL = 3, + STATE_CLASS_MEASUREMENT_ANGLE = 4, }; #endif enum LogLevel : uint32_t { diff --git a/esphome/components/api/api_pb2_dump.cpp b/esphome/components/api/api_pb2_dump.cpp index a985e052ac2..bea7fc53c4b 100644 --- a/esphome/components/api/api_pb2_dump.cpp +++ b/esphome/components/api/api_pb2_dump.cpp @@ -179,6 +179,8 @@ template<> const char *proto_enum_to_string(enums::Sens return "STATE_CLASS_TOTAL_INCREASING"; case enums::STATE_CLASS_TOTAL: return "STATE_CLASS_TOTAL"; + case enums::STATE_CLASS_MEASUREMENT_ANGLE: + return "STATE_CLASS_MEASUREMENT_ANGLE"; default: return "UNKNOWN"; } diff --git a/esphome/components/mipi_spi/models/jc.py b/esphome/components/mipi_spi/models/jc.py index 5dbf049dedf..5b936fd956f 100644 --- a/esphome/components/mipi_spi/models/jc.py +++ b/esphome/components/mipi_spi/models/jc.py @@ -484,4 +484,109 @@ DriverChip( ), ) +DriverChip( + "JC4827W543", + height=272, + width=480, + offset_height=0, + offset_width=0, + cs_pin={CONF_NUMBER: 45, CONF_IGNORE_STRAPPING_WARNING: True}, + invert_colors=True, + color_order=MODE_RGB, + bus_mode=TYPE_QUAD, + data_rate="20MHz", + initsequence=( + (0xFF, 0xA5), + (0x41, 0x03), + (0x44, 0x15), + (0x45, 0x15), + (0x7D, 0x03), + (0xC1, 0xBB), + (0xC2, 0x05), + (0xC3, 0x10), + (0xC6, 0x3E), + (0xC7, 0x25), + (0xC8, 0x11), + (0x7A, 0x5F), + (0x6F, 0x44), + (0x78, 0x70), + (0xC9, 0x00), + (0x67, 0x21), + (0x51, 0x0A), + (0x52, 0x76), + (0x53, 0x0A), + (0x54, 0x76), + (0x46, 0x0A), + (0x47, 0x2A), + (0x48, 0x0A), + (0x49, 0x1A), + (0x56, 0x43), + (0x57, 0x42), + (0x58, 0x3C), + (0x59, 0x64), + (0x5A, 0x41), + (0x5B, 0x3C), + (0x5C, 0x02), + (0x5D, 0x3C), + (0x5E, 0x1F), + (0x60, 0x80), + (0x61, 0x3F), + (0x62, 0x21), + (0x63, 0x07), + (0x64, 0xE0), + (0x65, 0x02), + (0xCA, 0x20), + (0xCB, 0x52), + (0xCC, 0x10), + (0xCD, 0x42), + (0xD0, 0x20), + (0xD1, 0x52), + (0xD2, 0x10), + (0xD3, 0x42), + (0xD4, 0x0A), + (0xD5, 0x32), + (0x80, 0x00), + (0xA0, 0x00), + (0x81, 0x07), + (0xA1, 0x06), + (0x82, 0x02), + (0xA2, 0x01), + (0x86, 0x11), + (0xA6, 0x10), + (0x87, 0x27), + (0xA7, 0x27), + (0x83, 0x37), + (0xA3, 0x37), + (0x84, 0x35), + (0xA4, 0x35), + (0x85, 0x3F), + (0xA5, 0x3F), + (0x88, 0x0B), + (0xA8, 0x0B), + (0x89, 0x14), + (0xA9, 0x14), + (0x8A, 0x1A), + (0xAA, 0x1A), + (0x8B, 0x0A), + (0xAB, 0x0A), + (0x8C, 0x14), + (0xAC, 0x08), + (0x8D, 0x17), + (0xAD, 0x07), + (0x8E, 0x16), + (0xAE, 0x06), + (0x8F, 0x1B), + (0xAF, 0x07), + (0x90, 0x04), + (0xB0, 0x04), + (0x91, 0x0A), + (0xB1, 0x0A), + (0x92, 0x16), + (0xB2, 0x15), + (0xFF, 0x00), + (0x11, 0x00), + (0x29, 0x00), + ), +) + models = {} diff --git a/esphome/components/sensor/__init__.py b/esphome/components/sensor/__init__.py index f83226d10fc..027d9a69b83 100644 --- a/esphome/components/sensor/__init__.py +++ b/esphome/components/sensor/__init__.py @@ -182,6 +182,7 @@ STATE_CLASSES = { "measurement": StateClasses.STATE_CLASS_MEASUREMENT, "total_increasing": StateClasses.STATE_CLASS_TOTAL_INCREASING, "total": StateClasses.STATE_CLASS_TOTAL, + "measurement_angle": StateClasses.STATE_CLASS_MEASUREMENT_ANGLE, } validate_state_class = cv.enum(STATE_CLASSES, lower=True, space="_") diff --git a/esphome/components/sensor/sensor.cpp b/esphome/components/sensor/sensor.cpp index 30187f498b0..3364798e55a 100644 --- a/esphome/components/sensor/sensor.cpp +++ b/esphome/components/sensor/sensor.cpp @@ -44,6 +44,8 @@ const LogString *state_class_to_string(StateClass state_class) { return LOG_STR("total_increasing"); case STATE_CLASS_TOTAL: return LOG_STR("total"); + case STATE_CLASS_MEASUREMENT_ANGLE: + return LOG_STR("measurement_angle"); case STATE_CLASS_NONE: default: return LOG_STR(""); diff --git a/esphome/components/sensor/sensor.h b/esphome/components/sensor/sensor.h index 42e540a3491..6f0412842a1 100644 --- a/esphome/components/sensor/sensor.h +++ b/esphome/components/sensor/sensor.h @@ -31,6 +31,7 @@ enum StateClass : uint8_t { STATE_CLASS_MEASUREMENT = 1, STATE_CLASS_TOTAL_INCREASING = 2, STATE_CLASS_TOTAL = 3, + STATE_CLASS_MEASUREMENT_ANGLE = 4 }; const LogString *state_class_to_string(StateClass state_class); diff --git a/esphome/const.py b/esphome/const.py index 2b6b60d395f..59bf0e8b8ad 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1346,6 +1346,9 @@ STATE_CLASS_NONE = "" # The state represents a measurement in present time STATE_CLASS_MEASUREMENT = "measurement" +# The state represents a measurement in present time for angles measured in degrees (°) +STATE_CLASS_MEASUREMENT_ANGLE = "measurement_angle" + # The state represents a total that only increases, a decrease is considered a reset. STATE_CLASS_TOTAL_INCREASING = "total_increasing" diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index 79e537153e1..0c05b07ae31 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -245,6 +245,9 @@ template class FixedVector { other.reset_(); } + // Allow conversion to std::vector + operator std::vector() const { return {data_, data_ + size_}; } + FixedVector &operator=(FixedVector &&other) noexcept { if (this != &other) { // Delete our current data diff --git a/requirements.txt b/requirements.txt index a5c919e95fe..45ae3d5925c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ platformio==6.1.18 # When updating platformio, also update /docker/Dockerfile esptool==5.1.0 click==8.1.7 esphome-dashboard==20251013.0 -aioesphomeapi==42.8.0 +aioesphomeapi==42.9.0 zeroconf==0.148.0 puremagic==1.30 ruamel.yaml==0.18.16 # dashboard_import diff --git a/requirements_test.txt b/requirements_test.txt index 7f6d3f8e268..3aec877126e 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -1,6 +1,6 @@ pylint==4.0.3 flake8==7.3.0 # also change in .pre-commit-config.yaml when updating -ruff==0.14.5 # also change in .pre-commit-config.yaml when updating +ruff==0.14.7 # also change in .pre-commit-config.yaml when updating pyupgrade==3.21.2 # also change in .pre-commit-config.yaml when updating pre-commit diff --git a/tests/components/sensor/common.yaml b/tests/components/sensor/common.yaml index 2180f66da8d..1961c986853 100644 --- a/tests/components/sensor/common.yaml +++ b/tests/components/sensor/common.yaml @@ -236,3 +236,10 @@ sensor: - multiply: 2.0 - offset: 10.0 - lambda: return x * 3.0; + + # Testing measurement_angle state class + - platform: template + name: "Angle Sensor" + lambda: return 42.0; + update_interval: 1s + state_class: "measurement_angle"