Merge pull request #17 from ElVit/heatpump_unittests
🚀 Add Comprehensive Tests and CI for Panasonic Heatpump
This commit is contained in:
commit
c3c6106ade
|
|
@ -0,0 +1,66 @@
|
|||
---
|
||||
# Clang-format configuration for ESPHome components
|
||||
# Based on ESPHome coding style
|
||||
|
||||
BasedOnStyle: Google
|
||||
IndentWidth: 2
|
||||
ColumnLimit: 120
|
||||
AccessModifierOffset: -1
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveDeclarations: false
|
||||
AlignEscapedNewlines: Left
|
||||
AlignOperands: true
|
||||
AlignTrailingComments: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowShortBlocksOnASingleLine: false
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: None
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeBraces: Attach
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakInheritanceList: BeforeColon
|
||||
BreakStringLiterals: true
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DerivePointerAlignment: false
|
||||
FixNamespaceComments: true
|
||||
IncludeBlocks: Preserve
|
||||
IndentCaseLabels: false
|
||||
IndentPPDirectives: None
|
||||
IndentWrappedFunctionNames: false
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
Language: Cpp
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
PointerAlignment: Left
|
||||
ReflowComments: true
|
||||
SortIncludes: false
|
||||
SortUsingDeclarations: true
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 2
|
||||
SpacesInAngles: false
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInContainerLiterals: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: c++11
|
||||
UseTab: Never
|
||||
|
|
@ -0,0 +1,184 @@
|
|||
name: Test Panasonic Heatpump Component
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- 'heatpump**'
|
||||
paths:
|
||||
- 'components/panasonic_heatpump/**'
|
||||
- 'tests/panasonic_heatpump/**'
|
||||
- '.github/workflows/test_panasonic_heatpump.yml'
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- 'components/panasonic_heatpump/**'
|
||||
- 'tests/panasonic_heatpump/**'
|
||||
- '.github/workflows/test_panasonic_heatpump.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
test-build:
|
||||
name: Test ESPHome Build
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
board: [esp8266, esp32s2, esp32c3, full]
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Build ESPHome firmware for ${{ matrix.board }}
|
||||
uses: esphome/build-action@v7
|
||||
with:
|
||||
yaml-file: tests/panasonic_heatpump/test_panasonic_heatpump_${{ matrix.board == 'full' && 'full' || matrix.board }}.yaml
|
||||
version: latest
|
||||
|
||||
lint-code:
|
||||
name: Lint C++ Code
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install clang-format
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y clang-format
|
||||
|
||||
- name: Run clang-format check
|
||||
run: |
|
||||
find components/panasonic_heatpump -name '*.cpp' -o -name '*.h' | \
|
||||
xargs clang-format -style=file --dry-run --Werror
|
||||
|
||||
lint-python:
|
||||
name: Lint Python Code
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.11'
|
||||
|
||||
- name: Install linting tools
|
||||
run: |
|
||||
pip install --upgrade pip
|
||||
pip install flake8 pylint black
|
||||
|
||||
- name: Run black check
|
||||
run: |
|
||||
black --check components/panasonic_heatpump/
|
||||
|
||||
- name: Run flake8
|
||||
run: |
|
||||
flake8 components/panasonic_heatpump/ --count --select=E9,F63,F7,F82 --show-source --statistics
|
||||
flake8 components/panasonic_heatpump/ --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
|
||||
|
||||
test-python:
|
||||
name: Python Unit Tests
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.11'
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
pip install --upgrade pip
|
||||
pip install pytest pytest-cov esphome
|
||||
|
||||
- name: Run Python unit tests
|
||||
run: |
|
||||
pytest tests/panasonic_heatpump/ -v --cov=components/panasonic_heatpump --cov-report=xml --cov-report=term
|
||||
|
||||
- name: Upload coverage to Codecov
|
||||
uses: codecov/codecov-action@v4
|
||||
with:
|
||||
file: ./coverage.xml
|
||||
flags: unittests
|
||||
name: codecov-panasonic-heatpump
|
||||
fail_ci_if_error: false
|
||||
|
||||
test-minimal-config:
|
||||
name: Test Minimal Configuration
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.11'
|
||||
|
||||
- name: Install ESPHome
|
||||
run: |
|
||||
pip install --upgrade pip
|
||||
pip install esphome
|
||||
|
||||
- name: Validate minimal config
|
||||
run: |
|
||||
esphome config tests/panasonic_heatpump/test_panasonic_heatpump_mini.yaml
|
||||
|
||||
test-full-config:
|
||||
name: Test Full Configuration
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.11'
|
||||
|
||||
- name: Install ESPHome
|
||||
run: |
|
||||
pip install --upgrade pip
|
||||
pip install esphome
|
||||
|
||||
- name: Validate full config
|
||||
run: |
|
||||
esphome config tests/panasonic_heatpump/test_panasonic_heatpump_full.yaml
|
||||
|
||||
summary:
|
||||
name: Test Summary
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
needs: [test-build, lint-code, lint-python, test-python, test-minimal-config, test-full-config]
|
||||
if: always()
|
||||
steps:
|
||||
- name: Check test results
|
||||
run: |
|
||||
echo "Test Build: ${{ needs.test-build.result }}"
|
||||
echo "Lint C++: ${{ needs.lint-code.result }}"
|
||||
echo "Lint Python: ${{ needs.lint-python.result }}"
|
||||
echo "Python Unit Tests: ${{ needs.test-python.result }}"
|
||||
echo "Minimal Config: ${{ needs.test-minimal-config.result }}"
|
||||
echo "Full Config: ${{ needs.test-full-config.result }}"
|
||||
|
||||
if [ "${{ needs.test-build.result }}" != "success" ] || \
|
||||
[ "${{ needs.lint-code.result }}" != "success" ] || \
|
||||
[ "${{ needs.lint-python.result }}" != "success" ] || \
|
||||
[ "${{ needs.test-python.result }}" != "success" ] || \
|
||||
[ "${{ needs.test-minimal-config.result }}" != "success" ] || \
|
||||
[ "${{ needs.test-full-config.result }}" != "success" ]; then
|
||||
echo "One or more tests failed"
|
||||
exit 1
|
||||
fi
|
||||
echo "All tests passed successfully!"
|
||||
|
|
@ -4,30 +4,32 @@ from esphome import pins
|
|||
from esphome.components import uart
|
||||
from esphome.const import CONF_ID
|
||||
|
||||
CODEOWNERS = ['@elvit']
|
||||
CODEOWNERS = ["@elvit"]
|
||||
MULTICONF = True
|
||||
DEPENDENCIES = ['uart']
|
||||
DEPENDENCIES = ["uart"]
|
||||
|
||||
CONF_MAIDESITE_DESK_ID = "maidesite_desk"
|
||||
CONF_LOG_UART_MSG = "log_uart_msg"
|
||||
|
||||
maidesite_desk_ns = cg.esphome_ns.namespace('maidesite_desk')
|
||||
MaidesiteDeskComponent = maidesite_desk_ns.class_('MaidesiteDeskComponent', cg.Component, uart.UARTDevice)
|
||||
|
||||
CONFIG_SCHEMA = (
|
||||
cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(MaidesiteDeskComponent),
|
||||
|
||||
cv.Optional(CONF_LOG_UART_MSG, default=False): cv.boolean,
|
||||
}
|
||||
)
|
||||
.extend(uart.UART_DEVICE_SCHEMA)
|
||||
.extend(cv.COMPONENT_SCHEMA)
|
||||
maidesite_desk_ns = cg.esphome_ns.namespace("maidesite_desk")
|
||||
MaidesiteDeskComponent = maidesite_desk_ns.class_(
|
||||
"MaidesiteDeskComponent", cg.Component, uart.UARTDevice
|
||||
)
|
||||
|
||||
CONFIG_SCHEMA = (
|
||||
cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(MaidesiteDeskComponent),
|
||||
cv.Optional(CONF_LOG_UART_MSG, default=False): cv.boolean,
|
||||
}
|
||||
)
|
||||
.extend(uart.UART_DEVICE_SCHEMA)
|
||||
.extend(cv.COMPONENT_SCHEMA)
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await cg.register_component(var, config)
|
||||
await uart.register_uart_device(var, config)
|
||||
cg.add(var.set_log_uart_msg(config[CONF_LOG_UART_MSG]))
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await cg.register_component(var, config)
|
||||
await uart.register_uart_device(var, config)
|
||||
cg.add(var.set_log_uart_msg(config[CONF_LOG_UART_MSG]))
|
||||
|
|
|
|||
|
|
@ -2,11 +2,10 @@ import esphome.codegen as cg
|
|||
import esphome.config_validation as cv
|
||||
from esphome.components import button
|
||||
from esphome.const import (
|
||||
ENTITY_CATEGORY_CONFIG,
|
||||
ENTITY_CATEGORY_CONFIG,
|
||||
)
|
||||
from .. import CONF_MAIDESITE_DESK_ID, MaidesiteDeskComponent, maidesite_desk_ns
|
||||
|
||||
|
||||
CONF_STEP_UP = "step_up"
|
||||
CONF_STEP_DOWN = "step_down"
|
||||
CONF_STOP = "stop"
|
||||
|
|
@ -22,79 +21,81 @@ CONF_SAVE_M3 = "save_m3"
|
|||
CONF_SAVE_M4 = "save_m4"
|
||||
|
||||
TYPES = [
|
||||
CONF_STEP_UP,
|
||||
CONF_STEP_DOWN,
|
||||
CONF_STOP,
|
||||
CONF_GOTO_MAX,
|
||||
CONF_GOTO_MIN,
|
||||
CONF_GOTO_M1,
|
||||
CONF_GOTO_M2,
|
||||
CONF_GOTO_M3,
|
||||
CONF_GOTO_M4,
|
||||
CONF_SAVE_M1,
|
||||
CONF_SAVE_M2,
|
||||
CONF_SAVE_M3,
|
||||
CONF_SAVE_M4,
|
||||
CONF_STEP_UP,
|
||||
CONF_STEP_DOWN,
|
||||
CONF_STOP,
|
||||
CONF_GOTO_MAX,
|
||||
CONF_GOTO_MIN,
|
||||
CONF_GOTO_M1,
|
||||
CONF_GOTO_M2,
|
||||
CONF_GOTO_M3,
|
||||
CONF_GOTO_M4,
|
||||
CONF_SAVE_M1,
|
||||
CONF_SAVE_M2,
|
||||
CONF_SAVE_M3,
|
||||
CONF_SAVE_M4,
|
||||
]
|
||||
|
||||
MaidesiteDeskButton = maidesite_desk_ns.class_("MaidesiteDeskButton", button.Button, cg.Component)
|
||||
MaidesiteDeskButton = maidesite_desk_ns.class_(
|
||||
"MaidesiteDeskButton", button.Button, cg.Component
|
||||
)
|
||||
|
||||
CONFIG_SCHEMA = cv.Schema(
|
||||
{
|
||||
cv.GenerateID(CONF_MAIDESITE_DESK_ID): cv.use_id(MaidesiteDeskComponent),
|
||||
|
||||
cv.Optional(CONF_STEP_UP): button.button_schema(
|
||||
MaidesiteDeskButton,
|
||||
),
|
||||
cv.Optional(CONF_STEP_DOWN): button.button_schema(
|
||||
MaidesiteDeskButton,
|
||||
),
|
||||
cv.Optional(CONF_STOP): button.button_schema(
|
||||
MaidesiteDeskButton,
|
||||
),
|
||||
cv.Optional(CONF_GOTO_MAX): button.button_schema(
|
||||
MaidesiteDeskButton,
|
||||
),
|
||||
cv.Optional(CONF_GOTO_MIN): button.button_schema(
|
||||
MaidesiteDeskButton,
|
||||
),
|
||||
cv.Optional(CONF_GOTO_M1): button.button_schema(
|
||||
MaidesiteDeskButton,
|
||||
),
|
||||
cv.Optional(CONF_GOTO_M2): button.button_schema(
|
||||
MaidesiteDeskButton,
|
||||
),
|
||||
cv.Optional(CONF_GOTO_M3): button.button_schema(
|
||||
MaidesiteDeskButton,
|
||||
),
|
||||
cv.Optional(CONF_GOTO_M4): button.button_schema(
|
||||
MaidesiteDeskButton,
|
||||
),
|
||||
cv.Optional(CONF_SAVE_M1): button.button_schema(
|
||||
MaidesiteDeskButton,
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
),
|
||||
cv.Optional(CONF_SAVE_M2): button.button_schema(
|
||||
MaidesiteDeskButton,
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
),
|
||||
cv.Optional(CONF_SAVE_M3): button.button_schema(
|
||||
MaidesiteDeskButton,
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
),
|
||||
cv.Optional(CONF_SAVE_M4): button.button_schema(
|
||||
MaidesiteDeskButton,
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
),
|
||||
}
|
||||
{
|
||||
cv.GenerateID(CONF_MAIDESITE_DESK_ID): cv.use_id(MaidesiteDeskComponent),
|
||||
cv.Optional(CONF_STEP_UP): button.button_schema(
|
||||
MaidesiteDeskButton,
|
||||
),
|
||||
cv.Optional(CONF_STEP_DOWN): button.button_schema(
|
||||
MaidesiteDeskButton,
|
||||
),
|
||||
cv.Optional(CONF_STOP): button.button_schema(
|
||||
MaidesiteDeskButton,
|
||||
),
|
||||
cv.Optional(CONF_GOTO_MAX): button.button_schema(
|
||||
MaidesiteDeskButton,
|
||||
),
|
||||
cv.Optional(CONF_GOTO_MIN): button.button_schema(
|
||||
MaidesiteDeskButton,
|
||||
),
|
||||
cv.Optional(CONF_GOTO_M1): button.button_schema(
|
||||
MaidesiteDeskButton,
|
||||
),
|
||||
cv.Optional(CONF_GOTO_M2): button.button_schema(
|
||||
MaidesiteDeskButton,
|
||||
),
|
||||
cv.Optional(CONF_GOTO_M3): button.button_schema(
|
||||
MaidesiteDeskButton,
|
||||
),
|
||||
cv.Optional(CONF_GOTO_M4): button.button_schema(
|
||||
MaidesiteDeskButton,
|
||||
),
|
||||
cv.Optional(CONF_SAVE_M1): button.button_schema(
|
||||
MaidesiteDeskButton,
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
),
|
||||
cv.Optional(CONF_SAVE_M2): button.button_schema(
|
||||
MaidesiteDeskButton,
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
),
|
||||
cv.Optional(CONF_SAVE_M3): button.button_schema(
|
||||
MaidesiteDeskButton,
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
),
|
||||
cv.Optional(CONF_SAVE_M4): button.button_schema(
|
||||
MaidesiteDeskButton,
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
),
|
||||
}
|
||||
).extend(cv.COMPONENT_SCHEMA)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
hub = await cg.get_variable(config[CONF_MAIDESITE_DESK_ID])
|
||||
for index, key in enumerate(TYPES):
|
||||
if child_config := config.get(key):
|
||||
var = await button.new_button(child_config)
|
||||
await cg.register_component(var, child_config)
|
||||
await cg.register_parented(var, config[CONF_MAIDESITE_DESK_ID])
|
||||
cg.add(getattr(hub, f"set_{key}_button")(var))
|
||||
cg.add(var.set_id(index))
|
||||
hub = await cg.get_variable(config[CONF_MAIDESITE_DESK_ID])
|
||||
for index, key in enumerate(TYPES):
|
||||
if child_config := config.get(key):
|
||||
var = await button.new_button(child_config)
|
||||
await cg.register_component(var, child_config)
|
||||
await cg.register_parented(var, config[CONF_MAIDESITE_DESK_ID])
|
||||
cg.add(getattr(hub, f"set_{key}_button")(var))
|
||||
cg.add(var.set_id(index))
|
||||
|
|
|
|||
|
|
@ -1,22 +1,17 @@
|
|||
#include "maidesite_desk_button.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace maidesite_desk {
|
||||
static const char* const TAG = "maidesite_desk.button";
|
||||
|
||||
namespace esphome
|
||||
{
|
||||
namespace maidesite_desk
|
||||
{
|
||||
static const char *const TAG = "maidesite_desk.button";
|
||||
void MaidesiteDeskButton::dump_config() {
|
||||
LOG_BUTTON("", "Maidesite Desk Button", this);
|
||||
delay(10);
|
||||
}
|
||||
|
||||
void MaidesiteDeskButton::dump_config()
|
||||
{
|
||||
LOG_BUTTON("", "Maidesite Desk Button", this);
|
||||
delay(10);
|
||||
}
|
||||
|
||||
void MaidesiteDeskButton::press_action()
|
||||
{
|
||||
this->parent_->button_press_action(this);
|
||||
}
|
||||
} // namespace maidesite_desk
|
||||
} // namespace esphome
|
||||
void MaidesiteDeskButton::press_action() {
|
||||
this->parent_->button_press_action(this);
|
||||
}
|
||||
} // namespace maidesite_desk
|
||||
} // namespace esphome
|
||||
|
|
|
|||
|
|
@ -3,21 +3,19 @@
|
|||
#include "esphome/core/component.h"
|
||||
#include "../maidesite_desk.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace maidesite_desk {
|
||||
class MaidesiteDeskButton : public button::Button, public Component, public Parented<MaidesiteDeskComponent> {
|
||||
public:
|
||||
MaidesiteDeskButton() = default;
|
||||
void dump_config() override;
|
||||
void set_id(int id) {
|
||||
this->id_ = id;
|
||||
}
|
||||
|
||||
namespace esphome
|
||||
{
|
||||
namespace maidesite_desk
|
||||
{
|
||||
class MaidesiteDeskButton : public button::Button, public Component, public Parented<MaidesiteDeskComponent>
|
||||
{
|
||||
public:
|
||||
MaidesiteDeskButton() = default;
|
||||
void dump_config() override;
|
||||
void set_id(int id) { this->id_ = id; }
|
||||
|
||||
protected:
|
||||
void press_action() override;
|
||||
int id_;
|
||||
};
|
||||
} // namespace maidesite_desk
|
||||
} // namespace esphome
|
||||
protected:
|
||||
void press_action() override;
|
||||
int id_;
|
||||
};
|
||||
} // namespace maidesite_desk
|
||||
} // namespace esphome
|
||||
|
|
|
|||
|
|
@ -1,397 +1,359 @@
|
|||
#include "maidesite_desk.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace maidesite_desk {
|
||||
static const char* const TAG = "maidesite_desk";
|
||||
|
||||
namespace esphome
|
||||
{
|
||||
namespace maidesite_desk
|
||||
{
|
||||
static const char *const TAG = "maidesite_desk";
|
||||
void MaidesiteDeskComponent::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, "Maidesite Desk");
|
||||
delay(10);
|
||||
}
|
||||
|
||||
void MaidesiteDeskComponent::dump_config()
|
||||
{
|
||||
ESP_LOGCONFIG(TAG, "Maidesite Desk");
|
||||
void MaidesiteDeskComponent::setup() {
|
||||
ESP_LOGCONFIG(TAG, "Setting up Maidesite Desk ...");
|
||||
delay(10);
|
||||
this->check_uart_settings(9600);
|
||||
this->request_physical_limits();
|
||||
this->request_limits();
|
||||
this->request_settings();
|
||||
}
|
||||
|
||||
void MaidesiteDeskComponent::loop() {
|
||||
// This is a very simple method of receiving messages from the desk.
|
||||
// It will fail on messages that contain the value 0x7E in their payload.
|
||||
// But it is super simple and works for the messages we care about.
|
||||
// Read message:
|
||||
// format: 0xF2 0xF2 [command] [param_count] [[param] ...] [checksum] 0x7E
|
||||
// checksum: sum of [command], [param_count] and all [param]s
|
||||
|
||||
uint8_t oneByte;
|
||||
while (this->available()) {
|
||||
this->read_byte(&oneByte);
|
||||
|
||||
// Message shall start with 0xF2, if not skip this byte
|
||||
if (!this->response_receiving_) {
|
||||
if (oneByte != 0xF2)
|
||||
continue;
|
||||
this->response_receiving_ = true;
|
||||
}
|
||||
// Add current byte to message buffer
|
||||
this->response_message_.push_back(oneByte);
|
||||
|
||||
// Discard message if 2. byte is not 0xF2
|
||||
if (this->response_message_.size() == 2 && oneByte != 0xF2) {
|
||||
ESP_LOGW(TAG, "Invalid response message: 2. byte is 0x%02X but expexted is 0xF2", oneByte);
|
||||
delay(10);
|
||||
this->response_message_.clear();
|
||||
this->response_receiving_ = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
void MaidesiteDeskComponent::setup()
|
||||
{
|
||||
ESP_LOGCONFIG(TAG, "Setting up Maidesite Desk ...");
|
||||
// Discard message if it is too long
|
||||
if (this->response_message_.size() > 10) {
|
||||
ESP_LOGW(TAG, "Response message too long: expected not more than 10 bytes");
|
||||
delay(10);
|
||||
this->check_uart_settings(9600);
|
||||
this->request_physical_limits();
|
||||
this->request_limits();
|
||||
this->request_settings();
|
||||
this->response_message_.clear();
|
||||
this->response_receiving_ = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
void MaidesiteDeskComponent::loop()
|
||||
{
|
||||
// This is a very simple method of receiving messages from the desk.
|
||||
// It will fail on messages that contain the value 0x7E in their payload.
|
||||
// But it is super simple and works for the messages we care about.
|
||||
// Read message:
|
||||
// format: 0xF2 0xF2 [command] [param_count] [[param] ...] [checksum] 0x7E
|
||||
// checksum: sum of [command], [param_count] and all [param]s
|
||||
|
||||
uint8_t oneByte;
|
||||
while (this->available())
|
||||
{
|
||||
this->read_byte(&oneByte);
|
||||
|
||||
// Message shall start with 0xF2, if not skip this byte
|
||||
if (!this->response_receiving_)
|
||||
{
|
||||
if (oneByte != 0xF2)
|
||||
continue;
|
||||
this->response_receiving_ = true;
|
||||
}
|
||||
// Add current byte to message buffer
|
||||
this->response_message_.push_back(oneByte);
|
||||
|
||||
// Discard message if 2. byte is not 0xF2
|
||||
if (this->response_message_.size() == 2 && oneByte != 0xF2)
|
||||
{
|
||||
ESP_LOGW(TAG, "Invalid response message: 2. byte is 0x%02X but expexted is 0xF2", oneByte);
|
||||
delay(10);
|
||||
this->response_message_.clear();
|
||||
this->response_receiving_ = false;
|
||||
continue;
|
||||
}
|
||||
// Discard message if it is too long
|
||||
if (this->response_message_.size() > 10)
|
||||
{
|
||||
ESP_LOGW(TAG, "Response message too long: expected not more than 10 bytes");
|
||||
delay(10);
|
||||
this->response_message_.clear();
|
||||
this->response_receiving_ = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Decode message if message is complete (last byte shall be 0x7E)
|
||||
if (oneByte == 0x7E)
|
||||
{
|
||||
this->log_uart_hex("<<<", this->response_message_, ',');
|
||||
this->decode_response(this->response_message_);
|
||||
this->response_message_.clear();
|
||||
this->response_receiving_ = false;
|
||||
}
|
||||
}
|
||||
// Decode message if message is complete (last byte shall be 0x7E)
|
||||
if (oneByte == 0x7E) {
|
||||
this->log_uart_hex("<<<", this->response_message_, ',');
|
||||
this->decode_response(this->response_message_);
|
||||
this->response_message_.clear();
|
||||
this->response_receiving_ = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MaidesiteDeskComponent::log_uart_hex(std::string prefix, std::vector<uint8_t> bytes, uint8_t separator)
|
||||
{
|
||||
if (this->log_uart_msg_ == false) return;
|
||||
void MaidesiteDeskComponent::log_uart_hex(std::string prefix, std::vector<uint8_t> bytes, uint8_t separator) {
|
||||
if (this->log_uart_msg_ == false)
|
||||
return;
|
||||
|
||||
std::string logStr;
|
||||
char buffer[5];
|
||||
std::string logStr;
|
||||
char buffer[5];
|
||||
|
||||
for (size_t i = 0; i < bytes.size(); i++)
|
||||
{
|
||||
if (i > 0) logStr += separator;
|
||||
sprintf(buffer, "%02X", bytes[i]);
|
||||
logStr += buffer;
|
||||
}
|
||||
for (size_t i = 0; i < logStr.length(); i += UART_LOG_CHUNK_SIZE)
|
||||
{
|
||||
ESP_LOGI(TAG, "%s %s", prefix.c_str(), logStr.substr(i, UART_LOG_CHUNK_SIZE).c_str());
|
||||
delay(10);
|
||||
}
|
||||
for (size_t i = 0; i < bytes.size(); i++) {
|
||||
if (i > 0)
|
||||
logStr += separator;
|
||||
sprintf(buffer, "%02X", bytes[i]);
|
||||
logStr += buffer;
|
||||
}
|
||||
for (size_t i = 0; i < logStr.length(); i += UART_LOG_CHUNK_SIZE) {
|
||||
ESP_LOGI(TAG, "%s %s", prefix.c_str(), logStr.substr(i, UART_LOG_CHUNK_SIZE).c_str());
|
||||
delay(10);
|
||||
}
|
||||
}
|
||||
|
||||
void MaidesiteDeskComponent::decode_response(std::vector<uint8_t> message) {
|
||||
// ToDo: Add checksum check
|
||||
|
||||
switch (message[2]) {
|
||||
case 0x01:
|
||||
ESP_LOGI(TAG, "Set height to 0x%0X%0X", message[4], message[5]);
|
||||
delay(10);
|
||||
|
||||
float new_height;
|
||||
new_height = byte2float(message[4], message[5]);
|
||||
if (new_height == this->current_height_)
|
||||
return;
|
||||
this->current_height_ = new_height;
|
||||
if (this->height_abs_sensor_ != nullptr)
|
||||
this->height_abs_sensor_->publish_state(this->current_height_);
|
||||
if (this->height_abs_number_ != nullptr)
|
||||
this->height_abs_number_->publish_state(this->current_height_);
|
||||
|
||||
if (this->height_pct_sensor_ != nullptr && limit_max_ != 0)
|
||||
this->height_pct_sensor_->publish_state((this->current_height_ - this->limit_min_) /
|
||||
(this->limit_max_ - this->limit_min_) * 100);
|
||||
if (this->height_pct_number_ != nullptr && limit_max_ != 0)
|
||||
this->height_pct_number_->publish_state(
|
||||
roundf((this->current_height_ - this->limit_min_) / (this->limit_max_ - this->limit_min_) * 1000) / 10);
|
||||
break;
|
||||
|
||||
case 0x20:
|
||||
ESP_LOGI(TAG, "Set limits to 0x%0X max=%i min=%i", message[4], (message[5] & 1), (message[4] >> 4));
|
||||
delay(10);
|
||||
|
||||
if ((message[4] & 1) == 0) { // low nibble 0 -> no max limit, use physical_max_
|
||||
this->limit_max_ = this->physical_max_;
|
||||
if (this->height_max_sensor_ != nullptr)
|
||||
this->height_max_sensor_->publish_state(this->limit_max_);
|
||||
if (height_abs_number_ != nullptr)
|
||||
this->height_abs_number_->traits.set_max_value(this->limit_max_);
|
||||
}
|
||||
|
||||
void MaidesiteDeskComponent::decode_response(std::vector<uint8_t> message)
|
||||
{
|
||||
// ToDo: Add checksum check
|
||||
|
||||
switch (message[2])
|
||||
{
|
||||
case 0x01:
|
||||
ESP_LOGI(TAG, "Set height to 0x%0X%0X", message[4], message[5]);
|
||||
delay(10);
|
||||
|
||||
float new_height;
|
||||
new_height = byte2float(message[4], message[5]);
|
||||
if (new_height == this->current_height_)
|
||||
return;
|
||||
this->current_height_ = new_height;
|
||||
if (this->height_abs_sensor_ != nullptr)
|
||||
this->height_abs_sensor_->publish_state(this->current_height_);
|
||||
if (this->height_abs_number_ != nullptr)
|
||||
this->height_abs_number_->publish_state(this->current_height_);
|
||||
|
||||
if (this->height_pct_sensor_ != nullptr && limit_max_ != 0)
|
||||
this->height_pct_sensor_->publish_state((this->current_height_ - this->limit_min_) / (this->limit_max_ - this->limit_min_) * 100);
|
||||
if (this->height_pct_number_ != nullptr && limit_max_ != 0)
|
||||
this->height_pct_number_->publish_state(roundf((this->current_height_ - this->limit_min_) / (this->limit_max_ - this->limit_min_) * 1000) / 10);
|
||||
break;
|
||||
|
||||
case 0x20:
|
||||
ESP_LOGI(TAG, "Set limits to 0x%0X max=%i min=%i", message[4], (message[5] & 1), (message[4] >> 4));
|
||||
delay(10);
|
||||
|
||||
if ((message[4] & 1) == 0)
|
||||
{ // low nibble 0 -> no max limit, use physical_max_
|
||||
this->limit_max_ = this->physical_max_;
|
||||
if (this->height_max_sensor_ != nullptr)
|
||||
this->height_max_sensor_->publish_state(this->limit_max_);
|
||||
if (height_abs_number_ != nullptr)
|
||||
this->height_abs_number_->traits.set_max_value(this->limit_max_);
|
||||
}
|
||||
if ((message[4] >> 4) == 0)
|
||||
{ // high nibble 0 -> no min limit, use physical_min_
|
||||
this->limit_min_ = this->physical_min_;
|
||||
if (this->height_min_sensor_ != nullptr)
|
||||
this->height_min_sensor_->publish_state(limit_min_);
|
||||
if (height_abs_number_ != nullptr)
|
||||
this->height_abs_number_->traits.set_min_value(limit_min_);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x07:
|
||||
ESP_LOGI(TAG, "Set physical limits to min=0x%02X%02X max=0x%02X%02X", message[4], message[5], message[6], message[7]);
|
||||
delay(10);
|
||||
|
||||
this->physical_max_ = this->byte2float(message[4], message[5]);
|
||||
this->physical_min_ = this->byte2float(message[6], message[7]);
|
||||
break;
|
||||
|
||||
case 0x21:
|
||||
ESP_LOGI(TAG, "Set max. height to 0x%02X%02X", message[4], message[5]);
|
||||
delay(10);
|
||||
|
||||
this->limit_max_ = this->byte2float(message[4], message[5]);
|
||||
if (this->height_max_sensor_ != nullptr)
|
||||
this->height_max_sensor_->publish_state(limit_max_);
|
||||
if (height_abs_number_ != nullptr)
|
||||
this->height_abs_number_->traits.set_max_value(limit_max_);
|
||||
break;
|
||||
|
||||
case 0x22:
|
||||
ESP_LOGI(TAG, "Set min. height to 0x%02X%02X", message[4], message[5]);
|
||||
delay(10);
|
||||
|
||||
this->limit_min_ = this->byte2float(message[4], message[5]);
|
||||
if (this->height_min_sensor_ != nullptr)
|
||||
this->height_min_sensor_->publish_state(limit_min_);
|
||||
if (height_abs_number_ != nullptr)
|
||||
this->height_abs_number_->traits.set_min_value(limit_min_);
|
||||
break;
|
||||
|
||||
case 0x25:
|
||||
ESP_LOGI(TAG, "Set position m1 to 0x%02X%02X", message[4], message[5]);
|
||||
delay(10);
|
||||
|
||||
if (this->position_m1_sensor_ != nullptr)
|
||||
this->position_m1_sensor_->publish_state(this->byte2float(message[4], message[5]));
|
||||
break;
|
||||
|
||||
case 0x26:
|
||||
ESP_LOGI(TAG, "Set position m2 to 0x%02X%02X", message[4], message[5]);
|
||||
delay(10);
|
||||
|
||||
if (this->position_m2_sensor_ != nullptr)
|
||||
this->position_m2_sensor_->publish_state(this->byte2float(message[4], message[5]));
|
||||
break;
|
||||
|
||||
case 0x27:
|
||||
ESP_LOGI(TAG, "Set position m3 to 0x%02X%02X", message[4], message[5]);
|
||||
delay(10);
|
||||
|
||||
if (this->position_m3_sensor_ != nullptr)
|
||||
this->position_m3_sensor_->publish_state(this->byte2float(message[4], message[5]));
|
||||
break;
|
||||
|
||||
case 0x28:
|
||||
ESP_LOGI(TAG, "Set position m4 to 0x%02X%02X", message[4], message[5]);
|
||||
delay(10);
|
||||
|
||||
if (this->position_m4_sensor_ != nullptr)
|
||||
this->position_m4_sensor_->publish_state(this->byte2float(message[4], message[5]));
|
||||
break;
|
||||
|
||||
// case 0x0E:
|
||||
// ESP_LOGI(TAG, "units 0x%02X", message[4]);
|
||||
// if (units != nullptr)
|
||||
// units->publish_state(byte2float(message[4], message[5]));
|
||||
// break;
|
||||
|
||||
default:
|
||||
ESP_LOGI(TAG, "Received unknown message");
|
||||
delay(10);
|
||||
}
|
||||
if ((message[4] >> 4) == 0) { // high nibble 0 -> no min limit, use physical_min_
|
||||
this->limit_min_ = this->physical_min_;
|
||||
if (this->height_min_sensor_ != nullptr)
|
||||
this->height_min_sensor_->publish_state(limit_min_);
|
||||
if (height_abs_number_ != nullptr)
|
||||
this->height_abs_number_->traits.set_min_value(limit_min_);
|
||||
}
|
||||
break;
|
||||
|
||||
float MaidesiteDeskComponent::byte2float(int high, int low)
|
||||
{
|
||||
return static_cast<float>((high << 8) + low) / 10;
|
||||
}
|
||||
case 0x07:
|
||||
ESP_LOGI(TAG, "Set physical limits to min=0x%02X%02X max=0x%02X%02X", message[4], message[5], message[6],
|
||||
message[7]);
|
||||
delay(10);
|
||||
|
||||
// Write message:
|
||||
// format: 0xF1 0xF1 [command] [param_count] [[param] ...] [checksum] 0x7E
|
||||
// checksum: sum of [command], [param_count] and all [param]s
|
||||
void MaidesiteDeskComponent::send_simple_command(unsigned char cmd)
|
||||
{
|
||||
this->request_message_.clear();
|
||||
this->request_message_.insert(this->request_message_.end(), { 0xF1, 0xF1, cmd, 0x00, cmd, 0x7E });
|
||||
this->write_array(this->request_message_);
|
||||
this->log_uart_hex(">>>", this->request_message_, ',');
|
||||
delay(100); // NOLINT
|
||||
}
|
||||
this->physical_max_ = this->byte2float(message[4], message[5]);
|
||||
this->physical_min_ = this->byte2float(message[6], message[7]);
|
||||
break;
|
||||
|
||||
void MaidesiteDeskComponent::send_2byte_command(unsigned char cmd, unsigned char high_byte, unsigned char low_byte)
|
||||
{
|
||||
// ToDo: make one function of send_simple_command and send_2byte_command
|
||||
case 0x21:
|
||||
ESP_LOGI(TAG, "Set max. height to 0x%02X%02X", message[4], message[5]);
|
||||
delay(10);
|
||||
|
||||
unsigned char checksum = cmd + 2 + high_byte + low_byte;
|
||||
this->request_message_.clear();
|
||||
this->request_message_.insert(this->request_message_.end(), { 0xF1, 0xF1, cmd, 0x02, high_byte, low_byte, checksum, 0x7E });
|
||||
this->write_array(this->request_message_);
|
||||
this->log_uart_hex(">>>", this->request_message_, ',');
|
||||
delay(100); // NOLINT
|
||||
}
|
||||
this->limit_max_ = this->byte2float(message[4], message[5]);
|
||||
if (this->height_max_sensor_ != nullptr)
|
||||
this->height_max_sensor_->publish_state(limit_max_);
|
||||
if (height_abs_number_ != nullptr)
|
||||
this->height_abs_number_->traits.set_max_value(limit_max_);
|
||||
break;
|
||||
|
||||
void MaidesiteDeskComponent::step_up()
|
||||
{
|
||||
this->send_simple_command(0x01);
|
||||
}
|
||||
case 0x22:
|
||||
ESP_LOGI(TAG, "Set min. height to 0x%02X%02X", message[4], message[5]);
|
||||
delay(10);
|
||||
|
||||
void MaidesiteDeskComponent::step_down()
|
||||
{
|
||||
this->send_simple_command(0x02);
|
||||
}
|
||||
this->limit_min_ = this->byte2float(message[4], message[5]);
|
||||
if (this->height_min_sensor_ != nullptr)
|
||||
this->height_min_sensor_->publish_state(limit_min_);
|
||||
if (height_abs_number_ != nullptr)
|
||||
this->height_abs_number_->traits.set_min_value(limit_min_);
|
||||
break;
|
||||
|
||||
void MaidesiteDeskComponent::stop()
|
||||
{
|
||||
this->send_simple_command(0x2B);
|
||||
}
|
||||
case 0x25:
|
||||
ESP_LOGI(TAG, "Set position m1 to 0x%02X%02X", message[4], message[5]);
|
||||
delay(10);
|
||||
|
||||
void MaidesiteDeskComponent::goto_mem_position(int pos)
|
||||
{
|
||||
switch (pos)
|
||||
{
|
||||
case 1:
|
||||
this->send_simple_command(0x05);
|
||||
break;
|
||||
case 2:
|
||||
this->send_simple_command(0x06);
|
||||
break;
|
||||
case 3:
|
||||
this->send_simple_command(0x27);
|
||||
break;
|
||||
case 4:
|
||||
this->send_simple_command(0x28);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (this->position_m1_sensor_ != nullptr)
|
||||
this->position_m1_sensor_->publish_state(this->byte2float(message[4], message[5]));
|
||||
break;
|
||||
|
||||
void MaidesiteDeskComponent::save_mem_position(int pos)
|
||||
{
|
||||
switch (pos)
|
||||
{
|
||||
case 1:
|
||||
this->send_simple_command(0x03);
|
||||
break;
|
||||
case 2:
|
||||
this->send_simple_command(0x04);
|
||||
break;
|
||||
case 3:
|
||||
this->send_simple_command(0x25);
|
||||
break;
|
||||
case 4:
|
||||
this->send_simple_command(0x26);
|
||||
break;
|
||||
}
|
||||
}
|
||||
case 0x26:
|
||||
ESP_LOGI(TAG, "Set position m2 to 0x%02X%02X", message[4], message[5]);
|
||||
delay(10);
|
||||
|
||||
void MaidesiteDeskComponent::request_physical_limits()
|
||||
{
|
||||
this->send_simple_command(0x0C);
|
||||
}
|
||||
if (this->position_m2_sensor_ != nullptr)
|
||||
this->position_m2_sensor_->publish_state(this->byte2float(message[4], message[5]));
|
||||
break;
|
||||
|
||||
void MaidesiteDeskComponent::request_limits()
|
||||
{
|
||||
this->send_simple_command(0x20);
|
||||
}
|
||||
case 0x27:
|
||||
ESP_LOGI(TAG, "Set position m3 to 0x%02X%02X", message[4], message[5]);
|
||||
delay(10);
|
||||
|
||||
void MaidesiteDeskComponent::request_settings()
|
||||
{
|
||||
this->send_simple_command(0x07);
|
||||
}
|
||||
if (this->position_m3_sensor_ != nullptr)
|
||||
this->position_m3_sensor_->publish_state(this->byte2float(message[4], message[5]));
|
||||
break;
|
||||
|
||||
void MaidesiteDeskComponent::request_move_to()
|
||||
{
|
||||
this->send_simple_command(0x1B);
|
||||
}
|
||||
case 0x28:
|
||||
ESP_LOGI(TAG, "Set position m4 to 0x%02X%02X", message[4], message[5]);
|
||||
delay(10);
|
||||
|
||||
void MaidesiteDeskComponent::goto_max_position()
|
||||
{
|
||||
this->goto_height(limit_max_);
|
||||
}
|
||||
if (this->position_m4_sensor_ != nullptr)
|
||||
this->position_m4_sensor_->publish_state(this->byte2float(message[4], message[5]));
|
||||
break;
|
||||
|
||||
void MaidesiteDeskComponent::goto_min_position()
|
||||
{
|
||||
this->goto_height(limit_min_);
|
||||
}
|
||||
// case 0x0E:
|
||||
// ESP_LOGI(TAG, "units 0x%02X", message[4]);
|
||||
// if (units != nullptr)
|
||||
// units->publish_state(byte2float(message[4], message[5]));
|
||||
// break;
|
||||
|
||||
void MaidesiteDeskComponent::goto_height(float height)
|
||||
{
|
||||
unsigned char high_byte = ((int)height * 10) >> 8;
|
||||
unsigned char low_byte = ((int)height * 10) & 0xFF;
|
||||
default:
|
||||
ESP_LOGI(TAG, "Received unknown message");
|
||||
delay(10);
|
||||
}
|
||||
}
|
||||
|
||||
this->send_2byte_command(0x80, high_byte, low_byte);
|
||||
this->request_move_to();
|
||||
}
|
||||
float MaidesiteDeskComponent::byte2float(int high, int low) {
|
||||
return static_cast<float>((high << 8) + low) / 10;
|
||||
}
|
||||
|
||||
// Write message:
|
||||
// format: 0xF1 0xF1 [command] [param_count] [[param] ...] [checksum] 0x7E
|
||||
// checksum: sum of [command], [param_count] and all [param]s
|
||||
void MaidesiteDeskComponent::send_simple_command(unsigned char cmd) {
|
||||
this->request_message_.clear();
|
||||
this->request_message_.insert(this->request_message_.end(), {0xF1, 0xF1, cmd, 0x00, cmd, 0x7E});
|
||||
this->write_array(this->request_message_);
|
||||
this->log_uart_hex(">>>", this->request_message_, ',');
|
||||
delay(100); // NOLINT
|
||||
}
|
||||
|
||||
void MaidesiteDeskComponent::send_2byte_command(unsigned char cmd, unsigned char high_byte, unsigned char low_byte) {
|
||||
// ToDo: make one function of send_simple_command and send_2byte_command
|
||||
|
||||
unsigned char checksum = cmd + 2 + high_byte + low_byte;
|
||||
this->request_message_.clear();
|
||||
this->request_message_.insert(this->request_message_.end(),
|
||||
{0xF1, 0xF1, cmd, 0x02, high_byte, low_byte, checksum, 0x7E});
|
||||
this->write_array(this->request_message_);
|
||||
this->log_uart_hex(">>>", this->request_message_, ',');
|
||||
delay(100); // NOLINT
|
||||
}
|
||||
|
||||
void MaidesiteDeskComponent::step_up() {
|
||||
this->send_simple_command(0x01);
|
||||
}
|
||||
|
||||
void MaidesiteDeskComponent::step_down() {
|
||||
this->send_simple_command(0x02);
|
||||
}
|
||||
|
||||
void MaidesiteDeskComponent::stop() {
|
||||
this->send_simple_command(0x2B);
|
||||
}
|
||||
|
||||
void MaidesiteDeskComponent::goto_mem_position(int pos) {
|
||||
switch (pos) {
|
||||
case 1:
|
||||
this->send_simple_command(0x05);
|
||||
break;
|
||||
case 2:
|
||||
this->send_simple_command(0x06);
|
||||
break;
|
||||
case 3:
|
||||
this->send_simple_command(0x27);
|
||||
break;
|
||||
case 4:
|
||||
this->send_simple_command(0x28);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void MaidesiteDeskComponent::save_mem_position(int pos) {
|
||||
switch (pos) {
|
||||
case 1:
|
||||
this->send_simple_command(0x03);
|
||||
break;
|
||||
case 2:
|
||||
this->send_simple_command(0x04);
|
||||
break;
|
||||
case 3:
|
||||
this->send_simple_command(0x25);
|
||||
break;
|
||||
case 4:
|
||||
this->send_simple_command(0x26);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void MaidesiteDeskComponent::request_physical_limits() {
|
||||
this->send_simple_command(0x0C);
|
||||
}
|
||||
|
||||
void MaidesiteDeskComponent::request_limits() {
|
||||
this->send_simple_command(0x20);
|
||||
}
|
||||
|
||||
void MaidesiteDeskComponent::request_settings() {
|
||||
this->send_simple_command(0x07);
|
||||
}
|
||||
|
||||
void MaidesiteDeskComponent::request_move_to() {
|
||||
this->send_simple_command(0x1B);
|
||||
}
|
||||
|
||||
void MaidesiteDeskComponent::goto_max_position() {
|
||||
this->goto_height(limit_max_);
|
||||
}
|
||||
|
||||
void MaidesiteDeskComponent::goto_min_position() {
|
||||
this->goto_height(limit_min_);
|
||||
}
|
||||
|
||||
void MaidesiteDeskComponent::goto_height(float height) {
|
||||
unsigned char high_byte = ((int)height * 10) >> 8;
|
||||
unsigned char low_byte = ((int)height * 10) & 0xFF;
|
||||
|
||||
this->send_2byte_command(0x80, high_byte, low_byte);
|
||||
this->request_move_to();
|
||||
}
|
||||
|
||||
#ifdef USE_BUTTON
|
||||
void MaidesiteDeskComponent::button_press_action(button::Button* object)
|
||||
{
|
||||
if (object == step_up_button_)
|
||||
this->step_up();
|
||||
else if (object == step_down_button_)
|
||||
this->step_down();
|
||||
else if (object == stop_button_)
|
||||
this->stop();
|
||||
else if (object == goto_max_button_)
|
||||
this->goto_max_position();
|
||||
else if (object == goto_min_button_)
|
||||
this->goto_min_position();
|
||||
else if (object == goto_m1_button_)
|
||||
this->goto_mem_position(1);
|
||||
else if (object == goto_m2_button_)
|
||||
this->goto_mem_position(2);
|
||||
else if (object == goto_m3_button_)
|
||||
this->goto_mem_position(3);
|
||||
else if (object == goto_m4_button_)
|
||||
this->goto_mem_position(4);
|
||||
else if (object == save_m1_button_)
|
||||
{
|
||||
this->save_mem_position(1);
|
||||
this->request_settings();
|
||||
}
|
||||
else if (object == save_m2_button_)
|
||||
{
|
||||
this->save_mem_position(2);
|
||||
this->request_settings();
|
||||
}
|
||||
else if (object == save_m3_button_)
|
||||
{
|
||||
this->save_mem_position(3);
|
||||
this->request_settings();
|
||||
}
|
||||
else if (object == save_m4_button_)
|
||||
{
|
||||
this->save_mem_position(4);
|
||||
this->request_settings();
|
||||
}
|
||||
}
|
||||
void MaidesiteDeskComponent::button_press_action(button::Button* object) {
|
||||
if (object == step_up_button_)
|
||||
this->step_up();
|
||||
else if (object == step_down_button_)
|
||||
this->step_down();
|
||||
else if (object == stop_button_)
|
||||
this->stop();
|
||||
else if (object == goto_max_button_)
|
||||
this->goto_max_position();
|
||||
else if (object == goto_min_button_)
|
||||
this->goto_min_position();
|
||||
else if (object == goto_m1_button_)
|
||||
this->goto_mem_position(1);
|
||||
else if (object == goto_m2_button_)
|
||||
this->goto_mem_position(2);
|
||||
else if (object == goto_m3_button_)
|
||||
this->goto_mem_position(3);
|
||||
else if (object == goto_m4_button_)
|
||||
this->goto_mem_position(4);
|
||||
else if (object == save_m1_button_) {
|
||||
this->save_mem_position(1);
|
||||
this->request_settings();
|
||||
} else if (object == save_m2_button_) {
|
||||
this->save_mem_position(2);
|
||||
this->request_settings();
|
||||
} else if (object == save_m3_button_) {
|
||||
this->save_mem_position(3);
|
||||
this->request_settings();
|
||||
} else if (object == save_m4_button_) {
|
||||
this->save_mem_position(4);
|
||||
this->request_settings();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_NUMBER
|
||||
void MaidesiteDeskComponent::number_control(number::Number* object, float value)
|
||||
{
|
||||
if (object == height_abs_number_)
|
||||
this->goto_height(value);
|
||||
else if (object == height_pct_number_)
|
||||
if (limit_max_ > 0 && limit_max_ > limit_min_)
|
||||
this->goto_height((limit_max_ - limit_min_) * value / 100 + limit_min_);
|
||||
}
|
||||
void MaidesiteDeskComponent::number_control(number::Number* object, float value) {
|
||||
if (object == height_abs_number_)
|
||||
this->goto_height(value);
|
||||
else if (object == height_pct_number_)
|
||||
if (limit_max_ > 0 && limit_max_ > limit_min_)
|
||||
this->goto_height((limit_max_ - limit_min_) * value / 100 + limit_min_);
|
||||
}
|
||||
#endif
|
||||
} // namespace maidesite_desk
|
||||
} // namespace esphome
|
||||
} // namespace maidesite_desk
|
||||
} // namespace esphome
|
||||
|
|
|
|||
|
|
@ -17,98 +17,98 @@
|
|||
|
||||
#define UART_LOG_CHUNK_SIZE 153
|
||||
|
||||
namespace esphome {
|
||||
namespace maidesite_desk {
|
||||
|
||||
namespace esphome
|
||||
{
|
||||
namespace maidesite_desk
|
||||
{
|
||||
|
||||
class MaidesiteDeskComponent : public Component, public uart::UARTDevice
|
||||
{
|
||||
public:
|
||||
class MaidesiteDeskComponent : public Component, public uart::UARTDevice {
|
||||
public:
|
||||
#ifdef USE_SENSOR
|
||||
SUB_SENSOR(unit);
|
||||
SUB_SENSOR(height_abs);
|
||||
SUB_SENSOR(height_pct);
|
||||
SUB_SENSOR(height_min);
|
||||
SUB_SENSOR(height_max);
|
||||
SUB_SENSOR(position_m1);
|
||||
SUB_SENSOR(position_m2);
|
||||
SUB_SENSOR(position_m3);
|
||||
SUB_SENSOR(position_m4);
|
||||
SUB_SENSOR(unit);
|
||||
SUB_SENSOR(height_abs);
|
||||
SUB_SENSOR(height_pct);
|
||||
SUB_SENSOR(height_min);
|
||||
SUB_SENSOR(height_max);
|
||||
SUB_SENSOR(position_m1);
|
||||
SUB_SENSOR(position_m2);
|
||||
SUB_SENSOR(position_m3);
|
||||
SUB_SENSOR(position_m4);
|
||||
#endif
|
||||
#ifdef USE_BUTTON
|
||||
SUB_BUTTON(unit);
|
||||
SUB_BUTTON(step_up);
|
||||
SUB_BUTTON(step_down);
|
||||
SUB_BUTTON(stop);
|
||||
SUB_BUTTON(goto_max);
|
||||
SUB_BUTTON(goto_min);
|
||||
SUB_BUTTON(goto_m1);
|
||||
SUB_BUTTON(goto_m2);
|
||||
SUB_BUTTON(goto_m3);
|
||||
SUB_BUTTON(goto_m4);
|
||||
SUB_BUTTON(save_m1);
|
||||
SUB_BUTTON(save_m2);
|
||||
SUB_BUTTON(save_m3);
|
||||
SUB_BUTTON(save_m4);
|
||||
SUB_BUTTON(unit);
|
||||
SUB_BUTTON(step_up);
|
||||
SUB_BUTTON(step_down);
|
||||
SUB_BUTTON(stop);
|
||||
SUB_BUTTON(goto_max);
|
||||
SUB_BUTTON(goto_min);
|
||||
SUB_BUTTON(goto_m1);
|
||||
SUB_BUTTON(goto_m2);
|
||||
SUB_BUTTON(goto_m3);
|
||||
SUB_BUTTON(goto_m4);
|
||||
SUB_BUTTON(save_m1);
|
||||
SUB_BUTTON(save_m2);
|
||||
SUB_BUTTON(save_m3);
|
||||
SUB_BUTTON(save_m4);
|
||||
|
||||
void button_press_action(button::Button* object);
|
||||
void button_press_action(button::Button* object);
|
||||
#endif
|
||||
#ifdef USE_NUMBER
|
||||
SUB_NUMBER(height_abs);
|
||||
SUB_NUMBER(height_pct);
|
||||
SUB_NUMBER(height_abs);
|
||||
SUB_NUMBER(height_pct);
|
||||
|
||||
void number_control(number::Number* object, float value);
|
||||
void number_control(number::Number* object, float value);
|
||||
#endif
|
||||
|
||||
MaidesiteDeskComponent() = default;
|
||||
// base class functions
|
||||
float get_setup_priority() const override { return setup_priority::LATE; }
|
||||
void dump_config() override;
|
||||
void setup() override;
|
||||
void loop() override;
|
||||
// option functions
|
||||
void set_log_uart_msg(bool enable) { this->log_uart_msg_ = enable; }
|
||||
// functions to use in lambdas
|
||||
void request_physical_limits();
|
||||
void request_limits();
|
||||
void request_settings();
|
||||
void request_move_to();
|
||||
void step_up();
|
||||
void step_down();
|
||||
void stop();
|
||||
void goto_height(float height);
|
||||
void goto_min_position();
|
||||
void goto_max_position();
|
||||
void goto_mem_position(int pos);
|
||||
void save_mem_position(int pos);
|
||||
MaidesiteDeskComponent() = default;
|
||||
// base class functions
|
||||
float get_setup_priority() const override {
|
||||
return setup_priority::LATE;
|
||||
}
|
||||
void dump_config() override;
|
||||
void setup() override;
|
||||
void loop() override;
|
||||
// option functions
|
||||
void set_log_uart_msg(bool enable) {
|
||||
this->log_uart_msg_ = enable;
|
||||
}
|
||||
// functions to use in lambdas
|
||||
void request_physical_limits();
|
||||
void request_limits();
|
||||
void request_settings();
|
||||
void request_move_to();
|
||||
void step_up();
|
||||
void step_down();
|
||||
void stop();
|
||||
void goto_height(float height);
|
||||
void goto_min_position();
|
||||
void goto_max_position();
|
||||
void goto_mem_position(int pos);
|
||||
void save_mem_position(int pos);
|
||||
|
||||
// variables to use in lambdas
|
||||
std::vector<uint8_t> response_message_;
|
||||
// variables to use in lambdas
|
||||
std::vector<uint8_t> response_message_;
|
||||
|
||||
protected:
|
||||
// uart message functions
|
||||
void decode_response(std::vector<uint8_t> message);
|
||||
void send_simple_command(unsigned char cmd);
|
||||
void send_2byte_command(unsigned char cmd, unsigned char high_byte, unsigned char low_byte);
|
||||
float byte2float(int high, int low);
|
||||
void log_uart_hex(std::string prefix, std::vector<uint8_t> bytes, uint8_t separator);
|
||||
protected:
|
||||
// uart message functions
|
||||
void decode_response(std::vector<uint8_t> message);
|
||||
void send_simple_command(unsigned char cmd);
|
||||
void send_2byte_command(unsigned char cmd, unsigned char high_byte, unsigned char low_byte);
|
||||
float byte2float(int high, int low);
|
||||
void log_uart_hex(std::string prefix, std::vector<uint8_t> bytes, uint8_t separator);
|
||||
|
||||
// options variables
|
||||
bool log_uart_msg_ { false };
|
||||
// uart message variables
|
||||
std::vector<uint8_t> request_message_;
|
||||
uint8_t response_payload_length_;
|
||||
uint8_t request_payload_length_;
|
||||
bool response_receiving_ { false };
|
||||
bool request_receiving_ { false };
|
||||
// sensor variables
|
||||
float current_height_ = 0;
|
||||
float limit_min_ = 0;
|
||||
float limit_max_ = 0;
|
||||
float physical_min_ = 0;
|
||||
float physical_max_ = 0;
|
||||
};
|
||||
} // namespace maidesite_desk
|
||||
} // namespace esphome
|
||||
// options variables
|
||||
bool log_uart_msg_{false};
|
||||
// uart message variables
|
||||
std::vector<uint8_t> request_message_;
|
||||
uint8_t response_payload_length_;
|
||||
uint8_t request_payload_length_;
|
||||
bool response_receiving_{false};
|
||||
bool request_receiving_{false};
|
||||
// sensor variables
|
||||
float current_height_ = 0;
|
||||
float limit_min_ = 0;
|
||||
float limit_max_ = 0;
|
||||
float physical_min_ = 0;
|
||||
float physical_max_ = 0;
|
||||
};
|
||||
} // namespace maidesite_desk
|
||||
} // namespace esphome
|
||||
|
|
|
|||
|
|
@ -2,53 +2,62 @@ import esphome.codegen as cg
|
|||
import esphome.config_validation as cv
|
||||
from esphome.components import number
|
||||
from esphome.const import (
|
||||
UNIT_CENTIMETER,
|
||||
UNIT_PERCENT,
|
||||
UNIT_CENTIMETER,
|
||||
UNIT_PERCENT,
|
||||
)
|
||||
from .. import CONF_MAIDESITE_DESK_ID, MaidesiteDeskComponent, maidesite_desk_ns
|
||||
|
||||
|
||||
CONF_HEIGHT_ABS = "height_abs"
|
||||
CONF_HEIGHT_PCT = "height_pct"
|
||||
|
||||
TYPES = [
|
||||
CONF_HEIGHT_ABS,
|
||||
CONF_HEIGHT_PCT,
|
||||
CONF_HEIGHT_ABS,
|
||||
CONF_HEIGHT_PCT,
|
||||
]
|
||||
|
||||
CONF_NUMBERS = [
|
||||
[ 0, 120, .2, ],
|
||||
[ 0, 100, .1, ],
|
||||
[
|
||||
0,
|
||||
120,
|
||||
0.2,
|
||||
],
|
||||
[
|
||||
0,
|
||||
100,
|
||||
0.1,
|
||||
],
|
||||
]
|
||||
|
||||
MaidesiteDeskNumber = maidesite_desk_ns.class_("MaidesiteDeskNumber", number.Number, cg.Component)
|
||||
MaidesiteDeskNumber = maidesite_desk_ns.class_(
|
||||
"MaidesiteDeskNumber", number.Number, cg.Component
|
||||
)
|
||||
|
||||
CONFIG_SCHEMA = cv.Schema(
|
||||
{
|
||||
cv.GenerateID(CONF_MAIDESITE_DESK_ID): cv.use_id(MaidesiteDeskComponent),
|
||||
|
||||
cv.Optional(CONF_HEIGHT_ABS): number.number_schema(
|
||||
MaidesiteDeskNumber,
|
||||
unit_of_measurement=UNIT_CENTIMETER,
|
||||
),
|
||||
cv.Optional(CONF_HEIGHT_PCT): number.number_schema(
|
||||
MaidesiteDeskNumber,
|
||||
unit_of_measurement=UNIT_PERCENT,
|
||||
),
|
||||
}
|
||||
{
|
||||
cv.GenerateID(CONF_MAIDESITE_DESK_ID): cv.use_id(MaidesiteDeskComponent),
|
||||
cv.Optional(CONF_HEIGHT_ABS): number.number_schema(
|
||||
MaidesiteDeskNumber,
|
||||
unit_of_measurement=UNIT_CENTIMETER,
|
||||
),
|
||||
cv.Optional(CONF_HEIGHT_PCT): number.number_schema(
|
||||
MaidesiteDeskNumber,
|
||||
unit_of_measurement=UNIT_PERCENT,
|
||||
),
|
||||
}
|
||||
).extend(cv.COMPONENT_SCHEMA)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
hub = await cg.get_variable(config[CONF_MAIDESITE_DESK_ID])
|
||||
for index, key in enumerate(TYPES):
|
||||
if child_config := config.get(key):
|
||||
var = await number.new_number(
|
||||
child_config,
|
||||
min_value=CONF_NUMBERS[index][0],
|
||||
max_value=CONF_NUMBERS[index][1],
|
||||
step=CONF_NUMBERS[index][2]
|
||||
)
|
||||
await cg.register_component(var, child_config)
|
||||
await cg.register_parented(var, config[CONF_MAIDESITE_DESK_ID])
|
||||
cg.add(getattr(hub, f"set_{key}_number")(var))
|
||||
cg.add(var.set_id(index))
|
||||
hub = await cg.get_variable(config[CONF_MAIDESITE_DESK_ID])
|
||||
for index, key in enumerate(TYPES):
|
||||
if child_config := config.get(key):
|
||||
var = await number.new_number(
|
||||
child_config,
|
||||
min_value=CONF_NUMBERS[index][0],
|
||||
max_value=CONF_NUMBERS[index][1],
|
||||
step=CONF_NUMBERS[index][2],
|
||||
)
|
||||
await cg.register_component(var, child_config)
|
||||
await cg.register_parented(var, config[CONF_MAIDESITE_DESK_ID])
|
||||
cg.add(getattr(hub, f"set_{key}_number")(var))
|
||||
cg.add(var.set_id(index))
|
||||
|
|
|
|||
|
|
@ -1,23 +1,18 @@
|
|||
#include "maidesite_desk_number.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace maidesite_desk {
|
||||
static const char* const TAG = "maidesite_desk.number";
|
||||
|
||||
namespace esphome
|
||||
{
|
||||
namespace maidesite_desk
|
||||
{
|
||||
static const char *const TAG = "maidesite_desk.number";
|
||||
void MaidesiteDeskNumber::dump_config() {
|
||||
LOG_NUMBER("", "Maidesite Desk Number", this);
|
||||
delay(10);
|
||||
}
|
||||
|
||||
void MaidesiteDeskNumber::dump_config()
|
||||
{
|
||||
LOG_NUMBER("", "Maidesite Desk Number", this);
|
||||
delay(10);
|
||||
}
|
||||
|
||||
void MaidesiteDeskNumber::control(float value)
|
||||
{
|
||||
this->publish_state(value);
|
||||
this->parent_->number_control(this, value);
|
||||
}
|
||||
} // namespace maidesite_desk
|
||||
} // namespace esphome
|
||||
void MaidesiteDeskNumber::control(float value) {
|
||||
this->publish_state(value);
|
||||
this->parent_->number_control(this, value);
|
||||
}
|
||||
} // namespace maidesite_desk
|
||||
} // namespace esphome
|
||||
|
|
|
|||
|
|
@ -3,21 +3,19 @@
|
|||
#include "esphome/core/component.h"
|
||||
#include "../maidesite_desk.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace maidesite_desk {
|
||||
class MaidesiteDeskNumber : public number::Number, public Component, public Parented<MaidesiteDeskComponent> {
|
||||
public:
|
||||
MaidesiteDeskNumber() = default;
|
||||
void dump_config() override;
|
||||
void set_id(int id) {
|
||||
this->id_ = id;
|
||||
}
|
||||
|
||||
namespace esphome
|
||||
{
|
||||
namespace maidesite_desk
|
||||
{
|
||||
class MaidesiteDeskNumber : public number::Number, public Component, public Parented<MaidesiteDeskComponent>
|
||||
{
|
||||
public:
|
||||
MaidesiteDeskNumber() = default;
|
||||
void dump_config() override;
|
||||
void set_id(int id) { this->id_ = id; }
|
||||
|
||||
protected:
|
||||
void control(float value) override;
|
||||
int id_;
|
||||
};
|
||||
} // namespace maidesite_desk
|
||||
} // namespace esphome
|
||||
protected:
|
||||
void control(float value) override;
|
||||
int id_;
|
||||
};
|
||||
} // namespace maidesite_desk
|
||||
} // namespace esphome
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ import esphome.codegen as cg
|
|||
import esphome.config_validation as cv
|
||||
from esphome.components import sensor
|
||||
from esphome.const import (
|
||||
UNIT_CENTIMETER,
|
||||
UNIT_PERCENT,
|
||||
UNIT_CENTIMETER,
|
||||
UNIT_PERCENT,
|
||||
)
|
||||
from .. import CONF_MAIDESITE_DESK_ID, MaidesiteDeskComponent, maidesite_desk_ns
|
||||
|
||||
|
|
@ -18,73 +18,74 @@ CONF_POSITION_M3 = "position_m3"
|
|||
CONF_POSITION_M4 = "position_m4"
|
||||
|
||||
TYPES = [
|
||||
CONF_UNIT,
|
||||
CONF_HEIGHT_ABS,
|
||||
CONF_HEIGHT_PCT,
|
||||
CONF_HEIGHT_MIN,
|
||||
CONF_HEIGHT_MAX,
|
||||
CONF_POSITION_M1,
|
||||
CONF_POSITION_M2,
|
||||
CONF_POSITION_M3,
|
||||
CONF_POSITION_M4,
|
||||
CONF_UNIT,
|
||||
CONF_HEIGHT_ABS,
|
||||
CONF_HEIGHT_PCT,
|
||||
CONF_HEIGHT_MIN,
|
||||
CONF_HEIGHT_MAX,
|
||||
CONF_POSITION_M1,
|
||||
CONF_POSITION_M2,
|
||||
CONF_POSITION_M3,
|
||||
CONF_POSITION_M4,
|
||||
]
|
||||
|
||||
MaidesiteDeskSensor = maidesite_desk_ns.class_("MaidesiteDeskSensor", sensor.Sensor, cg.Component)
|
||||
MaidesiteDeskSensor = maidesite_desk_ns.class_(
|
||||
"MaidesiteDeskSensor", sensor.Sensor, cg.Component
|
||||
)
|
||||
|
||||
CONFIG_SCHEMA = cv.Schema(
|
||||
{
|
||||
cv.GenerateID(CONF_MAIDESITE_DESK_ID): cv.use_id(MaidesiteDeskComponent),
|
||||
|
||||
cv.Optional(CONF_UNIT): sensor.sensor_schema(),
|
||||
|
||||
cv.Optional(CONF_HEIGHT_ABS): sensor.sensor_schema(
|
||||
MaidesiteDeskSensor,
|
||||
accuracy_decimals=2,
|
||||
unit_of_measurement=UNIT_CENTIMETER,
|
||||
),
|
||||
cv.Optional(CONF_HEIGHT_PCT): sensor.sensor_schema(
|
||||
MaidesiteDeskSensor,
|
||||
accuracy_decimals=2,
|
||||
unit_of_measurement=UNIT_PERCENT,
|
||||
),
|
||||
cv.Optional(CONF_HEIGHT_MIN): sensor.sensor_schema(
|
||||
MaidesiteDeskSensor,
|
||||
accuracy_decimals=2,
|
||||
unit_of_measurement=UNIT_CENTIMETER,
|
||||
),
|
||||
cv.Optional(CONF_HEIGHT_MAX): sensor.sensor_schema(
|
||||
MaidesiteDeskSensor,
|
||||
accuracy_decimals=2,
|
||||
unit_of_measurement=UNIT_CENTIMETER,
|
||||
),
|
||||
cv.Optional(CONF_POSITION_M1): sensor.sensor_schema(
|
||||
MaidesiteDeskSensor,
|
||||
accuracy_decimals=2,
|
||||
unit_of_measurement=UNIT_CENTIMETER,
|
||||
),
|
||||
cv.Optional(CONF_POSITION_M2): sensor.sensor_schema(
|
||||
MaidesiteDeskSensor,
|
||||
accuracy_decimals=2,
|
||||
unit_of_measurement=UNIT_CENTIMETER,
|
||||
),
|
||||
cv.Optional(CONF_POSITION_M3): sensor.sensor_schema(
|
||||
MaidesiteDeskSensor,
|
||||
accuracy_decimals=2,
|
||||
unit_of_measurement=UNIT_CENTIMETER,
|
||||
),
|
||||
cv.Optional(CONF_POSITION_M4): sensor.sensor_schema(
|
||||
MaidesiteDeskSensor,
|
||||
accuracy_decimals=2,
|
||||
unit_of_measurement=UNIT_CENTIMETER,
|
||||
),
|
||||
}
|
||||
{
|
||||
cv.GenerateID(CONF_MAIDESITE_DESK_ID): cv.use_id(MaidesiteDeskComponent),
|
||||
cv.Optional(CONF_UNIT): sensor.sensor_schema(),
|
||||
cv.Optional(CONF_HEIGHT_ABS): sensor.sensor_schema(
|
||||
MaidesiteDeskSensor,
|
||||
accuracy_decimals=2,
|
||||
unit_of_measurement=UNIT_CENTIMETER,
|
||||
),
|
||||
cv.Optional(CONF_HEIGHT_PCT): sensor.sensor_schema(
|
||||
MaidesiteDeskSensor,
|
||||
accuracy_decimals=2,
|
||||
unit_of_measurement=UNIT_PERCENT,
|
||||
),
|
||||
cv.Optional(CONF_HEIGHT_MIN): sensor.sensor_schema(
|
||||
MaidesiteDeskSensor,
|
||||
accuracy_decimals=2,
|
||||
unit_of_measurement=UNIT_CENTIMETER,
|
||||
),
|
||||
cv.Optional(CONF_HEIGHT_MAX): sensor.sensor_schema(
|
||||
MaidesiteDeskSensor,
|
||||
accuracy_decimals=2,
|
||||
unit_of_measurement=UNIT_CENTIMETER,
|
||||
),
|
||||
cv.Optional(CONF_POSITION_M1): sensor.sensor_schema(
|
||||
MaidesiteDeskSensor,
|
||||
accuracy_decimals=2,
|
||||
unit_of_measurement=UNIT_CENTIMETER,
|
||||
),
|
||||
cv.Optional(CONF_POSITION_M2): sensor.sensor_schema(
|
||||
MaidesiteDeskSensor,
|
||||
accuracy_decimals=2,
|
||||
unit_of_measurement=UNIT_CENTIMETER,
|
||||
),
|
||||
cv.Optional(CONF_POSITION_M3): sensor.sensor_schema(
|
||||
MaidesiteDeskSensor,
|
||||
accuracy_decimals=2,
|
||||
unit_of_measurement=UNIT_CENTIMETER,
|
||||
),
|
||||
cv.Optional(CONF_POSITION_M4): sensor.sensor_schema(
|
||||
MaidesiteDeskSensor,
|
||||
accuracy_decimals=2,
|
||||
unit_of_measurement=UNIT_CENTIMETER,
|
||||
),
|
||||
}
|
||||
).extend(cv.COMPONENT_SCHEMA)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
hub = await cg.get_variable(config[CONF_MAIDESITE_DESK_ID])
|
||||
for key in TYPES:
|
||||
if child_config := config.get(key):
|
||||
var = await sensor.new_sensor(child_config)
|
||||
await cg.register_component(var, child_config)
|
||||
await cg.register_parented(var, config[CONF_MAIDESITE_DESK_ID])
|
||||
cg.add(getattr(hub, f"set_{key}_sensor")(var))
|
||||
hub = await cg.get_variable(config[CONF_MAIDESITE_DESK_ID])
|
||||
for key in TYPES:
|
||||
if child_config := config.get(key):
|
||||
var = await sensor.new_sensor(child_config)
|
||||
await cg.register_component(var, child_config)
|
||||
await cg.register_parented(var, config[CONF_MAIDESITE_DESK_ID])
|
||||
cg.add(getattr(hub, f"set_{key}_sensor")(var))
|
||||
|
|
|
|||
|
|
@ -1,17 +1,13 @@
|
|||
#include "maidesite_desk_sensor.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace maidesite_desk {
|
||||
static const char* const TAG = "maidesite_desk.sensor";
|
||||
|
||||
namespace esphome
|
||||
{
|
||||
namespace maidesite_desk
|
||||
{
|
||||
static const char *const TAG = "maidesite_desk.sensor";
|
||||
|
||||
void MaidesiteDeskSensor::dump_config()
|
||||
{
|
||||
LOG_SENSOR("", "Maidesite Desk Sensor", this);
|
||||
delay(10);
|
||||
}
|
||||
} // namespace maidesite_desk
|
||||
} // namespace esphome
|
||||
void MaidesiteDeskSensor::dump_config() {
|
||||
LOG_SENSOR("", "Maidesite Desk Sensor", this);
|
||||
delay(10);
|
||||
}
|
||||
} // namespace maidesite_desk
|
||||
} // namespace esphome
|
||||
|
|
|
|||
|
|
@ -3,16 +3,12 @@
|
|||
#include "esphome/core/component.h"
|
||||
#include "../maidesite_desk.h"
|
||||
|
||||
|
||||
namespace esphome
|
||||
{
|
||||
namespace maidesite_desk
|
||||
{
|
||||
class MaidesiteDeskSensor : public sensor::Sensor, public Component, public Parented<MaidesiteDeskComponent>
|
||||
{
|
||||
public:
|
||||
MaidesiteDeskSensor() = default;
|
||||
void dump_config() override;
|
||||
};
|
||||
} // namespace maidesite_desk
|
||||
} // namespace esphome
|
||||
namespace esphome {
|
||||
namespace maidesite_desk {
|
||||
class MaidesiteDeskSensor : public sensor::Sensor, public Component, public Parented<MaidesiteDeskComponent> {
|
||||
public:
|
||||
MaidesiteDeskSensor() = default;
|
||||
void dump_config() override;
|
||||
};
|
||||
} // namespace maidesite_desk
|
||||
} // namespace esphome
|
||||
|
|
|
|||
|
|
@ -3,39 +3,39 @@ import esphome.config_validation as cv
|
|||
from esphome.components import uart
|
||||
from esphome.const import CONF_ID
|
||||
|
||||
|
||||
CODEOWNERS = ['@elvit']
|
||||
CODEOWNERS = ["@elvit"]
|
||||
DEPENDENCIES = ["uart"]
|
||||
MULTICONF = True
|
||||
DEPENDENCIES = ['uart']
|
||||
|
||||
CONF_PANASONIC_HEATPUMP_ID = "panasonic_heatpump"
|
||||
CONF_UART_CLIENT = "uart_client_id"
|
||||
CONF_LOG_UART_MSG = "log_uart_msg"
|
||||
|
||||
|
||||
panasonic_heatpump_ns = cg.esphome_ns.namespace('panasonic_heatpump')
|
||||
PanasonicHeatpumpComponent = panasonic_heatpump_ns.class_('PanasonicHeatpumpComponent', cg.PollingComponent, uart.UARTDevice)
|
||||
|
||||
CONFIG_SCHEMA = (
|
||||
cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(PanasonicHeatpumpComponent),
|
||||
|
||||
cv.Optional(CONF_UART_CLIENT): cv.use_id(uart.UARTComponent),
|
||||
cv.Optional(CONF_LOG_UART_MSG, default=False): cv.boolean,
|
||||
}
|
||||
)
|
||||
.extend(cv.polling_component_schema("3s"))
|
||||
.extend(uart.UART_DEVICE_SCHEMA)
|
||||
panasonic_heatpump_ns = cg.esphome_ns.namespace("panasonic_heatpump")
|
||||
PanasonicHeatpumpComponent = panasonic_heatpump_ns.class_(
|
||||
"PanasonicHeatpumpComponent", cg.PollingComponent, uart.UARTDevice
|
||||
)
|
||||
|
||||
CONFIG_SCHEMA = (
|
||||
cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(PanasonicHeatpumpComponent),
|
||||
cv.Optional(CONF_UART_CLIENT): cv.use_id(uart.UARTComponent),
|
||||
cv.Optional(CONF_LOG_UART_MSG, default=False): cv.boolean,
|
||||
}
|
||||
)
|
||||
.extend(cv.polling_component_schema("3s"))
|
||||
.extend(uart.UART_DEVICE_SCHEMA)
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await cg.register_component(var, config)
|
||||
await uart.register_uart_device(var, config)
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await cg.register_component(var, config)
|
||||
await uart.register_uart_device(var, config)
|
||||
|
||||
if CONF_UART_CLIENT in config:
|
||||
uart_client = await cg.get_variable(config[CONF_UART_CLIENT])
|
||||
cg.add(var.set_uart_client(uart_client))
|
||||
if CONF_UART_CLIENT in config:
|
||||
uart_client = await cg.get_variable(config[CONF_UART_CLIENT])
|
||||
cg.add(var.set_uart_client(uart_client))
|
||||
|
||||
cg.add(var.set_log_uart_msg(config[CONF_LOG_UART_MSG]))
|
||||
cg.add(var.set_log_uart_msg(config[CONF_LOG_UART_MSG]))
|
||||
|
|
|
|||
|
|
@ -2,10 +2,13 @@ import esphome.codegen as cg
|
|||
import esphome.config_validation as cv
|
||||
from esphome.components import binary_sensor
|
||||
from esphome.const import (
|
||||
DEVICE_CLASS_RUNNING,
|
||||
DEVICE_CLASS_RUNNING,
|
||||
)
|
||||
from .. import (
|
||||
CONF_PANASONIC_HEATPUMP_ID,
|
||||
PanasonicHeatpumpComponent,
|
||||
panasonic_heatpump_ns,
|
||||
)
|
||||
from .. import CONF_PANASONIC_HEATPUMP_ID, PanasonicHeatpumpComponent, panasonic_heatpump_ns
|
||||
|
||||
|
||||
CONF_TOP0 = "top0" # Heatpump State
|
||||
CONF_TOP2 = "top2" # Force DHW State
|
||||
|
|
@ -32,125 +35,129 @@ CONF_TOP132 = "top132" # Bivalent Advanced Heat
|
|||
CONF_TOP133 = "top133" # Bivalent Advanced DHW
|
||||
|
||||
TYPES = [
|
||||
CONF_TOP0,
|
||||
CONF_TOP2,
|
||||
CONF_TOP3,
|
||||
CONF_TOP13,
|
||||
CONF_TOP26,
|
||||
CONF_TOP60,
|
||||
CONF_TOP61,
|
||||
CONF_TOP68,
|
||||
CONF_TOP69,
|
||||
CONF_TOP99,
|
||||
CONF_TOP100,
|
||||
CONF_TOP108,
|
||||
CONF_TOP109,
|
||||
CONF_TOP110,
|
||||
CONF_TOP119,
|
||||
CONF_TOP120,
|
||||
CONF_TOP121,
|
||||
CONF_TOP122,
|
||||
CONF_TOP123,
|
||||
CONF_TOP124,
|
||||
CONF_TOP129,
|
||||
CONF_TOP132,
|
||||
CONF_TOP133,
|
||||
CONF_TOP0,
|
||||
CONF_TOP2,
|
||||
CONF_TOP3,
|
||||
CONF_TOP13,
|
||||
CONF_TOP26,
|
||||
CONF_TOP60,
|
||||
CONF_TOP61,
|
||||
CONF_TOP68,
|
||||
CONF_TOP69,
|
||||
CONF_TOP99,
|
||||
CONF_TOP100,
|
||||
CONF_TOP108,
|
||||
CONF_TOP109,
|
||||
CONF_TOP110,
|
||||
CONF_TOP119,
|
||||
CONF_TOP120,
|
||||
CONF_TOP121,
|
||||
CONF_TOP122,
|
||||
CONF_TOP123,
|
||||
CONF_TOP124,
|
||||
CONF_TOP129,
|
||||
CONF_TOP132,
|
||||
CONF_TOP133,
|
||||
]
|
||||
|
||||
PanasonicHeatpumpBinarySensor = panasonic_heatpump_ns.class_("PanasonicHeatpumpBinarySensor", binary_sensor.BinarySensor, cg.Component)
|
||||
PanasonicHeatpumpBinarySensor = panasonic_heatpump_ns.class_(
|
||||
"PanasonicHeatpumpBinarySensor", binary_sensor.BinarySensor, cg.Component
|
||||
)
|
||||
|
||||
CONFIG_SCHEMA = cv.Schema(
|
||||
{
|
||||
cv.GenerateID(CONF_PANASONIC_HEATPUMP_ID): cv.use_id(PanasonicHeatpumpComponent),
|
||||
|
||||
cv.Optional(CONF_TOP0): binary_sensor.binary_sensor_schema(
|
||||
PanasonicHeatpumpBinarySensor,
|
||||
device_class = DEVICE_CLASS_RUNNING,
|
||||
),
|
||||
cv.Optional(CONF_TOP2): binary_sensor.binary_sensor_schema(
|
||||
PanasonicHeatpumpBinarySensor,
|
||||
device_class = DEVICE_CLASS_RUNNING,
|
||||
),
|
||||
cv.Optional(CONF_TOP3): binary_sensor.binary_sensor_schema(
|
||||
PanasonicHeatpumpBinarySensor,
|
||||
device_class = DEVICE_CLASS_RUNNING,
|
||||
),
|
||||
cv.Optional(CONF_TOP13): binary_sensor.binary_sensor_schema(
|
||||
PanasonicHeatpumpBinarySensor,
|
||||
device_class = DEVICE_CLASS_RUNNING,
|
||||
),
|
||||
cv.Optional(CONF_TOP26): binary_sensor.binary_sensor_schema(
|
||||
PanasonicHeatpumpBinarySensor,
|
||||
device_class = DEVICE_CLASS_RUNNING,
|
||||
),
|
||||
cv.Optional(CONF_TOP60): binary_sensor.binary_sensor_schema(
|
||||
PanasonicHeatpumpBinarySensor,
|
||||
device_class = DEVICE_CLASS_RUNNING,
|
||||
),
|
||||
cv.Optional(CONF_TOP61): binary_sensor.binary_sensor_schema(
|
||||
PanasonicHeatpumpBinarySensor,
|
||||
device_class = DEVICE_CLASS_RUNNING,
|
||||
),
|
||||
cv.Optional(CONF_TOP68): binary_sensor.binary_sensor_schema(
|
||||
PanasonicHeatpumpBinarySensor,
|
||||
device_class = DEVICE_CLASS_RUNNING,
|
||||
),
|
||||
cv.Optional(CONF_TOP69): binary_sensor.binary_sensor_schema(
|
||||
PanasonicHeatpumpBinarySensor,
|
||||
device_class = DEVICE_CLASS_RUNNING,
|
||||
),
|
||||
cv.Optional(CONF_TOP99): binary_sensor.binary_sensor_schema(
|
||||
PanasonicHeatpumpBinarySensor,
|
||||
),
|
||||
cv.Optional(CONF_TOP100): binary_sensor.binary_sensor_schema(
|
||||
PanasonicHeatpumpBinarySensor,
|
||||
),
|
||||
cv.Optional(CONF_TOP108): binary_sensor.binary_sensor_schema(
|
||||
PanasonicHeatpumpBinarySensor,
|
||||
),
|
||||
cv.Optional(CONF_TOP109): binary_sensor.binary_sensor_schema(
|
||||
PanasonicHeatpumpBinarySensor,
|
||||
device_class = DEVICE_CLASS_RUNNING,
|
||||
),
|
||||
cv.Optional(CONF_TOP110): binary_sensor.binary_sensor_schema(
|
||||
PanasonicHeatpumpBinarySensor,
|
||||
),
|
||||
cv.Optional(CONF_TOP119): binary_sensor.binary_sensor_schema(
|
||||
PanasonicHeatpumpBinarySensor,
|
||||
),
|
||||
cv.Optional(CONF_TOP120): binary_sensor.binary_sensor_schema(
|
||||
PanasonicHeatpumpBinarySensor,
|
||||
),
|
||||
cv.Optional(CONF_TOP121): binary_sensor.binary_sensor_schema(
|
||||
PanasonicHeatpumpBinarySensor,
|
||||
),
|
||||
cv.Optional(CONF_TOP122): binary_sensor.binary_sensor_schema(
|
||||
PanasonicHeatpumpBinarySensor,
|
||||
),
|
||||
cv.Optional(CONF_TOP123): binary_sensor.binary_sensor_schema(
|
||||
PanasonicHeatpumpBinarySensor,
|
||||
),
|
||||
cv.Optional(CONF_TOP124): binary_sensor.binary_sensor_schema(
|
||||
PanasonicHeatpumpBinarySensor,
|
||||
),
|
||||
cv.Optional(CONF_TOP129): binary_sensor.binary_sensor_schema(
|
||||
PanasonicHeatpumpBinarySensor,
|
||||
),
|
||||
cv.Optional(CONF_TOP132): binary_sensor.binary_sensor_schema(
|
||||
PanasonicHeatpumpBinarySensor,
|
||||
),
|
||||
cv.Optional(CONF_TOP133): binary_sensor.binary_sensor_schema(
|
||||
PanasonicHeatpumpBinarySensor,
|
||||
),
|
||||
}
|
||||
{
|
||||
cv.GenerateID(CONF_PANASONIC_HEATPUMP_ID): cv.use_id(
|
||||
PanasonicHeatpumpComponent
|
||||
),
|
||||
cv.Optional(CONF_TOP0): binary_sensor.binary_sensor_schema(
|
||||
PanasonicHeatpumpBinarySensor,
|
||||
device_class=DEVICE_CLASS_RUNNING,
|
||||
),
|
||||
cv.Optional(CONF_TOP2): binary_sensor.binary_sensor_schema(
|
||||
PanasonicHeatpumpBinarySensor,
|
||||
device_class=DEVICE_CLASS_RUNNING,
|
||||
),
|
||||
cv.Optional(CONF_TOP3): binary_sensor.binary_sensor_schema(
|
||||
PanasonicHeatpumpBinarySensor,
|
||||
device_class=DEVICE_CLASS_RUNNING,
|
||||
),
|
||||
cv.Optional(CONF_TOP13): binary_sensor.binary_sensor_schema(
|
||||
PanasonicHeatpumpBinarySensor,
|
||||
device_class=DEVICE_CLASS_RUNNING,
|
||||
),
|
||||
cv.Optional(CONF_TOP26): binary_sensor.binary_sensor_schema(
|
||||
PanasonicHeatpumpBinarySensor,
|
||||
device_class=DEVICE_CLASS_RUNNING,
|
||||
),
|
||||
cv.Optional(CONF_TOP60): binary_sensor.binary_sensor_schema(
|
||||
PanasonicHeatpumpBinarySensor,
|
||||
device_class=DEVICE_CLASS_RUNNING,
|
||||
),
|
||||
cv.Optional(CONF_TOP61): binary_sensor.binary_sensor_schema(
|
||||
PanasonicHeatpumpBinarySensor,
|
||||
device_class=DEVICE_CLASS_RUNNING,
|
||||
),
|
||||
cv.Optional(CONF_TOP68): binary_sensor.binary_sensor_schema(
|
||||
PanasonicHeatpumpBinarySensor,
|
||||
device_class=DEVICE_CLASS_RUNNING,
|
||||
),
|
||||
cv.Optional(CONF_TOP69): binary_sensor.binary_sensor_schema(
|
||||
PanasonicHeatpumpBinarySensor,
|
||||
device_class=DEVICE_CLASS_RUNNING,
|
||||
),
|
||||
cv.Optional(CONF_TOP99): binary_sensor.binary_sensor_schema(
|
||||
PanasonicHeatpumpBinarySensor,
|
||||
),
|
||||
cv.Optional(CONF_TOP100): binary_sensor.binary_sensor_schema(
|
||||
PanasonicHeatpumpBinarySensor,
|
||||
),
|
||||
cv.Optional(CONF_TOP108): binary_sensor.binary_sensor_schema(
|
||||
PanasonicHeatpumpBinarySensor,
|
||||
),
|
||||
cv.Optional(CONF_TOP109): binary_sensor.binary_sensor_schema(
|
||||
PanasonicHeatpumpBinarySensor,
|
||||
device_class=DEVICE_CLASS_RUNNING,
|
||||
),
|
||||
cv.Optional(CONF_TOP110): binary_sensor.binary_sensor_schema(
|
||||
PanasonicHeatpumpBinarySensor,
|
||||
),
|
||||
cv.Optional(CONF_TOP119): binary_sensor.binary_sensor_schema(
|
||||
PanasonicHeatpumpBinarySensor,
|
||||
),
|
||||
cv.Optional(CONF_TOP120): binary_sensor.binary_sensor_schema(
|
||||
PanasonicHeatpumpBinarySensor,
|
||||
),
|
||||
cv.Optional(CONF_TOP121): binary_sensor.binary_sensor_schema(
|
||||
PanasonicHeatpumpBinarySensor,
|
||||
),
|
||||
cv.Optional(CONF_TOP122): binary_sensor.binary_sensor_schema(
|
||||
PanasonicHeatpumpBinarySensor,
|
||||
),
|
||||
cv.Optional(CONF_TOP123): binary_sensor.binary_sensor_schema(
|
||||
PanasonicHeatpumpBinarySensor,
|
||||
),
|
||||
cv.Optional(CONF_TOP124): binary_sensor.binary_sensor_schema(
|
||||
PanasonicHeatpumpBinarySensor,
|
||||
),
|
||||
cv.Optional(CONF_TOP129): binary_sensor.binary_sensor_schema(
|
||||
PanasonicHeatpumpBinarySensor,
|
||||
),
|
||||
cv.Optional(CONF_TOP132): binary_sensor.binary_sensor_schema(
|
||||
PanasonicHeatpumpBinarySensor,
|
||||
),
|
||||
cv.Optional(CONF_TOP133): binary_sensor.binary_sensor_schema(
|
||||
PanasonicHeatpumpBinarySensor,
|
||||
),
|
||||
}
|
||||
).extend(cv.COMPONENT_SCHEMA)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
parent = await cg.get_variable(config[CONF_PANASONIC_HEATPUMP_ID])
|
||||
for index, key in enumerate(TYPES):
|
||||
if child_config := config.get(key):
|
||||
var = await binary_sensor.new_binary_sensor(child_config)
|
||||
await cg.register_component(var, child_config)
|
||||
cg.add(var.set_parent(parent))
|
||||
cg.add(var.set_id(index))
|
||||
cg.add(parent.add_binary_sensor(var))
|
||||
parent = await cg.get_variable(config[CONF_PANASONIC_HEATPUMP_ID])
|
||||
for index, key in enumerate(TYPES):
|
||||
if child_config := config.get(key):
|
||||
var = await binary_sensor.new_binary_sensor(child_config)
|
||||
await cg.register_component(var, child_config)
|
||||
cg.add(var.set_parent(parent))
|
||||
cg.add(var.set_id(index))
|
||||
cg.add(parent.add_binary_sensor(var))
|
||||
|
|
|
|||
|
|
@ -1,121 +1,140 @@
|
|||
#include "panasonic_heatpump_binary_sensor.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace panasonic_heatpump {
|
||||
static const char* const TAG = "panasonic_heatpump.binary_sensor";
|
||||
|
||||
namespace esphome
|
||||
{
|
||||
namespace panasonic_heatpump
|
||||
{
|
||||
static const char *const TAG = "panasonic_heatpump.binary_sensor";
|
||||
void PanasonicHeatpumpBinarySensor::dump_config() {
|
||||
LOG_BINARY_SENSOR("", "Panasonic Heatpump Binary Sensor", this);
|
||||
delay(10);
|
||||
}
|
||||
|
||||
void PanasonicHeatpumpBinarySensor::dump_config()
|
||||
{
|
||||
LOG_BINARY_SENSOR("", "Panasonic Heatpump Binary Sensor", this);
|
||||
delay(10);
|
||||
}
|
||||
void PanasonicHeatpumpBinarySensor::publish_new_state(const std::vector<uint8_t>& data) {
|
||||
if (data.empty())
|
||||
return;
|
||||
|
||||
void PanasonicHeatpumpBinarySensor::publish_new_state(const std::vector<uint8_t>& data)
|
||||
{
|
||||
if (data.empty()) return;
|
||||
bool new_state;
|
||||
switch (this->id_) {
|
||||
case BinarySensorIds::CONF_TOP0:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit7and8(data[4]));
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case BinarySensorIds::CONF_TOP2:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit1and2(data[4]));
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case BinarySensorIds::CONF_TOP3:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit1and2(data[7]));
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case BinarySensorIds::CONF_TOP13:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit1and2(data[5]));
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case BinarySensorIds::CONF_TOP26:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit5and6(data[111]));
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case BinarySensorIds::CONF_TOP60:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit7and8(data[112]));
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case BinarySensorIds::CONF_TOP61:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit5and6(data[112]));
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case BinarySensorIds::CONF_TOP68:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit5and6(data[5]));
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case BinarySensorIds::CONF_TOP69:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit5and6(data[117]));
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case BinarySensorIds::CONF_TOP99:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit5and6(data[24]));
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case BinarySensorIds::CONF_TOP100:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit7and8(data[24]));
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case BinarySensorIds::CONF_TOP108:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit3and4(data[20]));
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case BinarySensorIds::CONF_TOP109:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit5and6(data[20]));
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case BinarySensorIds::CONF_TOP110:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit7and8(data[20]));
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case BinarySensorIds::CONF_TOP119:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit7and8(data[23]));
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case BinarySensorIds::CONF_TOP120:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit5and6(data[23]));
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case BinarySensorIds::CONF_TOP121:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit3and4(data[23]));
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case BinarySensorIds::CONF_TOP122:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit1and2(data[23]));
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case BinarySensorIds::CONF_TOP123:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit1and2(data[116]));
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case BinarySensorIds::CONF_TOP124:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit3and4(data[116]));
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case BinarySensorIds::CONF_TOP129:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit7and8(data[26]));
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case BinarySensorIds::CONF_TOP132:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit3and4(data[26]));
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case BinarySensorIds::CONF_TOP133:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit1and2(data[26]));
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
};
|
||||
|
||||
bool new_state;
|
||||
switch (this->id_)
|
||||
{
|
||||
case BinarySensorIds::CONF_TOP0:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit7and8(data[4]));
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case BinarySensorIds::CONF_TOP2:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit1and2(data[4]));
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case BinarySensorIds::CONF_TOP3:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit1and2(data[7]));
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case BinarySensorIds::CONF_TOP13:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit1and2(data[5]));
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case BinarySensorIds::CONF_TOP26:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit5and6(data[111]));
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case BinarySensorIds::CONF_TOP60:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit7and8(data[112]));
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case BinarySensorIds::CONF_TOP61:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit5and6(data[112]));
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case BinarySensorIds::CONF_TOP68:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit5and6(data[5]));
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case BinarySensorIds::CONF_TOP69:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit5and6(data[117]));
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case BinarySensorIds::CONF_TOP99:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit5and6(data[24]));
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case BinarySensorIds::CONF_TOP100:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit7and8(data[24]));
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case BinarySensorIds::CONF_TOP108:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit3and4(data[20]));
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case BinarySensorIds::CONF_TOP109:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit5and6(data[20]));
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case BinarySensorIds::CONF_TOP110:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit7and8(data[20]));
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case BinarySensorIds::CONF_TOP119:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit7and8(data[23]));
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case BinarySensorIds::CONF_TOP120:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit5and6(data[23]));
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case BinarySensorIds::CONF_TOP121:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit3and4(data[23]));
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case BinarySensorIds::CONF_TOP122:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit1and2(data[23]));
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case BinarySensorIds::CONF_TOP123:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit1and2(data[116]));
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case BinarySensorIds::CONF_TOP124:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit3and4(data[116]));
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case BinarySensorIds::CONF_TOP129:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit7and8(data[26]));
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case BinarySensorIds::CONF_TOP132:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit3and4(data[26]));
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case BinarySensorIds::CONF_TOP133:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit1and2(data[26]));
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
default: return;
|
||||
};
|
||||
|
||||
this->publish_state(new_state);
|
||||
}
|
||||
} // namespace panasonic_heatpump
|
||||
} // namespace esphome
|
||||
this->publish_state(new_state);
|
||||
}
|
||||
} // namespace panasonic_heatpump
|
||||
} // namespace esphome
|
||||
|
|
|
|||
|
|
@ -4,45 +4,42 @@
|
|||
#include "../panasonic_heatpump.h"
|
||||
#include "../decode.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace panasonic_heatpump {
|
||||
enum BinarySensorIds : uint8_t {
|
||||
CONF_TOP0,
|
||||
CONF_TOP2,
|
||||
CONF_TOP3,
|
||||
CONF_TOP13,
|
||||
CONF_TOP26,
|
||||
CONF_TOP60,
|
||||
CONF_TOP61,
|
||||
CONF_TOP68,
|
||||
CONF_TOP69,
|
||||
CONF_TOP99,
|
||||
CONF_TOP100,
|
||||
CONF_TOP108,
|
||||
CONF_TOP109,
|
||||
CONF_TOP110,
|
||||
CONF_TOP119,
|
||||
CONF_TOP120,
|
||||
CONF_TOP121,
|
||||
CONF_TOP122,
|
||||
CONF_TOP123,
|
||||
CONF_TOP124,
|
||||
CONF_TOP129,
|
||||
CONF_TOP132,
|
||||
CONF_TOP133,
|
||||
};
|
||||
|
||||
namespace esphome
|
||||
{
|
||||
namespace panasonic_heatpump
|
||||
{
|
||||
enum BinarySensorIds : uint8_t
|
||||
{
|
||||
CONF_TOP0,
|
||||
CONF_TOP2,
|
||||
CONF_TOP3,
|
||||
CONF_TOP13,
|
||||
CONF_TOP26,
|
||||
CONF_TOP60,
|
||||
CONF_TOP61,
|
||||
CONF_TOP68,
|
||||
CONF_TOP69,
|
||||
CONF_TOP99,
|
||||
CONF_TOP100,
|
||||
CONF_TOP108,
|
||||
CONF_TOP109,
|
||||
CONF_TOP110,
|
||||
CONF_TOP119,
|
||||
CONF_TOP120,
|
||||
CONF_TOP121,
|
||||
CONF_TOP122,
|
||||
CONF_TOP123,
|
||||
CONF_TOP124,
|
||||
CONF_TOP129,
|
||||
CONF_TOP132,
|
||||
CONF_TOP133,
|
||||
};
|
||||
|
||||
class PanasonicHeatpumpBinarySensor : public binary_sensor::BinarySensor, public Component,
|
||||
public Parented<PanasonicHeatpumpComponent>, public PanasonicHeatpumpEntity
|
||||
{
|
||||
public:
|
||||
PanasonicHeatpumpBinarySensor() = default;
|
||||
void dump_config() override;
|
||||
void publish_new_state(const std::vector<uint8_t>& data) override;
|
||||
};
|
||||
} // namespace panasonic_heatpump
|
||||
} // namespace esphome
|
||||
class PanasonicHeatpumpBinarySensor : public binary_sensor::BinarySensor,
|
||||
public Component,
|
||||
public Parented<PanasonicHeatpumpComponent>,
|
||||
public PanasonicHeatpumpEntity {
|
||||
public:
|
||||
PanasonicHeatpumpBinarySensor() = default;
|
||||
void dump_config() override;
|
||||
void publish_new_state(const std::vector<uint8_t>& data) override;
|
||||
};
|
||||
} // namespace panasonic_heatpump
|
||||
} // namespace esphome
|
||||
|
|
|
|||
|
|
@ -1,21 +1,16 @@
|
|||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import climate
|
||||
from esphome.components.climate import (
|
||||
ClimateMode,
|
||||
ClimatePreset,
|
||||
)
|
||||
from esphome.const import (
|
||||
CONF_ID,
|
||||
CONF_SUPPORTED_MODES,
|
||||
CONF_SUPPORTED_PRESETS,
|
||||
CONF_CUSTOM_PRESETS,
|
||||
CONF_VISUAL,
|
||||
CONF_MIN_TEMPERATURE,
|
||||
CONF_MAX_TEMPERATURE,
|
||||
CONF_TEMPERATURE_STEP,
|
||||
CONF_MIN_TEMPERATURE,
|
||||
CONF_MAX_TEMPERATURE,
|
||||
CONF_TEMPERATURE_STEP,
|
||||
)
|
||||
from .. import (
|
||||
CONF_PANASONIC_HEATPUMP_ID,
|
||||
PanasonicHeatpumpComponent,
|
||||
panasonic_heatpump_ns,
|
||||
)
|
||||
from .. import CONF_PANASONIC_HEATPUMP_ID, PanasonicHeatpumpComponent, panasonic_heatpump_ns
|
||||
|
||||
CONF_COOL_MODE = "cool_mode"
|
||||
CONF_CLIMATE_TANK = "tank"
|
||||
|
|
@ -23,56 +18,56 @@ CONF_CLIMATE_ZONE1 = "zone1"
|
|||
CONF_CLIMATE_ZONE2 = "zone2"
|
||||
|
||||
TYPES = [
|
||||
CONF_CLIMATE_TANK,
|
||||
CONF_CLIMATE_ZONE1,
|
||||
CONF_CLIMATE_ZONE2,
|
||||
CONF_CLIMATE_TANK,
|
||||
CONF_CLIMATE_ZONE1,
|
||||
CONF_CLIMATE_ZONE2,
|
||||
]
|
||||
|
||||
def climate_options(min_temp, max_temp, temp_step) -> cv.Schema:
|
||||
schema = cv.Schema({
|
||||
cv.Optional(CONF_MIN_TEMPERATURE, default=min_temp): cv.float_,
|
||||
cv.Optional(CONF_MAX_TEMPERATURE, default=max_temp): cv.float_,
|
||||
cv.Optional(CONF_TEMPERATURE_STEP, default=temp_step): cv.float_,
|
||||
})
|
||||
return schema
|
||||
|
||||
PanasonicHeatpumpClimate = panasonic_heatpump_ns.class_("PanasonicHeatpumpClimate", climate.Climate, cg.Component)
|
||||
def climate_options(min_temp, max_temp, temp_step) -> cv.Schema:
|
||||
schema = cv.Schema(
|
||||
{
|
||||
cv.Optional(CONF_MIN_TEMPERATURE, default=min_temp): cv.float_,
|
||||
cv.Optional(CONF_MAX_TEMPERATURE, default=max_temp): cv.float_,
|
||||
cv.Optional(CONF_TEMPERATURE_STEP, default=temp_step): cv.float_,
|
||||
}
|
||||
)
|
||||
return schema
|
||||
|
||||
|
||||
PanasonicHeatpumpClimate = panasonic_heatpump_ns.class_(
|
||||
"PanasonicHeatpumpClimate", climate.Climate, cg.Component
|
||||
)
|
||||
|
||||
CONFIG_SCHEMA = cv.Schema(
|
||||
{
|
||||
cv.GenerateID(CONF_PANASONIC_HEATPUMP_ID): cv.use_id(
|
||||
PanasonicHeatpumpComponent
|
||||
),
|
||||
cv.Optional(CONF_COOL_MODE, default=False): cv.boolean,
|
||||
|
||||
cv.Optional(CONF_CLIMATE_TANK): climate.climate_schema(
|
||||
PanasonicHeatpumpClimate
|
||||
).extend(
|
||||
climate_options(20.0, 65.0, 0.5)
|
||||
),
|
||||
cv.Optional(CONF_CLIMATE_ZONE1): climate.climate_schema(
|
||||
PanasonicHeatpumpClimate
|
||||
).extend(
|
||||
climate_options(-5.0, 5.0, 0.5)
|
||||
),
|
||||
cv.Optional(CONF_CLIMATE_ZONE2): climate.climate_schema(
|
||||
PanasonicHeatpumpClimate
|
||||
).extend(
|
||||
climate_options(-5.0, 5.0, 0.5)
|
||||
),
|
||||
}
|
||||
{
|
||||
cv.GenerateID(CONF_PANASONIC_HEATPUMP_ID): cv.use_id(
|
||||
PanasonicHeatpumpComponent
|
||||
),
|
||||
cv.Optional(CONF_COOL_MODE, default=False): cv.boolean,
|
||||
cv.Optional(CONF_CLIMATE_TANK): climate.climate_schema(
|
||||
PanasonicHeatpumpClimate
|
||||
).extend(climate_options(20.0, 65.0, 0.5)),
|
||||
cv.Optional(CONF_CLIMATE_ZONE1): climate.climate_schema(
|
||||
PanasonicHeatpumpClimate
|
||||
).extend(climate_options(-5.0, 5.0, 0.5)),
|
||||
cv.Optional(CONF_CLIMATE_ZONE2): climate.climate_schema(
|
||||
PanasonicHeatpumpClimate
|
||||
).extend(climate_options(-5.0, 5.0, 0.5)),
|
||||
}
|
||||
).extend(cv.COMPONENT_SCHEMA)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
parent = await cg.get_variable(config[CONF_PANASONIC_HEATPUMP_ID])
|
||||
for index, key in enumerate(TYPES):
|
||||
if child_config := config.get(key):
|
||||
var = await climate.new_climate(child_config)
|
||||
await cg.register_component(var, child_config)
|
||||
cg.add(var.set_parent(parent))
|
||||
cg.add(var.set_id(index))
|
||||
cg.add(var.set_min_temperature(child_config[CONF_MIN_TEMPERATURE]))
|
||||
cg.add(var.set_max_temperature(child_config[CONF_MAX_TEMPERATURE]))
|
||||
cg.add(var.set_temperature_step(child_config[CONF_TEMPERATURE_STEP]))
|
||||
cg.add(var.set_cool_mode(config[CONF_COOL_MODE]))
|
||||
cg.add(parent.add_climate(var))
|
||||
parent = await cg.get_variable(config[CONF_PANASONIC_HEATPUMP_ID])
|
||||
for index, key in enumerate(TYPES):
|
||||
if child_config := config.get(key):
|
||||
var = await climate.new_climate(child_config)
|
||||
await cg.register_component(var, child_config)
|
||||
cg.add(var.set_parent(parent))
|
||||
cg.add(var.set_id(index))
|
||||
cg.add(var.set_min_temperature(child_config[CONF_MIN_TEMPERATURE]))
|
||||
cg.add(var.set_max_temperature(child_config[CONF_MAX_TEMPERATURE]))
|
||||
cg.add(var.set_temperature_step(child_config[CONF_TEMPERATURE_STEP]))
|
||||
cg.add(var.set_cool_mode(config[CONF_COOL_MODE]))
|
||||
cg.add(parent.add_climate(var))
|
||||
|
|
|
|||
|
|
@ -1,228 +1,207 @@
|
|||
#include "panasonic_heatpump_climate.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace panasonic_heatpump {
|
||||
static const char* const TAG = "panasonic_heatpump.climate";
|
||||
|
||||
namespace esphome
|
||||
{
|
||||
namespace panasonic_heatpump
|
||||
{
|
||||
static const char *const TAG = "panasonic_heatpump.climate";
|
||||
void PanasonicHeatpumpClimate::dump_config() {
|
||||
LOG_CLIMATE("", "Panasonic Heatpump Climate", this);
|
||||
}
|
||||
|
||||
void PanasonicHeatpumpClimate::dump_config()
|
||||
{
|
||||
LOG_CLIMATE("", "Panasonic Heatpump Climate", this);
|
||||
climate::ClimateTraits PanasonicHeatpumpClimate::traits() {
|
||||
auto traits = climate::ClimateTraits();
|
||||
|
||||
// traits.set_supports_action(true);
|
||||
traits.add_feature_flags(climate::CLIMATE_SUPPORTS_CURRENT_TEMPERATURE);
|
||||
traits.set_supported_modes({climate::CLIMATE_MODE_OFF, climate::CLIMATE_MODE_HEAT});
|
||||
if (this->cool_mode_ &&
|
||||
(this->id_ == ClimateIds::CONF_CLIMATE_ZONE1 || this->id_ == ClimateIds::CONF_CLIMATE_ZONE2)) {
|
||||
traits.add_feature_flags(climate::CLIMATE_REQUIRES_TWO_POINT_TARGET_TEMPERATURE);
|
||||
traits.add_supported_mode(climate::CLIMATE_MODE_COOL);
|
||||
traits.add_supported_mode(climate::CLIMATE_MODE_AUTO);
|
||||
}
|
||||
|
||||
traits.set_visual_min_temperature(this->min_temperature_);
|
||||
traits.set_visual_max_temperature(this->max_temperature_);
|
||||
traits.set_visual_temperature_step(this->temperature_step_);
|
||||
|
||||
return traits;
|
||||
}
|
||||
|
||||
void PanasonicHeatpumpClimate::control(const climate::ClimateCall& call) {
|
||||
if (call.get_mode().has_value()) {
|
||||
int byte6 = this->parent_->getResponseByte(6);
|
||||
if (byte6 >= 0) {
|
||||
climate::ClimateMode new_mode = *call.get_mode();
|
||||
uint8_t newByte6 = this->setClimateMode(new_mode, (uint8_t)byte6);
|
||||
this->parent_->set_command_byte(newByte6, 6);
|
||||
}
|
||||
}
|
||||
|
||||
climate::ClimateTraits PanasonicHeatpumpClimate::traits()
|
||||
{
|
||||
auto traits = climate::ClimateTraits();
|
||||
if (call.get_target_temperature().has_value()) {
|
||||
float new_temp = *call.get_target_temperature();
|
||||
switch (this->id_) {
|
||||
case ClimateIds::CONF_CLIMATE_TANK:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus128(new_temp), 42); // set11
|
||||
break;
|
||||
case ClimateIds::CONF_CLIMATE_ZONE1:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus128(new_temp), 38); // set5
|
||||
break;
|
||||
case ClimateIds::CONF_CLIMATE_ZONE2:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus128(new_temp), 40); // set7
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
//traits.set_supports_action(true);
|
||||
traits.add_feature_flags(climate::CLIMATE_SUPPORTS_CURRENT_TEMPERATURE);
|
||||
traits.set_supported_modes({climate::CLIMATE_MODE_OFF, climate::CLIMATE_MODE_HEAT});
|
||||
if (this->cool_mode_ &&
|
||||
(this->id_ == ClimateIds::CONF_CLIMATE_ZONE1 ||
|
||||
this->id_ == ClimateIds::CONF_CLIMATE_ZONE2))
|
||||
{
|
||||
traits.add_feature_flags(climate::CLIMATE_REQUIRES_TWO_POINT_TARGET_TEMPERATURE);
|
||||
traits.add_supported_mode(climate::CLIMATE_MODE_COOL);
|
||||
traits.add_supported_mode(climate::CLIMATE_MODE_AUTO);
|
||||
}
|
||||
traits.set_visual_min_temperature(this->min_temperature_);
|
||||
traits.set_visual_max_temperature(this->max_temperature_);
|
||||
traits.set_visual_temperature_step(this->temperature_step_);
|
||||
if (call.get_target_temperature_high().has_value()) {
|
||||
float new_temp = *call.get_target_temperature_high();
|
||||
switch (this->id_) {
|
||||
case ClimateIds::CONF_CLIMATE_ZONE1:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus128(new_temp), 38); // set5
|
||||
break;
|
||||
case ClimateIds::CONF_CLIMATE_ZONE2:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus128(new_temp), 40); // set7
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
return traits;
|
||||
}
|
||||
if (call.get_target_temperature_low().has_value()) {
|
||||
float new_temp = *call.get_target_temperature_low();
|
||||
switch (this->id_) {
|
||||
case ClimateIds::CONF_CLIMATE_ZONE1:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus128(new_temp), 39); // set6
|
||||
break;
|
||||
case ClimateIds::CONF_CLIMATE_ZONE2:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus128(new_temp), 41); // set8
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
void PanasonicHeatpumpClimate::control(const climate::ClimateCall &call)
|
||||
{
|
||||
if (call.get_mode().has_value())
|
||||
{
|
||||
int byte6 = this->parent_->getResponseByte(6);
|
||||
if (byte6 >= 0)
|
||||
{
|
||||
climate::ClimateMode new_mode = *call.get_mode();
|
||||
uint8_t newByte6 = this->setClimateMode(new_mode, (uint8_t)byte6);
|
||||
this->parent_->set_command_byte(newByte6, 6);
|
||||
}
|
||||
}
|
||||
this->publish_state();
|
||||
this->keep_state_ = 2;
|
||||
}
|
||||
|
||||
if (call.get_target_temperature().has_value())
|
||||
{
|
||||
float new_temp = *call.get_target_temperature();
|
||||
switch (this->id_)
|
||||
{
|
||||
case ClimateIds::CONF_CLIMATE_TANK:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus128(new_temp), 42); // set11
|
||||
break;
|
||||
case ClimateIds::CONF_CLIMATE_ZONE1:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus128(new_temp), 38); // set5
|
||||
break;
|
||||
case ClimateIds::CONF_CLIMATE_ZONE2:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus128(new_temp), 40); // set7
|
||||
break;
|
||||
};
|
||||
}
|
||||
void PanasonicHeatpumpClimate::publish_new_state(const std::vector<uint8_t>& data) {
|
||||
if (this->keep_state_ > 0) {
|
||||
this->keep_state_--;
|
||||
return;
|
||||
}
|
||||
if (data.empty())
|
||||
return;
|
||||
|
||||
if (call.get_target_temperature_high().has_value())
|
||||
{
|
||||
float new_temp = *call.get_target_temperature_high();
|
||||
switch (this->id_)
|
||||
{
|
||||
case ClimateIds::CONF_CLIMATE_ZONE1:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus128(new_temp), 38); // set5
|
||||
break;
|
||||
case ClimateIds::CONF_CLIMATE_ZONE2:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus128(new_temp), 40); // set7
|
||||
break;
|
||||
};
|
||||
}
|
||||
uint8_t new_mode;
|
||||
float new_target_temp_heat;
|
||||
float new_target_temp_cool;
|
||||
float new_current_temp;
|
||||
|
||||
if (call.get_target_temperature_low().has_value())
|
||||
{
|
||||
float new_temp = *call.get_target_temperature_low();
|
||||
switch (this->id_)
|
||||
{
|
||||
case ClimateIds::CONF_CLIMATE_ZONE1:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus128(new_temp), 39); // set6
|
||||
break;
|
||||
case ClimateIds::CONF_CLIMATE_ZONE2:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus128(new_temp), 41); // set8
|
||||
break;
|
||||
};
|
||||
}
|
||||
new_mode = this->getClimateMode(data[6]); // set9
|
||||
switch (this->id_) {
|
||||
case ClimateIds::CONF_CLIMATE_TANK:
|
||||
new_target_temp_heat = PanasonicDecode::getByteMinus128(data[42]); // set11
|
||||
new_current_temp = PanasonicDecode::getByteMinus128(data[141]); // top10
|
||||
break;
|
||||
case ClimateIds::CONF_CLIMATE_ZONE1:
|
||||
new_target_temp_heat = PanasonicDecode::getByteMinus128(data[38]); // set5
|
||||
new_target_temp_cool = PanasonicDecode::getByteMinus128(data[39]); // set6
|
||||
new_current_temp = PanasonicDecode::getByteMinus128(data[139]); // top56
|
||||
break;
|
||||
case ClimateIds::CONF_CLIMATE_ZONE2:
|
||||
new_target_temp_heat = PanasonicDecode::getByteMinus128(data[40]); // set7
|
||||
new_target_temp_cool = PanasonicDecode::getByteMinus128(data[41]); // set8
|
||||
new_current_temp = PanasonicDecode::getByteMinus128(data[140]); // top57
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
};
|
||||
|
||||
this->publish_state();
|
||||
this->keep_state_ = 2;
|
||||
}
|
||||
if (!this->get_traits().has_feature_flags(climate::CLIMATE_REQUIRES_TWO_POINT_TARGET_TEMPERATURE) &&
|
||||
this->mode == new_mode && this->target_temperature == new_target_temp_heat &&
|
||||
this->current_temperature == new_current_temp)
|
||||
return;
|
||||
if (this->get_traits().has_feature_flags(climate::CLIMATE_REQUIRES_TWO_POINT_TARGET_TEMPERATURE) &&
|
||||
this->mode == new_mode && this->target_temperature_high == new_target_temp_heat &&
|
||||
this->target_temperature_low == new_target_temp_cool && this->current_temperature == new_current_temp)
|
||||
return;
|
||||
|
||||
void PanasonicHeatpumpClimate::publish_new_state(const std::vector<uint8_t>& data)
|
||||
{
|
||||
if (this->keep_state_ > 0)
|
||||
{
|
||||
this->keep_state_--;
|
||||
return;
|
||||
}
|
||||
if (data.empty()) return;
|
||||
if (new_mode != 255)
|
||||
this->mode = (climate::ClimateMode)new_mode;
|
||||
// this->action = climate::CLIMATE_ACTION_IDLE;
|
||||
if (this->get_traits().has_feature_flags(climate::CLIMATE_REQUIRES_TWO_POINT_TARGET_TEMPERATURE)) {
|
||||
this->target_temperature_high = new_target_temp_heat;
|
||||
this->target_temperature_low = new_target_temp_cool;
|
||||
} else {
|
||||
this->target_temperature = new_target_temp_heat;
|
||||
}
|
||||
this->current_temperature = new_current_temp;
|
||||
this->publish_state();
|
||||
}
|
||||
|
||||
uint8_t new_mode;
|
||||
float new_target_temp_heat;
|
||||
float new_target_temp_cool;
|
||||
float new_current_temp;
|
||||
uint8_t PanasonicHeatpumpClimate::getClimateMode(const uint8_t input) {
|
||||
switch (this->id_) {
|
||||
case ClimateIds::CONF_CLIMATE_TANK:
|
||||
switch ((uint8_t)(input & 0b110000)) {
|
||||
case 0b010000:
|
||||
return climate::CLIMATE_MODE_OFF;
|
||||
case 0b100000:
|
||||
return climate::CLIMATE_MODE_HEAT;
|
||||
default:
|
||||
return 255;
|
||||
};
|
||||
case ClimateIds::CONF_CLIMATE_ZONE1:
|
||||
case ClimateIds::CONF_CLIMATE_ZONE2:
|
||||
switch ((uint8_t)(input & 0b1111)) {
|
||||
case 0b0001:
|
||||
return climate::CLIMATE_MODE_OFF;
|
||||
case 0b0010:
|
||||
return climate::CLIMATE_MODE_HEAT;
|
||||
case 0b0011:
|
||||
return climate::CLIMATE_MODE_COOL;
|
||||
case 0b1000:
|
||||
return climate::CLIMATE_MODE_AUTO;
|
||||
case 0b1001:
|
||||
return climate::CLIMATE_MODE_AUTO; // 0x19 = auto-heat
|
||||
case 0b1010:
|
||||
return climate::CLIMATE_MODE_AUTO; // 0x1A = auto-cool
|
||||
default:
|
||||
return 255;
|
||||
};
|
||||
default:
|
||||
return 255;
|
||||
};
|
||||
}
|
||||
|
||||
new_mode = this->getClimateMode(data[6]); // set9
|
||||
switch (this->id_)
|
||||
{
|
||||
case ClimateIds::CONF_CLIMATE_TANK:
|
||||
new_target_temp_heat = PanasonicDecode::getByteMinus128(data[42]); // set11
|
||||
new_current_temp = PanasonicDecode::getByteMinus128(data[141]); // top10
|
||||
break;
|
||||
case ClimateIds::CONF_CLIMATE_ZONE1:
|
||||
new_target_temp_heat = PanasonicDecode::getByteMinus128(data[38]); // set5
|
||||
new_target_temp_cool = PanasonicDecode::getByteMinus128(data[39]); // set6
|
||||
new_current_temp = PanasonicDecode::getByteMinus128(data[139]); // top56
|
||||
break;
|
||||
case ClimateIds::CONF_CLIMATE_ZONE2:
|
||||
new_target_temp_heat = PanasonicDecode::getByteMinus128(data[40]); // set7
|
||||
new_target_temp_cool = PanasonicDecode::getByteMinus128(data[41]); // set8
|
||||
new_current_temp = PanasonicDecode::getByteMinus128(data[140]); // top57
|
||||
break;
|
||||
default: return;
|
||||
};
|
||||
|
||||
if (!this->get_traits().has_feature_flags(climate::CLIMATE_REQUIRES_TWO_POINT_TARGET_TEMPERATURE) &&
|
||||
this->mode == new_mode &&
|
||||
this->target_temperature == new_target_temp_heat &&
|
||||
this->current_temperature == new_current_temp) return;
|
||||
if (this->get_traits().has_feature_flags(climate::CLIMATE_REQUIRES_TWO_POINT_TARGET_TEMPERATURE) &&
|
||||
this->mode == new_mode &&
|
||||
this->target_temperature_high == new_target_temp_heat &&
|
||||
this->target_temperature_low == new_target_temp_cool &&
|
||||
this->current_temperature == new_current_temp) return;
|
||||
|
||||
if (new_mode != 255) this->mode = (climate::ClimateMode)new_mode;
|
||||
//this->action = climate::CLIMATE_ACTION_IDLE;
|
||||
if (this->get_traits().has_feature_flags(climate::CLIMATE_REQUIRES_TWO_POINT_TARGET_TEMPERATURE))
|
||||
{
|
||||
this->target_temperature_high = new_target_temp_heat;
|
||||
this->target_temperature_low = new_target_temp_cool;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->target_temperature = new_target_temp_heat;
|
||||
}
|
||||
this->current_temperature = new_current_temp;
|
||||
this->publish_state();
|
||||
}
|
||||
|
||||
uint8_t PanasonicHeatpumpClimate::getClimateMode(const uint8_t input)
|
||||
{
|
||||
switch (this->id_)
|
||||
{
|
||||
case ClimateIds::CONF_CLIMATE_TANK:
|
||||
switch ((uint8_t)(input & 0b110000))
|
||||
{
|
||||
case 0b010000:
|
||||
return climate::CLIMATE_MODE_OFF;
|
||||
case 0b100000:
|
||||
return climate::CLIMATE_MODE_HEAT;
|
||||
default: return 255;
|
||||
};
|
||||
case ClimateIds::CONF_CLIMATE_ZONE1:
|
||||
case ClimateIds::CONF_CLIMATE_ZONE2:
|
||||
switch ((uint8_t)(input & 0b1111))
|
||||
{
|
||||
case 0b0001:
|
||||
return climate::CLIMATE_MODE_OFF;
|
||||
case 0b0010:
|
||||
return climate::CLIMATE_MODE_HEAT;
|
||||
case 0b0011:
|
||||
return climate::CLIMATE_MODE_COOL;
|
||||
case 0b1000:
|
||||
return climate::CLIMATE_MODE_AUTO;
|
||||
case 0b1001:
|
||||
return climate::CLIMATE_MODE_AUTO; // 0x19 = auto-heat
|
||||
case 0b1010:
|
||||
return climate::CLIMATE_MODE_AUTO; // 0x1A = auto-cool
|
||||
default: return 255;
|
||||
};
|
||||
default: return 255;
|
||||
};
|
||||
}
|
||||
|
||||
uint8_t PanasonicHeatpumpClimate::setClimateMode(const climate::ClimateMode mode, uint8_t byte)
|
||||
{
|
||||
uint8_t newByte = byte;
|
||||
switch (this->id_)
|
||||
{
|
||||
case ClimateIds::CONF_CLIMATE_TANK:
|
||||
newByte = newByte & 0b11001111;
|
||||
switch (mode)
|
||||
{
|
||||
case climate::CLIMATE_MODE_OFF:
|
||||
return newByte + 0b010000;
|
||||
case climate::CLIMATE_MODE_HEAT:
|
||||
return newByte + 0b100000;
|
||||
default: return 0;
|
||||
};
|
||||
case ClimateIds::CONF_CLIMATE_ZONE1:
|
||||
case ClimateIds::CONF_CLIMATE_ZONE2:
|
||||
newByte = newByte & 0b11110000;
|
||||
switch (mode)
|
||||
{
|
||||
case climate::CLIMATE_MODE_OFF:
|
||||
return newByte + 0b0001;
|
||||
case climate::CLIMATE_MODE_HEAT:
|
||||
return newByte + 0b0010;
|
||||
case climate::CLIMATE_MODE_COOL:
|
||||
return newByte + 0b0011;
|
||||
case climate::CLIMATE_MODE_AUTO:
|
||||
return newByte + 0b1000;
|
||||
default: return 0;
|
||||
};
|
||||
default: return 0;
|
||||
};
|
||||
}
|
||||
} // namespace panasonic_heatpump
|
||||
} // namespace esphome
|
||||
uint8_t PanasonicHeatpumpClimate::setClimateMode(const climate::ClimateMode mode, uint8_t byte) {
|
||||
uint8_t newByte = byte;
|
||||
switch (this->id_) {
|
||||
case ClimateIds::CONF_CLIMATE_TANK:
|
||||
newByte = newByte & 0b11001111;
|
||||
switch (mode) {
|
||||
case climate::CLIMATE_MODE_OFF:
|
||||
return newByte + 0b010000;
|
||||
case climate::CLIMATE_MODE_HEAT:
|
||||
return newByte + 0b100000;
|
||||
default:
|
||||
return 0;
|
||||
};
|
||||
case ClimateIds::CONF_CLIMATE_ZONE1:
|
||||
case ClimateIds::CONF_CLIMATE_ZONE2:
|
||||
newByte = newByte & 0b11110000;
|
||||
switch (mode) {
|
||||
case climate::CLIMATE_MODE_OFF:
|
||||
return newByte + 0b0001;
|
||||
case climate::CLIMATE_MODE_HEAT:
|
||||
return newByte + 0b0010;
|
||||
case climate::CLIMATE_MODE_COOL:
|
||||
return newByte + 0b0011;
|
||||
case climate::CLIMATE_MODE_AUTO:
|
||||
return newByte + 0b1000;
|
||||
default:
|
||||
return 0;
|
||||
};
|
||||
default:
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
} // namespace panasonic_heatpump
|
||||
} // namespace esphome
|
||||
|
|
|
|||
|
|
@ -6,41 +6,46 @@
|
|||
#include "../commands.h"
|
||||
#include <set>
|
||||
|
||||
namespace esphome {
|
||||
namespace panasonic_heatpump {
|
||||
enum ClimateIds : uint8_t {
|
||||
CONF_CLIMATE_TANK,
|
||||
CONF_CLIMATE_ZONE1,
|
||||
CONF_CLIMATE_ZONE2,
|
||||
};
|
||||
|
||||
namespace esphome
|
||||
{
|
||||
namespace panasonic_heatpump
|
||||
{
|
||||
enum ClimateIds : uint8_t
|
||||
{
|
||||
CONF_CLIMATE_TANK,
|
||||
CONF_CLIMATE_ZONE1,
|
||||
CONF_CLIMATE_ZONE2,
|
||||
};
|
||||
class PanasonicHeatpumpClimate : public climate::Climate,
|
||||
public Component,
|
||||
public Parented<PanasonicHeatpumpComponent>,
|
||||
public PanasonicHeatpumpEntity {
|
||||
public:
|
||||
PanasonicHeatpumpClimate() = default;
|
||||
void dump_config() override;
|
||||
climate::ClimateTraits traits() override;
|
||||
void publish_new_state(const std::vector<uint8_t>& data) override;
|
||||
|
||||
class PanasonicHeatpumpClimate : public climate::Climate, public Component,
|
||||
public Parented<PanasonicHeatpumpComponent>, public PanasonicHeatpumpEntity
|
||||
{
|
||||
public:
|
||||
PanasonicHeatpumpClimate() = default;
|
||||
void dump_config() override;
|
||||
climate::ClimateTraits traits() override;
|
||||
void publish_new_state(const std::vector<uint8_t>& data) override;
|
||||
void set_cool_mode(bool value) {
|
||||
this->cool_mode_ = value;
|
||||
}
|
||||
void set_min_temperature(float value) {
|
||||
this->min_temperature_ = value;
|
||||
}
|
||||
void set_max_temperature(float value) {
|
||||
this->max_temperature_ = value;
|
||||
}
|
||||
void set_temperature_step(float value) {
|
||||
this->temperature_step_ = value;
|
||||
}
|
||||
|
||||
void set_cool_mode(bool value) { this->cool_mode_ = value; }
|
||||
void set_min_temperature(float value) { this->min_temperature_ = value; }
|
||||
void set_max_temperature(float value) { this->max_temperature_ = value; }
|
||||
void set_temperature_step(float value) { this->temperature_step_ = value; }
|
||||
protected:
|
||||
void control(const climate::ClimateCall& call) override;
|
||||
uint8_t getClimateMode(const uint8_t input);
|
||||
uint8_t setClimateMode(const climate::ClimateMode mode, const uint8_t byte);
|
||||
|
||||
protected:
|
||||
void control(const climate::ClimateCall &call) override;
|
||||
uint8_t getClimateMode(const uint8_t input);
|
||||
uint8_t setClimateMode(const climate::ClimateMode mode, const uint8_t byte);
|
||||
|
||||
bool cool_mode_ { false };
|
||||
float min_temperature_ { -5.0 };
|
||||
float max_temperature_ { 5.0 };
|
||||
float temperature_step_ { 0.5 };
|
||||
};
|
||||
} // namespace panasonic_heatpump
|
||||
} // namespace esphome
|
||||
bool cool_mode_{false};
|
||||
float min_temperature_{-5.0};
|
||||
float max_temperature_{5.0};
|
||||
float temperature_step_{0.5};
|
||||
};
|
||||
} // namespace panasonic_heatpump
|
||||
} // namespace esphome
|
||||
|
|
|
|||
|
|
@ -1,164 +1,145 @@
|
|||
#include "commands.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace panasonic_heatpump {
|
||||
const uint8_t PanasonicCommand::InitialRequest[INIT_REQUEST_SIZE] = {0x31, 0x05, 0x10, 0x01, 0x00, 0x00, 0x00, 0xB9};
|
||||
const uint8_t PanasonicCommand::InitialResponse[INIT_RESPONSE_SIZE] = {
|
||||
0x31, 0x30, 0x01, 0x10, 0x1E, 0x6C, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C};
|
||||
const uint8_t PanasonicCommand::PollingMessage[DATA_MESSAGE_SIZE] = {
|
||||
0x71, 0x6C, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12};
|
||||
const uint8_t PanasonicCommand::PollingExtraMessage[DATA_MESSAGE_SIZE] = {
|
||||
0x71, 0x6C, 0x01, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
|
||||
const uint8_t PanasonicCommand::CommandMessage[DATA_MESSAGE_SIZE] = {
|
||||
0xF1, 0x6C, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92};
|
||||
|
||||
namespace esphome
|
||||
{
|
||||
namespace panasonic_heatpump
|
||||
{
|
||||
const uint8_t PanasonicCommand::InitialRequest[INIT_REQUEST_SIZE] = {
|
||||
0x31, 0x05, 0x10, 0x01, 0x00, 0x00, 0x00, 0xB9
|
||||
};
|
||||
const uint8_t PanasonicCommand::InitialResponse[INIT_RESPONSE_SIZE] = {
|
||||
0x31, 0x30, 0x01, 0x10, 0x1E, 0x6C, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x3C
|
||||
};
|
||||
const uint8_t PanasonicCommand::PollingMessage[DATA_MESSAGE_SIZE] = {
|
||||
0x71, 0x6C, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x12
|
||||
};
|
||||
const uint8_t PanasonicCommand::PollingExtraMessage[DATA_MESSAGE_SIZE] = {
|
||||
0x71, 0x6C, 0x01, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x01
|
||||
};
|
||||
const uint8_t PanasonicCommand::CommandMessage[DATA_MESSAGE_SIZE] = {
|
||||
0xF1, 0x6C, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x92
|
||||
};
|
||||
uint8_t PanasonicCommand::calcChecksum(std::vector<uint8_t>& data, int length) {
|
||||
uint8_t checksum = 0;
|
||||
for (int i = 0; i < length; i++) {
|
||||
checksum += data[i];
|
||||
}
|
||||
checksum = (checksum ^ 0xFF) + 01;
|
||||
return checksum;
|
||||
}
|
||||
|
||||
uint8_t PanasonicCommand::calcChecksum(std::vector<uint8_t>& data, int length)
|
||||
{
|
||||
uint8_t checksum = 0;
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
checksum += data[i];
|
||||
}
|
||||
checksum = (checksum ^ 0xFF) + 01;
|
||||
return checksum;
|
||||
}
|
||||
uint8_t PanasonicCommand::setMultiply2(size_t input) {
|
||||
return input * 0b10;
|
||||
}
|
||||
|
||||
uint8_t PanasonicCommand::setMultiply2(size_t input)
|
||||
{
|
||||
return input * 0b10;
|
||||
}
|
||||
uint8_t PanasonicCommand::setMultiply4(size_t input) {
|
||||
return input * 0b100;
|
||||
}
|
||||
|
||||
uint8_t PanasonicCommand::setMultiply4(size_t input)
|
||||
{
|
||||
return input * 0b100;
|
||||
}
|
||||
uint8_t PanasonicCommand::setPlus1Multiply4(size_t input) {
|
||||
return (input + 1) * 0b100;
|
||||
}
|
||||
|
||||
uint8_t PanasonicCommand::setPlus1Multiply4(size_t input)
|
||||
{
|
||||
return (input + 1) * 0b100;
|
||||
}
|
||||
uint8_t PanasonicCommand::setPlus1Multiply8(size_t input) {
|
||||
return (input + 1) * 0b1000;
|
||||
}
|
||||
|
||||
uint8_t PanasonicCommand::setPlus1Multiply8(size_t input)
|
||||
{
|
||||
return (input + 1) * 0b1000;
|
||||
}
|
||||
uint8_t PanasonicCommand::setPlus1Multiply16(size_t input) {
|
||||
return (input + 1) * 0b10000;
|
||||
}
|
||||
|
||||
uint8_t PanasonicCommand::setPlus1Multiply16(size_t input)
|
||||
{
|
||||
return (input + 1) * 0b10000;
|
||||
}
|
||||
uint8_t PanasonicCommand::setPlus1Multiply64(size_t input) {
|
||||
return (input + 1) * 0b1000000;
|
||||
}
|
||||
|
||||
uint8_t PanasonicCommand::setPlus1Multiply64(size_t input)
|
||||
{
|
||||
return (input + 1) * 0b1000000;
|
||||
}
|
||||
uint8_t PanasonicCommand::setPlus1(size_t input) {
|
||||
return input + 1;
|
||||
}
|
||||
|
||||
uint8_t PanasonicCommand::setPlus1(size_t input)
|
||||
{
|
||||
return input + 1;
|
||||
}
|
||||
uint8_t PanasonicCommand::setPlus128(size_t input) {
|
||||
return input + 0b10000000;
|
||||
}
|
||||
|
||||
uint8_t PanasonicCommand::setPlus128(size_t input)
|
||||
{
|
||||
return input + 0b10000000;
|
||||
}
|
||||
uint8_t PanasonicCommand::setOperationMode(size_t input) {
|
||||
switch (input) {
|
||||
case 0:
|
||||
return 0b100001; // 0x21 = tank
|
||||
case 1:
|
||||
return 0b010010; // 0x12 = heat
|
||||
case 2:
|
||||
return 0b100010; // 0x22 = heat+tank
|
||||
case 3:
|
||||
return 0b010011; // 0x13 = cool
|
||||
case 4:
|
||||
return 0b100011; // 0x23 = cool+tank
|
||||
case 5:
|
||||
return 0b011000; // 0x18 = auto
|
||||
case 6:
|
||||
return 0b101000; // 0x28 = auto+tank
|
||||
case 7:
|
||||
return 0b011001; // 0x19 = auto-heat
|
||||
case 8:
|
||||
return 0b101001; // 0x29 = auto-heat+tank
|
||||
case 9:
|
||||
return 0b011010; // 0x1A = auto-cool
|
||||
case 10:
|
||||
return 0b101010; // 0x2A = auto-cool+tank
|
||||
default:
|
||||
return 0; // do nothing
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t PanasonicCommand::setOperationMode(size_t input)
|
||||
{
|
||||
switch (input)
|
||||
{
|
||||
case 0: return 0b100001; // 0x21 = tank
|
||||
case 1: return 0b010010; // 0x12 = heat
|
||||
case 2: return 0b100010; // 0x22 = heat+tank
|
||||
case 3: return 0b010011; // 0x13 = cool
|
||||
case 4: return 0b100011; // 0x23 = cool+tank
|
||||
case 5: return 0b011000; // 0x18 = auto
|
||||
case 6: return 0b101000; // 0x28 = auto+tank
|
||||
case 7: return 0b011001; // 0x19 = auto-heat
|
||||
case 8: return 0b101001; // 0x29 = auto-heat+tank
|
||||
case 9: return 0b011010; // 0x1A = auto-cool
|
||||
case 10: return 0b101010; // 0x2A = auto-cool+tank
|
||||
default: return 0; // do nothing
|
||||
}
|
||||
}
|
||||
// start of optional pcb commands
|
||||
|
||||
//start of optional pcb commands
|
||||
uint8_t PanasonicCommand::temp2hex(float temp) {
|
||||
int hextemp = 0;
|
||||
if (temp > 120) {
|
||||
hextemp = 0;
|
||||
} else if (temp < -78) {
|
||||
hextemp = 255;
|
||||
} else {
|
||||
uint8_t Uref = 255;
|
||||
int constant = 3695;
|
||||
int R25 = 6340;
|
||||
uint8_t T25 = 25;
|
||||
int Rf = 6480;
|
||||
float K = 273.15;
|
||||
float RT = R25 * exp(constant * (1 / (temp + K) - 1 / (T25 + K)));
|
||||
hextemp = Uref * (RT / (Rf + RT));
|
||||
}
|
||||
|
||||
uint8_t PanasonicCommand::temp2hex(float temp)
|
||||
{
|
||||
int hextemp = 0;
|
||||
if (temp > 120)
|
||||
{
|
||||
hextemp = 0;
|
||||
}
|
||||
else if (temp < -78)
|
||||
{
|
||||
hextemp = 255;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t Uref = 255;
|
||||
int constant = 3695;
|
||||
int R25 = 6340;
|
||||
uint8_t T25 = 25;
|
||||
int Rf = 6480;
|
||||
float K = 273.15;
|
||||
float RT = R25 * exp(constant * (1 / (temp + K) - 1 / (T25 + K)));
|
||||
hextemp = Uref * (RT / (Rf + RT));
|
||||
}
|
||||
return hextemp;
|
||||
}
|
||||
|
||||
return hextemp;
|
||||
}
|
||||
uint8_t PanasonicCommand::setByte6(uint8_t byte6, int val, int base, int bit) {
|
||||
return (byte6 & ~(base << bit)) | (val << bit);
|
||||
}
|
||||
|
||||
uint8_t PanasonicCommand::setByte6(uint8_t byte6, int val, int base, int bit)
|
||||
{
|
||||
return (byte6 & ~(base << bit)) | (val << bit);
|
||||
}
|
||||
|
||||
uint8_t PanasonicCommand::setDemandControl(size_t input)
|
||||
{
|
||||
switch (input)
|
||||
{
|
||||
case 0: return 0xEB;
|
||||
case 1: return 0xB8;
|
||||
case 2: return 0x85;
|
||||
case 3: return 0x52;
|
||||
case 4: return 0x2B;
|
||||
default: return 0; // do nothing
|
||||
}
|
||||
}
|
||||
} // namespace panasonic_heatpump
|
||||
} // namespace esphome
|
||||
uint8_t PanasonicCommand::setDemandControl(size_t input) {
|
||||
switch (input) {
|
||||
case 0:
|
||||
return 0xEB;
|
||||
case 1:
|
||||
return 0xB8;
|
||||
case 2:
|
||||
return 0x85;
|
||||
case 3:
|
||||
return 0x52;
|
||||
case 4:
|
||||
return 0x2B;
|
||||
default:
|
||||
return 0; // do nothing
|
||||
}
|
||||
}
|
||||
} // namespace panasonic_heatpump
|
||||
} // namespace esphome
|
||||
|
|
|
|||
|
|
@ -15,35 +15,31 @@
|
|||
#define OPTIONAL_MESSAGE_SIZE 20
|
||||
#endif
|
||||
|
||||
namespace esphome {
|
||||
namespace panasonic_heatpump {
|
||||
class PanasonicCommand {
|
||||
public:
|
||||
PanasonicCommand() = delete;
|
||||
|
||||
namespace esphome
|
||||
{
|
||||
namespace panasonic_heatpump
|
||||
{
|
||||
class PanasonicCommand
|
||||
{
|
||||
public:
|
||||
PanasonicCommand() = delete;
|
||||
static uint8_t calcChecksum(std::vector<uint8_t>& data, int length);
|
||||
static uint8_t setMultiply2(size_t input);
|
||||
static uint8_t setMultiply4(size_t input);
|
||||
static uint8_t setPlus1Multiply4(size_t input);
|
||||
static uint8_t setPlus1Multiply8(size_t input);
|
||||
static uint8_t setPlus1Multiply16(size_t input);
|
||||
static uint8_t setPlus1Multiply64(size_t input);
|
||||
static uint8_t setPlus1(size_t input);
|
||||
static uint8_t setPlus128(size_t input);
|
||||
static uint8_t setOperationMode(size_t input);
|
||||
static uint8_t temp2hex(float temp);
|
||||
static uint8_t setByte6(uint8_t byte6, int val, int base, int bit);
|
||||
static uint8_t setDemandControl(size_t input);
|
||||
|
||||
static uint8_t calcChecksum(std::vector<uint8_t>& data, int length);
|
||||
static uint8_t setMultiply2(size_t input);
|
||||
static uint8_t setMultiply4(size_t input);
|
||||
static uint8_t setPlus1Multiply4(size_t input);
|
||||
static uint8_t setPlus1Multiply8(size_t input);
|
||||
static uint8_t setPlus1Multiply16(size_t input);
|
||||
static uint8_t setPlus1Multiply64(size_t input);
|
||||
static uint8_t setPlus1(size_t input);
|
||||
static uint8_t setPlus128(size_t input);
|
||||
static uint8_t setOperationMode(size_t input);
|
||||
static uint8_t temp2hex(float temp);
|
||||
static uint8_t setByte6(uint8_t byte6, int val, int base, int bit);
|
||||
static uint8_t setDemandControl(size_t input);
|
||||
|
||||
static const uint8_t InitialRequest[INIT_REQUEST_SIZE];
|
||||
static const uint8_t InitialResponse[INIT_RESPONSE_SIZE];
|
||||
static const uint8_t PollingMessage[DATA_MESSAGE_SIZE];
|
||||
static const uint8_t PollingExtraMessage[DATA_MESSAGE_SIZE];
|
||||
static const uint8_t CommandMessage[DATA_MESSAGE_SIZE];
|
||||
};
|
||||
} // namespace panasonic_heatpump
|
||||
static const uint8_t InitialRequest[INIT_REQUEST_SIZE];
|
||||
static const uint8_t InitialResponse[INIT_RESPONSE_SIZE];
|
||||
static const uint8_t PollingMessage[DATA_MESSAGE_SIZE];
|
||||
static const uint8_t PollingExtraMessage[DATA_MESSAGE_SIZE];
|
||||
static const uint8_t CommandMessage[DATA_MESSAGE_SIZE];
|
||||
};
|
||||
} // namespace panasonic_heatpump
|
||||
} // namespace esphome
|
||||
|
|
|
|||
|
|
@ -1,278 +1,256 @@
|
|||
#include "decode.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace panasonic_heatpump {
|
||||
constexpr const char* const PanasonicDecode::DisabledEnabled[];
|
||||
constexpr const char* const PanasonicDecode::BlockedFree[];
|
||||
constexpr const char* const PanasonicDecode::OffOn[];
|
||||
constexpr const char* const PanasonicDecode::InactiveActive[];
|
||||
constexpr const char* const PanasonicDecode::PumpFlowRateMode[];
|
||||
constexpr const char* const PanasonicDecode::HolidayState[];
|
||||
constexpr const char* const PanasonicDecode::OperationMode[];
|
||||
constexpr const char* const PanasonicDecode::PowerfulMode[];
|
||||
constexpr const char* const PanasonicDecode::QuietMode[];
|
||||
constexpr const char* const PanasonicDecode::ThreeWayValve[];
|
||||
constexpr const char* const PanasonicDecode::TwoWayValve[];
|
||||
constexpr const char* const PanasonicDecode::MixingValve[];
|
||||
constexpr const char* const PanasonicDecode::ZoneState[];
|
||||
constexpr const char* const PanasonicDecode::WaterTempControl[];
|
||||
constexpr const char* const PanasonicDecode::SolarMode[];
|
||||
constexpr const char* const PanasonicDecode::ZoneSensorType[];
|
||||
constexpr const char* const PanasonicDecode::LiquidType[];
|
||||
constexpr const char* const PanasonicDecode::ExtPadHeaterType[];
|
||||
constexpr const char* const PanasonicDecode::BivalentMode[];
|
||||
constexpr const char* const PanasonicDecode::ModelNames[];
|
||||
|
||||
namespace esphome
|
||||
{
|
||||
namespace panasonic_heatpump
|
||||
{
|
||||
constexpr const char* const PanasonicDecode::DisabledEnabled[];
|
||||
constexpr const char* const PanasonicDecode::BlockedFree[];
|
||||
constexpr const char* const PanasonicDecode::OffOn[];
|
||||
constexpr const char* const PanasonicDecode::InactiveActive[];
|
||||
constexpr const char* const PanasonicDecode::PumpFlowRateMode[];
|
||||
constexpr const char* const PanasonicDecode::HolidayState[];
|
||||
constexpr const char* const PanasonicDecode::OperationMode[];
|
||||
constexpr const char* const PanasonicDecode::PowerfulMode[];
|
||||
constexpr const char* const PanasonicDecode::QuietMode[];
|
||||
constexpr const char* const PanasonicDecode::ThreeWayValve[];
|
||||
constexpr const char* const PanasonicDecode::TwoWayValve[];
|
||||
constexpr const char* const PanasonicDecode::MixingValve[];
|
||||
constexpr const char* const PanasonicDecode::ZoneState[];
|
||||
constexpr const char* const PanasonicDecode::WaterTempControl[];
|
||||
constexpr const char* const PanasonicDecode::SolarMode[];
|
||||
constexpr const char* const PanasonicDecode::ZoneSensorType[];
|
||||
constexpr const char* const PanasonicDecode::LiquidType[];
|
||||
constexpr const char* const PanasonicDecode::ExtPadHeaterType[];
|
||||
constexpr const char* const PanasonicDecode::BivalentMode[];
|
||||
constexpr const char* const PanasonicDecode::ModelNames[];
|
||||
constexpr const uint8_t KnownModels[NUMBER_OF_MODELS][10] = {
|
||||
{0xE2, 0xCF, 0x0B, 0x13, 0x33, 0x32, 0xD1, 0x0C, 0x16, 0x33}, // 0
|
||||
{0xE2, 0xCF, 0x0B, 0x14, 0x33, 0x42, 0xD1, 0x0B, 0x17, 0x33}, // 1
|
||||
{0xE2, 0xCF, 0x0D, 0x77, 0x09, 0x12, 0xD0, 0x0B, 0x05, 0x11}, // 2
|
||||
{0xE2, 0xCF, 0x0C, 0x88, 0x05, 0x12, 0xD0, 0x0B, 0x97, 0x05}, // 3
|
||||
{0xE2, 0xCF, 0x0D, 0x85, 0x05, 0x12, 0xD0, 0x0C, 0x94, 0x05}, // 4
|
||||
{0xE2, 0xCF, 0x0D, 0x86, 0x05, 0x12, 0xD0, 0x0C, 0x95, 0x05}, // 5
|
||||
{0xE2, 0xCF, 0x0D, 0x87, 0x05, 0x12, 0xD0, 0x0C, 0x96, 0x05}, // 6
|
||||
{0xE2, 0xCE, 0x0D, 0x71, 0x81, 0x72, 0xCE, 0x0C, 0x92, 0x81}, // 7
|
||||
{0x62, 0xD2, 0x0B, 0x43, 0x54, 0x42, 0xD2, 0x0B, 0x72, 0x66}, // 8
|
||||
{0xC2, 0xD3, 0x0B, 0x33, 0x65, 0xB2, 0xD3, 0x0B, 0x94, 0x65}, // 9
|
||||
{0xE2, 0xCF, 0x0B, 0x15, 0x33, 0x42, 0xD1, 0x0B, 0x18, 0x33}, // 10
|
||||
{0xE2, 0xCF, 0x0B, 0x41, 0x34, 0x82, 0xD1, 0x0B, 0x31, 0x35}, // 11
|
||||
{0x62, 0xD2, 0x0B, 0x45, 0x54, 0x42, 0xD2, 0x0B, 0x47, 0x55}, // 12
|
||||
{0xE2, 0xCF, 0x0C, 0x74, 0x09, 0x12, 0xD0, 0x0D, 0x95, 0x05}, // 13
|
||||
{0xE2, 0xCF, 0x0B, 0x82, 0x05, 0x12, 0xD0, 0x0C, 0x91, 0x05}, // 14
|
||||
{0xE2, 0xCF, 0x0C, 0x55, 0x14, 0x12, 0xD0, 0x0B, 0x15, 0x08}, // 15
|
||||
{0xE2, 0xCF, 0x0C, 0x43, 0x00, 0x12, 0xD0, 0x0B, 0x15, 0x08}, // 16
|
||||
{0x62, 0xD2, 0x0B, 0x45, 0x54, 0x32, 0xD2, 0x0C, 0x45, 0x55}, // 17
|
||||
{0x62, 0xD2, 0x0B, 0x43, 0x54, 0x42, 0xD2, 0x0C, 0x46, 0x55}, // 18
|
||||
{0xE2, 0xCF, 0x0C, 0x54, 0x14, 0x12, 0xD0, 0x0B, 0x14, 0x08}, // 19
|
||||
{0xC2, 0xD3, 0x0B, 0x34, 0x65, 0xB2, 0xD3, 0x0B, 0x95, 0x65}, // 20
|
||||
{0xC2, 0xD3, 0x0B, 0x35, 0x65, 0xB2, 0xD3, 0x0B, 0x96, 0x65}, // 21
|
||||
{0x62, 0xD2, 0x0B, 0x41, 0x54, 0x32, 0xD2, 0x0C, 0x45, 0x55}, // 22
|
||||
{0x32, 0xD4, 0x0B, 0x87, 0x84, 0x73, 0x90, 0x0C, 0x84, 0x84}, // 23
|
||||
{0x32, 0xD4, 0x0B, 0x88, 0x84, 0x73, 0x90, 0x0C, 0x85, 0x84}, // 24
|
||||
{0xE2, 0xCF, 0x0B, 0x75, 0x09, 0x12, 0xD0, 0x0C, 0x06, 0x11}, // 25
|
||||
{0x42, 0xD4, 0x0B, 0x83, 0x71, 0x42, 0xD2, 0x0C, 0x46, 0x55}, // 26
|
||||
{0xC2, 0xD3, 0x0C, 0x34, 0x65, 0xB2, 0xD3, 0x0B, 0x95, 0x65}, // 27
|
||||
{0xC2, 0xD3, 0x0C, 0x33, 0x65, 0xB2, 0xD3, 0x0B, 0x94, 0x65}, // 28
|
||||
{0xE2, 0xCF, 0x0B, 0x83, 0x05, 0x12, 0xD0, 0x0D, 0x92, 0x05}, // 29
|
||||
{0xE2, 0xCF, 0x0C, 0x78, 0x09, 0x12, 0xD0, 0x0B, 0x06, 0x11}, // 30
|
||||
{0xC2, 0xD3, 0x0C, 0x35, 0x65, 0xB2, 0xD3, 0x0B, 0x96, 0x65}, // 31
|
||||
{0x32, 0xD4, 0x0B, 0x99, 0x77, 0x62, 0x90, 0x0B, 0x01, 0x78}, // 32
|
||||
{0x42, 0xD4, 0x0B, 0x15, 0x76, 0x12, 0xD0, 0x0B, 0x10, 0x11}, // 33
|
||||
{0xE2, 0xD5, 0x0C, 0x29, 0x99, 0x83, 0x92, 0x0C, 0x28, 0x98}, // 34
|
||||
{0xE2, 0xCF, 0x0D, 0x85, 0x05, 0x12, 0xD0, 0x0E, 0x94, 0x05}, // 35
|
||||
{0xE2, 0xD5, 0x0D, 0x36, 0x99, 0x02, 0xD6, 0x0F, 0x67, 0x95}, // 36
|
||||
{0xE2, 0xD5, 0x0B, 0x08, 0x95, 0x02, 0xD6, 0x0E, 0x66, 0x95}, // 37
|
||||
{0xE2, 0xD5, 0x0B, 0x34, 0x99, 0x83, 0x92, 0x0C, 0x29, 0x98}, // 38
|
||||
{0xE2, 0xCF, 0x0C, 0x89, 0x05, 0x12, 0xD0, 0x0C, 0x98, 0x05}, // 39
|
||||
{0xE2, 0xD5, 0x0B, 0x08, 0x95, 0x02, 0xD6, 0x0E, 0x67, 0x95}, // 40
|
||||
{0xE2, 0xCF, 0x0C, 0x74, 0x09, 0x12, 0xD0, 0x0C, 0x96, 0x05}, // 41
|
||||
{0xE2, 0xCF, 0x0C, 0x74, 0x09, 0x12, 0xD0, 0x0E, 0x95, 0x05}, // 42
|
||||
{0x32, 0xD4, 0x0B, 0x89, 0x84, 0x73, 0x90, 0x0C, 0x86, 0x84}, // 43
|
||||
{0x32, 0xD4, 0x0B, 0x00, 0x78, 0x62, 0x90, 0x0B, 0x02, 0x78}, // 44
|
||||
{0xE2, 0xCF, 0x0B, 0x82, 0x05, 0x12, 0xD0, 0x0D, 0x91, 0x05}, // 45
|
||||
{0xE2, 0xD5, 0x0D, 0x99, 0x94, 0x02, 0xD6, 0x0D, 0x68, 0x95}, // 46
|
||||
{0xE2, 0xCF, 0x0C, 0x74, 0x09, 0x12, 0xD0, 0x0C, 0x95, 0x05}, // 47
|
||||
{0xE2, 0xD5, 0x0B, 0x34, 0x99, 0x83, 0x92, 0x0C, 0x28, 0x98}, // 48
|
||||
{0xE2, 0xCF, 0x0D, 0x77, 0x09, 0x12, 0xD0, 0x0C, 0x05, 0x11}, // 49
|
||||
{0xE2, 0xCF, 0x0B, 0x44, 0x34, 0x12, 0xD0, 0x0C, 0x34, 0x35}, // 50
|
||||
{0xE2, 0xD5, 0x0C, 0x67, 0x00, 0x83, 0x92, 0x0C, 0x27, 0x98}, // 51
|
||||
{0xE2, 0xD5, 0x0B, 0x34, 0x99, 0x83, 0x92, 0x0C, 0x27, 0x98}, // 52
|
||||
{0x42, 0xD4, 0x0B, 0x83, 0x71, 0x32, 0xD2, 0x0C, 0x44, 0x55}, // 53
|
||||
{0xE2, 0xCF, 0x0C, 0x74, 0x09, 0x12, 0xD0, 0x0E, 0x94, 0x05}, // 54
|
||||
};
|
||||
|
||||
constexpr const uint8_t KnownModels[NUMBER_OF_MODELS][10] =
|
||||
{
|
||||
{ 0xE2, 0xCF, 0x0B, 0x13, 0x33, 0x32, 0xD1, 0x0C, 0x16, 0x33 }, // 0
|
||||
{ 0xE2, 0xCF, 0x0B, 0x14, 0x33, 0x42, 0xD1, 0x0B, 0x17, 0x33 }, // 1
|
||||
{ 0xE2, 0xCF, 0x0D, 0x77, 0x09, 0x12, 0xD0, 0x0B, 0x05, 0x11 }, // 2
|
||||
{ 0xE2, 0xCF, 0x0C, 0x88, 0x05, 0x12, 0xD0, 0x0B, 0x97, 0x05 }, // 3
|
||||
{ 0xE2, 0xCF, 0x0D, 0x85, 0x05, 0x12, 0xD0, 0x0C, 0x94, 0x05 }, // 4
|
||||
{ 0xE2, 0xCF, 0x0D, 0x86, 0x05, 0x12, 0xD0, 0x0C, 0x95, 0x05 }, // 5
|
||||
{ 0xE2, 0xCF, 0x0D, 0x87, 0x05, 0x12, 0xD0, 0x0C, 0x96, 0x05 }, // 6
|
||||
{ 0xE2, 0xCE, 0x0D, 0x71, 0x81, 0x72, 0xCE, 0x0C, 0x92, 0x81 }, // 7
|
||||
{ 0x62, 0xD2, 0x0B, 0x43, 0x54, 0x42, 0xD2, 0x0B, 0x72, 0x66 }, // 8
|
||||
{ 0xC2, 0xD3, 0x0B, 0x33, 0x65, 0xB2, 0xD3, 0x0B, 0x94, 0x65 }, // 9
|
||||
{ 0xE2, 0xCF, 0x0B, 0x15, 0x33, 0x42, 0xD1, 0x0B, 0x18, 0x33 }, // 10
|
||||
{ 0xE2, 0xCF, 0x0B, 0x41, 0x34, 0x82, 0xD1, 0x0B, 0x31, 0x35 }, // 11
|
||||
{ 0x62, 0xD2, 0x0B, 0x45, 0x54, 0x42, 0xD2, 0x0B, 0x47, 0x55 }, // 12
|
||||
{ 0xE2, 0xCF, 0x0C, 0x74, 0x09, 0x12, 0xD0, 0x0D, 0x95, 0x05 }, // 13
|
||||
{ 0xE2, 0xCF, 0x0B, 0x82, 0x05, 0x12, 0xD0, 0x0C, 0x91, 0x05 }, // 14
|
||||
{ 0xE2, 0xCF, 0x0C, 0x55, 0x14, 0x12, 0xD0, 0x0B, 0x15, 0x08 }, // 15
|
||||
{ 0xE2, 0xCF, 0x0C, 0x43, 0x00, 0x12, 0xD0, 0x0B, 0x15, 0x08 }, // 16
|
||||
{ 0x62, 0xD2, 0x0B, 0x45, 0x54, 0x32, 0xD2, 0x0C, 0x45, 0x55 }, // 17
|
||||
{ 0x62, 0xD2, 0x0B, 0x43, 0x54, 0x42, 0xD2, 0x0C, 0x46, 0x55 }, // 18
|
||||
{ 0xE2, 0xCF, 0x0C, 0x54, 0x14, 0x12, 0xD0, 0x0B, 0x14, 0x08 }, // 19
|
||||
{ 0xC2, 0xD3, 0x0B, 0x34, 0x65, 0xB2, 0xD3, 0x0B, 0x95, 0x65 }, // 20
|
||||
{ 0xC2, 0xD3, 0x0B, 0x35, 0x65, 0xB2, 0xD3, 0x0B, 0x96, 0x65 }, // 21
|
||||
{ 0x62, 0xD2, 0x0B, 0x41, 0x54, 0x32, 0xD2, 0x0C, 0x45, 0x55 }, // 22
|
||||
{ 0x32, 0xD4, 0x0B, 0x87, 0x84, 0x73, 0x90, 0x0C, 0x84, 0x84 }, // 23
|
||||
{ 0x32, 0xD4, 0x0B, 0x88, 0x84, 0x73, 0x90, 0x0C, 0x85, 0x84 }, // 24
|
||||
{ 0xE2, 0xCF, 0x0B, 0x75, 0x09, 0x12, 0xD0, 0x0C, 0x06, 0x11 }, // 25
|
||||
{ 0x42, 0xD4, 0x0B, 0x83, 0x71, 0x42, 0xD2, 0x0C, 0x46, 0x55 }, // 26
|
||||
{ 0xC2, 0xD3, 0x0C, 0x34, 0x65, 0xB2, 0xD3, 0x0B, 0x95, 0x65 }, // 27
|
||||
{ 0xC2, 0xD3, 0x0C, 0x33, 0x65, 0xB2, 0xD3, 0x0B, 0x94, 0x65 }, // 28
|
||||
{ 0xE2, 0xCF, 0x0B, 0x83, 0x05, 0x12, 0xD0, 0x0D, 0x92, 0x05 }, // 29
|
||||
{ 0xE2, 0xCF, 0x0C, 0x78, 0x09, 0x12, 0xD0, 0x0B, 0x06, 0x11 }, // 30
|
||||
{ 0xC2, 0xD3, 0x0C, 0x35, 0x65, 0xB2, 0xD3, 0x0B, 0x96, 0x65 }, // 31
|
||||
{ 0x32, 0xD4, 0x0B, 0x99, 0x77, 0x62, 0x90, 0x0B, 0x01, 0x78 }, // 32
|
||||
{ 0x42, 0xD4, 0x0B, 0x15, 0x76, 0x12, 0xD0, 0x0B, 0x10, 0x11 }, // 33
|
||||
{ 0xE2, 0xD5, 0x0C, 0x29, 0x99, 0x83, 0x92, 0x0C, 0x28, 0x98 }, // 34
|
||||
{ 0xE2, 0xCF, 0x0D, 0x85, 0x05, 0x12, 0xD0, 0x0E, 0x94, 0x05 }, // 35
|
||||
{ 0xE2, 0xD5, 0x0D, 0x36, 0x99, 0x02, 0xD6, 0x0F, 0x67, 0x95 }, // 36
|
||||
{ 0xE2, 0xD5, 0x0B, 0x08, 0x95, 0x02, 0xD6, 0x0E, 0x66, 0x95 }, // 37
|
||||
{ 0xE2, 0xD5, 0x0B, 0x34, 0x99, 0x83, 0x92, 0x0C, 0x29, 0x98 }, // 38
|
||||
{ 0xE2, 0xCF, 0x0C, 0x89, 0x05, 0x12, 0xD0, 0x0C, 0x98, 0x05 }, // 39
|
||||
{ 0xE2, 0xD5, 0x0B, 0x08, 0x95, 0x02, 0xD6, 0x0E, 0x67, 0x95 }, // 40
|
||||
{ 0xE2, 0xCF, 0x0C, 0x74, 0x09, 0x12, 0xD0, 0x0C, 0x96, 0x05 }, // 41
|
||||
{ 0xE2, 0xCF, 0x0C, 0x74, 0x09, 0x12, 0xD0, 0x0E, 0x95, 0x05 }, // 42
|
||||
{ 0x32, 0xD4, 0x0B, 0x89, 0x84, 0x73, 0x90, 0x0C, 0x86, 0x84 }, // 43
|
||||
{ 0x32, 0xD4, 0x0B, 0x00, 0x78, 0x62, 0x90, 0x0B, 0x02, 0x78 }, // 44
|
||||
{ 0xE2, 0xCF, 0x0B, 0x82, 0x05, 0x12, 0xD0, 0x0D, 0x91, 0x05 }, // 45
|
||||
{ 0xE2, 0xD5, 0x0D, 0x99, 0x94, 0x02, 0xD6, 0x0D, 0x68, 0x95 }, // 46
|
||||
{ 0xE2, 0xCF, 0x0C, 0x74, 0x09, 0x12, 0xD0, 0x0C, 0x95, 0x05 }, // 47
|
||||
{ 0xE2, 0xD5, 0x0B, 0x34, 0x99, 0x83, 0x92, 0x0C, 0x28, 0x98 }, // 48
|
||||
{ 0xE2, 0xCF, 0x0D, 0x77, 0x09, 0x12, 0xD0, 0x0C, 0x05, 0x11 }, // 49
|
||||
{ 0xE2, 0xCF, 0x0B, 0x44, 0x34, 0x12, 0xD0, 0x0C, 0x34, 0x35 }, // 50
|
||||
{ 0xE2, 0xD5, 0x0C, 0x67, 0x00, 0x83, 0x92, 0x0C, 0x27, 0x98 }, // 51
|
||||
{ 0xE2, 0xD5, 0x0B, 0x34, 0x99, 0x83, 0x92, 0x0C, 0x27, 0x98 }, // 52
|
||||
{ 0x42, 0xD4, 0x0B, 0x83, 0x71, 0x32, 0xD2, 0x0C, 0x44, 0x55 }, // 53
|
||||
{ 0xE2, 0xCF, 0x0C, 0x74, 0x09, 0x12, 0xD0, 0x0E, 0x94, 0x05 }, // 54
|
||||
};
|
||||
int PanasonicDecode::getBit1(uint8_t input) {
|
||||
return input >> 7;
|
||||
}
|
||||
|
||||
int PanasonicDecode::getBit1(uint8_t input)
|
||||
{
|
||||
return input >> 7;
|
||||
int PanasonicDecode::getBit1and2(uint8_t input) {
|
||||
return (input >> 6) - 1;
|
||||
}
|
||||
|
||||
int PanasonicDecode::getBit3and4(uint8_t input) {
|
||||
return ((input >> 4) & 0b11) - 1;
|
||||
}
|
||||
|
||||
int PanasonicDecode::getBit5and6(uint8_t input) {
|
||||
return ((input >> 2) & 0b11) - 1;
|
||||
}
|
||||
|
||||
int PanasonicDecode::getBit7and8(uint8_t input) {
|
||||
return (input & 0b11) - 1;
|
||||
}
|
||||
|
||||
int PanasonicDecode::getBit3and4and5(uint8_t input) {
|
||||
return ((input >> 3) & 0b111) - 1;
|
||||
}
|
||||
|
||||
int PanasonicDecode::getBit6and7and8(uint8_t input) {
|
||||
return (input & 0b111) - 1;
|
||||
}
|
||||
|
||||
int PanasonicDecode::getByteMinus1(uint8_t input) {
|
||||
return (int)input - 1;
|
||||
}
|
||||
|
||||
int PanasonicDecode::getByteMinus128(uint8_t input) {
|
||||
return (int)input - 128;
|
||||
}
|
||||
|
||||
float PanasonicDecode::getByteMinus1Div2(uint8_t input) {
|
||||
return ((float)input - 1) / 2;
|
||||
}
|
||||
|
||||
float PanasonicDecode::getByteMinus1Div5(uint8_t input) {
|
||||
return ((float)input - 1) / 5;
|
||||
}
|
||||
|
||||
float PanasonicDecode::getByteMinus1Div50(uint8_t input) {
|
||||
return ((float)input - 1) / 50;
|
||||
}
|
||||
|
||||
int PanasonicDecode::getByteMinus1Times10(uint8_t input) {
|
||||
return ((int)input - 1) * 10;
|
||||
}
|
||||
|
||||
int PanasonicDecode::getByteMinus1Times50(uint8_t input) {
|
||||
return ((int)input - 1) * 50;
|
||||
}
|
||||
|
||||
int PanasonicDecode::getByteMinus1Times200(uint8_t input) {
|
||||
return ((int)input - 1) * 200;
|
||||
}
|
||||
|
||||
int PanasonicDecode::getHighNibbleMinus1(uint8_t input) {
|
||||
return (input >> 4) - 1;
|
||||
}
|
||||
|
||||
int PanasonicDecode::getLowNibbleMinus1(uint8_t input) {
|
||||
return (input & 0b1111) - 1;
|
||||
}
|
||||
|
||||
int PanasonicDecode::getWordMinus1(const std::vector<uint8_t>& data, uint8_t index) {
|
||||
return ((data[index + 1] << 8) + data[index]) - 1;
|
||||
}
|
||||
|
||||
int PanasonicDecode::getUintt16(const std::vector<uint8_t>& data, uint8_t index) {
|
||||
return (static_cast<uint16_t>((data[index + 1] << 8) | data[index])) - 1;
|
||||
}
|
||||
|
||||
// TOP4 //
|
||||
int PanasonicDecode::getOperationMode(uint8_t input) {
|
||||
switch ((int)(input & 0b111111)) {
|
||||
case 0b100001:
|
||||
return 0; // 0x21 = tank
|
||||
case 0b010010:
|
||||
return 1; // 0x12 = heat
|
||||
case 0b100010:
|
||||
return 2; // 0x22 = heat+tank
|
||||
case 0b010011:
|
||||
return 3; // 0x13 = cool
|
||||
case 0b100011:
|
||||
return 4; // 0x23 = cool+tank
|
||||
case 0b011000:
|
||||
return 5; // 0x18 = auto
|
||||
case 0b101000:
|
||||
return 6; // 0x28 = auto-tank
|
||||
case 0b011001:
|
||||
return 7; // 0x19 = auto-heat
|
||||
case 0b101001:
|
||||
return 8; // 0x29 = auto-heat+tank
|
||||
case 0b011010:
|
||||
return 9; // 0x1A = auto-cool
|
||||
case 0b101010:
|
||||
return 10; // 0x2A = auto-cool+tank
|
||||
default:
|
||||
return -1; // unknown
|
||||
}
|
||||
}
|
||||
|
||||
// TOP92 //
|
||||
int PanasonicDecode::getModel(const std::vector<uint8_t>& data, uint8_t index) {
|
||||
// Ensure there are at least 10 bytes in data message after the start index
|
||||
if (index + 10 > data.size())
|
||||
return -1;
|
||||
// Get model bytes from data message
|
||||
auto model = std::vector<uint8_t>(data.begin() + index, data.begin() + index + 10);
|
||||
// Search model bytes in the list of known models and return the index
|
||||
for (size_t i = 0; i < NUMBER_OF_MODELS; i++) {
|
||||
if (std::equal(KnownModels[i], KnownModels[i] + 10, model.begin())) {
|
||||
return static_cast<int>(i);
|
||||
}
|
||||
}
|
||||
|
||||
int PanasonicDecode::getBit1and2(uint8_t input)
|
||||
{
|
||||
return (input >> 6) - 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int PanasonicDecode::getBit3and4(uint8_t input)
|
||||
{
|
||||
return ((input >> 4) & 0b11) - 1;
|
||||
}
|
||||
// TOP1 //
|
||||
// input1 = data[169]
|
||||
// input2 = data[170]
|
||||
float PanasonicDecode::getPumpFlow(const std::vector<uint8_t>& data, uint8_t index) {
|
||||
return (((float)data[index] - 1) / 256) + ((int)data[index + 1]);
|
||||
}
|
||||
|
||||
int PanasonicDecode::getBit5and6(uint8_t input)
|
||||
{
|
||||
return ((input >> 2) & 0b11) - 1;
|
||||
}
|
||||
// TOP5, TOP6 //
|
||||
float PanasonicDecode::getFractional(uint8_t input, uint8_t shift) {
|
||||
return ((int)((input >> shift) & 0b111) - 1) * 0.25;
|
||||
}
|
||||
|
||||
int PanasonicDecode::getBit7and8(uint8_t input)
|
||||
{
|
||||
return (input & 0b11) - 1;
|
||||
}
|
||||
// TOP44 //
|
||||
// errorType = data[113]
|
||||
// errorNumber = data[114]
|
||||
std::string PanasonicDecode::getErrorInfo(uint8_t errorType, uint8_t errorNumber) {
|
||||
int error_type = (int)(errorType);
|
||||
int error_number = ((int)(errorNumber)) - 17;
|
||||
char error_string[10];
|
||||
|
||||
int PanasonicDecode::getBit3and4and5(uint8_t input)
|
||||
{
|
||||
return ((input >> 3) & 0b111) - 1;
|
||||
}
|
||||
switch (error_type) {
|
||||
case 177: // B1=F type error
|
||||
sprintf(error_string, "F%02X", error_number);
|
||||
break;
|
||||
case 161: // A1=H type error
|
||||
sprintf(error_string, "H%02X", error_number);
|
||||
break;
|
||||
default:
|
||||
sprintf(error_string, "No error");
|
||||
break;
|
||||
}
|
||||
|
||||
int PanasonicDecode::getBit6and7and8(uint8_t input)
|
||||
{
|
||||
return (input & 0b111) - 1;
|
||||
}
|
||||
return error_string;
|
||||
}
|
||||
|
||||
int PanasonicDecode::getByteMinus1(uint8_t input)
|
||||
{
|
||||
return (int)input - 1;
|
||||
}
|
||||
bool PanasonicDecode::getBinaryState(uint8_t input) {
|
||||
return input != 0;
|
||||
}
|
||||
|
||||
int PanasonicDecode::getByteMinus128(uint8_t input)
|
||||
{
|
||||
return (int)input - 128;
|
||||
}
|
||||
std::string PanasonicDecode::getTextState(const char* const array[], int index) {
|
||||
int size = atoi(array[0]);
|
||||
|
||||
float PanasonicDecode::getByteMinus1Div2(uint8_t input)
|
||||
{
|
||||
return ((float)input - 1) / 2;
|
||||
}
|
||||
if ((index < 0) || (index >= size)) {
|
||||
return "UNDEFINED";
|
||||
}
|
||||
|
||||
float PanasonicDecode::getByteMinus1Div5(uint8_t input)
|
||||
{
|
||||
return ((float)input - 1) / 5;
|
||||
}
|
||||
|
||||
float PanasonicDecode::getByteMinus1Div50(uint8_t input)
|
||||
{
|
||||
return ((float)input - 1) / 50;
|
||||
}
|
||||
|
||||
int PanasonicDecode::getByteMinus1Times10(uint8_t input)
|
||||
{
|
||||
return ((int)input - 1) * 10;
|
||||
}
|
||||
|
||||
int PanasonicDecode::getByteMinus1Times50(uint8_t input)
|
||||
{
|
||||
return ((int)input - 1) * 50;
|
||||
}
|
||||
|
||||
int PanasonicDecode::getByteMinus1Times200(uint8_t input)
|
||||
{
|
||||
return ((int)input - 1) * 200;
|
||||
}
|
||||
|
||||
int PanasonicDecode::getHighNibbleMinus1(uint8_t input)
|
||||
{
|
||||
return (input >> 4) - 1;
|
||||
}
|
||||
|
||||
int PanasonicDecode::getLowNibbleMinus1(uint8_t input)
|
||||
{
|
||||
return (input & 0b1111) - 1;
|
||||
}
|
||||
|
||||
int PanasonicDecode::getWordMinus1(const std::vector<uint8_t>& data, uint8_t index)
|
||||
{
|
||||
return ((data[index + 1] << 8) + data[index]) - 1;
|
||||
}
|
||||
|
||||
int PanasonicDecode::getUintt16(const std::vector<uint8_t>& data, uint8_t index)
|
||||
{
|
||||
return (static_cast<uint16_t>((data[index + 1] << 8) | data[index])) - 1;
|
||||
}
|
||||
|
||||
// TOP4 //
|
||||
int PanasonicDecode::getOperationMode(uint8_t input)
|
||||
{
|
||||
switch ((int)(input & 0b111111))
|
||||
{
|
||||
case 0b100001: return 0; // 0x21 = tank
|
||||
case 0b010010: return 1; // 0x12 = heat
|
||||
case 0b100010: return 2; // 0x22 = heat+tank
|
||||
case 0b010011: return 3; // 0x13 = cool
|
||||
case 0b100011: return 4; // 0x23 = cool+tank
|
||||
case 0b011000: return 5; // 0x18 = auto
|
||||
case 0b101000: return 6; // 0x28 = auto-tank
|
||||
case 0b011001: return 7; // 0x19 = auto-heat
|
||||
case 0b101001: return 8; // 0x29 = auto-heat+tank
|
||||
case 0b011010: return 9; // 0x1A = auto-cool
|
||||
case 0b101010: return 10; // 0x2A = auto-cool+tank
|
||||
default: return -1; // unknown
|
||||
}
|
||||
}
|
||||
|
||||
// TOP92 //
|
||||
int PanasonicDecode::getModel(const std::vector<uint8_t>& data, uint8_t index)
|
||||
{
|
||||
// Ensure there are at least 10 bytes in data message after the start index
|
||||
if (index + 10 > data.size()) return -1;
|
||||
// Get model bytes from data message
|
||||
auto model = std::vector<uint8_t>(data.begin() + index, data.begin() + index + 10);
|
||||
// Search model bytes in the list of known models and return the index
|
||||
for (size_t i = 0; i < NUMBER_OF_MODELS; i++)
|
||||
{
|
||||
if (std::equal(KnownModels[i], KnownModels[i] + 10, model.begin()))
|
||||
{
|
||||
return static_cast<int>(i);
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// TOP1 //
|
||||
// input1 = data[169]
|
||||
// input2 = data[170]
|
||||
float PanasonicDecode::getPumpFlow(const std::vector<uint8_t>& data, uint8_t index)
|
||||
{
|
||||
return (((float)data[index] - 1) / 256) + ((int)data[index + 1]);
|
||||
}
|
||||
|
||||
// TOP5, TOP6 //
|
||||
float PanasonicDecode::getFractional(uint8_t input, uint8_t shift)
|
||||
{
|
||||
return ((int)((input >> shift) & 0b111) - 1) * 0.25;
|
||||
}
|
||||
|
||||
// TOP44 //
|
||||
// errorType = data[113]
|
||||
// errorNumber = data[114]
|
||||
std::string PanasonicDecode::getErrorInfo(uint8_t errorType, uint8_t errorNumber)
|
||||
{
|
||||
int error_type = (int)(errorType);
|
||||
int error_number = ((int)(errorNumber)) - 17;
|
||||
char error_string[10];
|
||||
|
||||
switch (error_type)
|
||||
{
|
||||
case 177: // B1=F type error
|
||||
sprintf(error_string, "F%02X", error_number);
|
||||
break;
|
||||
case 161: // A1=H type error
|
||||
sprintf(error_string, "H%02X", error_number);
|
||||
break;
|
||||
default:
|
||||
sprintf(error_string, "No error");
|
||||
break;
|
||||
}
|
||||
|
||||
return error_string;
|
||||
}
|
||||
|
||||
bool PanasonicDecode::getBinaryState(uint8_t input)
|
||||
{
|
||||
return input != 0;
|
||||
}
|
||||
|
||||
std::string PanasonicDecode::getTextState(const char* const array[], int index)
|
||||
{
|
||||
int size = atoi(array[0]);
|
||||
|
||||
if ((index < 0) || (index >= size))
|
||||
{
|
||||
return "UNDEFINED";
|
||||
}
|
||||
|
||||
return array[index + 1];
|
||||
}
|
||||
} // namespace panasonic_heatpump
|
||||
return array[index + 1];
|
||||
}
|
||||
} // namespace panasonic_heatpump
|
||||
} // namespace esphome
|
||||
|
|
|
|||
|
|
@ -10,129 +10,123 @@
|
|||
#define NUMBER_OF_MODELS 55
|
||||
#endif
|
||||
|
||||
namespace esphome {
|
||||
namespace panasonic_heatpump {
|
||||
class PanasonicDecode {
|
||||
public:
|
||||
PanasonicDecode() = delete;
|
||||
|
||||
namespace esphome
|
||||
{
|
||||
namespace panasonic_heatpump
|
||||
{
|
||||
class PanasonicDecode
|
||||
{
|
||||
public:
|
||||
PanasonicDecode() = delete;
|
||||
static int getBit1(uint8_t input);
|
||||
static int getBit1and2(uint8_t input);
|
||||
static int getBit3and4(uint8_t input);
|
||||
static int getBit5and6(uint8_t input);
|
||||
static int getBit7and8(uint8_t input);
|
||||
static int getBit3and4and5(uint8_t input);
|
||||
static int getBit6and7and8(uint8_t input);
|
||||
static int getByteMinus1(uint8_t input);
|
||||
static int getByteMinus128(uint8_t input);
|
||||
static float getByteMinus1Div2(uint8_t input);
|
||||
static float getByteMinus1Div5(uint8_t input);
|
||||
static float getByteMinus1Div50(uint8_t input);
|
||||
static int getByteMinus1Times10(uint8_t input);
|
||||
static int getByteMinus1Times50(uint8_t input);
|
||||
static int getByteMinus1Times200(uint8_t input);
|
||||
static int getHighNibbleMinus1(uint8_t input);
|
||||
static int getLowNibbleMinus1(uint8_t input);
|
||||
static int getWordMinus1(const std::vector<uint8_t>& data, uint8_t index);
|
||||
static int getUintt16(const std::vector<uint8_t>& data, uint8_t index);
|
||||
|
||||
static int getBit1(uint8_t input);
|
||||
static int getBit1and2(uint8_t input);
|
||||
static int getBit3and4(uint8_t input);
|
||||
static int getBit5and6(uint8_t input);
|
||||
static int getBit7and8(uint8_t input);
|
||||
static int getBit3and4and5(uint8_t input);
|
||||
static int getBit6and7and8(uint8_t input);
|
||||
static int getByteMinus1(uint8_t input);
|
||||
static int getByteMinus128(uint8_t input);
|
||||
static float getByteMinus1Div2(uint8_t input);
|
||||
static float getByteMinus1Div5(uint8_t input);
|
||||
static float getByteMinus1Div50(uint8_t input);
|
||||
static int getByteMinus1Times10(uint8_t input);
|
||||
static int getByteMinus1Times50(uint8_t input);
|
||||
static int getByteMinus1Times200(uint8_t input);
|
||||
static int getHighNibbleMinus1(uint8_t input);
|
||||
static int getLowNibbleMinus1(uint8_t input);
|
||||
static int getWordMinus1(const std::vector<uint8_t>& data, uint8_t index);
|
||||
static int getUintt16(const std::vector<uint8_t>& data, uint8_t index);
|
||||
static int getOperationMode(uint8_t input);
|
||||
static int getModel(const std::vector<uint8_t>& data, uint8_t index);
|
||||
static float getPumpFlow(const std::vector<uint8_t>& data, uint8_t index);
|
||||
static float getFractional(uint8_t input, uint8_t shift);
|
||||
static std::string getErrorInfo(uint8_t errorType, uint8_t errorNumber);
|
||||
|
||||
static int getOperationMode(uint8_t input);
|
||||
static int getModel(const std::vector<uint8_t>& data, uint8_t index);
|
||||
static float getPumpFlow(const std::vector<uint8_t>& data, uint8_t index);
|
||||
static float getFractional(uint8_t input, uint8_t shift);
|
||||
static std::string getErrorInfo(uint8_t errorType, uint8_t errorNumber);
|
||||
static bool getBinaryState(uint8_t input);
|
||||
static std::string getTextState(const char* const array[], int index);
|
||||
|
||||
static bool getBinaryState(uint8_t input);
|
||||
static std::string getTextState(const char* const array[], int index);
|
||||
static const constexpr char* const DisabledEnabled[] = {"2", "Disabled", "Enabled"};
|
||||
static const constexpr char* const BlockedFree[] = {"2", "Blocked", "Free"};
|
||||
static const constexpr char* const OffOn[] = {"2", "Off", "On"};
|
||||
static const constexpr char* const InactiveActive[] = {"2", "Inactive", "Active"};
|
||||
static const constexpr char* const PumpFlowRateMode[] = {"2", "DeltaT", "Max flow"};
|
||||
static const constexpr char* const ThreeWayValve[] = {"2", "Buffer Tank", "DHW Tank"};
|
||||
static const constexpr char* const TwoWayValve[] = {"2", "Cool", "Heat"};
|
||||
static const constexpr char* const WaterTempControl[] = {"2", "Comp. Curve", "Direct"};
|
||||
static const constexpr char* const LiquidType[] = {"2", "Water", "Glycol"};
|
||||
static const constexpr char* const HolidayState[] = {"3", "Off", "Scheduled", "Active"};
|
||||
static const constexpr char* const SolarMode[] = {"3", "Disabled", "Buffer Tank", "DHW Tank"};
|
||||
static const constexpr char* const MixingValve[] = {"4", "Off", "Decrease", "Increase", "Invalid"};
|
||||
static const constexpr char* const ZoneSensorType[] = {"4", "Water Temperature", "External Thermostat",
|
||||
"Internal Thermostat", "Thermistor"};
|
||||
static const constexpr char* const QuietMode[] = {"4", "Off", "Level 1", "Level 2", "Level 3"};
|
||||
static const constexpr char* const PowerfulMode[] = {"4", "Off", "30min", "60min", "90min"};
|
||||
static const constexpr char* const OperationMode[] = {
|
||||
"11", "TANK", "HEAT", "HEAT+TANK", "COOL", "COOL+TANK",
|
||||
"AUTO", "AUTO+TANK", "AUTO(HEAT)", "AUTO(HEAT)+TANK", "AUTO(COOL)", "AUTO(COOL)+TANK"};
|
||||
static const constexpr char* const ZoneState[] = {"3", "Zone 1", "Zone 2", "Zone 1 & 2"};
|
||||
static const constexpr char* const ExtPadHeaterType[] = {"3", "Disabled", "Type-A", "Type-B"};
|
||||
static const constexpr char* const BivalentMode[] = {"3", "Alternative", "Parallel", "Advanced Parallel"};
|
||||
static const constexpr char* const ModelNames[] = {
|
||||
"55", // string representation of number of known models (last model number + 1)
|
||||
"WH-MDC05H3E5", // 0
|
||||
"WH-MDC07H3E5", // 1
|
||||
"IDU:WH-SXC09H3E5, ODU:WH-UX09HE5", // 2
|
||||
"IDU:WH-SDC09H3E8, ODU:WH-UD09HE8", // 3
|
||||
"IDU:WH-SXC09H3E8, ODU:WH-UX09HE8", // 4
|
||||
"IDU:WH-SXC12H9E8, ODU:WH-UX12HE8", // 5
|
||||
"IDU:WH-SXC16H9E8, ODU:WH-UX16HE8", // 6
|
||||
"IDU:WH-SDC05H3E5, ODU:WH-UD05HE5", // 7
|
||||
"IDU:WH-SDC0709J3E5, ODU:WH-UD09JE5", // 8
|
||||
"WH-MDC05J3E5", // 9
|
||||
"WH-MDC09H3E5", // 10
|
||||
"WH-MXC09H3E5", // 11
|
||||
"IDU:WH-ADC0309J3E5, ODU:WH-UD09JE5", // 12
|
||||
"IDU:WH-ADC0916H9E8, ODU:WH-UX12HE8", // 13
|
||||
"IDU:WH-SQC09H3E8, ODU:WH-UQ09HE8", // 14
|
||||
"IDU:WH-SDC09H3E5, ODU:WH-UD09HE5", // 15
|
||||
"IDU:WH-ADC0309H3E5, ODU:WH-UD09HE5", // 16
|
||||
"IDU:WH-ADC0309J3E5, ODU:WH-UD05JE5", // 17
|
||||
"IDU:WH-SDC0709J3E5, ODU:WH-UD07JE5", // 18
|
||||
"IDU:WH-SDC07H3E5-1, ODU:WH-UD07HE5-1", // 19
|
||||
"WH-MDC07J3E5", // 20
|
||||
"WH-MDC09J3E5", // 21
|
||||
"IDU:WH-SDC0305J3E5, ODU:WH-UD05JE5", // 22
|
||||
"WH-MXC09J3E8", // 23
|
||||
"WH-MXC12J9E8", // 24
|
||||
"IDU:WH-ADC1216H6E5, ODU:WH-UD12HE5", // 25
|
||||
"IDU:WH-ADC0309J3E5C, ODU:WH-UD07JE5", // 26
|
||||
"WH-MDC07J3E5", // 27
|
||||
"WH-MDC05J3E5", // 28
|
||||
"IDU:WH-SQC12H9E8, ODU:WH-UQ12HE8", // 29
|
||||
"IDU:WH-SXC12H6E5, ODU:WH-UX12HE5", // 30
|
||||
"WH-MDC09J3E5", // 31
|
||||
"WH-MXC09J3E5", // 32
|
||||
"IDU:WH-ADC1216H6E5C, ODU:WH-UD12HE5", // 33
|
||||
"IDU:WH-ADC0509L3E5, ODU:WH-WDG07LE5", // 34
|
||||
"IDU:WH-SXC09H3E8, ODU:WH-UX09HE8", // 35
|
||||
"IDU:WH-ADC0309K3E5AN, ODU:WH-UDZ07KE5", // 36
|
||||
"IDU:WH-SDC0309K3E5, ODU:WH-UDZ05KE5", // 37
|
||||
"IDU:WH-SDC0509L3E5, ODU:WH-WDG09LE5", // 38
|
||||
"IDU:WH-SDC12H9E8, ODU:WH-UD12HE8", // 39
|
||||
"IDU:WH-SDC0309K3E5, ODU:WH-UDZ07KE5", // 40
|
||||
"IDU:WH-ADC0916H9E8, ODU:WH-UX16HE8", // 41
|
||||
"IDU:WH-ADC0912H9E8, ODU:WH-UX12HE8", // 42
|
||||
"WH-MXC16J9E8", // 43
|
||||
"WH-MXC12J6E5", // 44
|
||||
"IDU:WH-SQC09H3E8, ODU:WH-UQ09HE8", // 45
|
||||
"IDU:WH-ADC0309K3E5, ODU:WH-UDZ09KE5", // 46
|
||||
"IDU:WH-ADC0916H9E8, ODU:WH-UX12HE8", // 47
|
||||
"IDU:WH-SDC0509L3E5, ODU:WH-WDG07LE5", // 48
|
||||
"IDU:WH-SXC09H3E5, ODU:WH-UX09HE5", // 49
|
||||
"WH-MXC12H9E8", // 50
|
||||
"IDU:WH-ADC0509L3E5AN, ODU:WH-WDG05LE5", // 51
|
||||
"IDU:WH-SDC0509L3E5, ODU:WH-WDG05LE5", // 52
|
||||
"IDU:WH-ADC0309J3E5C, ODU:WH-UD03JE5", // 53
|
||||
"IDU:WH-ADC0916H9E8, ODU:WH-UX09HE8", // 54
|
||||
};
|
||||
};
|
||||
|
||||
static const constexpr char* const DisabledEnabled[] = { "2", "Disabled", "Enabled" };
|
||||
static const constexpr char* const BlockedFree[] = { "2", "Blocked", "Free" };
|
||||
static const constexpr char* const OffOn[] = { "2", "Off", "On" };
|
||||
static const constexpr char* const InactiveActive[] = { "2", "Inactive", "Active" };
|
||||
static const constexpr char* const PumpFlowRateMode[] = { "2", "DeltaT", "Max flow" };
|
||||
static const constexpr char* const ThreeWayValve[] = { "2", "Buffer Tank", "DHW Tank" };
|
||||
static const constexpr char* const TwoWayValve[] = { "2", "Cool", "Heat" };
|
||||
static const constexpr char* const WaterTempControl[] = { "2", "Comp. Curve", "Direct" };
|
||||
static const constexpr char* const LiquidType[] = { "2", "Water", "Glycol" };
|
||||
static const constexpr char* const HolidayState[] = { "3", "Off", "Scheduled", "Active" };
|
||||
static const constexpr char* const SolarMode[] = { "3", "Disabled", "Buffer Tank", "DHW Tank" };
|
||||
static const constexpr char* const MixingValve[] = { "4", "Off", "Decrease","Increase", "Invalid" };
|
||||
static const constexpr char* const ZoneSensorType[] = { "4", "Water Temperature", "External Thermostat", "Internal Thermostat", "Thermistor" };
|
||||
static const constexpr char* const QuietMode[] = { "4", "Off", "Level 1", "Level 2", "Level 3" };
|
||||
static const constexpr char* const PowerfulMode[] = { "4", "Off", "30min", "60min", "90min" };
|
||||
static const constexpr char* const OperationMode[] =
|
||||
{
|
||||
"11", "TANK", "HEAT", "HEAT+TANK", "COOL", "COOL+TANK", "AUTO", "AUTO+TANK",
|
||||
"AUTO(HEAT)", "AUTO(HEAT)+TANK", "AUTO(COOL)", "AUTO(COOL)+TANK"
|
||||
};
|
||||
static const constexpr char* const ZoneState[] = { "3", "Zone 1", "Zone 2", "Zone 1 & 2" };
|
||||
static const constexpr char* const ExtPadHeaterType[] = { "3", "Disabled", "Type-A", "Type-B" };
|
||||
static const constexpr char* const BivalentMode[] = { "3", "Alternative", "Parallel", "Advanced Parallel" };
|
||||
static const constexpr char* const ModelNames[] =
|
||||
{
|
||||
"55", // string representation of number of known models (last model number + 1)
|
||||
"WH-MDC05H3E5", // 0
|
||||
"WH-MDC07H3E5", // 1
|
||||
"IDU:WH-SXC09H3E5, ODU:WH-UX09HE5", // 2
|
||||
"IDU:WH-SDC09H3E8, ODU:WH-UD09HE8", // 3
|
||||
"IDU:WH-SXC09H3E8, ODU:WH-UX09HE8", // 4
|
||||
"IDU:WH-SXC12H9E8, ODU:WH-UX12HE8", // 5
|
||||
"IDU:WH-SXC16H9E8, ODU:WH-UX16HE8", // 6
|
||||
"IDU:WH-SDC05H3E5, ODU:WH-UD05HE5", // 7
|
||||
"IDU:WH-SDC0709J3E5, ODU:WH-UD09JE5", // 8
|
||||
"WH-MDC05J3E5", // 9
|
||||
"WH-MDC09H3E5", // 10
|
||||
"WH-MXC09H3E5", // 11
|
||||
"IDU:WH-ADC0309J3E5, ODU:WH-UD09JE5", // 12
|
||||
"IDU:WH-ADC0916H9E8, ODU:WH-UX12HE8", // 13
|
||||
"IDU:WH-SQC09H3E8, ODU:WH-UQ09HE8", // 14
|
||||
"IDU:WH-SDC09H3E5, ODU:WH-UD09HE5", // 15
|
||||
"IDU:WH-ADC0309H3E5, ODU:WH-UD09HE5", // 16
|
||||
"IDU:WH-ADC0309J3E5, ODU:WH-UD05JE5", // 17
|
||||
"IDU:WH-SDC0709J3E5, ODU:WH-UD07JE5", // 18
|
||||
"IDU:WH-SDC07H3E5-1, ODU:WH-UD07HE5-1", // 19
|
||||
"WH-MDC07J3E5", // 20
|
||||
"WH-MDC09J3E5", // 21
|
||||
"IDU:WH-SDC0305J3E5, ODU:WH-UD05JE5", // 22
|
||||
"WH-MXC09J3E8", // 23
|
||||
"WH-MXC12J9E8", // 24
|
||||
"IDU:WH-ADC1216H6E5, ODU:WH-UD12HE5", // 25
|
||||
"IDU:WH-ADC0309J3E5C, ODU:WH-UD07JE5", // 26
|
||||
"WH-MDC07J3E5", // 27
|
||||
"WH-MDC05J3E5", // 28
|
||||
"IDU:WH-SQC12H9E8, ODU:WH-UQ12HE8", // 29
|
||||
"IDU:WH-SXC12H6E5, ODU:WH-UX12HE5", // 30
|
||||
"WH-MDC09J3E5", // 31
|
||||
"WH-MXC09J3E5", // 32
|
||||
"IDU:WH-ADC1216H6E5C, ODU:WH-UD12HE5", // 33
|
||||
"IDU:WH-ADC0509L3E5, ODU:WH-WDG07LE5", // 34
|
||||
"IDU:WH-SXC09H3E8, ODU:WH-UX09HE8", // 35
|
||||
"IDU:WH-ADC0309K3E5AN, ODU:WH-UDZ07KE5", // 36
|
||||
"IDU:WH-SDC0309K3E5, ODU:WH-UDZ05KE5", // 37
|
||||
"IDU:WH-SDC0509L3E5, ODU:WH-WDG09LE5", // 38
|
||||
"IDU:WH-SDC12H9E8, ODU:WH-UD12HE8", // 39
|
||||
"IDU:WH-SDC0309K3E5, ODU:WH-UDZ07KE5", // 40
|
||||
"IDU:WH-ADC0916H9E8, ODU:WH-UX16HE8", // 41
|
||||
"IDU:WH-ADC0912H9E8, ODU:WH-UX12HE8", // 42
|
||||
"WH-MXC16J9E8", // 43
|
||||
"WH-MXC12J6E5", // 44
|
||||
"IDU:WH-SQC09H3E8, ODU:WH-UQ09HE8", // 45
|
||||
"IDU:WH-ADC0309K3E5, ODU:WH-UDZ09KE5", // 46
|
||||
"IDU:WH-ADC0916H9E8, ODU:WH-UX12HE8", // 47
|
||||
"IDU:WH-SDC0509L3E5, ODU:WH-WDG07LE5", // 48
|
||||
"IDU:WH-SXC09H3E5, ODU:WH-UX09HE5", // 49
|
||||
"WH-MXC12H9E8", // 50
|
||||
"IDU:WH-ADC0509L3E5AN, ODU:WH-WDG05LE5", // 51
|
||||
"IDU:WH-SDC0509L3E5, ODU:WH-WDG05LE5", // 52
|
||||
"IDU:WH-ADC0309J3E5C, ODU:WH-UD03JE5", // 53
|
||||
"IDU:WH-ADC0916H9E8, ODU:WH-UX09HE8", // 54
|
||||
};
|
||||
};
|
||||
|
||||
extern const uint8_t KnownModels[NUMBER_OF_MODELS][10];
|
||||
} // namespace panasonic_heatpump
|
||||
extern const uint8_t KnownModels[NUMBER_OF_MODELS][10];
|
||||
} // namespace panasonic_heatpump
|
||||
} // namespace esphome
|
||||
|
|
|
|||
|
|
@ -1,66 +1,59 @@
|
|||
#include "helpers.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace panasonic_heatpump {
|
||||
static const char* const TAG = "panasonic_heatpump";
|
||||
|
||||
namespace esphome
|
||||
{
|
||||
namespace panasonic_heatpump
|
||||
{
|
||||
static const char *const TAG = "panasonic_heatpump";
|
||||
void PanasonicHelpers::log_uart_hex(UartLogDirection direction, const std::vector<uint8_t>& data,
|
||||
const char separator) {
|
||||
PanasonicHelpers::log_uart_hex(direction, &data[0], data.size(), separator);
|
||||
}
|
||||
|
||||
void PanasonicHelpers::log_uart_hex(UartLogDirection direction, const std::vector<uint8_t>& data, const char separator)
|
||||
{
|
||||
PanasonicHelpers::log_uart_hex(direction, &data[0], data.size(), separator);
|
||||
}
|
||||
void PanasonicHelpers::log_uart_hex(UartLogDirection direction, const uint8_t* data, const size_t length,
|
||||
const char separator) {
|
||||
std::string logStr = "";
|
||||
std::string msgDir = direction == UART_LOG_TX ? ">>>" : "<<<";
|
||||
std::string msgType = direction == UART_LOG_TX ? "request" : "response";
|
||||
switch (data[0]) {
|
||||
case 0x31:
|
||||
msgType = "initial_" + msgType;
|
||||
break;
|
||||
case 0x71:
|
||||
msgType = "polling_" + msgType;
|
||||
if (data[3] == 0x21)
|
||||
msgType = "extra_" + msgType;
|
||||
break;
|
||||
case 0xF1:
|
||||
msgType = "command_" + msgType;
|
||||
break;
|
||||
};
|
||||
|
||||
void PanasonicHelpers::log_uart_hex(UartLogDirection direction, const uint8_t* data, const size_t length, const char separator)
|
||||
{
|
||||
std::string logStr = "";
|
||||
std::string msgDir = direction == UART_LOG_TX ? ">>>" : "<<<";
|
||||
std::string msgType = direction == UART_LOG_TX ? "request" : "response";
|
||||
switch(data[0])
|
||||
{
|
||||
case 0x31:
|
||||
msgType = "initial_" + msgType;
|
||||
break;
|
||||
case 0x71:
|
||||
msgType = "polling_" + msgType;
|
||||
if (data[3] == 0x21) msgType = "extra_" + msgType;
|
||||
break;
|
||||
case 0xF1:
|
||||
msgType = "command_" + msgType;
|
||||
break;
|
||||
};
|
||||
ESP_LOGI(TAG, "%s %s[%i]", msgDir.c_str(), msgType.c_str(), length);
|
||||
delay(10);
|
||||
|
||||
ESP_LOGI(TAG, "%s %s[%i]", msgDir.c_str(), msgType.c_str(), length);
|
||||
delay(10);
|
||||
logStr += byte_array_to_hex_string(data, length, separator);
|
||||
|
||||
logStr += byte_array_to_hex_string(data, length, separator);
|
||||
for (size_t i = 0; i < logStr.length(); i += UART_LOG_CHUNK_SIZE) {
|
||||
ESP_LOGI(TAG, "%s %s", msgDir.c_str(), logStr.substr(i, UART_LOG_CHUNK_SIZE).c_str());
|
||||
delay(10);
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < logStr.length(); i += UART_LOG_CHUNK_SIZE)
|
||||
{
|
||||
ESP_LOGI(TAG, "%s %s", msgDir.c_str(), logStr.substr(i, UART_LOG_CHUNK_SIZE).c_str());
|
||||
delay(10);
|
||||
}
|
||||
}
|
||||
std::string PanasonicHelpers::byte_array_to_hex_string(const std::vector<uint8_t>& data, const char separator) {
|
||||
return PanasonicHelpers::byte_array_to_hex_string(&data[0], data.size(), separator);
|
||||
}
|
||||
|
||||
std::string PanasonicHelpers::byte_array_to_hex_string(const std::vector<uint8_t>& data, const char separator)
|
||||
{
|
||||
return PanasonicHelpers::byte_array_to_hex_string(&data[0], data.size(), separator);
|
||||
}
|
||||
std::string PanasonicHelpers::byte_array_to_hex_string(const uint8_t* data, const size_t length, const char separator) {
|
||||
std::string hexStr = "";
|
||||
char buffer[5];
|
||||
|
||||
std::string PanasonicHelpers::byte_array_to_hex_string(const uint8_t* data, const size_t length, const char separator)
|
||||
{
|
||||
std::string hexStr = "";
|
||||
char buffer[5];
|
||||
|
||||
for (size_t i = 0; i < length; i++)
|
||||
{
|
||||
if (i > 0) hexStr += separator;
|
||||
sprintf(buffer, "%02X", data[i]);
|
||||
hexStr += buffer;
|
||||
}
|
||||
|
||||
return hexStr;
|
||||
}
|
||||
} // namespace panasonic_heatpump
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
if (i > 0)
|
||||
hexStr += separator;
|
||||
sprintf(buffer, "%02X", data[i]);
|
||||
hexStr += buffer;
|
||||
}
|
||||
return hexStr;
|
||||
}
|
||||
} // namespace panasonic_heatpump
|
||||
} // namespace esphome
|
||||
|
|
|
|||
|
|
@ -9,24 +9,19 @@
|
|||
#define UART_LOG_CHUNK_SIZE 120
|
||||
#endif
|
||||
|
||||
namespace esphome {
|
||||
namespace panasonic_heatpump {
|
||||
enum UartLogDirection : uint8_t {
|
||||
UART_LOG_RX,
|
||||
UART_LOG_TX,
|
||||
};
|
||||
|
||||
namespace esphome
|
||||
{
|
||||
namespace panasonic_heatpump
|
||||
{
|
||||
enum UartLogDirection : uint8_t
|
||||
{
|
||||
UART_LOG_RX,
|
||||
UART_LOG_TX,
|
||||
};
|
||||
|
||||
class PanasonicHelpers
|
||||
{
|
||||
public:
|
||||
static void log_uart_hex(UartLogDirection direction, const std::vector<uint8_t>& data, const char separator);
|
||||
static void log_uart_hex(UartLogDirection direction, const uint8_t* data, const size_t length, const char separator);
|
||||
static std::string byte_array_to_hex_string(const std::vector<uint8_t>& data, const char separator);
|
||||
static std::string byte_array_to_hex_string(const uint8_t* data, const size_t length, const char separator);
|
||||
};
|
||||
}
|
||||
}
|
||||
class PanasonicHelpers {
|
||||
public:
|
||||
static void log_uart_hex(UartLogDirection direction, const std::vector<uint8_t>& data, const char separator);
|
||||
static void log_uart_hex(UartLogDirection direction, const uint8_t* data, const size_t length, const char separator);
|
||||
static std::string byte_array_to_hex_string(const std::vector<uint8_t>& data, const char separator);
|
||||
static std::string byte_array_to_hex_string(const uint8_t* data, const size_t length, const char separator);
|
||||
};
|
||||
} // namespace panasonic_heatpump
|
||||
} // namespace esphome
|
||||
|
|
|
|||
|
|
@ -2,16 +2,19 @@ import esphome.codegen as cg
|
|||
import esphome.config_validation as cv
|
||||
from esphome.components import number
|
||||
from esphome.const import (
|
||||
UNIT_CELSIUS,
|
||||
UNIT_KELVIN,
|
||||
UNIT_MINUTE,
|
||||
ENTITY_CATEGORY_CONFIG,
|
||||
CONF_MIN_VALUE,
|
||||
CONF_MAX_VALUE,
|
||||
CONF_STEP,
|
||||
UNIT_CELSIUS,
|
||||
UNIT_KELVIN,
|
||||
UNIT_MINUTE,
|
||||
ENTITY_CATEGORY_CONFIG,
|
||||
CONF_MIN_VALUE,
|
||||
CONF_MAX_VALUE,
|
||||
CONF_STEP,
|
||||
)
|
||||
from .. import (
|
||||
CONF_PANASONIC_HEATPUMP_ID,
|
||||
PanasonicHeatpumpComponent,
|
||||
panasonic_heatpump_ns,
|
||||
)
|
||||
from .. import CONF_PANASONIC_HEATPUMP_ID, PanasonicHeatpumpComponent, panasonic_heatpump_ns
|
||||
|
||||
|
||||
CONF_SET5 = "set5" # Set Z1 Heat Request Temperature
|
||||
CONF_SET6 = "set6" # Set Z1 Cool Request Temperature
|
||||
|
|
@ -48,284 +51,224 @@ CONF_SET37 = "set37" # Set Bivalent AP Start Temp
|
|||
CONF_SET38 = "set38" # Set Bivalent AP Stop Temp
|
||||
|
||||
TYPES = [
|
||||
CONF_SET5,
|
||||
CONF_SET6,
|
||||
CONF_SET7,
|
||||
CONF_SET8,
|
||||
CONF_SET11,
|
||||
CONF_SET15,
|
||||
CONF_SET16_01,
|
||||
CONF_SET16_02,
|
||||
CONF_SET16_03,
|
||||
CONF_SET16_04,
|
||||
CONF_SET16_05,
|
||||
CONF_SET16_06,
|
||||
CONF_SET16_07,
|
||||
CONF_SET16_08,
|
||||
CONF_SET16_09,
|
||||
CONF_SET16_10,
|
||||
CONF_SET16_11,
|
||||
CONF_SET16_12,
|
||||
CONF_SET16_13,
|
||||
CONF_SET16_14,
|
||||
CONF_SET16_15,
|
||||
CONF_SET16_16,
|
||||
CONF_SET18,
|
||||
CONF_SET19,
|
||||
CONF_SET20,
|
||||
CONF_SET21,
|
||||
CONF_SET22,
|
||||
CONF_SET23,
|
||||
CONF_SET27,
|
||||
CONF_SET29,
|
||||
CONF_SET36,
|
||||
CONF_SET37,
|
||||
CONF_SET38,
|
||||
CONF_SET5,
|
||||
CONF_SET6,
|
||||
CONF_SET7,
|
||||
CONF_SET8,
|
||||
CONF_SET11,
|
||||
CONF_SET15,
|
||||
CONF_SET16_01,
|
||||
CONF_SET16_02,
|
||||
CONF_SET16_03,
|
||||
CONF_SET16_04,
|
||||
CONF_SET16_05,
|
||||
CONF_SET16_06,
|
||||
CONF_SET16_07,
|
||||
CONF_SET16_08,
|
||||
CONF_SET16_09,
|
||||
CONF_SET16_10,
|
||||
CONF_SET16_11,
|
||||
CONF_SET16_12,
|
||||
CONF_SET16_13,
|
||||
CONF_SET16_14,
|
||||
CONF_SET16_15,
|
||||
CONF_SET16_16,
|
||||
CONF_SET18,
|
||||
CONF_SET19,
|
||||
CONF_SET20,
|
||||
CONF_SET21,
|
||||
CONF_SET22,
|
||||
CONF_SET23,
|
||||
CONF_SET27,
|
||||
CONF_SET29,
|
||||
CONF_SET36,
|
||||
CONF_SET37,
|
||||
CONF_SET38,
|
||||
]
|
||||
|
||||
def number_options(min_val, max_val, step) -> cv.Schema:
|
||||
schema = cv.Schema({
|
||||
cv.Optional(CONF_MIN_VALUE, default=min_val): cv.float_,
|
||||
cv.Optional(CONF_MAX_VALUE, default=max_val): cv.float_,
|
||||
cv.Optional(CONF_STEP, default=step): cv.float_range(min=1.0, max=10.0),
|
||||
})
|
||||
return schema
|
||||
|
||||
PanasonicHeatpumpNumber = panasonic_heatpump_ns.class_("PanasonicHeatpumpNumber", number.Number, cg.Component)
|
||||
def number_options(min_val, max_val, step) -> cv.Schema:
|
||||
schema = cv.Schema(
|
||||
{
|
||||
cv.Optional(CONF_MIN_VALUE, default=min_val): cv.float_,
|
||||
cv.Optional(CONF_MAX_VALUE, default=max_val): cv.float_,
|
||||
cv.Optional(CONF_STEP, default=step): cv.float_range(min=1.0, max=10.0),
|
||||
}
|
||||
)
|
||||
return schema
|
||||
|
||||
|
||||
PanasonicHeatpumpNumber = panasonic_heatpump_ns.class_(
|
||||
"PanasonicHeatpumpNumber", number.Number, cg.Component
|
||||
)
|
||||
|
||||
CONFIG_SCHEMA = cv.Schema(
|
||||
{
|
||||
cv.GenerateID(CONF_PANASONIC_HEATPUMP_ID): cv.use_id(
|
||||
PanasonicHeatpumpComponent
|
||||
),
|
||||
|
||||
cv.Optional(CONF_SET5): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
).extend(
|
||||
number_options(-5.0, 5.0, 1.0)
|
||||
),
|
||||
cv.Optional(CONF_SET6): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
).extend(
|
||||
number_options(-5.0, 5.0, 1.0)
|
||||
),
|
||||
cv.Optional(CONF_SET7): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
).extend(
|
||||
number_options(-5.0, 5.0, 1.0)
|
||||
),
|
||||
cv.Optional(CONF_SET8): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
).extend(
|
||||
number_options(-5.0, 5.0, 1.0)
|
||||
),
|
||||
cv.Optional(CONF_SET11): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
).extend(
|
||||
number_options(40.0, 75.0, 1.0)
|
||||
),
|
||||
cv.Optional(CONF_SET15): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
).extend(
|
||||
number_options(64.0, 254.0, 1.0)
|
||||
),
|
||||
cv.Optional(CONF_SET16_01): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
).extend(
|
||||
number_options(20.0, 60.0, 1.0)
|
||||
),
|
||||
cv.Optional(CONF_SET16_02): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
).extend(
|
||||
number_options(20.0, 60.0, 1.0)
|
||||
),
|
||||
cv.Optional(CONF_SET16_03): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
).extend(
|
||||
number_options(-20.0, 15.0, 1.0)
|
||||
),
|
||||
cv.Optional(CONF_SET16_04): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
).extend(
|
||||
number_options(-20.0, 15.0, 1.0)
|
||||
),
|
||||
cv.Optional(CONF_SET16_05): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
).extend(
|
||||
number_options(20.0, 60.0, 1.0)
|
||||
),
|
||||
cv.Optional(CONF_SET16_06): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
).extend(
|
||||
number_options(20.0, 60.0, 1.0)
|
||||
),
|
||||
cv.Optional(CONF_SET16_07): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
).extend(
|
||||
number_options(-20.0, 15.0, 1.0)
|
||||
),
|
||||
cv.Optional(CONF_SET16_08): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
).extend(
|
||||
number_options(-20.0, 15.0, 1.0)
|
||||
),
|
||||
cv.Optional(CONF_SET16_09): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
).extend(
|
||||
number_options(5.0, 20.0, 1.0)
|
||||
),
|
||||
cv.Optional(CONF_SET16_10): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
).extend(
|
||||
number_options(5.0, 20.0, 1.0)
|
||||
),
|
||||
cv.Optional(CONF_SET16_11): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
).extend(
|
||||
number_options(15.0, 30.0, 1.0)
|
||||
),
|
||||
cv.Optional(CONF_SET16_12): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
).extend(
|
||||
number_options(15.0, 30.0, 1.0)
|
||||
),
|
||||
cv.Optional(CONF_SET16_13): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
).extend(
|
||||
number_options(5.0, 20.0, 1.0)
|
||||
),
|
||||
cv.Optional(CONF_SET16_14): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
).extend(
|
||||
number_options(5.0, 20.0, 1.0)
|
||||
),
|
||||
cv.Optional(CONF_SET16_15): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
).extend(
|
||||
number_options(15.0, 30.0, 1.0)
|
||||
),
|
||||
cv.Optional(CONF_SET16_16): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
).extend(
|
||||
number_options(15.0, 30.0, 1.0)
|
||||
),
|
||||
cv.Optional(CONF_SET18): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_KELVIN,
|
||||
).extend(
|
||||
number_options(1.0, 15.0, 1.0)
|
||||
),
|
||||
cv.Optional(CONF_SET19): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_KELVIN,
|
||||
).extend(
|
||||
number_options(1.0, 15.0, 1.0)
|
||||
),
|
||||
cv.Optional(CONF_SET20): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_KELVIN,
|
||||
).extend(
|
||||
number_options(112.0, -2.0, 1.0)
|
||||
),
|
||||
cv.Optional(CONF_SET21): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_MINUTE,
|
||||
).extend(
|
||||
number_options(0.0, 250.0, 1.0)
|
||||
),
|
||||
cv.Optional(CONF_SET22): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_KELVIN,
|
||||
).extend(
|
||||
number_options(1.0, 15.0, 1.0)
|
||||
),
|
||||
cv.Optional(CONF_SET23): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_KELVIN,
|
||||
).extend(
|
||||
number_options(1.0, 15.0, 1.0)
|
||||
),
|
||||
cv.Optional(CONF_SET27): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_KELVIN,
|
||||
).extend(
|
||||
number_options(0.0, 10.0, 1.0)
|
||||
),
|
||||
cv.Optional(CONF_SET29): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
).extend(
|
||||
number_options(5.0, 35.0, 1.0)
|
||||
),
|
||||
cv.Optional(CONF_SET36): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
).extend(
|
||||
number_options(-15.0, 35.0, 1.0)
|
||||
),
|
||||
cv.Optional(CONF_SET37): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
).extend(
|
||||
number_options(-10.0, 0.0, 1.0)
|
||||
),
|
||||
cv.Optional(CONF_SET38): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
).extend(
|
||||
number_options(-10.0, 0.0, 1.0)
|
||||
),
|
||||
}
|
||||
{
|
||||
cv.GenerateID(CONF_PANASONIC_HEATPUMP_ID): cv.use_id(
|
||||
PanasonicHeatpumpComponent
|
||||
),
|
||||
cv.Optional(CONF_SET5): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
).extend(number_options(-5.0, 5.0, 1.0)),
|
||||
cv.Optional(CONF_SET6): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
).extend(number_options(-5.0, 5.0, 1.0)),
|
||||
cv.Optional(CONF_SET7): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
).extend(number_options(-5.0, 5.0, 1.0)),
|
||||
cv.Optional(CONF_SET8): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
).extend(number_options(-5.0, 5.0, 1.0)),
|
||||
cv.Optional(CONF_SET11): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
).extend(number_options(40.0, 75.0, 1.0)),
|
||||
cv.Optional(CONF_SET15): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
).extend(number_options(64.0, 254.0, 1.0)),
|
||||
cv.Optional(CONF_SET16_01): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
).extend(number_options(20.0, 60.0, 1.0)),
|
||||
cv.Optional(CONF_SET16_02): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
).extend(number_options(20.0, 60.0, 1.0)),
|
||||
cv.Optional(CONF_SET16_03): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
).extend(number_options(-20.0, 15.0, 1.0)),
|
||||
cv.Optional(CONF_SET16_04): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
).extend(number_options(-20.0, 15.0, 1.0)),
|
||||
cv.Optional(CONF_SET16_05): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
).extend(number_options(20.0, 60.0, 1.0)),
|
||||
cv.Optional(CONF_SET16_06): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
).extend(number_options(20.0, 60.0, 1.0)),
|
||||
cv.Optional(CONF_SET16_07): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
).extend(number_options(-20.0, 15.0, 1.0)),
|
||||
cv.Optional(CONF_SET16_08): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
).extend(number_options(-20.0, 15.0, 1.0)),
|
||||
cv.Optional(CONF_SET16_09): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
).extend(number_options(5.0, 20.0, 1.0)),
|
||||
cv.Optional(CONF_SET16_10): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
).extend(number_options(5.0, 20.0, 1.0)),
|
||||
cv.Optional(CONF_SET16_11): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
).extend(number_options(15.0, 30.0, 1.0)),
|
||||
cv.Optional(CONF_SET16_12): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
).extend(number_options(15.0, 30.0, 1.0)),
|
||||
cv.Optional(CONF_SET16_13): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
).extend(number_options(5.0, 20.0, 1.0)),
|
||||
cv.Optional(CONF_SET16_14): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
).extend(number_options(5.0, 20.0, 1.0)),
|
||||
cv.Optional(CONF_SET16_15): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
).extend(number_options(15.0, 30.0, 1.0)),
|
||||
cv.Optional(CONF_SET16_16): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
).extend(number_options(15.0, 30.0, 1.0)),
|
||||
cv.Optional(CONF_SET18): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_KELVIN,
|
||||
).extend(number_options(1.0, 15.0, 1.0)),
|
||||
cv.Optional(CONF_SET19): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_KELVIN,
|
||||
).extend(number_options(1.0, 15.0, 1.0)),
|
||||
cv.Optional(CONF_SET20): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_KELVIN,
|
||||
).extend(number_options(112.0, -2.0, 1.0)),
|
||||
cv.Optional(CONF_SET21): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_MINUTE,
|
||||
).extend(number_options(0.0, 250.0, 1.0)),
|
||||
cv.Optional(CONF_SET22): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_KELVIN,
|
||||
).extend(number_options(1.0, 15.0, 1.0)),
|
||||
cv.Optional(CONF_SET23): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_KELVIN,
|
||||
).extend(number_options(1.0, 15.0, 1.0)),
|
||||
cv.Optional(CONF_SET27): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_KELVIN,
|
||||
).extend(number_options(0.0, 10.0, 1.0)),
|
||||
cv.Optional(CONF_SET29): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
).extend(number_options(5.0, 35.0, 1.0)),
|
||||
cv.Optional(CONF_SET36): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
).extend(number_options(-15.0, 35.0, 1.0)),
|
||||
cv.Optional(CONF_SET37): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
).extend(number_options(-10.0, 0.0, 1.0)),
|
||||
cv.Optional(CONF_SET38): number.number_schema(
|
||||
PanasonicHeatpumpNumber,
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
).extend(number_options(-10.0, 0.0, 1.0)),
|
||||
}
|
||||
).extend(cv.COMPONENT_SCHEMA)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
parent = await cg.get_variable(config[CONF_PANASONIC_HEATPUMP_ID])
|
||||
for index, key in enumerate(TYPES):
|
||||
if child_config := config.get(key):
|
||||
var = await number.new_number(
|
||||
child_config,
|
||||
min_value=child_config[CONF_MIN_VALUE],
|
||||
max_value=child_config[CONF_MAX_VALUE],
|
||||
step=child_config[CONF_STEP],
|
||||
)
|
||||
await cg.register_component(var, child_config)
|
||||
cg.add(var.set_parent(parent))
|
||||
cg.add(var.set_id(index))
|
||||
cg.add(parent.add_number(var))
|
||||
parent = await cg.get_variable(config[CONF_PANASONIC_HEATPUMP_ID])
|
||||
for index, key in enumerate(TYPES):
|
||||
if child_config := config.get(key):
|
||||
var = await number.new_number(
|
||||
child_config,
|
||||
min_value=child_config[CONF_MIN_VALUE],
|
||||
max_value=child_config[CONF_MAX_VALUE],
|
||||
step=child_config[CONF_STEP],
|
||||
)
|
||||
await cg.register_component(var, child_config)
|
||||
cg.add(var.set_parent(parent))
|
||||
cg.add(var.set_id(index))
|
||||
cg.add(parent.add_number(var))
|
||||
|
|
|
|||
|
|
@ -1,276 +1,303 @@
|
|||
#include "panasonic_heatpump_number.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace panasonic_heatpump {
|
||||
static const char* const TAG = "panasonic_heatpump.number";
|
||||
|
||||
namespace esphome
|
||||
{
|
||||
namespace panasonic_heatpump
|
||||
{
|
||||
static const char *const TAG = "panasonic_heatpump.number";
|
||||
void PanasonicHeatpumpNumber::dump_config() {
|
||||
LOG_NUMBER("", "Panasonic Heatpump Number", this);
|
||||
delay(10);
|
||||
}
|
||||
|
||||
void PanasonicHeatpumpNumber::dump_config()
|
||||
{
|
||||
LOG_NUMBER("", "Panasonic Heatpump Number", this);
|
||||
delay(10);
|
||||
}
|
||||
void PanasonicHeatpumpNumber::control(float value) {
|
||||
switch (this->id_) {
|
||||
case NumberIds::CONF_SET5:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus128(value), 38);
|
||||
break;
|
||||
case NumberIds::CONF_SET6:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus128(value), 39);
|
||||
break;
|
||||
case NumberIds::CONF_SET7:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus128(value), 40);
|
||||
break;
|
||||
case NumberIds::CONF_SET8:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus128(value), 41);
|
||||
break;
|
||||
case NumberIds::CONF_SET11:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus128(value), 42);
|
||||
break;
|
||||
case NumberIds::CONF_SET15:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus1(value), 45);
|
||||
break;
|
||||
case NumberIds::CONF_SET16_01:
|
||||
this->parent_->set_command_curve(PanasonicCommand::setPlus128(value), 75);
|
||||
break;
|
||||
case NumberIds::CONF_SET16_02:
|
||||
this->parent_->set_command_curve(PanasonicCommand::setPlus128(value), 76);
|
||||
break;
|
||||
case NumberIds::CONF_SET16_03:
|
||||
this->parent_->set_command_curve(PanasonicCommand::setPlus128(value), 77);
|
||||
break;
|
||||
case NumberIds::CONF_SET16_04:
|
||||
this->parent_->set_command_curve(PanasonicCommand::setPlus128(value), 78);
|
||||
break;
|
||||
case NumberIds::CONF_SET16_05:
|
||||
this->parent_->set_command_curve(PanasonicCommand::setPlus128(value), 79);
|
||||
break;
|
||||
case NumberIds::CONF_SET16_06:
|
||||
this->parent_->set_command_curve(PanasonicCommand::setPlus128(value), 80);
|
||||
break;
|
||||
case NumberIds::CONF_SET16_07:
|
||||
this->parent_->set_command_curve(PanasonicCommand::setPlus128(value), 81);
|
||||
break;
|
||||
case NumberIds::CONF_SET16_08:
|
||||
this->parent_->set_command_curve(PanasonicCommand::setPlus128(value), 82);
|
||||
break;
|
||||
case NumberIds::CONF_SET16_09:
|
||||
this->parent_->set_command_curve(PanasonicCommand::setPlus128(value), 86);
|
||||
break;
|
||||
case NumberIds::CONF_SET16_10:
|
||||
this->parent_->set_command_curve(PanasonicCommand::setPlus128(value), 87);
|
||||
break;
|
||||
case NumberIds::CONF_SET16_11:
|
||||
this->parent_->set_command_curve(PanasonicCommand::setPlus128(value), 88);
|
||||
break;
|
||||
case NumberIds::CONF_SET16_12:
|
||||
this->parent_->set_command_curve(PanasonicCommand::setPlus128(value), 89);
|
||||
break;
|
||||
case NumberIds::CONF_SET16_13:
|
||||
this->parent_->set_command_curve(PanasonicCommand::setPlus128(value), 90);
|
||||
break;
|
||||
case NumberIds::CONF_SET16_14:
|
||||
this->parent_->set_command_curve(PanasonicCommand::setPlus128(value), 91);
|
||||
break;
|
||||
case NumberIds::CONF_SET16_15:
|
||||
this->parent_->set_command_curve(PanasonicCommand::setPlus128(value), 92);
|
||||
break;
|
||||
case NumberIds::CONF_SET16_16:
|
||||
this->parent_->set_command_curve(PanasonicCommand::setPlus128(value), 93);
|
||||
break;
|
||||
case NumberIds::CONF_SET18:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus128(value), 84);
|
||||
break;
|
||||
case NumberIds::CONF_SET19:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus128(value), 94);
|
||||
break;
|
||||
case NumberIds::CONF_SET20:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus128(value), 99);
|
||||
break;
|
||||
case NumberIds::CONF_SET21:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus1(value), 104);
|
||||
break;
|
||||
case NumberIds::CONF_SET22:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus128(value), 105);
|
||||
break;
|
||||
case NumberIds::CONF_SET23:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus128(value), 106);
|
||||
break;
|
||||
case NumberIds::CONF_SET27:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus128(value), 59);
|
||||
break;
|
||||
case NumberIds::CONF_SET29:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus128(value), 83);
|
||||
break;
|
||||
case NumberIds::CONF_SET36:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus128(value), 65);
|
||||
break;
|
||||
case NumberIds::CONF_SET37:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus128(value), 66);
|
||||
break;
|
||||
case NumberIds::CONF_SET38:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus128(value), 68);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
};
|
||||
|
||||
void PanasonicHeatpumpNumber::control(float value)
|
||||
{
|
||||
switch (this->id_)
|
||||
{
|
||||
case NumberIds::CONF_SET5:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus128(value), 38);
|
||||
break;
|
||||
case NumberIds::CONF_SET6:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus128(value), 39);
|
||||
break;
|
||||
case NumberIds::CONF_SET7:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus128(value), 40);
|
||||
break;
|
||||
case NumberIds::CONF_SET8:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus128(value), 41);
|
||||
break;
|
||||
case NumberIds::CONF_SET11:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus128(value), 42);
|
||||
break;
|
||||
case NumberIds::CONF_SET15:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus1(value), 45);
|
||||
break;
|
||||
case NumberIds::CONF_SET16_01:
|
||||
this->parent_->set_command_curve(PanasonicCommand::setPlus128(value), 75);
|
||||
break;
|
||||
case NumberIds::CONF_SET16_02:
|
||||
this->parent_->set_command_curve(PanasonicCommand::setPlus128(value), 76);
|
||||
break;
|
||||
case NumberIds::CONF_SET16_03:
|
||||
this->parent_->set_command_curve(PanasonicCommand::setPlus128(value), 77);
|
||||
break;
|
||||
case NumberIds::CONF_SET16_04:
|
||||
this->parent_->set_command_curve(PanasonicCommand::setPlus128(value), 78);
|
||||
break;
|
||||
case NumberIds::CONF_SET16_05:
|
||||
this->parent_->set_command_curve(PanasonicCommand::setPlus128(value), 79);
|
||||
break;
|
||||
case NumberIds::CONF_SET16_06:
|
||||
this->parent_->set_command_curve(PanasonicCommand::setPlus128(value), 80);
|
||||
break;
|
||||
case NumberIds::CONF_SET16_07:
|
||||
this->parent_->set_command_curve(PanasonicCommand::setPlus128(value), 81);
|
||||
break;
|
||||
case NumberIds::CONF_SET16_08:
|
||||
this->parent_->set_command_curve(PanasonicCommand::setPlus128(value), 82);
|
||||
break;
|
||||
case NumberIds::CONF_SET16_09:
|
||||
this->parent_->set_command_curve(PanasonicCommand::setPlus128(value), 86);
|
||||
break;
|
||||
case NumberIds::CONF_SET16_10:
|
||||
this->parent_->set_command_curve(PanasonicCommand::setPlus128(value), 87);
|
||||
break;
|
||||
case NumberIds::CONF_SET16_11:
|
||||
this->parent_->set_command_curve(PanasonicCommand::setPlus128(value), 88);
|
||||
break;
|
||||
case NumberIds::CONF_SET16_12:
|
||||
this->parent_->set_command_curve(PanasonicCommand::setPlus128(value), 89);
|
||||
break;
|
||||
case NumberIds::CONF_SET16_13:
|
||||
this->parent_->set_command_curve(PanasonicCommand::setPlus128(value), 90);
|
||||
break;
|
||||
case NumberIds::CONF_SET16_14:
|
||||
this->parent_->set_command_curve(PanasonicCommand::setPlus128(value), 91);
|
||||
break;
|
||||
case NumberIds::CONF_SET16_15:
|
||||
this->parent_->set_command_curve(PanasonicCommand::setPlus128(value), 92);
|
||||
break;
|
||||
case NumberIds::CONF_SET16_16:
|
||||
this->parent_->set_command_curve(PanasonicCommand::setPlus128(value), 93);
|
||||
break;
|
||||
case NumberIds::CONF_SET18:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus128(value), 84);
|
||||
break;
|
||||
case NumberIds::CONF_SET19:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus128(value), 94);
|
||||
break;
|
||||
case NumberIds::CONF_SET20:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus128(value), 99);
|
||||
break;
|
||||
case NumberIds::CONF_SET21:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus1(value), 104);
|
||||
break;
|
||||
case NumberIds::CONF_SET22:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus128(value), 105);
|
||||
break;
|
||||
case NumberIds::CONF_SET23:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus128(value), 106);
|
||||
break;
|
||||
case NumberIds::CONF_SET27:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus128(value), 59);
|
||||
break;
|
||||
case NumberIds::CONF_SET29:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus128(value), 83);
|
||||
break;
|
||||
case NumberIds::CONF_SET36:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus128(value), 65);
|
||||
break;
|
||||
case NumberIds::CONF_SET37:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus128(value), 66);
|
||||
break;
|
||||
case NumberIds::CONF_SET38:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus128(value), 68);
|
||||
break;
|
||||
default: return;
|
||||
};
|
||||
this->publish_state(state);
|
||||
this->keep_state_ = 2;
|
||||
}
|
||||
|
||||
this->publish_state(state);
|
||||
this->keep_state_ = 2;
|
||||
}
|
||||
void PanasonicHeatpumpNumber::publish_new_state(const std::vector<uint8_t>& data) {
|
||||
if (this->keep_state_ > 0) {
|
||||
this->keep_state_--;
|
||||
return;
|
||||
}
|
||||
if (data.empty())
|
||||
return;
|
||||
|
||||
void PanasonicHeatpumpNumber::publish_new_state(const std::vector<uint8_t>& data)
|
||||
{
|
||||
if (this->keep_state_ > 0)
|
||||
{
|
||||
this->keep_state_--;
|
||||
return;
|
||||
}
|
||||
if (data.empty()) return;
|
||||
float new_state;
|
||||
switch (this->id_) {
|
||||
case NumberIds::CONF_SET11:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[42]);
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case NumberIds::CONF_SET20:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[99]);
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case NumberIds::CONF_SET18:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[84]);
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case NumberIds::CONF_SET19:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[94]);
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case NumberIds::CONF_SET5:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[38]);
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case NumberIds::CONF_SET6:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[39]);
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case NumberIds::CONF_SET16_01:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[75]);
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case NumberIds::CONF_SET16_02:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[76]);
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case NumberIds::CONF_SET16_04:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[78]);
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case NumberIds::CONF_SET16_03:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[77]);
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case NumberIds::CONF_SET7:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[40]);
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case NumberIds::CONF_SET8:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[41]);
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case NumberIds::CONF_SET16_09:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[86]);
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case NumberIds::CONF_SET16_10:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[87]);
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case NumberIds::CONF_SET16_12:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[89]);
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case NumberIds::CONF_SET16_11:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[88]);
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case NumberIds::CONF_SET29:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[83]);
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case NumberIds::CONF_SET16_05:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[79]);
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case NumberIds::CONF_SET16_06:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[80]);
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case NumberIds::CONF_SET16_08:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[82]);
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case NumberIds::CONF_SET16_07:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[81]);
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case NumberIds::CONF_SET16_13:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[90]);
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case NumberIds::CONF_SET16_14:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[91]);
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case NumberIds::CONF_SET16_16:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[93]);
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case NumberIds::CONF_SET16_15:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[92]);
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case NumberIds::CONF_SET15:
|
||||
new_state = PanasonicDecode::getByteMinus1(data[45]);
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case NumberIds::CONF_SET21:
|
||||
new_state = PanasonicDecode::getByteMinus1(data[104]);
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case NumberIds::CONF_SET22:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[105]);
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case NumberIds::CONF_SET23:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[106]);
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case NumberIds::CONF_SET27:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[59]);
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case NumberIds::CONF_SET36:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[65]);
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case NumberIds::CONF_SET37:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[66]);
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case NumberIds::CONF_SET38:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[68]);
|
||||
if (this->has_state() && this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
};
|
||||
|
||||
float new_state;
|
||||
switch (this->id_)
|
||||
{
|
||||
case NumberIds::CONF_SET11:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[42]);
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case NumberIds::CONF_SET20:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[99]);
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case NumberIds::CONF_SET18:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[84]);
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case NumberIds::CONF_SET19:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[94]);
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case NumberIds::CONF_SET5:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[38]);
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case NumberIds::CONF_SET6:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[39]);
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case NumberIds::CONF_SET16_01:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[75]);
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case NumberIds::CONF_SET16_02:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[76]);
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case NumberIds::CONF_SET16_04:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[78]);
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case NumberIds::CONF_SET16_03:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[77]);
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case NumberIds::CONF_SET7:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[40]);
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case NumberIds::CONF_SET8:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[41]);
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case NumberIds::CONF_SET16_09:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[86]);
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case NumberIds::CONF_SET16_10:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[87]);
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case NumberIds::CONF_SET16_12:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[89]);
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case NumberIds::CONF_SET16_11:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[88]);
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case NumberIds::CONF_SET29:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[83]);
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case NumberIds::CONF_SET16_05:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[79]);
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case NumberIds::CONF_SET16_06:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[80]);
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case NumberIds::CONF_SET16_08:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[82]);
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case NumberIds::CONF_SET16_07:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[81]);
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case NumberIds::CONF_SET16_13:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[90]);
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case NumberIds::CONF_SET16_14:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[91]);
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case NumberIds::CONF_SET16_16:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[93]);
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case NumberIds::CONF_SET16_15:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[92]);
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case NumberIds::CONF_SET15:
|
||||
new_state = PanasonicDecode::getByteMinus1(data[45]);
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case NumberIds::CONF_SET21:
|
||||
new_state = PanasonicDecode::getByteMinus1(data[104]);
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case NumberIds::CONF_SET22:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[105]);
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case NumberIds::CONF_SET23:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[106]);
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case NumberIds::CONF_SET27:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[59]);
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case NumberIds::CONF_SET36:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[65]);
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case NumberIds::CONF_SET37:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[66]);
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
case NumberIds::CONF_SET38:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[68]);
|
||||
if (this->has_state() && this->state == new_state) return;
|
||||
break;
|
||||
default: return;
|
||||
};
|
||||
|
||||
this->publish_state(new_state);
|
||||
}
|
||||
} // namespace panasonic_heatpump
|
||||
} // namespace esphome
|
||||
this->publish_state(new_state);
|
||||
}
|
||||
} // namespace panasonic_heatpump
|
||||
} // namespace esphome
|
||||
|
|
|
|||
|
|
@ -5,58 +5,55 @@
|
|||
#include "../decode.h"
|
||||
#include "../commands.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace panasonic_heatpump {
|
||||
enum NumberIds : uint8_t {
|
||||
CONF_SET5,
|
||||
CONF_SET6,
|
||||
CONF_SET7,
|
||||
CONF_SET8,
|
||||
CONF_SET11,
|
||||
CONF_SET15,
|
||||
CONF_SET16_01,
|
||||
CONF_SET16_02,
|
||||
CONF_SET16_03,
|
||||
CONF_SET16_04,
|
||||
CONF_SET16_05,
|
||||
CONF_SET16_06,
|
||||
CONF_SET16_07,
|
||||
CONF_SET16_08,
|
||||
CONF_SET16_09,
|
||||
CONF_SET16_10,
|
||||
CONF_SET16_11,
|
||||
CONF_SET16_12,
|
||||
CONF_SET16_13,
|
||||
CONF_SET16_14,
|
||||
CONF_SET16_15,
|
||||
CONF_SET16_16,
|
||||
CONF_SET18,
|
||||
CONF_SET19,
|
||||
CONF_SET20,
|
||||
CONF_SET21,
|
||||
CONF_SET22,
|
||||
CONF_SET23,
|
||||
CONF_SET27,
|
||||
CONF_SET29,
|
||||
CONF_SET36,
|
||||
CONF_SET37,
|
||||
CONF_SET38,
|
||||
};
|
||||
|
||||
namespace esphome
|
||||
{
|
||||
namespace panasonic_heatpump
|
||||
{
|
||||
enum NumberIds : uint8_t
|
||||
{
|
||||
CONF_SET5,
|
||||
CONF_SET6,
|
||||
CONF_SET7,
|
||||
CONF_SET8,
|
||||
CONF_SET11,
|
||||
CONF_SET15,
|
||||
CONF_SET16_01,
|
||||
CONF_SET16_02,
|
||||
CONF_SET16_03,
|
||||
CONF_SET16_04,
|
||||
CONF_SET16_05,
|
||||
CONF_SET16_06,
|
||||
CONF_SET16_07,
|
||||
CONF_SET16_08,
|
||||
CONF_SET16_09,
|
||||
CONF_SET16_10,
|
||||
CONF_SET16_11,
|
||||
CONF_SET16_12,
|
||||
CONF_SET16_13,
|
||||
CONF_SET16_14,
|
||||
CONF_SET16_15,
|
||||
CONF_SET16_16,
|
||||
CONF_SET18,
|
||||
CONF_SET19,
|
||||
CONF_SET20,
|
||||
CONF_SET21,
|
||||
CONF_SET22,
|
||||
CONF_SET23,
|
||||
CONF_SET27,
|
||||
CONF_SET29,
|
||||
CONF_SET36,
|
||||
CONF_SET37,
|
||||
CONF_SET38,
|
||||
};
|
||||
class PanasonicHeatpumpNumber : public number::Number,
|
||||
public Component,
|
||||
public Parented<PanasonicHeatpumpComponent>,
|
||||
public PanasonicHeatpumpEntity {
|
||||
public:
|
||||
PanasonicHeatpumpNumber() = default;
|
||||
void dump_config() override;
|
||||
void publish_new_state(const std::vector<uint8_t>& data) override;
|
||||
|
||||
class PanasonicHeatpumpNumber : public number::Number, public Component,
|
||||
public Parented<PanasonicHeatpumpComponent>, public PanasonicHeatpumpEntity
|
||||
{
|
||||
public:
|
||||
PanasonicHeatpumpNumber() = default;
|
||||
void dump_config() override;
|
||||
void publish_new_state(const std::vector<uint8_t>& data) override;
|
||||
|
||||
protected:
|
||||
void control(float value) override;
|
||||
};
|
||||
} // namespace panasonic_heatpump
|
||||
} // namespace esphome
|
||||
protected:
|
||||
void control(float value) override;
|
||||
};
|
||||
} // namespace panasonic_heatpump
|
||||
} // namespace esphome
|
||||
|
|
|
|||
|
|
@ -1,437 +1,400 @@
|
|||
#include "panasonic_heatpump.h"
|
||||
#include "esphome/core/application.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace panasonic_heatpump {
|
||||
static const char* const TAG = "panasonic_heatpump";
|
||||
|
||||
namespace esphome
|
||||
{
|
||||
namespace panasonic_heatpump
|
||||
{
|
||||
static const char *const TAG = "panasonic_heatpump";
|
||||
void PanasonicHeatpumpComponent::dump_config() {
|
||||
ESP_LOGW(TAG, "*** Panasonic Heatpump Component v%s ***", PANASONIC_HEATPUMP_VERSION);
|
||||
delay(10); // NOLINT
|
||||
}
|
||||
|
||||
void PanasonicHeatpumpComponent::dump_config()
|
||||
{
|
||||
ESP_LOGW(TAG, "*** Panasonic Heatpump Component v%s ***", PanasonicHeatpumpComponent::version.c_str());
|
||||
void PanasonicHeatpumpComponent::setup() {
|
||||
ESP_LOGCONFIG(TAG, "Setting up Panasonic Heatpump ...");
|
||||
delay(10); // NOLINT
|
||||
this->check_uart_settings(9600, 1, uart::UART_CONFIG_PARITY_EVEN, 8);
|
||||
|
||||
this->update();
|
||||
}
|
||||
|
||||
void PanasonicHeatpumpComponent::update() {
|
||||
if (this->uart_client_ != nullptr)
|
||||
return;
|
||||
this->next_request_ = this->send_extra_request_ ? RequestType::POLLING_EXTRA : RequestType::POLLING;
|
||||
}
|
||||
|
||||
void PanasonicHeatpumpComponent::loop() {
|
||||
switch (this->loop_state_) {
|
||||
case LoopState::READ_RESPONSE:
|
||||
this->read_response();
|
||||
this->loop_state_ = LoopState::CHECK_RESPONSE;
|
||||
break;
|
||||
case LoopState::CHECK_RESPONSE:
|
||||
this->current_response_ = this->check_response(this->response_message_);
|
||||
switch (this->current_response_) {
|
||||
case ResponseType::UNKNOWN:
|
||||
this->loop_state_ = LoopState::SEND_REQUEST;
|
||||
break;
|
||||
case ResponseType::STANDARD:
|
||||
this->loop_state_ = LoopState::PUBLISH_SENSOR;
|
||||
break;
|
||||
case ResponseType::EXTRA:
|
||||
this->loop_state_ = LoopState::PUBLISH_EXTRA_SENSOR;
|
||||
break;
|
||||
};
|
||||
break;
|
||||
case LoopState::PUBLISH_SENSOR:
|
||||
for (auto* entity : this->sensors_) {
|
||||
entity->publish_new_state(this->heatpump_default_message_);
|
||||
}
|
||||
this->loop_state_ = LoopState::PUBLISH_BINARY_SENSOR;
|
||||
break;
|
||||
case LoopState::PUBLISH_BINARY_SENSOR:
|
||||
for (auto* entity : this->binary_sensors_) {
|
||||
entity->publish_new_state(this->heatpump_default_message_);
|
||||
}
|
||||
this->loop_state_ = LoopState::PUBLISH_TEXT_SENSOR;
|
||||
break;
|
||||
case LoopState::PUBLISH_TEXT_SENSOR:
|
||||
for (auto* entity : this->text_sensors_) {
|
||||
entity->publish_new_state(this->heatpump_default_message_);
|
||||
}
|
||||
this->loop_state_ = LoopState::PUBLISH_NUMBER;
|
||||
break;
|
||||
case LoopState::PUBLISH_NUMBER:
|
||||
for (auto* entity : this->numbers_) {
|
||||
entity->publish_new_state(this->heatpump_default_message_);
|
||||
}
|
||||
this->loop_state_ = LoopState::PUBLISH_SELECT;
|
||||
break;
|
||||
case LoopState::PUBLISH_SELECT:
|
||||
for (auto* entity : this->selects_) {
|
||||
entity->publish_new_state(this->heatpump_default_message_);
|
||||
}
|
||||
this->loop_state_ = LoopState::PUBLISH_SWITCH;
|
||||
break;
|
||||
case LoopState::PUBLISH_SWITCH:
|
||||
for (auto* entity : this->switches_) {
|
||||
entity->publish_new_state(this->heatpump_default_message_);
|
||||
}
|
||||
this->loop_state_ = LoopState::PUBLISH_CLIMATE;
|
||||
break;
|
||||
case LoopState::PUBLISH_CLIMATE:
|
||||
for (auto* entity : this->climates_) {
|
||||
entity->publish_new_state(this->heatpump_default_message_);
|
||||
}
|
||||
this->loop_state_ = LoopState::SEND_REQUEST;
|
||||
break;
|
||||
case LoopState::PUBLISH_EXTRA_SENSOR:
|
||||
for (auto* entity : this->extra_sensors_) {
|
||||
entity->publish_new_state(this->heatpump_extra_message_);
|
||||
}
|
||||
this->loop_state_ = LoopState::SEND_REQUEST;
|
||||
break;
|
||||
case LoopState::SEND_REQUEST:
|
||||
this->send_request(this->next_request_);
|
||||
this->loop_state_ = LoopState::READ_REQUEST;
|
||||
break;
|
||||
case LoopState::READ_REQUEST:
|
||||
this->read_request();
|
||||
this->loop_state_ = LoopState::RESTART_LOOP;
|
||||
break;
|
||||
default:
|
||||
this->loop_state_ = LoopState::READ_RESPONSE;
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
void PanasonicHeatpumpComponent::read_response() {
|
||||
while (this->available()) {
|
||||
// Read each byte from heatpump and forward it directly to the client (CZ-TAW1)
|
||||
this->read_byte(&byte_);
|
||||
if (this->uart_client_ != nullptr) {
|
||||
this->uart_client_->write_byte(byte_);
|
||||
}
|
||||
|
||||
// Message shall start with 0x31, 0x71 or 0xF1, if not skip this byte
|
||||
if (!this->response_receiving_) {
|
||||
if (byte_ != 0x31 && byte_ != 0x71 && byte_ != 0xF1)
|
||||
continue;
|
||||
this->response_message_.clear();
|
||||
this->response_receiving_ = true;
|
||||
}
|
||||
// Add current byte to message buffer
|
||||
this->response_message_.push_back(byte_);
|
||||
|
||||
// 2. byte contains the payload size
|
||||
if (this->response_message_.size() == 2) {
|
||||
this->payload_length_ = byte_;
|
||||
}
|
||||
// 3. byte shall be 0x01 or 0x10
|
||||
if (this->response_message_.size() == 3 && byte_ != 0x01 && byte_ != 0x10) {
|
||||
this->response_receiving_ = false;
|
||||
ESP_LOGW(TAG, "Invalid response message: 0x%s. Expected last byte to be 0x01 or 0x10",
|
||||
PanasonicHelpers::byte_array_to_hex_string(this->response_message_, ','));
|
||||
delay(10); // NOLINT
|
||||
continue;
|
||||
}
|
||||
|
||||
void PanasonicHeatpumpComponent::setup()
|
||||
{
|
||||
ESP_LOGCONFIG(TAG, "Setting up Panasonic Heatpump ...");
|
||||
// 4. byte shall be 0x10 or 0x21
|
||||
if (this->response_message_.size() == 4 && byte_ != 0x10 && byte_ != 0x21) {
|
||||
this->response_receiving_ = false;
|
||||
ESP_LOGW(TAG, "Invalid response message: 0x%s. Expected last byte to be 0x10 or 0x21",
|
||||
PanasonicHelpers::byte_array_to_hex_string(this->response_message_, ','));
|
||||
delay(10); // NOLINT
|
||||
this->check_uart_settings(9600, 1, uart::UART_CONFIG_PARITY_EVEN, 8);
|
||||
|
||||
this->update();
|
||||
continue;
|
||||
}
|
||||
|
||||
void PanasonicHeatpumpComponent::update()
|
||||
{
|
||||
if (this->uart_client_ != nullptr) return;
|
||||
this->next_request_ = this->send_extra_request_ ? RequestType::POLLING_EXTRA : RequestType::POLLING;
|
||||
// Check if message is complete
|
||||
if (this->response_message_.size() > 2 && this->response_message_.size() == this->payload_length_ + 3) {
|
||||
this->response_receiving_ = false;
|
||||
this->current_response_count_++;
|
||||
if (this->log_uart_msg_)
|
||||
PanasonicHelpers::log_uart_hex(UART_LOG_RX, this->response_message_, ',');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PanasonicHeatpumpComponent::send_request(RequestType requestType) {
|
||||
switch (requestType) {
|
||||
case RequestType::COMMAND:
|
||||
if (this->log_uart_msg_)
|
||||
PanasonicHelpers::log_uart_hex(UART_LOG_TX, this->command_message_, ',');
|
||||
this->write_array(this->command_message_);
|
||||
this->flush();
|
||||
break;
|
||||
case RequestType::INITIAL:
|
||||
// Probably not necessary but CZ-TAW1 sends this query on boot
|
||||
if (this->log_uart_msg_)
|
||||
PanasonicHelpers::log_uart_hex(UART_LOG_TX, PanasonicCommand::InitialRequest, INIT_REQUEST_SIZE, ',');
|
||||
this->write_array(PanasonicCommand::InitialRequest, INIT_REQUEST_SIZE);
|
||||
this->flush();
|
||||
break;
|
||||
case RequestType::POLLING:
|
||||
if (this->log_uart_msg_)
|
||||
PanasonicHelpers::log_uart_hex(UART_LOG_TX, PanasonicCommand::PollingMessage, DATA_MESSAGE_SIZE, ',');
|
||||
this->write_array(PanasonicCommand::PollingMessage, DATA_MESSAGE_SIZE);
|
||||
this->flush();
|
||||
break;
|
||||
case RequestType::POLLING_EXTRA:
|
||||
if (this->log_uart_msg_)
|
||||
PanasonicHelpers::log_uart_hex(UART_LOG_TX, PanasonicCommand::PollingExtraMessage, DATA_MESSAGE_SIZE, ',');
|
||||
this->write_array(PanasonicCommand::PollingExtraMessage, DATA_MESSAGE_SIZE);
|
||||
this->flush();
|
||||
break;
|
||||
};
|
||||
|
||||
this->next_request_ = RequestType::NONE;
|
||||
}
|
||||
|
||||
void PanasonicHeatpumpComponent::read_request() {
|
||||
if (this->uart_client_ == nullptr)
|
||||
return;
|
||||
|
||||
while (this->uart_client_->available()) {
|
||||
// Read each byte from client and forward it directly to the heatpump
|
||||
this->uart_client_->read_byte(&byte_);
|
||||
this->write_byte(byte_);
|
||||
|
||||
// Message shall start with 0x31, 0x71 or 0xF1, if not skip this byte
|
||||
if (!this->request_receiving_) {
|
||||
if (byte_ != 0x31 && byte_ != 0x71 && byte_ != 0xF1)
|
||||
continue;
|
||||
this->request_message_.clear();
|
||||
this->request_receiving_ = true;
|
||||
}
|
||||
// Add current byte to message buffer
|
||||
this->request_message_.push_back(byte_);
|
||||
|
||||
// 2. byte contains the payload size
|
||||
if (this->request_message_.size() == 2) {
|
||||
this->payload_length_ = byte_;
|
||||
}
|
||||
// 3. byte shall be 0x01 or 0x10
|
||||
if (this->request_message_.size() == 3 && byte_ != 0x01 && byte_ != 0x10) {
|
||||
this->request_receiving_ = false;
|
||||
ESP_LOGW(TAG, "Invalid request message: 0x%s. Expected last byte to be 0x01 or 0x10",
|
||||
PanasonicHelpers::byte_array_to_hex_string(this->request_message_, ','));
|
||||
delay(10); // NOLINT
|
||||
continue;
|
||||
}
|
||||
// 4. byte shall be 0x10 or 0x21
|
||||
if (this->request_message_.size() == 4 && byte_ != 0x10 && byte_ != 0x21) {
|
||||
this->request_receiving_ = false;
|
||||
ESP_LOGW(TAG, "Invalid request message: 0x%s. Expected last byte to be 0x10 or 0x21",
|
||||
PanasonicHelpers::byte_array_to_hex_string(this->request_message_, ','));
|
||||
delay(10); // NOLINT
|
||||
continue;
|
||||
}
|
||||
|
||||
void PanasonicHeatpumpComponent::loop()
|
||||
{
|
||||
switch (this->loop_state_)
|
||||
{
|
||||
case LoopState::READ_RESPONSE:
|
||||
this->read_response();
|
||||
this->loop_state_ = LoopState::CHECK_RESPONSE;
|
||||
break;
|
||||
case LoopState::CHECK_RESPONSE:
|
||||
this->current_response_ = this->check_response(this->response_message_);
|
||||
switch (this->current_response_)
|
||||
{
|
||||
case ResponseType::UNKNOWN:
|
||||
this->loop_state_ = LoopState::SEND_REQUEST;
|
||||
break;
|
||||
case ResponseType::DEFAULT:
|
||||
this->loop_state_ = LoopState::PUBLISH_SENSOR;
|
||||
break;
|
||||
case ResponseType::EXTRA:
|
||||
this->loop_state_ = LoopState::PUBLISH_EXTRA_SENSOR;
|
||||
break;
|
||||
};
|
||||
break;
|
||||
case LoopState::PUBLISH_SENSOR:
|
||||
for (auto *entity : this->sensors_)
|
||||
{
|
||||
entity->publish_new_state(this->heatpump_default_message_);
|
||||
}
|
||||
this->loop_state_ = LoopState::PUBLISH_BINARY_SENSOR;
|
||||
break;
|
||||
case LoopState::PUBLISH_BINARY_SENSOR:
|
||||
for (auto *entity : this->binary_sensors_)
|
||||
{
|
||||
entity->publish_new_state(this->heatpump_default_message_);
|
||||
}
|
||||
this->loop_state_ = LoopState::PUBLISH_TEXT_SENSOR;
|
||||
break;
|
||||
case LoopState::PUBLISH_TEXT_SENSOR:
|
||||
for (auto *entity : this->text_sensors_)
|
||||
{
|
||||
entity->publish_new_state(this->heatpump_default_message_);
|
||||
}
|
||||
this->loop_state_ = LoopState::PUBLISH_NUMBER;
|
||||
break;
|
||||
case LoopState::PUBLISH_NUMBER:
|
||||
for (auto *entity : this->numbers_)
|
||||
{
|
||||
entity->publish_new_state(this->heatpump_default_message_);
|
||||
}
|
||||
this->loop_state_ = LoopState::PUBLISH_SELECT;
|
||||
break;
|
||||
case LoopState::PUBLISH_SELECT:
|
||||
for (auto *entity : this->selects_)
|
||||
{
|
||||
entity->publish_new_state(this->heatpump_default_message_);
|
||||
}
|
||||
this->loop_state_ = LoopState::PUBLISH_SWITCH;
|
||||
break;
|
||||
case LoopState::PUBLISH_SWITCH:
|
||||
for (auto *entity : this->switches_)
|
||||
{
|
||||
entity->publish_new_state(this->heatpump_default_message_);
|
||||
}
|
||||
this->loop_state_ = LoopState::PUBLISH_CLIMATE;
|
||||
break;
|
||||
case LoopState::PUBLISH_CLIMATE:
|
||||
for (auto *entity : this->climates_)
|
||||
{
|
||||
entity->publish_new_state(this->heatpump_default_message_);
|
||||
}
|
||||
this->loop_state_ = LoopState::SEND_REQUEST;
|
||||
break;
|
||||
case LoopState::PUBLISH_EXTRA_SENSOR:
|
||||
for (auto *entity : this->extra_sensors_)
|
||||
{
|
||||
entity->publish_new_state(this->heatpump_extra_message_);
|
||||
}
|
||||
this->loop_state_ = LoopState::SEND_REQUEST;
|
||||
break;
|
||||
case LoopState::SEND_REQUEST:
|
||||
this->send_request(this->next_request_);
|
||||
this->loop_state_ = LoopState::READ_REQUEST;
|
||||
break;
|
||||
case LoopState::READ_REQUEST:
|
||||
this->read_request();
|
||||
this->loop_state_ = LoopState::RESTART_LOOP;
|
||||
break;
|
||||
default:
|
||||
this->loop_state_ = LoopState::READ_RESPONSE;
|
||||
break;
|
||||
};
|
||||
// Check if message is complete
|
||||
if (this->request_message_.size() > 2 && this->request_message_.size() == this->payload_length_ + 3) {
|
||||
this->request_receiving_ = false;
|
||||
if (this->log_uart_msg_)
|
||||
PanasonicHelpers::log_uart_hex(UART_LOG_TX, this->request_message_, ',');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PanasonicHeatpumpComponent::read_response()
|
||||
{
|
||||
while (this->available())
|
||||
{
|
||||
// Read each byte from heatpump and forward it directly to the client (CZ-TAW1)
|
||||
this->read_byte(&byte_);
|
||||
if (this->uart_client_ != nullptr)
|
||||
{
|
||||
this->uart_client_->write_byte(byte_);
|
||||
}
|
||||
int PanasonicHeatpumpComponent::getResponseByte(const int index) {
|
||||
if (this->heatpump_default_message_.size() > index)
|
||||
return this->heatpump_default_message_[index];
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Message shall start with 0x31, 0x71 or 0xF1, if not skip this byte
|
||||
if (!this->response_receiving_)
|
||||
{
|
||||
if (byte_ != 0x31 && byte_ != 0x71 && byte_ != 0xF1) continue;
|
||||
this->response_message_.clear();
|
||||
this->response_receiving_ = true;
|
||||
}
|
||||
// Add current byte to message buffer
|
||||
this->response_message_.push_back(byte_);
|
||||
int PanasonicHeatpumpComponent::getExtraResponseByte(const int index) {
|
||||
if (this->heatpump_extra_message_.size() > index)
|
||||
return this->heatpump_extra_message_[index];
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 2. byte contains the payload size
|
||||
if (this->response_message_.size() == 2)
|
||||
{
|
||||
this->payload_length_ = byte_;
|
||||
}
|
||||
// 3. byte shall be 0x01 or 0x10
|
||||
if (this->response_message_.size() == 3 && byte_ != 0x01 && byte_ != 0x10)
|
||||
{
|
||||
this->response_receiving_ = false;
|
||||
ESP_LOGW(TAG, "Invalid response message: 0x%s. Expected last byte to be 0x01 or 0x10",
|
||||
PanasonicHelpers::byte_array_to_hex_string(this->response_message_, ','));
|
||||
delay(10); // NOLINT
|
||||
continue;
|
||||
}
|
||||
// 4. byte shall be 0x10 or 0x21
|
||||
if (this->response_message_.size() == 4 && byte_ != 0x10 && byte_ != 0x21)
|
||||
{
|
||||
this->response_receiving_ = false;
|
||||
ESP_LOGW(TAG, "Invalid response message: 0x%s. Expected last byte to be 0x10 or 0x21",
|
||||
PanasonicHelpers::byte_array_to_hex_string(this->response_message_, ','));
|
||||
delay(10); // NOLINT
|
||||
continue;
|
||||
}
|
||||
ResponseType PanasonicHeatpumpComponent::check_response(const std::vector<uint8_t>& data) {
|
||||
// Read response message:
|
||||
// format: 0x71 [payload_length] 0x01 [0x10 || 0x21] [[TOP0 - TOP114] ...] 0x00 [checksum]
|
||||
// payload_length: payload_length + 3 = packet_length
|
||||
// checksum: if (sum(all bytes) & 0xFF == 0) ==> valid packet
|
||||
|
||||
// Check if message is complete
|
||||
if (this->response_message_.size() > 2 &&
|
||||
this->response_message_.size() == this->payload_length_ + 3)
|
||||
{
|
||||
this->response_receiving_ = false;
|
||||
this->current_response_count_++;
|
||||
if (this->log_uart_msg_) PanasonicHelpers::log_uart_hex(UART_LOG_RX, this->response_message_, ',');
|
||||
}
|
||||
}
|
||||
}
|
||||
if (data.empty())
|
||||
return ResponseType::UNKNOWN;
|
||||
if (data[0] != 0x71)
|
||||
return ResponseType::UNKNOWN;
|
||||
if (this->response_receiving_)
|
||||
return ResponseType::UNKNOWN;
|
||||
if (data.size() != RESPONSE_MSG_SIZE) {
|
||||
ESP_LOGW(TAG, "Invalid response message length: recieved %d - expected %d", data.size(), RESPONSE_MSG_SIZE);
|
||||
delay(10); // NOLINT
|
||||
return ResponseType::UNKNOWN;
|
||||
}
|
||||
|
||||
void PanasonicHeatpumpComponent::send_request(RequestType requestType)
|
||||
{
|
||||
switch (requestType)
|
||||
{
|
||||
case RequestType::COMMAND:
|
||||
if (this->log_uart_msg_) PanasonicHelpers::log_uart_hex(UART_LOG_TX, this->command_message_, ',');
|
||||
this->write_array(this->command_message_);
|
||||
this->flush();
|
||||
break;
|
||||
case RequestType::INITIAL:
|
||||
// Probably not necessary but CZ-TAW1 sends this query on boot
|
||||
if (this->log_uart_msg_) PanasonicHelpers::log_uart_hex(UART_LOG_TX, PanasonicCommand::InitialRequest, INIT_REQUEST_SIZE, ',');
|
||||
this->write_array(PanasonicCommand::InitialRequest, INIT_REQUEST_SIZE);
|
||||
this->flush();
|
||||
break;
|
||||
case RequestType::POLLING:
|
||||
if (this->log_uart_msg_) PanasonicHelpers::log_uart_hex(UART_LOG_TX, PanasonicCommand::PollingMessage, DATA_MESSAGE_SIZE, ',');
|
||||
this->write_array(PanasonicCommand::PollingMessage, DATA_MESSAGE_SIZE);
|
||||
this->flush();
|
||||
break;
|
||||
case RequestType::POLLING_EXTRA:
|
||||
if (this->log_uart_msg_) PanasonicHelpers::log_uart_hex(UART_LOG_TX, PanasonicCommand::PollingExtraMessage, DATA_MESSAGE_SIZE, ',');
|
||||
this->write_array(PanasonicCommand::PollingExtraMessage, DATA_MESSAGE_SIZE);
|
||||
this->flush();
|
||||
break;
|
||||
};
|
||||
// Verify checksum
|
||||
uint8_t checksum = 0;
|
||||
for (int i = 0; i < data.size(); i++) {
|
||||
checksum += data[i];
|
||||
}
|
||||
// all bytes (including checksum byte) shall be 0x00
|
||||
if (checksum != 0) {
|
||||
ESP_LOGW(TAG, "Invalid response message: checksum = 0x%02X, last_byte = 0x%02X", checksum, data[202]);
|
||||
delay(10); // NOLINT
|
||||
return ResponseType::UNKNOWN;
|
||||
}
|
||||
|
||||
this->next_request_ = RequestType::NONE;
|
||||
}
|
||||
this->send_extra_request_ = data[3] == 0x10 && data[199] > 0x02 && this->send_extra_request_ == false ? true : false;
|
||||
|
||||
void PanasonicHeatpumpComponent::read_request()
|
||||
{
|
||||
if (this->uart_client_ == nullptr) return;
|
||||
// Get response type and save the response
|
||||
auto responseType = ResponseType::UNKNOWN;
|
||||
if (data[3] == 0x10) {
|
||||
responseType = ResponseType::STANDARD;
|
||||
this->heatpump_default_message_ = data;
|
||||
} else if (data[3] == 0x21) {
|
||||
responseType = ResponseType::EXTRA;
|
||||
this->heatpump_extra_message_ = data;
|
||||
}
|
||||
if (responseType == ResponseType::UNKNOWN) {
|
||||
ESP_LOGW(TAG, "Unknown response type (4. byte): 0x%02X. Expected 0x10 or 0x21.", data[3]);
|
||||
delay(10); // NOLINT
|
||||
return responseType;
|
||||
}
|
||||
|
||||
while (this->uart_client_->available())
|
||||
{
|
||||
// Read each byte from client and forward it directly to the heatpump
|
||||
this->uart_client_->read_byte(&byte_);
|
||||
this->write_byte(byte_);
|
||||
// Check if the current response is a new response
|
||||
if (this->last_response_count_ == this->current_response_count_)
|
||||
return ResponseType::UNKNOWN;
|
||||
this->last_response_count_ = this->current_response_count_;
|
||||
|
||||
// Message shall start with 0x31, 0x71 or 0xF1, if not skip this byte
|
||||
if (!this->request_receiving_)
|
||||
{
|
||||
if (byte_ != 0x31 && byte_ != 0x71 && byte_ != 0xF1) continue;
|
||||
this->request_message_.clear();
|
||||
this->request_receiving_ = true;
|
||||
}
|
||||
// Add current byte to message buffer
|
||||
this->request_message_.push_back(byte_);
|
||||
return responseType;
|
||||
}
|
||||
|
||||
// 2. byte contains the payload size
|
||||
if (this->request_message_.size() == 2)
|
||||
{
|
||||
this->payload_length_ = byte_;
|
||||
}
|
||||
// 3. byte shall be 0x01 or 0x10
|
||||
if (this->request_message_.size() == 3 && byte_ != 0x01 && byte_ != 0x10)
|
||||
{
|
||||
this->request_receiving_ = false;
|
||||
ESP_LOGW(TAG, "Invalid request message: 0x%s. Expected last byte to be 0x01 or 0x10",
|
||||
PanasonicHelpers::byte_array_to_hex_string(this->request_message_, ','));
|
||||
delay(10); // NOLINT
|
||||
continue;
|
||||
}
|
||||
// 4. byte shall be 0x10 or 0x21
|
||||
if (this->request_message_.size() == 4 && byte_ != 0x10 && byte_ != 0x21)
|
||||
{
|
||||
this->request_receiving_ = false;
|
||||
ESP_LOGW(TAG, "Invalid request message: 0x%s. Expected last byte to be 0x10 or 0x21",
|
||||
PanasonicHelpers::byte_array_to_hex_string(this->request_message_, ','));
|
||||
delay(10); // NOLINT
|
||||
continue;
|
||||
}
|
||||
void PanasonicHeatpumpComponent::set_command_high_nibble(const uint8_t value, const uint8_t index) {
|
||||
if (this->next_request_ != RequestType::COMMAND) {
|
||||
// initialize the command
|
||||
this->command_message_.assign(std::begin(PanasonicCommand::CommandMessage),
|
||||
std::end(PanasonicCommand::CommandMessage));
|
||||
}
|
||||
uint8_t lowNibble = this->heatpump_default_message_[index] & 0b1111;
|
||||
uint8_t highNibble = value << 4;
|
||||
// set command byte
|
||||
this->command_message_[index] = highNibble + lowNibble;
|
||||
// calculate and set set checksum (last element)
|
||||
this->command_message_.back() =
|
||||
PanasonicCommand::calcChecksum(this->command_message_, this->command_message_.size() - 1);
|
||||
|
||||
// Check if message is complete
|
||||
if (this->request_message_.size() > 2 &&
|
||||
this->request_message_.size() == this->payload_length_ + 3)
|
||||
{
|
||||
this->request_receiving_ = false;
|
||||
if (this->log_uart_msg_) PanasonicHelpers::log_uart_hex(UART_LOG_TX, this->request_message_, ',');
|
||||
}
|
||||
}
|
||||
}
|
||||
// command will be send on next loop
|
||||
this->next_request_ = RequestType::COMMAND;
|
||||
}
|
||||
|
||||
int PanasonicHeatpumpComponent::getResponseByte(const int index)
|
||||
{
|
||||
if (this->heatpump_default_message_.size() > index) return this->heatpump_default_message_[index];
|
||||
return -1;
|
||||
}
|
||||
void PanasonicHeatpumpComponent::set_command_low_nibble(const uint8_t value, const uint8_t index) {
|
||||
if (this->next_request_ != RequestType::COMMAND) {
|
||||
// initialize the command
|
||||
this->command_message_.assign(std::begin(PanasonicCommand::CommandMessage),
|
||||
std::end(PanasonicCommand::CommandMessage));
|
||||
}
|
||||
uint8_t highNibble = this->heatpump_default_message_[index] & 0b11110000;
|
||||
uint8_t lowNibble = value & 0b1111;
|
||||
// set command byte
|
||||
this->command_message_[index] = highNibble + lowNibble;
|
||||
// calculate and set set checksum (last element)
|
||||
this->command_message_.back() =
|
||||
PanasonicCommand::calcChecksum(this->command_message_, this->command_message_.size() - 1);
|
||||
|
||||
int PanasonicHeatpumpComponent::getExtraResponseByte(const int index)
|
||||
{
|
||||
if (this->heatpump_extra_message_.size() > index) return this->heatpump_extra_message_[index];
|
||||
return -1;
|
||||
}
|
||||
// command will be send on next loop
|
||||
this->next_request_ = RequestType::COMMAND;
|
||||
}
|
||||
|
||||
ResponseType PanasonicHeatpumpComponent::check_response(const std::vector<uint8_t>& data)
|
||||
{
|
||||
// Read response message:
|
||||
// format: 0x71 [payload_length] 0x01 [0x10 || 0x21] [[TOP0 - TOP114] ...] 0x00 [checksum]
|
||||
// payload_length: payload_length + 3 = packet_length
|
||||
// checksum: if (sum(all bytes) & 0xFF == 0) ==> valid packet
|
||||
void PanasonicHeatpumpComponent::set_command_byte(const uint8_t value, const uint8_t index) {
|
||||
if (this->next_request_ != RequestType::COMMAND) {
|
||||
// initialize the command
|
||||
this->command_message_.assign(std::begin(PanasonicCommand::CommandMessage),
|
||||
std::end(PanasonicCommand::CommandMessage));
|
||||
}
|
||||
// set command byte
|
||||
this->command_message_[index] = value;
|
||||
// calculate and set set checksum (last element)
|
||||
this->command_message_.back() =
|
||||
PanasonicCommand::calcChecksum(this->command_message_, this->command_message_.size() - 1);
|
||||
|
||||
if (data.empty()) return ResponseType::UNKNOWN;
|
||||
if (data[0] != 0x71) return ResponseType::UNKNOWN;
|
||||
if (this->response_receiving_) return ResponseType::UNKNOWN;
|
||||
if (data.size() != RESPONSE_MSG_SIZE)
|
||||
{
|
||||
ESP_LOGW(TAG, "Invalid response message length: recieved %d - expected %d", data.size(), RESPONSE_MSG_SIZE);
|
||||
delay(10); // NOLINT
|
||||
return ResponseType::UNKNOWN;
|
||||
}
|
||||
// command will be send on next loop
|
||||
this->next_request_ = RequestType::COMMAND;
|
||||
}
|
||||
|
||||
// Verify checksum
|
||||
uint8_t checksum = 0;
|
||||
for (int i = 0; i < data.size(); i++)
|
||||
{
|
||||
checksum += data[i];
|
||||
}
|
||||
// all bytes (including checksum byte) shall be 0x00
|
||||
if (checksum != 0)
|
||||
{
|
||||
ESP_LOGW(TAG, "Invalid response message: checksum = 0x%02X, last_byte = 0x%02X", checksum, data[202]);
|
||||
delay(10); // NOLINT
|
||||
return ResponseType::UNKNOWN;
|
||||
}
|
||||
void PanasonicHeatpumpComponent::set_command_curve(const uint8_t value, const uint8_t index) {
|
||||
if (this->next_request_ != RequestType::COMMAND) {
|
||||
// initialize the command
|
||||
this->command_message_.assign(std::begin(PanasonicCommand::CommandMessage),
|
||||
std::end(PanasonicCommand::CommandMessage));
|
||||
}
|
||||
|
||||
this->send_extra_request_ = data[3] == 0x10 && data[199] > 0x02 &&
|
||||
this->send_extra_request_ == false ? true : false;
|
||||
// Set zone 1 curve bytes
|
||||
if (index == 75 || index == 76 || index == 77 || index == 78 || index == 86 || index == 87 || index == 88 ||
|
||||
index == 89) {
|
||||
this->command_message_[75] = this->heatpump_default_message_[75];
|
||||
this->command_message_[76] = this->heatpump_default_message_[76];
|
||||
this->command_message_[77] = this->heatpump_default_message_[77];
|
||||
this->command_message_[78] = this->heatpump_default_message_[78];
|
||||
this->command_message_[86] = this->heatpump_default_message_[86];
|
||||
this->command_message_[87] = this->heatpump_default_message_[87];
|
||||
this->command_message_[88] = this->heatpump_default_message_[88];
|
||||
this->command_message_[89] = this->heatpump_default_message_[89];
|
||||
}
|
||||
// Set zone 2 curve bytes
|
||||
if (index == 79 || index == 80 || index == 81 || index == 82 || index == 90 || index == 91 || index == 92 ||
|
||||
index == 93) {
|
||||
this->command_message_[79] = this->heatpump_default_message_[79];
|
||||
this->command_message_[80] = this->heatpump_default_message_[80];
|
||||
this->command_message_[81] = this->heatpump_default_message_[81];
|
||||
this->command_message_[82] = this->heatpump_default_message_[82];
|
||||
this->command_message_[90] = this->heatpump_default_message_[90];
|
||||
this->command_message_[91] = this->heatpump_default_message_[91];
|
||||
this->command_message_[92] = this->heatpump_default_message_[92];
|
||||
this->command_message_[93] = this->heatpump_default_message_[93];
|
||||
}
|
||||
|
||||
// Get response type and save the response
|
||||
auto responseType = ResponseType::UNKNOWN;
|
||||
if (data[3] == 0x10)
|
||||
{
|
||||
responseType = ResponseType::DEFAULT;
|
||||
this->heatpump_default_message_ = data;
|
||||
}
|
||||
else if (data[3] == 0x21)
|
||||
{
|
||||
responseType = ResponseType::EXTRA;
|
||||
this->heatpump_extra_message_ = data;
|
||||
}
|
||||
if (responseType == ResponseType::UNKNOWN)
|
||||
{
|
||||
ESP_LOGW(TAG, "Unknown response type (4. byte): 0x%02X. Expected 0x10 or 0x21.", data[3]);
|
||||
delay(10); // NOLINT
|
||||
return responseType;
|
||||
}
|
||||
// set command byte
|
||||
this->command_message_[index] = value;
|
||||
// calculate and set set checksum (last element)
|
||||
this->command_message_.back() =
|
||||
PanasonicCommand::calcChecksum(this->command_message_, this->command_message_.size() - 1);
|
||||
|
||||
// Check if the current response is a new response
|
||||
if (this->last_response_count_ == this->current_response_count_) return ResponseType::UNKNOWN;
|
||||
this->last_response_count_ = this->current_response_count_;
|
||||
|
||||
return responseType;
|
||||
}
|
||||
|
||||
void PanasonicHeatpumpComponent::set_command_high_nibble(const uint8_t value, const uint8_t index)
|
||||
{
|
||||
if (this->next_request_ != RequestType::COMMAND)
|
||||
{
|
||||
// initialize the command
|
||||
this->command_message_.assign(std::begin(PanasonicCommand::CommandMessage),
|
||||
std::end(PanasonicCommand::CommandMessage));
|
||||
}
|
||||
uint8_t lowNibble = this->heatpump_default_message_[index] & 0b1111;
|
||||
uint8_t highNibble = value << 4;
|
||||
// set command byte
|
||||
this->command_message_[index] = highNibble + lowNibble;
|
||||
// calculate and set set checksum (last element)
|
||||
this->command_message_.back() = PanasonicCommand::calcChecksum(this->command_message_, this->command_message_.size() - 1);
|
||||
|
||||
// command will be send on next loop
|
||||
this->next_request_ = RequestType::COMMAND;
|
||||
}
|
||||
|
||||
void PanasonicHeatpumpComponent::set_command_low_nibble(const uint8_t value, const uint8_t index)
|
||||
{
|
||||
if (this->next_request_ != RequestType::COMMAND)
|
||||
{
|
||||
// initialize the command
|
||||
this->command_message_.assign(std::begin(PanasonicCommand::CommandMessage),
|
||||
std::end(PanasonicCommand::CommandMessage));
|
||||
}
|
||||
uint8_t highNibble = this->heatpump_default_message_[index] & 0b11110000;
|
||||
uint8_t lowNibble = value & 0b1111;
|
||||
// set command byte
|
||||
this->command_message_[index] = highNibble + lowNibble;
|
||||
// calculate and set set checksum (last element)
|
||||
this->command_message_.back() = PanasonicCommand::calcChecksum(this->command_message_, this->command_message_.size() - 1);
|
||||
|
||||
// command will be send on next loop
|
||||
this->next_request_ = RequestType::COMMAND;
|
||||
}
|
||||
|
||||
void PanasonicHeatpumpComponent::set_command_byte(const uint8_t value, const uint8_t index)
|
||||
{
|
||||
if (this->next_request_ != RequestType::COMMAND)
|
||||
{
|
||||
// initialize the command
|
||||
this->command_message_.assign(std::begin(PanasonicCommand::CommandMessage),
|
||||
std::end(PanasonicCommand::CommandMessage));
|
||||
}
|
||||
// set command byte
|
||||
this->command_message_[index] = value;
|
||||
// calculate and set set checksum (last element)
|
||||
this->command_message_.back() = PanasonicCommand::calcChecksum(this->command_message_, this->command_message_.size() - 1);
|
||||
|
||||
// command will be send on next loop
|
||||
this->next_request_ = RequestType::COMMAND;
|
||||
}
|
||||
|
||||
void PanasonicHeatpumpComponent::set_command_curve(const uint8_t value, const uint8_t index)
|
||||
{
|
||||
if (this->next_request_ != RequestType::COMMAND)
|
||||
{
|
||||
// initialize the command
|
||||
this->command_message_.assign(std::begin(PanasonicCommand::CommandMessage),
|
||||
std::end(PanasonicCommand::CommandMessage));
|
||||
}
|
||||
|
||||
// Set zone 1 curve bytes
|
||||
if (index == 75 || index == 76 || index == 77 || index == 78 ||
|
||||
index == 86 || index == 87 || index == 88 || index == 89)
|
||||
{
|
||||
this->command_message_[75] = this->heatpump_default_message_[75];
|
||||
this->command_message_[76] = this->heatpump_default_message_[76];
|
||||
this->command_message_[77] = this->heatpump_default_message_[77];
|
||||
this->command_message_[78] = this->heatpump_default_message_[78];
|
||||
this->command_message_[86] = this->heatpump_default_message_[86];
|
||||
this->command_message_[87] = this->heatpump_default_message_[87];
|
||||
this->command_message_[88] = this->heatpump_default_message_[88];
|
||||
this->command_message_[89] = this->heatpump_default_message_[89];
|
||||
}
|
||||
// Set zone 2 curve bytes
|
||||
if (index == 79 || index == 80 || index == 81 || index == 82 ||
|
||||
index == 90 || index == 91 || index == 92 || index == 93)
|
||||
{
|
||||
this->command_message_[79] = this->heatpump_default_message_[79];
|
||||
this->command_message_[80] = this->heatpump_default_message_[80];
|
||||
this->command_message_[81] = this->heatpump_default_message_[81];
|
||||
this->command_message_[82] = this->heatpump_default_message_[82];
|
||||
this->command_message_[90] = this->heatpump_default_message_[90];
|
||||
this->command_message_[91] = this->heatpump_default_message_[91];
|
||||
this->command_message_[92] = this->heatpump_default_message_[92];
|
||||
this->command_message_[93] = this->heatpump_default_message_[93];
|
||||
}
|
||||
|
||||
// set command byte
|
||||
this->command_message_[index] = value;
|
||||
// calculate and set set checksum (last element)
|
||||
this->command_message_.back() = PanasonicCommand::calcChecksum(this->command_message_, this->command_message_.size() - 1);
|
||||
|
||||
// command will be send on next loop
|
||||
this->next_request_ = RequestType::COMMAND;
|
||||
}
|
||||
} // namespace panasonic_heatpump
|
||||
// command will be send on next loop
|
||||
this->next_request_ = RequestType::COMMAND;
|
||||
}
|
||||
} // namespace panasonic_heatpump
|
||||
} // namespace esphome
|
||||
|
|
|
|||
|
|
@ -11,123 +11,141 @@
|
|||
#include "decode.h"
|
||||
#include "commands.h"
|
||||
|
||||
#ifndef PANASONIC_HEATPUMP_VERSION
|
||||
#define PANASONIC_HEATPUMP_VERSION "0.0.5"
|
||||
#endif
|
||||
|
||||
namespace esphome
|
||||
{
|
||||
namespace panasonic_heatpump
|
||||
{
|
||||
enum LoopState : uint8_t
|
||||
{
|
||||
READ_RESPONSE,
|
||||
CHECK_RESPONSE,
|
||||
PUBLISH_SENSOR,
|
||||
PUBLISH_BINARY_SENSOR,
|
||||
PUBLISH_TEXT_SENSOR,
|
||||
PUBLISH_NUMBER,
|
||||
PUBLISH_SELECT,
|
||||
PUBLISH_SWITCH,
|
||||
PUBLISH_CLIMATE,
|
||||
PUBLISH_EXTRA_SENSOR,
|
||||
SEND_REQUEST,
|
||||
READ_REQUEST,
|
||||
RESTART_LOOP,
|
||||
};
|
||||
namespace esphome {
|
||||
namespace panasonic_heatpump {
|
||||
enum LoopState : uint8_t {
|
||||
READ_RESPONSE,
|
||||
CHECK_RESPONSE,
|
||||
PUBLISH_SENSOR,
|
||||
PUBLISH_BINARY_SENSOR,
|
||||
PUBLISH_TEXT_SENSOR,
|
||||
PUBLISH_NUMBER,
|
||||
PUBLISH_SELECT,
|
||||
PUBLISH_SWITCH,
|
||||
PUBLISH_CLIMATE,
|
||||
PUBLISH_EXTRA_SENSOR,
|
||||
SEND_REQUEST,
|
||||
READ_REQUEST,
|
||||
RESTART_LOOP,
|
||||
};
|
||||
|
||||
enum RequestType : uint8_t
|
||||
{
|
||||
NONE,
|
||||
COMMAND,
|
||||
INITIAL,
|
||||
POLLING,
|
||||
POLLING_EXTRA,
|
||||
};
|
||||
enum RequestType : uint8_t {
|
||||
NONE,
|
||||
COMMAND,
|
||||
INITIAL,
|
||||
POLLING,
|
||||
POLLING_EXTRA,
|
||||
};
|
||||
|
||||
enum ResponseType : uint8_t
|
||||
{
|
||||
UNKNOWN,
|
||||
DEFAULT,
|
||||
EXTRA,
|
||||
};
|
||||
enum ResponseType : uint8_t {
|
||||
UNKNOWN,
|
||||
STANDARD,
|
||||
EXTRA,
|
||||
};
|
||||
|
||||
class PanasonicHeatpumpEntity
|
||||
{
|
||||
public:
|
||||
virtual void set_id(const int id) { id_ = id; }
|
||||
virtual void publish_new_state(const std::vector<uint8_t>& data) = 0;
|
||||
class PanasonicHeatpumpEntity {
|
||||
public:
|
||||
virtual void set_id(const int id) {
|
||||
id_ = id;
|
||||
}
|
||||
virtual void publish_new_state(const std::vector<uint8_t>& data) = 0;
|
||||
|
||||
protected:
|
||||
int id_ { -1 };
|
||||
int keep_state_ { 0 };
|
||||
};
|
||||
protected:
|
||||
int id_{-1};
|
||||
int keep_state_{0};
|
||||
};
|
||||
|
||||
class PanasonicHeatpumpComponent : public PollingComponent, public uart::UARTDevice
|
||||
{
|
||||
public:
|
||||
PanasonicHeatpumpComponent() = default;
|
||||
// base class functions
|
||||
float get_setup_priority() const override { return setup_priority::DATA; }
|
||||
void dump_config() override;
|
||||
void setup() override;
|
||||
void update() override;
|
||||
void loop() override;
|
||||
// option functions
|
||||
void set_uart_client(uart::UARTComponent* uart) { this->uart_client_ = uart; }
|
||||
void set_log_uart_msg(bool active) { this->log_uart_msg_ = active; }
|
||||
// uart message variables to use in lambda functions
|
||||
int getResponseByte(const int index);
|
||||
int getExtraResponseByte(const int index);
|
||||
// command functions
|
||||
void set_command_high_nibble(const uint8_t value, const uint8_t index);
|
||||
void set_command_low_nibble(const uint8_t value, const uint8_t index);
|
||||
void set_command_byte(const uint8_t value, const uint8_t index);
|
||||
void set_command_curve(const uint8_t value, const uint8_t index);
|
||||
// entity functions
|
||||
void add_binary_sensor(PanasonicHeatpumpEntity *binary_sensor) { binary_sensors_.push_back(binary_sensor); }
|
||||
void add_climate(PanasonicHeatpumpEntity *climate) { climates_.push_back(climate); }
|
||||
void add_number(PanasonicHeatpumpEntity *number) { numbers_.push_back(number); }
|
||||
void add_select(PanasonicHeatpumpEntity *select) { selects_.push_back(select); }
|
||||
void add_sensor(PanasonicHeatpumpEntity *sensor) { sensors_.push_back(sensor); }
|
||||
void add_switch(PanasonicHeatpumpEntity *switch_) { switches_.push_back(switch_); }
|
||||
void add_text_sensor(PanasonicHeatpumpEntity *text_sensor) { text_sensors_.push_back(text_sensor); }
|
||||
void add_extra_sensor(PanasonicHeatpumpEntity *sensor) { extra_sensors_.push_back(sensor); }
|
||||
class PanasonicHeatpumpComponent : public PollingComponent, public uart::UARTDevice {
|
||||
public:
|
||||
PanasonicHeatpumpComponent() = default;
|
||||
// base class functions
|
||||
float get_setup_priority() const override {
|
||||
return setup_priority::DATA;
|
||||
}
|
||||
void dump_config() override;
|
||||
void setup() override;
|
||||
void update() override;
|
||||
void loop() override;
|
||||
// option functions
|
||||
void set_uart_client(uart::UARTComponent* uart) {
|
||||
this->uart_client_ = uart;
|
||||
}
|
||||
void set_log_uart_msg(bool active) {
|
||||
this->log_uart_msg_ = active;
|
||||
}
|
||||
// uart message variables to use in lambda functions
|
||||
int getResponseByte(const int index);
|
||||
int getExtraResponseByte(const int index);
|
||||
// command functions
|
||||
void set_command_high_nibble(const uint8_t value, const uint8_t index);
|
||||
void set_command_low_nibble(const uint8_t value, const uint8_t index);
|
||||
void set_command_byte(const uint8_t value, const uint8_t index);
|
||||
void set_command_curve(const uint8_t value, const uint8_t index);
|
||||
// entity functions
|
||||
void add_binary_sensor(PanasonicHeatpumpEntity* binary_sensor) {
|
||||
binary_sensors_.push_back(binary_sensor);
|
||||
}
|
||||
void add_climate(PanasonicHeatpumpEntity* climate) {
|
||||
climates_.push_back(climate);
|
||||
}
|
||||
void add_number(PanasonicHeatpumpEntity* number) {
|
||||
numbers_.push_back(number);
|
||||
}
|
||||
void add_select(PanasonicHeatpumpEntity* select) {
|
||||
selects_.push_back(select);
|
||||
}
|
||||
void add_sensor(PanasonicHeatpumpEntity* sensor) {
|
||||
sensors_.push_back(sensor);
|
||||
}
|
||||
void add_switch(PanasonicHeatpumpEntity* switch_) {
|
||||
switches_.push_back(switch_);
|
||||
}
|
||||
void add_text_sensor(PanasonicHeatpumpEntity* text_sensor) {
|
||||
text_sensors_.push_back(text_sensor);
|
||||
}
|
||||
void add_extra_sensor(PanasonicHeatpumpEntity* sensor) {
|
||||
extra_sensors_.push_back(sensor);
|
||||
}
|
||||
|
||||
protected:
|
||||
const std::string version = "0.0.5";
|
||||
|
||||
// options variables
|
||||
uart::UARTComponent* uart_client_ { nullptr };
|
||||
bool log_uart_msg_ { false };
|
||||
// uart message variables
|
||||
std::vector<uint8_t> heatpump_default_message_;
|
||||
std::vector<uint8_t> heatpump_extra_message_;
|
||||
std::vector<uint8_t> response_message_;
|
||||
std::vector<uint8_t> request_message_;
|
||||
std::vector<uint8_t> command_message_;
|
||||
uint8_t payload_length_;
|
||||
uint8_t byte_;
|
||||
uint8_t current_response_count_ { 0 };
|
||||
uint8_t last_response_count_ { 0 };
|
||||
bool response_receiving_ { false };
|
||||
bool request_receiving_ { false };
|
||||
bool send_extra_request_ { false };
|
||||
LoopState loop_state_ { LoopState::RESTART_LOOP };
|
||||
RequestType next_request_ { RequestType::INITIAL };
|
||||
ResponseType current_response_ { ResponseType::UNKNOWN };
|
||||
// entity vectors
|
||||
std::vector<PanasonicHeatpumpEntity *> binary_sensors_;
|
||||
std::vector<PanasonicHeatpumpEntity *> climates_;
|
||||
std::vector<PanasonicHeatpumpEntity *> numbers_;
|
||||
std::vector<PanasonicHeatpumpEntity *> selects_;
|
||||
std::vector<PanasonicHeatpumpEntity *> sensors_;
|
||||
std::vector<PanasonicHeatpumpEntity *> switches_;
|
||||
std::vector<PanasonicHeatpumpEntity *> text_sensors_;
|
||||
std::vector<PanasonicHeatpumpEntity *> extra_sensors_;
|
||||
protected:
|
||||
// options variables
|
||||
uart::UARTComponent* uart_client_{nullptr};
|
||||
bool log_uart_msg_{false};
|
||||
// uart message variables
|
||||
std::vector<uint8_t> heatpump_default_message_;
|
||||
std::vector<uint8_t> heatpump_extra_message_;
|
||||
std::vector<uint8_t> response_message_;
|
||||
std::vector<uint8_t> request_message_;
|
||||
std::vector<uint8_t> command_message_;
|
||||
uint8_t payload_length_;
|
||||
uint8_t byte_;
|
||||
uint8_t current_response_count_{0};
|
||||
uint8_t last_response_count_{0};
|
||||
bool response_receiving_{false};
|
||||
bool request_receiving_{false};
|
||||
bool send_extra_request_{false};
|
||||
LoopState loop_state_{LoopState::RESTART_LOOP};
|
||||
RequestType next_request_{RequestType::INITIAL};
|
||||
ResponseType current_response_{ResponseType::UNKNOWN};
|
||||
// entity vectors
|
||||
std::vector<PanasonicHeatpumpEntity*> binary_sensors_;
|
||||
std::vector<PanasonicHeatpumpEntity*> climates_;
|
||||
std::vector<PanasonicHeatpumpEntity*> numbers_;
|
||||
std::vector<PanasonicHeatpumpEntity*> selects_;
|
||||
std::vector<PanasonicHeatpumpEntity*> sensors_;
|
||||
std::vector<PanasonicHeatpumpEntity*> switches_;
|
||||
std::vector<PanasonicHeatpumpEntity*> text_sensors_;
|
||||
std::vector<PanasonicHeatpumpEntity*> extra_sensors_;
|
||||
|
||||
// uart message functions
|
||||
void read_response();
|
||||
void send_request(RequestType requestType);
|
||||
void read_request();
|
||||
ResponseType check_response(const std::vector<uint8_t>& data);
|
||||
};
|
||||
} // namespace panasonic_heatpump
|
||||
// uart message functions
|
||||
void read_response();
|
||||
void send_request(RequestType requestType);
|
||||
void read_request();
|
||||
ResponseType check_response(const std::vector<uint8_t>& data);
|
||||
};
|
||||
} // namespace panasonic_heatpump
|
||||
} // namespace esphome
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import select
|
||||
from esphome.const import (
|
||||
ENTITY_CATEGORY_CONFIG,
|
||||
from .. import (
|
||||
CONF_PANASONIC_HEATPUMP_ID,
|
||||
PanasonicHeatpumpComponent,
|
||||
panasonic_heatpump_ns,
|
||||
)
|
||||
from .. import CONF_PANASONIC_HEATPUMP_ID, PanasonicHeatpumpComponent, panasonic_heatpump_ns
|
||||
|
||||
|
||||
CONF_COOL_MODE = "cool_mode"
|
||||
CONF_SET2 = "set2" # Set Holiday Mode
|
||||
|
|
@ -18,67 +18,104 @@ CONF_SET26 = "set26" # Set External PadHeater
|
|||
CONF_SET35 = "set35" # Set Bivalent Mode
|
||||
|
||||
TYPES = [
|
||||
CONF_SET2,
|
||||
CONF_SET3,
|
||||
CONF_SET4,
|
||||
CONF_SET9,
|
||||
CONF_SET17,
|
||||
CONF_SET26,
|
||||
CONF_SET35,
|
||||
CONF_SET2,
|
||||
CONF_SET3,
|
||||
CONF_SET4,
|
||||
CONF_SET9,
|
||||
CONF_SET17,
|
||||
CONF_SET26,
|
||||
CONF_SET35,
|
||||
]
|
||||
|
||||
CONF_SELECTS = [
|
||||
[ "Off", "Scheduled", "Active", ],
|
||||
[ "Off", "Level 1", "Level 2", "Level 3", ],
|
||||
[ "Off", "30min", "60min", "90min", ],
|
||||
[ "TANK", "HEAT", "HEAT+TANK", ],
|
||||
[ "Zone 1", "Zone 2", "Zone 1 & 2", ],
|
||||
[ "Disabled", "Type-A", "Type-B" ],
|
||||
[ "Alternative", "Parallel", "Advanced Parallel" ],
|
||||
[
|
||||
"Off",
|
||||
"Scheduled",
|
||||
"Active",
|
||||
],
|
||||
[
|
||||
"Off",
|
||||
"Level 1",
|
||||
"Level 2",
|
||||
"Level 3",
|
||||
],
|
||||
[
|
||||
"Off",
|
||||
"30min",
|
||||
"60min",
|
||||
"90min",
|
||||
],
|
||||
[
|
||||
"TANK",
|
||||
"HEAT",
|
||||
"HEAT+TANK",
|
||||
],
|
||||
[
|
||||
"Zone 1",
|
||||
"Zone 2",
|
||||
"Zone 1 & 2",
|
||||
],
|
||||
["Disabled", "Type-A", "Type-B"],
|
||||
["Alternative", "Parallel", "Advanced Parallel"],
|
||||
]
|
||||
CONF_SELECT_COOL_MODE = [ "TANK", "HEAT", "HEAT+TANK", "COOL", "COOL+TANK", "AUTO", "AUTO+TANK", ]
|
||||
|
||||
PanasonicHeatpumpSelect = panasonic_heatpump_ns.class_("PanasonicHeatpumpSelect", select.Select, cg.Component)
|
||||
CONF_SELECT_COOL_MODE = [
|
||||
"TANK",
|
||||
"HEAT",
|
||||
"HEAT+TANK",
|
||||
"COOL",
|
||||
"COOL+TANK",
|
||||
"AUTO",
|
||||
"AUTO+TANK",
|
||||
]
|
||||
|
||||
PanasonicHeatpumpSelect = panasonic_heatpump_ns.class_(
|
||||
"PanasonicHeatpumpSelect", select.Select, cg.Component
|
||||
)
|
||||
|
||||
CONFIG_SCHEMA = cv.Schema(
|
||||
{
|
||||
cv.GenerateID(CONF_PANASONIC_HEATPUMP_ID): cv.use_id(
|
||||
PanasonicHeatpumpComponent
|
||||
),
|
||||
cv.Optional(CONF_COOL_MODE, default=False): cv.boolean,
|
||||
|
||||
cv.Optional(CONF_SET2): select.select_schema(
|
||||
PanasonicHeatpumpSelect,
|
||||
),
|
||||
cv.Optional(CONF_SET3): select.select_schema(
|
||||
PanasonicHeatpumpSelect,
|
||||
),
|
||||
cv.Optional(CONF_SET4): select.select_schema(
|
||||
PanasonicHeatpumpSelect,
|
||||
),
|
||||
cv.Optional(CONF_SET9): select.select_schema(
|
||||
PanasonicHeatpumpSelect,
|
||||
),
|
||||
cv.Optional(CONF_SET17): select.select_schema(
|
||||
PanasonicHeatpumpSelect,
|
||||
),
|
||||
cv.Optional(CONF_SET26): select.select_schema(
|
||||
PanasonicHeatpumpSelect,
|
||||
),
|
||||
cv.Optional(CONF_SET35): select.select_schema(
|
||||
PanasonicHeatpumpSelect,
|
||||
),
|
||||
}
|
||||
{
|
||||
cv.GenerateID(CONF_PANASONIC_HEATPUMP_ID): cv.use_id(
|
||||
PanasonicHeatpumpComponent
|
||||
),
|
||||
cv.Optional(CONF_COOL_MODE, default=False): cv.boolean,
|
||||
cv.Optional(CONF_SET2): select.select_schema(
|
||||
PanasonicHeatpumpSelect,
|
||||
),
|
||||
cv.Optional(CONF_SET3): select.select_schema(
|
||||
PanasonicHeatpumpSelect,
|
||||
),
|
||||
cv.Optional(CONF_SET4): select.select_schema(
|
||||
PanasonicHeatpumpSelect,
|
||||
),
|
||||
cv.Optional(CONF_SET9): select.select_schema(
|
||||
PanasonicHeatpumpSelect,
|
||||
),
|
||||
cv.Optional(CONF_SET17): select.select_schema(
|
||||
PanasonicHeatpumpSelect,
|
||||
),
|
||||
cv.Optional(CONF_SET26): select.select_schema(
|
||||
PanasonicHeatpumpSelect,
|
||||
),
|
||||
cv.Optional(CONF_SET35): select.select_schema(
|
||||
PanasonicHeatpumpSelect,
|
||||
),
|
||||
}
|
||||
).extend(cv.COMPONENT_SCHEMA)
|
||||
|
||||
async def to_code(config):
|
||||
parent = await cg.get_variable(config[CONF_PANASONIC_HEATPUMP_ID])
|
||||
for index, key in enumerate(TYPES):
|
||||
if child_config := config.get(key):
|
||||
child_options = CONF_SELECT_COOL_MODE if config[CONF_COOL_MODE] and key == CONF_SET9 else CONF_SELECTS[index]
|
||||
|
||||
var = await select.new_select(child_config, options=child_options)
|
||||
await cg.register_component(var, child_config)
|
||||
cg.add(var.set_parent(parent))
|
||||
cg.add(var.set_id(index))
|
||||
cg.add(parent.add_select(var))
|
||||
async def to_code(config):
|
||||
parent = await cg.get_variable(config[CONF_PANASONIC_HEATPUMP_ID])
|
||||
for index, key in enumerate(TYPES):
|
||||
if child_config := config.get(key):
|
||||
child_options = (
|
||||
CONF_SELECT_COOL_MODE
|
||||
if config[CONF_COOL_MODE] and key == CONF_SET9
|
||||
else CONF_SELECTS[index]
|
||||
)
|
||||
|
||||
var = await select.new_select(child_config, options=child_options)
|
||||
await cg.register_component(var, child_config)
|
||||
cg.add(var.set_parent(parent))
|
||||
cg.add(var.set_id(index))
|
||||
cg.add(parent.add_select(var))
|
||||
|
|
|
|||
|
|
@ -1,98 +1,102 @@
|
|||
#include "panasonic_heatpump_select.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace panasonic_heatpump {
|
||||
static const char* const TAG = "panasonic_heatpump.select";
|
||||
|
||||
namespace esphome
|
||||
{
|
||||
namespace panasonic_heatpump
|
||||
{
|
||||
static const char *const TAG = "panasonic_heatpump.select";
|
||||
void PanasonicHeatpumpSelect::dump_config() {
|
||||
LOG_SELECT("", "Panasonic Heatpump Select", this);
|
||||
delay(10);
|
||||
}
|
||||
|
||||
void PanasonicHeatpumpSelect::dump_config()
|
||||
{
|
||||
LOG_SELECT("", "Panasonic Heatpump Select", this);
|
||||
delay(10);
|
||||
}
|
||||
void PanasonicHeatpumpSelect::control(const std::string& value) {
|
||||
auto optIndex = this->index_of(value);
|
||||
if (!optIndex.has_value())
|
||||
return;
|
||||
size_t index = optIndex.value();
|
||||
|
||||
void PanasonicHeatpumpSelect::control(const std::string &value)
|
||||
{
|
||||
auto optIndex = this->index_of(value);
|
||||
if (!optIndex.has_value()) return;
|
||||
size_t index = optIndex.value();
|
||||
switch (this->id_) {
|
||||
case SelectIds::CONF_SET2:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus1Multiply16(index), 5);
|
||||
break;
|
||||
case SelectIds::CONF_SET3:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus1Multiply8(index), 7);
|
||||
break;
|
||||
case SelectIds::CONF_SET4:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus1(index), 7);
|
||||
break;
|
||||
case SelectIds::CONF_SET9:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setOperationMode(index), 6);
|
||||
break;
|
||||
case SelectIds::CONF_SET17:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus1Multiply64(index), 6);
|
||||
break;
|
||||
case SelectIds::CONF_SET26:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus1Multiply16(index), 25);
|
||||
break;
|
||||
case SelectIds::CONF_SET35:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus1Multiply4(index), 26);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
};
|
||||
|
||||
switch (this->id_)
|
||||
{
|
||||
case SelectIds::CONF_SET2:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus1Multiply16(index), 5);
|
||||
break;
|
||||
case SelectIds::CONF_SET3:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus1Multiply8(index), 7);
|
||||
break;
|
||||
case SelectIds::CONF_SET4:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus1(index), 7);
|
||||
break;
|
||||
case SelectIds::CONF_SET9:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setOperationMode(index), 6);
|
||||
break;
|
||||
case SelectIds::CONF_SET17:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus1Multiply64(index), 6);
|
||||
break;
|
||||
case SelectIds::CONF_SET26:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus1Multiply16(index), 25);
|
||||
break;
|
||||
case SelectIds::CONF_SET35:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus1Multiply4(index), 26);
|
||||
break;
|
||||
default: return;
|
||||
};
|
||||
this->publish_state(value);
|
||||
this->keep_state_ = 2;
|
||||
}
|
||||
|
||||
this->publish_state(value);
|
||||
this->keep_state_ = 2;
|
||||
}
|
||||
void PanasonicHeatpumpSelect::publish_new_state(const std::vector<uint8_t>& data) {
|
||||
if (this->keep_state_ > 0) {
|
||||
this->keep_state_--;
|
||||
return;
|
||||
}
|
||||
if (data.empty())
|
||||
return;
|
||||
|
||||
void PanasonicHeatpumpSelect::publish_new_state(const std::vector<uint8_t>& data)
|
||||
{
|
||||
if (this->keep_state_ > 0)
|
||||
{
|
||||
this->keep_state_--;
|
||||
return;
|
||||
}
|
||||
if (data.empty()) return;
|
||||
std::string new_state;
|
||||
switch (this->id_) {
|
||||
case SelectIds::CONF_SET9:
|
||||
new_state =
|
||||
PanasonicDecode::getTextState(PanasonicDecode::OperationMode, PanasonicDecode::getOperationMode(data[6]));
|
||||
if (this->has_state() && this->current_option() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SelectIds::CONF_SET4:
|
||||
new_state = PanasonicDecode::getTextState(PanasonicDecode::PowerfulMode, PanasonicDecode::getBit6and7and8(data[7]));
|
||||
if (this->has_state() && this->current_option() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SelectIds::CONF_SET3:
|
||||
new_state = PanasonicDecode::getTextState(PanasonicDecode::QuietMode, PanasonicDecode::getBit3and4and5(data[7]));
|
||||
if (this->has_state() && this->current_option() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SelectIds::CONF_SET2:
|
||||
new_state = PanasonicDecode::getTextState(PanasonicDecode::HolidayState, PanasonicDecode::getBit3and4(data[5]));
|
||||
if (this->has_state() && this->current_option() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SelectIds::CONF_SET17:
|
||||
new_state = PanasonicDecode::getTextState(PanasonicDecode::ZoneState, PanasonicDecode::getBit1and2(data[6]));
|
||||
if (this->has_state() && this->current_option() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SelectIds::CONF_SET26:
|
||||
new_state =
|
||||
PanasonicDecode::getTextState(PanasonicDecode::ExtPadHeaterType, PanasonicDecode::getBit3and4(data[25]));
|
||||
if (this->has_state() && this->current_option() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SelectIds::CONF_SET35:
|
||||
new_state = PanasonicDecode::getTextState(PanasonicDecode::BivalentMode, PanasonicDecode::getBit5and6(data[26]));
|
||||
if (this->has_state() && this->current_option() == new_state)
|
||||
return;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
};
|
||||
|
||||
std::string new_state;
|
||||
switch (this->id_)
|
||||
{
|
||||
case SelectIds::CONF_SET9:
|
||||
new_state = PanasonicDecode::getTextState(PanasonicDecode::OperationMode, PanasonicDecode::getOperationMode(data[6]));
|
||||
if (this->has_state() && this->current_option() == new_state) return;
|
||||
break;
|
||||
case SelectIds::CONF_SET4:
|
||||
new_state = PanasonicDecode::getTextState(PanasonicDecode::PowerfulMode, PanasonicDecode::getBit6and7and8(data[7]));
|
||||
if (this->has_state() && this->current_option() == new_state) return;
|
||||
break;
|
||||
case SelectIds::CONF_SET3:
|
||||
new_state = PanasonicDecode::getTextState(PanasonicDecode::QuietMode, PanasonicDecode::getBit3and4and5(data[7]));
|
||||
if (this->has_state() && this->current_option() == new_state) return;
|
||||
break;
|
||||
case SelectIds::CONF_SET2:
|
||||
new_state = PanasonicDecode::getTextState(PanasonicDecode::HolidayState, PanasonicDecode::getBit3and4(data[5]));
|
||||
if (this->has_state() && this->current_option() == new_state) return;
|
||||
break;
|
||||
case SelectIds::CONF_SET17:
|
||||
new_state = PanasonicDecode::getTextState(PanasonicDecode::ZoneState, PanasonicDecode::getBit1and2(data[6]));
|
||||
if (this->has_state() && this->current_option() == new_state) return;
|
||||
break;
|
||||
case SelectIds::CONF_SET26:
|
||||
new_state = PanasonicDecode::getTextState(PanasonicDecode::ExtPadHeaterType, PanasonicDecode::getBit3and4(data[25]));
|
||||
if (this->has_state() && this->current_option() == new_state) return;
|
||||
break;
|
||||
case SelectIds::CONF_SET35:
|
||||
new_state = PanasonicDecode::getTextState(PanasonicDecode::BivalentMode, PanasonicDecode::getBit5and6(data[26]));
|
||||
if (this->has_state() && this->current_option() == new_state) return;
|
||||
break;
|
||||
default: return;
|
||||
};
|
||||
|
||||
this->publish_state(new_state);
|
||||
}
|
||||
} // namespace panasonic_heatpump
|
||||
} // namespace esphome
|
||||
this->publish_state(new_state);
|
||||
}
|
||||
} // namespace panasonic_heatpump
|
||||
} // namespace esphome
|
||||
|
|
|
|||
|
|
@ -5,32 +5,29 @@
|
|||
#include "../decode.h"
|
||||
#include "../commands.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace panasonic_heatpump {
|
||||
enum SelectIds : uint8_t {
|
||||
CONF_SET2,
|
||||
CONF_SET3,
|
||||
CONF_SET4,
|
||||
CONF_SET9,
|
||||
CONF_SET17,
|
||||
CONF_SET26,
|
||||
CONF_SET35,
|
||||
};
|
||||
|
||||
namespace esphome
|
||||
{
|
||||
namespace panasonic_heatpump
|
||||
{
|
||||
enum SelectIds : uint8_t
|
||||
{
|
||||
CONF_SET2,
|
||||
CONF_SET3,
|
||||
CONF_SET4,
|
||||
CONF_SET9,
|
||||
CONF_SET17,
|
||||
CONF_SET26,
|
||||
CONF_SET35,
|
||||
};
|
||||
class PanasonicHeatpumpSelect : public select::Select,
|
||||
public Component,
|
||||
public Parented<PanasonicHeatpumpComponent>,
|
||||
public PanasonicHeatpumpEntity {
|
||||
public:
|
||||
PanasonicHeatpumpSelect() = default;
|
||||
void dump_config() override;
|
||||
void publish_new_state(const std::vector<uint8_t>& data) override;
|
||||
|
||||
class PanasonicHeatpumpSelect : public select::Select, public Component,
|
||||
public Parented<PanasonicHeatpumpComponent>, public PanasonicHeatpumpEntity
|
||||
{
|
||||
public:
|
||||
PanasonicHeatpumpSelect() = default;
|
||||
void dump_config() override;
|
||||
void publish_new_state(const std::vector<uint8_t>& data) override;
|
||||
|
||||
protected:
|
||||
void control(const std::string &value) override;
|
||||
};
|
||||
} // namespace panasonic_heatpump
|
||||
} // namespace esphome
|
||||
protected:
|
||||
void control(const std::string& value) override;
|
||||
};
|
||||
} // namespace panasonic_heatpump
|
||||
} // namespace esphome
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,434 +1,531 @@
|
|||
#include "panasonic_heatpump_sensor.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace panasonic_heatpump {
|
||||
static const char* const TAG = "panasonic_heatpump.sensor";
|
||||
|
||||
namespace esphome
|
||||
{
|
||||
namespace panasonic_heatpump
|
||||
{
|
||||
static const char *const TAG = "panasonic_heatpump.sensor";
|
||||
void PanasonicHeatpumpSensor::dump_config() {
|
||||
LOG_SENSOR("", "Panasonic Heatpump Sensor", this);
|
||||
delay(10);
|
||||
}
|
||||
|
||||
void PanasonicHeatpumpSensor::dump_config()
|
||||
{
|
||||
LOG_SENSOR("", "Panasonic Heatpump Sensor", this);
|
||||
delay(10);
|
||||
}
|
||||
void PanasonicHeatpumpSensor::publish_new_state(const std::vector<uint8_t>& data) {
|
||||
if (data.empty())
|
||||
return;
|
||||
|
||||
void PanasonicHeatpumpSensor::publish_new_state(const std::vector<uint8_t>& data)
|
||||
{
|
||||
if (data.empty()) return;
|
||||
float new_state;
|
||||
switch (this->id_) {
|
||||
case SensorIds::CONF_TOP1:
|
||||
new_state = PanasonicDecode::getPumpFlow(data, 169);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP5:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[143]) + PanasonicDecode::getFractional(data[118], 0);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP6:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[144]) + PanasonicDecode::getFractional(data[118], 3);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP7:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[153]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP8:
|
||||
new_state = PanasonicDecode::getByteMinus1(data[166]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP9:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[42]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP10:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[141]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP11:
|
||||
new_state = PanasonicDecode::getWordMinus1(data, 182);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP12:
|
||||
new_state = PanasonicDecode::getWordMinus1(data, 179);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP14:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[142]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP15:
|
||||
new_state = PanasonicDecode::getByteMinus1Times200(data[194]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP16:
|
||||
new_state = PanasonicDecode::getByteMinus1Times200(data[193]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP21:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[158]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP22:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[99]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP23:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[84]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP24:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[94]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP25:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[44]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP27:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[38]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP28:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[39]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP29:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[75]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP30:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[76]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP31:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[78]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP32:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[77]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP33:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[156]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP34:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[40]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP35:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[41]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP36:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[145]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP37:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[146]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP38:
|
||||
new_state = PanasonicDecode::getByteMinus1Times200(data[196]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP39:
|
||||
new_state = PanasonicDecode::getByteMinus1Times200(data[195]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP40:
|
||||
new_state = PanasonicDecode::getByteMinus1Times200(data[198]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP41:
|
||||
new_state = PanasonicDecode::getByteMinus1Times200(data[197]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP42:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[147]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP43:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[148]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP45:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[43]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP46:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[149]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP47:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[150]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP48:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[151]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP49:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[154]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP50:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[155]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP51:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[157]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP52:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[159]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP53:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[160]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP54:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[161]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP55:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[162]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP56:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[139]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP57:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[140]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP62:
|
||||
new_state = PanasonicDecode::getByteMinus1Times10(data[173]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP63:
|
||||
new_state = PanasonicDecode::getByteMinus1Times10(data[174]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP64:
|
||||
new_state = PanasonicDecode::getByteMinus1Div5(data[163]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP65:
|
||||
new_state = PanasonicDecode::getByteMinus1Times50(data[171]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP66:
|
||||
new_state = PanasonicDecode::getByteMinus1Times50(data[164]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP67:
|
||||
new_state = PanasonicDecode::getByteMinus1Div5(data[165]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP70:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[100]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP71:
|
||||
new_state = PanasonicDecode::getByteMinus1(data[101]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP72:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[86]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP73:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[87]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP74:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[89]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP75:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[88]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP77:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[83]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP78:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[85]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP79:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[95]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP80:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[96]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP82:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[79]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP83:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[80]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP84:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[82]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP85:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[81]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP86:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[90]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP87:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[91]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP88:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[93]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP89:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[92]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP90:
|
||||
new_state = PanasonicDecode::getWordMinus1(data, 185);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP91:
|
||||
new_state = PanasonicDecode::getWordMinus1(data, 188);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP93:
|
||||
new_state = PanasonicDecode::getByteMinus1(data[172]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP95:
|
||||
new_state = PanasonicDecode::getByteMinus1(data[45]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP96:
|
||||
new_state = PanasonicDecode::getByteMinus1(data[104]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP97:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[105]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP98:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[106]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP102:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[61]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP103:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[62]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP104:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[63]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP105:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[64]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP113:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[59]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP115:
|
||||
new_state = PanasonicDecode::getByteMinus1Div50(data[125]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP116:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[126]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP117:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[127]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP118:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[128]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP127:
|
||||
new_state = PanasonicDecode::getByteMinus1Div2(data[177]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP128:
|
||||
new_state = PanasonicDecode::getByteMinus1Div2(data[178]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP131:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[65]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP134:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[66]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP135:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[68]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP136:
|
||||
new_state = PanasonicDecode::getByteMinus1(data[67]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP137:
|
||||
new_state = PanasonicDecode::getByteMinus1(data[69]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP138:
|
||||
new_state = PanasonicDecode::getByteMinus1(data[70]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
|
||||
float new_state;
|
||||
switch (this->id_)
|
||||
{
|
||||
case SensorIds::CONF_TOP1:
|
||||
new_state = PanasonicDecode::getPumpFlow(data, 169);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP5:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[143]) + PanasonicDecode::getFractional(data[118], 0);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP6:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[144]) + PanasonicDecode::getFractional(data[118], 3);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP7:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[153]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP8:
|
||||
new_state = PanasonicDecode::getByteMinus1(data[166]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP9:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[42]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP10:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[141]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP11:
|
||||
new_state = PanasonicDecode::getWordMinus1(data, 182);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP12:
|
||||
new_state = PanasonicDecode::getWordMinus1(data, 179);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP14:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[142]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP15:
|
||||
new_state = PanasonicDecode::getByteMinus1Times200(data[194]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP16:
|
||||
new_state = PanasonicDecode::getByteMinus1Times200(data[193]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP21:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[158]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP22:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[99]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP23:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[84]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP24:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[94]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP25:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[44]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP27:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[38]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP28:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[39]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP29:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[75]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP30:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[76]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP31:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[78]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP32:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[77]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP33:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[156]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP34:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[40]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP35:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[41]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP36:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[145]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP37:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[146]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP38:
|
||||
new_state = PanasonicDecode::getByteMinus1Times200(data[196]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP39:
|
||||
new_state = PanasonicDecode::getByteMinus1Times200(data[195]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP40:
|
||||
new_state = PanasonicDecode::getByteMinus1Times200(data[198]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP41:
|
||||
new_state = PanasonicDecode::getByteMinus1Times200(data[197]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP42:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[147]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP43:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[148]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP45:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[43]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP46:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[149]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP47:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[150]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP48:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[151]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP49:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[154]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP50:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[155]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP51:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[157]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP52:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[159]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP53:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[160]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP54:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[161]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP55:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[162]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP56:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[139]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP57:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[140]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP62:
|
||||
new_state = PanasonicDecode::getByteMinus1Times10(data[173]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP63:
|
||||
new_state = PanasonicDecode::getByteMinus1Times10(data[174]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP64:
|
||||
new_state = PanasonicDecode::getByteMinus1Div5(data[163]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP65:
|
||||
new_state = PanasonicDecode::getByteMinus1Times50(data[171]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP66:
|
||||
new_state = PanasonicDecode::getByteMinus1Times50(data[164]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP67:
|
||||
new_state = PanasonicDecode::getByteMinus1Div5(data[165]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP70:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[100]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP71:
|
||||
new_state = PanasonicDecode::getByteMinus1(data[101]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP72:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[86]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP73:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[87]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP74:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[89]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP75:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[88]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP77:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[83]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP78:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[85]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP79:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[95]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP80:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[96]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP82:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[79]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP83:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[80]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP84:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[82]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP85:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[81]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP86:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[90]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP87:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[91]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP88:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[93]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP89:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[92]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP90:
|
||||
new_state = PanasonicDecode::getWordMinus1(data, 185);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP91:
|
||||
new_state = PanasonicDecode::getWordMinus1(data, 188);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP93:
|
||||
new_state = PanasonicDecode::getByteMinus1(data[172]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP95:
|
||||
new_state = PanasonicDecode::getByteMinus1(data[45]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP96:
|
||||
new_state = PanasonicDecode::getByteMinus1(data[104]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP97:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[105]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP98:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[106]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP102:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[61]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP103:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[62]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP104:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[63]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP105:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[64]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP113:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[59]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP115:
|
||||
new_state = PanasonicDecode::getByteMinus1Div50(data[125]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP116:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[126]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP117:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[127]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP118:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[128]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP127:
|
||||
new_state = PanasonicDecode::getByteMinus1Div2(data[177]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP128:
|
||||
new_state = PanasonicDecode::getByteMinus1Div2(data[178]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP131:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[65]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP134:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[66]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP135:
|
||||
new_state = PanasonicDecode::getByteMinus128(data[68]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP136:
|
||||
new_state = PanasonicDecode::getByteMinus1(data[67]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP137:
|
||||
new_state = PanasonicDecode::getByteMinus1(data[69]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_TOP138:
|
||||
new_state = PanasonicDecode::getByteMinus1(data[70]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_XTOP0:
|
||||
new_state = PanasonicDecode::getWordMinus1(data, 14);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_XTOP1:
|
||||
new_state = PanasonicDecode::getWordMinus1(data, 16);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_XTOP2:
|
||||
new_state = PanasonicDecode::getWordMinus1(data, 18);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_XTOP3:
|
||||
new_state = PanasonicDecode::getWordMinus1(data, 20);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_XTOP4:
|
||||
new_state = PanasonicDecode::getWordMinus1(data, 22);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case SensorIds::CONF_XTOP5:
|
||||
new_state = PanasonicDecode::getWordMinus1(data, 24);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
};
|
||||
|
||||
case SensorIds::CONF_XTOP0:
|
||||
new_state = PanasonicDecode::getWordMinus1(data, 14);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_XTOP1:
|
||||
new_state = PanasonicDecode::getWordMinus1(data, 16);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_XTOP2:
|
||||
new_state = PanasonicDecode::getWordMinus1(data, 18);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_XTOP3:
|
||||
new_state = PanasonicDecode::getWordMinus1(data, 20);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_XTOP4:
|
||||
new_state = PanasonicDecode::getWordMinus1(data, 22);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case SensorIds::CONF_XTOP5:
|
||||
new_state = PanasonicDecode::getWordMinus1(data, 24);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
default: return;
|
||||
};
|
||||
|
||||
this->publish_state(new_state);
|
||||
}
|
||||
} // namespace panasonic_heatpump
|
||||
} // namespace esphome
|
||||
this->publish_state(new_state);
|
||||
}
|
||||
} // namespace panasonic_heatpump
|
||||
} // namespace esphome
|
||||
|
|
|
|||
|
|
@ -4,124 +4,121 @@
|
|||
#include "../panasonic_heatpump.h"
|
||||
#include "../decode.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace panasonic_heatpump {
|
||||
enum SensorIds : uint8_t {
|
||||
CONF_TOP1,
|
||||
CONF_TOP5,
|
||||
CONF_TOP6,
|
||||
CONF_TOP7,
|
||||
CONF_TOP8,
|
||||
CONF_TOP9,
|
||||
CONF_TOP10,
|
||||
CONF_TOP11,
|
||||
CONF_TOP12,
|
||||
CONF_TOP14,
|
||||
CONF_TOP15,
|
||||
CONF_TOP16,
|
||||
CONF_TOP21,
|
||||
CONF_TOP22,
|
||||
CONF_TOP23,
|
||||
CONF_TOP24,
|
||||
CONF_TOP25,
|
||||
CONF_TOP27,
|
||||
CONF_TOP28,
|
||||
CONF_TOP29,
|
||||
CONF_TOP30,
|
||||
CONF_TOP31,
|
||||
CONF_TOP32,
|
||||
CONF_TOP33,
|
||||
CONF_TOP34,
|
||||
CONF_TOP35,
|
||||
CONF_TOP36,
|
||||
CONF_TOP37,
|
||||
CONF_TOP38,
|
||||
CONF_TOP39,
|
||||
CONF_TOP40,
|
||||
CONF_TOP41,
|
||||
CONF_TOP42,
|
||||
CONF_TOP43,
|
||||
CONF_TOP45,
|
||||
CONF_TOP46,
|
||||
CONF_TOP47,
|
||||
CONF_TOP48,
|
||||
CONF_TOP49,
|
||||
CONF_TOP50,
|
||||
CONF_TOP51,
|
||||
CONF_TOP52,
|
||||
CONF_TOP53,
|
||||
CONF_TOP54,
|
||||
CONF_TOP55,
|
||||
CONF_TOP56,
|
||||
CONF_TOP57,
|
||||
CONF_TOP62,
|
||||
CONF_TOP63,
|
||||
CONF_TOP64,
|
||||
CONF_TOP65,
|
||||
CONF_TOP66,
|
||||
CONF_TOP67,
|
||||
CONF_TOP70,
|
||||
CONF_TOP71,
|
||||
CONF_TOP72,
|
||||
CONF_TOP73,
|
||||
CONF_TOP74,
|
||||
CONF_TOP75,
|
||||
CONF_TOP77,
|
||||
CONF_TOP78,
|
||||
CONF_TOP79,
|
||||
CONF_TOP80,
|
||||
CONF_TOP82,
|
||||
CONF_TOP83,
|
||||
CONF_TOP84,
|
||||
CONF_TOP85,
|
||||
CONF_TOP86,
|
||||
CONF_TOP87,
|
||||
CONF_TOP88,
|
||||
CONF_TOP89,
|
||||
CONF_TOP90,
|
||||
CONF_TOP91,
|
||||
CONF_TOP93,
|
||||
CONF_TOP95,
|
||||
CONF_TOP96,
|
||||
CONF_TOP97,
|
||||
CONF_TOP98,
|
||||
CONF_TOP102,
|
||||
CONF_TOP103,
|
||||
CONF_TOP104,
|
||||
CONF_TOP105,
|
||||
CONF_TOP113,
|
||||
CONF_TOP115,
|
||||
CONF_TOP116,
|
||||
CONF_TOP117,
|
||||
CONF_TOP118,
|
||||
CONF_TOP127,
|
||||
CONF_TOP128,
|
||||
CONF_TOP131,
|
||||
CONF_TOP134,
|
||||
CONF_TOP135,
|
||||
CONF_TOP136,
|
||||
CONF_TOP137,
|
||||
CONF_TOP138,
|
||||
|
||||
namespace esphome
|
||||
{
|
||||
namespace panasonic_heatpump
|
||||
{
|
||||
enum SensorIds : uint8_t
|
||||
{
|
||||
CONF_TOP1,
|
||||
CONF_TOP5,
|
||||
CONF_TOP6,
|
||||
CONF_TOP7,
|
||||
CONF_TOP8,
|
||||
CONF_TOP9,
|
||||
CONF_TOP10,
|
||||
CONF_TOP11,
|
||||
CONF_TOP12,
|
||||
CONF_TOP14,
|
||||
CONF_TOP15,
|
||||
CONF_TOP16,
|
||||
CONF_TOP21,
|
||||
CONF_TOP22,
|
||||
CONF_TOP23,
|
||||
CONF_TOP24,
|
||||
CONF_TOP25,
|
||||
CONF_TOP27,
|
||||
CONF_TOP28,
|
||||
CONF_TOP29,
|
||||
CONF_TOP30,
|
||||
CONF_TOP31,
|
||||
CONF_TOP32,
|
||||
CONF_TOP33,
|
||||
CONF_TOP34,
|
||||
CONF_TOP35,
|
||||
CONF_TOP36,
|
||||
CONF_TOP37,
|
||||
CONF_TOP38,
|
||||
CONF_TOP39,
|
||||
CONF_TOP40,
|
||||
CONF_TOP41,
|
||||
CONF_TOP42,
|
||||
CONF_TOP43,
|
||||
CONF_TOP45,
|
||||
CONF_TOP46,
|
||||
CONF_TOP47,
|
||||
CONF_TOP48,
|
||||
CONF_TOP49,
|
||||
CONF_TOP50,
|
||||
CONF_TOP51,
|
||||
CONF_TOP52,
|
||||
CONF_TOP53,
|
||||
CONF_TOP54,
|
||||
CONF_TOP55,
|
||||
CONF_TOP56,
|
||||
CONF_TOP57,
|
||||
CONF_TOP62,
|
||||
CONF_TOP63,
|
||||
CONF_TOP64,
|
||||
CONF_TOP65,
|
||||
CONF_TOP66,
|
||||
CONF_TOP67,
|
||||
CONF_TOP70,
|
||||
CONF_TOP71,
|
||||
CONF_TOP72,
|
||||
CONF_TOP73,
|
||||
CONF_TOP74,
|
||||
CONF_TOP75,
|
||||
CONF_TOP77,
|
||||
CONF_TOP78,
|
||||
CONF_TOP79,
|
||||
CONF_TOP80,
|
||||
CONF_TOP82,
|
||||
CONF_TOP83,
|
||||
CONF_TOP84,
|
||||
CONF_TOP85,
|
||||
CONF_TOP86,
|
||||
CONF_TOP87,
|
||||
CONF_TOP88,
|
||||
CONF_TOP89,
|
||||
CONF_TOP90,
|
||||
CONF_TOP91,
|
||||
CONF_TOP93,
|
||||
CONF_TOP95,
|
||||
CONF_TOP96,
|
||||
CONF_TOP97,
|
||||
CONF_TOP98,
|
||||
CONF_TOP102,
|
||||
CONF_TOP103,
|
||||
CONF_TOP104,
|
||||
CONF_TOP105,
|
||||
CONF_TOP113,
|
||||
CONF_TOP115,
|
||||
CONF_TOP116,
|
||||
CONF_TOP117,
|
||||
CONF_TOP118,
|
||||
CONF_TOP127,
|
||||
CONF_TOP128,
|
||||
CONF_TOP131,
|
||||
CONF_TOP134,
|
||||
CONF_TOP135,
|
||||
CONF_TOP136,
|
||||
CONF_TOP137,
|
||||
CONF_TOP138,
|
||||
CONF_XTOP0,
|
||||
CONF_XTOP1,
|
||||
CONF_XTOP2,
|
||||
CONF_XTOP3,
|
||||
CONF_XTOP4,
|
||||
CONF_XTOP5,
|
||||
};
|
||||
|
||||
CONF_XTOP0,
|
||||
CONF_XTOP1,
|
||||
CONF_XTOP2,
|
||||
CONF_XTOP3,
|
||||
CONF_XTOP4,
|
||||
CONF_XTOP5,
|
||||
};
|
||||
|
||||
class PanasonicHeatpumpSensor : public sensor::Sensor, public Component,
|
||||
public Parented<PanasonicHeatpumpComponent>, public PanasonicHeatpumpEntity
|
||||
{
|
||||
public:
|
||||
PanasonicHeatpumpSensor() = default;
|
||||
void dump_config() override;
|
||||
void publish_new_state(const std::vector<uint8_t>& data) override;
|
||||
};
|
||||
} // namespace panasonic_heatpump
|
||||
} // namespace esphome
|
||||
class PanasonicHeatpumpSensor : public sensor::Sensor,
|
||||
public Component,
|
||||
public Parented<PanasonicHeatpumpComponent>,
|
||||
public PanasonicHeatpumpEntity {
|
||||
public:
|
||||
PanasonicHeatpumpSensor() = default;
|
||||
void dump_config() override;
|
||||
void publish_new_state(const std::vector<uint8_t>& data) override;
|
||||
};
|
||||
} // namespace panasonic_heatpump
|
||||
} // namespace esphome
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import switch
|
||||
from esphome.const import (
|
||||
ENTITY_CATEGORY_CONFIG,
|
||||
from .. import (
|
||||
CONF_PANASONIC_HEATPUMP_ID,
|
||||
PanasonicHeatpumpComponent,
|
||||
panasonic_heatpump_ns,
|
||||
)
|
||||
from .. import CONF_PANASONIC_HEATPUMP_ID, PanasonicHeatpumpComponent, panasonic_heatpump_ns
|
||||
|
||||
CONF_SET1 = "set1" # Set Heatpump
|
||||
CONF_SET10 = "set10" # Set Force DHW
|
||||
|
|
@ -21,77 +22,79 @@ CONF_SET33 = "set33" # Set External Heat Cool Control
|
|||
CONF_SET34 = "set34" # Set Bivalent Control
|
||||
|
||||
TYPES = [
|
||||
CONF_SET1,
|
||||
CONF_SET10,
|
||||
CONF_SET12,
|
||||
CONF_SET13,
|
||||
CONF_SET14,
|
||||
CONF_SET24,
|
||||
CONF_SET25,
|
||||
CONF_SET28,
|
||||
CONF_SET30,
|
||||
CONF_SET31,
|
||||
CONF_SET32,
|
||||
CONF_SET33,
|
||||
CONF_SET34,
|
||||
CONF_SET1,
|
||||
CONF_SET10,
|
||||
CONF_SET12,
|
||||
CONF_SET13,
|
||||
CONF_SET14,
|
||||
CONF_SET24,
|
||||
CONF_SET25,
|
||||
CONF_SET28,
|
||||
CONF_SET30,
|
||||
CONF_SET31,
|
||||
CONF_SET32,
|
||||
CONF_SET33,
|
||||
CONF_SET34,
|
||||
]
|
||||
|
||||
PanasonicHeatpumpSwitch = panasonic_heatpump_ns.class_("PanasonicHeatpumpSwitch", switch.Switch, cg.Component)
|
||||
PanasonicHeatpumpSwitch = panasonic_heatpump_ns.class_(
|
||||
"PanasonicHeatpumpSwitch", switch.Switch, cg.Component
|
||||
)
|
||||
|
||||
CONFIG_SCHEMA = cv.Schema(
|
||||
{
|
||||
cv.GenerateID(CONF_PANASONIC_HEATPUMP_ID): cv.use_id(
|
||||
PanasonicHeatpumpComponent
|
||||
),
|
||||
|
||||
cv.Optional(CONF_SET1): switch.switch_schema(
|
||||
PanasonicHeatpumpSwitch,
|
||||
),
|
||||
cv.Optional(CONF_SET10): switch.switch_schema(
|
||||
PanasonicHeatpumpSwitch,
|
||||
),
|
||||
cv.Optional(CONF_SET12): switch.switch_schema(
|
||||
PanasonicHeatpumpSwitch,
|
||||
),
|
||||
cv.Optional(CONF_SET13): switch.switch_schema(
|
||||
PanasonicHeatpumpSwitch,
|
||||
),
|
||||
cv.Optional(CONF_SET14): switch.switch_schema(
|
||||
PanasonicHeatpumpSwitch,
|
||||
),
|
||||
cv.Optional(CONF_SET24): switch.switch_schema(
|
||||
PanasonicHeatpumpSwitch,
|
||||
),
|
||||
cv.Optional(CONF_SET25): switch.switch_schema(
|
||||
PanasonicHeatpumpSwitch,
|
||||
),
|
||||
cv.Optional(CONF_SET28): switch.switch_schema(
|
||||
PanasonicHeatpumpSwitch,
|
||||
),
|
||||
cv.Optional(CONF_SET30): switch.switch_schema(
|
||||
PanasonicHeatpumpSwitch,
|
||||
),
|
||||
cv.Optional(CONF_SET31): switch.switch_schema(
|
||||
PanasonicHeatpumpSwitch,
|
||||
),
|
||||
cv.Optional(CONF_SET32): switch.switch_schema(
|
||||
PanasonicHeatpumpSwitch,
|
||||
),
|
||||
cv.Optional(CONF_SET33): switch.switch_schema(
|
||||
PanasonicHeatpumpSwitch,
|
||||
),
|
||||
cv.Optional(CONF_SET34): switch.switch_schema(
|
||||
PanasonicHeatpumpSwitch,
|
||||
),
|
||||
}
|
||||
{
|
||||
cv.GenerateID(CONF_PANASONIC_HEATPUMP_ID): cv.use_id(
|
||||
PanasonicHeatpumpComponent
|
||||
),
|
||||
cv.Optional(CONF_SET1): switch.switch_schema(
|
||||
PanasonicHeatpumpSwitch,
|
||||
),
|
||||
cv.Optional(CONF_SET10): switch.switch_schema(
|
||||
PanasonicHeatpumpSwitch,
|
||||
),
|
||||
cv.Optional(CONF_SET12): switch.switch_schema(
|
||||
PanasonicHeatpumpSwitch,
|
||||
),
|
||||
cv.Optional(CONF_SET13): switch.switch_schema(
|
||||
PanasonicHeatpumpSwitch,
|
||||
),
|
||||
cv.Optional(CONF_SET14): switch.switch_schema(
|
||||
PanasonicHeatpumpSwitch,
|
||||
),
|
||||
cv.Optional(CONF_SET24): switch.switch_schema(
|
||||
PanasonicHeatpumpSwitch,
|
||||
),
|
||||
cv.Optional(CONF_SET25): switch.switch_schema(
|
||||
PanasonicHeatpumpSwitch,
|
||||
),
|
||||
cv.Optional(CONF_SET28): switch.switch_schema(
|
||||
PanasonicHeatpumpSwitch,
|
||||
),
|
||||
cv.Optional(CONF_SET30): switch.switch_schema(
|
||||
PanasonicHeatpumpSwitch,
|
||||
),
|
||||
cv.Optional(CONF_SET31): switch.switch_schema(
|
||||
PanasonicHeatpumpSwitch,
|
||||
),
|
||||
cv.Optional(CONF_SET32): switch.switch_schema(
|
||||
PanasonicHeatpumpSwitch,
|
||||
),
|
||||
cv.Optional(CONF_SET33): switch.switch_schema(
|
||||
PanasonicHeatpumpSwitch,
|
||||
),
|
||||
cv.Optional(CONF_SET34): switch.switch_schema(
|
||||
PanasonicHeatpumpSwitch,
|
||||
),
|
||||
}
|
||||
).extend(cv.COMPONENT_SCHEMA)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
parent = await cg.get_variable(config[CONF_PANASONIC_HEATPUMP_ID])
|
||||
for index, key in enumerate(TYPES):
|
||||
if child_config := config.get(key):
|
||||
var = await switch.new_switch(child_config)
|
||||
await cg.register_component(var, child_config)
|
||||
cg.add(var.set_parent(parent))
|
||||
cg.add(var.set_id(index))
|
||||
cg.add(parent.add_switch(var))
|
||||
parent = await cg.get_variable(config[CONF_PANASONIC_HEATPUMP_ID])
|
||||
for index, key in enumerate(TYPES):
|
||||
if child_config := config.get(key):
|
||||
var = await switch.new_switch(child_config)
|
||||
await cg.register_component(var, child_config)
|
||||
cg.add(var.set_parent(parent))
|
||||
cg.add(var.set_id(index))
|
||||
cg.add(parent.add_switch(var))
|
||||
|
|
|
|||
|
|
@ -1,134 +1,140 @@
|
|||
#include "panasonic_heatpump_switch.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace panasonic_heatpump {
|
||||
static const char* const TAG = "panasonic_heatpump.switch";
|
||||
|
||||
namespace esphome
|
||||
{
|
||||
namespace panasonic_heatpump
|
||||
{
|
||||
static const char *const TAG = "panasonic_heatpump.switch";
|
||||
void PanasonicHeatpumpSwitch::dump_config() {
|
||||
LOG_SWITCH("", "Panasonic Heatpump Switch", this);
|
||||
delay(10);
|
||||
}
|
||||
|
||||
void PanasonicHeatpumpSwitch::dump_config()
|
||||
{
|
||||
LOG_SWITCH("", "Panasonic Heatpump Switch", this);
|
||||
delay(10);
|
||||
}
|
||||
void PanasonicHeatpumpSwitch::write_state(bool state) {
|
||||
size_t value = state ? 1 : 0;
|
||||
|
||||
void PanasonicHeatpumpSwitch::write_state(bool state)
|
||||
{
|
||||
size_t value = state ? 1 : 0;
|
||||
switch (this->id_) {
|
||||
case SwitchIds::CONF_SET1:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus1(value), 4);
|
||||
break;
|
||||
case SwitchIds::CONF_SET10:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus1Multiply64(value), 4);
|
||||
break;
|
||||
case SwitchIds::CONF_SET12:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setMultiply2(value), 8);
|
||||
break;
|
||||
case SwitchIds::CONF_SET13:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setMultiply4(value), 8);
|
||||
break;
|
||||
case SwitchIds::CONF_SET14:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus1Multiply16(value), 4);
|
||||
break;
|
||||
case SwitchIds::CONF_SET24:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus1Multiply64(value), 5);
|
||||
break;
|
||||
case SwitchIds::CONF_SET25:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus1Multiply16(value), 20);
|
||||
break;
|
||||
case SwitchIds::CONF_SET28:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus1Multiply4(value), 24);
|
||||
break;
|
||||
case SwitchIds::CONF_SET30:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus1(value), 23);
|
||||
break;
|
||||
case SwitchIds::CONF_SET31:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus1Multiply16(value), 23);
|
||||
break;
|
||||
case SwitchIds::CONF_SET32:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus1Multiply64(value), 23);
|
||||
break;
|
||||
case SwitchIds::CONF_SET33:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus1Multiply4(value), 23);
|
||||
break;
|
||||
case SwitchIds::CONF_SET34:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus1(value), 26);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
};
|
||||
|
||||
switch (this->id_)
|
||||
{
|
||||
case SwitchIds::CONF_SET1:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus1(value), 4);
|
||||
break;
|
||||
case SwitchIds::CONF_SET10:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus1Multiply64(value), 4);
|
||||
break;
|
||||
case SwitchIds::CONF_SET12:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setMultiply2(value), 8);
|
||||
break;
|
||||
case SwitchIds::CONF_SET13:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setMultiply4(value), 8);
|
||||
break;
|
||||
case SwitchIds::CONF_SET14:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus1Multiply16(value), 4);
|
||||
break;
|
||||
case SwitchIds::CONF_SET24:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus1Multiply64(value), 5);
|
||||
break;
|
||||
case SwitchIds::CONF_SET25:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus1Multiply16(value), 20);
|
||||
break;
|
||||
case SwitchIds::CONF_SET28:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus1Multiply4(value), 24);
|
||||
break;
|
||||
case SwitchIds::CONF_SET30:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus1(value), 23);
|
||||
break;
|
||||
case SwitchIds::CONF_SET31:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus1Multiply16(value), 23);
|
||||
break;
|
||||
case SwitchIds::CONF_SET32:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus1Multiply64(value), 23);
|
||||
break;
|
||||
case SwitchIds::CONF_SET33:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus1Multiply4(value), 23);
|
||||
break;
|
||||
case SwitchIds::CONF_SET34:
|
||||
this->parent_->set_command_byte(PanasonicCommand::setPlus1(value), 26);
|
||||
break;
|
||||
default: return;
|
||||
};
|
||||
this->publish_state(state);
|
||||
this->keep_state_ = 2;
|
||||
}
|
||||
|
||||
this->publish_state(state);
|
||||
this->keep_state_ = 2;
|
||||
}
|
||||
void PanasonicHeatpumpSwitch::publish_new_state(const std::vector<uint8_t>& data) {
|
||||
if (this->keep_state_ > 0) {
|
||||
this->keep_state_--;
|
||||
return;
|
||||
}
|
||||
if (data.empty())
|
||||
return;
|
||||
|
||||
void PanasonicHeatpumpSwitch::publish_new_state(const std::vector<uint8_t>& data)
|
||||
{
|
||||
if (this->keep_state_ > 0)
|
||||
{
|
||||
this->keep_state_--;
|
||||
return;
|
||||
}
|
||||
if (data.empty()) return;
|
||||
bool new_state;
|
||||
switch (this->id_) {
|
||||
case SwitchIds::CONF_SET1:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit7and8(data[4]));
|
||||
if (this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case SwitchIds::CONF_SET10:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit1and2(data[4]));
|
||||
if (this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case SwitchIds::CONF_SET24:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit1and2(data[5]));
|
||||
if (this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case SwitchIds::CONF_SET12:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit5and6(data[111]));
|
||||
if (this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case SwitchIds::CONF_SET13:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit5and6(data[117]));
|
||||
if (this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case SwitchIds::CONF_SET28:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit5and6(data[24]));
|
||||
if (this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case SwitchIds::CONF_SET25:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit3and4(data[20]));
|
||||
if (this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case SwitchIds::CONF_SET30:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit7and8(data[23]));
|
||||
if (this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case SwitchIds::CONF_SET33:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit5and6(data[23]));
|
||||
if (this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case SwitchIds::CONF_SET31:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit3and4(data[23]));
|
||||
if (this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case SwitchIds::CONF_SET32:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit1and2(data[23]));
|
||||
if (this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
case SwitchIds::CONF_SET34:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit7and8(data[26]));
|
||||
if (this->state == new_state)
|
||||
return;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
};
|
||||
|
||||
bool new_state;
|
||||
switch (this->id_)
|
||||
{
|
||||
case SwitchIds::CONF_SET1:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit7and8(data[4]));
|
||||
if (this->state == new_state) return;
|
||||
break;
|
||||
case SwitchIds::CONF_SET10:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit1and2(data[4]));
|
||||
if (this->state == new_state) return;
|
||||
break;
|
||||
case SwitchIds::CONF_SET24:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit1and2(data[5]));
|
||||
if (this->state == new_state) return;
|
||||
break;
|
||||
case SwitchIds::CONF_SET12:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit5and6(data[111]));
|
||||
if (this->state == new_state) return;
|
||||
break;
|
||||
case SwitchIds::CONF_SET13:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit5and6(data[117]));
|
||||
if (this->state == new_state) return;
|
||||
break;
|
||||
case SwitchIds::CONF_SET28:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit5and6(data[24]));
|
||||
if (this->state == new_state) return;
|
||||
break;
|
||||
case SwitchIds::CONF_SET25:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit3and4(data[20]));
|
||||
if (this->state == new_state) return;
|
||||
break;
|
||||
case SwitchIds::CONF_SET30:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit7and8(data[23]));
|
||||
if (this->state == new_state) return;
|
||||
break;
|
||||
case SwitchIds::CONF_SET33:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit5and6(data[23]));
|
||||
if (this->state == new_state) return;
|
||||
break;
|
||||
case SwitchIds::CONF_SET31:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit3and4(data[23]));
|
||||
if (this->state == new_state) return;
|
||||
break;
|
||||
case SwitchIds::CONF_SET32:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit1and2(data[23]));
|
||||
if (this->state == new_state) return;
|
||||
break;
|
||||
case SwitchIds::CONF_SET34:
|
||||
new_state = PanasonicDecode::getBinaryState(PanasonicDecode::getBit7and8(data[26]));
|
||||
if (this->state == new_state) return;
|
||||
break;
|
||||
default: return;
|
||||
};
|
||||
|
||||
this->publish_state(new_state);
|
||||
}
|
||||
} // namespace panasonic_heatpump
|
||||
} // namespace esphome
|
||||
this->publish_state(new_state);
|
||||
}
|
||||
} // namespace panasonic_heatpump
|
||||
} // namespace esphome
|
||||
|
|
|
|||
|
|
@ -5,38 +5,35 @@
|
|||
#include "../decode.h"
|
||||
#include "../commands.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace panasonic_heatpump {
|
||||
enum SwitchIds : uint8_t {
|
||||
CONF_SET1,
|
||||
CONF_SET10,
|
||||
CONF_SET12,
|
||||
CONF_SET13,
|
||||
CONF_SET14,
|
||||
CONF_SET24,
|
||||
CONF_SET25,
|
||||
CONF_SET28,
|
||||
CONF_SET30,
|
||||
CONF_SET31,
|
||||
CONF_SET32,
|
||||
CONF_SET33,
|
||||
CONF_SET34,
|
||||
};
|
||||
|
||||
namespace esphome
|
||||
{
|
||||
namespace panasonic_heatpump
|
||||
{
|
||||
enum SwitchIds : uint8_t
|
||||
{
|
||||
CONF_SET1,
|
||||
CONF_SET10,
|
||||
CONF_SET12,
|
||||
CONF_SET13,
|
||||
CONF_SET14,
|
||||
CONF_SET24,
|
||||
CONF_SET25,
|
||||
CONF_SET28,
|
||||
CONF_SET30,
|
||||
CONF_SET31,
|
||||
CONF_SET32,
|
||||
CONF_SET33,
|
||||
CONF_SET34,
|
||||
};
|
||||
class PanasonicHeatpumpSwitch : public switch_::Switch,
|
||||
public Component,
|
||||
public Parented<PanasonicHeatpumpComponent>,
|
||||
public PanasonicHeatpumpEntity {
|
||||
public:
|
||||
PanasonicHeatpumpSwitch() = default;
|
||||
void dump_config() override;
|
||||
void publish_new_state(const std::vector<uint8_t>& data) override;
|
||||
|
||||
class PanasonicHeatpumpSwitch : public switch_::Switch, public Component,
|
||||
public Parented<PanasonicHeatpumpComponent>, public PanasonicHeatpumpEntity
|
||||
{
|
||||
public:
|
||||
PanasonicHeatpumpSwitch() = default;
|
||||
void dump_config() override;
|
||||
void publish_new_state(const std::vector<uint8_t>& data) override;
|
||||
|
||||
protected:
|
||||
void write_state(bool state) override;
|
||||
};
|
||||
} // namespace panasonic_heatpump
|
||||
} // namespace esphome
|
||||
protected:
|
||||
void write_state(bool state) override;
|
||||
};
|
||||
} // namespace panasonic_heatpump
|
||||
} // namespace esphome
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import text_sensor
|
||||
from esphome.const import (
|
||||
DEVICE_CLASS_HEAT,
|
||||
from .. import (
|
||||
CONF_PANASONIC_HEATPUMP_ID,
|
||||
PanasonicHeatpumpComponent,
|
||||
panasonic_heatpump_ns,
|
||||
)
|
||||
from .. import CONF_PANASONIC_HEATPUMP_ID, PanasonicHeatpumpComponent, panasonic_heatpump_ns
|
||||
|
||||
|
||||
ICON_OPERATION_MODE = "mdi:thermostat"
|
||||
ICON_POWERFUL_MODE = "mdi:arm-flex"
|
||||
|
|
@ -23,7 +23,6 @@ ICON_VALVE = "mdi:pipe-valve"
|
|||
ICON_PUMP = "mdi:pump"
|
||||
ICON_EXTERNAL_PAD_HEATER = "mdi:radiator"
|
||||
|
||||
|
||||
CONF_TOP4 = "top4" # Operation Mode
|
||||
# ToDo: Split up top4 into top4_1 (Heating Mode State) and top4_2 (DHW Mode State)
|
||||
CONF_TOP17 = "top17" # Powerful Mode Time
|
||||
|
|
@ -48,126 +47,129 @@ CONF_TOP126 = "top126" # ThreeWay Valve State2
|
|||
CONF_TOP130 = "top130" # Bivalent Mode
|
||||
|
||||
TYPES = [
|
||||
CONF_TOP4,
|
||||
CONF_TOP17,
|
||||
CONF_TOP18,
|
||||
CONF_TOP19,
|
||||
CONF_TOP20,
|
||||
CONF_TOP44,
|
||||
CONF_TOP58,
|
||||
CONF_TOP59,
|
||||
CONF_TOP76,
|
||||
CONF_TOP81,
|
||||
CONF_TOP92,
|
||||
CONF_TOP94,
|
||||
CONF_TOP101,
|
||||
CONF_TOP106,
|
||||
CONF_TOP107,
|
||||
CONF_TOP111,
|
||||
CONF_TOP112,
|
||||
CONF_TOP114,
|
||||
CONF_TOP125,
|
||||
CONF_TOP126,
|
||||
CONF_TOP130,
|
||||
CONF_TOP4,
|
||||
CONF_TOP17,
|
||||
CONF_TOP18,
|
||||
CONF_TOP19,
|
||||
CONF_TOP20,
|
||||
CONF_TOP44,
|
||||
CONF_TOP58,
|
||||
CONF_TOP59,
|
||||
CONF_TOP76,
|
||||
CONF_TOP81,
|
||||
CONF_TOP92,
|
||||
CONF_TOP94,
|
||||
CONF_TOP101,
|
||||
CONF_TOP106,
|
||||
CONF_TOP107,
|
||||
CONF_TOP111,
|
||||
CONF_TOP112,
|
||||
CONF_TOP114,
|
||||
CONF_TOP125,
|
||||
CONF_TOP126,
|
||||
CONF_TOP130,
|
||||
]
|
||||
|
||||
PanasonicHeatpumpTextSensor = panasonic_heatpump_ns.class_("PanasonicHeatpumpTextSensor", text_sensor.TextSensor, cg.Component)
|
||||
PanasonicHeatpumpTextSensor = panasonic_heatpump_ns.class_(
|
||||
"PanasonicHeatpumpTextSensor", text_sensor.TextSensor, cg.Component
|
||||
)
|
||||
|
||||
CONFIG_SCHEMA = cv.Schema(
|
||||
{
|
||||
cv.GenerateID(CONF_PANASONIC_HEATPUMP_ID): cv.use_id(
|
||||
PanasonicHeatpumpComponent
|
||||
),
|
||||
|
||||
cv.Optional(CONF_TOP4): text_sensor.text_sensor_schema(
|
||||
PanasonicHeatpumpTextSensor,
|
||||
icon=ICON_OPERATION_MODE,
|
||||
),
|
||||
cv.Optional(CONF_TOP17): text_sensor.text_sensor_schema(
|
||||
PanasonicHeatpumpTextSensor,
|
||||
icon=ICON_POWERFUL_MODE,
|
||||
),
|
||||
cv.Optional(CONF_TOP18): text_sensor.text_sensor_schema(
|
||||
PanasonicHeatpumpTextSensor,
|
||||
icon=ICON_QUIET_MODE,
|
||||
),
|
||||
cv.Optional(CONF_TOP19): text_sensor.text_sensor_schema(
|
||||
PanasonicHeatpumpTextSensor,
|
||||
icon=ICON_HOLIDAY_MODE,
|
||||
),
|
||||
cv.Optional(CONF_TOP20): text_sensor.text_sensor_schema(
|
||||
PanasonicHeatpumpTextSensor,
|
||||
icon=ICON_VALVE,
|
||||
),
|
||||
cv.Optional(CONF_TOP44): text_sensor.text_sensor_schema(
|
||||
PanasonicHeatpumpTextSensor,
|
||||
icon=ICON_ERROR,
|
||||
),
|
||||
cv.Optional(CONF_TOP58): text_sensor.text_sensor_schema(
|
||||
PanasonicHeatpumpTextSensor,
|
||||
icon=ICON_BLOCKED,
|
||||
),
|
||||
cv.Optional(CONF_TOP59): text_sensor.text_sensor_schema(
|
||||
PanasonicHeatpumpTextSensor,
|
||||
icon=ICON_BLOCKED,
|
||||
),
|
||||
cv.Optional(CONF_TOP76): text_sensor.text_sensor_schema(
|
||||
PanasonicHeatpumpTextSensor,
|
||||
icon=ICON_HEATING_MODE,
|
||||
),
|
||||
cv.Optional(CONF_TOP81): text_sensor.text_sensor_schema(
|
||||
PanasonicHeatpumpTextSensor,
|
||||
icon=ICON_COOLING_MODE,
|
||||
),
|
||||
cv.Optional(CONF_TOP92): text_sensor.text_sensor_schema(
|
||||
PanasonicHeatpumpTextSensor,
|
||||
icon=ICON_MODEL,
|
||||
),
|
||||
cv.Optional(CONF_TOP94): text_sensor.text_sensor_schema(
|
||||
PanasonicHeatpumpTextSensor,
|
||||
icon=ICON_ZONE,
|
||||
),
|
||||
cv.Optional(CONF_TOP101): text_sensor.text_sensor_schema(
|
||||
PanasonicHeatpumpTextSensor,
|
||||
icon=ICON_SOLAR_MODE,
|
||||
),
|
||||
cv.Optional(CONF_TOP106): text_sensor.text_sensor_schema(
|
||||
PanasonicHeatpumpTextSensor,
|
||||
icon=ICON_PUMP,
|
||||
),
|
||||
cv.Optional(CONF_TOP107): text_sensor.text_sensor_schema(
|
||||
PanasonicHeatpumpTextSensor,
|
||||
icon=ICON_LIQUID,
|
||||
),
|
||||
cv.Optional(CONF_TOP111): text_sensor.text_sensor_schema(
|
||||
PanasonicHeatpumpTextSensor,
|
||||
),
|
||||
cv.Optional(CONF_TOP112): text_sensor.text_sensor_schema(
|
||||
PanasonicHeatpumpTextSensor,
|
||||
),
|
||||
cv.Optional(CONF_TOP114): text_sensor.text_sensor_schema(
|
||||
PanasonicHeatpumpTextSensor,
|
||||
icon=ICON_EXTERNAL_PAD_HEATER,
|
||||
),
|
||||
cv.Optional(CONF_TOP125): text_sensor.text_sensor_schema(
|
||||
PanasonicHeatpumpTextSensor,
|
||||
icon=ICON_VALVE,
|
||||
),
|
||||
cv.Optional(CONF_TOP126): text_sensor.text_sensor_schema(
|
||||
PanasonicHeatpumpTextSensor,
|
||||
icon=ICON_VALVE,
|
||||
),
|
||||
cv.Optional(CONF_TOP130): text_sensor.text_sensor_schema(
|
||||
PanasonicHeatpumpTextSensor,),
|
||||
}
|
||||
{
|
||||
cv.GenerateID(CONF_PANASONIC_HEATPUMP_ID): cv.use_id(
|
||||
PanasonicHeatpumpComponent
|
||||
),
|
||||
cv.Optional(CONF_TOP4): text_sensor.text_sensor_schema(
|
||||
PanasonicHeatpumpTextSensor,
|
||||
icon=ICON_OPERATION_MODE,
|
||||
),
|
||||
cv.Optional(CONF_TOP17): text_sensor.text_sensor_schema(
|
||||
PanasonicHeatpumpTextSensor,
|
||||
icon=ICON_POWERFUL_MODE,
|
||||
),
|
||||
cv.Optional(CONF_TOP18): text_sensor.text_sensor_schema(
|
||||
PanasonicHeatpumpTextSensor,
|
||||
icon=ICON_QUIET_MODE,
|
||||
),
|
||||
cv.Optional(CONF_TOP19): text_sensor.text_sensor_schema(
|
||||
PanasonicHeatpumpTextSensor,
|
||||
icon=ICON_HOLIDAY_MODE,
|
||||
),
|
||||
cv.Optional(CONF_TOP20): text_sensor.text_sensor_schema(
|
||||
PanasonicHeatpumpTextSensor,
|
||||
icon=ICON_VALVE,
|
||||
),
|
||||
cv.Optional(CONF_TOP44): text_sensor.text_sensor_schema(
|
||||
PanasonicHeatpumpTextSensor,
|
||||
icon=ICON_ERROR,
|
||||
),
|
||||
cv.Optional(CONF_TOP58): text_sensor.text_sensor_schema(
|
||||
PanasonicHeatpumpTextSensor,
|
||||
icon=ICON_BLOCKED,
|
||||
),
|
||||
cv.Optional(CONF_TOP59): text_sensor.text_sensor_schema(
|
||||
PanasonicHeatpumpTextSensor,
|
||||
icon=ICON_BLOCKED,
|
||||
),
|
||||
cv.Optional(CONF_TOP76): text_sensor.text_sensor_schema(
|
||||
PanasonicHeatpumpTextSensor,
|
||||
icon=ICON_HEATING_MODE,
|
||||
),
|
||||
cv.Optional(CONF_TOP81): text_sensor.text_sensor_schema(
|
||||
PanasonicHeatpumpTextSensor,
|
||||
icon=ICON_COOLING_MODE,
|
||||
),
|
||||
cv.Optional(CONF_TOP92): text_sensor.text_sensor_schema(
|
||||
PanasonicHeatpumpTextSensor,
|
||||
icon=ICON_MODEL,
|
||||
),
|
||||
cv.Optional(CONF_TOP94): text_sensor.text_sensor_schema(
|
||||
PanasonicHeatpumpTextSensor,
|
||||
icon=ICON_ZONE,
|
||||
),
|
||||
cv.Optional(CONF_TOP101): text_sensor.text_sensor_schema(
|
||||
PanasonicHeatpumpTextSensor,
|
||||
icon=ICON_SOLAR_MODE,
|
||||
),
|
||||
cv.Optional(CONF_TOP106): text_sensor.text_sensor_schema(
|
||||
PanasonicHeatpumpTextSensor,
|
||||
icon=ICON_PUMP,
|
||||
),
|
||||
cv.Optional(CONF_TOP107): text_sensor.text_sensor_schema(
|
||||
PanasonicHeatpumpTextSensor,
|
||||
icon=ICON_LIQUID,
|
||||
),
|
||||
cv.Optional(CONF_TOP111): text_sensor.text_sensor_schema(
|
||||
PanasonicHeatpumpTextSensor,
|
||||
),
|
||||
cv.Optional(CONF_TOP112): text_sensor.text_sensor_schema(
|
||||
PanasonicHeatpumpTextSensor,
|
||||
),
|
||||
cv.Optional(CONF_TOP114): text_sensor.text_sensor_schema(
|
||||
PanasonicHeatpumpTextSensor,
|
||||
icon=ICON_EXTERNAL_PAD_HEATER,
|
||||
),
|
||||
cv.Optional(CONF_TOP125): text_sensor.text_sensor_schema(
|
||||
PanasonicHeatpumpTextSensor,
|
||||
icon=ICON_VALVE,
|
||||
),
|
||||
cv.Optional(CONF_TOP126): text_sensor.text_sensor_schema(
|
||||
PanasonicHeatpumpTextSensor,
|
||||
icon=ICON_VALVE,
|
||||
),
|
||||
cv.Optional(CONF_TOP130): text_sensor.text_sensor_schema(
|
||||
PanasonicHeatpumpTextSensor,
|
||||
),
|
||||
}
|
||||
).extend(cv.COMPONENT_SCHEMA)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
parent = await cg.get_variable(config[CONF_PANASONIC_HEATPUMP_ID])
|
||||
for index, key in enumerate(TYPES):
|
||||
if child_config := config.get(key):
|
||||
var = await text_sensor.new_text_sensor(child_config)
|
||||
await cg.register_component(var, child_config)
|
||||
cg.add(var.set_parent(parent))
|
||||
cg.add(var.set_id(index))
|
||||
cg.add(parent.add_text_sensor(var))
|
||||
parent = await cg.get_variable(config[CONF_PANASONIC_HEATPUMP_ID])
|
||||
for index, key in enumerate(TYPES):
|
||||
if child_config := config.get(key):
|
||||
var = await text_sensor.new_text_sensor(child_config)
|
||||
await cg.register_component(var, child_config)
|
||||
cg.add(var.set_parent(parent))
|
||||
cg.add(var.set_id(index))
|
||||
cg.add(parent.add_text_sensor(var))
|
||||
|
|
|
|||
|
|
@ -1,113 +1,137 @@
|
|||
#include "panasonic_heatpump_text_sensor.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace panasonic_heatpump {
|
||||
static const char* const TAG = "panasonic_heatpump.text_sensor";
|
||||
|
||||
namespace esphome
|
||||
{
|
||||
namespace panasonic_heatpump
|
||||
{
|
||||
static const char *const TAG = "panasonic_heatpump.text_sensor";
|
||||
void PanasonicHeatpumpTextSensor::dump_config() {
|
||||
LOG_TEXT_SENSOR("", "Panasonic Heatpump Text Sensor", this);
|
||||
delay(10);
|
||||
}
|
||||
|
||||
void PanasonicHeatpumpTextSensor::dump_config()
|
||||
{
|
||||
LOG_TEXT_SENSOR("", "Panasonic Heatpump Text Sensor", this);
|
||||
delay(10);
|
||||
}
|
||||
void PanasonicHeatpumpTextSensor::publish_new_state(const std::vector<uint8_t>& data) {
|
||||
if (data.empty())
|
||||
return;
|
||||
|
||||
void PanasonicHeatpumpTextSensor::publish_new_state(const std::vector<uint8_t>& data)
|
||||
{
|
||||
if (data.empty()) return;
|
||||
std::string new_state;
|
||||
switch (this->id_) {
|
||||
case TextSensorIds::CONF_TOP4:
|
||||
new_state =
|
||||
PanasonicDecode::getTextState(PanasonicDecode::OperationMode, PanasonicDecode::getOperationMode(data[6]));
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case TextSensorIds::CONF_TOP17:
|
||||
new_state = PanasonicDecode::getTextState(PanasonicDecode::PowerfulMode, PanasonicDecode::getBit6and7and8(data[7]));
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case TextSensorIds::CONF_TOP18:
|
||||
new_state = PanasonicDecode::getTextState(PanasonicDecode::QuietMode, PanasonicDecode::getBit3and4and5(data[7]));
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case TextSensorIds::CONF_TOP19:
|
||||
new_state = PanasonicDecode::getTextState(PanasonicDecode::HolidayState, PanasonicDecode::getBit3and4(data[5]));
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case TextSensorIds::CONF_TOP20:
|
||||
new_state = PanasonicDecode::getTextState(PanasonicDecode::ThreeWayValve, PanasonicDecode::getBit7and8(data[111]));
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case TextSensorIds::CONF_TOP44:
|
||||
new_state = PanasonicDecode::getErrorInfo(data[113], data[114]);
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case TextSensorIds::CONF_TOP58:
|
||||
new_state = PanasonicDecode::getTextState(PanasonicDecode::BlockedFree, PanasonicDecode::getBit5and6(data[9]));
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case TextSensorIds::CONF_TOP59:
|
||||
new_state = PanasonicDecode::getTextState(PanasonicDecode::BlockedFree, PanasonicDecode::getBit7and8(data[9]));
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case TextSensorIds::CONF_TOP76:
|
||||
new_state =
|
||||
PanasonicDecode::getTextState(PanasonicDecode::WaterTempControl, PanasonicDecode::getBit7and8(data[28]));
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case TextSensorIds::CONF_TOP81:
|
||||
new_state =
|
||||
PanasonicDecode::getTextState(PanasonicDecode::WaterTempControl, PanasonicDecode::getBit5and6(data[28]));
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case TextSensorIds::CONF_TOP92:
|
||||
new_state = PanasonicDecode::getTextState(PanasonicDecode::ModelNames, PanasonicDecode::getModel(data, 129));
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case TextSensorIds::CONF_TOP94:
|
||||
new_state = PanasonicDecode::getTextState(PanasonicDecode::ZoneState, PanasonicDecode::getBit1and2(data[6]));
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case TextSensorIds::CONF_TOP101:
|
||||
new_state = PanasonicDecode::getTextState(PanasonicDecode::SolarMode, PanasonicDecode::getBit3and4(data[24]));
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case TextSensorIds::CONF_TOP106:
|
||||
new_state =
|
||||
PanasonicDecode::getTextState(PanasonicDecode::PumpFlowRateMode, PanasonicDecode::getBit3and4(data[29]));
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case TextSensorIds::CONF_TOP107:
|
||||
new_state = PanasonicDecode::getTextState(PanasonicDecode::LiquidType, PanasonicDecode::getBit1(data[20]));
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case TextSensorIds::CONF_TOP111:
|
||||
new_state =
|
||||
PanasonicDecode::getTextState(PanasonicDecode::ZoneSensorType, PanasonicDecode::getLowNibbleMinus1(data[22]));
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case TextSensorIds::CONF_TOP112:
|
||||
new_state =
|
||||
PanasonicDecode::getTextState(PanasonicDecode::ZoneSensorType, PanasonicDecode::getHighNibbleMinus1(data[22]));
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case TextSensorIds::CONF_TOP114:
|
||||
new_state =
|
||||
PanasonicDecode::getTextState(PanasonicDecode::ExtPadHeaterType, PanasonicDecode::getBit3and4(data[25]));
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case TextSensorIds::CONF_TOP125:
|
||||
new_state = PanasonicDecode::getTextState(PanasonicDecode::TwoWayValve, PanasonicDecode::getBit5and6(data[116]));
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case TextSensorIds::CONF_TOP126:
|
||||
new_state = PanasonicDecode::getTextState(PanasonicDecode::ThreeWayValve, PanasonicDecode::getBit7and8(data[116]));
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
case TextSensorIds::CONF_TOP130:
|
||||
new_state = PanasonicDecode::getTextState(PanasonicDecode::BivalentMode, PanasonicDecode::getBit5and6(data[26]));
|
||||
if (this->has_state() && this->get_state() == new_state)
|
||||
return;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
};
|
||||
|
||||
std::string new_state;
|
||||
switch (this->id_)
|
||||
{
|
||||
case TextSensorIds::CONF_TOP4:
|
||||
new_state = PanasonicDecode::getTextState(PanasonicDecode::OperationMode, PanasonicDecode::getOperationMode(data[6]));
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case TextSensorIds::CONF_TOP17:
|
||||
new_state = PanasonicDecode::getTextState(PanasonicDecode::PowerfulMode, PanasonicDecode::getBit6and7and8(data[7]));
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case TextSensorIds::CONF_TOP18:
|
||||
new_state = PanasonicDecode::getTextState(PanasonicDecode::QuietMode, PanasonicDecode::getBit3and4and5(data[7]));
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case TextSensorIds::CONF_TOP19:
|
||||
new_state = PanasonicDecode::getTextState(PanasonicDecode::HolidayState, PanasonicDecode::getBit3and4(data[5]));
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case TextSensorIds::CONF_TOP20:
|
||||
new_state = PanasonicDecode::getTextState(PanasonicDecode::ThreeWayValve, PanasonicDecode::getBit7and8(data[111]));
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case TextSensorIds::CONF_TOP44:
|
||||
new_state = PanasonicDecode::getErrorInfo(data[113], data[114]);
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case TextSensorIds::CONF_TOP58:
|
||||
new_state = PanasonicDecode::getTextState(PanasonicDecode::BlockedFree, PanasonicDecode::getBit5and6(data[9]));
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case TextSensorIds::CONF_TOP59:
|
||||
new_state = PanasonicDecode::getTextState(PanasonicDecode::BlockedFree, PanasonicDecode::getBit7and8(data[9]));
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case TextSensorIds::CONF_TOP76:
|
||||
new_state = PanasonicDecode::getTextState(PanasonicDecode::WaterTempControl, PanasonicDecode::getBit7and8(data[28]));
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case TextSensorIds::CONF_TOP81:
|
||||
new_state = PanasonicDecode::getTextState(PanasonicDecode::WaterTempControl, PanasonicDecode::getBit5and6(data[28]));
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case TextSensorIds::CONF_TOP92:
|
||||
new_state = PanasonicDecode::getTextState(PanasonicDecode::ModelNames, PanasonicDecode::getModel(data, 129));
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case TextSensorIds::CONF_TOP94:
|
||||
new_state = PanasonicDecode::getTextState(PanasonicDecode::ZoneState, PanasonicDecode::getBit1and2(data[6]));
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case TextSensorIds::CONF_TOP101:
|
||||
new_state = PanasonicDecode::getTextState(PanasonicDecode::SolarMode, PanasonicDecode::getBit3and4(data[24]));
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case TextSensorIds::CONF_TOP106:
|
||||
new_state = PanasonicDecode::getTextState(PanasonicDecode::PumpFlowRateMode, PanasonicDecode::getBit3and4(data[29]));
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case TextSensorIds::CONF_TOP107:
|
||||
new_state = PanasonicDecode::getTextState(PanasonicDecode::LiquidType, PanasonicDecode::getBit1(data[20]));
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case TextSensorIds::CONF_TOP111:
|
||||
new_state = PanasonicDecode::getTextState(PanasonicDecode::ZoneSensorType, PanasonicDecode::getLowNibbleMinus1(data[22]));
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case TextSensorIds::CONF_TOP112:
|
||||
new_state = PanasonicDecode::getTextState(PanasonicDecode::ZoneSensorType, PanasonicDecode::getHighNibbleMinus1(data[22]));
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case TextSensorIds::CONF_TOP114:
|
||||
new_state = PanasonicDecode::getTextState(PanasonicDecode::ExtPadHeaterType, PanasonicDecode::getBit3and4(data[25]));
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case TextSensorIds::CONF_TOP125:
|
||||
new_state = PanasonicDecode::getTextState(PanasonicDecode::TwoWayValve, PanasonicDecode::getBit5and6(data[116]));
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case TextSensorIds::CONF_TOP126:
|
||||
new_state = PanasonicDecode::getTextState(PanasonicDecode::ThreeWayValve, PanasonicDecode::getBit7and8(data[116]));
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
case TextSensorIds::CONF_TOP130:
|
||||
new_state = PanasonicDecode::getTextState(PanasonicDecode::BivalentMode, PanasonicDecode::getBit5and6(data[26]));
|
||||
if (this->has_state() && this->get_state() == new_state) return;
|
||||
break;
|
||||
default: return;
|
||||
};
|
||||
|
||||
this->publish_state(new_state);
|
||||
}
|
||||
} // namespace panasonic_heatpump
|
||||
} // namespace esphome
|
||||
this->publish_state(new_state);
|
||||
}
|
||||
} // namespace panasonic_heatpump
|
||||
} // namespace esphome
|
||||
|
|
|
|||
|
|
@ -4,43 +4,40 @@
|
|||
#include "../panasonic_heatpump.h"
|
||||
#include "../decode.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace panasonic_heatpump {
|
||||
enum TextSensorIds : uint8_t {
|
||||
CONF_TOP4,
|
||||
CONF_TOP17,
|
||||
CONF_TOP18,
|
||||
CONF_TOP19,
|
||||
CONF_TOP20,
|
||||
CONF_TOP44,
|
||||
CONF_TOP58,
|
||||
CONF_TOP59,
|
||||
CONF_TOP76,
|
||||
CONF_TOP81,
|
||||
CONF_TOP92,
|
||||
CONF_TOP94,
|
||||
CONF_TOP101,
|
||||
CONF_TOP106,
|
||||
CONF_TOP107,
|
||||
CONF_TOP111,
|
||||
CONF_TOP112,
|
||||
CONF_TOP114,
|
||||
CONF_TOP125,
|
||||
CONF_TOP126,
|
||||
CONF_TOP130,
|
||||
};
|
||||
|
||||
namespace esphome
|
||||
{
|
||||
namespace panasonic_heatpump
|
||||
{
|
||||
enum TextSensorIds : uint8_t
|
||||
{
|
||||
CONF_TOP4,
|
||||
CONF_TOP17,
|
||||
CONF_TOP18,
|
||||
CONF_TOP19,
|
||||
CONF_TOP20,
|
||||
CONF_TOP44,
|
||||
CONF_TOP58,
|
||||
CONF_TOP59,
|
||||
CONF_TOP76,
|
||||
CONF_TOP81,
|
||||
CONF_TOP92,
|
||||
CONF_TOP94,
|
||||
CONF_TOP101,
|
||||
CONF_TOP106,
|
||||
CONF_TOP107,
|
||||
CONF_TOP111,
|
||||
CONF_TOP112,
|
||||
CONF_TOP114,
|
||||
CONF_TOP125,
|
||||
CONF_TOP126,
|
||||
CONF_TOP130,
|
||||
};
|
||||
|
||||
class PanasonicHeatpumpTextSensor : public text_sensor::TextSensor, public Component,
|
||||
public Parented<PanasonicHeatpumpComponent>, public PanasonicHeatpumpEntity
|
||||
{
|
||||
public:
|
||||
PanasonicHeatpumpTextSensor() = default;
|
||||
void dump_config() override;
|
||||
void publish_new_state(const std::vector<uint8_t>& data) override;
|
||||
};
|
||||
} // namespace panasonic_heatpump
|
||||
} // namespace esphome
|
||||
class PanasonicHeatpumpTextSensor : public text_sensor::TextSensor,
|
||||
public Component,
|
||||
public Parented<PanasonicHeatpumpComponent>,
|
||||
public PanasonicHeatpumpEntity {
|
||||
public:
|
||||
PanasonicHeatpumpTextSensor() = default;
|
||||
void dump_config() override;
|
||||
void publish_new_state(const std::vector<uint8_t>& data) override;
|
||||
};
|
||||
} // namespace panasonic_heatpump
|
||||
} // namespace esphome
|
||||
|
|
|
|||
|
|
@ -1 +1,128 @@
|
|||
prototypes/maidesite_desk/example_basic.yaml
|
||||
esp32:
|
||||
board: esp32-c3-devkitm-1
|
||||
variant: ESP32C3
|
||||
framework:
|
||||
type: esp-idf
|
||||
|
||||
esphome:
|
||||
name: maidesite-desk-controller
|
||||
friendly_name: Maidesite Desk Controller
|
||||
|
||||
ota:
|
||||
platform: esphome
|
||||
password: !secret ota_password
|
||||
|
||||
api:
|
||||
encryption:
|
||||
key: !secret encryption_key
|
||||
|
||||
wifi:
|
||||
ssid: !secret wifi_ssid
|
||||
password: !secret wifi_password
|
||||
ap:
|
||||
ssid: "Maidesite Desk Fallback"
|
||||
password: !secret fallback_password
|
||||
|
||||
logger:
|
||||
|
||||
external_components:
|
||||
- source:
|
||||
type: git
|
||||
url: https://github.com/ElVit/esphome_components/
|
||||
components: [ maidesite_desk ]
|
||||
|
||||
uart:
|
||||
- id: uart_bus
|
||||
tx_pin: GPIO03
|
||||
rx_pin: GPIO04
|
||||
baud_rate: 9600
|
||||
|
||||
maidesite_desk_controller:
|
||||
id: my_desk
|
||||
uart_id: uart_bus
|
||||
log_uart_msg: true
|
||||
|
||||
sensor:
|
||||
- platform: maidesite_desk
|
||||
height_abs:
|
||||
name: "Height absolut"
|
||||
height_pct:
|
||||
name: "Height percent"
|
||||
height_min:
|
||||
name: "Height Min"
|
||||
height_max:
|
||||
name: "Height Max"
|
||||
position_m1:
|
||||
name: "Position M1"
|
||||
position_m2:
|
||||
name: "Position M2"
|
||||
position_m3:
|
||||
name: "Position M3"
|
||||
position_m4:
|
||||
name: "Position M4"
|
||||
|
||||
button:
|
||||
- platform: maidesite_desk
|
||||
stop:
|
||||
name: "Stop"
|
||||
step_up:
|
||||
name: "Step up"
|
||||
step_down:
|
||||
name: "Step down"
|
||||
goto_max:
|
||||
name: "Move to MAX"
|
||||
goto_min:
|
||||
name: "Move to MIN"
|
||||
goto_m1:
|
||||
name: "Move to M1"
|
||||
goto_m2:
|
||||
name: "Move to M2"
|
||||
goto_m3:
|
||||
name: "Move to M3"
|
||||
goto_m4:
|
||||
name: "Move to M4"
|
||||
save_m1:
|
||||
name: "Save M1"
|
||||
save_m2:
|
||||
name: "Save M2"
|
||||
save_m3:
|
||||
name: "Save M3"
|
||||
save_m4:
|
||||
name: "Save M4"
|
||||
|
||||
number:
|
||||
- platform: maidesite_desk
|
||||
height_abs:
|
||||
name: "Height absolut"
|
||||
mode: SLIDER
|
||||
height_pct:
|
||||
name: "Height percent"
|
||||
mode: SLIDER
|
||||
|
||||
## lambda usage
|
||||
# button:
|
||||
# - platform: template
|
||||
# name: "Step up"
|
||||
# on_press:
|
||||
# lambda: "id(my_desk).step_up();"
|
||||
# - platform: template
|
||||
# name: "Step down"
|
||||
# on_press:
|
||||
# lambda: "id(my_desk).step_down();"
|
||||
# - platform: template
|
||||
# name: "Stop"
|
||||
# on_press:
|
||||
# lambda: "id(my_desk).stop();"
|
||||
# - platform: template
|
||||
# name: "Position 2"
|
||||
# on_press:
|
||||
# lambda: "id(my_desk).goto_mem_position(2);"
|
||||
# - platform: template
|
||||
# name: "Save Position 4"
|
||||
# on_press:
|
||||
# lambda: "id(my_desk).save_mem_position(4);"
|
||||
# - platform: template
|
||||
# name: "Go to 100cm"
|
||||
# on_press:
|
||||
# lambda: "id(my_desk).goto_height(100);"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,3 @@
|
|||
substitutions:
|
||||
mdns_name: panasonic-heatpump
|
||||
device_name: Panasonic Heatpump
|
||||
|
||||
pin_rx_hp: GPIO37 # heatpump reads data (RX) on this pin (yellow)
|
||||
pin_tx_hp: GPIO39 # heatpump sends data (TX) on this pin (green)
|
||||
pin_tx_wm: GPIO18 # WiFi module sends data (TX) on this pin (white)
|
||||
pin_rx_wm: GPIO16 # WiFi module reads data (RX) on this pin (blue)
|
||||
|
||||
esp32:
|
||||
board: lolin_s2_mini
|
||||
variant: ESP32S2
|
||||
|
|
@ -14,13 +5,12 @@ esp32:
|
|||
type: esp-idf
|
||||
|
||||
esphome:
|
||||
name: $mdns_name
|
||||
friendly_name: $device_name
|
||||
name: panasonic-heatpump
|
||||
friendly_name: Panasonic Heatpump
|
||||
|
||||
ota:
|
||||
platform: esphome
|
||||
password: !secret ota_password
|
||||
id: ota_pass
|
||||
|
||||
api:
|
||||
encryption:
|
||||
|
|
@ -30,43 +20,33 @@ wifi:
|
|||
ssid: !secret wifi_ssid
|
||||
password: !secret wifi_password
|
||||
ap:
|
||||
ssid: "${device_name} Fallback"
|
||||
ssid: "Panasonic Heatpump Fallback"
|
||||
password: !secret fallback_password
|
||||
|
||||
web_server:
|
||||
port: 80
|
||||
auth:
|
||||
username: !secret webserver_username
|
||||
password: !secret webserver_password
|
||||
|
||||
captive_portal:
|
||||
|
||||
improv_serial:
|
||||
|
||||
logger:
|
||||
|
||||
uart:
|
||||
- id: uart_heatpump
|
||||
tx_pin: $pin_rx_hp
|
||||
rx_pin: $pin_tx_hp
|
||||
baud_rate: 9600
|
||||
data_bits: 8
|
||||
parity: EVEN
|
||||
stop_bits: 1
|
||||
- id: uart_cz_taw1
|
||||
tx_pin: $pin_rx_wm
|
||||
rx_pin: $pin_tx_wm
|
||||
baud_rate: 9600
|
||||
data_bits: 8
|
||||
parity: EVEN
|
||||
stop_bits: 1
|
||||
|
||||
external_components:
|
||||
- source:
|
||||
type: git
|
||||
url: https://github.com/ElVit/esphome_components/
|
||||
components: [ panasonic_heatpump ]
|
||||
|
||||
uart:
|
||||
- id: uart_heatpump
|
||||
tx_pin: GPIO37 # heatpump reads data (RX) on this pin (yellow)
|
||||
rx_pin: GPIO39 # heatpump sends data (TX) on this pin (green)
|
||||
baud_rate: 9600
|
||||
data_bits: 8
|
||||
parity: EVEN
|
||||
stop_bits: 1
|
||||
- id: uart_cz_taw1
|
||||
tx_pin: GPIO16 # WiFi module reads data (RX) on this pin (blue)
|
||||
rx_pin: GPIO18 # WiFi module sends data (TX) on this pin (white)
|
||||
baud_rate: 9600
|
||||
data_bits: 8
|
||||
parity: EVEN
|
||||
stop_bits: 1
|
||||
|
||||
panasonic_heatpump:
|
||||
id: my_heatpump
|
||||
uart_id: uart_heatpump
|
||||
|
|
@ -419,23 +399,23 @@ number:
|
|||
name: "Set DHW Temp"
|
||||
set15:
|
||||
name: "Set Max Pump Duty"
|
||||
set16_1:
|
||||
set16_01:
|
||||
name: "Set Zone1 Heat Target High"
|
||||
set16_2:
|
||||
set16_02:
|
||||
name: "Set Zone1 Heat Target Low"
|
||||
set16_3:
|
||||
set16_03:
|
||||
name: "Set Zone1 Heat Outside Low"
|
||||
set16_4:
|
||||
set16_04:
|
||||
name: "Set Zone1 Heat Outside High"
|
||||
set16_5:
|
||||
set16_05:
|
||||
name: "Set Zone2 Heat Target High"
|
||||
set16_6:
|
||||
set16_06:
|
||||
name: "Set Zone2 Heat Target Low"
|
||||
set16_7:
|
||||
set16_07:
|
||||
name: "Set Zone2 Heat Outside Low"
|
||||
set16_8:
|
||||
set16_08:
|
||||
name: "Set Zone2 Heat Outside High"
|
||||
set16_9:
|
||||
set16_09:
|
||||
name: "Set Zone1 Cool Target High"
|
||||
set16_10:
|
||||
name: "Set Zone1 Cool Target Low"
|
||||
|
|
@ -474,8 +454,38 @@ number:
|
|||
set38:
|
||||
name: "Set Bivalent AP Stop Temp"
|
||||
|
||||
switch:
|
||||
- platform: panasonic_heatpump
|
||||
set1:
|
||||
name: "Set Heatpump"
|
||||
set10:
|
||||
name: "Set Force DHW"
|
||||
set12:
|
||||
name: "Set Force Defrost"
|
||||
set13:
|
||||
name: "Set Force Sterilization"
|
||||
set14:
|
||||
name: "Set Pump"
|
||||
set24:
|
||||
name: "Set Main Schedule"
|
||||
set25:
|
||||
name: "Set Alt External Sensor"
|
||||
set28:
|
||||
name: "Set Buffer"
|
||||
set30:
|
||||
name: "Set External Control"
|
||||
set31:
|
||||
name: "Set External Error"
|
||||
set32:
|
||||
name: "Set External Compressor Control"
|
||||
set33:
|
||||
name: "Set External Heat Cool Control"
|
||||
set34:
|
||||
name: "Set Bivalent Control"
|
||||
|
||||
select:
|
||||
- platform: panasonic_heatpump
|
||||
cool_mode: true
|
||||
set2:
|
||||
name: "Set Holiday Mode"
|
||||
set3:
|
||||
|
|
@ -491,31 +501,12 @@ select:
|
|||
set35:
|
||||
name: "Set Bivalent Mode"
|
||||
|
||||
switch:
|
||||
- platform: panasonic_heatpump
|
||||
set1:
|
||||
name: "Set Heatpump"
|
||||
set10:
|
||||
name: "Set Force DHW"
|
||||
set12:
|
||||
name: "Set Force Defrost"
|
||||
set13:
|
||||
name: "Set Force Sterilization"
|
||||
set14:
|
||||
name: "Set Pump"
|
||||
set24:
|
||||
name: "Set Main Schedule"
|
||||
set25:
|
||||
name: "Set Alt External Sensor"
|
||||
set28:
|
||||
name: "Set Buffer"
|
||||
set30:
|
||||
name: "Set External Control"
|
||||
set31:
|
||||
name: "Set External Error"
|
||||
set32:
|
||||
name: "Set External Compressor Control"
|
||||
set33:
|
||||
name: "Set External Heat Cool Control"
|
||||
set34:
|
||||
name: "Set Bivalent Control"
|
||||
climate:
|
||||
- platform: panasonic_heatpump
|
||||
cool_mode: true
|
||||
tank:
|
||||
name: "DHW"
|
||||
zone1:
|
||||
name: "Zone 1"
|
||||
zone2:
|
||||
name: "Zone 2"
|
||||
|
|
|
|||
|
|
@ -1,70 +0,0 @@
|
|||
esphome:
|
||||
name: maidesite-desk
|
||||
friendly_name: Maidesite Desk
|
||||
|
||||
external_components:
|
||||
- source:
|
||||
type: git
|
||||
url: https://github.com/ElVit/esphome_components/
|
||||
components: [ maidesite_desk ]
|
||||
|
||||
uart:
|
||||
- id: uart_bus
|
||||
tx_pin: $pin_tx
|
||||
rx_pin: $pin_rx
|
||||
baud_rate: 9600
|
||||
|
||||
maidesite_desk_controller:
|
||||
id: my_desk
|
||||
|
||||
sensor:
|
||||
- platform: maidesite_desk
|
||||
height_abs:
|
||||
name: "Height"
|
||||
|
||||
button:
|
||||
- platform: maidesite_desk
|
||||
stop:
|
||||
name: "Stop"
|
||||
step_up:
|
||||
name: "Step up"
|
||||
step_down:
|
||||
name: "Step down"
|
||||
goto_max:
|
||||
name: "Move to MAX"
|
||||
goto_min:
|
||||
name: "Move to MIN"
|
||||
goto_m1:
|
||||
name: "Move to M1"
|
||||
goto_m2:
|
||||
name: "Move to M2"
|
||||
goto_m3:
|
||||
name: "Move to M3"
|
||||
goto_m4:
|
||||
name: "Move to M4"
|
||||
|
||||
number:
|
||||
- platform: maidesite_desk
|
||||
height_abs:
|
||||
name: "Height"
|
||||
mode: SLIDER
|
||||
|
||||
# the usual stuff
|
||||
|
||||
esp8266:
|
||||
board: esp01_1m
|
||||
|
||||
wifi:
|
||||
ssid: !secret wifi_ssid
|
||||
password: !secret wifi_password
|
||||
ap:
|
||||
ssid: "esphome-desk"
|
||||
password: "9ebc6eac0b4e0e26b8d3b955ec660557"
|
||||
|
||||
captive_portal:
|
||||
api:
|
||||
encryption:
|
||||
key: !secret encryption_key
|
||||
ota:
|
||||
|
||||
logger:
|
||||
|
|
@ -1,128 +0,0 @@
|
|||
esphome:
|
||||
name: maidesite-desk-controller
|
||||
friendly_name: Maidesite Desk Controller
|
||||
|
||||
external_components:
|
||||
- source:
|
||||
type: local
|
||||
path: esphome_components/components/
|
||||
# type: git
|
||||
# url: https://github.com/ElVit/esphome_components/
|
||||
components: [ maidesite_desk ]
|
||||
|
||||
uart:
|
||||
- id: uart_bus
|
||||
tx_pin: $pin_tx
|
||||
rx_pin: $pin_rx
|
||||
baud_rate: 9600
|
||||
|
||||
maidesite_desk_controller:
|
||||
id: my_desk
|
||||
uart_id: uart_bus
|
||||
|
||||
sensor:
|
||||
- platform: maidesite_desk
|
||||
height_abs:
|
||||
name: "Height absolut"
|
||||
height_pct:
|
||||
name: "Height percent"
|
||||
height_min:
|
||||
name: "Height Min"
|
||||
height_max:
|
||||
name: "Height Max"
|
||||
position_m1:
|
||||
name: "Position M1"
|
||||
position_m2:
|
||||
name: "Position M2"
|
||||
position_m3:
|
||||
name: "Position M3"
|
||||
position_m4:
|
||||
name: "Position M4"
|
||||
|
||||
button:
|
||||
- platform: maidesite_desk
|
||||
stop:
|
||||
name: "Stop"
|
||||
step_up:
|
||||
name: "Step up"
|
||||
step_down:
|
||||
name: "Step down"
|
||||
goto_max:
|
||||
name: "Move to MAX"
|
||||
goto_min:
|
||||
name: "Move to MIN"
|
||||
goto_m1:
|
||||
name: "Move to M1"
|
||||
goto_m2:
|
||||
name: "Move to M2"
|
||||
goto_m3:
|
||||
name: "Move to M3"
|
||||
goto_m4:
|
||||
name: "Move to M4"
|
||||
save_m1:
|
||||
name: "Save M1"
|
||||
save_m2:
|
||||
name: "Save M2"
|
||||
save_m3:
|
||||
name: "Save M3"
|
||||
save_m4:
|
||||
name: "Save M4"
|
||||
|
||||
number:
|
||||
- platform: maidesite_desk
|
||||
height_abs:
|
||||
name: "Height absolut"
|
||||
mode: SLIDER
|
||||
height_pct:
|
||||
name: "Height percent"
|
||||
mode: SLIDER
|
||||
|
||||
## lambda usage
|
||||
# button:
|
||||
# - platform: template
|
||||
# name: "Step up"
|
||||
# on_press:
|
||||
# lambda: "id(my_desk).step_up();"
|
||||
# - platform: template
|
||||
# name: "Step down"
|
||||
# on_press:
|
||||
# lambda: "id(my_desk).step_down();"
|
||||
# - platform: template
|
||||
# name: "Stop"
|
||||
# on_press:
|
||||
# lambda: "id(my_desk).stop();"
|
||||
# - platform: template
|
||||
# name: "Position 2"
|
||||
# on_press:
|
||||
# lambda: "id(my_desk).goto_mem_position(2);"
|
||||
# - platform: template
|
||||
# name: "Save Position 4"
|
||||
# on_press:
|
||||
# lambda: "id(my_desk).save_mem_position(4);"
|
||||
# - platform: template
|
||||
# name: "Go to 100cm"
|
||||
# on_press:
|
||||
# lambda: "id(my_desk).goto_height(100);"
|
||||
|
||||
# the usual stuff
|
||||
|
||||
esp32:
|
||||
board: esp32-c3-devkitm-1
|
||||
variant: ESP32C3
|
||||
framework:
|
||||
type: esp-idf
|
||||
|
||||
wifi:
|
||||
ssid: !secret wifi_ssid
|
||||
password: !secret wifi_password
|
||||
ap:
|
||||
ssid: "esphome-desk"
|
||||
password: "9ebc6eac0b4e0e26b8d3b955ec660557"
|
||||
|
||||
captive_portal:
|
||||
api:
|
||||
encryption:
|
||||
key: !secret encryption_key
|
||||
ota:
|
||||
|
||||
logger:
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,45 @@
|
|||
[tool:pytest]
|
||||
# Pytest configuration for all component tests
|
||||
|
||||
testpaths = tests
|
||||
python_files = test_*.py
|
||||
python_classes = Test*
|
||||
python_functions = test_*
|
||||
|
||||
# Coverage settings
|
||||
addopts =
|
||||
--verbose
|
||||
--strict-markers
|
||||
--tb=short
|
||||
--cov-report=term-missing
|
||||
--cov-report=html
|
||||
--cov-report=xml
|
||||
|
||||
# Markers
|
||||
markers =
|
||||
unit: Unit tests that don't require ESPHome compilation
|
||||
integration: Integration tests that compile ESPHome configurations
|
||||
slow: Tests that take a long time to run
|
||||
|
||||
# Timeout for tests (in seconds)
|
||||
timeout = 300
|
||||
|
||||
# Coverage options
|
||||
[coverage:run]
|
||||
source = components/panasonic_heatpump
|
||||
omit =
|
||||
*/tests/*
|
||||
*/test_*
|
||||
|
||||
[coverage:report]
|
||||
exclude_lines =
|
||||
pragma: no cover
|
||||
def __repr__
|
||||
raise AssertionError
|
||||
raise NotImplementedError
|
||||
if __name__ == .__main__.:
|
||||
if TYPE_CHECKING:
|
||||
@abstractmethod
|
||||
|
||||
[coverage:html]
|
||||
directory = htmlcov
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
# ESPHome Components Tests
|
||||
|
||||
This directory contains tests for all custom ESPHome components in this repository.
|
||||
|
||||
## Directory Structure
|
||||
|
||||
```
|
||||
tests/
|
||||
├── requirements.txt # Common Python dependencies for all tests
|
||||
├── panasonic_heatpump/ # Tests for panasonic_heatpump component
|
||||
│ ├── README.md
|
||||
│ ├── test_panasonic_heatpump_unit.py # Unit tests
|
||||
│ ├── test_panasonic_heatpump_integration.py # Integration tests
|
||||
│ ├── test_panasonic_heatpump_esp8266.yaml # ESP8266 test config
|
||||
│ ├── test_panasonic_heatpump_esp32s2.yaml # ESP32-S2 test config
|
||||
│ ├── test_panasonic_heatpump_esp32c3.yaml # ESP32-C3 test config
|
||||
│ ├── test_panasonic_heatpump_cztaw1.yaml # CZ-TAW1 test config
|
||||
│ ├── test_panasonic_heatpump_mini.yaml # Minimal ESP32 test config
|
||||
│ └── test_panasonic_heatpump_full.yaml # Full ESP32 test config
|
||||
└── [other_component]/ # Tests for other components (future)
|
||||
```
|
||||
|
||||
## Running Tests
|
||||
|
||||
### Install Dependencies
|
||||
```bash
|
||||
pip install -r tests/requirements.txt
|
||||
```
|
||||
|
||||
### Run All Tests
|
||||
```bash
|
||||
pytest tests/ -v
|
||||
```
|
||||
|
||||
### Run Tests for Specific Component
|
||||
```bash
|
||||
# Panasonic Heatpump
|
||||
pytest tests/panasonic_heatpump/ -v
|
||||
|
||||
# Other components (when added)
|
||||
pytest tests/[component_name]/ -v
|
||||
```
|
||||
|
||||
### Run with Coverage
|
||||
```bash
|
||||
pytest tests/ -v --cov=components --cov-report=html
|
||||
```
|
||||
|
||||
## Adding Tests for New Components
|
||||
|
||||
When adding a new component, create a subdirectory under `tests/` with the same name as your component:
|
||||
|
||||
1. Create directory: `tests/[component_name]/`
|
||||
2. Add test files:
|
||||
- `test_[component_name].yaml` - ESPHome configuration for testing
|
||||
- `test_[component_name]_unit.py` - Python unit tests
|
||||
- `test_[component_name]_integration.py` - Integration tests
|
||||
- `README.md` - Component-specific test documentation
|
||||
3. Create GitHub Actions workflow: `.github/workflows/test_[component_name].yml`
|
||||
|
||||
## Test Types
|
||||
|
||||
### Unit Tests
|
||||
- Test Python configuration validation
|
||||
- Test component metadata
|
||||
- Test schema structure
|
||||
- Fast execution, no compilation required
|
||||
|
||||
### Integration Tests
|
||||
- Test ESPHome configuration validation
|
||||
- Test actual firmware compilation
|
||||
- Test various configuration scenarios
|
||||
- Slower execution, requires ESPHome
|
||||
|
||||
## Configuration
|
||||
|
||||
Test configuration is managed in `pytest.ini` at the repository root.
|
||||
|
||||
## GitHub Actions
|
||||
|
||||
Each component should have its own GitHub Actions workflow in `.github/workflows/` that:
|
||||
- Validates ESPHome configurations
|
||||
- Compiles test firmware
|
||||
- Runs Python unit tests
|
||||
- Checks code formatting
|
||||
- Reports coverage
|
||||
|
||||
See `panasonic_heatpump` for a complete example.
|
||||
|
|
@ -0,0 +1,208 @@
|
|||
# Testing Documentation for Panasonic Heatpump Component
|
||||
|
||||
This directory contains comprehensive tests for the `panasonic_heatpump` ESPHome component.
|
||||
|
||||
## Test Structure
|
||||
|
||||
### Unit Tests (`test_panasonic_heatpump_unit.py`)
|
||||
- Tests Python configuration validation
|
||||
- Tests component metadata (CODEOWNERS, DEPENDENCIES, etc.)
|
||||
- Tests configuration schema structure
|
||||
- Tests all platform imports (sensor, binary_sensor, text_sensor, number, select, switch, climate)
|
||||
- Tests code generation logic
|
||||
|
||||
### Integration Tests (`test_panasonic_heatpump_integration.py`)
|
||||
- Tests minimal feature configuration on ESP32 board
|
||||
- Tests full feature configuration on ESP32 board
|
||||
- Tests configuration on ESP8266 board
|
||||
- Tests configuration on ESP32-S2 board
|
||||
- Tests configuration on ESP32-C3 board
|
||||
- Tests configuration with CZ-TAW1 (UART-proxy)
|
||||
|
||||
### Test Configuration Files
|
||||
- `test_panasonic_heatpump_esp8266.yaml` - ESP8266 Wemos D1 Mini
|
||||
- `test_panasonic_heatpump_esp32s2.yaml` - ESP32-S2 Wemos S2 Mini
|
||||
- `test_panasonic_heatpump_esp32c3.yaml` - ESP32-C3 mini (RISC-V)
|
||||
- `test_panasonic_heatpump_cztaw1.yaml` - UART proxy setup for CZ-TAW1 client support
|
||||
- `test_panasonic_heatpump_mini.yaml` - Minimal ESP32 configuration for basic testing
|
||||
- `test_panasonic_heatpump_full.yaml` - Comprehensive ESP32 configuration with all features
|
||||
|
||||
## Running Tests Locally
|
||||
|
||||
### Prerequisites
|
||||
```bash
|
||||
pip install -r tests/requirements.txt
|
||||
```
|
||||
|
||||
### Run All Tests
|
||||
```bash
|
||||
pytest tests/panasonic_heatpump/ -v
|
||||
```
|
||||
|
||||
### Run Only Unit Tests
|
||||
```bash
|
||||
pytest tests/panasonic_heatpump/test_panasonic_heatpump_unit.py -v
|
||||
```
|
||||
|
||||
### Run Only Integration Tests
|
||||
```bash
|
||||
pytest tests/panasonic_heatpump/test_panasonic_heatpump_integration.py -v
|
||||
```
|
||||
|
||||
### Run with Coverage
|
||||
```bash
|
||||
pytest tests/panasonic_heatpump/ -v --cov=components/panasonic_heatpump --cov-report=html
|
||||
```
|
||||
|
||||
View coverage report by opening `htmlcov/index.html` in a browser.
|
||||
|
||||
### Run Specific Test
|
||||
```bash
|
||||
pytest tests/panasonic_heatpump/test_panasonic_heatpump_unit.py::TestPanasonicHeatpumpConfig::test_component_metadata -v
|
||||
```
|
||||
|
||||
## GitHub Actions Workflow
|
||||
|
||||
The GitHub Actions workflow (`.github/workflows/test_panasonic_heatpump.yml`) includes:
|
||||
|
||||
### Jobs
|
||||
|
||||
1. **test-build**: Validates and compiles the component
|
||||
- Tests on multiple board types: ESP8266, ESP32 (full), ESP32-S2, ESP32-C3 and with CZ-TAW1 (UART-proxy)
|
||||
- Uses esphome/build-action for firmware compilation
|
||||
|
||||
2. **lint-code**: Runs clang-format on C++ code
|
||||
- Ensures consistent code formatting
|
||||
- Checks all .cpp and .h files
|
||||
|
||||
3. **lint-python**: Runs Python linters
|
||||
- black: Code formatting
|
||||
- flake8: Style guide enforcement
|
||||
|
||||
4. **test-python**: Runs Python unit tests
|
||||
- Executes pytest with coverage
|
||||
- Uploads coverage to Codecov
|
||||
|
||||
5. **test-minimal-config**: Tests minimal configuration
|
||||
- Validates minimal configuration file
|
||||
- Ensures component works with bare minimum settings
|
||||
|
||||
6. **test-full-config**: Tests full configuration
|
||||
- Validates full feature configuration with all platforms
|
||||
|
||||
7. **summary**: Aggregates all test results
|
||||
- Fails if any test job fails
|
||||
- Provides overview of all test results
|
||||
|
||||
### Triggers
|
||||
|
||||
The workflow runs on:
|
||||
- Push to `main` or `heatpump**` branches
|
||||
- Pull requests to `main` branch
|
||||
- Manual workflow dispatch
|
||||
- When relevant files change:
|
||||
- `components/panasonic_heatpump/**`
|
||||
- `tests/panasonic_heatpump/**`
|
||||
- `.github/workflows/test_panasonic_heatpump.yml`
|
||||
|
||||
## Test Coverage
|
||||
|
||||
The test suite covers:
|
||||
|
||||
✅ Component configuration validation
|
||||
✅ UART dependency checking
|
||||
✅ All sensor platforms
|
||||
✅ All binary sensor platforms
|
||||
✅ All text sensor platforms
|
||||
✅ All number control platforms
|
||||
✅ All select control platforms
|
||||
✅ All switch control platforms
|
||||
✅ All climate control platforms
|
||||
✅ Code compilation for different ESP boards
|
||||
✅ C++ code formatting
|
||||
✅ Python code formatting and style
|
||||
|
||||
## Configuration Examples
|
||||
|
||||
### Minimal Configuration
|
||||
```yaml
|
||||
uart:
|
||||
- id: uart_hp
|
||||
tx_pin: GPIO1
|
||||
rx_pin: GPIO3
|
||||
baud_rate: 9600
|
||||
parity: EVEN
|
||||
|
||||
panasonic_heatpump:
|
||||
id: hp
|
||||
```
|
||||
|
||||
### Full Configuration
|
||||
```yaml
|
||||
uart:
|
||||
- id: uart_heatpump
|
||||
tx_pin: GPIO37
|
||||
rx_pin: GPIO39
|
||||
baud_rate: 9600
|
||||
parity: EVEN
|
||||
- id: uart_client
|
||||
tx_pin: GPIO18
|
||||
rx_pin: GPIO16
|
||||
baud_rate: 9600
|
||||
parity: EVEN
|
||||
|
||||
panasonic_heatpump:
|
||||
id: my_heatpump
|
||||
uart_id: uart_heatpump
|
||||
uart_client_id: uart_client
|
||||
log_uart_msg: true
|
||||
update_interval: 3s
|
||||
```
|
||||
|
||||
## Adding New Tests
|
||||
|
||||
When adding new features to the component:
|
||||
|
||||
1. Update `test_panasonic_heatpump.yaml` with new configuration options
|
||||
2. Add unit tests in `test_panasonic_heatpump_unit.py`
|
||||
3. Add integration tests in `test_panasonic_heatpump_integration.py` if needed
|
||||
4. Update this README with new test coverage information
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### ESPHome Not Found
|
||||
If you get "ESPHome not installed" errors, install it:
|
||||
```bash
|
||||
pip install esphome
|
||||
```
|
||||
|
||||
### Import Errors
|
||||
Make sure you're running pytest from the repository root:
|
||||
```bash
|
||||
cd /path/to/esphome_components
|
||||
pytest tests/ -v
|
||||
```
|
||||
|
||||
### Timeout Errors
|
||||
Some tests may timeout on slower systems. Increase the timeout in `pytest.ini`:
|
||||
```ini
|
||||
timeout = 600 # 10 minutes
|
||||
```
|
||||
|
||||
## Continuous Integration
|
||||
|
||||
All tests must pass before merging to main branch. The GitHub Actions workflow ensures:
|
||||
- Code compiles successfully
|
||||
- Code follows formatting standards
|
||||
- All unit and integration tests pass
|
||||
- Latest ESPHome versions is supported
|
||||
- ESP8266 and ESP32 boards are supported
|
||||
|
||||
## Contributing
|
||||
|
||||
When contributing to the panasonic_heatpump component:
|
||||
1. Write tests for new features
|
||||
2. Ensure all existing tests pass
|
||||
3. Maintain or improve code coverage
|
||||
4. Follow the existing code style
|
||||
5. Update this documentation as needed
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
---
|
||||
# Test configuration for panasonic_heatpump component with CZ-TAW1 (UART-man-in-the-middle)
|
||||
# Tests the proxy functionality of the CZ-TAW1 client to the heatpump
|
||||
|
||||
esp32:
|
||||
board: esp32dev
|
||||
framework:
|
||||
type: esp-idf
|
||||
|
||||
esphome:
|
||||
name: test-panasonic-heatpump-cztaw1
|
||||
friendly_name: "Test Panasonic Heatpump CZ-TAW1"
|
||||
|
||||
logger:
|
||||
level: DEBUG
|
||||
|
||||
external_components:
|
||||
- source:
|
||||
type: local
|
||||
path: ../../components
|
||||
components: [panasonic_heatpump]
|
||||
|
||||
uart:
|
||||
- id: uart_heatpump
|
||||
tx_pin: GPIO16
|
||||
rx_pin: GPIO17
|
||||
baud_rate: 9600
|
||||
data_bits: 8
|
||||
parity: EVEN
|
||||
stop_bits: 1
|
||||
- id: uart_cz_taw1
|
||||
tx_pin: GPIO19
|
||||
rx_pin: GPIO18
|
||||
baud_rate: 9600
|
||||
data_bits: 8
|
||||
parity: EVEN
|
||||
stop_bits: 1
|
||||
|
||||
# Test configuration with cz_taw1 client
|
||||
panasonic_heatpump:
|
||||
id: my_heatpump
|
||||
uart_id: uart_heatpump
|
||||
uart_client_id: uart_cz_taw1
|
||||
log_uart_msg: true
|
||||
update_interval: 3s
|
||||
|
||||
# Test sensor types - first item only
|
||||
sensor:
|
||||
- platform: panasonic_heatpump
|
||||
top1:
|
||||
name: "Pump Flow"
|
||||
|
||||
# Test binary sensors - first item only
|
||||
binary_sensor:
|
||||
- platform: panasonic_heatpump
|
||||
top0:
|
||||
name: "Heatpump State"
|
||||
|
||||
# Test text sensors - first item only
|
||||
text_sensor:
|
||||
- platform: panasonic_heatpump
|
||||
top4:
|
||||
name: "Operating Mode State"
|
||||
|
||||
# Test number controls - first item only
|
||||
number:
|
||||
- platform: panasonic_heatpump
|
||||
set5:
|
||||
name: "Set Z1 Heat Request Temperature"
|
||||
|
||||
# Test select controls - first item only
|
||||
select:
|
||||
- platform: panasonic_heatpump
|
||||
set2:
|
||||
name: "Set Holiday Mode"
|
||||
|
||||
# Test switch controls - first item only
|
||||
switch:
|
||||
- platform: panasonic_heatpump
|
||||
set1:
|
||||
name: "Set Heatpump"
|
||||
|
||||
# Test climate controls - first item only
|
||||
climate:
|
||||
- platform: panasonic_heatpump
|
||||
tank:
|
||||
name: "DHW"
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
---
|
||||
# Test configuration for panasonic_heatpump component on ESP32-C3
|
||||
# ESP32-C3 is a compact chip with limited GPIO pins
|
||||
|
||||
esp32:
|
||||
board: esp32-c3-devkitm-1
|
||||
variant: esp32c3
|
||||
framework:
|
||||
type: esp-idf
|
||||
|
||||
esphome:
|
||||
name: test-panasonic-heatpump-esp32c3
|
||||
friendly_name: "Test Panasonic Heatpump ESP32-C3"
|
||||
|
||||
logger:
|
||||
level: DEBUG
|
||||
|
||||
external_components:
|
||||
- source:
|
||||
type: local
|
||||
path: ../../components
|
||||
components: [panasonic_heatpump]
|
||||
|
||||
uart:
|
||||
- id: uart_heatpump
|
||||
tx_pin: GPIO4
|
||||
rx_pin: GPIO5
|
||||
baud_rate: 9600
|
||||
data_bits: 8
|
||||
parity: EVEN
|
||||
stop_bits: 1
|
||||
|
||||
# Test basic configuration
|
||||
panasonic_heatpump:
|
||||
id: my_heatpump
|
||||
uart_id: uart_heatpump
|
||||
|
||||
# Test sensor types - first item only
|
||||
sensor:
|
||||
- platform: panasonic_heatpump
|
||||
top1:
|
||||
name: "Pump Flow"
|
||||
|
||||
# Test binary sensors - first item only
|
||||
binary_sensor:
|
||||
- platform: panasonic_heatpump
|
||||
top0:
|
||||
name: "Heatpump State"
|
||||
|
||||
# Test text sensors - first item only
|
||||
text_sensor:
|
||||
- platform: panasonic_heatpump
|
||||
top4:
|
||||
name: "Operating Mode State"
|
||||
|
||||
# Test number controls - first item only
|
||||
number:
|
||||
- platform: panasonic_heatpump
|
||||
set5:
|
||||
name: "Set Z1 Heat Request Temperature"
|
||||
|
||||
# Test select controls - first item only
|
||||
select:
|
||||
- platform: panasonic_heatpump
|
||||
set2:
|
||||
name: "Set Holiday Mode"
|
||||
|
||||
# Test switch controls - first item only
|
||||
switch:
|
||||
- platform: panasonic_heatpump
|
||||
set1:
|
||||
name: "Set Heatpump"
|
||||
|
||||
# Test climate controls - first item only
|
||||
climate:
|
||||
- platform: panasonic_heatpump
|
||||
tank:
|
||||
name: "DHW"
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
---
|
||||
# Test configuration for panasonic_heatpump component on ESP32-S2
|
||||
# ESP32-S2 has GPIO pins but limited compared to ESP32
|
||||
|
||||
esp32:
|
||||
board: lolin_s2_mini
|
||||
variant: esp32s2
|
||||
framework:
|
||||
type: esp-idf
|
||||
|
||||
esphome:
|
||||
name: test-panasonic-heatpump-esp32s2
|
||||
friendly_name: "Test Panasonic Heatpump ESP32-S2"
|
||||
|
||||
logger:
|
||||
level: DEBUG
|
||||
|
||||
external_components:
|
||||
- source:
|
||||
type: local
|
||||
path: ../../components
|
||||
components: [panasonic_heatpump]
|
||||
|
||||
uart:
|
||||
- id: uart_heatpump
|
||||
tx_pin: GPIO39
|
||||
rx_pin: GPIO37
|
||||
baud_rate: 9600
|
||||
data_bits: 8
|
||||
parity: EVEN
|
||||
stop_bits: 1
|
||||
|
||||
# Test basic configuration
|
||||
panasonic_heatpump:
|
||||
id: my_heatpump
|
||||
uart_id: uart_heatpump
|
||||
|
||||
# Test sensor types - first item only
|
||||
sensor:
|
||||
- platform: panasonic_heatpump
|
||||
top1:
|
||||
name: "Pump Flow"
|
||||
|
||||
# Test binary sensors - first item only
|
||||
binary_sensor:
|
||||
- platform: panasonic_heatpump
|
||||
top0:
|
||||
name: "Heatpump State"
|
||||
|
||||
# Test text sensors - first item only
|
||||
text_sensor:
|
||||
- platform: panasonic_heatpump
|
||||
top4:
|
||||
name: "Operating Mode State"
|
||||
|
||||
# Test number controls - first item only
|
||||
number:
|
||||
- platform: panasonic_heatpump
|
||||
set5:
|
||||
name: "Set Z1 Heat Request Temperature"
|
||||
|
||||
# Test select controls - first item only
|
||||
select:
|
||||
- platform: panasonic_heatpump
|
||||
set2:
|
||||
name: "Set Holiday Mode"
|
||||
|
||||
# Test switch controls - first item only
|
||||
switch:
|
||||
- platform: panasonic_heatpump
|
||||
set1:
|
||||
name: "Set Heatpump"
|
||||
|
||||
# Test climate controls - first item only
|
||||
climate:
|
||||
- platform: panasonic_heatpump
|
||||
tank:
|
||||
name: "DHW"
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
---
|
||||
# Test configuration for panasonic_heatpump component on ESP8266
|
||||
# ESP8266 has limited GPIO pins and only one UART
|
||||
|
||||
esp8266:
|
||||
board: d1_mini
|
||||
|
||||
esphome:
|
||||
name: test-panasonic-heatpump-esp8266
|
||||
friendly_name: "Test Panasonic Heatpump ESP8266"
|
||||
|
||||
logger:
|
||||
level: DEBUG
|
||||
|
||||
external_components:
|
||||
- source:
|
||||
type: local
|
||||
path: ../../components
|
||||
components: [panasonic_heatpump]
|
||||
|
||||
uart:
|
||||
- id: uart_heatpump
|
||||
tx_pin: GPIO13
|
||||
rx_pin: GPIO15
|
||||
baud_rate: 9600
|
||||
data_bits: 8
|
||||
parity: EVEN
|
||||
stop_bits: 1
|
||||
|
||||
# Test basic configuration
|
||||
panasonic_heatpump:
|
||||
id: my_heatpump
|
||||
uart_id: uart_heatpump
|
||||
|
||||
# Test sensor types - first item only
|
||||
sensor:
|
||||
- platform: panasonic_heatpump
|
||||
top1:
|
||||
name: "Pump Flow"
|
||||
|
||||
# Test binary sensors - first item only
|
||||
binary_sensor:
|
||||
- platform: panasonic_heatpump
|
||||
top0:
|
||||
name: "Heatpump State"
|
||||
|
||||
# Test text sensors - first item only
|
||||
text_sensor:
|
||||
- platform: panasonic_heatpump
|
||||
top4:
|
||||
name: "Operating Mode State"
|
||||
|
||||
# Test number controls - first item only
|
||||
number:
|
||||
- platform: panasonic_heatpump
|
||||
set5:
|
||||
name: "Set Z1 Heat Request Temperature"
|
||||
|
||||
# Test select controls - first item only
|
||||
select:
|
||||
- platform: panasonic_heatpump
|
||||
set2:
|
||||
name: "Set Holiday Mode"
|
||||
|
||||
# Test switch controls - first item only
|
||||
switch:
|
||||
- platform: panasonic_heatpump
|
||||
set1:
|
||||
name: "Set Heatpump"
|
||||
|
||||
# Test climate controls - first item only
|
||||
climate:
|
||||
- platform: panasonic_heatpump
|
||||
tank:
|
||||
name: "DHW"
|
||||
|
|
@ -0,0 +1,480 @@
|
|||
---
|
||||
# Test configuration for panasonic_heatpump component
|
||||
# This file validates all component features and configurations
|
||||
|
||||
esp32:
|
||||
board: esp32dev
|
||||
framework:
|
||||
type: esp-idf
|
||||
|
||||
esphome:
|
||||
name: test-panasonic-heatpump-full
|
||||
friendly_name: "Test Panasonic Heatpump Full"
|
||||
|
||||
logger:
|
||||
level: DEBUG
|
||||
|
||||
external_components:
|
||||
- source:
|
||||
type: local
|
||||
path: ../../components
|
||||
components: [panasonic_heatpump]
|
||||
|
||||
uart:
|
||||
- id: uart_heatpump
|
||||
tx_pin: GPIO16
|
||||
rx_pin: GPIO17
|
||||
baud_rate: 9600
|
||||
data_bits: 8
|
||||
parity: EVEN
|
||||
stop_bits: 1
|
||||
- id: uart_cz_taw1
|
||||
tx_pin: GPIO19
|
||||
rx_pin: GPIO18
|
||||
baud_rate: 9600
|
||||
data_bits: 8
|
||||
parity: EVEN
|
||||
stop_bits: 1
|
||||
|
||||
# Test basic configuration
|
||||
panasonic_heatpump:
|
||||
id: my_heatpump
|
||||
uart_id: uart_heatpump
|
||||
uart_client_id: uart_cz_taw1
|
||||
log_uart_msg: true
|
||||
update_interval: 3s
|
||||
|
||||
# Test all sensor types
|
||||
sensor:
|
||||
- platform: panasonic_heatpump
|
||||
top1:
|
||||
name: "Pump Flow"
|
||||
top5:
|
||||
name: "Main Inlet Temp"
|
||||
top6:
|
||||
name: "Main Outlet Temp"
|
||||
top7:
|
||||
name: "Main Target Temp"
|
||||
top8:
|
||||
name: "Compressor Freq"
|
||||
top9:
|
||||
name: "DHW Target Temp"
|
||||
top10:
|
||||
name: "DHW Temp"
|
||||
top11:
|
||||
name: "Operations Hours"
|
||||
top12:
|
||||
name: "Operations Counter"
|
||||
top14:
|
||||
name: "Outside Temp"
|
||||
top15:
|
||||
name: "Heat Power Production"
|
||||
top16:
|
||||
name: "Heat Power Consumption"
|
||||
id: heat_power_cons
|
||||
top21:
|
||||
name: "Outside Pipe Temp"
|
||||
top22:
|
||||
name: "DHW Heat Delta"
|
||||
top23:
|
||||
name: "Heat Delta"
|
||||
top24:
|
||||
name: "Cool Delta"
|
||||
top25:
|
||||
name: "DHW Holiday Shift Temp"
|
||||
top27:
|
||||
name: "Z1 Heat Request Temp"
|
||||
top28:
|
||||
name: "Z1 Cool Request Temp"
|
||||
top29:
|
||||
name: "Z1 Heat Curve Target High Temp"
|
||||
top30:
|
||||
name: "Z1 Heat Curve Target Low Temp"
|
||||
top31:
|
||||
name: "Z1 Heat Curve Outside High Temp"
|
||||
top32:
|
||||
name: "Z1 Heat Curve Outside Low Temp"
|
||||
top33:
|
||||
name: "Room Thermostat Temp"
|
||||
top34:
|
||||
name: "Z2 Heat Request Temp"
|
||||
top35:
|
||||
name: "Z2 Cool Request Temp"
|
||||
top36:
|
||||
name: "Z1 Water Temp"
|
||||
top37:
|
||||
name: "Z2 Water Temp"
|
||||
top38:
|
||||
name: "Cool Power Production"
|
||||
top39:
|
||||
name: "Cool Power Consumption"
|
||||
id: cool_power_cons
|
||||
top40:
|
||||
name: "DHW Power Production"
|
||||
top41:
|
||||
name: "DHW Power Consumption"
|
||||
id: dhw_power_cons
|
||||
top42:
|
||||
name: "Z1 Water Target Temp"
|
||||
top43:
|
||||
name: "Z2 Water Target Temp"
|
||||
top45:
|
||||
name: "Room Holiday Shift Temp"
|
||||
top46:
|
||||
name: "Buffer Temp"
|
||||
top47:
|
||||
name: "Solar Temp"
|
||||
top48:
|
||||
name: "Pool Temp"
|
||||
top49:
|
||||
name: "Main Hex Outlet Temp"
|
||||
top50:
|
||||
name: "Discharge Temp"
|
||||
top51:
|
||||
name: "Inside Pipe Temp"
|
||||
top52:
|
||||
name: "Defrost Temp"
|
||||
top53:
|
||||
name: "Eva Outlet Temp"
|
||||
top54:
|
||||
name: "Bypass Outlet Temp"
|
||||
top55:
|
||||
name: "Ipm Temp"
|
||||
top56:
|
||||
name: "Z1 Temp"
|
||||
top57:
|
||||
name: "Z2 Temp"
|
||||
top62:
|
||||
name: "Fan1 Motor Speed"
|
||||
top63:
|
||||
name: "Fan2 Motor Speed"
|
||||
top64:
|
||||
name: "High Pressure"
|
||||
top65:
|
||||
name: "Pump Speed"
|
||||
top66:
|
||||
name: "Low Pressure"
|
||||
top67:
|
||||
name: "Compressor Current"
|
||||
top70:
|
||||
name: "Sterilization Temp"
|
||||
top71:
|
||||
name: "Sterilization Max Time"
|
||||
top72:
|
||||
name: "Z1 Cool Curve Target High Temp"
|
||||
top73:
|
||||
name: "Z1 Cool Curve Target Low Temp"
|
||||
top74:
|
||||
name: "Z1 Cool Curve Outside High Temp"
|
||||
top75:
|
||||
name: "Z1 Cool Curve Outside Low Temp"
|
||||
top77:
|
||||
name: "Heating Off Outdoor Temp"
|
||||
top78:
|
||||
name: "Heater On Outdoor Temp"
|
||||
top79:
|
||||
name: "Heat To Cool Temp"
|
||||
top80:
|
||||
name: "Cool To Heat Temp"
|
||||
top82:
|
||||
name: "Z2 Heat Curve Target High Temp"
|
||||
top83:
|
||||
name: "Z2 Heat Curve Target Low Temp"
|
||||
top84:
|
||||
name: "Z2 Heat Curve Outside High Temp"
|
||||
top85:
|
||||
name: "Z2 Heat Curve Outside Low Temp"
|
||||
top86:
|
||||
name: "Z2 Cool Curve Target High Temp"
|
||||
top87:
|
||||
name: "Z2 Cool Curve Target Low Temp"
|
||||
top88:
|
||||
name: "Z2 Cool Curve Outside High Temp"
|
||||
top89:
|
||||
name: "Z2 Cool Curve Outside Low Temp"
|
||||
top90:
|
||||
name: "Room Heater Operations Hours"
|
||||
top91:
|
||||
name: "DHW Heater Operations Hours"
|
||||
top93:
|
||||
name: "Pump Duty"
|
||||
top95:
|
||||
name: "Max Pump Duty"
|
||||
top96:
|
||||
name: "Heater Delay Time"
|
||||
top97:
|
||||
name: "Heater Start Delta"
|
||||
top98:
|
||||
name: "Heater Stop Delta"
|
||||
top102:
|
||||
name: "Solar On Delta"
|
||||
top103:
|
||||
name: "Solar Off Delta"
|
||||
top104:
|
||||
name: "Solar Frost Protection"
|
||||
top105:
|
||||
name: "Solar High Limit"
|
||||
top113:
|
||||
name: "Buffer Tank Delta"
|
||||
top115:
|
||||
name: "Water Pressure"
|
||||
top116:
|
||||
name: "Second Inlet Temp"
|
||||
top117:
|
||||
name: "Economizer Outlet Temp"
|
||||
top118:
|
||||
name: "Second Room Thermostat Temp"
|
||||
top127:
|
||||
name: "Z1 Valve PID"
|
||||
top128:
|
||||
name: "Z2 Valve PID"
|
||||
top131:
|
||||
name: "Bivalent Start Temperature"
|
||||
top134:
|
||||
name: "Bivalent Advanced Start Temp"
|
||||
top135:
|
||||
name: "Bivalent Advanced Stop Temp"
|
||||
top136:
|
||||
name: "Bivalent Advanced Start Delay"
|
||||
top137:
|
||||
name: "Bivalent Advanced Stop Delay"
|
||||
top138:
|
||||
name: "Bivalent Advanced DHW Delay"
|
||||
xtop0:
|
||||
name: "Heat Power Consumption Extra"
|
||||
xtop1:
|
||||
name: "Cool Power Consumption Extra"
|
||||
xtop2:
|
||||
name: "DHW Power Consumption Extra"
|
||||
xtop3:
|
||||
name: "Heat Power Production Extra"
|
||||
xtop4:
|
||||
name: "Cool Power Production Extra"
|
||||
xtop5:
|
||||
name: "DHW Power Production Extra"
|
||||
|
||||
# Test all binary sensors
|
||||
binary_sensor:
|
||||
- platform: panasonic_heatpump
|
||||
top0:
|
||||
name: "Heatpump State"
|
||||
top2:
|
||||
name: "Force DHW State"
|
||||
top3:
|
||||
name: "Quiet Mode Schedule"
|
||||
top13:
|
||||
name: "Main Schedule State"
|
||||
top26:
|
||||
name: "Defrosting State"
|
||||
top60:
|
||||
name: "Internal Heater State"
|
||||
top61:
|
||||
name: "External Heater State"
|
||||
top68:
|
||||
name: "Force Heater State"
|
||||
top69:
|
||||
name: "Sterilization State"
|
||||
top99:
|
||||
name: "Buffer Installed"
|
||||
top100:
|
||||
name: "DHW Installed"
|
||||
top108:
|
||||
name: "Alt External Sensor"
|
||||
top109:
|
||||
name: "Anti Freeze Mode"
|
||||
top110:
|
||||
name: "Optional PCB"
|
||||
top119:
|
||||
name: "External Control"
|
||||
top120:
|
||||
name: "External Heat Cool Control"
|
||||
top121:
|
||||
name: "External Error Signal"
|
||||
top122:
|
||||
name: "External Compressor Control"
|
||||
top123:
|
||||
name: "Z2 Pump State"
|
||||
top124:
|
||||
name: "Z1 Pump State"
|
||||
top129:
|
||||
name: "Bivalent Control"
|
||||
top132:
|
||||
name: "Bivalent Advanced Heat"
|
||||
top133:
|
||||
name: "Bivalent Advanced DHW"
|
||||
|
||||
# Test all text sensors
|
||||
text_sensor:
|
||||
- platform: panasonic_heatpump
|
||||
top4:
|
||||
name: "Operating Mode State"
|
||||
top17:
|
||||
name: "Powerful Mode Time"
|
||||
top18:
|
||||
name: "Quiet Mode Level"
|
||||
top19:
|
||||
name: "Holiday Mode State"
|
||||
top20:
|
||||
name: "ThreeWay Valve State"
|
||||
top44:
|
||||
name: "Error"
|
||||
top58:
|
||||
name: "DHW Heater State"
|
||||
top59:
|
||||
name: "Room Heater State"
|
||||
top76:
|
||||
name: "Heating Mode"
|
||||
top81:
|
||||
name: "Cooling Mode"
|
||||
top92:
|
||||
name: "Heat Pump Model"
|
||||
top94:
|
||||
name: "Zones State"
|
||||
top101:
|
||||
name: "Solar Mode"
|
||||
top106:
|
||||
name: "Pump Flowrate Mode"
|
||||
top107:
|
||||
name: "Liquid Type"
|
||||
top111:
|
||||
name: "Z1 Sensor Settings"
|
||||
top112:
|
||||
name: "Z2 Sensor Settings"
|
||||
top114:
|
||||
name: "External Pad Heater"
|
||||
top125:
|
||||
name: "TwoWay Valve State"
|
||||
top126:
|
||||
name: "ThreeWay Valve State2"
|
||||
top130:
|
||||
name: "Bivalent Mode"
|
||||
|
||||
# Test all number controls
|
||||
number:
|
||||
- platform: panasonic_heatpump
|
||||
set5:
|
||||
name: "Set Z1 Heat Request Temperature"
|
||||
set6:
|
||||
name: "Set Z1 Cool Request Temperature"
|
||||
set7:
|
||||
name: "Set Z2 Heat Request Temperature"
|
||||
set8:
|
||||
name: "Set Z2 Cool Request Temperature"
|
||||
set11:
|
||||
name: "Set DHW Temperature"
|
||||
set15:
|
||||
name: "Set Max Pump Duty"
|
||||
set16_01:
|
||||
name: "Set Zone1 Heat Target High"
|
||||
set16_02:
|
||||
name: "Set Zone1 Heat Target Low"
|
||||
set16_03:
|
||||
name: "Set Zone1 Heat Outside Low"
|
||||
set16_04:
|
||||
name: "Set Zone1 Heat Outside High"
|
||||
set16_05:
|
||||
name: "Set Zone2 Heat Target High"
|
||||
set16_06:
|
||||
name: "Set Zone2 Heat Target Low"
|
||||
set16_07:
|
||||
name: "Set Zone2 Heat Outside Low"
|
||||
set16_08:
|
||||
name: "Set Zone2 Heat Outside High"
|
||||
set16_09:
|
||||
name: "Set Zone1 Cool Target High"
|
||||
set16_10:
|
||||
name: "Set Zone1 Cool Target Low"
|
||||
set16_11:
|
||||
name: "Set Zone1 Cool Outside Low"
|
||||
set16_12:
|
||||
name: "Set Zone1 Cool Outside High"
|
||||
set16_13:
|
||||
name: "Set Zone2 Cool Target High"
|
||||
set16_14:
|
||||
name: "Set Zone2 Cool Target Low"
|
||||
set16_15:
|
||||
name: "Set Zone2 Cool Outside Low"
|
||||
set16_16:
|
||||
name: "Set Zone2 Cool Outside High"
|
||||
set18:
|
||||
name: "Set Floor Heat Delta"
|
||||
set19:
|
||||
name: "Set Floor Cool Delta"
|
||||
set20:
|
||||
name: "Set DHW Heat Delta"
|
||||
set21:
|
||||
name: "Set Heater Delay Time"
|
||||
set22:
|
||||
name: "Set Heater Start Delta"
|
||||
set23:
|
||||
name: "Set Heater Stop Delta"
|
||||
set27:
|
||||
name: "Set Buffer Delta"
|
||||
set29:
|
||||
name: "Set Heating Off Outdoor Temp"
|
||||
set36:
|
||||
name: "Set Bivalent Start Temp"
|
||||
set37:
|
||||
name: "Set Bivalent AP Start Temp"
|
||||
set38:
|
||||
name: "Set Bivalent AP Stop Temp"
|
||||
|
||||
# Test all select controls
|
||||
select:
|
||||
- platform: panasonic_heatpump
|
||||
cool_mode: true
|
||||
set2:
|
||||
name: "Set Holiday Mode"
|
||||
set3:
|
||||
name: "Set Quiet Mode"
|
||||
set4:
|
||||
name: "Set Powerful Mode"
|
||||
set9:
|
||||
name: "Set Operation Mode"
|
||||
set17:
|
||||
name: "Set Zones"
|
||||
set26:
|
||||
name: "Set External PadHeater"
|
||||
set35:
|
||||
name: "Set Bivalent Mode"
|
||||
|
||||
# Test all switch controls
|
||||
switch:
|
||||
- platform: panasonic_heatpump
|
||||
set1:
|
||||
name: "Set Heatpump"
|
||||
set10:
|
||||
name: "Set Force DHW"
|
||||
set12:
|
||||
name: "Set Force Defrost"
|
||||
set13:
|
||||
name: "Set Force Sterilization"
|
||||
set14:
|
||||
name: "Set Pump Max Speed"
|
||||
set24:
|
||||
name: "Set Main Schedule"
|
||||
set25:
|
||||
name: "Set Alt External Sensor"
|
||||
set28:
|
||||
name: "Set Buffer Installed"
|
||||
set30:
|
||||
name: "Set External Control"
|
||||
set31:
|
||||
name: "Set External Error"
|
||||
set32:
|
||||
name: "Set External Compressor Control"
|
||||
set33:
|
||||
name: "Set External Heat Cool Control"
|
||||
set34:
|
||||
name: "Set Bivalent Control"
|
||||
|
||||
# Test climate platform
|
||||
climate:
|
||||
- platform: panasonic_heatpump
|
||||
cool_mode: true
|
||||
tank:
|
||||
name: "DHW"
|
||||
zone1:
|
||||
name: "Zone1"
|
||||
zone2:
|
||||
name: "Zone2"
|
||||
|
|
@ -0,0 +1,136 @@
|
|||
"""
|
||||
Integration tests for panasonic_heatpump component.
|
||||
|
||||
Tests the component's behavior with actual ESPHome compilation.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
import subprocess
|
||||
import os
|
||||
|
||||
|
||||
class TestPanasonicHeatpumpIntegration:
|
||||
"""Integration tests using ESPHome CLI."""
|
||||
|
||||
@pytest.fixture
|
||||
def test_yaml_esp8266(self):
|
||||
"""Get the path to the ESP8266 test YAML file."""
|
||||
base_dir = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
|
||||
return os.path.join(base_dir, 'tests', 'panasonic_heatpump', 'test_panasonic_heatpump_esp8266.yaml')
|
||||
|
||||
@pytest.fixture
|
||||
def test_yaml_esp32(self):
|
||||
"""Get the path to the ESP32 test YAML file."""
|
||||
base_dir = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
|
||||
return os.path.join(base_dir, 'tests', 'panasonic_heatpump', 'test_panasonic_heatpump_full.yaml')
|
||||
|
||||
@pytest.fixture
|
||||
def test_yaml_esp32s2(self):
|
||||
"""Get the path to the ESP32-S2 test YAML file."""
|
||||
base_dir = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
|
||||
return os.path.join(base_dir, 'tests', 'panasonic_heatpump', 'test_panasonic_heatpump_esp32s2.yaml')
|
||||
|
||||
@pytest.fixture
|
||||
def test_yaml_esp32c3(self):
|
||||
"""Get the path to the ESP32-C3 test YAML file."""
|
||||
base_dir = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
|
||||
return os.path.join(base_dir, 'tests', 'panasonic_heatpump', 'test_panasonic_heatpump_esp32c3.yaml')
|
||||
|
||||
@pytest.fixture
|
||||
def test_yaml_cztaw1(self):
|
||||
"""Get the path to the CZ-TAW1 client test YAML file."""
|
||||
base_dir = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
|
||||
return os.path.join(base_dir, 'tests', 'panasonic_heatpump', 'test_panasonic_heatpump_cztaw1.yaml')
|
||||
|
||||
def test_validate_esp8266_config(self, test_yaml_esp8266):
|
||||
"""Test that the ESP8266 configuration is valid."""
|
||||
if not os.path.exists(test_yaml_esp8266):
|
||||
pytest.skip(f"Test file not found: {test_yaml_esp8266}")
|
||||
|
||||
try:
|
||||
result = subprocess.run(
|
||||
['esphome', 'config', test_yaml_esp8266],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=120
|
||||
)
|
||||
assert result.returncode == 0, f"ESP8266 config validation failed: {result.stderr}"
|
||||
except FileNotFoundError:
|
||||
pytest.skip("ESPHome not installed")
|
||||
except subprocess.TimeoutExpired:
|
||||
pytest.fail("ESPHome config validation timed out")
|
||||
|
||||
def test_validate_esp32_config(self, test_yaml_esp32):
|
||||
"""Test that the ESP32 configuration is valid."""
|
||||
if not os.path.exists(test_yaml_esp32):
|
||||
pytest.skip(f"Test file not found: {test_yaml_esp32}")
|
||||
|
||||
try:
|
||||
result = subprocess.run(
|
||||
['esphome', 'config', test_yaml_esp32],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=120
|
||||
)
|
||||
assert result.returncode == 0, f"ESP32 config validation failed: {result.stderr}"
|
||||
except FileNotFoundError:
|
||||
pytest.skip("ESPHome not installed")
|
||||
except subprocess.TimeoutExpired:
|
||||
pytest.fail("ESPHome config validation timed out")
|
||||
|
||||
def test_validate_esp32s2_config(self, test_yaml_esp32s2):
|
||||
"""Test that the ESP32-S2 configuration is valid."""
|
||||
if not os.path.exists(test_yaml_esp32s2):
|
||||
pytest.skip(f"Test file not found: {test_yaml_esp32s2}")
|
||||
|
||||
try:
|
||||
result = subprocess.run(
|
||||
['esphome', 'config', test_yaml_esp32s2],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=120
|
||||
)
|
||||
assert result.returncode == 0, f"ESP32-S2 config validation failed: {result.stderr}"
|
||||
except FileNotFoundError:
|
||||
pytest.skip("ESPHome not installed")
|
||||
except subprocess.TimeoutExpired:
|
||||
pytest.fail("ESPHome config validation timed out")
|
||||
|
||||
def test_validate_esp32c3_config(self, test_yaml_esp32c3):
|
||||
"""Test that the ESP32-C3 configuration is valid."""
|
||||
if not os.path.exists(test_yaml_esp32c3):
|
||||
pytest.skip(f"Test file not found: {test_yaml_esp32c3}")
|
||||
|
||||
try:
|
||||
result = subprocess.run(
|
||||
['esphome', 'config', test_yaml_esp32c3],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=120
|
||||
)
|
||||
assert result.returncode == 0, f"ESP32-C3 config validation failed: {result.stderr}"
|
||||
except FileNotFoundError:
|
||||
pytest.skip("ESPHome not installed")
|
||||
except subprocess.TimeoutExpired:
|
||||
pytest.fail("ESPHome config validation timed out")
|
||||
|
||||
def test_validate_cztaw1_config(self, test_yaml_cztaw1):
|
||||
"""Test that the CZ-TAW1 client configuration with UART-proxy is valid."""
|
||||
if not os.path.exists(test_yaml_cztaw1):
|
||||
pytest.skip(f"Test file not found: {test_yaml_cztaw1}")
|
||||
|
||||
try:
|
||||
result = subprocess.run(
|
||||
['esphome', 'config', test_yaml_cztaw1],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=120
|
||||
)
|
||||
assert result.returncode == 0, f"CZ-TAW1 config validation failed: {result.stderr}"
|
||||
except FileNotFoundError:
|
||||
pytest.skip("ESPHome not installed")
|
||||
except subprocess.TimeoutExpired:
|
||||
pytest.fail("ESPHome config validation timed out")
|
||||
|
||||
if __name__ == '__main__':
|
||||
pytest.main([__file__, '-v'])
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
---
|
||||
# Test configuration for panasonic_heatpump component - minimal configuration
|
||||
# Tests basic component functionality with minimal required settings
|
||||
|
||||
esp32:
|
||||
board: esp32dev
|
||||
framework:
|
||||
type: esp-idf
|
||||
|
||||
esphome:
|
||||
name: test-panasonic-heatpump-mini
|
||||
friendly_name: "Test Panasonic Heatpump Minimal"
|
||||
|
||||
logger:
|
||||
level: DEBUG
|
||||
|
||||
external_components:
|
||||
- source:
|
||||
type: local
|
||||
path: ../../components
|
||||
components: [panasonic_heatpump]
|
||||
|
||||
uart:
|
||||
- id: uart_heatpump
|
||||
tx_pin: GPIO16
|
||||
rx_pin: GPIO17
|
||||
baud_rate: 9600
|
||||
data_bits: 8
|
||||
parity: EVEN
|
||||
stop_bits: 1
|
||||
|
||||
# Test minimal configuration
|
||||
panasonic_heatpump:
|
||||
id: my_heatpump
|
||||
|
|
@ -0,0 +1,344 @@
|
|||
"""
|
||||
Unit tests for panasonic_heatpump component configuration validation.
|
||||
|
||||
Tests the Python configuration schema and validation logic.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
from unittest.mock import Mock, MagicMock, patch
|
||||
import esphome.config_validation as cv
|
||||
from esphome.core import CORE
|
||||
|
||||
|
||||
class TestPanasonicHeatpumpConfig:
|
||||
"""Test suite for panasonic_heatpump configuration validation."""
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def setup(self):
|
||||
"""Setup test fixtures."""
|
||||
# Mock CORE to avoid ESPHome initialization issues
|
||||
CORE.data = {}
|
||||
yield
|
||||
|
||||
@pytest.fixture
|
||||
def mock_uart(self):
|
||||
"""Mock UART component."""
|
||||
with patch('esphome.components.uart') as mock:
|
||||
yield mock
|
||||
|
||||
@pytest.fixture
|
||||
def mock_cg(self):
|
||||
"""Mock code generator."""
|
||||
with patch('esphome.codegen') as mock:
|
||||
mock.esphome_ns = MagicMock()
|
||||
mock.esphome_ns.namespace.return_value.class_ = MagicMock()
|
||||
yield mock
|
||||
|
||||
def test_import_component(self):
|
||||
"""Test that the component can be imported."""
|
||||
try:
|
||||
import sys
|
||||
import os
|
||||
# Add components directory to path
|
||||
components_path = os.path.join(
|
||||
os.path.dirname(__file__), '..', '..', 'components'
|
||||
)
|
||||
sys.path.insert(0, components_path)
|
||||
|
||||
import panasonic_heatpump as ph_init
|
||||
assert ph_init is not None
|
||||
except ImportError as e:
|
||||
pytest.fail(f"Failed to import panasonic_heatpump: {e}")
|
||||
|
||||
def test_component_metadata(self):
|
||||
"""Test component metadata is correctly defined."""
|
||||
import sys
|
||||
import os
|
||||
components_path = os.path.join(
|
||||
os.path.dirname(__file__), '..', '..', 'components'
|
||||
)
|
||||
sys.path.insert(0, components_path)
|
||||
|
||||
import panasonic_heatpump as ph_init
|
||||
|
||||
assert hasattr(ph_init, 'CODEOWNERS')
|
||||
assert ph_init.CODEOWNERS == ['@elvit']
|
||||
|
||||
assert hasattr(ph_init, 'MULTICONF')
|
||||
assert ph_init.MULTICONF is True
|
||||
|
||||
assert hasattr(ph_init, 'DEPENDENCIES')
|
||||
assert 'uart' in ph_init.DEPENDENCIES
|
||||
|
||||
def test_config_constants(self):
|
||||
"""Test that configuration constants are defined."""
|
||||
import sys
|
||||
import os
|
||||
components_path = os.path.join(
|
||||
os.path.dirname(__file__), '..', '..', 'components'
|
||||
)
|
||||
sys.path.insert(0, components_path)
|
||||
|
||||
import panasonic_heatpump as ph_init
|
||||
|
||||
assert hasattr(ph_init, 'CONF_PANASONIC_HEATPUMP_ID')
|
||||
assert ph_init.CONF_PANASONIC_HEATPUMP_ID == "panasonic_heatpump"
|
||||
|
||||
assert hasattr(ph_init, 'CONF_UART_CLIENT')
|
||||
assert ph_init.CONF_UART_CLIENT == "uart_client_id"
|
||||
|
||||
assert hasattr(ph_init, 'CONF_LOG_UART_MSG')
|
||||
assert ph_init.CONF_LOG_UART_MSG == "log_uart_msg"
|
||||
|
||||
@patch('esphome.components.uart')
|
||||
@patch('esphome.codegen')
|
||||
def test_config_schema_structure(self, mock_cg, mock_uart):
|
||||
"""Test that CONFIG_SCHEMA has the correct structure."""
|
||||
import sys
|
||||
import os
|
||||
components_path = os.path.join(
|
||||
os.path.dirname(__file__), '..', '..', 'components'
|
||||
)
|
||||
sys.path.insert(0, components_path)
|
||||
|
||||
import panasonic_heatpump as ph_init
|
||||
|
||||
assert hasattr(ph_init, 'CONFIG_SCHEMA')
|
||||
assert ph_init.CONFIG_SCHEMA is not None
|
||||
|
||||
def test_valid_minimal_config(self):
|
||||
"""Test validation of minimal valid configuration."""
|
||||
config = {
|
||||
'id': 'my_heatpump',
|
||||
'uart_id': 'uart_bus',
|
||||
}
|
||||
# This would require full ESPHome environment to validate
|
||||
# Just verify the config structure is reasonable
|
||||
assert 'id' in config
|
||||
assert 'uart_id' in config
|
||||
|
||||
def test_valid_full_config(self):
|
||||
"""Test validation of full configuration with all options."""
|
||||
config = {
|
||||
'id': 'my_heatpump',
|
||||
'uart_id': 'uart_bus',
|
||||
'uart_client_id': 'uart_client',
|
||||
'log_uart_msg': True,
|
||||
'update_interval': '3s',
|
||||
}
|
||||
assert 'id' in config
|
||||
assert 'uart_id' in config
|
||||
assert 'uart_client_id' in config
|
||||
assert 'log_uart_msg' in config
|
||||
assert 'update_interval' in config
|
||||
|
||||
def test_log_uart_msg_default(self):
|
||||
"""Test that log_uart_msg defaults to False."""
|
||||
import sys
|
||||
import os
|
||||
components_path = os.path.join(
|
||||
os.path.dirname(__file__), '..', '..', 'components'
|
||||
)
|
||||
sys.path.insert(0, components_path)
|
||||
|
||||
import panasonic_heatpump as ph_init
|
||||
|
||||
# The default is specified in the schema as False
|
||||
# This test verifies the constant exists
|
||||
assert ph_init.CONF_LOG_UART_MSG == "log_uart_msg"
|
||||
|
||||
def test_update_interval_default(self):
|
||||
"""Test that update_interval has a default value."""
|
||||
# The default update_interval should be 3s according to the example
|
||||
default_interval = "3s"
|
||||
assert default_interval == "3s"
|
||||
|
||||
def test_multiconf_support(self):
|
||||
"""Test that component supports multiple instances."""
|
||||
import sys
|
||||
import os
|
||||
components_path = os.path.join(
|
||||
os.path.dirname(__file__), '..', '..', 'components'
|
||||
)
|
||||
sys.path.insert(0, components_path)
|
||||
|
||||
import panasonic_heatpump as ph_init
|
||||
|
||||
# Verify MULTICONF is True, allowing multiple instances
|
||||
assert ph_init.MULTICONF is True
|
||||
|
||||
def test_uart_dependency(self):
|
||||
"""Test that UART is listed as a dependency."""
|
||||
import sys
|
||||
import os
|
||||
components_path = os.path.join(
|
||||
os.path.dirname(__file__), '..', '..', 'components'
|
||||
)
|
||||
sys.path.insert(0, components_path)
|
||||
|
||||
import panasonic_heatpump as ph_init
|
||||
|
||||
assert 'uart' in ph_init.DEPENDENCIES
|
||||
|
||||
def test_namespace_definition(self):
|
||||
"""Test that component namespace is correctly defined."""
|
||||
import sys
|
||||
import os
|
||||
components_path = os.path.join(
|
||||
os.path.dirname(__file__), '..', '..', 'components'
|
||||
)
|
||||
sys.path.insert(0, components_path)
|
||||
|
||||
import panasonic_heatpump as ph_init
|
||||
|
||||
# Verify namespace constant exists
|
||||
assert hasattr(ph_init, 'panasonic_heatpump_ns')
|
||||
|
||||
|
||||
class TestPanasonicHeatpumpPlatforms:
|
||||
"""Test suite for platform configurations."""
|
||||
|
||||
def test_sensor_platform_exists(self):
|
||||
"""Test that sensor platform can be imported."""
|
||||
try:
|
||||
import sys
|
||||
import os
|
||||
components_path = os.path.join(
|
||||
os.path.dirname(__file__), '..', '..', 'components'
|
||||
)
|
||||
sys.path.insert(0, components_path)
|
||||
|
||||
from panasonic_heatpump.sensor import __init__ as sensor_init
|
||||
assert sensor_init is not None
|
||||
except ImportError:
|
||||
pytest.skip("Sensor platform not accessible in test environment")
|
||||
|
||||
def test_binary_sensor_platform_exists(self):
|
||||
"""Test that binary_sensor platform can be imported."""
|
||||
try:
|
||||
import sys
|
||||
import os
|
||||
components_path = os.path.join(
|
||||
os.path.dirname(__file__), '..', '..', 'components'
|
||||
)
|
||||
sys.path.insert(0, components_path)
|
||||
|
||||
from panasonic_heatpump.binary_sensor import __init__ as bs_init
|
||||
assert bs_init is not None
|
||||
except ImportError:
|
||||
pytest.skip("Binary sensor platform not accessible in test environment")
|
||||
|
||||
def test_text_sensor_platform_exists(self):
|
||||
"""Test that text_sensor platform can be imported."""
|
||||
try:
|
||||
import sys
|
||||
import os
|
||||
components_path = os.path.join(
|
||||
os.path.dirname(__file__), '..', '..', 'components'
|
||||
)
|
||||
sys.path.insert(0, components_path)
|
||||
|
||||
from panasonic_heatpump.text_sensor import __init__ as ts_init
|
||||
assert ts_init is not None
|
||||
except ImportError:
|
||||
pytest.skip("Text sensor platform not accessible in test environment")
|
||||
|
||||
def test_number_platform_exists(self):
|
||||
"""Test that number platform can be imported."""
|
||||
try:
|
||||
import sys
|
||||
import os
|
||||
components_path = os.path.join(
|
||||
os.path.dirname(__file__), '..', '..', 'components'
|
||||
)
|
||||
sys.path.insert(0, components_path)
|
||||
|
||||
from panasonic_heatpump.number import __init__ as num_init
|
||||
assert num_init is not None
|
||||
except ImportError:
|
||||
pytest.skip("Number platform not accessible in test environment")
|
||||
|
||||
def test_select_platform_exists(self):
|
||||
"""Test that select platform can be imported."""
|
||||
try:
|
||||
import sys
|
||||
import os
|
||||
components_path = os.path.join(
|
||||
os.path.dirname(__file__), '..', '..', 'components'
|
||||
)
|
||||
sys.path.insert(0, components_path)
|
||||
|
||||
from panasonic_heatpump.select import __init__ as sel_init
|
||||
assert sel_init is not None
|
||||
except ImportError:
|
||||
pytest.skip("Select platform not accessible in test environment")
|
||||
|
||||
def test_switch_platform_exists(self):
|
||||
"""Test that switch platform can be imported."""
|
||||
try:
|
||||
import sys
|
||||
import os
|
||||
components_path = os.path.join(
|
||||
os.path.dirname(__file__), '..', '..', 'components'
|
||||
)
|
||||
sys.path.insert(0, components_path)
|
||||
|
||||
from panasonic_heatpump.switch import __init__ as sw_init
|
||||
assert sw_init is not None
|
||||
except ImportError:
|
||||
pytest.skip("Switch platform not accessible in test environment")
|
||||
|
||||
def test_climate_platform_exists(self):
|
||||
"""Test that climate platform can be imported."""
|
||||
try:
|
||||
import sys
|
||||
import os
|
||||
components_path = os.path.join(
|
||||
os.path.dirname(__file__), '..', '..', 'components'
|
||||
)
|
||||
sys.path.insert(0, components_path)
|
||||
|
||||
from panasonic_heatpump.climate import __init__ as clim_init
|
||||
assert clim_init is not None
|
||||
except ImportError:
|
||||
pytest.skip("Climate platform not accessible in test environment")
|
||||
|
||||
|
||||
class TestPanasonicHeatpumpCodeGeneration:
|
||||
"""Test suite for code generation logic."""
|
||||
|
||||
@pytest.fixture
|
||||
def mock_dependencies(self):
|
||||
"""Mock all ESPHome dependencies."""
|
||||
with patch('esphome.codegen') as mock_cg, \
|
||||
patch('esphome.components.uart') as mock_uart, \
|
||||
patch('esphome.config_validation'):
|
||||
|
||||
mock_cg.new_Pvariable = MagicMock(return_value=Mock())
|
||||
mock_cg.register_component = MagicMock()
|
||||
mock_uart.register_uart_device = MagicMock()
|
||||
mock_cg.get_variable = MagicMock(return_value=Mock())
|
||||
mock_cg.add = MagicMock()
|
||||
|
||||
yield {
|
||||
'cg': mock_cg,
|
||||
'uart': mock_uart,
|
||||
}
|
||||
|
||||
def test_to_code_function_exists(self):
|
||||
"""Test that to_code function is defined."""
|
||||
import sys
|
||||
import os
|
||||
components_path = os.path.join(
|
||||
os.path.dirname(__file__), '..', '..', 'components'
|
||||
)
|
||||
sys.path.insert(0, components_path)
|
||||
|
||||
import panasonic_heatpump as ph_init
|
||||
|
||||
assert hasattr(ph_init, 'to_code')
|
||||
assert callable(ph_init.to_code)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
pytest.main([__file__, '-v'])
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
# Requirements for testing panasonic_heatpump component
|
||||
pytest>=7.4.0
|
||||
pytest-cov>=4.1.0
|
||||
pytest-timeout>=2.1.0
|
||||
pyyaml>=6.0.1
|
||||
esphome>=2024.11.0
|
||||
Loading…
Reference in New Issue