from appium.webdriver.common.appiumby import AppiumBy
from time import sleep
from appium.options.android import UiAutomator2Options
from django.db.models.fields import return_None
from hytest import *
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)

# 请使用“pip install opencv-python”安装PIL库
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("灯光未成功打开")

# 请使用“pip install opencv-python”安装cv2库
import cv2
import numpy as np

import logging
from PIL import Image
import numpy as np


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

def compare_images_feature_matching(image1_path, image2_path):
    try:
        # 验证图片路径是否存在且为有效图片文件
        if not os.path.isfile(image1_path) or not os.path.isfile(image2_path):
            logging.error("图片路径无效")
            return {"result": False, "error": "图片路径无效"}

        # 打开两张图片
        img1 = Image.open(image1_path)
        img2 = Image.open(image2_path)

        # 验证图片是否为有效格式
        if img1.format not in ['JPEG', 'PNG'] or img2.format not in ['JPEG', 'PNG']:
            logging.error("图片格式无效")
            return {"result": False, "error": "图片格式无效"}

        # 如果尺寸不同,先调整大小
        if img1.size != img2.size:
            logging.info("图片尺寸不同,调整为相同尺寸进行比较")
            img2 = img2.resize(img1.size, Image.ANTIALIAS)  # 保持纵横比

        # 将图片转换为相同的模式
        img1 = img1.convert("RGB")
        img2 = img2.convert("RGB")

        # 转换为 numpy 数组进行比较
        img1_array = np.array(img1)
        img2_array = np.array(img2)

        # 输出numpy数组信息
        logging.info(f"图片1数组: {img1_array},图片2数组: {img2_array}")

        # 比较两个数组是否相同
        return {"result": np.array_equal(img1_array, img2_array), "error": None}

    except FileNotFoundError as e:
        logging.error(f"文件未找到: {e}")
        return {"result": False, "error": f"文件未找到: {e}"}
    except OSError as e:
        logging.error(f"图片处理错误: {e}")
        return {"result": False, "error": f"图片处理错误: {e}"}
    except MemoryError as e:
        logging.error(f"内存不足: {e}")
        return {"result": False, "error": f"内存不足: {e}"}
    except Exception as e:
        logging.error(f"未知错误: {e}")
        return {"result": False, "error": f"未知错误: {e}"}


# 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\预定系统\reports\imgs\Exhibit_Inspect\No_PaperLess\DeviceA-ShareScreen.png'
#     image2_path = r'D:\GithubData\自动化\ubains-module-test\预定系统\reports\imgs\Exhibit_Inspect\No_PaperLess\同屏前-无纸化设备B界面截屏.png'
#
#     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 numpy
from PIL import Image
import logging
import os


def calculate(image1, image2):
    image1 = cv2.cvtColor(numpy.asarray(image1), cv2.COLOR_RGB2BGR)
    image2 = cv2.cvtColor(numpy.asarray(image2), cv2.COLOR_RGB2BGR)
    hist1 = cv2.calcHist([image1], [0], None, [256], [0.0, 255.0])
    hist2 = cv2.calcHist([image2], [0], None, [256], [0.0, 255.0])
    # 计算直方图的重合度
    degree = 0
    for i in range(len(hist1)):
        if hist1[i] != hist2[i]:
            degree = degree + (1 - abs(hist1[i] - hist2[i]) / max(hist1[i], hist2[i]))
        else:
            degree = degree + 1
    degree = degree / len(hist1)
    return degree


def classify_hist_with_split(image1, image2, size=(256, 256)):
    image1 = Image.open(image1)
    image2 = Image.open(image2)
    # 将图像resize后,分离为RGB三个通道,再计算每个通道的相似值
    image1 = cv2.cvtColor(numpy.asarray(image1), cv2.COLOR_RGB2BGR)
    image2 = cv2.cvtColor(numpy.asarray(image2), cv2.COLOR_RGB2BGR)
    image1 = cv2.resize(image1, size)
    image2 = cv2.resize(image2, size)
    sub_image1 = cv2.split(image1)
    sub_image2 = cv2.split(image2)
    sub_data = 0
    for im1, im2 in zip(sub_image1, sub_image2):
        sub_data += calculate(im1, im2)
    sub_data = sub_data / 3
    return sub_data


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\预定系统\reports\imgs\Exhibit_Inspect\No_PaperLess\DeviceA-ShareScreen.png'
    image2_path = r'D:\GithubData\自动化\ubains-module-test\预定系统\reports\imgs\Exhibit_Inspect\No_PaperLess\DeviceB-ShareScreen.png'

    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)

    # 对比两张截图的相似度
    result1 = classify_hist_with_split(image1_path, image2_path)

    # 确保 result1 是一个标量值
    if isinstance(result1, numpy.ndarray):
        result1 = result1.item()

    print("相似度为:" + "%.2f%%" % (result1 * 100))


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

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,wd):
    # 所有窗帘全部上升
    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)
    INFO("请检查窗帘上升状态是否正常")
    SELENIUM_LOG_SCREEN(wd, "50%", "Exhibit_Inspect", "Control_Manage", "curtain_up")
    # 截图获取当前中控屏软件窗帘上升的界面
    app_drive.get_screenshot_as_file(
        r"D:\GithubData\自动化\ubains-module-test\预定系统\reports\imgs\Exhibit_Inspect\Control_Manage\curtain_up.png")
    sleep(30)
    # # 测试报告中补充窗帘上升的截图
    SELENIUM_LOG_SCREEN(wd, "50%", "Exhibit_Inspect", "Control_Manage", "curtain_rtsp_up")
    # 通过rtsp流获取当前窗帘的上升效果图
    curtain_rtsp_url = "rtsp://admin:huawei@123@192.168.4.18/LiveMedia/ch1/Media2"
    logging.info("开始捕获RTSP流中的帧")
    if capture_frame_from_rtsp(curtain_rtsp_url, "curtain_rtsp_up.png"):
        logging.info("帧捕获成功")
    else:
        logging.error("帧捕获失败")

    # 所有窗帘全部下降
    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)
    sleep(30)
    INFO("请检查窗帘下降状态是否正常")
    SELENIUM_LOG_SCREEN(wd, "50%", "Exhibit_Inspect", "Control_Manage", "curtain_down")
    # 截图获取当前中控屏软件窗帘上升的界面
    app_drive.get_screenshot_as_file(
        r"D:\GithubData\自动化\ubains-module-test\预定系统\reports\imgs\Exhibit_Inspect\Control_Manage\curtain_down.png")
    # 测试报告中补充窗帘下降的截图
    SELENIUM_LOG_SCREEN(wd, "50%", "Exhibit_Inspect", "Control_Manage", "curtain_rtsp_down")
    logging.info("开始捕获RTSP流中的帧")
    if capture_frame_from_rtsp(curtain_rtsp_url, "curtain_rtsp_down.png"):
        logging.info("帧捕获成功")
    else:
        logging.error("帧捕获失败")

def air_condition_control(app_drive,wd):
    # 点击【打开空调】按钮
    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)

    # 这是空调开启的状态显示
    INFO("请检查空调开启的状态是否正常")
    SELENIUM_LOG_SCREEN(wd, "50%", "Exhibit_Inspect", "Control_Manage", "air_condition_on")

    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)
    # 这是空调关闭的状态显示
    INFO("请检查空调关闭的状态是否正常")
    SELENIUM_LOG_SCREEN(wd, "50%", "Exhibit_Inspect", "Control_Manage", "air_condition_off")
    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 information_control(app_drive,wd):
    # 选择生日快乐内容播放
    brithday_information_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]")
    brithday_information_button.click()
    logging.info("选择生日快乐内容播放")
    sleep(5)
    # 这是生日快乐主题内容发布
    INFO("请检查中控屏软件信息发布界面是否正常")
    SELENIUM_LOG_SCREEN(wd, "50%", "Exhibit_Inspect", "Control_Manage", "information_brithday_on")

    information_rtsp_url = "rtsp://admin:huawei@123@192.168.4.19/LiveMedia/ch1/Media2"  # 替换为你的RTSP流地址
    logging.info("开始捕获RTSP流中的帧")
    if capture_frame_from_rtsp(information_rtsp_url, "information_brithday_on.png"):
        logging.info("帧捕获成功")
    else:
        logging.error("帧捕获失败")

    # 选择欢迎领导发布内容播放
    meeting_information_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]")
    meeting_information_button.click()
    logging.info("选择会议发布内容播放")
    sleep(5)
    # 这是会议欢迎主题内容发布
    INFO("请检查中控屏软件信息发布界面是否正常")
    SELENIUM_LOG_SCREEN(wd, "50%", "Exhibit_Inspect", "Control_Manage", "information_meeting_on")

    logging.info("开始捕获RTSP流中的帧")
    if capture_frame_from_rtsp(information_rtsp_url, "information_meeting_on.png"):
        logging.info("帧捕获成功")
    else:
        logging.error("帧捕获失败")

    # 选择展厅空间结构内容播放
    information_space_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]")
    information_space_button.click()
    logging.info("选择展厅空间结构内容播放")
    sleep(5)
    # 这是展厅空间结构内容发布
    INFO("请检查中控屏软件信息发布界面是否正常")
    SELENIUM_LOG_SCREEN(wd, "50%", "Exhibit_Inspect", "Control_Manage", "information_space_on")

    if capture_frame_from_rtsp(information_rtsp_url, "information_space_on.png"):
        logging.info("帧捕获成功")
    else:
        logging.error("帧捕获失败")

    # 点击信息发布关闭按钮
    logging.info("点击信息发布关闭按钮")
    information_close_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[7]")
    information_close_button.click()


def music_control(app_drive,wd):
    # 点击【播放音乐】
    logging.info("尝试定位【播放音乐】按钮元素,并点击按钮")
    play_music_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[8]")
    play_music_button.click()
    sleep(2)
    # 调用音频采集判断音量函数
    INFO("请检查中控屏音乐播放的音频采集是否正常!!!")
    volume_acquisition()
    sleep(5)
    # 这是音乐开启播放后的界面显示
    INFO("请检查中控屏软件打开音乐播放后的界面状态显示")
    SELENIUM_LOG_SCREEN(wd, "50%", "Exhibit_Inspect", "Control_Manage", "music_on")
    app_drive.get_screenshot_as_file(
        r"D:\GithubData\自动化\ubains-module-test\预定系统\reports\imgs\Exhibit_Inspect\Control_Manage\music_on.png")

    # 点击【关闭播放音乐】
    logging.info("尝试定位【关闭播放音乐】按钮元素,并点击按钮")
    close_play_music_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[8]")
    close_play_music_button.click()
    sleep(5)
    # 这是音乐关闭播放后的界面显示
    INFO("请检查中控屏软件关闭音乐播放后的界面状态显示")
    SELENIUM_LOG_SCREEN(wd, "50%", "Exhibit_Inspect", "Control_Manage", "music_off")
    app_drive.get_screenshot_as_file(
        r"D:\GithubData\自动化\ubains-module-test\预定系统\reports\imgs\Exhibit_Inspect\Control_Manage\music_off.png")


def command_centre_control(rtsp_url,app_drive,wd):
    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)
    # 这是指挥大屏开启的监控视频显示
    INFO("请检查指挥大屏开启的监控视频状态是否正常")
    SELENIUM_LOG_SCREEN(wd, "50%", "Exhibit_Inspect", "Control_Manage", "command_screen_on")
    # 从rtsp流中截取一帧保存为图片
    logging.info("开始捕获RTSP流中的帧")
    if capture_frame_from_rtsp(rtsp_url, "command_screen_on.png"):
        logging.info("帧捕获成功")
    else:
        logging.error("帧捕获失败")

    # 这是指挥大屏关闭的监控视频显示
    INFO("请检查指挥大屏关闭的监控视频状态是否正常")
    SELENIUM_LOG_SCREEN(wd, "50%", "Exhibit_Inspect", "Control_Manage", "command_screen_down")
    # 关闭指挥中心大屏幕
    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("帧捕获失败")

import pyaudio
import numpy as np

# 定义参数
FORMAT = pyaudio.paInt16  # 16-bit resolution
CHANNELS = 1              # 1 channel
RATE = 44100              # 44.1kHz sampling rate
CHUNK = 1024              # 2^10 samples for buffer
THRESHOLD = 1000          # 阈值,可以根据实际情况调整
RECORD_SECONDS = 10       # 录制时长

def is_audio_loud(data, threshold=THRESHOLD):
    """
    判断音频数据是否超过阈值
    :param data: 音频数据
    :param threshold: 阈值
    :return: 如果声音大小超过阈值,返回True;否则返回False
    """
    return np.abs(np.frombuffer(data, dtype=np.int16)).mean() > threshold

def volume_acquisition():
    audio = pyaudio.PyAudio()  # 初始化pyaudio
    # 打开音频流
    stream = audio.open(format=FORMAT,
                        channels=CHANNELS,
                        rate=RATE,
                        input=True,
                        frames_per_buffer=CHUNK)

    logging.info("开始录音...")

    frames = []
    for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
        data = stream.read(CHUNK)  # 读取音频数据
        frames.append(data)

    logging.info("录音结束。")

    # 停止和关闭音频流
    stream.stop_stream()
    stream.close()
    audio.terminate()

    # 将所有帧合并成一个字节流
    audio_data = b''.join(frames)

    # 判断音量状态
    if is_audio_loud(audio_data):
        INFO("整段音频声音过大!")
    else:
        INFO("整段音频声音正常。")

    # 进一步处理音频数据(例如保存为文件或分析)
    # ...

# if __name__ == "__main__":
#     volume_acquisition()

import subprocess
from venv import logger

def app_init(device_ip, port=5555):
    """
    初始化浏览器设置和实例。

    此函数旨在初始化程序与app设备之间的adb连接,判断adb连接状态是否可控
    """
    # 标记初始化过程的开始
    INFO("'----------' 正在初始化ADB连接 '----------'")
    """
        通过 ADB 连接设备并检查设备状态
        :param device_ip: 设备的 IP 地址
        :param port: 端口号,默认为 5555
        """
    try:
        # 构建设备地址
        device_address = f"{device_ip}:{port}"
        # 连接设备
        subprocess.run(['adb', 'connect', device_address], check=True)
        INFO(f"尝试连接到设备: {device_address}")

        # 检查设备状态
        result = subprocess.run(['adb', 'devices'], capture_output=True, text=True, check=True)
        devices = result.stdout.strip().split('\n')[1:]  # 去掉标题行
        for device in devices:
            ip, status = device.split()
            if ip == device_address and status == 'device':
                INFO(f"设备 {device_address} 已连接并可用")
                return True
            elif ip == device_address and status == 'offline':
                INFO(f"设备 {device_address} 处于 offline 状态,当前设备不可控制,请检查设备网络状态")
                return False
            elif ip == device_address and status == 'unauthorized':
                logger.error(f"设备 {device_address} 未授权调试")
                return False
        INFO(f"设备 {device_address} 未找到,请检查设备IP是否正确!")
        return False
    except subprocess.CalledProcessError as e:
        INFO(f"连接设备失败: {e}")
        return False

def app_quit(device_ip,port=5555):
    """
    退出浏览器并释放资源。

    该函数从全局存储中获取设备adb连接状态
    """
    # 断开特定 IP 和端口的 ADB 连接
    device_address = f"{device_ip}:{port}"
    subprocess.run(['adb', 'disconnect', device_address])
    INFO(f"ADB 连接已断开: {device_address}")