You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular 7中如何基于Sonoff接口响应动态切换CSS类并实时更新

实现Sonoff Tasmota设备状态同步与样式切换(Angular新手友好)

嗨,我来帮你搞定这个需求!你已经用Angular初始化了项目,接下来我们一步步实现两个核心功能:调用接口切换CSS类,以及实体按键按下时自动同步页面状态。

第一步:准备工作——导入HttpClientModule

首先,Angular的HTTP请求需要依赖HttpClientModule,我们得先在根模块里导入它:

打开src/app/app.module.ts,修改代码:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule } from '@angular/common/http'; // 导入HTTP模块
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule, // 添加到imports数组
    AppRoutingModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

第二步:创建Sonoff服务封装HTTP请求

Angular推荐把数据请求逻辑放在服务里,这样组件更简洁,也方便复用。我们创建一个专门的服务来和Sonoff设备交互:

在终端运行命令创建服务:

ng generate service sonoff
# 或者简写 ng g s sonoff

打开src/app/sonoff.service.ts,编写请求方法:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class SonoffService {
  // 替换成你的Sonoff设备实际IP地址
  private deviceIp = 'http://sonoff';

  constructor(private http: HttpClient) { }

  // 获取当前电源状态
  getPowerStatus(): Observable<{ power: string }> {
    return this.http.get<{ power: string }>(`${this.deviceIp}/cmnd?cmnd=Power`);
  }

  // 可选:切换电源状态的方法(如果需要在页面上控制设备)
  togglePower(): Observable<{ power: string }> {
    return this.http.get<{ power: string }>(`${this.deviceIp}/cmnd?cmnd=Power%20Toggle`);
  }
}

第三步:组件里实现状态获取与实时同步

接下来在你的主组件(比如AppComponent)里,注入Sonoff服务,实现状态初始化和轮询更新——轮询就是解决实体按键按下后页面同步的核心方案:

打开src/app/app.component.ts:

import { Component, OnInit, OnDestroy } from '@angular/core';
import { SonoffService } from './sonoff.service';
import { Subscription } from 'rxjs';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit, OnDestroy {
  title = 'PrinterPanel';
  powerStatus: string = 'off'; // 默认初始状态
  private pollTimer?: any;
  private pollInterval = 3000; // 每3秒轮询一次,可按需调整

  constructor(private sonoffService: SonoffService) { }

  ngOnInit(): void {
    // 页面加载时先获取一次状态
    this.updatePowerStatus();
    // 启动轮询,实时同步设备状态
    this.startPolling();
  }

  ngOnDestroy(): void {
    // 组件销毁时停止轮询,避免内存泄漏
    this.stopPolling();
  }

  // 更新电源状态的核心方法
  private updatePowerStatus(): void {
    this.sonoffService.getPowerStatus().subscribe({
      next: (response) => {
        // 统一转成小写,避免接口返回大小写不一致的问题
        this.powerStatus = response.power.toLowerCase();
      },
      error: (err) => {
        console.error('获取设备状态失败:', err);
        // 可选:给用户显示错误提示,比如弹窗或文字
      }
    });
  }

  // 启动轮询
  private startPolling(): void {
    this.pollTimer = setInterval(() => {
      this.updatePowerStatus();
    }, this.pollInterval);
  }

  // 停止轮询
  private stopPolling(): void {
    if (this.pollTimer) {
      clearInterval(this.pollTimer);
      this.pollTimer = undefined;
    }
  }

  // 可选:页面点击按钮切换设备状态
  toggleDevicePower(): void {
    this.sonoffService.togglePower().subscribe({
      next: (response) => {
        this.powerStatus = response.power.toLowerCase();
      },
      error: (err) => {
        console.error('切换设备状态失败:', err);
      }
    });
  }
}

第四步:HTML模板绑定样式类

现在在组件的HTML模板里,根据powerStatus变量用[ngClass]切换CSS类,实现状态样式变化:

打开src/app/app.component.html:

<h1>Sonoff 设备控制面板</h1>

<!-- 设备状态显示块,根据powerStatus切换样式 -->
<div class="device-status" [ngClass]="{ 'active': powerStatus === 'on' }">
  <span>{{ powerStatus === 'on' ? '设备已开启' : '设备已关闭' }}</span>
</div>

<!-- 可选:页面控制按钮 -->
<button (click)="toggleDevicePower()" class="control-btn">
  {{ powerStatus === 'on' ? '关闭设备' : '开启设备' }}
</button>

第五步:添加CSS样式

最后在组件的CSS文件里定义不同状态的样式:

打开src/app/app.component.css:

.device-status {
  padding: 16px;
  border-radius: 8px;
  background-color: #f5f5f5;
  margin: 20px 0;
  font-size: 18px;
  text-align: center;
  transition: background-color 0.3s ease;
}

/* 设备开启时的样式 */
.device-status.active {
  background-color: #4caf50;
  color: white;
}

.control-btn {
  padding: 10px 20px;
  font-size: 16px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  background-color: #2196f3;
  color: white;
}

.control-btn:hover {
  background-color: #1976d2;
}

关于实体按键同步的补充说明

上面的轮询方案是最适合新手的简单实现——每隔几秒主动请求一次设备状态,这样当你按下实体按键改变设备状态后,最多3秒页面就会同步更新。

如果想要更高效的实时同步(比如毫秒级响应),可以考虑用Tasmota的MQTT功能:

  • Tasmota设备可以配置MQTT服务器,当状态变化时主动推送消息到MQTT主题
  • Angular项目里使用MQTT客户端库(比如ngx-mqtt)订阅这个主题,实时接收状态变化并更新页面
    不过这个方案需要额外配置MQTT服务器,对新手来说门槛稍高,你可以先把轮询方案跑通,之后再探索MQTT。

内容的提问来源于stack exchange,提问作者TolleyB-J

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 06:29:32