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

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

[经验分享] 明基投影仪RS232接入(之ESPHome版)

[复制链接]

22

主题

649

帖子

4502

积分

版主

Rank: 7Rank: 7Rank: 7

积分
4502
金钱
3838
HASS币
40
发表于 2024-8-25 23:25:21 | 显示全部楼层 |阅读模式
本帖最后由 whxciotw 于 2024-8-26 00:08 编辑

之前分享过投影仪接入的rs232-esp的mqtt方案,这是以前的帖子,这次再分享一个ESPHome的固件方案,灵活性更强。
主要参考来源:GitHub链接

ESPHome配置文件
substitutions:
  device_name: benq
  ip_address: 192.168.19.54
      
esphome:
  name: ${device_name}
  includes:
    - uart_read_line_sensor.h

esp8266:
  board: nodemcuv2

# Enable logging
logger:

# Enable UART. Please select the pins you're using on your board.
uart:
  id: projector
  tx_pin: D4  #GPIO2
  rx_pin: RX  #GPIO3
  baud_rate: 115200

# Enable Home Assistant API
api:

ota:
  platform: esphome

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  fast_connect: true  
  use_address: ${ip_address}
  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: ${device_name}
    password: !secret ap_password

captive_portal:

# This is our hub - it manages our connection to the projector.
text_sensor:
  - platform: custom
    lambda: |-
      auto my_custom_sensor = new UartReadLineSensor(id(projector));
      App.register_component(my_custom_sensor);
      return {my_custom_sensor};
    text_sensors:
      id: "uart_readline"
      on_value:
        then:
          - lambda: |-
             // Clean up the end of the string    
             std::string str = x;
             str = str.erase(str.size()-1, 1);

             // Parse commands and values
             std::string command = str.substr(1, str.find("=")-1); 
             std::string param = str.substr(str.find("=")+1, str.size());
             
             if ((param == "?") || (param == "+") || (param == "-")){
               return;
             }

             if (command == "VOL") {
               id(projector_volume).publish_state(atoi(param.c_str()));
             } else if (command == "LTIM") {
               id(projector_ltim).publish_state(atoi(param.c_str()));
             } else if (command == "POW") {
               id(projector_power).publish_state(param == "ON");
             } else if (command == "SOUR") {
               id(projector_source).publish_state(param.c_str());
             }

select:
  - platform: template
    name: ${device_name} Source
    id: projector_source
    # Change this to the inputs your projector has
    options:
      - HDMI1
      - HDMI2
      - USBREADER
    set_action:
      then:
        - lambda: |-
            if ((x) != id(projector_source).state) {
              std::string c = "\r*SOUR=" + x + "#\r";
              id(projector).write_array((const uint8_t*)c.c_str(), c.size());
              id(projector_source).publish_state(x);
            }
    
    
number:
  - platform: template
    id: projector_volume
    step: 1
    min_value: 0
    max_value: 50
    name: ${device_name} Volume
      
    set_action:
      then:
        - lambda: |-
            int target = round(x);
            int current = id(projector_volume).state;
            int delta = target - current;

            for (int i=0; i<abs(delta);i++) {
              std::string c = "";
              if (delta < 0) {
                  
                  c = "\r*vol=-#\r";
              }
              else if (delta > 0){
                  c = "\r*vol=+#\r";
              }
              else {
                // nothing
              }
              
              if (c != "") {
                id(projector).write_array((const uint8_t*)c.c_str(), c.size());
              }
            }
            
            id(projector_volume).publish_state(target);

    
      
sensor:

  - platform: template
    name: ${device_name} Lamp Hours
    id: projector_ltim


switch:
  - platform: template
    name: ${device_name} Power 
    id: projector_power

    turn_on_action:
      - uart.write: "\r*pow=on#\r"
    turn_off_action:
      - uart.write: "\r*pow=off#\r"
  
interval:
  - interval: 10s # not pretty, but works
    then:
      - uart.write: "\r*pow=?#\r"
      - delay: 1s
      - if:
          condition:
            lambda: 'return id(projector_power).state;'
          then:
            - uart.write: "\r*sour=?#\r"
            - delay: 1s
            - uart.write: "\r*vol=?#\r"
            - delay: 1s
            - uart.write: "\r*ltim=?#\r"

          else:
            - logger.log: "Projector is OFF"


      


uart_read_line_sensor.h文件
#include "esphome.h"

class UartReadLineSensor : public Component, public UARTDevice, public TextSensor {
 public:
  UartReadLineSensor(UARTComponent *parent) : UARTDevice(parent) {}

  void setup() override {
    // nothing to do here
  }

  int readline(int readch, char *buffer, int len)
  {
    static int pos = 0;
    int rpos;

    if (readch > 0) {
      switch (readch) {
        case '\n': // Ignore new-lines
          break;
        case '\r': // Return on CR
          rpos = pos;
          pos = 0;  // Reset position index ready for next time
          return rpos;
        default:
          if (pos < len-1) {
            buffer[pos++] = readch;
            buffer[pos] = 0;
          }
      }
    }
    // No end of line has been found, so return -1.
    return -1;
  }

  void loop() override {
    const int max_line_length = 80;
    static char buffer[max_line_length];
    while (available()) {
      if(readline(read(), buffer, max_line_length) > 0) {
        publish_state(buffer);
      }
    }
  }
};


评分

参与人数 1金钱 +12 收起 理由
隔壁的王叔叔 + 12 感谢楼主分享!

查看全部评分

回复

使用道具 举报

0

主题

38

帖子

267

积分

中级会员

Rank: 3Rank: 3

积分
267
金钱
229
HASS币
0
发表于 2024-8-26 10:52:14 | 显示全部楼层
感谢分享
回复

使用道具 举报

0

主题

38

帖子

267

积分

中级会员

Rank: 3Rank: 3

积分
267
金钱
229
HASS币
0
发表于 2024-8-26 11:00:50 | 显示全部楼层
其他牌子的投影仪不知道能不能用啊
回复

使用道具 举报

22

主题

649

帖子

4502

积分

版主

Rank: 7Rank: 7Rank: 7

积分
4502
金钱
3838
HASS币
40
 楼主| 发表于 2024-8-26 13:00:29 | 显示全部楼层
lxgxdx 发表于 2024-8-26 11:00
其他牌子的投影仪不知道能不能用啊

看 rs232 协议是否一致
回复

使用道具 举报

0

主题

38

帖子

267

积分

中级会员

Rank: 3Rank: 3

积分
267
金钱
229
HASS币
0
发表于 2024-8-26 20:57:20 | 显示全部楼层
whxciotw 发表于 2024-8-26 13:00
看 rs232 协议是否一致

怎么看协议是不是一样啊
回复

使用道具 举报

22

主题

649

帖子

4502

积分

版主

Rank: 7Rank: 7Rank: 7

积分
4502
金钱
3838
HASS币
40
 楼主| 发表于 2024-8-26 22:26:59 | 显示全部楼层
lxgxdx 发表于 2024-8-26 20:57
怎么看协议是不是一样啊

试着去问问AI
回复

使用道具 举报

3

主题

51

帖子

512

积分

高级会员

Rank: 4

积分
512
金钱
461
HASS币
0
发表于 前天 17:10 | 显示全部楼层
本帖最后由 fulinsky 于 2024-10-24 08:17 编辑

斑竹好,本人手上有HITACHI N3410W投影机,用的D1-mini,只想实现ha控制开关机,照葫芦画瓢您的方案,现在是能开机,但是开机后开关就变成关闭状态,也没有办法关机!请求大大伸手相助。投影机的232控制代码见下图: 截屏2024-10-22 17.00.13.png

下面是我的yaml代码:
esphome:
  name: mediaroom-bridge
  includes:
    - uart_read_line_sensor.h

logger:
  level: DEBUG #makes uart stream available in esphome logstream
  baud_rate: 0 #disable logging over uart

uart:
  id: uart_bus
  tx_pin: D4
  rx_pin: RX
  baud_rate: 19200

text_sensor:
- platform: custom
  lambda: |-
    auto my_custom_sensor = new UartReadLineSensor(id(uart_bus));
    App.register_component(my_custom_sensor);
    return {my_custom_sensor};
  text_sensors:
    id: "uart_readline"
    on_value:
      then:
        - lambda: |-
           // Clean up the end of the string    
           std::string str = x;
           str = str.erase(str.size()-1, 1);

           // Parse commands and values
           std::string command = str.substr(1, str.find("=")-1); 
           std::string param = str.substr(str.find("=")+1, str.size());
             
           if ((param == "?") || (param == "+") || (param == "-")){
             return;
           }

           if (command == "POW") {
             id(projector_power).publish_state(param == "ON");
           } 

switch:
  - platform: template
    name: "HITACHI Projector"
    id: projector_power
    turn_on_action:
      - uart.write: [0xBE, 0xEF, 0x03, 0x06, 0x00, 0xBA, 0xD2, 0x01, 0x00, 0x00, 0x60, 0x01, 0x00]
    turn_off_action:
      - uart.write: [0xBE, 0xEF, 0x03, 0x06, 0x00, 0x2A, 0xD3, 0x01, 0x00, 0x00, 0x60, 0x00, 0x00]

interval:
  - interval: 10s
    then:
      - uart.write:  [0xBE, 0xEF, 0x03, 0x06, 0x00, 0x19, 0xD3, 0x02, 0x00, 0x00, 0x60, 0x00, 0x00]
    
esp8266:
  board: d1_mini
  
web_server:
  port: 80

# Enable Home Assistant API
api:
  encryption:
    key: "XXXXXXXXXXXXXXXX"

ota:
  - platform: esphome
    password: "XXXXXXXXXXXXXXX"

wifi:
  ssid: "XXXX"
  password: "XXXXXXXX"
  fast_connect: True
  manual_ip: 
    static_ip: 192.168.1.XXX
    gateway: 192.168.1.1
    subnet: 255.255.255.0

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Mediaroom-Bridge"
    password: "XXXXXXXX"

captive_portal:

回复

使用道具 举报

22

主题

649

帖子

4502

积分

版主

Rank: 7Rank: 7Rank: 7

积分
4502
金钱
3838
HASS币
40
 楼主| 发表于 昨天 23:47 | 显示全部楼层
本帖最后由 whxciotw 于 2024-10-23 23:50 编辑
fulinsky 发表于 2024-10-22 17:10
斑竹大大好,本人手上有HITACHI N3410W投影机,用的D1-mini,只想实现ha控制开关机,照葫芦画瓢您的方案, ...
你试试这个,markdown发不出来,你将就看下

esphome:
  name: mediaroom-bridge
  includes:
    - uart_read_line_sensor.h

logger:
  level: DEBUG #makes uart stream available in esphome logstream
  baud_rate: 0 #disable logging over uart

uart:
  id: uart_bus
  tx_pin: D4
  rx_pin: RX
  baud_rate: 19200


switch:
  - platform: template
    name: "HITACHI Projector"
    id: projector_power
    assumed_state: true
    turn_on_action:
      - uart.write: [0xBE, 0xEF, 0x03, 0x06, 0x00, 0xBA, 0xD2, 0x01, 0x00, 0x00, 0x60, 0x01, 0x00]
    turn_off_action:
      - uart.write: [0xBE, 0xEF, 0x03, 0x06, 0x00, 0x2A, 0xD3, 0x01, 0x00, 0x00, 0x60, 0x00, 0x00]

esp8266:
  board: d1_mini

web_server:
  port: 80

# Enable Home Assistant API
api:
  encryption:
    key: "XXXXXXXXXXXXXXXX"

ota:
  - platform: esphome
    password: "XXXXXXXXXXXXXXX"

wifi:
  ssid: "XXXX"
  password: "XXXXXXXX"
  fast_connect: True
  manual_ip:
    static_ip: 192.168.1.XXX
    gateway: 192.168.1.1
    subnet: 255.255.255.0

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Mediaroom-Bridge"
    password: "XXXXXXXX"

captive_portal:

回复

使用道具 举报

3

主题

51

帖子

512

积分

高级会员

Rank: 4

积分
512
金钱
461
HASS币
0
发表于 1 小时前 | 显示全部楼层
本帖最后由 fulinsky 于 2024-10-24 08:28 编辑
whxciotw 发表于 2024-10-23 23:47
你试试这个,markdown发不出来,你将就看下

esphome:

修改后,下载project失败,加上text_sensor:就可以了,感谢!

<div style="color: rgb(232, 232, 233); background-color: rgb(30, 30, 30); font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, &quot;Liberation Mono&quot;, &quot;Courier New&quot;, monospace, Menlo, Monaco, &quot;Courier New&quot;, monospace; font-size: 12px; line-height: 18px; white-space: pre;"><div>text_sensor:</div><div>- platform: custom</div><div>  lambda: |-</div><div><span style="color: rgb(206, 145, 120);">    auto my_custom_sensor = new UartReadLineSensor(id(uart_bus));</span></div><div><span style="color: rgb(206, 145, 120);">    App.register_component(my_custom_sensor);</span></div><div><span style="color: rgb(206, 145, 120);">    return {my_custom_sensor};</span></div><div>  text_sensors:</div><div>    id: <span style="color: rgb(206, 145, 120);">"uart_readline"</span></div></div>

回复

使用道具 举报

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

本版积分规则

Archiver|手机版|小黑屋|Hassbian

GMT+8, 2024-10-24 09:26 , Processed in 0.115689 second(s), 34 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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