Слияние кода завершено, страница обновится автоматически
import ubluetooth as bt
import struct
from utime import sleep_ms
import gc
from ble.const import BLEConst
from ble.tools import BLETools
PACK = struct.pack
class GenericAccess(object):
UUID = bt.UUID(0x1800)
__DEVICE_NAME_CHAR = (bt.UUID(0x2A00), bt.FLAG_READ,)
__APPEARANCE_CHAR = (bt.UUID(0x2A01), bt.FLAG_READ,)
__PERIPHERAL_PREFERRED_CONNECTION_PARAMETERS = (bt.UUID(0x2A04), bt.FLAG_READ,)
__CENTRAL_ADDRESS_RESOLUTION = (bt.UUID(0x2AA6), bt.FLAG_READ,)
SERVICE = (
UUID,
(
__DEVICE_NAME_CHAR,
__APPEARANCE_CHAR,
__PERIPHERAL_PREFERRED_CONNECTION_PARAMETERS,
__CENTRAL_ADDRESS_RESOLUTION
)
)
class Values(object):
DEVICE_NAME = PACK("<14s", "Walkline KPB20".encode())
APPEARANCE = PACK("<h", 961)
PERIPHERAL_PREFERRED_CONNECTION_PARAMETERS = PACK("<4h", 40, 80, 10, 300) # (6, 6, 60, 300) <- ble mouse # (min, max, latency, timeout), for min & max, 1 = 1.25ms
CENTRAL_ADDRESS_RESOLUTION = PACK("<b", 1)
class GenericAttribute(object):
UUID = bt.UUID(0x1801)
# __CLIENT_CHARACTERISTIC_CONFIGURATION_DESC = (bt.UUID(0x2902), bt.FLAG_READ | bt.FLAG_WRITE)
# __GENERIC_ATTRIBUTE_DESCS = (__CLIENT_CHARACTERISTIC_CONFIGURATION_DESC,)
__SERVICE_CHANGED_CHAR = (bt.UUID(0x2A05), bt.FLAG_NOTIFY,) # __GENERIC_ATTRIBUTE_DESCS)
SERVICE = (
UUID,
(
__SERVICE_CHANGED_CHAR,
),
)
class Values(object):
pass
class BatteryService(object):
UUID = bt.UUID(0x180F)
# __CLIENT_CHARACTERISTIC_CONFIGURATION_DESC = (bt.UUID(0x2902), bt.FLAG_READ | bt.FLAG_WRITE)
# __CHARACTERISTIC_PRESENTATION_FORMAT_DESC = (bt.UUID(0x2904), bt.FLAG_READ)
# __BATTERY_LEVEL_DESCS = (__CLIENT_CHARACTERISTIC_CONFIGURATION_DESC,)
__BATTERY_LEVEL_CHAR = (bt.UUID(0x2A19), bt.FLAG_READ | bt.FLAG_NOTIFY,) # __BATTERY_LEVEL_DESCS)
SERVICE = (
UUID,
(
__BATTERY_LEVEL_CHAR,
),
)
class Values(object):
BATTERY_LEVEL_INT = PACK("<B", int(100))
class DeviceInformation(object):
UUID = bt.UUID(0x180A)
__MODEL_NUMBER_STRING_CHAR = (bt.UUID(0x2A24), bt.FLAG_READ,)
__SERIAL_NUMBER_STRING_CHAR = (bt.UUID(0x2A25), bt.FLAG_READ,)
__FIRMWARE_REVISION_STRING_CHAR = (bt.UUID(0x2A26), bt.FLAG_READ,)
__HARDWARE_REVISION_STRING_CHAR = (bt.UUID(0x2A27), bt.FLAG_READ,)
__SOFTWARE_REVISION_STRING_CHAR = (bt.UUID(0x2A28), bt.FLAG_READ,)
__MANUFACTURER_NAME_STRING_CHAR = (bt.UUID(0x2A29), bt.FLAG_READ,)
__PNP_ID_CHAR = (bt.UUID(0x2A50), bt.FLAG_READ,)
SERVICE = (
UUID,
(
__MODEL_NUMBER_STRING_CHAR,
__SERIAL_NUMBER_STRING_CHAR,
__FIRMWARE_REVISION_STRING_CHAR,
__HARDWARE_REVISION_STRING_CHAR,
__SOFTWARE_REVISION_STRING_CHAR,
__MANUFACTURER_NAME_STRING_CHAR,
__PNP_ID_CHAR,
),
)
class Values(object):
MANUFACTURER_NAME_STRING = PACK("<17s", "Walkline Hardware".encode())
MODEL_NUMBER_STRING = PACK("<11s", "WKHW BK-C87".encode())
SERIAL_NUMBER_STRING = PACK("<36s", "4e897424-061d-4dd9-a798-454f79b37245".encode())
FIRMWARE_REVISION_STRING = PACK("<4s", "v0.1".encode())
HARDWARE_REVISION_STRING = PACK("<4s", "v0.1".encode())
SOFTWARE_REVISION_STRING = PACK("<4s", "v0.1".encode())
# key="1" value="Bluetooth SIG assigned Company Identifier value from the Assigned Numbers document"
# key="2" value="USB Implementer’s Forum assigned Vendor ID value"
# VendorID: https://www.bluetooth.com/specifications/assigned-numbers/company-identifiers/
PNP_ID = PACK("<BHHH", 1, 0x0006, 0x01, 0x01) # 0x02E5: Espressif, 0x0006: Microsoft
class HumanInterfaceDevice(object):
UUID = bt.UUID(0x1812)
# __CLIENT_CHARACTERISTIC_CONFIGURATION_DESC = (bt.UUID(0x2902), bt.FLAG_READ | bt.FLAG_WRITE)
__REPORT_REFERENCE_DESC = (bt.UUID(0x2908), bt.FLAG_READ)
__REPORT_DESCRIPTOR = (__REPORT_REFERENCE_DESC,) # __CLIENT_CHARACTERISTIC_CONFIGURATION_DESC,)
__PROTOCOL_MODE_CHAR = (bt.UUID(0x2A4E), bt.FLAG_READ | bt.FLAG_WRITE,)
__REPORT_CHAR = (bt.UUID(0x2A4D), bt.FLAG_READ | bt.FLAG_WRITE | bt.FLAG_NOTIFY, __REPORT_DESCRIPTOR)
__REPORT_MAP_CHAR = (bt.UUID(0x2A4B), bt.FLAG_READ,)
__BOOT_KEYBOARD_INPUT_REPORT_CHAR = (bt.UUID(0x2A22), bt.FLAG_READ | bt.FLAG_WRITE | bt.FLAG_NOTIFY,)
__BOOT_KEYBOARD_OUTPUT_REPORT_CHAR = (bt.UUID(0x2A32), bt.FLAG_READ | bt.FLAG_WRITE,)
__HID_INFORMATION_CHAR = (bt.UUID(0x2A4A), bt.FLAG_READ,)
__HID_CONTROL_POINT_CHAR = (bt.UUID(0x2A4C), bt.FLAG_WRITE,)
SERVICE = (
UUID,
(
__PROTOCOL_MODE_CHAR,
__REPORT_CHAR,
__REPORT_MAP_CHAR,
__BOOT_KEYBOARD_INPUT_REPORT_CHAR,
__BOOT_KEYBOARD_OUTPUT_REPORT_CHAR,
__HID_INFORMATION_CHAR,
__HID_CONTROL_POINT_CHAR,
),
)
class Values(object):
# key="0" value="Boot Protocol Mode"
# key="1" value="Report Protocol Mode"
PROTOCOL_MODE = PACK("<B", int(1))
HID_INFORMATION = PACK("<Hbb", 0x0100, 0x00, 0b0011)
# param 1: Report ID
# param 2: Report Type
# value="Input Report" key="1"
# value="Output report" key="2"
# value="Feature Report" key="3"
REPORT_REFERANCE = PACK("<BB", int(1), int(1))
# http://www.freebsddiary.org/APC/usb_hid_usages
REPORT_MAP_DATA = [
0x05, 0x01, # USAGE_PAGE (Generic Desktop)
0x09, 0x06, # USAGE (Keyboard)
0xA1, 0x01, # COLLECTION (Application)
# 8 keycode
0x05, 0x07, # USAGE_PAGE (Keyboard)
0x19, 0xE0, # USAGE_MINIMUM (Keyboard LeftControl)
0x29, 0xE7, # USAGE_MAXIMUM (Keyboard Right GUI)
# keycode value 0 and 1
0x15, 0x00, # LOGICAL_MINIMUM (0)
0x25, 0x01, # LOGICAL_MAXIMUM (1)
# Modifier byte
0x75, 0x01, # REPORT_SIZE (1)
0x95, 0x08, # REPORT_COUNT (8)
0x81, 0x02, # INPUT (Data,Var,Abs)
# Reserved byte
0x95, 0x01, # REPORT_COUNT (1)
0x75, 0x08, # REPORT_SIZE (8)
0x81, 0x01, # INPUT (Cnst,Var,Abs)
# # LED report
0x95, 0x05, # REPORT_COUNT (5)
0x75, 0x01, # REPORT_SIZE (1)
0x05, 0x08, # USAGE_PAGE (LEDs)
0x19, 0x01, # USAGE_MINIMUM (Num Lock)
0x29, 0x05, # USAGE_MAXIMUM (Kana)
0x91, 0x02, # OUTPUT (Data,Var,Abs)
# # LED report padding
0x95, 0x01, # REPORT_COUNT (1)
0x75, 0x03, # REPORT_SIZE (3)
0x91, 0x03, # OUTPUT (Cnst,Var,Abs)
# Key arrays (6 bytes)
0x95, 0x06, # REPORT_COUNT (6)
0x75, 0x08, # REPORT_SIZE (8)
0x15, 0x00, # LOGICAL_MINIMUM (0)
0x25, 0x65, # LOGICAL_MAXIMUM (101)
0x05, 0x07, # USAGE_PAGE (Keyboard)
0x19, 0x00, # USAGE_MINIMUM (Reserved (no event indicated))
0x29, 0x65, # USAGE_MAXIMUM (Keyboard Application)
0x81, 0x00, # INPUT (Data,Ary,Abs)
0xC0, # END_COLLECTION
]
class BLE_HID(object):
def __init__(self, ble, name='wk_kb'):
self.__ble = ble
self.__conn_handle = None
self.__last_addr = None
self.__write = self.__ble.gatts_write
self.__read = self.__ble.gatts_read
self.__notify = self.__ble.gatts_notify
self.__services = (GenericAccess.SERVICE, GenericAttribute.SERVICE, BatteryService.SERVICE, DeviceInformation.SERVICE, HumanInterfaceDevice.SERVICE)
self.__ble.active(False)
print("activating ble...")
self.__ble.active(True)
print("ble activated")
self.__ble.config(rxbuf=256)
self.__ble.config(gap_name="Walkline KPB20")
# self.__ble.config(mac="246f289da322") #bytes([0x24, 0x6f, 0x28, 0x9d, 0xa3, 0x22]))
# print("mac: [{}]".format(BLETools.decode_mac(self.__ble.config("mac"))))
print("rxbuf: [{}]".format(self.__ble.config("rxbuf")))
self.__ble.irq(self.__irq)
self.__register_services()
self.__adv_payload = BLETools.advertising_hid_payload(
services=[BatteryService.UUID, DeviceInformation.UUID, HumanInterfaceDevice.UUID],
appearance=961 # https://www.bluetooth.com/wp-content/uploads/Sitecore-Media-Library/Gatt/Xml/Characteristics/org.bluetooth.characteristic.gap.appearance.xml
)
self.__resp_payload = BLETools.advertising_resp_payload(
name="Walkline KPB20",
services=[GenericAccess.UUID, GenericAttribute.UUID]
)
self.__advertise()
def __advertise(self, interval_us=100000):
self.__ble.gap_advertise(None)
print("advertising...")
self.__ble.gap_advertise(interval_us, adv_data=self.__adv_payload, resp_data=self.__resp_payload)
def __register_services(self):
(
(
self.__device_name_handle,
self.__appearance_handle,
self.__peripheral_preferred_connection_parameters_handle,
self.__central_address_resolution_handle,
),
(
self.__service_changed_handle,
# self.__service_changed_ccc_descriptor_handle,
),
(
self.__battery_level_handle,
# self.__battery_level_ccc_descriptor_handle,
),
(
self.__model_handle,
self.__serial_handle,
self.__firmware_handle,
self.__hardware_handle,
self.__software_handle,
self.__manufacturer_handle,
self.__pnp_id_handle,
),
(
self.__protocol_mode_handle,
self.__report_handle,
self.__report_report_reference_descriptor_handle,
self.__report_map_handle,
self.__boot_kb_input_report_handle,
self.__boot_kb_output_report_handle,
self.__hid_information_handle,
self.__hid_control_point_handle,
# self.__boot_kb_input_report_descriptor_handle,
),
) = self.__ble.gatts_register_services(self.__services)
print("services registed")
self.__setup_generic_access()
# self.__setup_generic_attribute()
# self.set_battery_level()
self.__setup_device_info()
self.__setup_hid()
print("characteristic values setup")
# gc.collect()
def __irq(self, event, data):
if event == BLEConst.IRQ.IRQ_CENTRAL_CONNECT:
self.__conn_handle, _, addr = data
print("[{}] connected, handle: {}".format(BLETools.decode_mac(addr), self.__conn_handle))
self.__ble.gap_advertise(None)
sleep_ms(300)
print("start bonding...")
# try:
self.__ble.gap_pair(self.__conn_handle, bond=True, mitm=True, lesc=True)
# except OSError as ose:
# if str(ose) == "[Errno 2] ENOENT":
# self.__ble.gap_pair(self.__conn_handle)
# self.__notify(self.__conn_handle, self.__battery_level_handle)
# gc.collect()
elif event == BLEConst.IRQ.IRQ_CENTRAL_DISCONNECT:
self.__conn_handle, _, addr = data
print("[{}] disconnected, handle: {}".format(BLETools.decode_mac(addr), self.__conn_handle))
self.__conn_handle = None
self.__advertise()
elif event == BLEConst.IRQ.IRQ_MTU_EXCHANGED:
print("MTU Exchange value: {}".format(data[1]))
self.__ble.config(mtu=data[1])
else:
print("event: {}, data: {}".format(event, data))
gc.collect()
def __setup_generic_access(self):
self.__write(self.__device_name_handle, GenericAccess.Values.DEVICE_NAME)
self.__write(self.__appearance_handle, GenericAccess.Values.APPEARANCE)
self.__write(self.__peripheral_preferred_connection_parameters_handle, GenericAccess.Values.PERIPHERAL_PREFERRED_CONNECTION_PARAMETERS)
self.__write(self.__central_address_resolution_handle, GenericAccess.Values.CENTRAL_ADDRESS_RESOLUTION)
def __setup_device_info(self):
"""
used for Device Information
"""
self.__write(self.__manufacturer_handle, DeviceInformation.Values.MANUFACTURER_NAME_STRING)
self.__write(self.__model_handle, DeviceInformation.Values.MODEL_NUMBER_STRING)
self.__write(self.__serial_handle, DeviceInformation.Values.SERIAL_NUMBER_STRING)
self.__write(self.__firmware_handle, DeviceInformation.Values.FIRMWARE_REVISION_STRING)
self.__write(self.__hardware_handle, DeviceInformation.Values.HARDWARE_REVISION_STRING)
self.__write(self.__software_handle, DeviceInformation.Values.SOFTWARE_REVISION_STRING)
self.__write(self.__pnp_id_handle, DeviceInformation.Values.PNP_ID)
def __setup_hid(self):
self.__write(self.__protocol_mode_handle, HumanInterfaceDevice.Values.PROTOCOL_MODE)
self.__write(self.__report_report_reference_descriptor_handle, HumanInterfaceDevice.Values.REPORT_REFERANCE)
self.__write(self.__hid_information_handle, HumanInterfaceDevice.Values.HID_INFORMATION)
self.__write(self.__report_map_handle, bytes(HumanInterfaceDevice.Values.REPORT_MAP_DATA))
def set_battery_level(self):
self.__write(self.__battery_level_handle, BatteryService.Values.BATTERY_LEVEL_INT)
self.__notify(self.__conn_handle, self.__battery_level_handle)
# self.__write(self.__battery_level_ccc_descriptor_handle, __PACK("<H", 0x0100))
def send_key(self, keycode):
self.__write(self.__report_handle, bytes([0x0, 0x0, keycode, 0x0, 0x0, 0x0, 0x0, 0x0]))
self.__notify(self.__conn_handle, self.__report_handle)
self.__write(self.__report_handle, bytes([0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]))
self.__notify(self.__conn_handle, self.__report_handle)
def send_key_down(self, keycode):
self.__write(self.__report_handle, bytes([0x0, 0x0, keycode, 0x0, 0x0, 0x0, 0x0, 0x0]))
self.__notify(self.__conn_handle, self.__report_handle)
def send_key_up(self):
self.__write(self.__report_handle, bytes([0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]))
self.__notify(self.__conn_handle, self.__report_handle)
hid = None
keypad = None
# keycode = 0
def init_button():
global hid
from machine import Pin
import random
def button_click_cb(timer):
"""
a:4 b:5 c:6 d:7 e:8f:9 g:10 h:11 i:12 j:13 k:14 l:15 m:16 n:17 o:18 p:19 q:20 r:21 s:22 t:23 u:24 v:25 w:26 x:27 y:28 z:29
"""
keycode = random.randint(4, 29)
# keycode = random.randint(7, 54)
print("send key: {}".format(keycode))
# hid.send_key(keycode)
hid.send_key_down(keycode)
hid.send_key_up()
button = Pin(0, Pin.IN, Pin.PULL_UP)
button.irq(button_click_cb, Pin.IRQ_RISING)
print("button initialized")
def main():
global hid
ble = bt.BLE()
hid = BLE_HID(ble)
init_button()
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
print("\nPRESS CTRL+D TO RESET DEVICE")
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )