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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 28 additions & 4 deletions components/danfoss_eco/climate.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import climate, ble_client, sensor, binary_sensor
from esphome.components import climate, ble_client, sensor, binary_sensor, text_sensor
from esphome.const import (
CONF_ID,
CONF_NAME,
CONF_ICON,

CONF_TEMPERATURE,
CONF_BATTERY_LEVEL,

CONF_VISUAL,
CONF_MIN_TEMPERATURE,
CONF_MAX_TEMPERATURE,

CONF_ENTITY_CATEGORY,
ENTITY_CATEGORY_DIAGNOSTIC,
Expand All @@ -24,11 +29,13 @@
CODEOWNERS = ["@dmitry-cherkas"]
DEPENDENCIES = ["ble_client"]
# load zero-configuration dependencies automatically
AUTO_LOAD = ["sensor", "binary_sensor", "esp32_ble_tracker"]
AUTO_LOAD = ["sensor", "binary_sensor", "text_sensor", "esp32_ble_tracker"]

CONF_PIN_CODE = 'pin_code'
CONF_SECRET_KEY = 'secret_key'
CONF_PROBLEMS = 'problems'
CONF_PROBLEMS_DETAIL = 'problems_detail'
CONF_PROBLEMS_DETAIL_DEFAULT_ICON = 'mdi:format-list-checks'

eco_ns = cg.esphome_ns.namespace("danfoss_eco")
DanfossEco = eco_ns.class_(
Expand All @@ -50,7 +57,7 @@ def validate_pin(value):
return value

CONFIG_SCHEMA = (
climate.CLIMATE_SCHEMA.extend(
climate.climate_schema(DanfossEco).extend(
{
cv.GenerateID(): cv.declare_id(DanfossEco),
cv.Optional(CONF_SECRET_KEY): validate_secret,
Expand All @@ -68,10 +75,24 @@ def validate_pin(value):
device_class=DEVICE_CLASS_TEMPERATURE,
state_class=STATE_CLASS_MEASUREMENT,
),
cv.Optional(CONF_PROBLEMS): binary_sensor.BINARY_SENSOR_SCHEMA.extend({
cv.Optional(CONF_VISUAL, default={
CONF_MIN_TEMPERATURE:10,
CONF_MAX_TEMPERATURE:30,
}): cv.Schema(
{
cv.Optional(CONF_MIN_TEMPERATURE): cv.temperature,
cv.Optional(CONF_MAX_TEMPERATURE): cv.temperature,
}
),
cv.Optional(CONF_PROBLEMS): binary_sensor.binary_sensor_schema().extend({
cv.Optional(CONF_NAME): cv.string,
cv.Optional(CONF_ENTITY_CATEGORY, default=ENTITY_CATEGORY_DIAGNOSTIC): cv.entity_category,
cv.Optional(CONF_DEVICE_CLASS, default=DEVICE_CLASS_PROBLEM): binary_sensor.validate_device_class
}),
cv.Optional(CONF_PROBLEMS_DETAIL): text_sensor.text_sensor_schema().extend({
cv.Optional(CONF_NAME): cv.string,
cv.Optional(CONF_ENTITY_CATEGORY, default=ENTITY_CATEGORY_DIAGNOSTIC): cv.entity_category,
cv.Optional(CONF_ICON, default=CONF_PROBLEMS_DETAIL_DEFAULT_ICON): cv.icon,
})
}
)
Expand All @@ -97,4 +118,7 @@ async def to_code(config):
if CONF_PROBLEMS in config:
b_sens = await binary_sensor.new_binary_sensor(config[CONF_PROBLEMS])
cg.add(var.set_problems(b_sens))
if CONF_PROBLEMS_DETAIL in config:
t_sens = await text_sensor.new_text_sensor(config[CONF_PROBLEMS_DETAIL])
cg.add(var.set_problems_detail(t_sens))

5 changes: 3 additions & 2 deletions components/danfoss_eco/command.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include "esphome/core/lock_free_queue.h"
#include "esphome/components/esp32_ble_tracker/esp32_ble_tracker.h"

#include "properties.h"
Expand Down Expand Up @@ -35,10 +36,10 @@ namespace esphome
}
};

class CommandQueue : public esphome::esp32_ble_tracker::Queue<Command>
class CommandQueue : public esphome::LockFreeQueue<Command, MAX_BLE_QUEUE_SIZE>
{
public:
bool is_empty() { return this->q_.empty(); }
bool is_empty() { return this->empty(); }
};

} // namespace danfoss_eco
Expand Down
4 changes: 3 additions & 1 deletion components/danfoss_eco/device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -220,9 +220,11 @@ namespace esphome
ESP_LOGD(TAG, "[%s] re-enabling ble_client", this->get_name().c_str());
parent()->set_enabled(true);
}

// gap scanning interferes with connection attempts, which results in esp_gatt_status_t::ESP_GATT_ERROR (0x85)
esp_ble_gap_stop_scanning();
this->parent()->set_state(ClientState::READY_TO_CONNECT); // this will cause ble_client to attempt connect() from its loop()

this->parent()->connect();
}

void Device::disconnect()
Expand Down
2 changes: 2 additions & 0 deletions components/danfoss_eco/device.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#ifdef USE_ESP32

#include <esp_gattc_api.h>
#include <set>

namespace esphome
{
Expand All @@ -34,6 +35,7 @@ namespace esphome
LOG_SENSOR("", "Battery Level", this->battery_level_);
LOG_SENSOR("", "Room Temperature", this->temperature_);
LOG_BINARY_SENSOR("", "Problems", this->problems_);
LOG_TEXT_SENSOR("", "Problems (Detail)", this->problems_detail_);
}

void setup() override;
Expand Down
2 changes: 1 addition & 1 deletion components/danfoss_eco/device_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ namespace esphome

struct WritableData : public DeviceData
{
WritableData(uint16_t l, shared_ptr<Xxtea> &xxtea) : DeviceData(8, xxtea) {}
WritableData(uint16_t l, shared_ptr<Xxtea> &xxtea) : DeviceData(l, xxtea) {}
virtual void pack(uint8_t *) = 0;
};

Expand Down
17 changes: 12 additions & 5 deletions components/danfoss_eco/my_component.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "esphome/core/component.h"
#include "esphome/components/sensor/sensor.h"
#include "esphome/components/binary_sensor/binary_sensor.h"
#include "esphome/components/text_sensor/text_sensor.h"
#include "esphome/components/climate/climate.h"

#include "helpers.h"
Expand All @@ -15,6 +16,7 @@ namespace esphome
using namespace esphome::climate;
using namespace esphome::sensor;
using namespace esphome::binary_sensor;
using namespace esphome::text_sensor;

class MyComponent : public Climate, public PollingComponent, public enable_shared_from_this<MyComponent>
{
Expand All @@ -24,30 +26,35 @@ namespace esphome
ClimateTraits traits() override
{
auto traits = ClimateTraits();
traits.set_supports_current_temperature(true);

traits.set_supported_modes(set<ClimateMode>({ClimateMode::CLIMATE_MODE_HEAT, ClimateMode::CLIMATE_MODE_AUTO}));
traits.set_visual_temperature_step(0.5);
// supports reporting current temperature
traits.add_feature_flags(CLIMATE_SUPPORTS_CURRENT_TEMPERATURE);
// supports reporting current action
traits.add_feature_flags(CLIMATE_SUPPORTS_ACTION);

traits.set_supports_current_temperature(true); // supports reporting current temperature
traits.set_supports_action(true); // supports reporting current action
traits.add_supported_mode(ClimateMode::CLIMATE_MODE_HEAT);
traits.add_supported_mode(ClimateMode::CLIMATE_MODE_AUTO);
traits.set_visual_temperature_step(0.5);
return traits;
}

void set_battery_level(Sensor *battery_level) { battery_level_ = battery_level; }
void set_temperature(Sensor *temperature) { temperature_ = temperature; }
void set_problems(BinarySensor *problems) { problems_ = problems; }
void set_problems_detail(TextSensor *problems_detail) { problems_detail_ = problems_detail; }

Sensor *battery_level() { return this->battery_level_; }
Sensor *temperature() { return this->temperature_; }
BinarySensor *problems() { return this->problems_; }
TextSensor *problems_detail() { return this->problems_detail_; }

virtual void set_secret_key(uint8_t *, bool) = 0;

protected:
Sensor *battery_level_{nullptr};
Sensor *temperature_{nullptr};
BinarySensor *problems_{nullptr};
TextSensor *problems_detail_{nullptr};
};

} // namespace danfoss_eco
Expand Down
35 changes: 34 additions & 1 deletion components/danfoss_eco/properties.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ namespace esphome
auto chr = client->get_characteristic(this->service_uuid, this->characteristic_uuid);
if (chr == nullptr)
{
ESP_LOGW(TAG, "[%s] characteristic uuid=%s not found", this->component_->get_name().c_str(), this->characteristic_uuid.to_string().c_str());
char characteristic_uuid_str[UUID_STR_LEN];
ESP_LOGW(TAG, "[%s] characteristic uuid=%s not found", this->component_->get_name().c_str(), this->characteristic_uuid.to_str(characteristic_uuid_str));
return false;
}

Expand Down Expand Up @@ -128,6 +129,38 @@ namespace esphome
// TODO: it would be great to add actual error code to binary_sensor state attributes, but I'm not sure how to achieve that
if (this->component_->problems() != nullptr)
this->component_->problems()->publish_state(e_data->E9_VALVE_DOES_NOT_CLOSE || e_data->E10_INVALID_TIME || e_data->E14_LOW_BATTERY || e_data->E15_VERY_LOW_BATTERY);

string problems = "";

if (e_data->E9_VALVE_DOES_NOT_CLOSE)
problems += "Valve Stuck";

if (e_data->E10_INVALID_TIME)
{
if (problems.size() > 0)
problems += " | ";

problems += "Invalid Time";
}

if (e_data->E14_LOW_BATTERY)
{
if (problems.size() > 0)
problems += " | ";

problems += "Low Battery";
}

if (e_data->E15_VERY_LOW_BATTERY)
{
if (problems.size() > 0)
problems += " | ";

problems += "Very Low Battery";
}

if (this->component_->problems_detail() != nullptr)
this->component_->problems_detail()->publish_state(problems);
}

bool SecretKeyProperty::init_handle(BLEClient *client)
Expand Down
58 changes: 58 additions & 0 deletions components/danfoss_eco/xxtea-lib.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// ---------------------------------------------------------------------------
// Created by Abhijit Bose (boseji) on 04/03/16.
// Copyright 2016 - Under creative commons license 3.0:
// Attribution-ShareAlike CC BY-SA
//
// This software is furnished "as is", without technical support, and with no
// warranty, express or implied, as to its usefulness for any purpose.
//
// Thread Safe: No
// Extendable: Yes
//
// @file xxtea-lib.h
//
// @brief
// Library to provide the XXTEA Encryption and Decryption Facility both for
// Raw input and Strings
//
// @attribution
// This is based on the prior work done by Alessandro Pasqualini
// http://github.com/alessandro1105/XXTEA-Arduino
//
// @version API 2.0.0 - Change in library name and some more documentation
// 1.2.0 - Added Travis CI & Fixed redundent code
// 1.1.0 - Updated the Size inputs and more standard Conversion
// for buffer between the uint32_t and uint8_t types
//
//
// @author boseji - salearj@hotmail.com
// ---------------------------------------------------------------------------

#ifndef _XXTEA_LIB_H_
#define _XXTEA_LIB_H_

#ifndef MAX_XXTEA_DATA8
// Maximum Size of Data Buffer in Bytes
#define MAX_XXTEA_DATA8 80
#endif

// Status Codes

//!< All is well
#define XXTEA_STATUS_SUCCESS 0
//!< Generic Error in failure to execute
#define XXTEA_STATUS_GENERAL_ERROR 1
//!< Errors in input parameters
#define XXTEA_STATUS_PARAMETER_ERROR 2
//!< Error in Size of either of the buffers
#define XXTEA_STATUS_SIZE_ERROR 3
//!< Error in word alignment of the buffer
#define XXTEA_STATUS_ALIGNMENT_ERROR 4

// Find size of Uint32 array from an input of Byte array size
#define UINT32CALCBYTE(X) ( ( ( X & 3 ) != 0 ) ? ((X >> 2) + 1) : (X >> 2) )

// Find size of Byte array from an input of Uint32 array size
#define BYTECALCUINT32(X) ( X << 2 )

#endif /* _XXTEA_LIB_H_ */
3 changes: 2 additions & 1 deletion components/danfoss_eco/xxtea.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include <cstring>
#include "xxtea.h"
#include <xxtea_core.h>
#include "xxtea_core.h"

int Xxtea::set_key(uint8_t *key, size_t len)
{
Expand Down
4 changes: 3 additions & 1 deletion components/danfoss_eco/xxtea.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#pragma once

#include <xxtea-lib.h>
#include <cstddef>
#include <cstdint>
#include "xxtea-lib.h"

// key Size is always fixed
#define MAX_XXTEA_KEY8 16
Expand Down
70 changes: 70 additions & 0 deletions components/danfoss_eco/xxtea_core.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// ---------------------------------------------------------------------------
// Created by Abhijit Bose (boseji) on 04/03/16.
// Copyright 2016 - Under creative commons license 3.0:
// Attribution-ShareAlike CC BY-SA
//
// This software is furnished "as is", without technical support, and with no
// warranty, express or implied, as to its usefulness for any purpose.
//
// Thread Safe: No
// Extendable: Yes
//
// @file xxtea_core.cpp
//
// @brief
// Library to provide the XXTEA Encryption and Decryption Facility both for
// Raw input and Strings
//
// @version API 2.0.0 - Program now In main to get included for RAW operations
// 1.2.1 - Fixed the Signed Arithmetic Problem
// 1.0.0 - Initial Version
//
//
// @author boseji - salearj@hotmail.com
// ---------------------------------------------------------------------------
#include "xxtea_core.h"

#define DELTA 0x9e3779b9
#define MX ((((z>>5)^(y<<2)) + ((y>>3)^(z<<4))) ^ ((sum^y) + (key[(p&3)^e] ^ z)))

void dtea_fn1(uint32_t *v, int32_t n, uint32_t const key[4])
{
uint32_t y, z, sum;
uint32_t p, rounds, e, an;
an = n;
if (n > 1)
{ // Coding Part
rounds = 6 + 52/an;
sum = 0;
z = v[an-1];
do {
sum += DELTA;
e = (sum >> 2) & 3;
for (p=0; p<an-1; p++)
{
y = v[p+1];
z = v[p] += MX;
}
y = v[0];
z = v[an-1] += MX;
} while (--rounds);
} // End of Encoding
else if (n < -1)
{ // Decoding Part
an = (uint32_t)-n;
rounds = 6 + 52/an;
sum = rounds*DELTA;
y = v[0];
do {
e = (sum >> 2) & 3;
for (p=an-1; p>0; p--)
{
z = v[p-1];
y = v[p] -= MX;
}
z = v[an-1];
y = v[0] -= MX;
sum -= DELTA;
} while (--rounds);
} // End of Decoding
}
Loading