Skip to content

Commit c1d639f

Browse files
author
Samuel Sieb
committed
add CSV serial sensor
1 parent d9af361 commit c1d639f

File tree

5 files changed

+133
-0
lines changed

5 files changed

+133
-0
lines changed

components/serial_csv/README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# A component that reads CSV values from the uart.
2+
3+
A configured uart is required.
4+
5+
Configure a list of sensors. The index is required, the rest is the standard sensor config.
6+
7+
Example:
8+
```yaml
9+
sensor:
10+
- platform: serial_csv
11+
uart_id: my_uart # optional
12+
sensors:
13+
- index: 0
14+
name: First value
15+
- index: 3
16+
name: Fourth value
17+
```
18+

components/serial_csv/__init__.py

Whitespace-only changes.

components/serial_csv/sensor.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import esphome.codegen as cg
2+
import esphome.config_validation as cv
3+
from esphome import automation
4+
from esphome.components import uart
5+
from esphome.components import sensor
6+
from esphome.const import CONF_ID, CONF_INDEX, CONF_SENSORS
7+
8+
CODEOWNERS = ["@ssieb"]
9+
10+
DEPENDENCIES = ['uart']
11+
12+
serial_ns = cg.esphome_ns.namespace('serial')
13+
14+
SerialCSV = serial_ns.class_('SerialCSV', cg.Component, sensor.Sensor, uart.UARTDevice)
15+
16+
17+
CONFIG_SCHEMA = uart.UART_DEVICE_SCHEMA.extend(
18+
{
19+
cv.GenerateID(): cv.declare_id(SerialCSV),
20+
cv.Required(CONF_SENSORS): cv.ensure_list(
21+
sensor.SENSOR_SCHEMA.extend(
22+
{
23+
cv.Required(CONF_INDEX): cv.positive_int,
24+
}
25+
)
26+
),
27+
}
28+
)
29+
30+
31+
async def to_code(config):
32+
var = cg.new_Pvariable(config[CONF_ID])
33+
await cg.register_component(var, config)
34+
await uart.register_uart_device(var, config)
35+
for conf in config[CONF_SENSORS]:
36+
sens = await sensor.new_sensor(conf)
37+
index = conf[CONF_INDEX]
38+
cg.add(var.add_sensor(index, sens))

components/serial_csv/serial_csv.cpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#include "serial_csv.h"
2+
#include "esphome/core/log.h"
3+
4+
namespace esphome {
5+
namespace serial {
6+
7+
static const char *TAG = "serial.csv";
8+
9+
void SerialCSV::loop() {
10+
while (this->available()) {
11+
uint8_t c;
12+
this->read_byte(&c);
13+
if (c == '\r')
14+
continue;
15+
if (c == '\n')
16+
this->parse_values_();
17+
else
18+
this->rx_message_.push_back(c);
19+
}
20+
}
21+
22+
void SerialCSV::parse_values_() {
23+
std::string s(this->rx_message_.begin(), this->rx_message_.end());
24+
int spos = 0;
25+
int epos = 0;
26+
std::vector<float> values;
27+
while (epos != std::string::npos) {
28+
epos = s.find(',', spos);
29+
int len = (epos == std::string::npos ? s.size() - spos : epos - spos);
30+
values.push_back(parse_number<float>(s.substr(spos, len)).value_or(NAN));
31+
if (epos != std::string::npos)
32+
spos = epos + 1;
33+
}
34+
this->rx_message_.clear();
35+
for (auto sens : this->sensors_) {
36+
if (sens.first < values.size())
37+
sens.second->publish_state(values[sens.first]);
38+
}
39+
}
40+
41+
void SerialCSV::dump_config() {
42+
ESP_LOGCONFIG("", "Serial CSV Reader");
43+
for (auto sens : this->sensors_) {
44+
ESP_LOGCONFIG(TAG, "Index %d", sens.first);
45+
LOG_SENSOR(TAG, "", sens.second);
46+
}
47+
}
48+
49+
} // namespace serial
50+
} // namespace esphome

components/serial_csv/serial_csv.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#pragma once
2+
3+
#include "esphome/core/component.h"
4+
#include "esphome/components/sensor/sensor.h"
5+
#include "esphome/components/uart/uart.h"
6+
7+
namespace esphome {
8+
namespace serial {
9+
10+
class SerialCSV : public Component, public uart::UARTDevice {
11+
public:
12+
float get_setup_priority() const override { return setup_priority::DATA; }
13+
void loop() override;
14+
void dump_config() override;
15+
16+
void add_sensor(int index, sensor::Sensor *sens) {
17+
this->sensors_.push_back(std::make_pair(index, sens));
18+
}
19+
20+
protected:
21+
void parse_values_();
22+
std::vector<uint8_t> rx_message_;
23+
std::vector<std::pair<int, sensor::Sensor *>> sensors_;
24+
};
25+
26+
} // namespace serial
27+
} // namespace esphome

0 commit comments

Comments
 (0)