Python连接VNC

# -*- coding: utf-8 -*-
"""
安装命令:pip install opencv-python vncdotool -i https://mirrors.aliyun.com/pypi/simple

"""
import ctypes
import time
from logging import shutdown
import random

import cv2, numpy as np

from vncdotool import api
from vncdotool.client import KEYMAP


class VNC:
    button_left = 1
    button_mid = 2
    button_right = 3

    def __init__(self, ip, prot,password=None):
        self.ip = ip + "::" + prot
        self.cmd = f"vncdo -s {self.ip} "
        self.client = api.connect(self.ip,password)
        self.key_map = KEYMAP
        self.image_size = 1024*768  # 1024*768分辨率大小的
        self.image_buffer = (ctypes.c_ubyte * self.image_size)()

    def __del__(self):
        self.stop()

    def stop(self):
        self.client.disconnect()

    # 截图,可以保存到本地,也可以直接获取cv图像对象
    def capture(self, path=None):
        if path:
            self.client.captureScreen(path)
        else:  # 不写入图像,直接转cv图像bgr格式
            self.flush_screen(1)
            return cv2.cvtColor(np.asarray(self.client.screen), cv2.COLOR_RGB2BGR)

    def capture_to_addr(self):
        self.flush_screen(1)
        image_bytes = np.asarray(self.client.screen).tobytes()
        ctypes.memmove(self.image_buffer, image_bytes, self.image_size)
        return ctypes.addressof(self.image_buffer), self.image_size

    # 移动鼠标
    def move(self, x, y):
        self.client.mouseMove(x, y)

    # 点击鼠标按钮,123分别对应左中右键
    def click(self, button=1, delay=0.05):
        self.client.mouseDown(button)
        time.sleep(delay)
        self.client.mouseUp(button)
        # self.flush_screen()

    # 移动并点击鼠标左键
    def left_click(self, x, y):
        self.move(x, y)
        self.click()
        self.flush_screen()

    # 双击鼠标左键
    def double_left_click(self, x, y):
        self.move(x, y)
        self.click()
        time.sleep(0.1)
        self.click()

    # 点击鼠标右键
    def right_click(self, x, y):
        self.move(x, y)
        self.click(3)

    # 拖动
    def drag(self, x, y, step=1):
        return self.client.mouseDrag(x, y, step)

    # 按键一次
    def key_press(self, key_str):
        # key_str可以参考 KEYMAP
        self.client.keyPress(key_str)
        self.flush_screen()

    # 刷新屏幕
    def flush_screen(self, incremental=1):
        return self.client.refreshScreen(incremental)  # 屏幕更改时才刷新,节省宽带

    def key_down(self, key_str):
        return self.client.keyDown(key_str)

    def key_up(self, key_str):
        return self.client.keyUp(key_str)

    # 组合键
    def hot_key(self, key_list):
        for key_str in key_list:
            self.key_down(key_str)
            time.sleep(0.05)
        for key_str in key_list[::-1]:
            self.key_down(key_str)
            time.sleep(0.05)


if __name__ == '__main__':
    v = VNC("176.232.102.57", "5900","Qwert12345")
    # # 键盘测试
    # v.key_press("a")
    # # 鼠标测试
    # v.move(200, 500)
    # v.click(1)
    # 截图测试
    FPS = 0
    while True:
        s = time.time()
        new_image = v.capture(path=None)  # 获取新图像
        print(time.time()-s)
        FPS = 1 / (time.time() - s)
        # 绘制帧率
        cv2.putText(new_image, str(int(FPS)), (0, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)
        cv2.imshow("img", new_image)
        cv2.waitKey(1)
        v.move(random.randint(100,800),random.randint(100,800))
    api.shutdown() # 关闭事件循环

 测试链接是否可用

import socket


def check_vnc_connection(host, port=5900, timeout=1):
    """
    尝试连接到VNC服务器。
    :param host: VNC服务器的IP地址或主机名
    :param port: VNC服务器的端口,默认为5900
    :param timeout: 连接超时时间,默认为5秒
    :return: 如果连接成功返回True,否则返回False
    """
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.settimeout(timeout)
    try:
        s.connect((host, port))
        # 如果连接成功,发送一个VNC协议版本请求
        s.sendall(b"RFB 003.008\n")
        # 简单地读取响应,但不做解析
        response = s.recv(1024)
        print(f"VNC server response: {response}")
        return True
    except socket.error as e:
        print(f"连接失败: {e}")
        return False
    finally:
        s.close()


# 使用示例
host = '176.232.102.20'  # 替换为你的VNC服务器地址
port = 5900  # 替换为你的VNC服务器端口,如果默认端口没有被更改
can_connect = check_vnc_connection(host, port)
print(f"连接VNC服务器状态: {can_connect}")

实时刷新

import time

import cv2
import numpy as np
from vncdotool import api

# 连接到 VNC 服务器
client = api.connect('127.0.0.1::5900', password='Qwert123')

# 创建 OpenCV 窗口
cv2.namedWindow("VNC Display", cv2.WINDOW_NORMAL)

try:
    while True:
        # 获取 VNC 屏幕数据
        screen_data = client.screen
        print(screen_data is not None)
        # 检查是否获取到屏幕数据
        if screen_data is not None:
            # 将屏幕数据转换为 OpenCV 格式
            frame = cv2.cvtColor(np.asarray(screen_data), cv2.COLOR_RGB2BGR)

            # 在 OpenCV 窗口中显示画面
            cv2.imshow("VNC Display", frame)

            # 检查是否需要退出循环,例如通过按键或窗口关闭事件
            if cv2.waitKey(1) & 0xFF == ord('q'):
                break
        else:
            client.refreshScreen(incremental=0)
except Exception as e:
    print(f"An error occurred: {e}")
finally:
    # 断开连接
    client.disconnect()
    # 关闭 OpenCV 窗口
    cv2.destroyAllWindows()

 

posted @ 2024-11-12 18:11  zwnsyw  阅读(63)  评论(0编辑  收藏  举报