mirror of
https://github.com/esphome/esphome.git
synced 2025-03-13 22:28:14 +00:00
Add component to query car data over OBD can bus
This commit is contained in:
parent
c457d8835e
commit
837fec7f72
93
esphome/components/obd/__init__.py
Normal file
93
esphome/components/obd/__init__.py
Normal file
@ -0,0 +1,93 @@
|
||||
import esphome.config_validation as cv
|
||||
import esphome.codegen as cg
|
||||
import esphome.components.sensor as s
|
||||
import esphome.components.binary_sensor as bs
|
||||
from esphome import automation
|
||||
from esphome.const import (
|
||||
CONF_ID,
|
||||
CONF_INTERVAL,
|
||||
CONF_TRIGGER_ID
|
||||
)
|
||||
|
||||
obd_ns = cg.esphome_ns.namespace("obd")
|
||||
OBDComponent = obd_ns.class_("OBDComponent", cg.PollingComponent)
|
||||
OBDSensor = obd_ns.class_("OBDSensor", s.Sensor, cg.Component)
|
||||
OBDBinarySensor = obd_ns.class_("OBDBinarySensor", bs.BinarySensor, cg.Component)
|
||||
PIDRequest = obd_ns.class_("PIDRequest", cg.Component)
|
||||
OBDPidTrigger = obd_ns.class_(
|
||||
"OBDPidTrigger",
|
||||
automation.Trigger.template(cg.std_vector.template(cg.uint8)),
|
||||
cg.Component
|
||||
)
|
||||
|
||||
CONF_CANBUS_ID = 'canbus_id'
|
||||
CONF_ENABLED_BY_DEFAULT = 'enabled_by_default'
|
||||
CONF_OBD_ID = 'obd_id'
|
||||
CONF_PID_ID = "pid_id"
|
||||
CONF_CAN_ID = "can_id"
|
||||
CONF_RESPONSE_CAN_ID = "response_can_id"
|
||||
CONF_USE_EXTENDED_ID = "use_extended_id"
|
||||
CONF_PIDS = "pids"
|
||||
CONF_PID = "pid"
|
||||
CONF_TIMEOUT = "timeout"
|
||||
CONF_REPLY_LENGTH = "reply_length"
|
||||
CONF_ON_FRAME = "on_frame"
|
||||
CONF_MASK = "mask"
|
||||
CONF_SIGNED = "signed"
|
||||
|
||||
CONFIG_SCHEMA = cv.Schema({
|
||||
cv.GenerateID(): cv.declare_id(OBDComponent),
|
||||
cv.Required(CONF_CANBUS_ID): cv.use_id("CanbusComponent"),
|
||||
cv.Optional(CONF_ENABLED_BY_DEFAULT, default=False): cv.boolean,
|
||||
cv.Optional(CONF_PIDS): cv.ensure_list(
|
||||
{
|
||||
cv.GenerateID(CONF_ID): cv.declare_id(PIDRequest),
|
||||
cv.Required(CONF_CAN_ID): cv.int_range(min=0, max=0x1FFFFFFF),
|
||||
cv.Required(CONF_PID): cv.int_range(min=0, max=0x1FFFFFFF),
|
||||
cv.Optional(CONF_RESPONSE_CAN_ID): cv.int_range(min=0, max=0x1FFFFFFF),
|
||||
cv.Optional(CONF_USE_EXTENDED_ID, default=False): cv.boolean,
|
||||
cv.Optional(CONF_INTERVAL, default="5s"): cv.positive_time_period_milliseconds,
|
||||
cv.Optional(CONF_TIMEOUT, default="500ms"): cv.positive_time_period_milliseconds,
|
||||
cv.Optional(CONF_REPLY_LENGTH, default=8): cv.positive_int,
|
||||
cv.Optional(CONF_ON_FRAME): automation.validate_automation(
|
||||
{
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(OBDPidTrigger),
|
||||
}
|
||||
),
|
||||
}
|
||||
)
|
||||
}).extend(cv.COMPONENT_SCHEMA)
|
||||
|
||||
async def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await cg.register_component(var, config)
|
||||
|
||||
can_bus = await cg.get_variable(config[CONF_CANBUS_ID])
|
||||
|
||||
cg.add(var.set_canbus(can_bus))
|
||||
cg.add(var.set_enabled_by_default(config[CONF_ENABLED_BY_DEFAULT]))
|
||||
|
||||
for pid_conf in config.get(CONF_PIDS, []):
|
||||
can_id = pid_conf[CONF_CAN_ID]
|
||||
pid = pid_conf[CONF_PID]
|
||||
use_extended_id = pid_conf[CONF_USE_EXTENDED_ID]
|
||||
response_can_id = pid_conf.get(CONF_RESPONSE_CAN_ID)
|
||||
|
||||
if (response_can_id is None):
|
||||
response_can_id = can_id | 8
|
||||
|
||||
pid_request = cg.new_Pvariable(
|
||||
pid_conf[CONF_ID], var, can_id, pid, response_can_id, use_extended_id
|
||||
)
|
||||
await cg.register_component(pid_request, pid_conf)
|
||||
|
||||
cg.add(pid_request.set_interval(pid_conf[CONF_INTERVAL]))
|
||||
cg.add(pid_request.set_timeout(pid_conf[CONF_TIMEOUT]))
|
||||
cg.add(pid_request.set_reply_length(pid_conf[CONF_REPLY_LENGTH]))
|
||||
|
||||
for trigger_conf in pid_conf.get(CONF_ON_FRAME, []):
|
||||
trigger = cg.new_Pvariable(trigger_conf[CONF_TRIGGER_ID], pid_request)
|
||||
await cg.register_component(trigger, trigger_conf)
|
||||
await automation.build_automation(trigger, [(cg.std_vector.template(cg.uint8), "data")], trigger_conf)
|
||||
|
||||
return var
|
49
esphome/components/obd/binary_sensor.py
Normal file
49
esphome/components/obd/binary_sensor.py
Normal file
@ -0,0 +1,49 @@
|
||||
import esphome.config_validation as cv
|
||||
import esphome.codegen as cg
|
||||
from esphome.components import binary_sensor
|
||||
from esphome.cpp_generator import LambdaExpression
|
||||
from esphome.const import (
|
||||
CONF_LAMBDA,
|
||||
CONF_INDEX,
|
||||
)
|
||||
from . import (
|
||||
CONF_PID_ID,
|
||||
CONF_MASK,
|
||||
OBDBinarySensor,
|
||||
PIDRequest
|
||||
)
|
||||
|
||||
CONFIG_SCHEMA = cv.All(
|
||||
binary_sensor.binary_sensor_schema(
|
||||
OBDBinarySensor,
|
||||
)
|
||||
.extend(
|
||||
{
|
||||
cv.Required(CONF_PID_ID): cv.use_id(PIDRequest),
|
||||
cv.Optional(CONF_LAMBDA): cv.returning_lambda,
|
||||
cv.Optional(CONF_INDEX): cv.positive_int,
|
||||
cv.Optional(CONF_MASK): cv.hex_int,
|
||||
}
|
||||
),
|
||||
cv.has_exactly_one_key(CONF_LAMBDA, CONF_INDEX),
|
||||
cv.has_none_or_all_keys(CONF_INDEX, CONF_MASK)
|
||||
)
|
||||
|
||||
async def to_code(config):
|
||||
pid_request = await cg.get_variable(config[CONF_PID_ID])
|
||||
var = await binary_sensor.new_binary_sensor(config, pid_request)
|
||||
await cg.register_component(var, config)
|
||||
|
||||
if lambda_ := config.get(CONF_LAMBDA):
|
||||
template = await cg.process_lambda(lambda_, [(cg.std_vector.template(cg.uint8), "data")], return_type=cg.bool_)
|
||||
cg.add(var.set_template(template))
|
||||
|
||||
else:
|
||||
index = config[CONF_INDEX]
|
||||
mask = config[CONF_MASK]
|
||||
template = LambdaExpression(
|
||||
f"return (data[{index}] & {mask}) == {mask};",
|
||||
[(cg.std_vector.template(cg.uint8), "data")],
|
||||
return_type=cg.bool_
|
||||
)
|
||||
cg.add(var.set_template(template))
|
179
esphome/components/obd/obd_component.cpp
Normal file
179
esphome/components/obd/obd_component.cpp
Normal file
@ -0,0 +1,179 @@
|
||||
#include "obd_component.h"
|
||||
#include "esphome/core/application.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/components/canbus/canbus.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace obd {
|
||||
|
||||
static const char *const TAG = "obd";
|
||||
|
||||
// Skip setup from PollingComponent to stop polling from starting automatically
|
||||
void OBDComponent::call_setup() {
|
||||
if (this->enabled_by_default_) {
|
||||
this->start_poller();
|
||||
}
|
||||
}
|
||||
|
||||
void OBDComponent::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, "OBD Component");
|
||||
}
|
||||
|
||||
void OBDComponent::update() {
|
||||
if (this->current_request_ == nullptr) {
|
||||
|
||||
// No current request, find the next request to do
|
||||
for (auto *request : this->pidrequests_) {
|
||||
if (request->start()) {
|
||||
this->current_request_ = request;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// No pid to be polled, exit loop
|
||||
return;
|
||||
} else {
|
||||
if (this->current_request_->update()) {
|
||||
this->current_request_ = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OBDComponent::send(std::uint32_t can_id, bool use_extended_id, uint8_t a, uint8_t b, uint8_t c, uint8_t d) {
|
||||
std::vector<uint8_t> data(8, 0xAA);
|
||||
data[0] = a;
|
||||
data[1] = b;
|
||||
data[2] = c;
|
||||
data[3] = d;
|
||||
|
||||
this->canbus_->send_data(can_id, use_extended_id, data);
|
||||
}
|
||||
|
||||
void OBDComponent::send(std::uint32_t can_id, bool use_extended_id, uint8_t a, uint8_t b, uint8_t c) {
|
||||
std::vector<uint8_t> data(8, 0xAA);
|
||||
data[0] = a;
|
||||
data[1] = b;
|
||||
data[2] = c;
|
||||
|
||||
this->canbus_->send_data(can_id, use_extended_id, data);
|
||||
}
|
||||
|
||||
void OBDComponent::add_pidrequest(PIDRequest *request) {
|
||||
ESP_LOGVV(TAG, "add request for canid=0x%03, pid=0x%06" PRIx32, request->can_id_, PRIx32, request->pid_);
|
||||
this->pidrequests_.push_back(request);
|
||||
};
|
||||
|
||||
void PIDRequest::setup() {
|
||||
this->parent_->add_pidrequest(this);
|
||||
|
||||
auto trigger = new OBDCanbusTrigger(this);
|
||||
trigger->setup();
|
||||
}
|
||||
|
||||
bool PIDRequest::start() {
|
||||
if (this->state_ != WAITING)
|
||||
return false;
|
||||
|
||||
if ((this->last_polled_ + this->interval_) >= millis())
|
||||
return false;
|
||||
|
||||
this->response_buffer_.clear();
|
||||
this->response_buffer_.reserve(this->reply_length_);
|
||||
|
||||
auto can_id = this->can_id_;
|
||||
auto pid = this->pid_;
|
||||
|
||||
ESP_LOGD(TAG, "polling can_id: 0x%03x for pid 0x%04x", can_id, pid);
|
||||
|
||||
if (pid > 0xFFFF) {
|
||||
// 24 bit pid
|
||||
this->parent_->send(can_id, this->use_extended_id_, 0x03, (pid >> 16) & 0xFF, (pid >> 8) & 0xFF, pid & 0xFF);
|
||||
} else {
|
||||
this->parent_->send(can_id, this->use_extended_id_, 0x02, (pid >> 8) & 0xFF, pid & 0xFF);
|
||||
}
|
||||
|
||||
this->last_polled_ = millis();
|
||||
this->state_ = POLLING;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PIDRequest::update() {
|
||||
if (this->state_ != POLLING)
|
||||
return true; // Invalid state, update should not have been called here
|
||||
|
||||
if ((this->last_polled_ + this->timeout_) > millis()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this->response_buffer_.size() < this->reply_length_) {
|
||||
ESP_LOGD(TAG, "timeout for polling can_id: 0x%03x for pid 0x%04x", this->can_id_, this->pid_);
|
||||
this->state_ = WAITING;
|
||||
return true;
|
||||
}
|
||||
|
||||
for (auto *trigger : this->triggers_) {
|
||||
trigger->trigger(this->response_buffer_);
|
||||
}
|
||||
|
||||
for (auto *sensor : this->sensors_) {
|
||||
sensor->update(this->response_buffer_);
|
||||
}
|
||||
|
||||
this->state_ = WAITING;
|
||||
return true;
|
||||
}
|
||||
|
||||
void PIDRequest::handle_incoming(std::vector<uint8_t> &data) {
|
||||
if (this->state_ != POLLING)
|
||||
return; // Not our cup of tea here, some other pid might be polling on the same can_id
|
||||
|
||||
ESP_LOGD(TAG, "recieved content for pid 0x%04x: %s", this->can_id_, this->pid_, format_hex_pretty(data).c_str());
|
||||
|
||||
// Handle the data
|
||||
if ((data[0] & 0xF0) == 0x10) {
|
||||
// This is a flow control frame, we should ask for more
|
||||
this->parent_->send(this->can_id_, this->use_extended_id_, 0x30, 0x0, 0x10);
|
||||
}
|
||||
|
||||
for (int i = 0; i < data.size(); i++) {
|
||||
this->response_buffer_.push_back(data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void PIDRequest::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, "PID Request 0x%03", this->pid_);
|
||||
|
||||
if (this->use_extended_id_) {
|
||||
ESP_LOGCONFIG(TAG, " Can extended id: 0x%08" PRIx32, this->can_id_);
|
||||
ESP_LOGCONFIG(TAG, " Can response id: 0x%08" PRIx32, this->can_response_id_);
|
||||
} else {
|
||||
ESP_LOGCONFIG(TAG, " Can id: 0x%03" PRIx32, this->can_id_);
|
||||
ESP_LOGCONFIG(TAG, " Can response id: 0x%03" PRIx32, this->can_response_id_);
|
||||
}
|
||||
|
||||
ESP_LOGCONFIG(TAG, " Pid: 0x%03" PRIx32, this->pid_);
|
||||
ESP_LOGCONFIG(TAG, " Interval: %ims", this->interval_);
|
||||
ESP_LOGCONFIG(TAG, " Timeout: %ims", this->timeout_);
|
||||
}
|
||||
|
||||
void OBDSensor::update(const std::vector<uint8_t> &data) {
|
||||
auto value = this->data_to_value_func_(data);
|
||||
this->publish_state(value);
|
||||
}
|
||||
|
||||
void OBDSensor::dump_config() {
|
||||
LOG_SENSOR("", "OBD Sensor", this);
|
||||
}
|
||||
|
||||
void OBDBinarySensor::update(const std::vector<uint8_t> &data) {
|
||||
auto value = this->data_to_value_func_(data);
|
||||
this->publish_state(value);
|
||||
}
|
||||
|
||||
void OBDBinarySensor::dump_config() {
|
||||
LOG_BINARY_SENSOR("", "OBD Binary Sensor", this);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
154
esphome/components/obd/obd_component.h
Normal file
154
esphome/components/obd/obd_component.h
Normal file
@ -0,0 +1,154 @@
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/components/canbus/canbus.h"
|
||||
#include "esphome/components/sensor/sensor.h"
|
||||
#include "esphome/components/binary_sensor/binary_sensor.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace obd {
|
||||
|
||||
class PIDRequest;
|
||||
class OBDPidTrigger;
|
||||
class OBDSensorBase;
|
||||
class OBDSensor;
|
||||
|
||||
class OBDComponent : public PollingComponent {
|
||||
friend class OBDCanbusTrigger;
|
||||
|
||||
public:
|
||||
explicit OBDComponent() : PollingComponent(500) {}
|
||||
void call_setup() override;
|
||||
void update() override;
|
||||
|
||||
void set_canbus(canbus::Canbus *canbus) { this->canbus_ = canbus; }
|
||||
void set_enabled_by_default(bool enabled_by_default) { this->enabled_by_default_ = enabled_by_default; }
|
||||
|
||||
void add_pidrequest(PIDRequest *request);
|
||||
void dump_config() override;
|
||||
|
||||
void send(std::uint32_t can_id, bool use_extended_id, uint8_t a, uint8_t b, uint8_t c);
|
||||
void send(std::uint32_t can_id, bool use_extended_id, uint8_t a, uint8_t b, uint8_t c, uint8_t d);
|
||||
|
||||
protected:
|
||||
canbus::Canbus *canbus_{nullptr};
|
||||
bool enabled_by_default_{false};
|
||||
|
||||
std::vector<PIDRequest *> pidrequests_{};
|
||||
|
||||
PIDRequest* current_request_{nullptr};
|
||||
};
|
||||
|
||||
using data_to_value_t = std::function<float(std::vector<uint8_t>)>;
|
||||
using data_to_bool_t = std::function<float(std::vector<uint8_t>)>;
|
||||
|
||||
enum request_state_t {
|
||||
WAITING,
|
||||
POLLING,
|
||||
};
|
||||
|
||||
class PIDRequest : public Component {
|
||||
friend class OBDCanbusTrigger;
|
||||
|
||||
public:
|
||||
explicit PIDRequest(OBDComponent *parent, const std::uint32_t can_id, const std::uint32_t pid,
|
||||
const std::uint32_t can_response_id, const bool use_extended_id)
|
||||
: parent_(parent), can_id_(can_id), pid_(pid), can_response_id_(can_response_id), use_extended_id_(use_extended_id){
|
||||
this->state_ = WAITING;
|
||||
};
|
||||
|
||||
void setup() override;
|
||||
uint32_t last_polled_{0};
|
||||
|
||||
bool start();
|
||||
bool update();
|
||||
|
||||
void set_timeout(std::uint32_t timeout) { this->timeout_ = timeout; }
|
||||
void set_interval(std::uint32_t interval) { this->interval_ = interval; }
|
||||
void set_reply_length(std::uint32_t reply_length) { this->reply_length_ = reply_length; }
|
||||
|
||||
void add_sensor(OBDSensorBase *sensor) { this->sensors_.push_back(sensor); }
|
||||
void add_trigger(OBDPidTrigger *trigger) { this->triggers_.push_back(trigger); }
|
||||
void dump_config() override;
|
||||
|
||||
protected:
|
||||
void handle_incoming(std::vector<uint8_t> &data);
|
||||
|
||||
OBDComponent *parent_;
|
||||
uint32_t can_id_;
|
||||
uint32_t can_response_id_;
|
||||
uint32_t pid_;
|
||||
bool use_extended_id_;
|
||||
uint32_t interval_{5000};
|
||||
uint32_t timeout_{500};
|
||||
uint32_t reply_length_{8};
|
||||
|
||||
request_state_t state_{WAITING};
|
||||
std::vector<uint8_t> response_buffer_{};
|
||||
|
||||
std::vector<OBDSensorBase *> sensors_{};
|
||||
std::vector<OBDPidTrigger *> triggers_{};
|
||||
};
|
||||
|
||||
class OBDPidTrigger : public Trigger<std::vector<uint8_t>>, public Component {
|
||||
public:
|
||||
explicit OBDPidTrigger(PIDRequest *parent) : parent_(parent){}
|
||||
|
||||
void setup() override { this->parent_->add_trigger(this); }
|
||||
|
||||
protected:
|
||||
PIDRequest *parent_;
|
||||
};
|
||||
|
||||
class OBDSensorBase {
|
||||
public:
|
||||
virtual void update(const std::vector<uint8_t> &data) {}
|
||||
};
|
||||
|
||||
class OBDSensor : public OBDSensorBase, public sensor::Sensor, public Component {
|
||||
public:
|
||||
explicit OBDSensor(PIDRequest *parent) : parent_(parent){}
|
||||
|
||||
void set_template(data_to_value_t &&lambda) { this->data_to_value_func_ = lambda; }
|
||||
|
||||
void update(const std::vector<uint8_t> &data) override ;
|
||||
void setup() override { this->parent_->add_sensor(this); }
|
||||
void dump_config() override;
|
||||
|
||||
protected:
|
||||
PIDRequest *parent_;
|
||||
data_to_value_t data_to_value_func_{};
|
||||
};
|
||||
|
||||
class OBDBinarySensor : public OBDSensorBase, public binary_sensor::BinarySensor, public Component {
|
||||
public:
|
||||
explicit OBDBinarySensor(PIDRequest *parent) : parent_(parent){}
|
||||
|
||||
void set_template(data_to_bool_t &&lambda) { this->data_to_value_func_ = lambda; }
|
||||
void update(const std::vector<uint8_t> &data) override;
|
||||
|
||||
void setup() override { this->parent_->add_sensor(this); }
|
||||
|
||||
void dump_config() override;
|
||||
|
||||
protected:
|
||||
PIDRequest *parent_;
|
||||
data_to_bool_t data_to_value_func_;
|
||||
};
|
||||
|
||||
class OBDCanbusTrigger : public canbus::CanbusTrigger, public Action<std::vector<uint8_t>, uint32_t, bool> {
|
||||
public:
|
||||
explicit OBDCanbusTrigger(PIDRequest *parent) : CanbusTrigger(parent->parent_->canbus_, parent->can_response_id_, 0x1FFFFFFF, parent->use_extended_id_), parent_(parent){
|
||||
auto automation = new Automation<std::vector<uint8_t>, uint32_t, bool>(this);
|
||||
automation->add_action(this);
|
||||
};
|
||||
|
||||
void play(std::vector<uint8_t> data, uint32_t can_id, bool rx) override {
|
||||
this->parent_->handle_incoming(data);
|
||||
}
|
||||
|
||||
protected:
|
||||
PIDRequest *parent_;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
75
esphome/components/obd/sensor.py
Normal file
75
esphome/components/obd/sensor.py
Normal file
@ -0,0 +1,75 @@
|
||||
import esphome.config_validation as cv
|
||||
import esphome.codegen as cg
|
||||
from esphome.components import sensor
|
||||
from esphome.cpp_generator import LambdaExpression
|
||||
from esphome.const import (
|
||||
CONF_ID,
|
||||
CONF_LAMBDA,
|
||||
CONF_INDEX,
|
||||
)
|
||||
from . import (
|
||||
CONF_PID_ID,
|
||||
CONF_SIGNED,
|
||||
OBDSensor,
|
||||
PIDRequest
|
||||
)
|
||||
|
||||
CONFIG_SCHEMA = cv.All(
|
||||
sensor.sensor_schema(
|
||||
OBDSensor,
|
||||
)
|
||||
.extend(
|
||||
{
|
||||
cv.Required(CONF_PID_ID): cv.use_id(PIDRequest),
|
||||
cv.Optional(CONF_SIGNED, default=False): cv.boolean,
|
||||
cv.Exclusive(CONF_LAMBDA, CONF_LAMBDA): cv.returning_lambda,
|
||||
cv.Exclusive(CONF_INDEX, CONF_LAMBDA): cv.ensure_list(cv.positive_int)
|
||||
}
|
||||
),
|
||||
cv.has_exactly_one_key(CONF_LAMBDA, CONF_INDEX)
|
||||
)
|
||||
|
||||
async def to_code(config):
|
||||
pid_request = await cg.get_variable(config[CONF_PID_ID])
|
||||
var = await sensor.new_sensor(config, pid_request)
|
||||
await cg.register_component(var, config)
|
||||
|
||||
template = False
|
||||
|
||||
if lambda_ := config.get(CONF_LAMBDA):
|
||||
template = await cg.process_lambda(lambda_, [(cg.std_vector.template(cg.uint8), "data")], return_type=cg.float_)
|
||||
cg.add(var.set_template(template))
|
||||
else:
|
||||
indexes = config[CONF_INDEX]
|
||||
signed = "(int8_t)" if config[CONF_SIGNED] else ""
|
||||
|
||||
if len(indexes) == 4:
|
||||
template = LambdaExpression(
|
||||
f"return ({signed}data[{indexes[0]}] << 24) | (data[{indexes[1]}] << 16) | (data[{indexes[2]}] << 8) | data[{indexes[3]}];",
|
||||
[(cg.std_vector.template(cg.uint8), "data")],
|
||||
return_type=cg.float_
|
||||
)
|
||||
|
||||
if len(indexes) == 3:
|
||||
template = LambdaExpression(
|
||||
f"return ({signed}data[{indexes[0]}] << 16) | (data[{indexes[1]}] << 8) | data[{indexes[2]}];",
|
||||
[(cg.std_vector.template(cg.uint8), "data")],
|
||||
return_type=cg.float_
|
||||
)
|
||||
|
||||
if len(indexes) == 2:
|
||||
template = LambdaExpression(
|
||||
f"return ({signed}data[{indexes[0]}] << 8) | data[{indexes[1]}];",
|
||||
[(cg.std_vector.template(cg.uint8), "data")],
|
||||
return_type=cg.float_
|
||||
)
|
||||
|
||||
if len(indexes) == 1:
|
||||
template = LambdaExpression(
|
||||
f"return {signed}data[{indexes[0]}];",
|
||||
[(cg.std_vector.template(cg.uint8), "data")],
|
||||
return_type=cg.float_
|
||||
)
|
||||
|
||||
cg.add(var.set_template(template))
|
||||
|
Loading…
x
Reference in New Issue
Block a user