hello can someone help, why are the sensors not showing up, it seems like there is some autodiscover problem
sometimes 3 sometimes 4 sometimes 5 sensors, but need 8-9
modbus tcb via wifi
sensor:
- platform: custom
lambda: |-
auto mg_l = new ModbusTCPSensor("172.16.48.49", 502, 4, "AB_CD", 150000);
App.register_component(mg_l);
return {mg_l};
sensors:
- name: "Dissolved_Oxygen_mgL_5711"
id: dissolved_oxygen_mgL_5711
unit_of_measurement: "mg/L"
state_class: measurement
- platform: custom
lambda: |-
auto co2 = new ModbusTCPSensor("172.16.48.49", 502, 13, "CD_AB", 200000);
App.register_component(co2);
return {co2};
sensors:
- name: "CO2_oxy_5711"
id: co2_oxy_5711
state_class: measurement
- platform: custom
lambda: |-
auto redox = new ModbusTCPSensor("172.16.48.49", 502, 33, "CD_AB", 180000);
App.register_component(redox);
return {redox};
sensors:
- name: "Redox_Potential_5711"
id: redox_potential_5711
unit_of_measurement: "mV"
device_class: voltage
state_class: measurement
- platform: custom
lambda: |-
auto ph = new ModbusTCPSensor("172.16.48.49", 502, 23, "CD_AB", 150000);
App.register_component(ph);
return {ph};
sensors:
- name: "pH_5711"
id: ph_5711
state_class: measurement
- platform: custom
lambda: |-
auto o3 = new ModbusTCPSensor("172.16.48.49", 502, 43, "CD_AB", 210000);
App.register_component(o3);
return {o3};
sensors:
- name: "O3_5711"
id: o3_5711
state_class: measurement
- platform: custom
lambda: |-
auto temp_o2 = new ModbusTCPSensor("172.16.48.49", 502, 10, "AB_CD", 210000);
App.register_component(temp_o2);
return {temp_o2};
sensors:
- name: "temp_o22"
id: temp_o22
state_class: measurement
unit_of_measurement: "°C"
device_class: temperature
#pragma once
#include "esphome.h"
// POSIX/lwIP socketid
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <cstring>
#include <string>
class ModbusTCPSensor : public esphome::PollingComponent, public esphome::sensor::Sensor {
public:
ModbusTCPSensor(const std::string &host,
uint16_t port,
uint16_t register_address,
uint8_t unit_id,
const std::string &byte_order,
uint32_t update_interval_ms)
: esphome::PollingComponent(update_interval_ms),
host_(host),
port_(port),
register_address_(register_address),
unit_id_(unit_id),
byte_order_(byte_order) {}
ModbusTCPSensor(const std::string &host,
uint16_t port,
uint16_t register_address,
const std::string &byte_order,
uint32_t update_interval_ms)
: ModbusTCPSensor(host, port, register_address, 1, byte_order, update_interval_ms) {}
void setup() override {
ESP_LOGCONFIG(TAG, "ModbusTCP init host=%s port=%u reg=0x%04X",
host_.c_str(), port_, register_address_);
this->set_accuracy_decimals(2);
}
void update() override {
int fd = -1;
if (!open_and_connect_(fd)) {
ESP_LOGE(TAG, "TCP connect failed");
return;
}
uint8_t req[12];
build_request_(req);
if (!write_n_(fd, req, sizeof(req))) {
ESP_LOGE(TAG, "Write failed");
::close(fd);
return;
}
uint8_t hdr[9];
if (!read_n_(fd, hdr, sizeof(hdr))) {
ESP_LOGE(TAG, "Header read failed");
::close(fd);
return;
}
uint8_t fc = hdr[7];
uint8_t bc = hdr[8];
if (fc & 0x80) {
ESP_LOGE(TAG, "Modbus exception FC=0x%02X", fc);
::close(fd);
return;
}
if (bc < 4) {
ESP_LOGE(TAG, "Bytecount too small");
::close(fd);
return;
}
uint8_t payload[32];
if (!read_n_(fd, payload, bc)) {
ESP_LOGE(TAG, "Payload read failed");
::close(fd);
return;
}
float value = decode_float_(payload, byte_order_);
publish_state(value);
::close(fd);
}
protected:
static constexpr const char *TAG = "modbus_tcp";
std::string host_;
uint16_t port_;
uint16_t register_address_;
uint8_t unit_id_;
std::string byte_order_;
uint16_t tx_id_ = 1;
void build_request_(uint8_t *o) {
uint16_t tid = tx_id_++;
o[0] = tid >> 8;
o[1] = tid & 0xFF;
o[2] = 0x00;
o[3] = 0x00;
o[4] = 0x00;
o[5] = 0x06;
o[6] = unit_id_;
o[7] = 0x03;
o[8] = register_address_ >> 8;
o[9] = register_address_ & 0xFF;
o[10] = 0x00;
o[11] = 0x02;
}
float decode_float_(const uint8_t *d, const std::string &o) {
uint32_t raw;
if (o == "AB_CD")
raw = (d[0] << 24) | (d[1] << 16) | (d[2] << 8) | d[3];
else
raw = (d[2] << 24) | (d[3] << 16) | (d[0] << 8) | d[1];
float f;
std::memcpy(&f, &raw, sizeof(f));
return f;
}
bool open_and_connect_(int &fd) {
fd = -1;
struct addrinfo hints = {};
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
struct addrinfo *res = nullptr;
char port_str[8];
snprintf(port_str, sizeof(port_str), "%u", port_);
if (::getaddrinfo(host_.c_str(), port_str, &hints, &res) != 0 || !res)
return false;
fd = ::socket(res->ai_family, res->ai_socktype, 0);
if (fd < 0) {
::freeaddrinfo(res);
return false;
}
if (::connect(fd, res->ai_addr, res->ai_addrlen) != 0) {
::close(fd);
fd = -1;
::freeaddrinfo(res);
return false;
}
::freeaddrinfo(res);
return true;
}
bool write_n_(int fd, const uint8_t *b, size_t n) {
size_t s = 0;
while (s < n) {
ssize_t x = ::send(fd, b + s, n - s, 0);
if (x <= 0) return false;
s += x;
}
return true;
}
bool read_n_(int fd, uint8_t *b, size_t n) {
size_t r = 0;
while (r < n) {
ssize_t x = ::recv(fd, b + r, n - r, 0);
if (x <= 0) return false;
r += x;
}
return true;
}
};