openclaw能否像电影钢铁侠中的贾维斯一样帮你管理家里的电器设备呢?答案是可以,只需要简单训练将家里智能设备接入协议告诉openclaw,他就能自己写程序控制智能设备,然后在后续对话时识别你的指令,实现智能管家。

下面以openclaw控制客厅电视智能插座为例训练过程

直接一句话搞定!!!

D盘训练代码main.py内容:

import sys
import base64
import logging
import requests
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout,
                             QHBoxLayout, QLabel, QLineEdit, QPushButton,
                             QMessageBox, QStatusBar, QTextEdit)
from PyQt5.QtCore import QThread, pyqtSignal, Qt
from PyQt5.QtGui import QFont

# ------------------ 日志配置 ------------------
logging.basicConfig(
    level=logging.DEBUG,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    handlers=[logging.StreamHandler(sys.stdout)]
)
logger = logging.getLogger("CyberSwitch")

# ------------------ 网络请求函数 ------------------
def get_code_img(server_url):
    """获取验证码,返回包含 uuid 的字典"""
    url = server_url.rstrip('/') + "/captchaImage"
    logger.info(f"请求验证码 URL: {url}")
    try:
        resp = requests.get(url, timeout=10)
        logger.debug(f"验证码响应状态码: {resp.status_code}")
        resp.raise_for_status()
        data = resp.json()
        logger.debug(f"验证码响应内容: {data}")
        if "img" in data and data["img"]:
            data["img_bytes"] = base64.b64decode(data["img"])
        return data
    except Exception as e:
        logger.exception("获取验证码失败")
        raise Exception(f"获取验证码失败: {e}")

def login_in(server_url, username, password, code, uuid):
    """用户登录,返回包含 token 的字典"""
    url = server_url.rstrip('/') + "/login"
    payload = {
        "username": username,
        "password": password,
        "code": code,
        "uuid": uuid
    }
    headers = {"Content-Type": "application/json"}
    logger.info(f"登录请求 URL: {url}")
    logger.debug(f"登录请求参数: {payload}")
    try:
        resp = requests.post(url, json=payload, headers=headers, timeout=10)
        logger.debug(f"登录响应状态码: {resp.status_code}")
        resp.raise_for_status()
        data = resp.json()
        logger.debug(f"登录响应内容: {data}")
        return data
    except Exception as e:
        logger.exception("登录失败")
        raise Exception(f"登录失败: {e}")

def send_switch_cmd(server_url, token, eqp_id, flag, time):
    """发送开关指令(flag 固定为 "1")"""
    url = server_url.rstrip('/') + "/switch/eqp/time/add"
    form_data = {
        "eqpId": eqp_id,
        "flag": flag,      # 固定为 "1"
        "time": str(time)  # 确保字符串
    }
    headers = {"Authorization": f"Bearer {token}"}
    logger.info(f"发送控制指令 URL: {url}")
    logger.debug(f"控制指令参数: {form_data}")
    try:
        resp = requests.post(url, data=form_data, headers=headers, timeout=10)
        logger.debug(f"控制指令响应状态码: {resp.status_code}")
        resp.raise_for_status()
        data = resp.json()
        logger.debug(f"控制指令响应内容: {data}")
        if data.get("code") == 401:
            raise Exception(f"服务器返回: {data.get('code')} {data.get('msg')}")
        return data
    except Exception as e:
        logger.exception("发送命令失败")
        raise Exception(f"发送命令失败: {e}")

# ------------------ 工作线程 ------------------
class WorkerThread(QThread):
    finished = pyqtSignal(object)
    error = pyqtSignal(str)

    def __init__(self, parent=None):
        super().__init__(parent)

class LoginThread(WorkerThread):
    def __init__(self, server_url, username, password, code):
        super().__init__()
        self.server_url = server_url
        self.username = username
        self.password = password
        self.code = code

    def run(self):
        try:
            code_data = get_code_img(self.server_url)
            uuid = code_data.get("uuid")
            if not uuid:
                raise Exception("未获取到 uuid")
            login_data = login_in(self.server_url, self.username, self.password, self.code, uuid)
            result = {
                "token": login_data.get("token"),
                "code_data": code_data,
                "login_data": login_data
            }
            self.finished.emit(result)
        except Exception as e:
            self.error.emit(str(e))

class ControlThread(WorkerThread):
    def __init__(self, server_url, token, eqp_id, flag, time):
        super().__init__()
        self.server_url = server_url
        self.token = token
        self.eqp_id = eqp_id
        self.flag = flag
        self.time = time

    def run(self):
        try:
            result = send_switch_cmd(self.server_url, self.token, self.eqp_id, self.flag, self.time)
            self.finished.emit(result)
        except Exception as e:
            self.error.emit(str(e))

# ------------------ 主窗口 ------------------
class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        # 配置信息
        self.server_url = "http://your_server_url"   # 服务器地址
        self.username = "1832xxxx591"
        self.password = "ff415926"
        self.code = "kwxxxxtch"          # 固定验证码
        self.eqp_id = "24d7xxxebaa2"    # 设备ID

        self.token = None
        self.initUI()
        self.auto_login()

    def initUI(self):
        self.setWindowTitle("赛博朋克智能开关")
        self.setGeometry(100, 100, 650, 450)
        self.setMinimumSize(550, 350)

        # 全局样式表(赛博朋克风格)
        self.setStyleSheet("""
            QMainWindow {
                background-color: #0a0f0f;
            }
            QLabel {
                color: #0ff;
                font-family: 'Courier New';
                font-size: 14px;
                font-weight: bold;
            }
            QLineEdit {
                background-color: #1a1f2a;
                color: #0ff;
                border: 2px solid #0ff;
                border-radius: 5px;
                padding: 5px;
                font-family: 'Courier New';
                font-size: 14px;
            }
            QPushButton {
                background-color: #1a1f2a;
                color: #0ff;
                border: 2px solid #0ff;
                border-radius: 5px;
                padding: 12px 24px;
                font-family: 'Courier New';
                font-size: 16px;
                font-weight: bold;
                min-width: 100px;
            }
            QPushButton:hover {
                background-color: #0ff;
                color: #0a0f0f;
                border: 2px solid #0ff;
            }
            QPushButton:pressed {
                background-color: #00cccc;
            }
            QStatusBar {
                background-color: #1a1f2a;
                color: #0ff;
                border-top: 1px solid #0ff;
                font-family: 'Courier New';
            }
            QTextEdit {
                background-color: #1a1f2a;
                color: #0ff;
                border: 1px solid #0ff;
                font-family: 'Courier New';
                font-size: 12px;
            }
        """)

        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        layout = QVBoxLayout(central_widget)

        # 标题
        title = QLabel("⚡ 赛博智能控制终端 ⚡")
        title.setAlignment(Qt.AlignCenter)
        title.setStyleSheet("font-size: 24px; color: #f0f; border-bottom: 2px solid #f0f; padding-bottom: 10px;")
        layout.addWidget(title)

        # 状态标签
        self.status_label = QLabel("状态: 正在登录...")
        self.status_label.setStyleSheet("color: #ff0; font-size: 16px;")
        layout.addWidget(self.status_label)

        # 设备信息
        device_label = QLabel(f"设备: 大冶客厅电视 (ID: {self.eqp_id})")
        device_label.setStyleSheet("font-size: 14px; color: #0ff; margin: 5px;")
        layout.addWidget(device_label)

        # 定时输入区域
        timer_layout = QHBoxLayout()
        timer_label = QLabel("定时秒数:")
        self.time_edit = QLineEdit("30")   # 默认30秒
        self.time_edit.setPlaceholderText("输入正整数")
        timer_layout.addWidget(timer_label)
        timer_layout.addWidget(self.time_edit)
        layout.addLayout(timer_layout)

        # 三个按钮水平布局
        button_layout = QHBoxLayout()
        self.on_button = QPushButton("常开")
        self.timer_button = QPushButton("定时")
        self.off_button = QPushButton("关闭")

        self.on_button.clicked.connect(self.send_on_command)
        self.timer_button.clicked.connect(self.send_timer_command)
        self.off_button.clicked.connect(self.send_off_command)

        button_layout.addWidget(self.on_button)
        button_layout.addWidget(self.timer_button)
        button_layout.addWidget(self.off_button)
        layout.addLayout(button_layout)

        # 日志区域
        log_label = QLabel("📋 操作日志")
        log_label.setStyleSheet("color: #f0f; font-size: 16px; margin-top: 10px;")
        layout.addWidget(log_label)

        self.log_text = QTextEdit()
        self.log_text.setReadOnly(True)
        self.log_text.setMaximumHeight(150)
        layout.addWidget(self.log_text)

        # 状态栏
        self.status_bar = QStatusBar()
        self.setStatusBar(self.status_bar)
        self.status_bar.showMessage("就绪")

        # 初始禁用按钮,登录成功后才启用
        self.on_button.setEnabled(False)
        self.timer_button.setEnabled(False)
        self.off_button.setEnabled(False)

    def log_message(self, msg, level="info"):
        """在界面日志区域和控制台同时输出"""
        if level == "error":
            logger.error(msg)
            self.log_text.append(f"<span style='color:#f66;'>[ERROR] {msg}</span>")
        elif level == "warning":
            logger.warning(msg)
            self.log_text.append(f"<span style='color:#ff0;'>[WARN] {msg}</span>")
        else:
            logger.info(msg)
            self.log_text.append(f"<span style='color:#0ff;'>[INFO] {msg}</span>")

    def auto_login(self):
        self.log_message("开始自动登录流程...")
        self.status_label.setText("状态: 正在登录...")
        self.status_bar.showMessage("登录中...")
        self.login_thread = LoginThread(self.server_url, self.username, self.password, self.code)
        self.login_thread.finished.connect(self.on_login_success)
        self.login_thread.error.connect(self.on_login_error)
        self.login_thread.start()

    def on_login_success(self, result):
        self.token = result.get("token")
        if not self.token:
            self.on_login_error("登录成功但未获取到 token")
            return
        self.log_message("登录成功,token 已获取")
        self.status_label.setText("状态: 已登录")
        self.status_bar.showMessage("登录成功")
        self.on_button.setEnabled(True)
        self.timer_button.setEnabled(True)
        self.off_button.setEnabled(True)

    def on_login_error(self, err_msg):
        self.log_message(f"登录失败: {err_msg}", level="error")
        self.status_label.setText("状态: 登录失败")
        self.status_bar.showMessage("登录失败")
        QMessageBox.critical(self, "登录错误", f"自动登录失败: {err_msg}")

    def send_on_command(self):
        """常开:time = -1"""
        if not self.token:
            QMessageBox.warning(self, "警告", "尚未登录,请稍后重试")
            return
        self.log_message("发送常开命令 (time=-1)")
        self.status_bar.showMessage("正在发送常开命令...")
        self.control_thread = ControlThread(self.server_url, self.token, self.eqp_id, "1", "-1")
        self.control_thread.finished.connect(self.on_command_success)
        self.control_thread.error.connect(self.on_command_error)
        self.control_thread.start()

    def send_timer_command(self):
        """定时:使用输入框中的秒数"""
        if not self.token:
            QMessageBox.warning(self, "警告", "尚未登录,请稍后重试")
            return
        time_str = self.time_edit.text().strip()
        if not time_str:
            QMessageBox.warning(self, "输入错误", "请输入定时秒数")
            return
        try:
            time_val = int(time_str)
        except ValueError:
            QMessageBox.warning(self, "输入错误", "定时秒数必须是整数")
            return
        if time_val <= 0:
            QMessageBox.warning(self, "输入错误", "定时秒数必须为正整数")
            return
        self.log_message(f"发送定时命令 (time={time_val})")
        self.status_bar.showMessage(f"正在发送定时命令 ({time_val}秒)...")
        self.control_thread = ControlThread(self.server_url, self.token, self.eqp_id, "1", str(time_val))
        self.control_thread.finished.connect(self.on_command_success)
        self.control_thread.error.connect(self.on_command_error)
        self.control_thread.start()

    def send_off_command(self):
        """关闭:time = 0"""
        if not self.token:
            QMessageBox.warning(self, "警告", "尚未登录,请稍后重试")
            return
        self.log_message("发送关闭命令 (time=0)")
        self.status_bar.showMessage("正在发送关闭命令...")
        self.control_thread = ControlThread(self.server_url, self.token, self.eqp_id, "1", "0")
        self.control_thread.finished.connect(self.on_command_success)
        self.control_thread.error.connect(self.on_command_error)
        self.control_thread.start()

    def on_command_success(self, result):
        msg = result.get("msg", "未知")
        code = result.get("code")
        self.log_message(f"命令响应: code={code}, msg={msg}")
        self.status_bar.showMessage("命令发送成功")
        if code != 200:
            self.log_message(f"命令执行可能未成功: {msg}", level="warning")
            QMessageBox.warning(self, "命令结果", f"命令执行可能未成功: {msg}")
        else:
            self.log_message("命令执行成功")
            QMessageBox.information(self, "成功", f"命令已发送: {msg}")

    def on_command_error(self, err_msg):
        self.log_message(f"命令发送失败: {err_msg}", level="error")
        self.status_bar.showMessage("命令发送失败")
        QMessageBox.critical(self, "命令错误", f"发送失败: {err_msg}")

if __name__ == "__main__":
    app = QApplication(sys.argv)
    font = QFont("Courier New", 10)
    app.setFont(font)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

openclaw思考过程:

 

 

训练结束,测试一下。

测试成功!

 

 

 

 

 

 

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐