[ESPHOME]自定义开发

esphome提供的框架偏向于让我们尽量在yaml配置文件中定义逻辑,它提供了很多基本的功能,这样可以减少自己需要写的代码,也可以减少出问题的概率。

如果框架提供的部分满足不了自己的全部需求的话,就需要自己写c++代码。另外再强调一下,esphome基于platformIO工具链,再底层可以选Arduino,也可以是esp-idf,在开发时要考虑兼容性的话(比如在esp8266和esp32上都可以运行),就尽量使用esphome和arduino的api。

esphome提供了几种方式混入外部的代码:

  1. 在配置文件中使用”includes”选项直接一同编译指定的文件。
  2. 在配置文件中使用”libraries”选项引入外部的库。
  3. 使用外部组件,外部组件支持直接指定仓库地址,它在编译时会去把仓库克隆下来。当指定的是本地路径时,也就是把本地的一个目录当成一个组件库来处理。

要自定义代码我认为最好的方式就是在项目目录里定义一个本地的外部组件,虽然使用外部组件需要写一个python初始化脚本(这是我极其讨厌的,还好有AI帮我写),但这种组件的形式可以更容易地嵌入和调用我们的代码(因为如果你不用这种形式,就要禁用main.cpp自动生成,然后自己去手写入口文件,否则你的代码就没有地方可以调用。esphome框架默认会生成一份它自己的入口和loop,你就不能再在全局定义你的了。)。

接下来是如何写一个自定义外部组件的笔记。

首先在配置yaml文件中加两个顶层属性,定义外部组件的目录,再定义你的组件名字以及id(为的是方便其他组件调用我们组件里的代码,这里我的组件名称叫”Jia_comp”):

external_components:
  - source:
      type: local        # 本地组件
      path: components   # 组件所在的路径,定义为相对路径时就是相对项目根目录的路径。注意这不是某个组件的路径,而是组件的目录所在的上级目录。
                         # 该目录下的每一个子目录都是一个组件
      # components: [Jia_comp]   #这里注释掉的一行是用来指定仅加载上面组件目录中特定组件的,如果不指定就会加载此目录下的所有组件。
Jia_comp: #组件名称
  id: jia_comp  #组件id,id可以随便定义,不一定要和组件名称有关系

然后在项目目录中创建一个”components”目录,再在里面创建一个”Jia_comp”目录,这就是我们的组件目录。组件目录中需要一个和目录同名的h或cpp文件作为入口,这里我们定义一个”Jia_comp.h”文件:

#pragma once
#include "esphome.h"

namespace esphome {
	namespace jia_component { //按照其它组件的惯例,在esphome命名空间下创建一个自己的命名空间
		class Jia_comp : public Component { //定义Jia_comp组件,继承自Component类
		public:
			void setup() override {
				//在这里写初始化代码,比如连接设备等等
				ESP_LOGI("Jia_comp", "自定义组件初始化开始");
			}

			void loop() override {
				//在这里写每个循环要执行的代码
			}
		};

	} // namespace jia_component
} // namespace esphome

接下来再在”Jia_comp”目录中创建一个”__init__.py”文件,此文件是用于对该组件进行定义的。

import esphome.codegen as cg
import esphome.config_validation as cv
from esphome import pins  #如果需要定义引脚的话需要这个,但我这没用到
from esphome.const import CONF_ID

jia_comp_ns = cg.esphome_ns.namespace('jia_component')  #获取命名空间
Jia_comp = jia_comp_ns.class_('Jia_comp', cg.Component)  #获取命名空间里的类

CONFIG_SCHEMA = cv.Schema({
    cv.GenerateID(): cv.declare_id(Jia_comp), #这里对应配置文件中我们需要设置的id
}).extend(cv.COMPONENT_SCHEMA)

async def to_code(config):  #此方法用于自动在main.cpp中生成初始化代码,如果没有其它参数需要传递的话直接照这么写就行
    var = cg.new_Pvariable(config[CONF_ID])
    await cg.register_component(var, config)

这样一个可以通过编译的外部组件就定义好了,你可以在你的组件类中定义公共方法,并在配置文件中其它组件的事件中使用`id(组件id).方法();`来调用它。



本文发布于 https://luojia.me

本站文章未经文下加注授权不得拷贝发布。

0 0 投票数
打分
订阅评论
提醒
guest
0 评论
内联反馈
查看所有评论