1
0
mirror of https://github.com/undera/pylgbst.git synced 2020-11-18 19:37:26 -08:00
2017-09-12 22:25:16 +03:00

140 lines
3.6 KiB
Python

import json
import logging
import socket
import traceback
from abc import abstractmethod
from gattlib import DiscoveryService, GATTRequester
from pylegoboost.constants import DEVICE_NAME
log = logging.getLogger('transport')
LEGO_MOVE_HUB = "LEGO Move Hub"
def strtohex(sval):
return " ".join("{:02x}".format(ord(c)) for c in sval)
# noinspection PyMethodOverriding
class Requester(GATTRequester):
def on_notification(self, handle, data):
log.debug("Notification on handle %s: %s", handle, strtohex(data))
def on_indication(self, handle, data):
log.debug("Indication on handle %s: %s", handle, strtohex(data))
class Transport(object):
@abstractmethod
def read(self, handle):
pass
@abstractmethod
def write(self, handle, data):
pass
class BLETransport(Transport):
"""
:type requester: Requester
"""
def __init__(self):
super(Transport, self).__init__()
self.requester = None
def connect(self, bt_iface_name='hci0'):
service = DiscoveryService(bt_iface_name)
while not self.requester:
log.info("Discovering devices using %s...", bt_iface_name)
devices = service.discover(5)
log.debug("Devices: %s", devices)
for address, name in devices.items():
if name == LEGO_MOVE_HUB:
logging.info("Found %s at %s", name, address)
self._get_requester(address, bt_iface_name)
break
log.info("Device declares itself as: %s", self.read(DEVICE_NAME))
return self
def _get_requester(self, address, bt_iface_name):
self.requester = Requester(address, True, bt_iface_name)
def read(self, handle):
log.debug("Reading from: %s", handle)
data = self.requester.read_by_handle(handle)
log.debug("Result: %s", data)
if isinstance(data, list):
data = data[0]
return data
def write(self, handle, data):
log.debug("Writing to %s: %s", handle, data)
return self.requester.write_by_handle(handle, data)
class DebugServer(object):
def __init__(self, ble_trans):
self.sock = socket.socket()
self.ble = ble_trans
def start(self, port=9090):
self.sock.bind(('', port))
self.sock.listen(1)
while True:
conn, addr = self.sock.accept()
try:
self._handle_conn(conn)
finally:
conn.close()
def __del__(self):
self.sock.close()
def _handle_conn(self, conn):
"""
:type conn: socket._socketobject
"""
buf = ""
while True:
data = conn.recv(1024)
log.debug("Recv: %s", data)
if not data:
break
buf += data
if "\n" in buf:
line = buf[:buf.index("\n")]
buf = buf[buf.index("\n") + 1:]
if line:
log.debug("Cmd line: %s", line)
try:
self._handle_cmd(json.loads(line))
except BaseException:
log.error("Failed to handle cmd: %s", traceback.format_exc())
# conn.send(data.upper())
def _handle_cmd(self, line):
pass
class DebugServerTransport(Transport):
def __init__(self):
self.sock = socket.socket()
self.sock.connect(('localhost', 9090))
# sock.send('hello, world!')
# data = sock.recv(1024)
def __del__(self):
self.sock.close()