『瀚思彼岸』» 智能家居技术论坛

 找回密码
 立即注册
查看: 1033|回复: 8

[进阶教程] 让smartac支持esphome的mqtt协议

[复制链接]

37

主题

396

帖子

4104

积分

元老级技术达人

积分
4104
金钱
3653
HASS币
250
发表于 2023-9-17 12:46:16 | 显示全部楼层 |阅读模式
一直在用ryanh7大佬的smarac空调控制插件感觉这个插件非常好用,但是大佬比较低调,所以对这个插件有没有太多的介绍不过不知道为啥大佬更新后删掉了红外库的索引文件,现在最新的插件里面不包含了代码库索引,所以导致新手配置这个索引可能比较困难。
https://bbs.hassbian.com/forum.php?mod=viewthread&tid=15827


插件对esphome的原生api插件支持比较友好,但是如果esphome刷了mqtt协议就不太友好了,
首先就是配置方面,如果是原生的api,只需要在配置文件里面加上如下代码,就搞定了,但是esphome的原生api和mqtt协议不能同时存在,使用mqtt协议无法套用此配置
esphome:
  name: my_espir
  platform: ESP8266
  board: esp01_1m

api:
  services:
    - service: send_raw_command
      variables:
        command: int[]
      then:
        - remote_transmitter.transmit_raw:
            code: !lambda 'return command;'

remote_transmitter:
  pin: GPIO14
  carrier_duty_percent: 50%
经过对esphome几天几夜的研究,翻阅大量资料,结合chatgpt的代码解析功能,终于研究出了esphome-mqtt搭配smartAC的使用方法需要在esphome中使用如下配置



mqtt:
  id: mqtt_client
  broker: mqtt.iot.org
  port: 1883
  username: pi
  password: xxxx
  discovery_prefix: tj
  discovery_object_id_generator: device_name
  discovery_unique_id_generator: mac
  log_topic:
    topic: "${device_name}/logs"
    level: debug
  discovery: true
  
ota:
  safe_mode: true
  password: xxxx
  on_state_change:
    then:
      - lambda: "App.feed_wdt();delay(1);"
captive_portal:

web_server:
  port: 80
  version: 2
  auth:
    username: xxxx
    password: xxxxxxx
wifi:
  networks:
  - ssid: iot
    password: xxxxxx

  reboot_timeout: 1200s
  fast_connect: true
  ap:
    ssid: esphome
    password: xxxxxx




substitutions:
  device_name: my_espir
  #device_name: esp32mmwsolo
  gpio_ir_t: GPIO14
  gpio_ir_r: GPIO26
  config_version: esp32ir-mqtt-20230916




esphome:
  name: $device_name
  platform: esp32
  board: esp32doit-devkit-v1
  name_add_mac_suffix: yes 
  build_path: ../build/$device_name


  on_boot: 
    - priority: 300
      then:
        - lambda: |-
              MQTTMessage new_birth_message;
              new_birth_message.topic = App.get_name() + "/" + "status";
              new_birth_message.payload = "online";
              new_birth_message.qos = 1;
              new_birth_message.retain = true;
              id(mqtt_client).set_birth_message(std::move(new_birth_message));

              MQTTMessage new_last_message;
              new_last_message.topic =   App.get_name() + "/" + "status";
              new_last_message.payload = "offline";
              new_last_message.qos = 1;
              new_last_message.retain = true;
              id(mqtt_client).set_last_will(std::move(new_last_message));

              MQTTMessage new_shutdown_message;
              new_shutdown_message.topic =   App.get_name() + "/" + "status";
              new_shutdown_message.payload = "offline";
              new_shutdown_message.qos = 1;
              new_shutdown_message.retain = true;
              id(mqtt_client).set_shutdown_message(std::move(new_shutdown_message));

              id(mqtt_client).set_topic_prefix(App.get_name());

    - priority: -100
      then:
        - lambda: |-
            id(mqtt_client).subscribe(App.get_name() + "/ir_send", [=](const std::string &topic, const std::string &payload) {
            
            std::string txstr = payload;
            std::vector<int> txv1;
            if (!txstr.empty()) {
              txstr = txstr.substr(1);  
              }
            if (!txstr.empty()) {
              txstr = txstr.substr(0, txstr.size() - 1);  
              }
              txstr.erase(std::remove_if(txstr.begin(), txstr.end(), [](char c) { return std::isspace(c); }), txstr.end());
  
            char * token;
            char seps[] = ",";
            token = strtok (&txstr[0],seps);
            while (token != NULL)
            {
              txv1.push_back( atoi(token) );
              token = strtok (NULL, seps);
            }
            for (int i = 0; i < txv1.size(); i++) {
              if (i % 2 == 1) {  // 如果是偶数位
                txv1[i] = -txv1[i];  // 在偶数位的数据前面加上负号
              }
            }
            id(txv)=txv1;
            id(irsend).press();
            });
            //
logger:
  level: ERROR  #不同的log等级看到的信息详细程度不一样,信息量从少到多依次为NONE、ERROR、WARN、INFO、DEBUG、VERBOSE、VERY_VERBOSE
#  baud_rate: 0 #设置为0关闭通过UART的log输出


globals:
  - id: txv
    type: std::vector<int>
    restore_value: false

button:
  - platform: template
    name: "irsend"
    id: "irsend"
    internal: true
    on_press:
      then:
        - remote_transmitter.transmit_raw:
            carrier_frequency: 38kHz
            code: !lambda |-
                    return id(txv);
remote_transmitter:
  pin: $gpio_ir_t
  carrier_duty_percent: 50%
  id: my_transmitter





接下来就只需要在smartAC插件里面填入订阅的topic就行了。
]BE24WJ)UAXMCM5]E]9GF.png

评分

参与人数 2金钱 +20 收起 理由
隔壁的王叔叔 + 10 高手,这是高手!
sorrypqa + 10 大神666!

查看全部评分

回复

使用道具 举报

50

主题

1300

帖子

4901

积分

论坛DIY达人

积分
4901
金钱
3601
HASS币
20
发表于 2023-9-17 17:11:59 | 显示全部楼层
厉害!!俺一看到MQTT的东西就头痛!
回复

使用道具 举报

39

主题

2049

帖子

7695

积分

元老级技术达人

积分
7695
金钱
5631
HASS币
110
发表于 2023-9-18 09:09:00 | 显示全部楼层
两个疑问:
1、为啥不用原生API而用mqtt呢,这么做的好处是?
2、还有原作不包含代码库索引后,在使用上有什么问题?

smartac刚出来那周我就吃上了,后续一直没更新过,用的挺好
硬件用的移动X12,在esphome里把电量计量也做进去了
然后通过巴法接到天猫,现在遥控器都没电好久了
回复

使用道具 举报

37

主题

396

帖子

4104

积分

元老级技术达人

积分
4104
金钱
3653
HASS币
250
 楼主| 发表于 2023-9-18 10:47:06 | 显示全部楼层
本帖最后由 trz0332 于 2023-9-18 10:48 编辑
ghostist 发表于 2023-9-18 09:09
两个疑问:
1、为啥不用原生API而用mqtt呢,这么做的好处是?
2、还有原作不包含代码库索引后,在使用上有 ...

1、原生api需要在路由器里面绑定mac地址,如果不绑定,路由器重启ip变更后可能会出现2个esphome设备串IP,测点出不来,需要删除重新添加,使用mqtt就方便多了,配置好自动发现在mqtt里面就直接出现设备了。
2、使用没问题,就是需要你自己添加索引,而且需要去自己下载红外代码库。如果你有最开始的smartac插件就不要担心这个问题,旧版本是包含了索引库和红外代码库
回复

使用道具 举报

39

主题

2049

帖子

7695

积分

元老级技术达人

积分
7695
金钱
5631
HASS币
110
发表于 2023-9-18 11:52:43 | 显示全部楼层
trz0332 发表于 2023-9-18 10:47
1、原生api需要在路由器里面绑定mac地址,如果不绑定,路由器重启ip变更后可能会出现2个esphome设备串IP, ...

哦 原来如此,好像出现过HA里识别到两个一样名字的ESP设备
不过我前阵子抽空把家里所有wifi设备都划分了静态IP,可能就没这个问题了
回复

使用道具 举报

50

主题

244

帖子

4302

积分

元老级技术达人

积分
4302
金钱
4048
HASS币
80
发表于 2023-9-19 10:51:18 | 显示全部楼层
内存富余的可以这么干,大概会多占用3~4kB内存
mqtt:
  # .... 其他配置
  on_message:
    topic: climate/send
    qos: 0
    then:
      - remote_transmitter.transmit_raw:
          code: !lambda |-
            std::vector<int> data;
            DynamicJsonDocument json_document(JSON_ARRAY_SIZE(x.size() / 5));
            deserializeJson(json_document, x);
            JsonArray root = json_document.as<JsonArray>();
            int s = -1;
            for(auto value : root) {
                s *= -1;
                data.push_back(value.as<int>() * s);
            }
            return data;
          carrier_frequency: 38k
没意思,跑路了
回复

使用道具 举报

37

主题

396

帖子

4104

积分

元老级技术达人

积分
4104
金钱
3653
HASS币
250
 楼主| 发表于 2023-9-19 11:45:58 | 显示全部楼层
本帖最后由 trz0332 于 2023-9-19 15:42 编辑
ryanh7 发表于 2023-9-19 10:51
内存富余的可以这么干,大概会多占用3~4kB内存

大神本尊驾到 顺便可以抄一下你的代码。
回复

使用道具 举报

0

主题

21

帖子

91

积分

注册会员

Rank: 2

积分
91
金钱
70
HASS币
0
发表于 2023-12-29 20:26:07 | 显示全部楼层
学习
回复

使用道具 举报

0

主题

21

帖子

91

积分

注册会员

Rank: 2

积分
91
金钱
70
HASS币
0
发表于 2024-1-6 11:33:30 | 显示全部楼层
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|Hassbian

GMT+8, 2024-4-28 01:30 , Processed in 0.059598 second(s), 34 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表