mirror of
https://github.com/thingsboard/thingsboard-gateway
synced 2025-10-26 22:31:42 +08:00
Added building map of device to BLEConnector and processing of the READ characteristics.
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
28
thingsboard_gateway/config/ble.json
Normal file
28
thingsboard_gateway/config/ble.json
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"name": "BLE Connector",
|
||||||
|
"rescanIntervalSeconds": 10,
|
||||||
|
"scanTimeSeconds": 5,
|
||||||
|
"passiveScanMode": true,
|
||||||
|
"devices": [
|
||||||
|
{
|
||||||
|
"name": "Temperature and humidity sensor",
|
||||||
|
"readStandardInformation": true,
|
||||||
|
"MACAddress": "4C:65:A8:DF:85:C0",
|
||||||
|
"checkIntervalSeconds": 10,
|
||||||
|
"telemetry": [
|
||||||
|
{
|
||||||
|
"key": "temperature",
|
||||||
|
"characteristicUUID": "00002A00-0000-1000-8000-00805F9B34FB",
|
||||||
|
"fromByte": 0,
|
||||||
|
"toByte": -1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"attributes": [
|
||||||
|
{
|
||||||
|
"key": "batteryLevel",
|
||||||
|
"handle": 9
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -11,42 +11,36 @@
|
|||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
import tb_ble_adapter
|
|
||||||
import logging
|
|
||||||
from bluepy.btle import DefaultDelegate, Peripheral, Scanner, BTLEDisconnectError
|
|
||||||
|
|
||||||
import random
|
from bluepy import __path__ as bluepy_path
|
||||||
|
from pprint import pformat
|
||||||
|
from bluepy.btle import DefaultDelegate, Peripheral, Scanner
|
||||||
|
from bluepy.btle import BTLEDisconnectError, BTLEManagementError, BTLEGattError
|
||||||
|
from random import choice
|
||||||
from string import ascii_lowercase
|
from string import ascii_lowercase
|
||||||
import time
|
import time
|
||||||
import codecs
|
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
from struct import unpack
|
from thingsboard_gateway.connectors.connector import Connector, log
|
||||||
from bluepy.btle import DefaultDelegate, Peripheral, Scanner
|
|
||||||
from thingsboard_gateway.connectors.connector import Connector
|
|
||||||
|
|
||||||
logging.basicConfig(level=logging.DEBUG,
|
|
||||||
format='%(asctime)s - %(levelname)s - %(module)s - %(lineno)d - %(message)s',
|
|
||||||
datefmt='%Y-%m-%d %H:%M:%S')
|
|
||||||
log = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class BLEConnector(Connector, Thread):
|
class BLEConnector(Connector, Thread):
|
||||||
def __init__(self, gateway, config):
|
def __init__(self, gateway, config):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
self.__default_service_end = '-0000-1000-8000-00805F9B34FB'
|
||||||
self.statistics = {'MessagesReceived': 0,
|
self.statistics = {'MessagesReceived': 0,
|
||||||
'MessagesSent': 0}
|
'MessagesSent': 0}
|
||||||
self.__gateway = gateway
|
self.__gateway = gateway
|
||||||
self.__config = config
|
self.__config = config
|
||||||
self.setName(self.__config.get("name",
|
self.setName(self.__config.get("name",
|
||||||
'BLE Connector ' + ''.join(random.choice(ascii_lowercase) for _ in range(5))))
|
'BLE Connector ' + ''.join(choice(ascii_lowercase) for _ in range(5))))
|
||||||
|
|
||||||
self._connected = False
|
self._connected = False
|
||||||
self.__stopped = False
|
self.__stopped = False
|
||||||
self.__previous_scan_time = 0
|
self.__previous_scan_time = 0
|
||||||
self.__rescan_time = self.__config['rescanIntervalSeconds'] if self.__config.get('rescanIntervalSeconds') is not None else 1
|
self.__rescan_time = self.__config['rescanIntervalSeconds'] if self.__config.get(
|
||||||
|
'rescanIntervalSeconds') is not None else 1
|
||||||
self.__scanner = Scanner().withDelegate(ScanDelegate(self))
|
self.__scanner = Scanner().withDelegate(ScanDelegate(self))
|
||||||
self.__devices_around = {}
|
self.__devices_around = {}
|
||||||
self.__devices_found = {}
|
|
||||||
self.__notify_delegators = {}
|
self.__notify_delegators = {}
|
||||||
self.__fill_interest_devices()
|
self.__fill_interest_devices()
|
||||||
self.daemon = True
|
self.daemon = True
|
||||||
@@ -55,14 +49,14 @@ class BLEConnector(Connector, Thread):
|
|||||||
while True:
|
while True:
|
||||||
if time.time() - self.__previous_scan_time >= self.__rescan_time != 0:
|
if time.time() - self.__previous_scan_time >= self.__rescan_time != 0:
|
||||||
self.__scan_ble()
|
self.__scan_ble()
|
||||||
for device_addr in self.__devices_found:
|
# for device_addr in self.__devices_found:
|
||||||
device = self.__devices_found[device_addr]
|
# device = self.__devices_found[device_addr]
|
||||||
log.debug('%s\t\t%s', device.addr, device.rssi)
|
# # log.debug('%s\t\t%s', device.addr, device.rssi)
|
||||||
scanned_data = device.getScanData()
|
# scanned_data = device.getScanData()
|
||||||
try:
|
# try:
|
||||||
log.debug(scanned_data[-1][-1])
|
# log.debug(scanned_data[-1][-1])
|
||||||
except Exception as e:
|
# except Exception as e:
|
||||||
log.exception(e)
|
# log.exception(e)
|
||||||
self.__get_services_and_chars()
|
self.__get_services_and_chars()
|
||||||
time.sleep(.1)
|
time.sleep(.1)
|
||||||
if self.__stopped:
|
if self.__stopped:
|
||||||
@@ -71,6 +65,12 @@ class BLEConnector(Connector, Thread):
|
|||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
self.__stopped = True
|
self.__stopped = True
|
||||||
|
for device in self.__devices_around:
|
||||||
|
try:
|
||||||
|
self.__devices_around[device]['peripheral'].disconnect()
|
||||||
|
except Exception as e:
|
||||||
|
log.exception(e)
|
||||||
|
raise e
|
||||||
|
|
||||||
def get_name(self):
|
def get_name(self):
|
||||||
return self.name
|
return self.name
|
||||||
@@ -81,6 +81,9 @@ class BLEConnector(Connector, Thread):
|
|||||||
def server_side_rpc_handler(self, content):
|
def server_side_rpc_handler(self, content):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def is_connected(self):
|
||||||
|
return self._connected
|
||||||
|
|
||||||
def open(self):
|
def open(self):
|
||||||
self.__stopped = False
|
self.__stopped = False
|
||||||
self.start()
|
self.start()
|
||||||
@@ -89,50 +92,74 @@ class BLEConnector(Connector, Thread):
|
|||||||
for interested_device in self.__devices_around:
|
for interested_device in self.__devices_around:
|
||||||
if device.addr.upper() == interested_device:
|
if device.addr.upper() == interested_device:
|
||||||
self.__devices_around[interested_device]['scanned_device'] = device
|
self.__devices_around[interested_device]['scanned_device'] = device
|
||||||
else:
|
|
||||||
if device.addr not in self.__devices_found:
|
|
||||||
self.__devices_found[device.addr] = device
|
|
||||||
log.debug('Device with address: %s - found.', device.addr.upper())
|
log.debug('Device with address: %s - found.', device.addr.upper())
|
||||||
|
else:
|
||||||
|
log.debug('Unknown device with address: %s - found.', device.addr.upper())
|
||||||
|
|
||||||
def __get_services_and_chars(self):
|
def __get_services_and_chars(self):
|
||||||
for device in self.__devices_around:
|
for device in self.__devices_around:
|
||||||
try:
|
try:
|
||||||
if self.__devices_around.get(device) is not None and self.__devices_around[device].get('scanned_device') is not None:
|
if self.__devices_around.get(device) is not None and self.__devices_around[device].get(
|
||||||
log.debug('Trying connect to device with address: %s',
|
'scanned_device') is not None:
|
||||||
|
log.debug('Connecting to device with address: %s',
|
||||||
self.__devices_around[device]['scanned_device'].addr.upper())
|
self.__devices_around[device]['scanned_device'].addr.upper())
|
||||||
|
new_device = False
|
||||||
if self.__devices_around[device].get('peripheral') is None:
|
if self.__devices_around[device].get('peripheral') is None:
|
||||||
peripheral = Peripheral(self.__devices_around[device]['scanned_device'])
|
peripheral = Peripheral(self.__devices_around[device]['scanned_device'])
|
||||||
self.__devices_around[device]['peripheral'] = peripheral
|
self.__devices_around[device]['peripheral'] = peripheral
|
||||||
|
new_device = True
|
||||||
else:
|
else:
|
||||||
peripheral = self.__devices_around[device]['peripheral']
|
peripheral = self.__devices_around[device]['peripheral']
|
||||||
peripheral.connect(self.__devices_around[device]['scanned_device'])
|
peripheral.connect(self.__devices_around[device]['scanned_device'])
|
||||||
services = peripheral.getServices()
|
services = peripheral.getServices()
|
||||||
for service in services:
|
for service in services:
|
||||||
if self.__devices_around[device].get('services') is None:
|
if self.__devices_around[device].get('services') is None:
|
||||||
|
log.debug('Building device %s map, it may take a time, please wait...', device)
|
||||||
self.__devices_around[device]['services'] = {}
|
self.__devices_around[device]['services'] = {}
|
||||||
service_uuid = str(service.uuid).upper()
|
service_uuid = str(service.uuid).upper()
|
||||||
if self.__devices_around[device]['services'].get(service_uuid) is None:
|
if self.__devices_around[device]['services'].get(service_uuid) is None:
|
||||||
|
self.__devices_around[device]['services'][service_uuid] = {}
|
||||||
for characteristic in service.getCharacteristics():
|
for characteristic in service.getCharacteristics():
|
||||||
log.debug('\n\nCharacteristic %s found in device %s,\n mode: %s,\n Characteristic name: %s,\n Characteristic UUID: %s,\n Characteristic handle: %s\n',
|
descriptors = []
|
||||||
characteristic,
|
try:
|
||||||
device,
|
self.__check_and_reconnect(device)
|
||||||
characteristic.propertiesToString(),
|
try:
|
||||||
characteristic.uuid.getCommonName(),
|
descriptors = characteristic.getDescriptors()
|
||||||
characteristic.uuid,
|
except BTLEDisconnectError:
|
||||||
characteristic.handle)
|
self.__check_and_reconnect(device)
|
||||||
log.debug('service uuid: %s', service_uuid)
|
descriptors = characteristic.getDescriptors()
|
||||||
service_available = self.__devices_around[device]['services'].get(service_uuid)
|
except BTLEGattError:
|
||||||
if service_available is None:
|
log.debug('Device %s - services, characteristics and descriptors found.', device)
|
||||||
self.__devices_around[device]['services'][service_uuid] = {"service_object": service,
|
except Exception as e:
|
||||||
"characteristic": [characteristic],
|
log.exception(e)
|
||||||
}
|
characteristic_uuid = str(characteristic.uuid).upper()
|
||||||
else:
|
self.__devices_around[device]['services'][service_uuid][characteristic_uuid] = {
|
||||||
service_available['characteristic'].append(characteristic)
|
'characteristic': characteristic,
|
||||||
self.__service_processing()
|
'descriptors': {}}
|
||||||
|
for descriptor in descriptors:
|
||||||
|
self.__devices_around[device]['services'][service_uuid][characteristic_uuid][
|
||||||
|
'descriptors'] = {str(descriptor.uuid).upper(): descriptor}
|
||||||
|
except BTLEDisconnectError:
|
||||||
|
self.__check_and_reconnect(device)
|
||||||
|
if new_device:
|
||||||
|
self.__new_device_processing(device)
|
||||||
|
self.__service_processing(device)
|
||||||
|
|
||||||
except BTLEDisconnectError:
|
except BTLEDisconnectError:
|
||||||
log.debug('Cannot connect to device.')
|
log.debug('Cannot connect to device.')
|
||||||
continue
|
continue
|
||||||
|
except Exception as e:
|
||||||
|
log.exception(e)
|
||||||
|
self.__previous_scan_time = time.time()
|
||||||
|
|
||||||
|
def __new_device_processing(self, device):
|
||||||
|
if self.__config.get('readStandardInformation', False):
|
||||||
|
log.debug(pformat(self.__devices_around[device]))
|
||||||
|
# TODO READ STANDARD INFORMATION
|
||||||
|
|
||||||
|
def __check_and_reconnect(self, device):
|
||||||
|
while self.__devices_around[device]['peripheral']._helper is None:
|
||||||
|
self.__devices_around[device]['peripheral'].connect(self.__devices_around[device]['scanned_device'])
|
||||||
|
|
||||||
def __notify_handler(self, device, notify_handle, delegate=None):
|
def __notify_handler(self, device, notify_handle, delegate=None):
|
||||||
class NotifyDelegate(DefaultDelegate):
|
class NotifyDelegate(DefaultDelegate):
|
||||||
@@ -144,11 +171,11 @@ class BLEConnector(Connector, Thread):
|
|||||||
|
|
||||||
def handleNotification(self, handle, data):
|
def handleNotification(self, handle, data):
|
||||||
self.incoming_data = data
|
self.incoming_data = data
|
||||||
|
self.data = data
|
||||||
|
log.debug('Notification received handle, data:')
|
||||||
log.debug(handle)
|
log.debug(handle)
|
||||||
fromByte = 0
|
log.debug(data)
|
||||||
toByte = -1
|
|
||||||
# self.data = {"temperature": data.decode('UTF-8')[2:6], "humidity": data.decode('UTF-8')[9:13]}
|
|
||||||
self.data = {"temperature": data.decode('UTF-8')}
|
|
||||||
if delegate is None:
|
if delegate is None:
|
||||||
delegate = NotifyDelegate()
|
delegate = NotifyDelegate()
|
||||||
device['peripheral'].withDelegate(delegate)
|
device['peripheral'].withDelegate(delegate)
|
||||||
@@ -157,60 +184,98 @@ class BLEConnector(Connector, Thread):
|
|||||||
log.debug("Data received: %s", delegate.data)
|
log.debug("Data received: %s", delegate.data)
|
||||||
return delegate
|
return delegate
|
||||||
|
|
||||||
def __service_processing(self):
|
def __service_processing(self, device):
|
||||||
for device in self.__devices_around:
|
for uuid in self.__devices_around[device]['interest_uuid']:
|
||||||
for service_uuid in self.__devices_around[device]['interest_services']:
|
for service in self.__devices_around[device]['services']:
|
||||||
if self.__devices_around[device]['peripheral']._helper is None:
|
if uuid in self.__devices_around[device]['services'][service]:
|
||||||
self.__devices_around[device]['peripheral'].connect(self.__devices_around[device]['scanned_device'])
|
characteristic = self.__devices_around[device]['services'][service][uuid]['characteristic']
|
||||||
service_processing_conf = self.__devices_around[device]['interest_services'][service_uuid]
|
|
||||||
log.debug('Service with UUID: %s processing for %s key %s',
|
|
||||||
service_uuid,
|
|
||||||
service_processing_conf['type'],
|
|
||||||
service_processing_conf['section_config']['key'])
|
|
||||||
for characteristic in self.__devices_around[device]['services'][service_uuid]['characteristic']:
|
|
||||||
if self.__devices_around[device]['peripheral']._helper is None:
|
|
||||||
self.__devices_around[device]['peripheral'].connect(self.__devices_around[device]['scanned_device'])
|
|
||||||
|
|
||||||
log.debug(characteristic)
|
log.debug('Characteristic with name: "%s" and uuid: %s - processing.', characteristic.uuid.getCommonName(), uuid)
|
||||||
log.debug(characteristic.propertiesToString())
|
self.__check_and_reconnect(device)
|
||||||
if 'READ' not in characteristic.propertiesToString() and 'NOTIFY' in characteristic.propertiesToString():
|
characteristic_processing_conf = self.__devices_around[device]['interest_uuid'][uuid]['section_config']
|
||||||
self.__notify_delegators[str(characteristic.uuid).upper()] = self.__notify_handler(
|
if 'READ' in characteristic.propertiesToString():
|
||||||
self.__devices_around[device],
|
self.__check_and_reconnect(device)
|
||||||
characteristic.handle+1,
|
|
||||||
self.__notify_delegators.get(str(characteristic.uuid).upper()))
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
data = characteristic.read()
|
data = characteristic.read()
|
||||||
log.debug(data)
|
log.debug(data)
|
||||||
# data = {"temperature": data.decode('UTF-8')[2:6], "humidity": data.decode('UTF-8')[9:13]}
|
# for desc in self.__devices_around[device]['peripheral'].getDescriptors():
|
||||||
data = data.decode('UTF-8')
|
# try:
|
||||||
log.debug('data: %s', data)
|
# if self.__devices_around[device]['peripheral']._helper is None:
|
||||||
except:
|
# self.__devices_around[device]['peripheral'].connect(self.__devices_around[device]['scanned_device'])
|
||||||
pass
|
# if desc.uuid.getCommonName() == 'Service Changed':
|
||||||
|
#
|
||||||
|
# log.debug(desc)
|
||||||
|
# # log.debug(desc.read())
|
||||||
|
# log.debug(desc.uuid)
|
||||||
|
# log.debug(desc.handle)
|
||||||
|
# self.__notify_delegators[str(desc.uuid).upper()] = self.__notify_handler(self.__devices_around[device],
|
||||||
|
# int.from_bytes(bytes.fromhex(str(desc.handle)), "big"),
|
||||||
|
# self.__notify_delegators.get(str(desc.uuid).upper()))
|
||||||
|
# except Exception as e:
|
||||||
|
# log.error(e)
|
||||||
|
# for characteristic in self.__devices_around[device]['services'][service_uuid]['characteristic']:
|
||||||
|
# self.__check_and_reconnect(device)
|
||||||
|
# log.debug(characteristic)
|
||||||
|
# log.debug(characteristic.propertiesToString())
|
||||||
|
# characteristic_properties = characteristic.propertiesToString()
|
||||||
|
# if 'NOTIFY' in characteristic.propertiesToString() or 'READ' in characteristic.propertiesToString():
|
||||||
|
# descriptors = characteristic.getDescriptors()
|
||||||
|
# for descriptor in descriptors:
|
||||||
|
# try:
|
||||||
|
# if 'READ' in characteristic_properties:
|
||||||
|
# log.debug(descriptor.handle)
|
||||||
|
# if descriptor.handle != 17 and descriptor.handle != 26 and descriptor.handle != 43 and descriptor.handle != 47:
|
||||||
|
# self.__check_and_reconnect(device)
|
||||||
|
# log.debug(descriptor.read())
|
||||||
|
# elif 'NOTIFY' in characteristic_properties:
|
||||||
|
# log.debug(characteristic.handle)
|
||||||
|
# if descriptor.handle != 17 and descriptor.handle != 26 and descriptor.handle != 43:
|
||||||
|
# if self.__devices_around[device]['peripheral']._helper is None:
|
||||||
|
# self.__devices_around[device]['peripheral'].connect(
|
||||||
|
# self.__devices_around[device]['scanned_device'])
|
||||||
|
# self.__notify_delegators[str(descriptor.uuid).upper()] = self.__notify_handler(
|
||||||
|
# self.__devices_around[device],
|
||||||
|
# descriptor.handle + 1,
|
||||||
|
# self.__notify_delegators.get(str(descriptor.uuid).upper()))
|
||||||
|
# self.__notify_delegators[descriptor.handler] = {'function': self.__notify_handler,
|
||||||
|
# 'args': (
|
||||||
|
# self.__devices_around[device],
|
||||||
|
# descriptor.handle + 1,
|
||||||
|
# self.__notify_delegators.get(
|
||||||
|
# str(descriptor.uuid).upper()))
|
||||||
|
# }
|
||||||
|
# except Exception as e:
|
||||||
|
# log.exception(e)
|
||||||
|
|
||||||
def __scan_ble(self):
|
def __scan_ble(self):
|
||||||
log.debug("Scanning for devices...")
|
log.debug("Scanning for devices...")
|
||||||
try:
|
try:
|
||||||
devices = self.__scanner.scan(15)
|
self.__scanner.scan(self.__config.get('scanTimeSeconds', 5), passive=self.__config.get('passiveScanMode', False))
|
||||||
log.debug(devices)
|
except BTLEManagementError as e:
|
||||||
except BTLEDisconnectError:
|
log.error('BLE working only with root user.')
|
||||||
pass
|
log.error('Or you can try this command:\nsudo setcap '
|
||||||
|
'\'cap_net_raw,cap_net_admin+eip\' %s'
|
||||||
|
'\n====== Attention! ====== '
|
||||||
|
'\nCommand above - provided access to ble devices to any user.'
|
||||||
|
'\n========================', str(bluepy_path[0] + '/bluepy-helper'))
|
||||||
|
self._connected = False
|
||||||
|
raise e
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.exception(e)
|
log.exception(e)
|
||||||
|
time.sleep(10)
|
||||||
|
|
||||||
def __fill_interest_devices(self):
|
def __fill_interest_devices(self):
|
||||||
for interest_device in self.__config.get('devices'):
|
for interest_device in self.__config.get('devices'):
|
||||||
keys_in_config = ['attributes', 'telemetry']
|
keys_in_config = ['attributes', 'telemetry']
|
||||||
if interest_device.get('MACAddress') is not None:
|
if interest_device.get('MACAddress') is not None:
|
||||||
interest_services = {}
|
interest_uuid = {}
|
||||||
for key_type in keys_in_config:
|
for key_type in keys_in_config:
|
||||||
for type_section in interest_device.get(key_type):
|
for type_section in interest_device.get(key_type):
|
||||||
if type_section.get("serviceId") is not None:
|
if type_section.get("characteristicUUID") is not None:
|
||||||
interest_services[type_section["serviceId"].upper()] = {'section_config': type_section,
|
interest_uuid[type_section["characteristicUUID"].upper()] = {'section_config': type_section,
|
||||||
'type': key_type}
|
'type': key_type}
|
||||||
if self.__devices_around.get(interest_device['MACAddress'].upper()) is None:
|
if self.__devices_around.get(interest_device['MACAddress'].upper()) is None:
|
||||||
self.__devices_around[interest_device['MACAddress'].upper()] = {}
|
self.__devices_around[interest_device['MACAddress'].upper()] = {}
|
||||||
self.__devices_around[interest_device['MACAddress'].upper()]['interest_services'] = interest_services
|
self.__devices_around[interest_device['MACAddress'].upper()]['interest_uuid'] = interest_uuid
|
||||||
else:
|
else:
|
||||||
log.error("Device address not found, please check your settings.")
|
log.error("Device address not found, please check your settings.")
|
||||||
|
|
||||||
@@ -223,50 +288,3 @@ class ScanDelegate(DefaultDelegate):
|
|||||||
def handleDiscovery(self, dev, is_new_device, is_new_data):
|
def handleDiscovery(self, dev, is_new_device, is_new_data):
|
||||||
if is_new_device:
|
if is_new_device:
|
||||||
self.__connector.device_add(dev)
|
self.__connector.device_add(dev)
|
||||||
|
|
||||||
def handleNotification(self, handle, data):
|
|
||||||
log.debug('Received notification for handle: %s', handle)
|
|
||||||
log.debug(data)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
test_config = {
|
|
||||||
"name": "BLE Connector",
|
|
||||||
"rescanIntervalSeconds": 10,
|
|
||||||
"devices": [
|
|
||||||
{
|
|
||||||
"name": "Temperature and humidity sensor",
|
|
||||||
"notify": True,
|
|
||||||
"MACAddress": "EC:C8:BB:6E:05:67",
|
|
||||||
"checkIntervalMillis": 10000,
|
|
||||||
"telemetry": [
|
|
||||||
{
|
|
||||||
"key": "temperature",
|
|
||||||
"serviceId": "00001800-0000-1000-8000-00805F9B34FB",
|
|
||||||
"fromNotify": True,
|
|
||||||
"fromByte": 0,
|
|
||||||
"toByte": -1,
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"attributes": [
|
|
||||||
{
|
|
||||||
"key": "batteryLevel",
|
|
||||||
"handle": 0x15,
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
connector = BLEConnector(None, test_config)
|
|
||||||
try:
|
|
||||||
connector.open()
|
|
||||||
log.debug('Started')
|
|
||||||
except Exception as e:
|
|
||||||
log.exception(e)
|
|
||||||
log.error(e)
|
|
||||||
connector.close()
|
|
||||||
while True:
|
|
||||||
time.sleep(.1)
|
|
||||||
# connector.close()
|
|
||||||
# break
|
|
||||||
|
|||||||
@@ -32,6 +32,10 @@ class Connector(ABC):
|
|||||||
def get_name(self):
|
def get_name(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def is_connected(self):
|
||||||
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def on_attributes_update(self, content):
|
def on_attributes_update(self, content):
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ from thingsboard_gateway.tb_utility.tb_utility import TBUtility
|
|||||||
from thingsboard_gateway.connectors.mqtt.mqtt_connector import MqttConnector
|
from thingsboard_gateway.connectors.mqtt.mqtt_connector import MqttConnector
|
||||||
from thingsboard_gateway.connectors.opcua.opcua_connector import OpcUaConnector
|
from thingsboard_gateway.connectors.opcua.opcua_connector import OpcUaConnector
|
||||||
from thingsboard_gateway.connectors.modbus.modbus_connector import ModbusConnector
|
from thingsboard_gateway.connectors.modbus.modbus_connector import ModbusConnector
|
||||||
|
from thingsboard_gateway.connectors.ble.ble_connector import BLEConnector
|
||||||
from thingsboard_gateway.storage.memory_event_storage import MemoryEventStorage
|
from thingsboard_gateway.storage.memory_event_storage import MemoryEventStorage
|
||||||
from thingsboard_gateway.storage.file_event_storage import FileEventStorage
|
from thingsboard_gateway.storage.file_event_storage import FileEventStorage
|
||||||
|
|
||||||
@@ -57,6 +58,7 @@ class TBGatewayService:
|
|||||||
"mqtt": MqttConnector,
|
"mqtt": MqttConnector,
|
||||||
"modbus": ModbusConnector,
|
"modbus": ModbusConnector,
|
||||||
"opcua": OpcUaConnector,
|
"opcua": OpcUaConnector,
|
||||||
|
"ble": BLEConnector,
|
||||||
}
|
}
|
||||||
self.__event_storage_types = {
|
self.__event_storage_types = {
|
||||||
"memory": MemoryEventStorage,
|
"memory": MemoryEventStorage,
|
||||||
@@ -135,6 +137,7 @@ class TBGatewayService:
|
|||||||
connector.open()
|
connector.open()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.exception(e)
|
log.exception(e)
|
||||||
|
connector.close()
|
||||||
|
|
||||||
def __send_statistic(self):
|
def __send_statistic(self):
|
||||||
self.tb_client.client.gw_send_telemetry()
|
self.tb_client.client.gw_send_telemetry()
|
||||||
|
|||||||
Reference in New Issue
Block a user