liuq пре 3 месеци
родитељ
комит
6bb84365c2
5 измењених фајлова са 157 додато и 25 уклоњено
  1. 12 1
      API_DOCUMENTATION.md
  2. 37 8
      api/ha.py
  3. 8 2
      ha_config_prod.yaml
  4. 66 10
      hardware/ha_devices_module.py
  5. 34 4
      templates/ha/index.html

+ 12 - 1
API_DOCUMENTATION.md

@@ -216,11 +216,22 @@
 | :--- | :--- | :--- |
 | **一楼大门玄关顶灯** | `/api/ha/entrance_lights/turn_on` | `/api/ha/entrance_lights/turn_off` |
 | **一楼大门玄关射灯** | `/api/ha/exhibition_spotlight/turn_on` | `/api/ha/exhibition_spotlight/turn_off` |
-| **一楼展厅顶灯** | `/api/ha/exhibition_ceiling_light/turn_on` | `/api/ha/exhibition_ceiling_light/turn_off` |
+| **一楼展厅顶灯 (等级)** | `/api/ha/exhibition_ceiling_lights/set_level` | (使用等级0关闭) |
 | **展厅桌面灯座总开关** | `/api/ha/exhibition_desktop_switch/turn_on` | `/api/ha/exhibition_desktop_switch/turn_off` |
 | **展厅桌面3D风扇投影** | `/api/ha/exhibition_3d_fan/turn_on` | `/api/ha/exhibition_3d_fan/turn_off` |
 | **展台桌子灯带** | `/api/ha/exhibition_stand_light_strip/turn_on` | `/api/ha/exhibition_stand_light_strip/turn_off` |
 
+### 展厅顶灯等级控制 (一楼)
+- **接口地址**: `/api/ha/exhibition_ceiling_lights/set_level`
+- **请求方式**: `POST`
+- **请求头**: `Content-Type: application/json`
+- **请求参数**:
+  ```json
+  {
+      "level": 1  // (必填) 等级 0-3 (0:全关, 1:单灯, 2:双灯, 3:全开)
+  }
+  ```
+
 ### 全局控制
 - **打开所有设备**: `/api/ha/turn_on_all` (POST)
 - **关闭所有设备**: `/api/ha/turn_off_all` (POST)

+ 37 - 8
api/ha.py

@@ -1,8 +1,8 @@
-from flask import Blueprint, jsonify
+from flask import Blueprint, jsonify, request
 from hardware.ha_devices_module import (
     turn_on_entrance_lights, turn_off_entrance_lights,
     turn_on_exhibition_spotlight, turn_off_exhibition_spotlight,
-    turn_on_exhibition_ceiling_light, turn_off_exhibition_ceiling_light,
+    turn_on_exhibition_ceiling_lights, turn_off_exhibition_ceiling_lights, set_exhibition_ceiling_light_level,
     turn_on_exhibition_desktop_switch, turn_off_exhibition_desktop_switch,
     turn_on_exhibition_3d_fan, turn_off_exhibition_3d_fan,
     turn_on_exhibition_stand_light_strip, turn_off_exhibition_stand_light_strip,
@@ -106,14 +106,14 @@ def turn_off_exhibition_spotlight_api():
             "message": f"关闭一楼大门玄关射灯失败: {str(e)}"
         }), 500
 
-@ha_bp.route('/api/ha/exhibition_ceiling_light/turn_on', methods=['POST'])
+@ha_bp.route('/api/ha/exhibition_ceiling_lights/turn_on', methods=['POST'])
 @login_required
-def turn_on_exhibition_ceiling_light_api():
+def turn_on_exhibition_ceiling_lights_api():
     """打开一楼展厅顶灯"""
     try:
         def task():
             try:
-                turn_on_exhibition_ceiling_light()
+                turn_on_exhibition_ceiling_lights()
             except Exception as e:
                 logger.error(f"异步打开一楼展厅顶灯异常: {str(e)}")
         
@@ -129,14 +129,14 @@ def turn_on_exhibition_ceiling_light_api():
             "message": f"打开一楼展厅顶灯失败: {str(e)}"
         }), 500
 
-@ha_bp.route('/api/ha/exhibition_ceiling_light/turn_off', methods=['POST'])
+@ha_bp.route('/api/ha/exhibition_ceiling_lights/turn_off', methods=['POST'])
 @login_required
-def turn_off_exhibition_ceiling_light_api():
+def turn_off_exhibition_ceiling_lights_api():
     """关闭一楼展厅顶灯"""
     try:
         def task():
             try:
-                turn_off_exhibition_ceiling_light()
+                turn_off_exhibition_ceiling_lights()
             except Exception as e:
                 logger.error(f"异步关闭一楼展厅顶灯异常: {str(e)}")
         
@@ -152,6 +152,35 @@ def turn_off_exhibition_ceiling_light_api():
             "message": f"关闭一楼展厅顶灯失败: {str(e)}"
         }), 500
 
+@ha_bp.route('/api/ha/exhibition_ceiling_lights/set_level', methods=['POST'])
+@login_required
+def set_exhibition_ceiling_light_level_api():
+    """设置一楼展厅顶灯等级 (0-3)"""
+    try:
+        data = request.get_json()
+        if not data or 'level' not in data:
+            return jsonify({"success": False, "message": "缺少参数 level"}), 400
+            
+        level = data['level']
+        
+        def task():
+            try:
+                set_exhibition_ceiling_light_level(level)
+            except Exception as e:
+                logger.error(f"异步设置一楼展厅顶灯等级异常: {str(e)}")
+        
+        threading.Thread(target=task).start()
+        return jsonify({
+            "success": True,
+            "message": f"已发送设置一楼展厅顶灯等级指令 ({level}) - 异步执行"
+        })
+    except Exception as e:
+        logger.error(f"设置一楼展厅顶灯等级异常: {str(e)}")
+        return jsonify({
+            "success": False,
+            "message": f"设置一楼展厅顶灯等级失败: {str(e)}"
+        }), 500
+
 @ha_bp.route('/api/ha/exhibition_desktop_switch/turn_on', methods=['POST'])
 @login_required
 def turn_on_exhibition_desktop_switch_api():

+ 8 - 2
ha_config_prod.yaml

@@ -12,8 +12,14 @@ ha_devices:
   exhibition_spotlight:
     name: "一楼大门玄关射灯"
     entity_id: "switch.babai_cn_557604830_bb101s_on_p_2_1"
-  exhibition_ceiling_light:
-    name: "一楼展厅顶灯"
+  exhibition_ceiling_light_1:
+    name: "一楼展厅顶灯1"
+    entity_id: "switch.zhi_neng_dao_gui_shi_tong_duan_qi_switch"
+  exhibition_ceiling_light_2:
+    name: "一楼展厅顶灯2"
+    entity_id: "switch.zhi_neng_dao_gui_shi_tong_duan_qi_switch"
+  exhibition_ceiling_light_3:
+    name: "一楼展厅顶灯3"
     entity_id: "switch.zhi_neng_dao_gui_shi_tong_duan_qi_switch"
   exhibition_desktop_switch:
     name: "展厅桌面的灯座总开关"

+ 66 - 10
hardware/ha_devices_module.py

@@ -127,13 +127,66 @@ class HADeviceController:
         """关闭一楼大门玄关射灯"""
         return self.control_device('exhibition_spotlight', 'turn_off')
         
-    def turn_on_exhibition_ceiling_light(self):
-        """打开一楼展厅顶灯"""
-        return self.control_device('exhibition_ceiling_light', 'turn_on')
+    def turn_on_exhibition_ceiling_lights(self):
+        """打开一楼展厅顶灯 (全部)"""
+        r1 = self.control_device('exhibition_ceiling_light_1', 'turn_on')
+        r2 = self.control_device('exhibition_ceiling_light_2', 'turn_on')
+        r3 = self.control_device('exhibition_ceiling_light_3', 'turn_on')
+        return r1 and r2 and r3
+
+    def turn_off_exhibition_ceiling_lights(self):
+        """关闭一楼展厅顶灯 (全部)"""
+        r1 = self.control_device('exhibition_ceiling_light_1', 'turn_off')
+        r2 = self.control_device('exhibition_ceiling_light_2', 'turn_off')
+        r3 = self.control_device('exhibition_ceiling_light_3', 'turn_off')
+        return r1 and r2 and r3
+
+    def set_exhibition_ceiling_light_level(self, level):
+        """
+        设置一楼展厅顶灯等级 (0-3)
+        0: 全关
+        1: 开启灯1 (关2,3)
+        2: 开启灯1,2 (关3)
+        3: 全开 (1,2,3)
+        """
+        logger.info(f"设置展厅顶灯等级: {level}")
+        
+        # 确保 level 在 0-3 之间
+        try:
+            level = int(level)
+            if level < 0: level = 0
+            if level > 3: level = 3
+        except (ValueError, TypeError):
+            logger.error(f"无效的灯光等级: {level}")
+            return False
+
+        r1, r2, r3 = True, True, True
 
-    def turn_off_exhibition_ceiling_light(self):
-        """关闭一楼展厅顶灯"""
-        return self.control_device('exhibition_ceiling_light', 'turn_off')
+        if level == 0:
+            # 0: 全关
+            r1 = self.control_device('exhibition_ceiling_light_1', 'turn_off')
+            r2 = self.control_device('exhibition_ceiling_light_2', 'turn_off')
+            r3 = self.control_device('exhibition_ceiling_light_3', 'turn_off')
+        
+        elif level == 1:
+            # 1: 开启灯1 (关2,3)
+            r1 = self.control_device('exhibition_ceiling_light_1', 'turn_on')
+            r2 = self.control_device('exhibition_ceiling_light_2', 'turn_off')
+            r3 = self.control_device('exhibition_ceiling_light_3', 'turn_off')
+            
+        elif level == 2:
+            # 2: 开启灯1,2 (关3)
+            r1 = self.control_device('exhibition_ceiling_light_1', 'turn_on')
+            r2 = self.control_device('exhibition_ceiling_light_2', 'turn_on')
+            r3 = self.control_device('exhibition_ceiling_light_3', 'turn_off')
+            
+        elif level == 3:
+            # 3: 全开
+            r1 = self.control_device('exhibition_ceiling_light_1', 'turn_on')
+            r2 = self.control_device('exhibition_ceiling_light_2', 'turn_on')
+            r3 = self.control_device('exhibition_ceiling_light_3', 'turn_on')
+
+        return r1 and r2 and r3
 
     def turn_on_exhibition_desktop_switch(self):
         """打开展厅桌面的灯座总开关"""
@@ -192,11 +245,14 @@ def turn_on_exhibition_spotlight():
 def turn_off_exhibition_spotlight():
     return ha_device_controller.turn_off_exhibition_spotlight()
 
-def turn_on_exhibition_ceiling_light():
-    return ha_device_controller.turn_on_exhibition_ceiling_light()
+def turn_on_exhibition_ceiling_lights():
+    return ha_device_controller.turn_on_exhibition_ceiling_lights()
+
+def turn_off_exhibition_ceiling_lights():
+    return ha_device_controller.turn_off_exhibition_ceiling_lights()
 
-def turn_off_exhibition_ceiling_light():
-    return ha_device_controller.turn_off_exhibition_ceiling_light()
+def set_exhibition_ceiling_light_level(level):
+    return ha_device_controller.set_exhibition_ceiling_light_level(level)
 
 def turn_on_exhibition_desktop_switch():
     return ha_device_controller.turn_on_exhibition_desktop_switch()

+ 34 - 4
templates/ha/index.html

@@ -33,11 +33,20 @@
 
         <!-- 3. 展厅顶灯 -->
         <div style="background: #f8f9fa; padding: 15px; border-radius: 8px; border: 1px solid #eee; margin-bottom: 15px;">
-            <h4 style="margin-bottom: 15px; color: #555;">一楼展厅顶灯</h4>
+            <h4 style="margin-bottom: 15px; color: #555;">一楼展厅顶灯 (等级控制)</h4>
             <div class="control-row">
-                <div class="control-group" style="display: flex; gap: 15px;">
-                     <button class="btn btn-secondary" style="flex: 1;" onclick="controlHALight('exhibition_ceiling_light', 'turn_on')">打开</button>
-                     <button class="btn" style="flex: 1; background-color: #34495e; color: white;" onclick="controlHALight('exhibition_ceiling_light', 'turn_off')">关闭</button>
+                <div class="control-group" style="display: flex; gap: 10px; align-items: center;">
+                    <span style="font-weight: bold; min-width: 30px;" id="ceilingLightLevelVal">0</span>
+                    <input type="range" id="ceilingLightLevel" min="0" max="3" value="0" step="1" 
+                           style="flex: 1; height: 30px;"
+                           onchange="controlHALightLevel(this.value)"
+                           oninput="document.getElementById('ceilingLightLevelVal').textContent = this.value">
+                </div>
+                <div style="display: flex; justify-content: space-between; font-size: 12px; color: #666; margin-top: 5px; padding: 0 5px;">
+                    <span>0 (全关)</span>
+                    <span>1 (单灯)</span>
+                    <span>2 (双灯)</span>
+                    <span>3 (全开)</span>
                 </div>
             </div>
         </div>
@@ -73,5 +82,26 @@
             showLoading(false);
         }
     }
+
+    async function controlHALightLevel(level) {
+        try {
+            showLoading(true);
+            const response = await fetch('/api/ha/exhibition_ceiling_lights/set_level', {
+                method: 'POST',
+                headers: { 'Content-Type': 'application/json' },
+                body: JSON.stringify({ level: parseInt(level) })
+            });
+            const result = await response.json();
+            if (result.success) {
+                showMessage(result.message);
+            } else {
+                showMessage(result.message, 'error');
+            }
+        } catch (error) {
+            showMessage('网络错误: ' + error.message, 'error');
+        } finally {
+            showLoading(false);
+        }
+    }
 </script>
 {% endblock %}