体会event 事件中的 client offset page 中的区别

本文介绍了一个简单的HTML页面示例,通过JavaScript实现点击事件监听,详细解析了如何获取鼠标点击时的位置信息,包括clientX、clientY、pageX、pageY和screenY等属性。



点击桌面上的div 都会产生一个对象,存放着点击之后的相关的信息;相关信息的集合。其中event的属性和方法有,width该窗口的或者框架的宽度   pageX光标相对于网页的水平位置 clientX相对于网页中可视区域水平位置。比如鼠标点击之后的坐标等等;既然是对象就有很多的属性和方法。

<!DOCTYPE html>

<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style>
        body {
            height: 2000px;
        }
    </style>
</head>
<body>


</body>
</html>
<script>
    document.onclick = function(event){  // 文档中点击
        // console.log(window.event.clientX);  ie 678

        var event = event || window.event;   // 兼容性写法

       console.log(event);

      console.log(event.clientY);

        console.log(event.pageY);
        console.log(event.screenY);
       // console.log(event.clientY);


    }
    
</script>
#include <Arduino.h> #include <usb/usb_host.h> // USB标准描述符类型 #define USB_DEVICE_DESC 1 #define USB_CONFIGURATION_DESC 2 #define USB_INTERFACE_DESC 4 #define USB_ENDPOINT_DESC 5 // USB传输类型 //#define USB_BM_ATTRIBUTES_XFER_BULK 2 #define USB_B_ENDPOINT_ADDRESS_EP_DIR_MASK 0x80 class MyUsbHost { private: usb_host_client_handle_t clientHandle = nullptr; bool currentInterfaceIsPrinter = false; uint8_t currentInterfaceNumber = 0; bool isTransferInProgress = false; uint8_t printerDeviceAddress = 0; public: bool printerReady = false; uint8_t printerEndpointOut = 0; uint8_t printerEndpointIn = 0; uint16_t printerVid = 0; uint16_t printerPid = 0; usb_device_handle_t printerDeviceHandle = nullptr; bool printerInterfaceFound = false; bool interfaceClaimed = false; void begin() { const usb_host_config_t config = { .skip_phy_setup = false, .intr_flags = ESP_INTR_FLAG_LEVEL1 }; esp_err_t err = usb_host_install(&config); if (err != ESP_OK) { Serial.printf("usb_host_install failed: %d\n", err); return; } Serial.println("USB Host initialized"); } void task() { // 处理USB主机事件 uint32_t event_flags; usb_host_lib_handle_events(0, &event_flags); if (clientHandle == nullptr) { usb_host_client_config_t client_config = { .is_synchronous = false, .max_num_event_msg = 10, .async = { .client_event_callback = client_event_callback, .callback_arg = this, } }; Serial.println("USB Host client config set"); esp_err_t err = usb_host_client_register(&client_config, &clientHandle); if (err != ESP_OK) { Serial.printf("usb_host_client_register failed: %d\n", err); return; } Serial.println("USB Host client registered"); } if (clientHandle != nullptr) { usb_host_client_handle_events(clientHandle, 0); } } private: static void client_event_callback(const usb_host_client_event_msg_t* event_msg, void* arg) { MyUsbHost* host = (MyUsbHost*)arg; Serial.printf("USB_HOST_CLIENT_EVENT: %d\n", event_msg->event); switch (event_msg->event) { case USB_HOST_CLIENT_EVENT_NEW_DEV: Serial.printf("USB_HOST_CLIENT_EVENT_NEW_DEV: address=%d\n", event_msg->new_dev.address); host->handleNewDevice(event_msg->new_dev.address); break; case USB_HOST_CLIENT_EVENT_DEV_GONE: Serial.println("USB_HOST_CLIENT_EVENT_DEV_GONE"); host->handleDeviceGone(); break; default: Serial.printf("Unknown event: %d\n", event_msg->event); break; } } void handleNewDevice(uint8_t dev_addr) { printerDeviceAddress = dev_addr; Serial.printf("New device connected with address: %d\n", dev_addr); // 根据设备地址打开设备以获取设备句柄 esp_err_t err = usb_host_device_open(clientHandle, dev_addr, &printerDeviceHandle); if (err != ESP_OK) { Serial.printf("Failed to open device: %d (%s)\n", err, esp_err_to_name(err)); return; } if (printerDeviceHandle == nullptr) { Serial.println("Device handle is null"); return; } Serial.printf("Device opened successfully. Address: %d, Handle: %p\n", dev_addr, printerDeviceHandle); // 获取设备描述符 const usb_device_desc_t* dev_desc; err = usb_host_get_device_descriptor(printerDeviceHandle, &dev_desc); if (err != ESP_OK) { Serial.printf("Failed to get device descriptor: %d (%s)\n", err, esp_err_to_name(err)); usb_host_device_close(clientHandle, printerDeviceHandle); printerDeviceHandle = nullptr; return; } printerVid = dev_desc->idVendor; printerPid = dev_desc->idProduct; Serial.printf("Device found: VID=0x%04x, PID=0x%04x\n", printerVid, printerPid); // 获取配置描述符 const usb_config_desc_t* config_desc; err = usb_host_get_active_config_descriptor(printerDeviceHandle, &config_desc); if (err != ESP_OK) { Serial.printf("Failed to get config descriptor: %d (%s)\n", err, esp_err_to_name(err)); usb_host_device_close(clientHandle, printerDeviceHandle); printerDeviceHandle = nullptr; return; } Serial.printf("Config descriptor length: %d\n", config_desc->wTotalLength); // 解析配置描述符 parseConfigDescriptor((uint8_t*)config_desc, config_desc->wTotalLength); // 如果找到了打印机接口,尝试claim接口 if (printerInterfaceFound && printerDeviceHandle != nullptr) { Serial.printf("Attempting to claim interface %d\n", currentInterfaceNumber); err = usb_host_interface_claim(clientHandle, printerDeviceHandle, currentInterfaceNumber, 0); if (err != ESP_OK) { Serial.printf("Failed to claim interface: %d (%s)\n", err, esp_err_to_name(err)); printerReady = false; } else { Serial.println("Interface claimed successfully"); interfaceClaimed = true; printerReady = true; } } } void handleDeviceGone() { Serial.println("Device disconnected"); resetPrinterState(); } void resetPrinterState() { printerReady = false; printerEndpointOut = 0; printerEndpointIn = 0; interfaceClaimed = false; printerInterfaceFound = false; currentInterfaceNumber = 0; currentInterfaceIsPrinter = false; isTransferInProgress = false; printerVid = 0; printerPid = 0; // 只在设备句柄有效时关闭设备 if (printerDeviceHandle != nullptr) { // 先释放声明的接口 if (interfaceClaimed) { usb_host_interface_release(clientHandle, printerDeviceHandle, currentInterfaceNumber); } usb_host_device_close(clientHandle, printerDeviceHandle); printerDeviceHandle = nullptr; } } void parseConfigDescriptor(uint8_t* desc, uint16_t len) { uint8_t* p = desc; uint16_t offset = 0; Serial.printf("Parsing config descriptor, total length: %d\n", len); // 重置打印机端点信息 printerEndpointOut = 0; printerEndpointIn = 0; printerInterfaceFound = false; currentInterfaceIsPrinter = false; uint8_t printerInterfaceNumber = 0; // 保存打印机接口编号 while (offset < len) { if (offset + 2 > len) { Serial.printf("End of descriptor at offset %d\n", offset); break; } uint8_t length = p[0]; uint8_t type = p[1]; if (length == 0) { Serial.println("Invalid descriptor length: 0"); break; } if (offset + length > len) { Serial.printf("Descriptor length %d exceeds total length at offset %d\n", length, offset); break; } Serial.printf("Descriptor: type=0x%02x, length=%d\n", type, length); if (type == USB_INTERFACE_DESC) { if (length < sizeof(usb_intf_desc_t)) { Serial.printf("Interface descriptor too short: %d\n", length); } else { usb_intf_desc_t* intf = (usb_intf_desc_t*)p; currentInterfaceNumber = intf->bInterfaceNumber; // 检查是否为标准打印机类 currentInterfaceIsPrinter = (intf->bInterfaceClass == 0x07); Serial.printf("Interface descriptor found: Interface=%d, Class=0x%02x, SubClass=0x%02x, Protocol=0x%02x\n", intf->bInterfaceNumber, intf->bInterfaceClass, intf->bInterfaceSubClass, intf->bInterfaceProtocol); if (currentInterfaceIsPrinter) { printerInterfaceFound = true; printerInterfaceNumber = currentInterfaceNumber; // 保存打印机接口编号 Serial.printf("Printer interface found: Interface=%d, Class=0x%02x, SubClass=0x%02x, Protocol=0x%02x\n", intf->bInterfaceNumber, intf->bInterfaceClass, intf->bInterfaceSubClass, intf->bInterfaceProtocol); } } } else if (type == USB_ENDPOINT_DESC) { if (length < sizeof(usb_ep_desc_t)) { Serial.printf("Endpoint descriptor too short: %d\n", length); } else { usb_ep_desc_t* ep_desc = (usb_ep_desc_t*)p; Serial.printf("Endpoint descriptor found for interface %d: Address=0x%02x, Attributes=0x%02x\n", currentInterfaceNumber, ep_desc->bEndpointAddress, ep_desc->bmAttributes); if ((ep_desc->bmAttributes & 0x03) == USB_BM_ATTRIBUTES_XFER_BULK) { if (currentInterfaceIsPrinter) { if (ep_desc->bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_DIR_MASK) { printerEndpointIn = ep_desc->bEndpointAddress; Serial.printf("Printer IN endpoint found: 0x%02x\n", printerEndpointIn); } else { printerEndpointOut = ep_desc->bEndpointAddress; Serial.printf("Printer OUT endpoint found: 0x%02x\n", printerEndpointOut); } } else { Serial.printf("BULK endpoint for non-printer interface: 0x%02x\n", ep_desc->bEndpointAddress); } } } } p += length; offset += length; } // 检查是否找到了打印机接口和至少一个端点 if (printerInterfaceFound && (printerEndpointOut != 0 || printerEndpointIn != 0)) { currentInterfaceNumber = printerInterfaceNumber; // 使用打印机接口编号 printerReady = true; Serial.println("Printer is ready!"); if (printerEndpointOut != 0) { Serial.printf("Printer OUT endpoint: 0x%02x\n", printerEndpointOut); } if (printerEndpointIn != 0) { Serial.printf("Printer IN endpoint: 0x%02x\n", printerEndpointIn); } } else if (printerInterfaceFound) { Serial.println("Printer interface found but no BULK endpoints detected"); } else { Serial.println("No printer interface found"); } } static void transferCallback(usb_transfer_t *transfer) { MyUsbHost* host = (MyUsbHost*)transfer->context; host->isTransferInProgress = false; if (transfer->status == USB_TRANSFER_STATUS_COMPLETED) { Serial.printf("Transfer completed, %d bytes transferred\n", transfer->actual_num_bytes); } else { Serial.printf("Transfer failed with status: %d\n", transfer->status); } host->isTransferInProgress = false; usb_host_transfer_free(transfer); } public: // 打印数据到打印机(带重试机制) bool printData(const uint8_t* data, size_t length, int maxRetries = 3) { for (int attempt = 0; attempt < maxRetries; attempt++) { if (attempt > 0) { Serial.printf("Retry attempt %d/%d\n", attempt, maxRetries); delay(100 * attempt); } // 检查设备状态 if (!printerReady || printerEndpointOut == 0) { Serial.println("Printer not ready for printing"); Serial.printf("Printer ready: %s, Device handle: %p, Endpoint OUT: 0x%02x\n", printerReady ? "YES" : "NO", printerDeviceHandle, printerEndpointOut); // 尝试重新打开设备 if (printerDeviceHandle == nullptr && printerDeviceAddress != 0) { Serial.println("Attempting to re-open device..."); esp_err_t open_err = usb_host_device_open(clientHandle, printerDeviceAddress, &printerDeviceHandle); if (open_err != ESP_OK) { Serial.printf("Failed to re-open device: %d (%s)\n", open_err, esp_err_to_name(open_err)); // 如果无法重新打开设备,重置状态并返回 if (open_err == ESP_ERR_NOT_FOUND) { resetPrinterState(); } continue; } // 重新声明接口 if (!interfaceClaimed && printerDeviceHandle != nullptr) { Serial.println("Re-claiming interface..."); esp_err_t claim_err = usb_host_interface_claim(clientHandle, printerDeviceHandle, currentInterfaceNumber, 0); if (claim_err != ESP_OK) { Serial.printf("Failed to re-claim interface: %d (%s)\n", claim_err, esp_err_to_name(claim_err)); // 如果无法声明接口,关闭设备并继续尝试 usb_host_device_close(clientHandle, printerDeviceHandle); printerDeviceHandle = nullptr; continue; } else { Serial.println("Interface re-claimed successfully"); interfaceClaimed = true; printerReady = true; } } } // 如果仍然没有有效的设备句柄,返回失败 if (printerDeviceHandle == nullptr) { Serial.println("No valid device handle available"); continue; } } if (isTransferInProgress) { Serial.println("Transfer already in progress, please wait"); continue; } // 确保USB主机栈已处理所有事件 task(); // 检查设备是否仍然连接 if (printerDeviceHandle == nullptr) { Serial.println("Device handle became null before transfer"); continue; } usb_transfer_t* transfer; esp_err_t err = usb_host_transfer_alloc(length, 0, &transfer); if (err != ESP_OK) { Serial.printf("Failed to allocate transfer: %d (%s)\n", err, esp_err_to_name(err)); continue; } // 配置传输前再次检查设备句柄 if (printerDeviceHandle == nullptr) { Serial.println("Device handle became null before transfer configuration"); usb_host_transfer_free(transfer); continue; } // 配置传输 transfer->device_handle = printerDeviceHandle; transfer->bEndpointAddress = printerEndpointOut; transfer->num_bytes = length; transfer->callback = transferCallback; transfer->context = this; transfer->timeout_ms = 5000; // 复制数据到传输缓冲区 memcpy(transfer->data_buffer, data, length); isTransferInProgress = true; // 提交传输前再次检查设备句柄 if (printerDeviceHandle == nullptr) { Serial.println("Device handle became null before transfer submission"); isTransferInProgress = false; usb_host_transfer_free(transfer); continue; } // 提交传输 err = usb_host_transfer_submit(transfer); if (err != ESP_OK) { Serial.printf("Failed to submit transfer: %d (%s)\n", err, esp_err_to_name(err)); isTransferInProgress = false; usb_host_transfer_free(transfer); // 根据错误类型采取不同措施 switch (err) { case ESP_ERR_NOT_FOUND: Serial.println("Device not found during transfer submit"); // 设备可能已断开,重置状态 resetPrinterState(); return false; case ESP_ERR_INVALID_STATE: Serial.println("Invalid state during transfer submit"); // 尝试重置接口声明状态 if (interfaceClaimed && printerDeviceHandle != nullptr) { usb_host_interface_release(clientHandle, printerDeviceHandle, currentInterfaceNumber); interfaceClaimed = false; } // 重新声明接口 if (printerDeviceHandle != nullptr) { esp_err_t claim_err = usb_host_interface_claim(clientHandle, printerDeviceHandle, currentInterfaceNumber, 0); if (claim_err == ESP_OK) { Serial.println("Interface re-claimed successfully"); interfaceClaimed = true; } else { Serial.printf("Failed to re-claim interface: %d (%s)\n", claim_err, esp_err_to_name(claim_err)); } } continue; default: Serial.println("Other error during transfer submit"); continue; } } // 等待传输完成 uint32_t startTime = millis(); while (isTransferInProgress && (millis() - startTime < 6000)) { task(); delay(10); } if (!isTransferInProgress) { return true; } else { Serial.println("Transfer timeout"); isTransferInProgress = false; } } Serial.println("All print attempts failed"); return false; } // HP打印机初始化 bool hpInitialize() { // 发送HP标准重置命令 const uint8_t initCmd[] = "x1B@"; // HP Reset Serial.println("Sending HP reset command..."); if (printData(initCmd, sizeof(initCmd)-1)) { delay(100); return true; } return false; } // 打印文本 bool printText(const char* text) { return printData((const uint8_t*)text, strlen(text)); } // 打印简单文本页 bool printSimpleTestPage() { Serial.println("Sending simple test page..."); const char* testPage = "HP Deskjet 1212 Test Page\r\n" "=========================\r\n\r\n" "This is a simple test print from ESP32.\r\n" "Printer Model: HP Deskjet 1212\r\n" "Connection: USB\r\n" "Status: Connected and Ready\r\n\r\n" "If you can read this text, the test was successful!\r\n\r\n" "Timestamp: "; if (!printData((const uint8_t*)testPage, strlen(testPage))) return false; // 添加时间戳 char timestamp[20]; sprintf(timestamp, "%lu\r\n\r\n", millis()); if (!printData((const uint8_t*)timestamp, strlen(timestamp))) return false; // 表单进纸命令 const char* formFeed = "\r\n\r\n\x0C"; return printData((const uint8_t*)formFeed, strlen(formFeed)); } }; MyUsbHost usbHost; void setup() { Serial.begin(115200); Serial.println("HP Deskjet 1212 USB Printer Test"); Serial.println("================================="); Serial.println("Waiting for printer connection..."); usbHost.begin(); } void loop() { usbHost.task(); static bool testStarted = false; static uint32_t testStartTime = 0; if (usbHost.printerReady && !testStarted) { testStarted = true; testStartTime = millis(); Serial.println("=== PRINTER READY FOR TESTING ==="); // 初始化打印机 Serial.println("Initializing printer..."); if (usbHost.hpInitialize()) { Serial.println("Printer initialized successfully"); } else { Serial.println("Failed to initialize printer"); } delay(1000); // 打印简单测试页 Serial.println("Printing simple test page..."); if (usbHost.printSimpleTestPage()) { Serial.println("Simple test page sent to printer"); } else { Serial.println("Failed to send simple test page"); } Serial.println("=== PRINT TESTING COMPLETED ==="); } delay(100); } 运行结果如下: 11:33:54.911 -> Descriptor: type=0x04, length=9 11:33:54.911 -> Interface descriptor found: Interface=2, Class=0xff, SubClass=0x04, Protocol=0x01 11:33:54.945 -> Descriptor: type=0x05, length=7 11:33:54.945 -> Endpoint descriptor found for interface 2: Address=0x0a, Attributes=0x02 11:33:54.945 -> BULK endpoint for non-printer interface: 0x0a 11:33:54.945 -> Descriptor: type=0x05, length=7 11:33:54.945 -> Endpoint descriptor found for interface 2: Address=0x8b, Attributes=0x02 11:33:54.945 -> BULK endpoint for non-printer interface: 0x8b 11:33:54.945 -> Printer is ready! 11:33:54.945 -> Printer OUT endpoint: 0x08 11:33:54.945 -> Printer IN endpoint: 0x89 11:33:54.988 -> Attempting to claim interface 0 11:33:54.988 -> Interface claimed successfully 11:33:54.988 -> === PRINTER READY FOR TESTING === 11:33:54.988 -> Initializing printer... 11:33:54.988 -> Sending HP reset command... 11:33:54.988 -> Transfer completed, 4 bytes transferred 11:33:55.108 -> Printer initialized successfully 11:33:56.121 -> Printing simple test page... 11:33:56.121 -> Sending simple test page... 11:33:56.121 -> Transfer completed, 243 bytes transferred 11:33:56.121 -> Transfer completed, 8 bytes transferred 11:33:56.167 -> Transfer completed, 5 bytes transferred 11:33:56.167 -> Simple test page sent to printer 11:33:56.167 -> === PRINT TESTING COMPLETED === 优化、简化一下
最新发布
09-02
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值