Python Mesh
Pykonik 2019
czyli zdalnie sterowane żarówki
Agenda
- Słówko o topologii sieci
- Stos BT Mesh
- Adresowanie i subskrypcje
- Połączenie z BT Mesh
- Demo!
Gwiazda
- Ethernet (10BaseT)
- IP
rozszerzona
Magistrala
- Ethernet (10Base2)
- CAN, I2C, RS-485
Siatka
Pobożne życzenia
Smutna rzeczywistość
Siatka
Retransmisje
Relay
Bezpieczeństwo
Idempotentność
listonosz nie
czyta poczty
powtórzenie komendy
nie ma skutków ubocznych
BT Mesh
Stos
Network
Transport
Application
Bearer
IP
TCP
HTTP
Ethernet
BT Mesh
Rozgłoszenia
Połączenia
Bearer
BT Mesh
Preamble | Access Address | Header | MAC Address | Payload | CRC |
---|---|---|---|---|---|
1 byte | 4 bytes | 2 bytes | 6 bytes | 0-31 bytes | 3 bytes |
Bearer
Length | Type | Data | ... | Length | Type | Data |
---|---|---|---|---|---|---|
1 byte | 1 byte | 0-29 bytes | ... | 1 byte | 1 byte | 0-29 bytes |
Losowy adres
0x2a
BT Mesh
Network
IVI | NID | CTL | TTL | SEQ | SRC | DST | PDU | MIC |
---|---|---|---|---|---|---|---|---|
1 bit | 7 bits | 1 bit | 7 bits | 24 bits | 16 bits | 16 bits | 8-128 bits | 32-64 bits |
Adresy
Podpis
Numer pakietu
Ramka
transportowa
Ukryte
Tajne
Jawne
Jawne
Identyfikator klucza
BT Mesh
Szyfrowanie
Plaintext
Nonce
Key
AES
Ciphertext
MIC
IV Index | SEQ | SRC | ... |
---|---|---|---|
32bit | 24bit | 16 bit |
Ogólnie znane
Część pakietu
Numer pakietu jest niepowtarzalny!
DST | PDU |
---|
BT Mesh
Network
from bitstring import pack
from crypto import aes_ccm, aes_ecb
network_nonce = pack('uint:8, uint:1, uint:7, '
'uintbe:24, uintbe:16, pad:16, uintbe:32',
0x00, ctl, ttl, seq, src, iv_index)
encrypted_pdu = aes_ccm(encryption_key, nonce,
bitstring.pack('uintbe:16, bytes', dst, transport_pdu))
network_header = pack('uint:1, uint:7, uintbe:24, uintbe:16',
ctl, ttl, seq, src)
# nie całkiem prawda ;-)
privacy_nonce = pack('pad:40, uintbe:32, bytes:7',
iv_index, encrypted_pdu[:7])
obfuscated_header = aes_ecb(privacy_key, privacy_nonce,
network_header)
network_pdu = pack('uint:1, uint:7, bits, bytes',
iv_index & 1, nid, obfuscated_header, network_pdu)
BT Mesh
Transport
SEG | AKF | AID | PDU | MIC |
---|---|---|---|---|
1 bit | 1 bit | 6 bits | 0-88 bits | 32-64 bits |
Identyfikator klucza
Fragmentacja
Podpis
Ramka aplikacyjna
Tajne
Jawne
Jawne
BT Mesh
Transport
from bitstring import pack
from crypto import aes_ccm
transport_nonce = pack('uint:8, uint:1, pad:7, '
'uintbe:24, uintbe:16, pad:16, uintbe:32',
0x01, long_mic, seq, src, dst, iv_index)
encrypted_pdu = aes_ccm(application_key, application_nonce,
application_pdu)
seg = len(encrypted_pdu) > 15
if not seg:
transport_pdu = pack('uint:1, uint:1, uint:6, bytes',
seg, akf, aid, encrypted_pdu)
else:
raise NotImplementedError # ;-)
BT Mesh
Application
OPCODE | PARAMETERS |
---|---|
1-3 bytes | 0-379 bytes |
'Assigned
Numbers'
- 0x00: Config Application Key Add
- 0x80 0x00: Config Application Key Delete
- 0x80 0x01: Config Application Key Get
- 0x80 0x31: Health Fault Get
- 0x05: Health Fault Status
- ...
BT Mesh
Application
application_pdu = pack('bits, bits',
opcode, parameters)
opcode = '\x80\x05' # "health: attention set"
parameters = pack('uint:8', timeout)
opcode = '\x82\x03' # "generic on-off: set unacknowledged"
parameters = pack('uint:8, uint:8, uint:2, uint:6, uint:8',
trigger, transaction, resolution, steps, delay)
opcode = '\x80\x1b' # "config: subscription add"
parameters = ...
BT Mesh
Adresowanie
0 | 15 bits |
1 | 0 | 14 bits |
1 | 1 | 14 bits |
0 | 0 |
---|
Unassigned
Unicast
Virtual
Group
BT Mesh
Elementy i modele
Adres | Element | Modele |
---|---|---|
0x0010 | #0 | Health Config Scene Server Presence Sensor |
0x0011 | #1 | Lightness Controller Ambient Light Sensor |
0x0012 | #2 | Scene Translator |
#0 | #1 | #2 | #3 |
---|---|---|---|
OnOff | OnOff | OnOff | OnOff |
0x0010 | 0x0011 | 0x0012 | 0x0013 |
Element
Adres unicast
Model
BT Mesh
Subskrypcje
0x8000
0x8001
0x0010
0x0020
0x0030
0x0040
0x8000
0x8001
0x8000
0x0050
0x8001
0x8002
BT Mesh
Subskrypcje + relay
0x8000
0x8001
0x0010
0x0030
0x8001
0x0050
0x8001
relay
BT Mesh
Retransmisje
włącz się
za 90ms
włącz się
za 30ms
włącz się
za 60ms
czas
Wszystko pięknie, ale jak się do tego podłączyć?
Mesh Proxy
Ogólnie
Proxy
GATT
0x0050
PC
Mesh Proxy
GATT
BlueZ
DBus
Python
Linux
BlueZ
Mesh Proxy
Usługi
Profil
Usługa
Charakterystyka
Charakterystyka
Usługa
Charakterystyka
Charakterystyka
BLUETOOTH_SIG = \
'0000-1000-8000-00805f9b34fb'
proxy_service = \
'00001828-' + BLUETOOTH_SIG
write_char = \
'00002add-' + BLUETOOTH_SIG
read_char = \
'00002ade-' + BLUETOOTH_SIG
Mesh Proxy
Rozgłoszenia
Preamble | Access Address | Header | MAC Address | Payload | CRC |
---|---|---|---|---|---|
1 byte | 4 bytes | 2 bytes | 6 bytes | 0-31 bytes | 3 bytes |
Length | Type | Data | ... | Length | Type | Data |
---|---|---|---|---|---|---|
1 byte | 1 byte | 0-29 bytes | ... | 1 byte | 1 byte | 0-29 bytes |
Prawdziwy adres
0x03
0x16
Mesh Proxy
Rozgłoszenia
from pydbus import SystemBus
bus = SystemBus()
adapter = bus.get('org.bluez',
'/org/bluez/hci0')
adapter.StartDiscovery()
...
def device_discovered(device):
network_id = device.ServiceData.get(ServiceId.MESH_PROXY)
proxy_mac = device.Address
Mesh Proxy
from pydbus import SystemBus
bus = SystemBus()
adapter = bus.get('org.bluez',
'/org/bluez/hci0')
adapter.StartDiscovery()
device = bus.get('org.bluez',
'/org/bluez/hci0/dev_%s' % proxy_mac)
device.Connect()
service = bus.get('org.bluez',
'/org/bluez/hci0/dev_%s/service_%s' % (proxy_mac,
proxy_service))
send = bus.get('org.bluez',
'/org/bluez/hci0/dev_%s/char_%s' % (proxy_mac,
write_char))
recv = bus.get('org.bluez',
'/org/bluez/hci0/dev_%s/char_%s' % (proxy_mac,
read_char))
Usługi
Mesh Proxy
send = bus.get('org.bluez',
'/org/bluez/hci0/dev_%s/char_%s' % (proxy_mac,
write_char))
recv = bus.get('org.bluez',
'/org/bluez/hci0/dev_%s/char_%s' % (proxy_mac,
read_char))
def packet_send(packet):
send.WriteValue(bytes(....))
def properties_changed(properties):
value = properties.get('Value')
if value is not None:
packet_receive(bytes(value))
recv.PropertiesChanged.connect(packet_received)
recv.StartNotify()
GATT Bearer
Mesh Proxy
Szczegółowo
GATT
BlueZ
DBus
Python
Linux
Relay
Proxy
pip install bluetooth-mesh
SilvairGit/python-bluetooth-mesh
GPL 2.0
Dziękuję za uwagę!
Pytania?
Bluetooth Mesh
By Michał Lowas-Rzechonek
Bluetooth Mesh
Remote controlled bulbs
- 611