{"id":1551,"date":"2021-05-28T21:31:35","date_gmt":"2021-05-28T13:31:35","guid":{"rendered":"https:\/\/swf.com.tw\/?p=1551"},"modified":"2022-11-21T07:14:29","modified_gmt":"2022-11-20T23:14:29","slug":"%e8%87%aa%e8%a3%bdswitch-pro%e7%9b%b8%e5%ae%b9%e9%81%8a%e6%88%b2%e6%8e%a7%e5%88%b6%e5%99%a8%ef%bc%88%e5%9b%9b%ef%bc%89%ef%bc%9aesp32-ble%e8%97%8d%e7%89%99%e4%bd%8e%e5%8a%9f%e8%80%97%e9%81%8a%e6%88%b2","status":"publish","type":"post","link":"https:\/\/swf.com.tw\/?p=1551","title":{"rendered":"\u81ea\u88fdSwitch Pro\u76f8\u5bb9\u904a\u6232\u63a7\u5236\u5668\uff08\u56db\uff09\uff1aESP32 BLE\u85cd\u7259\u4f4e\u529f\u8017\u904a\u6232\u624b\u628a"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">\u672c\u6587\u65e8\u5728\u88dc\u5145\u300a<a href=\"\/?p=1498\" target=\"_blank\" rel=\"noreferrer noopener\">\u8d85\u5716\u89e3ESP32\u6df1\u5ea6\u5be6\u4f5c<\/a>\u300b\u7b2c16\u7ae0\u300cBLE\u85cd\u7259\u4eba\u6a5f\u8f38\u5165\u88dd\u7f6e\u61c9\u7528\u5be6\u4f5c\u300d\u55ae\u5143\uff0c\u8aaa\u660eHID\u88dd\u7f6e\u7684<strong>Vender ID\uff08\u5ee0\u5546\u8b58\u5225\u78bc\uff0c\u7e2e\u5bebVID\uff09<\/strong>\u4ee5\u53ca<strong>Product ID\uff08\u7522\u54c1\u8b58\u5225\u78bc\uff0c\u7e2e\u5bebPID\uff09<\/strong>\uff0c\u4ee5\u53caESP32\u7684BLEHIDDevice\u985e\u5225\u7684\u4e00\u4e9b\u65b9\u6cd5\uff0c\u4e26\u4e14\u7de8\u5beb\u4e00\u500b\u85cd\u7259BLE\u904a\u6232\u63a7\u5236\u5668\u7a0b\u5f0f\u5eab\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">ESP32-BLE-Gamepad\u7a0b\u5f0f\u5eab<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">\u201clemmingDev\u201d\u7de8\u5beb\u4e86\u4e00\u500b\u5177\u5099\u4e0b\u5217\u529f\u80fd\u7684\u201cESP32-BLE-Gamepad\u201d\u7a0b\u5f0f\u5eab\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u652f\u63f4Windows, Android, Linux\u548cmacOS\uff0c\u4e0d\u652f\u63f4iOS\u3002<\/li>\n\n\n\n<li>\u9ad8\u9054128\u500b\u6309\u9375<\/li>\n\n\n\n<li>6\u8ef8\u985e\u6bd4\u6416\u687f\uff08x, y, z, rZ, rX, rY\uff09\u300116\u4f4d\u5143\u89e3\u6790\u5ea6<\/li>\n\n\n\n<li>2\u500b\u6ed1\u687f\u300116\u4f4d\u5143\u89e3\u6790\u5ea6<\/li>\n\n\n\n<li>4\u7d44HAT\uff08\u4e00\u500b\u5341\u5b57\u9375\u548c3\u500b\u5e3d\u5b50\u958b\u95dc\uff09<\/li>\n\n\n\n<li>\u6a21\u64ec\u5668\u63a7\u5236\u88dd\u7f6e\uff08\u65b9\u5411\u8235\u3001\u65b9\u5411\u76e4\u3001\u6cb9\u9580\u3001\u715e\u8eca\u2026\uff09<\/li>\n\n\n\n<li>\u53ef\u8a2d\u7f6e\u7684HID\u63cf\u8ff0\u5668\uff08descriptor\uff09<\/li>\n\n\n\n<li>\u53ef\u5ba2\u88fd\u5316\u7684\u85cd\u7259\u88dd\u7f6e\u540d\u7a31\u548c\u88fd\u9020\u5546\u540d\u7a31<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">\u5728Arduino IDE\u7684\u7a0b\u5f0f\u5eab\u7ba1\u7406\u54e1\u641c\u5c0b\u201cesp32 ble gamepad\u201d\uff0c\u5373\u53ef\u627e\u5230\u4e26\u5b89\u88dd\u9019\u500b\u7a0b\u5f0f\u5eab\uff1a<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" loading=\"lazy\" src=\"\/images\/hardware\/arduino\/wii_classic_controller\/esp32_ble_gamepad_lib.png\" alt=\"\u7a0b\u5f0f\u5eab\u7ba1\u7406\u54e1\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">\u5e95\u4e0b\u662f<a href=\"https:\/\/github.com\/lemmingDev\/ESP32-BLE-Gamepad\" target=\"_blank\" rel=\"noreferrer noopener\">ESP32 BLE Gamepad\u5c08\u6848\u539f\u59cb\u78bc\u9801\u9762<\/a>\u5c55\u793a\u7684\u7bc4\u4f8b\u7a0b\u5f0f\u78bc\uff0c\u7b46\u8005\u628a\u5176\u4e2d\u8a0a\u606f\u548c\u8a3b\u89e3\u7ffb\u8b6f\u6210\u4e2d\u6587\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">#include &lt;BleGamepad.h&gt; \nBleGamepad bleGamepad;\nvoid setup()  {\n  Serial.begin(115200);\n  Serial.println(\"BLE\u4f4e\u529f\u8017\u85cd\u7259\u958b\u5de5\u4e86\uff5e\");\n  bleGamepad.begin();\n  \/\/ \u4e0a\u9762\u7684bleGamepad.begin() \u6558\u8ff0\u7b49\u540c\n\/\/ bleGamepad.begin(16, 1, true, true, true, true, true, true, true, true, false, false, false, false, false);\n  \/\/ \u4ee3\u8868\u6b64\u88dd\u7f6e\u670916\u500b\u6309\u9375\u30011\u500b\u5341\u5b57\u9375\u3001\u555f\u7528x, y, z, rZ, rX, rY, \u6ed1\u687f1, \u6ed1\u687f2\u3001\u6c92\u6709\u65b9\u5411\u8235\u3001\u63a8\u9032\u5668\u3001\u52a0\u901f\u5668\u3001\u715e\u8eca\u548c\u65b9\u5411\u76e4\u3002\n  \/\/ \u9810\u8a2d\u555f\u7528\u300c\u81ea\u52d5\u50b3\u9001HID\u5831\u544a\u300d\n  \/\/ \u57f7\u884cbleGamepad.setAutoReport(false); \u53ef\u505c\u6b62\u81ea\u52d5\u50b3\u9001\u5831\u544a\n\/\/ \u7136\u5f8c\u900f\u904ebleGamepad.sendReport(); \u5728\u9700\u8981\u6642\u50b3\u9001\u5831\u544a\n}\nvoid loop() {\n  if(bleGamepad.isConnected()) {\n    Serial.println(\"\u6309\u4e0b\u6309\u93755\u548c16\uff0c\u6240\u6709\u6416\u687f\u8ef8\u90fd\u63a8\u5230\u6700\u5927\u503c\uff0c\u5341\u5b57\u9375\uff08hat 1\uff09\u6309\u8457\u300c\u53f3\u4e0b\u300d\u3002\");\n    bleGamepad.press(BUTTON_5);\n    bleGamepad.press(BUTTON_16);\n    bleGamepad.setAxes(32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, DPAD_DOWN_RIGHT);\n    \/\/ \u6240\u6709\u6416\u687f\u8ef8\u3001\u6ed1\u687f\u3001\u5e3d\u5b50\u958b\u95dc\u2026\u7b49\uff0c\u90fd\u80fd\u55ae\u7368\u8a2d\u7f6e\uff0c\u8acb\u53c3\u95b1IndividualAxes.ino\u7bc4\u4f8b\u6a94\u3002\n    delay(500);\n    Serial.println(\"\u653e\u958b\u6309\u93755\uff0c\u6240\u6709\u6416\u687f\u8ef8\u90fd\u63a8\u5411\u6700\u5c0f\u503c\uff0c\u5341\u5b57\u9375\uff08hat 1\uff09\u56de\u5230\u4e2d\u9593\uff08\u672a\u6309\u4e0b\uff09\u72c0\u614b\");\n    bleGamepad.release(BUTTON_5);\n    bleGamepad.setAxes(-32767, -32767, -32767, -32767, -32767, -32767, -32767, -32767, DPAD_CENTERED);\n    delay(500);\n  }\n}\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\u6b64\u7a0b\u5f0f\u5eab\u7684\u539f\u59cb\u78bc\u8aaa\u660e\u9801\u9762\u5e95\u4e0b\u6709\u63d0\u5230\uff0c\u9019\u500b\u7a0b\u5f0f\u5eab\u4e43\u57fa\u65bcT-vK \u7de8\u5beb\u7684<a href=\"https:\/\/github.com\/T-vK\/ESP32-BLE-Mouse\" target=\"_blank\" rel=\"noreferrer noopener\">ESP32-BLE-Mouse<\/a> \u4ee5\u53cachegewara\u7de8\u5beb\u7684<a href=\"https:\/\/github.com\/nkolban\/esp32-snippets\/issues\/230#issuecomment-473135679\" target=\"_blank\" rel=\"noreferrer noopener\">\u9019\u500bESP32 Windows 10\u7121\u7dda\u85cd\u7259\u6ed1\u9f20\u7a0b\u5f0f\u78bc<\/a>\u3002<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\u958b\u555f \u201cESP32-BLE-Gamepad\u201d\u7a0b\u5f0f\u5eab\u7684\u8cc7\u6599\u593e\uff08\u9810\u8a2d\u5b89\u88dd\u8def\u5f91\uff1a\u201c\u6587\u4ef6\\ Arduino\\libraries\\ESP32-BLE-Gamepad\u201d\uff09\uff0c\u53ef\u4ee5\u770b\u5230\u5b83\u67094\u500b\u7a0b\u5f0f\u6a94\uff1a<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" loading=\"lazy\" src=\"\/images\/hardware\/arduino\/wii_classic_controller\/esp32-ble-gamepad_folder.png\" alt=\"\u201cESP32-BLE-Gamepad\u201d\u7a0b\u5f0f\u5eab\u7684\u8cc7\u6599\u593e\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">\u5176\u4e2d\u7684BleConnectionStatus.cpp\uff08BLE\u9023\u7dda\u72c0\u614b\uff09\u6a94\u6e90\u81eaESP32-BLE-Mouse\u7a0b\u5f0f\u5eab\uff0c\u9019\u500b\u7a0b\u5f0f\u6a94\u5b9a\u7fa9\u4e86\u5169\u500b\u65b9\u6cd5\uff0c\u90fd\u9700\u8981\u50b3\u5165BLEServer\u985e\u578b\u7269\u4ef6\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>onConnect()\uff1a\u85cd\u7259\u9023\u7dda\u4e4b\u5f8c\u555f\u52d5\u901a\u77e5\u3002<\/li>\n\n\n\n<li>onDisconnect()\uff1a\u85cd\u7259\u65b7\u7dda\u4e4b\u5f8c\u505c\u6b62\u901a\u77e5\u3002<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">\u5e95\u4e0b\u662fonDisconnect()\u65b9\u6cd5\u7684\u539f\u59cb\u78bc\uff0c\u95dc\u65bc0x2902\u7279\u5fb5UUID\u7684\u8aaa\u660e\uff0c\u8acb\u53c3\u95b1\u300a\u8d85\u5716\u89e3ESP32\u6df1\u5ea6\u5be6\u4f5c\u300b\u7b2c15-29\u548c15-34\u9801\u8aaa\u660e\u3002<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">void BleConnectionStatus::onDisconnect(BLEServer* pServer) {\n  this-&gt;connected = false;\n  BLE2902* desc = (BLE2902*)this-&gt;inputGamepad-&gt;getDescriptorByUUID(BLEUUID((uint16_t)0x2902));\n  desc-&gt;setNotifications(false);  \n}\n<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">\u81ea\u88fdESP32\u85cd\u7259BLE\u904a\u6232\u624b\u628a<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">\u7b46\u8005\u57fa\u65bc\u201clemmingDev\u201d\u7de8\u5beb\u7684\u201cESP32-BLE-Gamepad\u201d\u7a0b\u5f0f\u5eab\uff0c\u4ee5\u53caJason Harley\u7de8\u5beb\u7684Leonardo-Switch-Controller\u7a0b\u5f0f\u5eab\uff0c\u6539\u5beb\u4e86\u4e00\u500b\u53ef\u7528\u65bc\u96fb\u8166\u548cAndroid\u624b\u6a5f\u7684ESP32\u85cd\u7259\u904a\u6232\u624b\u628a\u7a0b\u5f0f\u5eab\uff0c\u53ef<a href=\"\/files\/arduino\/ESP32_BLE_Gamepad.zip\">\u9ede\u64ca\u6b64\u9023\u7d50\u4e0b\u8f09\u539f\u59cb\u6a94<\/a>\u3002\u9019\u500b\u7a0b\u5f0f\u5eab\u7684\u65b9\u6cd5\u540d\u7a31\u6cbf\u7528Leonardo-Switch-Controller\u7a0b\u5f0f\u5eab\u7684\u5b9a\u7fa9\uff08\u53c3\u95b1\u300c<a href=\"\/?p=1544\" target=\"_blank\" rel=\"noreferrer noopener\">\u81ea\u88fdSwitch Pro\u76f8\u5bb9\u904a\u6232\u63a7\u5236\u5668\uff08\u4e09\uff09\uff1aJoystick\u7a0b\u5f0f\u5eab\u7684\u985e\u5225\u65b9\u6cd5\u8aaa\u660e<\/a>\u300d\uff09\u3002<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" loading=\"lazy\" src=\"\/images\/hardware\/arduino\/wii_classic_controller\/esp32_ble_gamepad_lib_folder.png\" alt=\"\u81ea\u88fdESP32\u85cd\u7259BLE\u904a\u6232\u624b\u628a\u7684\u8cc7\u6599\u593e\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">HID\u5831\u544a\u63cf\u8ff0\u5668\u7684\u5167\u5bb9\u4e5f\u6cbf\u7528\u4efb\u5929\u5802Switch Pro\u63a7\u5236\u5668\u7684\u8a2d\u7f6e\uff0c\u76f8\u95dc\u8aaa\u660e\u8acb\u53c3\u95b1\u300c<a href=\"\/?p=1536\" target=\"_blank\" rel=\"noreferrer noopener\">Gamepad\u624b\u628a\u7684HID Report Descriptor\uff08\u5831\u544a\u63cf\u8ff0\u5668\uff09\u683c\u5f0f\u8aaa\u660e<\/a>\u300d\u3002<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\u9019\u500b\u4f8b\u5b50\u7684\u904a\u6232\u63a7\u5236\u5668\u63a1\u7528\u73fe\u6210\u7684Wii\u7d93\u5178\u624b\u628a\uff0c\u4f60\u53ef\u4ee5\u6539\u7528\u6309\u9375\u958b\u95dc\u548c\u985e\u6bd4\u6416\u687f\u6a21\u7d44\u81ea\u884c\u7d44\u88dd\u904a\u6232\u624b\u628a\u3002Wii\u7d93\u5178\u624b\u628a\u63a1\u7528<strong>I2C\u901a\u8a0a<\/strong>\uff0c\u9023\u63a5ESP32\u7684\u9810\u8a2dI2C\u63a5\u8173\u548c3.3V\uff0c\u9eb5\u5305\u677f\u793a\u7bc4\u63a5\u7dda\uff1a<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" loading=\"lazy\" src=\"\/images\/hardware\/arduino\/wii_classic_controller\/ESP32_breadboard.png\" alt=\"ESP32 BLE\u904a\u6232\u624b\u628a\u793a\u7bc4\u63a5\u7dda\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">\u63a1\u7528\u81ea\u88fd\u7684ESP32\u85cd\u7259BLE\u904a\u6232\u63a7\u5236\u5668\u7a0b\u5f0f\u5eab\u7684Arduino\u7bc4\u4f8b\u7a0b\u5f0f\uff0cNintendoExtensionCtrl.h\u7a0b\u5f0f\u5eab\u9700\u8981\u984d\u5916\u5b89\u88dd\uff0c\u8acb\u53c3\u95b1<a href=\"\/?p=1530\" target=\"_blank\" rel=\"noreferrer noopener\">\u7b2c\u4e00\u7bc7\u6587\u7ae0<\/a>\u8aaa\u660e\u3002<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">#include &lt;esp32blegamepad.h&gt;    \/\/ \u81ea\u88fd\u7684ESP32\u85cd\u7259BLE\u904a\u6232\u63a7\u5236\u5668\u7a0b\u5f0f\u5eab\n#include &lt;nintendoextensionctrl.h&gt; \/\/ \u8b80\u53d6Wii\u63a7\u5236\u5668\u7684\u7a0b\u5f0f\u5eab\nBleGamepad bleGamepad;\nClassicController classic;\nvoid setup() {\n  Serial.begin(115200);\n  bleGamepad.begin(false);\n  classic.begin();\n  while (!classic.connect()) {\n    Serial.println(\"\u9023\u4e0aWii\u7d93\u5178\u63a7\u5236\u5668\uff0c\u958b\u59cb\u555f\u52d5\u85cd\u7259\u2026\");\n    delay(1000);\n  }\n}\n\/\/ \u5de6\u53f3\u985e\u6bd4\u6416\u687f\u7684\u6578\u503c\u7bc4\u570d\uff1a0~255\nint rightStick(uint8_t input) {\n  if (input &gt; 24)\n    return 255;\n  else if (input &gt; 20)\n    return 127;\n  else if (input &lt; 8)\n    return 0;\n  else if (input &lt; 12)\n    return 64;\n  return 127;\n}\nint leftStick(uint8_t input) {\n  if (input &gt; 45)\n    return 255;\n  else if (input &gt; 35)\n    return 191;\n  else if (input &lt; 15)\n    return 0;\n  else if (input &lt; 25)\n    return 64;\n  return 127;\n}\nvoid loop() {\n  boolean success = classic.update();  \/\/ \u8b80\u53d6Wii\u7d93\u5178\u624b\u628a\u7684\u8cc7\u6599\n  if (!success) {\n    Serial.println(\"\u7d93\u5178\u63a7\u5236\u5668\u65b7\u7dda\u4e86\uff5e\u91cd\u65b0\u9023\u7dda\u2026\");\n    classic.reconnect();\n    delay(100);\n  } else {\n    classic.printDebug();  \/\/ \u986f\u793a\u7d93\u5178\u624b\u628a\u7684\u72c0\u614b\n    \/\/ \u8b80\u53d6Wii\u7d93\u5178\u624b\u628a\u7684\u6240\u6709\u6309\u9375\u7684\u72c0\u614b\n    bleGamepad.setButton(2, classic.buttonA());\n    bleGamepad.setButton(1, classic.buttonB());\n    bleGamepad.setButton(3, classic.buttonX());\n    bleGamepad.setButton(0, classic.buttonY());\n    bleGamepad.setButton(4, classic.buttonL());\n    bleGamepad.setButton(5, classic.buttonR());\n    bleGamepad.setButton(6, classic.buttonZL());\n    bleGamepad.setButton(7, classic.buttonZR());\n    bleGamepad.setButton(9, classic.buttonPlus());\n    bleGamepad.setButton(8, classic.buttonMinus());\n    bleGamepad.setButton(12, classic.buttonHome());\n    \/\/ \u8b80\u53d6\u5de6\u53f3\u985e\u6bd4\u8ef8\n    bleGamepad.setXAxis(leftStick(classic.leftJoyX()));\n    bleGamepad.setYAxis(255-leftStick(classic.leftJoyY()));  \/\/ \u53cd\u76f8Y\u8ef8\u7684\u503c\n    bleGamepad.setZAxis(rightStick(classic.rightJoyX()));\n    bleGamepad.setZAxisRotation(255-rightStick(classic.rightJoyY()));\n    \/\/ \u8b80\u53d6\u5341\u5b57\u9375\n    if (classic.dpadUp()) {\n      if (classic.dpadLeft())\n        bleGamepad.setHatSwitch(7);\n      else if (classic.dpadRight())\n        bleGamepad.setHatSwitch(1);\n      else\n        bleGamepad.setHatSwitch(0);\n    } else if (classic.dpadDown()) {\n      if (classic.dpadLeft())\n        bleGamepad.setHatSwitch(5);\n      else if (classic.dpadRight())\n        bleGamepad.setHatSwitch(3);\n      else\n        bleGamepad.setHatSwitch(4);\n    } else if (classic.dpadRight())\n      bleGamepad.setHatSwitch(2);\n    else if (classic.dpadLeft())\n      bleGamepad.setHatSwitch(6);\n    else\n      bleGamepad.setHatSwitch(-1);\n  }\n  \/\/ \u9001\u51fa\u7d93\u5178\u624b\u628a\u7684HID\u5831\u544a\n  bleGamepad.sendState();\n  delay(1);\n}\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\u7de8\u8b6f\u7a0b\u5f0f\u5f8c\u4e0a\u50b3\u5230\u9023\u63a5Wii\u7d93\u5178\u63a7\u5236\u5668\u7684ESP32\u958b\u767c\u677f\uff0c\u5f9e\u96fb\u8166\u7cfb\u7d71\u7684\u63a7\u5236\u53f0\u641c\u5c0b\u4e26\u9023\u7d50\u5230ESP32 BLE Gamepad\u88dd\u7f6e\uff1a<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" loading=\"lazy\" src=\"\/images\/hardware\/arduino\/wii_classic_controller\/windows10_BLE.png\" alt=\"Windows 10\u85cd\u82bd\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">\u63a5\u8457\u958b\u555f\u700f\u89bd\u5668\u9023\u7d50\u5230<a href=\"https:\/\/gamepad-tester.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Gamepad Tester<\/a>\uff08\u904a\u6232\u63a7\u5236\u5668\u6e2c\u8a66\u7db2\u9801\uff09\uff0c\u5373\u53ef\u6e2c\u8a66\u904a\u6232\u63a7\u5236\u5668\u7684\u5404\u500b\u6309\u9375\u548c\u6416\u687f\uff1a<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" loading=\"lazy\" src=\"\/images\/hardware\/arduino\/wii_classic_controller\/gamepad-tester.png\" alt=\"Gamepad Tester\uff08\u904a\u6232\u63a7\u5236\u5668\u6e2c\u8a66\u7db2\u9801\uff09\"\/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">ESP32\u85cd\u7259BLE\u904a\u6232\u63a7\u5236\u5668\u7a0b\u5f0f\u5eab\u7684\u539f\u59cb\u78bc<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">\u5e95\u4e0b\u662fESP32BleGamepad.cpp\u7684\u539f\u59cb\u78bc\uff0c\u7a0b\u5f0f\u900f\u904e\u4e00\u500bFreeRTOS\u591a\u5de5\u4efb\u52d9\u5efa\u7acb\u4e26\u5ee3\u64adHID\u88dd\u7f6e\u8cc7\u8a0a\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">#include &lt;ESP32BleGamepad.h&gt;\n#include &lt;BLEDevice.h&gt;\n#include &lt;BLEUtils.h&gt;\n#include &lt;BLEServer.h&gt;\n#include &lt;BLEHIDDevice.h&gt;\n#include &lt;HIDTypes.h&gt;\n#define GAMEPAD_REPORT_ID 0x03\n#define GAMEPAD_STATE_SIZE 7\n\/\/ \u5831\u544a\u63cf\u8ff0\u5668\u8cc7\u6599\nstatic const uint8_t _hidReportDescriptor[] = {\n    \/\/ \u904a\u6232\u63a7\u5236\u5668\uff08Gamepad\uff09\n    0x05, 0x01, \/\/ USAGE_PAGE (Generic Desktop)\n    0x09, 0x05, \/\/ USAGE (Gamepad)\n    0xa1, 0x01, \/\/ COLLECTION (Application)\n    0x85, 0x03, \/\/   REPORT_ID (3)\n    \/\/ 14\u500b\u6309\u9375\n    0x05, 0x09, \/\/   USAGE_PAGE (Button)\n    0x19, 0x01, \/\/   USAGE_MINIMUM (\u7bc4\u570d\u6700\u5c0f\u503c\uff1a1)\n    0x29, 0x0E, \/\/   USAGE_MAXIMUM (\u7bc4\u570d\u6700\u5927\u503c\uff1a14)\n    0x15, 0x00, \/\/   LOGICAL_MINIMUM (0)\n    0x25, 0x01, \/\/   LOGICAL_MAXIMUM (1)\n    0x75, 0x01, \/\/   REPORT_SIZE (1)\n    0x95, 0x0E, \/\/   REPORT_COUNT (14\u500b\u6309\u9375)\n    0x81, 0x02, \/\/   INPUT (Data,Var,Abs)\n    \/\/ \u88dc\u4e0a\u5169\u500b\u7a7a\u767d\n    0x95, 0x01, \/\/   REPORT_COUNT (1)\n    0x75, 0x02, \/\/   REPORT_SIZE (2\u500b\u4f4d\u5143)\n    0x81, 0x01, \/\/   INPUT (\u4fdd\u7559)\n    \/\/ 8\u65b9\u5411\u5341\u5b57\u9375\uff08HAT\uff09\n    0x05, 0x01,       \/\/   USAGE_PAGE (General Desktop)\uff0c\u901a\u7528\u684c\u4e0a\u578b\n    0x09, 0x39,       \/\/   USAGE (Hat Switch)\uff0c\u5e3d\u5b50\u958b\u95dc\uff08\u5341\u5b57\u9375\uff09\n    0x15, 0x00,       \/\/   LOGICAL_MINIMUM (0)\uff0c\u908f\u8f2f\u6700\u5c0f\u503c\n    0x25, 0x07,       \/\/   LOGICAL_MAXIMUM (7)\uff0c\u908f\u8f2f\u6700\u5927\u503c\n    0x35, 0x00,       \/\/   PHYSICAL_MINIMUM (0)\uff0c\u5be6\u9ad4\u6700\u5c0f\u503c\n    0x46, 0x3B, 0x01, \/\/   PHYSICAL_MAXIMUM (315) \uff0c\u5be6\u9ad4\u6700\u5927\u503c\n    0x65, 0x14,       \/\/   UNIT (Eng Rot:Angular Pos)\uff0c\u55ae\u4f4d\uff1a\u82f1\u5236\u89d2\u5ea6\n    0x75, 0x04,       \/\/   REPORT_SIZE (4)\uff0c\u4f544\u500b\u4f4d\u5143\n    0x95, 0x01,       \/\/   REPORT_COUNT (1)\n    0x81, 0x02,       \/\/   INPUT (Data,Var,Abs)\uff0c\u7d55\u5c0d\u53ef\u8b8a\u8cc7\u6599\n                      \/\/ \u586b\u88dc4\u500b\u7a7a\u767d\u4f4d\u5143\n    0x95, 0x01,       \/\/ REPORT_COUNT (1)\n    0x75, 0x04,       \/\/ REPORT_SIZE (4)\uff0c\u51714\u500b\u4f4d\u5143\n    0x81, 0x01,       \/\/ INPUT\n    \/\/ X, Y\u548cZ\u8ef8\n    0x15, 0x00,       \/\/   LOGICAL_MINIMUM (0)\n    0x26, 0xff, 0x00, \/\/   LOGICAL_MAXIMUM (255)\n    0x75, 0x08,       \/\/   REPORT_SIZE (8)\n    0x09, 0x01,       \/\/   USAGE (Pointer)\uff0c\u6e38\u6a19\n    0xA1, 0x00,       \/\/   COLLECTION (Physical)\uff0c\u6e38\u6a19\u7684\u5ea7\u6a19\u8cc7\u6599\u96c6\u5408\n    0x09, 0x30,       \/\/     USAGE (x)\n    0x09, 0x31,       \/\/     USAGE (y)\n    0x09, 0x32,       \/\/     USAGE (z)\n    0x09, 0x35,       \/\/     USAGE (rz)\n    0x95, 0x04,       \/\/     REPORT_COUNT (4)\n    0x81, 0x02,       \/\/     INPUT (Data,Var,Abs)\n    0xc0,             \/\/   END_COLLECTION\n    0xc0 \/\/ END_COLLECTION\n};\nBleGamepad::BleGamepad(std::string deviceName, std::string deviceManufacturer, uint8_t batteryLevel) {\n    \/\/ \u521d\u59cb\u5316\u985e\u6bd4\u6416\u687f\u3001\u5341\u5b57\u9375\u548c\u6309\u9375\u7684\u72c0\u614b\n    xAxis = 0;\n    yAxis = 0;\n    zAxis = 0;\n    zAxisRotation = 0;\n    buttons = 0;\n    hatSwitch = -1;\n    this-&gt;deviceName = deviceName;                       \/\/ \u88dd\u7f6e\u540d\u7a31\u5b57\u4e32\n    this-&gt;deviceManufacturer = deviceManufacturer;       \/\/ \u88fd\u9020\u5546\u540d\u7a31\u5b57\u4e32\n    this-&gt;batteryLevel = batteryLevel;                   \/\/ \u96fb\u91cf\u6e96\u4f4d\n    this-&gt;connectionStatus = new BleConnectionStatus(); \/\/ \u9023\u7dda\u72c0\u614b\u7269\u4ef6\n}\nvoid BleGamepad::begin(bool initAutoSendState) {\n    autoSendState = initAutoSendState;\n    \/\/ \u5efa\u7acbFreeRTOS\u4efb\u52d9\n    xTaskCreate(this-&gt;taskServer, \"server\", 20000, (void *)this, 5, NULL);\n}\n\/\/ FreeRTOS\u4efb\u52d9\u51fd\u5f0f\nvoid BleGamepad::taskServer(void *pvParameter) {\n    \/\/ \u5f9e\u4efb\u52d9\u53c3\u6578\u53d6\u5f97\u904a\u6232\u63a7\u5236\u5668\u7269\u4ef6\uff08BleGamepadInstance\uff09\n    BleGamepad *BleGamepadInstance = (BleGamepad *)pvParameter;\n    \/\/ \u8a2d\u5b9a\u88dd\u7f6e\u540d\u7a31\n    BLEDevice::init(BleGamepadInstance-&gt;deviceName);\n    \/\/ \u5efa\u7acb\u85cd\u7259\u88dd\u7f6e\u4f3a\u670d\u5668\n    BLEServer *pServer = BLEDevice::createServer();\n    \/\/ \u8a2d\u5b9a\u9023\u7dda\u72c0\u614b\u56de\u547c\n    pServer-&gt;setCallbacks(BleGamepadInstance-&gt;connectionStatus);\n    \/\/ \u5efa\u7acbHID\uff08\u4eba\u6a5f\u4ecb\u9762\u88dd\u7f6e\uff09\u7269\u4ef6\n    BleGamepadInstance-&gt;hid = new BLEHIDDevice(pServer);\n    \/\/ \u8a2d\u5b9a\u300c\u8f38\u5165\u300d\u985e\u578b\u88dd\u7f6e\u7684\u5831\u544aID\n    BleGamepadInstance-&gt;inputGamepad = BleGamepadInstance-&gt;hid-&gt;inputReport(GAMEPAD_REPORT_ID);\n    \/\/ \u66ff\u9023\u7dda\u72c0\u614b\u8a2d\u5b9a\u5075\u807d\u7684\u5c0d\u8c61\n    BleGamepadInstance-&gt;connectionStatus-&gt;inputGamepad = BleGamepadInstance-&gt;inputGamepad;\n    \/\/ \u8a2d\u5b9a\u88fd\u9020\u5546\u8cc7\u8a0a\uff08UTF-8\u7de8\u78bc\u5b57\u4e32\u7684\u81ea\u8a02\u5ee0\u5546\u540d\u7a31\uff09\n    BleGamepadInstance-&gt;hid-&gt;manufacturer()-&gt;setValue(BleGamepadInstance-&gt;deviceManufacturer);\n    \/\/ \u8a2d\u5b9a\u88dd\u7f6e\u7684PID\u548cVID\uff0c\u53c3\u95b1\u4e0b\u6587\u8aaa\u660e\u3002\n    BleGamepadInstance-&gt;hid-&gt;pnp(0x02, 0x7e05, 0x0920, 0x0110);\n    BleGamepadInstance-&gt;hid-&gt;hidInfo(0x00, 0x01);\n    \/\/ \u8a2d\u5b9a\u9023\u7dda\u8a8d\u8b49\u6a21\u5f0f\uff0c\u201cESP_LE_AUTH_BOND\u201d\u4ee3\u8868\u300c\u7d81\u5b9a\u300d\uff0c\n\/\/ \u4e5f\u5c31\u662f\u5132\u5b58\u9577\u671f\u5bc6\u9470\uff0c\u65e5\u5f8c\u9023\u7dda\u4e0d\u5fc5\u518d\u914d\u5c0d\uff0c\n\/\/ \u76f8\u95dc\u8aaa\u660e\u8acb\u53c3\u95b1\u300a\u8d85\u5716\u89e3ESP32\u6df1\u5ea6\u5be6\u4f5c\u300b15-17\u9801\u3002\n    BLESecurity *pSecurity = new BLESecurity();\n    pSecurity-&gt;setAuthenticationMode(ESP_LE_AUTH_BOND);\n    \/\/ \u8a2d\u5b9aHID\u5831\u544a\u63cf\u8ff0\u5668\n    BleGamepadInstance-&gt;hid-&gt;reportMap((uint8_t *)_hidReportDescriptor, sizeof(_hidReportDescriptor));\n    \/\/ \u555f\u52d5\u670d\u52d9\n    BleGamepadInstance-&gt;hid-&gt;startServices();\n    \/\/ \u8a2d\u5b9a\u555f\u52d5\u670d\u52d9\u7684\u56de\u547c\u8655\u7406\u51fd\u5f0f\n    BleGamepadInstance-&gt;onStarted(pServer);\n    \/\/ \u8a2d\u5b9a\u5ee3\u64ad\u8a0a\u606f\uff08\u5ee3\u544a\u5c01\u5305\uff09\n    BLEAdvertising *pAdvertising = pServer-&gt;getAdvertising();\n    \/\/ \u8a2d\u5b9aHID\u88dd\u7f6e\u7684\u5716\u793a\n    pAdvertising-&gt;setAppearance(HID_GAMEPAD);\n    pAdvertising-&gt;addServiceUUID(BleGamepadInstance-&gt;hid-&gt;hidService()-&gt;getUUID());\n    \/\/ \u958b\u59cb\u5ee3\u64ad\n    pAdvertising-&gt;start();\n    \/\/ \u8a2d\u5b9a\u96fb\u91cf\u6e96\u4f4d\n    BleGamepadInstance-&gt;hid-&gt;setBatteryLevel(BleGamepadInstance-&gt;batteryLevel);\n    \/\/ \u7121\u9650\u671f\u7b49\u5f85\n    vTaskDelay(portMAX_DELAY);\n}\nvoid BleGamepad::end() {\n}\n\/\/ \u8a2d\u5b9a\u6309\u9375\nvoid BleGamepad::setButton(uint8_t button, uint8_t value) {\n    if (value == 0) {\n        releaseButton(button);\n    } else {\n        pressButton(button);\n    }\n}\n\/\/ \u6309\u4e0b\u6309\u9375\nvoid BleGamepad::pressButton(uint8_t button) {\n    bitSet(buttons, button);\n    if (autoSendState)\n        sendState();\n}\n\/\/ \u653e\u958b\u6309\u9375\nvoid BleGamepad::releaseButton(uint8_t button) {\n    bitClear(buttons, button);\n    if (autoSendState)\n        sendState();\n}\n\/\/ \u8a2d\u5b9a\u985e\u6bd4\u6416\u687fX\u8ef8\uff08\u5de6\u6416\u687fX\uff09\nvoid BleGamepad::setXAxis(uint8_t value) {\n    xAxis = value;\n    if (autoSendState)\n        sendState();\n}\n\/\/ \u8a2d\u5b9a\u985e\u6bd4\u6416\u687fY\u8ef8\uff08\u5de6\u6416\u687fY\uff09\nvoid BleGamepad::setYAxis(uint8_t value) {\n    yAxis = value;\n    if (autoSendState)\n        sendState();\n}\n\/\/ \u53f3\u6416\u687fX\nvoid BleGamepad::setZAxis(uint8_t value) {\n    zAxis = value;\n    if (autoSendState)\n        sendState();\n}\n\/\/ \u53f3\u6416\u687fY\nvoid BleGamepad::setZAxisRotation(uint8_t value) {\n    zAxisRotation = value;\n    if (autoSendState)\n        sendState();\n}\n\/\/ \u8a2d\u5b9a\u5341\u5b57\u9375\nvoid BleGamepad::setHatSwitch(int16_t value) {\n    hatSwitch = value;\n    if (autoSendState)\n        sendState();\n}\n\/\/ \u50b3\u9001HID\u5831\u544a\nvoid BleGamepad::sendState() {\n    if (this-&gt;isConnected()) {\n        uint8_t data[GAMEPAD_STATE_SIZE];\n        uint32_t buttonTmp = buttons;\n        \/\/ \u628a16\u4f4d\u5143\u62c6\u5206\u62102\u4f4d\u5143\u7d44\n        data[0] = buttonTmp &amp; 0xFF;\n        buttonTmp &gt;&gt;= 8;\n        data[1] = buttonTmp &amp; 0xFF;\n        if (hatSwitch &lt; 0)\n            hatSwitch = 8;\n        \/\/ \u628a\u5341\u5b57\u9375\u6309\u9375\u72c0\u614b\u5305\u88dd\u6210\u4e00\u500b\u4f4d\u5143\u7d44\n        data[2] = (B00001111 &amp; hatSwitch);\n        data[3] = xAxis;\n        data[4] = yAxis;\n        data[5] = zAxis;\n        data[6] = zAxisRotation;\n        this-&gt;inputGamepad-&gt;setValue(data, GAMEPAD_STATE_SIZE);\n        this-&gt;inputGamepad-&gt;notify();\n    }\n}\n\/\/ \u78ba\u8a8d\u85cd\u7259\u7684\u9023\u7dda\u72c0\u614b\nbool BleGamepad::isConnected() {\n    return this-&gt;connectionStatus-&gt;connected;\n}\n\/\/ \u8a2d\u5b9a\u96fb\u91cf\u6e96\u4f4d\nvoid BleGamepad::setBatteryLevel(uint8_t level) {\n    this-&gt;batteryLevel = level;\n    if (hid != 0)\n        this-&gt;hid-&gt;setBatteryLevel(this-&gt;batteryLevel);\n}\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">FreeRTOS\u7684taskServer\u4efb\u52d9\u51fd\u5f0f\uff0c\u548c<a href=\"https:\/\/github.com\/T-vK\/ESP32-BLE-Mouse\" target=\"_blank\" rel=\"noreferrer noopener\">ESP32-BLE-Mouse<\/a>\u7684\u540c\u540d\u4efb\u52d9\u51fd\u5f0f\u76f8\u6bd4\uff0c\u4e3b\u8981\u7684\u5dee\u5225\u5728\u4eba\u6a5f\u4ecb\u9762\u88dd\u7f6e\u7684Report ID\uff08\u5831\u544aID\uff09\u4e0d\u540c\uff0c\u6ed1\u9f20\u662f0x02\uff0c\u904a\u6232\u63a7\u5236\u5668\uff08Gamepad\uff09\u662f0x03\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">USB\u88dd\u7f6e\u7684VID, PID\u548cDID<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">\u96fb\u8166\u7cfb\u7d71\u900f\u904eHID\u88dd\u7f6e\u7684<strong>Vender ID\uff08\u5ee0\u5546\u8b58\u5225\u78bc\uff0c\u7e2e\u5bebVID\uff09<\/strong>\u4ee5\u53caP<strong>roduct ID\uff08\u7522\u54c1\u8b58\u5225\u78bc\uff0c\u7e2e\u5bebPID\uff09<\/strong>\u4f86\u8fa8\u8b58\u88dd\u7f6e\uff0c\u9032\u800c\u5b89\u88dd\u9069\u5408\u7684\u9a45\u52d5\u7a0b\u5f0f\u3002\u5728Windows 10\u7cfb\u7d71\u7684\u300c\u88dd\u7f6e\u7ba1\u7406\u54e1\u300d\u7684\u300c\u4eba\u6027\u5316\u4ecb\u9762\u88dd\u7f6e\u300d\u5206\u985e\uff0c\u5217\u8209\u6240\u6709\u9023\u63a5\u9019\u53f0\u96fb\u8166\u7684HID\u88dd\u7f6e\u3002\u4ee5Xbox One\u63a7\u5236\u5668\u70ba\u4f8b\uff0c\u9664\u4e86\u5217\u5728\u300c\u4eba\u6027\u5316\u4ecb\u9762\u88dd\u7f6e\u300d\uff0c\u9084\u6703\u55ae\u7368\u5217\u8209\u5728\u300cXbox\u9031\u908a\u8a2d\u5099\u300d\u88e1\u9762\uff1b\u5728\u4efb\u4e00HID\u88dd\u7f6e\u540d\u7a31\u4e0a\u6309\u6ed1\u9f20\u53f3\u9375\uff0c\u9078\u64c7\u300c\u5167\u5bb9\u300d\uff1a<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" loading=\"lazy\" src=\"\/images\/hardware\/arduino\/wii_classic_controller\/HID_VID_PID_1.png\" alt=\"indows 10\u7684\u88dd\u7f6e\u7ba1\u7406\u54e1\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">\u5207\u63db\u5230\u300c\u8a73\u7d30\u8cc7\u6599\u300d\u5206\u9801\uff0c\u5f9e\u300c\u5c6c\u6027\u300d\u9078\u55ae\u9078\u64c7\u300c\u786c\u9ad4\u8b58\u5225\u78bc\u300d\uff0c\u5373\u53ef\u898b\u5230\u8a72\u88dd\u7f6e\u7684VID\u548cPID\u78bc\uff0c\u4ee5\u9019\u500bXbox One\u63a7\u5236\u5668\u70ba\u4f8b\uff0cVID\u662f0x045E\uff08\u4ee3\u8868\u5fae\u8edf\u516c\u53f8\uff09\u3001PID\u662f0x02EA\uff08\u4ee3\u8868Xbox One S\u63a7\u5236\u5668\uff09\u3002<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" loading=\"lazy\" src=\"\/images\/hardware\/arduino\/wii_classic_controller\/HID_VID_PID_2.png\" alt=\"\u786c\u9ad4\u8b58\u5225\u78bc\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">VID\u7531USB\u6a5f\u69cb\u7d71\u7c4c\u7de8\u5236\uff0c\u6839\u64daUSB\u6a5f\u69cb\u7684\u201c<a href=\"https:\/\/www.usb.org\/getting-vendor-id\" target=\"_blank\" rel=\"noreferrer noopener\">Getting a Vendor ID<\/a>\u201d\u9801\u9762\u6307\u51fa\uff0c\u53d6\u5f97VID\u7684\u65b9\u5f0f\u6709\u5169\u7a2e\uff1a\u652f\u4ed8\u5e74\u8cbb\u7f8e\u91d1$5,000\u52a0\u5165\u6703\u54e1\uff0c\u6216\u8005\u7e73\u7d0d\u7f8e\u91d1$3,500\u5143\u53d6\u5f97\u70ba\u671f\u5169\u5e74\u7684\u975e<a href=\"https:\/\/zh.wikipedia.org\/wiki\/USB%E9%96%8B%E7%99%BC%E8%80%85%E8%AB%96%E5%A3%87\" target=\"_blank\" rel=\"noreferrer noopener\">USB\u958b\u767c\u8005\u8ad6\u58c7\uff08USB Implementers Forum\uff0c\u7e2e\u5beb\u70baUSB-IF\uff09<\/a>\u6703\u54e1\u5546\u6a19\u6388\u6b0a\u3002<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\u5be6\u9a57\u7522\u54c1\u6216\u8005\u81ea\u5df1DIY\u7684\u6771\u897f\u7576\u7136\u4e0d\u7528\u53d6\u5f97VID\uff0c\u53ef\u63a1\u7528\u73fe\u6709\u5ee0\u5546\u7684\u8b58\u5225\u78bc\u3002<a href=\"https:\/\/devicehunt.com\/all-usb-vendors\" target=\"_blank\" rel=\"noreferrer noopener\">devicehunt.com\u7684\u9019\u500b\u7db2\u9801<\/a>\u4ee5\u53ca<a href=\"http:\/\/www.linux-usb.org\/usb.ids\" target=\"_blank\" rel=\"noreferrer noopener\">linux-usb.org\u7684\u9019\u500b\u6587\u4ef6<\/a>\uff0c\u5217\u8209\u4e86\u6240\u6709USB\u88fd\u9020\u5546\u7684VID\u4ee5\u53ca\u7522\u54c1\u7684ID\uff1b\u9019\u4e9b\u7db2\u9801\u7528<strong>Device ID\uff08\u88dd\u7f6eID\uff0c\u7e2e\u5bebDID\uff09<\/strong>\u4f86\u7a31\u547cPID\uff0c\u4f46\u300c\u88dd\u7f6eID\u300d\u901a\u5e38\u662f\u6307VID\u548cPID\u7d44\u6210\u7684\u88dd\u7f6e\u552f\u4e00\u8b58\u5225\u78bc\u3002<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" loading=\"lazy\" src=\"\/images\/hardware\/arduino\/wii_classic_controller\/HID_VID_PID_3.png\" alt=\"devicehunt.com\"\/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">ESP32 BLEHIDDevice\u985e\u5225\u7684\u65b9\u6cd5<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">ESP32 BLE\u4eba\u6a5f\u4ecb\u9762\u88dd\u7f6e\u900f\u904e<a href=\"https:\/\/github.com\/espressif\/arduino-esp32\/blob\/master\/libraries\/BLE\/src\/BLEHIDDevice.h\" target=\"_blank\" rel=\"noreferrer noopener\">BLEHIDDevice\u985e\u5225<\/a>\u8a2d\u5b9a\u88dd\u7f6e\u7684\u8cc7\u8a0a\uff0c\u5e95\u4e0b\u5217\u8209\u672c\u6587\u7528\u5230\u7684\u4e00\u4e9b\u65b9\u6cd5\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>BLECharacteristic* inputReport(uint8_t reportID)\uff1a\u8a2d\u5b9a\u300c\u8f38\u5165\u5831\u544a\u300d\u7684\u5831\u544aID\uff0c\u6b64\u4f8b\u70ba3\u3002<\/li>\n\n\n\n<li>void reportMap(uint8_t* map, uint16_t)\uff1a\u8a2d\u5b9aHID\u5831\u544a\u63cf\u8ff0\u5668\u3002<\/li>\n\n\n\n<li>void startServices()\uff1a\u555f\u52d5\u670d\u52d9<\/li>\n\n\n\n<li>void manufacturer(std::string name)\uff1a\u8a2d\u5b9a\u88fd\u9020\u5546\u540d\u7a31\u5b57\u4e32<\/li>\n\n\n\n<li>void setBatteryLevel(uint8_t level)\uff1a\u8a2d\u5b9a\u96fb\u91cf\u6e96\u4f4d\u3002<\/li>\n\n\n\n<li>void pnp(uint8_t sig, uint16_t vid, uint16_t pid, uint16_t version)\uff1a\u8a2d\u5b9a\u88dd\u7f6e\u7684VID\u548cPID\u3002<\/li>\n\n\n\n<li>void hidInfo(uint8_t country, uint8_t flags)\uff1a\u8a2d\u5b9a\u6b64\u88dd\u7f6e\u7684\u5730\u5340\u4ee5\u53ca\u662f\u5426\u53ef\u559a\u9192\u4e3b\u6a5f\u7b49\u8cc7\u8a0a\u3002<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">\u5176\u4e2d\uff0chidInfo()\u65b9\u6cd5\u7684\u7b2c1\u500b\u53c3\u6578\u662f\u5730\u5340\u78bc\uff0c\u4f46HID\u88dd\u7f6e\u901a\u5e38\u8ddf\u4f7f\u7528\u5730\u5340\u7121\u95dc\uff0c\u6240\u4ee5\u7b2c1\u500b\u53c3\u6578\u8a2d\u62100\uff1b\u7b2c2\u500b\u53c3\u6578\u7684\u7b2c1\u500b\u4f4d\u5143\u6307\u51fa\u88dd\u7f6e\u662f\u5426\u5177\u5099\u559a\u9192\u4e3b\u6a5f\u7684\u529f\u80fd\uff0c\u7b2c2\u500b\u4f4d\u5143\u5247\u6307\u51fa\u88dd\u7f6e\u662f\u5426\u70ba\u53ef\u76f4\u63a5\u9023\u7dda\uff08normally connectable\uff09\uff0c\u4e5f\u5c31\u662f\u901a\u96fb\u4e4b\u5f8c\uff0c\u7121\u9700\u4eba\u70ba\u64cd\u4f5c\u5373\u53ef\u8207\u4e3b\u6a5f\u9023\u7dda\u3002<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\u8a2d\u5b9a\u88dd\u7f6eVID\u548cPID\u7684pnp()\u65b9\u6cd5\u67094\u500b\u53c3\u6578\uff1a<br \/>\u7b2c1\u500b\u53c3\u6578\u7684\u53ef\u80fd\u503c\u70ba1\u62162\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>1\uff1a\u4ee3\u8868\u7531<a href=\"https:\/\/zh.wikipedia.org\/wiki\/%E8%97%8D%E7%89%99%E6%8A%80%E8%A1%93%E8%81%AF%E7%9B%9F\" target=\"_blank\" rel=\"noreferrer noopener\">\u85cd\u7259\u6280\u8853\u806f\u76df\uff08Bluetooth Special Interest Group\uff0c\u7e2e\u5beb\u70baBluetooth SIG\uff09<\/a>\u6838\u767c\u7684\u516c\u53f8ID\u3002<\/li>\n\n\n\n<li>2\uff1a\u4ee3\u8868\u7531USB\u958b\u767c\u8005\u8ad6\u58c7\uff08USB-IF\uff09\u6838\u767c\u7684\u88fd\u9020\u5546ID\uff08VID\uff09\u3002<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">\u7b2c2\u500b\u53c3\u6578\u662fVID\uff08\u88fd\u9020\u5546ID\uff09\uff0c\u7531\u4e0a\u8ff0\u5169\u500b\u55ae\u4f4d\u6838\u767c\u3002<br \/>\u7b2c3\u500b\u53c3\u6578\u662fPID\uff08\u7522\u54c1ID\uff09\uff0c\u7531\u5ee0\u5546\u81ea\u884c\u6307\u5b9a\u3002<br \/>\u7b2c4\u500b\u53c3\u6578\u662f\u7248\u672c\u7de8\u865f\uff0c\u7531\u5ee0\u5546\u81ea\u884c\u6307\u5b9a\u3002<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\u672c\u6587\u7684\u85cd\u7259BLE\u904a\u6232\u624b\u628a\u7a0b\u5f0f\u5eab\u7684hidinfo()\u548cpnp()\u65b9\u6cd5\u6558\u8ff0\u6cbf\u7528\u201cESP32-BLE-Gamepad\u201d\u7a0b\u5f0f\u5eab\u7684\u8a2d\u5b9a\uff1b\u201cBleGamepadInstance\u201d\u662fBleGamepad\u985e\u5225\u7269\u4ef6\uff0chid\u5247\u662fBLEHIDDevice\u985e\u5225\u7269\u4ef6\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">BleGamepadInstance-&gt;hid-&gt;pnp(0x02,  0x7e05, 0x0920, 0x0110);\nBleGamepadInstance-&gt;hid-&gt;hidInfo(0x00,  0x01);\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>\u672c\u6587\u65e8\u5728\u88dc\u5145\u300a<a href=\"\/?p=1498\" target=\"_blank\" rel=\"noopener\">\u8d85\u5716\u89e3ESP32\u6df1\u5ea6\u5be6\u4f5c<\/a>\u300b\u7b2c16\u7ae0\u300cBLE\u85cd\u7259\u4eba\u6a5f\u8f38\u5165\u88dd\u7f6e\u61c9\u7528\u5be6\u4f5c\u300d\u55ae\u5143\uff0c\u8aaa\u660eHID\u88dd\u7f6e\u7684<strong>Vender ID\uff08\u5ee0\u5546\u8b58\u5225\u78bc\uff0c\u7e2e\u5bebVID\uff09<\/strong>\u4ee5\u53ca<strong>Product ID\uff08\u7522\u54c1\u8b58\u5225\u78bc\uff0c\u7e2e\u5bebPID\uff09<\/strong>\uff0c\u4ee5\u53caESP32\u7684BLEHIDDevice\u985e\u5225\u7684\u4e00\u4e9b\u65b9\u6cd5\uff0c\u4e26\u4e14\u7de8\u5beb\u4e00\u500b\u85cd\u7259BLE\u904a\u6232\u63a7\u5236\u5668\u7a0b\u5f0f\u5eab\u3002<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"\/images\/hardware\/arduino\/wii_classic_controller\/ESP32_breadboard.png\" width=\"688\" height=\"276\" alt=\"ESP32 BLE\u904a\u6232\u624b\u628a\u793a\u7bc4\u63a5\u7dda\"\/><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"nf_dc_page":"","footnotes":""},"categories":[3,15],"tags":[32,55,38],"class_list":["post-1551","post","type-post","status-publish","format-standard","hentry","category-3","category-diy","tag-arduino","tag-esp32","tag--bluetooth"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>\u81ea\u88fdSwitch Pro\u76f8\u5bb9\u904a\u6232\u63a7\u5236\u5668\uff08\u56db\uff09\uff1aESP32 BLE\u85cd\u7259\u4f4e\u529f\u8017\u904a\u6232\u624b\u628a - \u8d85\u5716\u89e3\u7cfb\u5217\u5716\u66f8<\/title>\n<meta name=\"description\" content=\"\u672c\u6587\u65e8\u5728\u88dc\u5145\u300a\u8d85\u5716\u89e3ESP32\u6df1\u5ea6\u5be6\u4f5c\u300b\u7b2c16\u7ae0\u300cBLE\u85cd\u7259\u4eba\u6a5f\u8f38\u5165\u88dd\u7f6e\u61c9\u7528\u5be6\u4f5c\u300d\u55ae\u5143\uff0c\u8aaa\u660eHID\u88dd\u7f6e\u7684Vender ID\uff08\u5ee0\u5546\u8b58\u5225\u78bc\uff09\u4ee5\u53caProduct ID\uff08\u7522\u54c1\u8b58\u5225\u78bc\uff09\uff0c\u4ee5\u53caESP32\u7684BLEHIDDevice\u985e\u5225\u7684\u4e00\u4e9b\u65b9\u6cd5\uff0c\u4e26\u4e14\u7de8\u5beb\u4e00\u500b\u85cd\u7259BLE\u904a\u6232\u63a7\u5236\u5668\u7a0b\u5f0f\u5eab\u3002\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/swf.com.tw\/?p=1551\" \/>\n<meta name=\"twitter:label1\" content=\"\u4f5c\u8005:\" \/>\n\t<meta name=\"twitter:data1\" content=\"cubie\" \/>\n\t<meta name=\"twitter:label2\" content=\"\u9810\u4f30\u95b1\u8b80\u6642\u9593\" \/>\n\t<meta name=\"twitter:data2\" content=\"7 \u5206\u9418\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/swf.com.tw\\\/?p=1551#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/swf.com.tw\\\/?p=1551\"},\"author\":{\"name\":\"cubie\",\"@id\":\"https:\\\/\\\/swf.com.tw\\\/#\\\/schema\\\/person\\\/24480fda9184aa137df8f05d79bc2f57\"},\"headline\":\"\u81ea\u88fdSwitch Pro\u76f8\u5bb9\u904a\u6232\u63a7\u5236\u5668\uff08\u56db\uff09\uff1aESP32 BLE\u85cd\u7259\u4f4e\u529f\u8017\u904a\u6232\u624b\u628a\",\"datePublished\":\"2021-05-28T13:31:35+00:00\",\"dateModified\":\"2022-11-20T23:14:29+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/swf.com.tw\\\/?p=1551\"},\"wordCount\":273,\"commentCount\":2,\"publisher\":{\"@id\":\"https:\\\/\\\/swf.com.tw\\\/#organization\"},\"keywords\":[\"arduino\",\"ESP32\",\"\u85cd\u7259 Bluetooth\"],\"articleSection\":[\"\u6559\u5b78\u6587\u4ef6\",\"\u786c\u9ad4\u8207DIY\"],\"inLanguage\":\"zh-TW\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/swf.com.tw\\\/?p=1551#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/swf.com.tw\\\/?p=1551\",\"url\":\"https:\\\/\\\/swf.com.tw\\\/?p=1551\",\"name\":\"\u81ea\u88fdSwitch Pro\u76f8\u5bb9\u904a\u6232\u63a7\u5236\u5668\uff08\u56db\uff09\uff1aESP32 BLE\u85cd\u7259\u4f4e\u529f\u8017\u904a\u6232\u624b\u628a - \u8d85\u5716\u89e3\u7cfb\u5217\u5716\u66f8\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/swf.com.tw\\\/#website\"},\"datePublished\":\"2021-05-28T13:31:35+00:00\",\"dateModified\":\"2022-11-20T23:14:29+00:00\",\"description\":\"\u672c\u6587\u65e8\u5728\u88dc\u5145\u300a\u8d85\u5716\u89e3ESP32\u6df1\u5ea6\u5be6\u4f5c\u300b\u7b2c16\u7ae0\u300cBLE\u85cd\u7259\u4eba\u6a5f\u8f38\u5165\u88dd\u7f6e\u61c9\u7528\u5be6\u4f5c\u300d\u55ae\u5143\uff0c\u8aaa\u660eHID\u88dd\u7f6e\u7684Vender ID\uff08\u5ee0\u5546\u8b58\u5225\u78bc\uff09\u4ee5\u53caProduct ID\uff08\u7522\u54c1\u8b58\u5225\u78bc\uff09\uff0c\u4ee5\u53caESP32\u7684BLEHIDDevice\u985e\u5225\u7684\u4e00\u4e9b\u65b9\u6cd5\uff0c\u4e26\u4e14\u7de8\u5beb\u4e00\u500b\u85cd\u7259BLE\u904a\u6232\u63a7\u5236\u5668\u7a0b\u5f0f\u5eab\u3002\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/swf.com.tw\\\/?p=1551#breadcrumb\"},\"inLanguage\":\"zh-TW\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/swf.com.tw\\\/?p=1551\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/swf.com.tw\\\/?p=1551#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/swf.com.tw\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"\u81ea\u88fdSwitch Pro\u76f8\u5bb9\u904a\u6232\u63a7\u5236\u5668\uff08\u56db\uff09\uff1aESP32 BLE\u85cd\u7259\u4f4e\u529f\u8017\u904a\u6232\u624b\u628a\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/swf.com.tw\\\/#website\",\"url\":\"https:\\\/\\\/swf.com.tw\\\/\",\"name\":\"\u8d85\u5716\u89e3\u7cfb\u5217\u5716\u66f8\",\"description\":\"Arduino+Python+JavaScript+\u7a0b\u5f0f\u8a2d\u8a08+\u786c\u9ad4DIY\",\"publisher\":{\"@id\":\"https:\\\/\\\/swf.com.tw\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/swf.com.tw\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"zh-TW\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/swf.com.tw\\\/#organization\",\"name\":\"\u8d85\u5716\u89e3\u7cfb\u5217\u5716\u66f8\",\"url\":\"https:\\\/\\\/swf.com.tw\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"zh-TW\",\"@id\":\"https:\\\/\\\/swf.com.tw\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/swf.com.tw\\\/wp-content\\\/uploads\\\/2019\\\/10\\\/logo_bat.png\",\"contentUrl\":\"https:\\\/\\\/swf.com.tw\\\/wp-content\\\/uploads\\\/2019\\\/10\\\/logo_bat.png\",\"width\":71,\"height\":65,\"caption\":\"\u8d85\u5716\u89e3\u7cfb\u5217\u5716\u66f8\"},\"image\":{\"@id\":\"https:\\\/\\\/swf.com.tw\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/swf.com.tw\\\/#\\\/schema\\\/person\\\/24480fda9184aa137df8f05d79bc2f57\",\"name\":\"cubie\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"zh-TW\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/c77b6f4d3b4ccdcdc343aeee53301c212f54787c43bd2ebf6648bf74ff59b474?s=96&d=retro&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/c77b6f4d3b4ccdcdc343aeee53301c212f54787c43bd2ebf6648bf74ff59b474?s=96&d=retro&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/c77b6f4d3b4ccdcdc343aeee53301c212f54787c43bd2ebf6648bf74ff59b474?s=96&d=retro&r=g\",\"caption\":\"cubie\"},\"sameAs\":[\"https:\\\/\\\/swf.com.tw\"],\"url\":\"https:\\\/\\\/swf.com.tw\\\/?author=1\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"\u81ea\u88fdSwitch Pro\u76f8\u5bb9\u904a\u6232\u63a7\u5236\u5668\uff08\u56db\uff09\uff1aESP32 BLE\u85cd\u7259\u4f4e\u529f\u8017\u904a\u6232\u624b\u628a - \u8d85\u5716\u89e3\u7cfb\u5217\u5716\u66f8","description":"\u672c\u6587\u65e8\u5728\u88dc\u5145\u300a\u8d85\u5716\u89e3ESP32\u6df1\u5ea6\u5be6\u4f5c\u300b\u7b2c16\u7ae0\u300cBLE\u85cd\u7259\u4eba\u6a5f\u8f38\u5165\u88dd\u7f6e\u61c9\u7528\u5be6\u4f5c\u300d\u55ae\u5143\uff0c\u8aaa\u660eHID\u88dd\u7f6e\u7684Vender ID\uff08\u5ee0\u5546\u8b58\u5225\u78bc\uff09\u4ee5\u53caProduct ID\uff08\u7522\u54c1\u8b58\u5225\u78bc\uff09\uff0c\u4ee5\u53caESP32\u7684BLEHIDDevice\u985e\u5225\u7684\u4e00\u4e9b\u65b9\u6cd5\uff0c\u4e26\u4e14\u7de8\u5beb\u4e00\u500b\u85cd\u7259BLE\u904a\u6232\u63a7\u5236\u5668\u7a0b\u5f0f\u5eab\u3002","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/swf.com.tw\/?p=1551","twitter_misc":{"\u4f5c\u8005:":"cubie","\u9810\u4f30\u95b1\u8b80\u6642\u9593":"7 \u5206\u9418"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/swf.com.tw\/?p=1551#article","isPartOf":{"@id":"https:\/\/swf.com.tw\/?p=1551"},"author":{"name":"cubie","@id":"https:\/\/swf.com.tw\/#\/schema\/person\/24480fda9184aa137df8f05d79bc2f57"},"headline":"\u81ea\u88fdSwitch Pro\u76f8\u5bb9\u904a\u6232\u63a7\u5236\u5668\uff08\u56db\uff09\uff1aESP32 BLE\u85cd\u7259\u4f4e\u529f\u8017\u904a\u6232\u624b\u628a","datePublished":"2021-05-28T13:31:35+00:00","dateModified":"2022-11-20T23:14:29+00:00","mainEntityOfPage":{"@id":"https:\/\/swf.com.tw\/?p=1551"},"wordCount":273,"commentCount":2,"publisher":{"@id":"https:\/\/swf.com.tw\/#organization"},"keywords":["arduino","ESP32","\u85cd\u7259 Bluetooth"],"articleSection":["\u6559\u5b78\u6587\u4ef6","\u786c\u9ad4\u8207DIY"],"inLanguage":"zh-TW","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/swf.com.tw\/?p=1551#respond"]}]},{"@type":"WebPage","@id":"https:\/\/swf.com.tw\/?p=1551","url":"https:\/\/swf.com.tw\/?p=1551","name":"\u81ea\u88fdSwitch Pro\u76f8\u5bb9\u904a\u6232\u63a7\u5236\u5668\uff08\u56db\uff09\uff1aESP32 BLE\u85cd\u7259\u4f4e\u529f\u8017\u904a\u6232\u624b\u628a - \u8d85\u5716\u89e3\u7cfb\u5217\u5716\u66f8","isPartOf":{"@id":"https:\/\/swf.com.tw\/#website"},"datePublished":"2021-05-28T13:31:35+00:00","dateModified":"2022-11-20T23:14:29+00:00","description":"\u672c\u6587\u65e8\u5728\u88dc\u5145\u300a\u8d85\u5716\u89e3ESP32\u6df1\u5ea6\u5be6\u4f5c\u300b\u7b2c16\u7ae0\u300cBLE\u85cd\u7259\u4eba\u6a5f\u8f38\u5165\u88dd\u7f6e\u61c9\u7528\u5be6\u4f5c\u300d\u55ae\u5143\uff0c\u8aaa\u660eHID\u88dd\u7f6e\u7684Vender ID\uff08\u5ee0\u5546\u8b58\u5225\u78bc\uff09\u4ee5\u53caProduct ID\uff08\u7522\u54c1\u8b58\u5225\u78bc\uff09\uff0c\u4ee5\u53caESP32\u7684BLEHIDDevice\u985e\u5225\u7684\u4e00\u4e9b\u65b9\u6cd5\uff0c\u4e26\u4e14\u7de8\u5beb\u4e00\u500b\u85cd\u7259BLE\u904a\u6232\u63a7\u5236\u5668\u7a0b\u5f0f\u5eab\u3002","breadcrumb":{"@id":"https:\/\/swf.com.tw\/?p=1551#breadcrumb"},"inLanguage":"zh-TW","potentialAction":[{"@type":"ReadAction","target":["https:\/\/swf.com.tw\/?p=1551"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/swf.com.tw\/?p=1551#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/swf.com.tw\/"},{"@type":"ListItem","position":2,"name":"\u81ea\u88fdSwitch Pro\u76f8\u5bb9\u904a\u6232\u63a7\u5236\u5668\uff08\u56db\uff09\uff1aESP32 BLE\u85cd\u7259\u4f4e\u529f\u8017\u904a\u6232\u624b\u628a"}]},{"@type":"WebSite","@id":"https:\/\/swf.com.tw\/#website","url":"https:\/\/swf.com.tw\/","name":"\u8d85\u5716\u89e3\u7cfb\u5217\u5716\u66f8","description":"Arduino+Python+JavaScript+\u7a0b\u5f0f\u8a2d\u8a08+\u786c\u9ad4DIY","publisher":{"@id":"https:\/\/swf.com.tw\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/swf.com.tw\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"zh-TW"},{"@type":"Organization","@id":"https:\/\/swf.com.tw\/#organization","name":"\u8d85\u5716\u89e3\u7cfb\u5217\u5716\u66f8","url":"https:\/\/swf.com.tw\/","logo":{"@type":"ImageObject","inLanguage":"zh-TW","@id":"https:\/\/swf.com.tw\/#\/schema\/logo\/image\/","url":"https:\/\/swf.com.tw\/wp-content\/uploads\/2019\/10\/logo_bat.png","contentUrl":"https:\/\/swf.com.tw\/wp-content\/uploads\/2019\/10\/logo_bat.png","width":71,"height":65,"caption":"\u8d85\u5716\u89e3\u7cfb\u5217\u5716\u66f8"},"image":{"@id":"https:\/\/swf.com.tw\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/swf.com.tw\/#\/schema\/person\/24480fda9184aa137df8f05d79bc2f57","name":"cubie","image":{"@type":"ImageObject","inLanguage":"zh-TW","@id":"https:\/\/secure.gravatar.com\/avatar\/c77b6f4d3b4ccdcdc343aeee53301c212f54787c43bd2ebf6648bf74ff59b474?s=96&d=retro&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/c77b6f4d3b4ccdcdc343aeee53301c212f54787c43bd2ebf6648bf74ff59b474?s=96&d=retro&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/c77b6f4d3b4ccdcdc343aeee53301c212f54787c43bd2ebf6648bf74ff59b474?s=96&d=retro&r=g","caption":"cubie"},"sameAs":["https:\/\/swf.com.tw"],"url":"https:\/\/swf.com.tw\/?author=1"}]}},"_links":{"self":[{"href":"https:\/\/swf.com.tw\/index.php?rest_route=\/wp\/v2\/posts\/1551","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/swf.com.tw\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/swf.com.tw\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/swf.com.tw\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/swf.com.tw\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1551"}],"version-history":[{"count":0,"href":"https:\/\/swf.com.tw\/index.php?rest_route=\/wp\/v2\/posts\/1551\/revisions"}],"wp:attachment":[{"href":"https:\/\/swf.com.tw\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1551"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/swf.com.tw\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1551"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/swf.com.tw\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1551"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}