mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 15:12:06 +00:00 
			
		
		
		
	Add KMeterISO component. (#5170)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
		
							
								
								
									
										0
									
								
								esphome/components/kmeteriso/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								esphome/components/kmeteriso/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										82
									
								
								esphome/components/kmeteriso/kmeteriso.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								esphome/components/kmeteriso/kmeteriso.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,82 @@ | |||||||
|  | #include "kmeteriso.h" | ||||||
|  | #include "esphome/core/hal.h" | ||||||
|  | #include "esphome/core/log.h" | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace kmeteriso { | ||||||
|  |  | ||||||
|  | static const char *const TAG = "kmeteriso.sensor"; | ||||||
|  |  | ||||||
|  | static const uint8_t KMETER_ERROR_STATUS_REG = 0x20; | ||||||
|  | static const uint8_t KMETER_TEMP_VAL_REG = 0x00; | ||||||
|  | static const uint8_t KMETER_INTERNAL_TEMP_VAL_REG = 0x10; | ||||||
|  | static const uint8_t KMETER_FIRMWARE_VERSION_REG = 0xFE; | ||||||
|  |  | ||||||
|  | void KMeterISOComponent::setup() { | ||||||
|  |   ESP_LOGCONFIG(TAG, "Setting up KMeterISO..."); | ||||||
|  |   this->error_code_ = NONE; | ||||||
|  |  | ||||||
|  |   // Mark as not failed before initializing. Some devices will turn off sensors to save on batteries | ||||||
|  |   // and when they come back on, the COMPONENT_STATE_FAILED bit must be unset on the component. | ||||||
|  |   if ((this->component_state_ & COMPONENT_STATE_MASK) == COMPONENT_STATE_FAILED) { | ||||||
|  |     this->component_state_ &= ~COMPONENT_STATE_MASK; | ||||||
|  |     this->component_state_ |= COMPONENT_STATE_CONSTRUCTION; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   auto err = this->bus_->writev(this->address_, nullptr, 0); | ||||||
|  |   if (err == esphome::i2c::ERROR_OK) { | ||||||
|  |     ESP_LOGCONFIG(TAG, "Could write to the address %d.", this->address_); | ||||||
|  |   } else { | ||||||
|  |     ESP_LOGCONFIG(TAG, "Could not write to the address %d.", this->address_); | ||||||
|  |     this->error_code_ = COMMUNICATION_FAILED; | ||||||
|  |     this->mark_failed(); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   uint8_t read_buf[4] = {1}; | ||||||
|  |   if (!this->read_bytes(KMETER_ERROR_STATUS_REG, read_buf, 1)) { | ||||||
|  |     ESP_LOGCONFIG(TAG, "Could not read from the device."); | ||||||
|  |     this->error_code_ = COMMUNICATION_FAILED; | ||||||
|  |     this->mark_failed(); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |   if (read_buf[0] != 0) { | ||||||
|  |     ESP_LOGCONFIG(TAG, "The device is not ready."); | ||||||
|  |     this->error_code_ = STATUS_FAILED; | ||||||
|  |     this->mark_failed(); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |   ESP_LOGCONFIG(TAG, "The device was successfully setup."); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | float KMeterISOComponent::get_setup_priority() const { return setup_priority::DATA; } | ||||||
|  |  | ||||||
|  | void KMeterISOComponent::update() { | ||||||
|  |   uint8_t read_buf[4]; | ||||||
|  |  | ||||||
|  |   if (this->temperature_sensor_ != nullptr) { | ||||||
|  |     if (!this->read_bytes(KMETER_TEMP_VAL_REG, read_buf, 4)) { | ||||||
|  |       ESP_LOGW(TAG, "Error reading temperature."); | ||||||
|  |     } else { | ||||||
|  |       int32_t temp = encode_uint32(read_buf[3], read_buf[2], read_buf[1], read_buf[0]); | ||||||
|  |       float temp_f = temp / 100.0; | ||||||
|  |       ESP_LOGV(TAG, "Got temperature=%.2f °C", temp_f); | ||||||
|  |       this->temperature_sensor_->publish_state(temp_f); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   if (this->internal_temperature_sensor_ != nullptr) { | ||||||
|  |     if (!this->read_bytes(KMETER_INTERNAL_TEMP_VAL_REG, read_buf, 4)) { | ||||||
|  |       ESP_LOGW(TAG, "Error reading internal temperature."); | ||||||
|  |       return; | ||||||
|  |     } else { | ||||||
|  |       int32_t internal_temp = encode_uint32(read_buf[3], read_buf[2], read_buf[1], read_buf[0]); | ||||||
|  |       float internal_temp_f = internal_temp / 100.0; | ||||||
|  |       ESP_LOGV(TAG, "Got internal temperature=%.2f °C", internal_temp_f); | ||||||
|  |       this->internal_temperature_sensor_->publish_state(internal_temp_f); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | }  // namespace kmeteriso | ||||||
|  | }  // namespace esphome | ||||||
							
								
								
									
										34
									
								
								esphome/components/kmeteriso/kmeteriso.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								esphome/components/kmeteriso/kmeteriso.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | |||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "esphome/core/component.h" | ||||||
|  | #include "esphome/components/sensor/sensor.h" | ||||||
|  | #include "esphome/components/i2c/i2c.h" | ||||||
|  | #include "esphome/components/i2c/i2c_bus.h" | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace kmeteriso { | ||||||
|  |  | ||||||
|  | /// This class implements support for the KMeterISO thermocouple sensor. | ||||||
|  | class KMeterISOComponent : public PollingComponent, public i2c::I2CDevice { | ||||||
|  |  public: | ||||||
|  |   void set_temperature_sensor(sensor::Sensor *t) { this->temperature_sensor_ = t; } | ||||||
|  |   void set_internal_temperature_sensor(sensor::Sensor *t) { this->internal_temperature_sensor_ = t; } | ||||||
|  |  | ||||||
|  |   // ========== INTERNAL METHODS ========== | ||||||
|  |   // (In most use cases you won't need these) | ||||||
|  |   void setup() override; | ||||||
|  |   float get_setup_priority() const override; | ||||||
|  |   void update() override; | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   sensor::Sensor *temperature_sensor_{nullptr}; | ||||||
|  |   sensor::Sensor *internal_temperature_sensor_{nullptr}; | ||||||
|  |   enum ErrorCode { | ||||||
|  |     NONE = 0, | ||||||
|  |     COMMUNICATION_FAILED, | ||||||
|  |     STATUS_FAILED, | ||||||
|  |   } error_code_{NONE}; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | }  // namespace kmeteriso | ||||||
|  | }  // namespace esphome | ||||||
							
								
								
									
										55
									
								
								esphome/components/kmeteriso/sensor.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								esphome/components/kmeteriso/sensor.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,55 @@ | |||||||
|  | import esphome.codegen as cg | ||||||
|  | import esphome.config_validation as cv | ||||||
|  | from esphome.components import i2c, sensor | ||||||
|  | from esphome.const import ( | ||||||
|  |     CONF_ID, | ||||||
|  |     CONF_TEMPERATURE, | ||||||
|  |     DEVICE_CLASS_TEMPERATURE, | ||||||
|  |     STATE_CLASS_MEASUREMENT, | ||||||
|  |     UNIT_CELSIUS, | ||||||
|  |     ENTITY_CATEGORY_DIAGNOSTIC, | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | CONF_INTERNAL_TEMPERATURE = "internal_temperature" | ||||||
|  | DEPENDENCIES = ["i2c"] | ||||||
|  |  | ||||||
|  | kmeteriso_ns = cg.esphome_ns.namespace("kmeteriso") | ||||||
|  |  | ||||||
|  | KMeterISOComponent = kmeteriso_ns.class_( | ||||||
|  |     "KMeterISOComponent", cg.PollingComponent, i2c.I2CDevice | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | CONFIG_SCHEMA = ( | ||||||
|  |     cv.Schema( | ||||||
|  |         { | ||||||
|  |             cv.GenerateID(): cv.declare_id(KMeterISOComponent), | ||||||
|  |             cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema( | ||||||
|  |                 unit_of_measurement=UNIT_CELSIUS, | ||||||
|  |                 accuracy_decimals=2, | ||||||
|  |                 device_class=DEVICE_CLASS_TEMPERATURE, | ||||||
|  |                 state_class=STATE_CLASS_MEASUREMENT, | ||||||
|  |             ), | ||||||
|  |             cv.Optional(CONF_INTERNAL_TEMPERATURE): sensor.sensor_schema( | ||||||
|  |                 unit_of_measurement=UNIT_CELSIUS, | ||||||
|  |                 device_class=DEVICE_CLASS_TEMPERATURE, | ||||||
|  |                 state_class=STATE_CLASS_MEASUREMENT, | ||||||
|  |                 entity_category=ENTITY_CATEGORY_DIAGNOSTIC, | ||||||
|  |             ), | ||||||
|  |         } | ||||||
|  |     ) | ||||||
|  |     .extend(cv.polling_component_schema("60s")) | ||||||
|  |     .extend(i2c.i2c_device_schema(0x66)) | ||||||
|  | ) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | async def to_code(config): | ||||||
|  |     var = cg.new_Pvariable(config[CONF_ID]) | ||||||
|  |     await cg.register_component(var, config) | ||||||
|  |     await i2c.register_i2c_device(var, config) | ||||||
|  |  | ||||||
|  |     if temperature_config := config.get(CONF_TEMPERATURE): | ||||||
|  |         sens = await sensor.new_sensor(temperature_config) | ||||||
|  |         cg.add(var.set_temperature_sensor(sens)) | ||||||
|  |     if internal_temperature_config := config.get(CONF_INTERNAL_TEMPERATURE): | ||||||
|  |         sens = await sensor.new_sensor(internal_temperature_config) | ||||||
|  |         cg.add(var.set_internal_temperature_sensor(sens)) | ||||||
| @@ -792,6 +792,13 @@ sensor: | |||||||
|         name: INA3221 Channel 1 Shunt Voltage |         name: INA3221 Channel 1 Shunt Voltage | ||||||
|     update_interval: 15s |     update_interval: 15s | ||||||
|     i2c_id: i2c_bus |     i2c_id: i2c_bus | ||||||
|  |   - platform: kmeteriso | ||||||
|  |     temperature: | ||||||
|  |       name: Outside Temperature | ||||||
|  |     internal_temperature: | ||||||
|  |       name: Internal Ttemperature | ||||||
|  |     update_interval: 15s | ||||||
|  |     i2c_id: i2c_bus | ||||||
|   - platform: kalman_combinator |   - platform: kalman_combinator | ||||||
|     name: Kalman-filtered temperature |     name: Kalman-filtered temperature | ||||||
|     process_std_dev: 0.00139 |     process_std_dev: 0.00139 | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user