from time import sleep
from appium.webdriver.common.appiumby import AppiumBy
from dominate.tags import button
from pygments.console import light_colors
import logging
from time import sleep
from appium.options.android import UiAutomator2Options
import logging
from selenium import webdriver

def app_setup_driver(platformName, platformVersion, deviceName, appPackage, appActivity, udid):

    desired_caps = {
        'platformName': platformName,  # 被测手机是安卓
        'platformVersion': platformVersion,  # 手机安卓版本，如果是鸿蒙系统，依次尝试 12、11、10 这些版本号
        'deviceName': deviceName,  # 设备名，安卓手机可以随意填写
        'appPackage': appPackage,  # 启动APP Package名称
        'appActivity': appActivity,  # 启动Activity名称
        'unicodeKeyboard': True,  # 自动化需要输入中文时填True
        'resetKeyboard': True,  # 执行完程序恢复原来输入法
        'noReset': True,  # 不要重置App
        'newCommandTimeout': 6000,
        'automationName': 'UiAutomator2',
        'skipUnlock': True,
        'autoGrantPermissions': True,
        'udid':udid
    }
    logging.info(f"desired_caps参数：{desired_caps}")

    try:
        logging.info("正在初始化 Appium 驱动程序...")
        driver = webdriver.Remote('http://localhost:4723/wd/hub',
                                  options=UiAutomator2Options().load_capabilities(desired_caps))
        logging.info("Appium 驱动程序初始化成功。")
        return driver
    except Exception as e:
        logging.error(f"初始化驱动程序失败: {e}")
        raise

def swipe_up(app_driver):
    # 获取屏幕尺寸
    size = app_driver.get_window_size()
    start_x = size['width'] // 2
    start_y = int(size['height'] * 0.2)  # 起始y坐标，屏幕高度的20%
    end_x = start_x
    end_y = int(size['height'] * 0.8)  # 结束y坐标，屏幕高度的80%

    # 执行滑动操作
    app_driver.swipe(start_x, start_y, end_x, end_y, duration=500)

from PIL import Image
import numpy as np
import os
import logging

# 配置日志记录
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')


def compare_brightness(light_down_path, light_on_path, threshold=1):
    """
    对比两张图片的亮度，返回亮度是否增加的布尔值。
    light_on_path：传入暗色的图片
    light_down_path：传入亮色的图片
    """
    try:
        image1 = Image.open(light_down_path).convert('L')  # 转换为灰度图像
        image2 = Image.open(light_on_path).convert('L')  # 转换为灰度图像

        # 将图像转换为numpy数组
        array1 = np.array(image1)
        array2 = np.array(image2)

        # 计算平均亮度
        avg_brightness1 = np.mean(array1)
        avg_brightness2 = np.mean(array2)

        logging.info(f"关闭灯光时的平均亮度: {avg_brightness1}")
        logging.info(f"打开灯光时的平均亮度: {avg_brightness2}")

        # 判断亮度是否增加，考虑阈值
        brightness_increase = avg_brightness2 - avg_brightness1
        logging.info(f"亮度变化量: {brightness_increase}")

        return brightness_increase > threshold
    except Exception as e:
        logging.error(f"对比亮度时发生错误: {e}", exc_info=True)
        return False

# if __name__ == '__main__':
#     logging.info("开始对比亮度")
#
#     image1_path = r'D:\GithubData\自动化\ubains-module-test\预定系统\Base\captured_frame2.jpg'
#     image2_path = r'D:\GithubData\自动化\ubains-module-test\预定系统\Base\captured_frame.jpg'
#
#     # 检查图片路径是否存在
#     if not os.path.exists(image1_path):
#         logging.error(f"图片 {image1_path} 不存在")
#         exit(1)
#     if not os.path.exists(image2_path):
#         logging.error(f"图片 {image2_path} 不存在")
#         exit(1)
#
#     # 对比两张截图的亮度
#     result = compare_brightness(image1_path, image2_path)
#     logging.info(f"亮度比较结果: {result}")
#
#     if result:
#         logging.info("灯光已成功打开")
#     else:
#         logging.error("灯光未成功打开")

import cv2
import numpy as np

def compare_images_feature_matching(image1_path, image2_path):
    """
    使用特征匹配对比两张图片的相似度。
    """
    try:
        image1 = cv2.imread(image1_path, cv2.IMREAD_GRAYSCALE)
        image2 = cv2.imread(image2_path, cv2.IMREAD_GRAYSCALE)

        # 初始化ORB检测器
        orb = cv2.ORB_create()

        # 查找关键点和描述符
        kp1, des1 = orb.detectAndCompute(image1, None)
        kp2, des2 = orb.detectAndCompute(image2, None)

        # BFMatcher对象
        bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)

        # 匹配描述符
        matches = bf.match(des1, des2)

        # 按距离排序
        matches = sorted(matches, key=lambda x: x.distance)

        # 计算匹配点的数量
        num_matches = len(matches)
        logging.info(f"匹配点数量: {num_matches}")

        # 判断匹配点数量是否在可接受范围内
        return num_matches > 10  # 可以根据需要调整阈值
    except Exception as e:
        logging.error(f"对比图片时发生错误: {e}", exc_info=True)
        return False


# if __name__ == '__main__':
#     logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
#     logging.info("开始对比图片")
#
#     image1_path = r'D:\GithubData\自动化\ubains-module-test\预定系统\Base\captured_frame2.jpg'
#     image2_path = r'D:\GithubData\自动化\ubains-module-test\预定系统\Base\captured_frame.jpg'
#
#     if not os.path.exists(image1_path):
#         logging.error(f"图片 {image1_path} 不存在")
#         exit(1)
#     if not os.path.exists(image2_path):
#         logging.error(f"图片 {image2_path} 不存在")
#         exit(1)
#
#     # 对比两张截图的相似度
#     if compare_images_feature_matching(image1_path, image2_path):
#         logging.info("图片相同")
#     else:
#         logging.error("图片不同")

import cv2
import logging
import os
import shutil  # 导入 shutil 模块以检查磁盘空间

# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

def check_output_path(output_path):
    output_dir = os.path.dirname(output_path)
    if not os.path.exists(output_dir):
        try:
            os.makedirs(output_dir)
            logging.info(f"创建目录: {output_dir}")
        except Exception as e:
            logging.error(f"无法创建目录 {output_dir}: {e}")
            return False
    # 检查文件权限
    if not os.access(output_dir, os.W_OK):
        logging.error(f"没有写权限: {output_dir}")
        return False
    return True


def capture_frame_from_rtsp(rtsp_url, file_name, output_path=None):
    """
    从RTSP流中捕获一帧并保存为图像文件。
    """
    try:
        # 验证输入参数
        if not rtsp_url:
            logging.error("RTSP URL 为空")
            return False

        # 获取当前脚本所在的根目录
        script_dir = os.path.dirname(os.path.abspath(__file__))
        root_dir = os.path.dirname(script_dir)

        # 构建默认输出路径
        if output_path is None:
            output_path = os.path.join(root_dir, "reports", "imgs", "Exhibit_Inspect", "Control_Manage", file_name)

        # 检查并创建输出目录
        if not check_output_path(output_path):
            return False

        # 打开RTSP流
        cap = cv2.VideoCapture(rtsp_url)
        if not cap.isOpened():
            logging.error("无法打开RTSP流")
            return False

        # 尝试多次读取帧以确保获取有效帧
        for _ in range(5):  # 尝试读取5次
            ret, frame = cap.read()
            if ret and frame is not None:
                break
        else:
            logging.error("无法从RTSP流中读取有效帧")
            cap.release()
            return False

        # 确认帧不为空
        if frame is None or frame.size == 0:
            logging.error("捕获到的帧为空")
            cap.release()
            return False

        # 检查帧的形状和类型
        logging.info(f"捕获到的帧尺寸: {frame.shape}, 数据类型: {frame.dtype}")

        # 尝试保存帧为图像文件
        success = False
        try:
            # 使用 cv2.imencode 保存图像到内存中，再写入文件
            _, img_encoded = cv2.imencode('.png', frame)
            with open(output_path, 'wb') as f:
                f.write(img_encoded.tobytes())
            success = True
        except Exception as e:
            logging.error(f"无法保存帧到 {output_path}: {e}")
            logging.error(f"检查路径是否存在: {os.path.exists(os.path.dirname(output_path))}")
            logging.error(f"检查路径是否可写: {os.access(os.path.dirname(output_path), os.W_OK)}")

            # 使用 shutil.disk_usage 检查磁盘空间
            try:
                total, used, free = shutil.disk_usage(os.path.dirname(output_path))
                logging.error(f"检查磁盘空间: {free // (2 ** 20)} MB available")
            except Exception as e:
                logging.error(f"无法检查磁盘空间: {e}")

        if success:
            logging.info(f"帧已保存到 {output_path}")
        else:
            logging.error(f"帧保存失败")

        # 释放资源
        cap.release()
        return success
    except Exception as e:
        logging.error(f"捕获帧时发生错误: {e}", exc_info=True)
        return False

# if __name__ == '__main__':
#     # 先截取当前空间的灯光状态图片
#     rtsp_url = "rtsp://admin:huawei@123@192.168.4.15/LiveMedia/ch1/Media2"  # 替换为你的RTSP流地址
#     logging.info("开始捕获RTSP流中的帧")
#     if capture_frame_from_rtsp(rtsp_url,"light_on.png"):
#         logging.info("帧捕获成功")
#     else:
#         logging.error("帧捕获失败")

def light_control(app_drive):
    # 开启所有区域灯光
    # 定位【接待区】灯光
    light_reception_button = app_drive.find_element(AppiumBy.XPATH,
                                                    "/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.RelativeLayout/android.widget.RelativeLayout/android.widget.RelativeLayout[2]/android.widget.ImageView[1]")
    sleep(2)
    logging.info("尝试定位【接待区】按钮元素，并点击按钮")
    light_reception_button.click()
    sleep(2)

    # 定位【指挥中心】灯光
    light_command_center_button = app_drive.find_element(AppiumBy.XPATH,
                                                         "/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.RelativeLayout/android.widget.RelativeLayout/android.widget.RelativeLayout[2]/android.widget.Button[3]")
    sleep(2)
    logging.info("尝试定位【指挥中心】按钮元素，并点击按钮")
    light_command_center_button.click()
    sleep(2)

    # 定位【影音室】灯光
    light_audio_room_button = app_drive.find_element(AppiumBy.XPATH,
                                                     "/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.RelativeLayout/android.widget.RelativeLayout/android.widget.RelativeLayout[2]/android.widget.Button[2]")
    sleep(2)
    logging.info("尝试定位【影音室】按钮元素，并点击按钮")
    light_audio_room_button.click()
    sleep(2)

    # 定位【会议室】灯光
    light_meeting_room_button = app_drive.find_element(AppiumBy.XPATH,
                                                       "/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.RelativeLayout/android.widget.RelativeLayout/android.widget.RelativeLayout[2]/android.widget.Button[5]")
    sleep(2)
    logging.info("尝试定位【会议室】按钮元素，并点击按钮")
    light_meeting_room_button.click()
    sleep(2)

    # 定位【会商区】灯光
    light_meeting_area_button = app_drive.find_element(AppiumBy.XPATH,
                                                       "/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.RelativeLayout/android.widget.RelativeLayout/android.widget.RelativeLayout[2]/android.widget.Button[4]")
    sleep(2)
    logging.info("尝试定位【会商区】按钮元素，并点击按钮")
    light_meeting_area_button.click()
    sleep(2)

    # 定位【培训室】灯光
    light_training_room_button = app_drive.find_element(AppiumBy.XPATH,
                                                        "/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.RelativeLayout/android.widget.RelativeLayout/android.widget.RelativeLayout[2]/android.widget.Button[6]")
    sleep(2)
    logging.info("尝试定位【培训室】按钮元素，并点击按钮")
    light_training_room_button.click()
    sleep(2)

def curtain_control(app_drive):
    # 所有窗帘全部上升
    logging.info("尝试定位所有【窗帘上升】按钮元素，并点击按钮")
    # 上升按钮的定位
    curtain_up_locator = ['3', '4', '5', '1', '13']
    for i in curtain_up_locator:
        curtain_up_button = app_drive.find_element(AppiumBy.XPATH,
                                                   f"/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.RelativeLayout/android.widget.RelativeLayout/android.widget.RelativeLayout[2]/android.widget.Button[{i}]")
        curtain_up_button.click()
        sleep(2)
    # 截图获取当前中控屏软件窗帘上升的界面
    app_drive.get_screenshot_as_file(
        r"D:\GithubData\自动化\ubains-module-test\预定系统\reports\imgs\Exhibit_Inspect\Control_Manage\curtain_up.png")
    sleep(10)

    # 所有窗帘全部下降
    logging.info("尝试定位所有【窗帘下降】按钮元素，并点击按钮")
    # 下降按钮的定位
    curtain_down_locator = ['10', '11', '12', '6', '15']
    for i in curtain_down_locator:
        curtain_down_button = app_drive.find_element(AppiumBy.XPATH,
                                                     f"/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.RelativeLayout/android.widget.RelativeLayout/android.widget.RelativeLayout[2]/android.widget.Button[{i}]")
        curtain_down_button.click()
        sleep(2)
    # 截图获取当前中控屏软件窗帘上升的界面
    app_drive.get_screenshot_as_file(
        r"D:\GithubData\自动化\ubains-module-test\预定系统\reports\imgs\Exhibit_Inspect\Control_Manage\curtain_down.png")

def air_condition_control(app_drive):
    # 点击【打开空调】按钮
    logging.info("尝试定位【打开空调】按钮元素，并点击按钮")
    open_air_conditioner_button = app_drive.find_element(AppiumBy.XPATH,
                                                         "/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.RelativeLayout/android.widget.RelativeLayout/android.widget.RelativeLayout[2]/android.widget.Button[14]")
    open_air_conditioner_button.click()
    sleep(20)
    app_drive.get_screenshot_as_file(
        r"D:\GithubData\自动化\ubains-module-test\预定系统\reports\imgs\Exhibit_Inspect\Control_Manage\air_condition_on.png")
    sleep(2)

    # 点击【关闭空调】按钮
    logging.info("尝试定位【关闭空调】按钮元素，并点击按钮")
    close_air_conditioner_button = app_drive.find_element(AppiumBy.XPATH,
                                                          "/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.RelativeLayout/android.widget.RelativeLayout/android.widget.RelativeLayout[2]/android.widget.Button[14]")
    close_air_conditioner_button.click()
    sleep(20)
    app_drive.get_screenshot_as_file(
        r"D:\GithubData\自动化\ubains-module-test\预定系统\reports\imgs\Exhibit_Inspect\Control_Manage\air_condition_off.png")
    sleep(2)

def command_centre_control(rtsp_url,app_drive):
    open_center_button = app_drive.find_element(AppiumBy.XPATH,
                                                "/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.RelativeLayout/android.widget.RelativeLayout/android.widget.RelativeLayout[2]/android.widget.Button")
    open_center_button.click()
    sleep(10)
    # 从rtsp流中截取一帧保存为图片
    logging.info("开始捕获RTSP流中的帧")
    if capture_frame_from_rtsp(rtsp_url, "command_screen_on.png"):
        logging.info("帧捕获成功")
    else:
        logging.error("帧捕获失败")

    # 关闭指挥中心大屏幕
    logging.info("尝试定位【关闭指挥中心控制】按钮元素，并点击按钮")
    close_center_button = app_drive.find_element(AppiumBy.XPATH,
                                                 "/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.RelativeLayout/android.widget.RelativeLayout/android.widget.RelativeLayout[2]/android.widget.Button")
    close_center_button.click()
    sleep(10)
    # 从rtsp流中截取一帧保存为图片
    logging.info("开始捕获RTSP流中的帧")
    if capture_frame_from_rtsp(rtsp_url,
                               "command_screen_down.png"):
        logging.info("帧捕获成功")
    else:
        logging.error("帧捕获失败")
