189 lines
5.3 KiB
Python
189 lines
5.3 KiB
Python
from esphome import automation
|
|
import esphome.codegen as cg
|
|
from esphome.components import i2c
|
|
import esphome.config_validation as cv
|
|
from esphome.const import (
|
|
CONF_CALIBRATION,
|
|
CONF_ID,
|
|
CONF_MIRROR_X,
|
|
CONF_MIRROR_Y,
|
|
CONF_OFFSET_X,
|
|
CONF_OFFSET_Y,
|
|
CONF_OFFSET_Z,
|
|
CONF_RANGE,
|
|
CONF_RESOLUTION,
|
|
CONF_SWAP_XY,
|
|
CONF_TRANSFORM,
|
|
CONF_TYPE,
|
|
)
|
|
|
|
CODEOWNERS = ["@latonita"]
|
|
DEPENDENCIES = ["i2c"]
|
|
|
|
MULTI_CONF = True
|
|
|
|
CONF_MSA3XX_ID = "msa3xx_id"
|
|
|
|
CONF_MIRROR_Z = "mirror_z"
|
|
CONF_ON_ACTIVE = "on_active"
|
|
CONF_ON_DOUBLE_TAP = "on_double_tap"
|
|
CONF_ON_FREEFALL = "on_freefall"
|
|
CONF_ON_ORIENTATION = "on_orientation"
|
|
CONF_ON_TAP = "on_tap"
|
|
|
|
MODEL_MSA301 = "MSA301"
|
|
MODEL_MSA311 = "MSA311"
|
|
|
|
msa3xx_ns = cg.esphome_ns.namespace("msa3xx")
|
|
MSA3xxComponent = msa3xx_ns.class_(
|
|
"MSA3xxComponent", cg.PollingComponent, i2c.I2CDevice
|
|
)
|
|
|
|
MSAModels = msa3xx_ns.enum("Model", True)
|
|
MSA_MODELS = {
|
|
MODEL_MSA301: MSAModels.MSA301,
|
|
MODEL_MSA311: MSAModels.MSA311,
|
|
}
|
|
|
|
MSARange = msa3xx_ns.enum("Range", True)
|
|
MSA_RANGES = {
|
|
"2G": MSARange.RANGE_2G,
|
|
"4G": MSARange.RANGE_4G,
|
|
"8G": MSARange.RANGE_8G,
|
|
"16G": MSARange.RANGE_16G,
|
|
}
|
|
|
|
MSAResolution = msa3xx_ns.enum("Resolution", True)
|
|
RESOLUTIONS_MSA301 = {
|
|
14: MSAResolution.RES_14BIT,
|
|
12: MSAResolution.RES_12BIT,
|
|
10: MSAResolution.RES_10BIT,
|
|
8: MSAResolution.RES_8BIT,
|
|
}
|
|
|
|
RESOLUTIONS_MSA311 = {
|
|
12: MSAResolution.RES_12BIT,
|
|
}
|
|
|
|
_COMMON_SCHEMA = cv.Schema(
|
|
{
|
|
cv.GenerateID(): cv.declare_id(MSA3xxComponent),
|
|
cv.Optional(CONF_RANGE, default="2G"): cv.enum(MSA_RANGES, upper=True),
|
|
cv.Optional(CONF_CALIBRATION): cv.Schema(
|
|
{
|
|
cv.Optional(CONF_OFFSET_X, default=0): cv.float_range(
|
|
min=-4.5, max=4.5
|
|
),
|
|
cv.Optional(CONF_OFFSET_Y, default=0): cv.float_range(
|
|
min=-4.5, max=4.5
|
|
),
|
|
cv.Optional(CONF_OFFSET_Z, default=0): cv.float_range(
|
|
min=-4.5, max=4.5
|
|
),
|
|
}
|
|
),
|
|
cv.Optional(CONF_TRANSFORM): cv.Schema(
|
|
{
|
|
cv.Optional(CONF_MIRROR_X, default=False): cv.boolean,
|
|
cv.Optional(CONF_MIRROR_Y, default=False): cv.boolean,
|
|
cv.Optional(CONF_MIRROR_Z, default=False): cv.boolean,
|
|
cv.Optional(CONF_SWAP_XY, default=False): cv.boolean,
|
|
}
|
|
),
|
|
cv.Optional(CONF_ON_ACTIVE): automation.validate_automation(single=True),
|
|
cv.Optional(CONF_ON_TAP): automation.validate_automation(single=True),
|
|
cv.Optional(CONF_ON_DOUBLE_TAP): automation.validate_automation(single=True),
|
|
cv.Optional(CONF_ON_FREEFALL): automation.validate_automation(single=True),
|
|
cv.Optional(CONF_ON_ORIENTATION): automation.validate_automation(single=True),
|
|
}
|
|
).extend(cv.polling_component_schema("10s"))
|
|
|
|
|
|
CONFIG_SCHEMA = cv.typed_schema(
|
|
{
|
|
MODEL_MSA301: _COMMON_SCHEMA.extend(
|
|
{
|
|
cv.Optional(CONF_RESOLUTION, default=14): cv.enum(RESOLUTIONS_MSA301),
|
|
}
|
|
).extend(i2c.i2c_device_schema(0x26)),
|
|
MODEL_MSA311: _COMMON_SCHEMA.extend(
|
|
{
|
|
cv.Optional(CONF_RESOLUTION, default=12): cv.enum(RESOLUTIONS_MSA311),
|
|
}
|
|
).extend(i2c.i2c_device_schema(0x62)),
|
|
},
|
|
upper=True,
|
|
enum=MSA_MODELS,
|
|
)
|
|
|
|
MSA_SENSOR_SCHEMA = cv.Schema(
|
|
{
|
|
cv.GenerateID(CONF_MSA3XX_ID): cv.use_id(MSA3xxComponent),
|
|
}
|
|
)
|
|
|
|
|
|
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)
|
|
|
|
cg.add(var.set_model(config[CONF_TYPE]))
|
|
cg.add(var.set_range(MSA_RANGES[config[CONF_RANGE]]))
|
|
cg.add(var.set_resolution(RESOLUTIONS_MSA301[config[CONF_RESOLUTION]]))
|
|
|
|
if transform := config.get(CONF_TRANSFORM):
|
|
cg.add(
|
|
var.set_transform(
|
|
transform[CONF_MIRROR_X],
|
|
transform[CONF_MIRROR_Y],
|
|
transform[CONF_MIRROR_Z],
|
|
transform[CONF_SWAP_XY],
|
|
)
|
|
)
|
|
|
|
if calibration_config := config.get(CONF_CALIBRATION):
|
|
cg.add(
|
|
var.set_offset(
|
|
calibration_config[CONF_OFFSET_X],
|
|
calibration_config[CONF_OFFSET_Y],
|
|
calibration_config[CONF_OFFSET_Z],
|
|
)
|
|
)
|
|
|
|
# Triggers secton
|
|
|
|
if CONF_ON_ORIENTATION in config:
|
|
await automation.build_automation(
|
|
var.get_orientation_trigger(),
|
|
[],
|
|
config[CONF_ON_ORIENTATION],
|
|
)
|
|
|
|
if CONF_ON_TAP in config:
|
|
await automation.build_automation(
|
|
var.get_tap_trigger(),
|
|
[],
|
|
config[CONF_ON_TAP],
|
|
)
|
|
|
|
if CONF_ON_DOUBLE_TAP in config:
|
|
await automation.build_automation(
|
|
var.get_double_tap_trigger(),
|
|
[],
|
|
config[CONF_ON_DOUBLE_TAP],
|
|
)
|
|
|
|
if CONF_ON_ACTIVE in config:
|
|
await automation.build_automation(
|
|
var.get_active_trigger(),
|
|
[],
|
|
config[CONF_ON_ACTIVE],
|
|
)
|
|
|
|
if CONF_ON_FREEFALL in config:
|
|
await automation.build_automation(
|
|
var.get_freefall_trigger(),
|
|
[],
|
|
config[CONF_ON_FREEFALL],
|
|
)
|