mirror of
https://github.com/DanielPollithy/bluetooth_drone.git
synced 2025-10-16 11:45:38 +00:00
198 lines
6.3 KiB
Python
198 lines
6.3 KiB
Python
|
|
import bluetooth
|
|
|
|
import time
|
|
import json
|
|
|
|
from subprocess import Popen, PIPE
|
|
|
|
import settings
|
|
from drone_poller import notify_website
|
|
|
|
settings.activate_bluetooth_discovery()
|
|
bt_mac = settings.get_own_bt_address()
|
|
print('This devices bluetooth address is: {}'.format(bt_mac))
|
|
|
|
|
|
def protocol(address):
|
|
payload = json.dumps({'addr': settings.CLIENT_ETHEREUM_ADDRESS})
|
|
assert len(payload) < 1024
|
|
sock = bluetooth.BluetoothSocket(bluetooth.RFCOMM)
|
|
|
|
bt_addr = address
|
|
port = 0x1001
|
|
|
|
print("trying to connect to %s on PSM 0x%X" % (bt_addr, port))
|
|
|
|
sock.connect((bt_addr, port))
|
|
|
|
print("connected. Sending: ", payload)
|
|
sock.send(payload)
|
|
|
|
with open('connection_state.txt', 'w') as inp:
|
|
inp.write(json.dumps({
|
|
'state': 'landing approach',
|
|
'station': ''
|
|
}))
|
|
notify_website()
|
|
|
|
# THE SERVER WILL ONLY REPLY WHEN THE BLUETOOTH DISTANCE IS CLOSE ENOUGH
|
|
# BUT THE SOCKET STAYS OPEN
|
|
|
|
data = sock.recv(1024)
|
|
print("Data received:", str(data))
|
|
try:
|
|
data = json.loads(data)
|
|
assert 'accepted' in data
|
|
connection_accepted = data['accepted']
|
|
if connection_accepted:
|
|
assert 'addr' in data
|
|
server_ethereum_address = data['addr'].lower()
|
|
with open('connection_state.txt', 'w') as inp:
|
|
inp.write(json.dumps({
|
|
'status': 'landing accepted',
|
|
'station': server_ethereum_address
|
|
}))
|
|
notify_website()
|
|
else:
|
|
server_ethereum_address = False
|
|
with open('connection_state.txt', 'w') as inp:
|
|
inp.write(json.dumps({
|
|
'status': 'landing denied',
|
|
'station': ''
|
|
}))
|
|
notify_website()
|
|
except AssertionError:
|
|
print('Json is missing data')
|
|
sock.close()
|
|
raise StandardError
|
|
except:
|
|
print('Error reading json from the data')
|
|
sock.close()
|
|
raise StandardError
|
|
|
|
if not connection_accepted:
|
|
print('The server has not accepted the drone')
|
|
print('Closing connection.')
|
|
sock.close()
|
|
|
|
print('Connection accepted')
|
|
print('calling ethereum network')
|
|
|
|
# ETHEREUM
|
|
# now start the transaction
|
|
if not settings.DEMO:
|
|
print('node start_charging.js {} {}'.format(settings.CLIENT_ETHEREUM_ADDRESS, server_ethereum_address))
|
|
p = Popen(
|
|
[
|
|
'node',
|
|
'start_charging.js',
|
|
settings.CLIENT_ETHEREUM_ADDRESS,
|
|
server_ethereum_address
|
|
],
|
|
stdin=PIPE,
|
|
stdout=PIPE,
|
|
stderr=PIPE
|
|
)
|
|
output, err = p.communicate()
|
|
returncode = p.returncode
|
|
else:
|
|
returncode = 0
|
|
|
|
if returncode != 0:
|
|
sock.send(json.dumps({'start_charging': False}))
|
|
print('Not starting charging logic (no reservation or blockchain problem)')
|
|
print('Closing connection.')
|
|
with open('connection_state.txt', 'w') as inp:
|
|
inp.write(json.dumps({
|
|
'status': 'charging denied',
|
|
'station': server_ethereum_address
|
|
}))
|
|
notify_website()
|
|
# wait for remote closing
|
|
data = sock.recv(1024)
|
|
# sock.close()
|
|
|
|
with open('connection_state.txt', 'w') as inp:
|
|
inp.write(json.dumps({
|
|
'status': 'start charging',
|
|
'station': server_ethereum_address
|
|
}))
|
|
notify_website()
|
|
sock.send(json.dumps({'start_charging': True}))
|
|
|
|
# the server will activate the relais now
|
|
# the loading will take time and there could be some information exchanged here in the future
|
|
data = sock.recv(1024)
|
|
print("Data received:", str(data))
|
|
try:
|
|
data = json.loads(data)
|
|
assert 'electricity' in data
|
|
electricity = data['electricity']
|
|
except AssertionError:
|
|
print('Json is missing data')
|
|
sock.close()
|
|
raise StandardError
|
|
except:
|
|
print('Error reading json from the data')
|
|
sock.close()
|
|
raise StandardError
|
|
|
|
print('Energy consumption as hangar says: {}'.format(electricity))
|
|
print('Transaction done.')
|
|
|
|
with open('connection_state.txt', 'w') as inp:
|
|
inp.write(json.dumps({
|
|
'status': 'charging ended',
|
|
'station': server_ethereum_address
|
|
}))
|
|
notify_website()
|
|
|
|
sock.close()
|
|
|
|
def run():
|
|
connecting = True
|
|
while connecting:
|
|
nearby_devices = bluetooth.discover_devices(duration=settings.BT_DISCOVERY_DURATION, flush_cache=False)
|
|
print("found %d devices" % len(nearby_devices))
|
|
|
|
for address in nearby_devices:
|
|
print(" %s " % (address))
|
|
if address.lower() == settings.PEER_BT_ADDRESS:
|
|
print("PEERING PARTNER FOUND")
|
|
try:
|
|
protocol(address.lower())
|
|
except bluetooth.BluetoothError as e:
|
|
print('e')
|
|
print(e)
|
|
print('errno')
|
|
print(e.errno)
|
|
print('args')
|
|
print(e.args)
|
|
print('msg')
|
|
print(e.message)
|
|
print('__repr__()')
|
|
print(e.__repr__())
|
|
if e.__repr__() == "(104, 'Connection reset by peer')":
|
|
print('Connection reset by peer')
|
|
print('That is o.k. I make a break and then we keep on')
|
|
time.sleep(settings.DRONE_REJECTED_RESTART_TIME)
|
|
elif e.message == "(112, 'Host is down')":
|
|
print('The host is down. :(')
|
|
print('Try to reconnect')
|
|
elif e.message == "(9, 'Bad file descriptor')":
|
|
print('Closing connection because booking is unconfirmed')
|
|
print('No booking in blockchain')
|
|
elif e.message == "(104, 'Connection reset by peer')":
|
|
print('Peer closed connection')
|
|
print('No booking in blockchain')
|
|
else:
|
|
print('This error is not known. I stop connecting')
|
|
print(e)
|
|
# connecting = False
|
|
|
|
time.sleep(settings.BT_SLEEP)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
run() |