-
Notifications
You must be signed in to change notification settings - Fork 55
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a Bluetooth server of pi version
- Loading branch information
Showing
10 changed files
with
1,733 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# Used for mycobot pi and mycobot_app | ||
|
||
## Usage method | ||
|
||
### 1.Make sure raspberry pi Bluetooth is available | ||
|
||
The Ubuntu 20.04 system needs to restart the Bluetooth service first. | ||
|
||
```shell | ||
sudo systemctl restart bluetooth | ||
``` | ||
|
||
### 2.Run Bluetooth server | ||
|
||
```shell | ||
python uart_peripheral_serial.py | ||
``` |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
import sys, time, threading, logging | ||
sys.path.append('.') | ||
|
||
from ai import singleton, parameters, functools, coloredlogging | ||
|
||
logger = coloredlogging.get_logger("AS", coloredlogging.BLUE) | ||
logger.addHandler(logging.NullHandler()) | ||
|
||
class AppStates(metaclass=singleton.Singleton): | ||
happiness = 4 | ||
hungry = 4 | ||
energy = 4 | ||
comfort = 4 | ||
counter = 0 | ||
|
||
def __init__(self) -> None: | ||
... | ||
|
||
@classmethod | ||
def recover(cls, genre): | ||
if genre == 'energy': | ||
cls.energy += 1 | ||
cls.energy = min(4, cls.energy) | ||
elif genre == 'happiness': | ||
cls.happiness += 1 | ||
cls.happiness = min(4, cls.happiness) | ||
elif genre == 'hungry': | ||
cls.happiness += 1 | ||
cls.happiness = min(4, cls.happiness) | ||
elif genre == 'comfort': | ||
cls.comfort += 1 | ||
cls.comfort = min(4, cls.comfort) | ||
|
||
@classmethod | ||
def drop(cls, genre: str): | ||
if genre == 'energy': | ||
cls.energy -= 1 | ||
cls.energy = max(0, cls.energy) | ||
elif genre == 'happiness': | ||
cls.happiness -= 1 | ||
cls.happiness = max(0, cls.happiness) | ||
elif genre == 'hungry': | ||
cls.happiness -= 1 | ||
cls.happiness = max(0, cls.happiness) | ||
elif genre == 'comfort': | ||
cls.comfort -= 1 | ||
cls.comfort = max(0, cls.comfort) | ||
|
||
@classmethod | ||
def recover_by_action(cls, action: str): | ||
if action == 'eat': | ||
cls.recover('hungry') | ||
elif action.startswith('touch'): | ||
cls.recover('comfort') | ||
elif action in parameters.BEHAVIOURS['relax']: | ||
cls.recover('energy') | ||
elif action.startswith('voice') or action.startswith( | ||
'stare') or action in ['ball', 'attack', 'flap']: | ||
cls.recover('happiness') | ||
|
||
@classmethod | ||
@functools.thread_run | ||
def async_run(cls): | ||
logger.debug(f'Starting Stats recorder') | ||
while ...: | ||
time.sleep(60 * 10) | ||
AppStates.counter += 1 | ||
cls.drop('energy') | ||
if AppStates.counter % 2 == 0: | ||
cls.drop('happiness') | ||
cls.drop('comfort') | ||
elif AppStates.counter % 12 == 0: | ||
cls.drop('hungry') | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,195 @@ | ||
import bluetooth | ||
import pygatt | ||
import pathlib | ||
import time | ||
import json | ||
import hashlib | ||
from func_timeout import func_timeout, FunctionTimedOut | ||
import os | ||
import sys | ||
sys.path.append('.') | ||
|
||
from typing import Tuple | ||
|
||
import ai.action.move.movement | ||
|
||
mars = ai.action.move.movement.Movements() | ||
|
||
|
||
class BluetoothService: | ||
pass | ||
|
||
|
||
def list_devices() -> Tuple[str, str]: | ||
nearby_devices = bluetooth.discover_devices(lookup_names=True) | ||
return nearby_devices | ||
|
||
|
||
def filter_marscat(bluetooth_devices: Tuple[str, str]) -> Tuple[str, str]: | ||
marscats = [] | ||
for addr, name in bluetooth_devices: | ||
name.encode('utf-8', 'replace') | ||
if name == 'marscat': | ||
marscats.append((addr, name)) | ||
return marscats | ||
|
||
|
||
def start_marscat_bt() -> None: | ||
server_sock = bluetooth.BluetoothSocket(bluetooth.L2CAP) | ||
server_sock.bind(("", bluetooth.PORT_ANY)) | ||
server_sock.listen(1) | ||
port = server_sock.getsockname()[1] | ||
uuid = '26754beb-1bd0-4017-b341-154bed30b71a' | ||
name = 'marscat_bt' | ||
bluetooth.advertise_service( | ||
server_sock, | ||
name, | ||
service_id=uuid, | ||
service_classes=[uuid, bluetooth.SERIAL_PORT_CLASS], | ||
profiles=[bluetooth.SERIAL_PORT_PROFILE], | ||
provider='', | ||
description='', | ||
protocols=[bluetooth.OBEX_UUID]) | ||
print("Waiting for connection on RFCOMM channel {}".format(port)) | ||
|
||
client_sock, client_info = server_sock.accept() | ||
|
||
|
||
print("Accepted connection from", client_info) | ||
|
||
while True: | ||
time.sleep(0.1) | ||
try: | ||
data = client_sock.recv(1024) | ||
except OSError: | ||
print("Remote client disconnected") | ||
data = None | ||
|
||
if not data: | ||
client_sock.close() | ||
print("Close Client Socket") | ||
print("Waiting for connection on RFCOMM channel {}".format(port)) | ||
client_sock, client_info = server_sock.accept() | ||
print("Accepted connection from", client_info) | ||
continue | ||
|
||
if data == b'run': | ||
pass | ||
#mars.set_run() | ||
elif data == b'walk': | ||
pass | ||
#mars.set_walk() | ||
elif data == b'stand': | ||
pass | ||
#mars.set_stand() | ||
elif data == b'sit': | ||
pass | ||
#mars.set_sit() | ||
elif data == b'left': | ||
pass | ||
#mars.set_turn() | ||
elif data == b'right': | ||
pass | ||
#mars.set_turn(-1) | ||
elif data == b'send_update_start': | ||
print('start receive') | ||
|
||
# recv file information | ||
data = client_sock.recv(1024) | ||
file_len = int(str(data, encoding='utf8')) | ||
print('file size : ', file_len) | ||
|
||
data = client_sock.recv(1024) | ||
file_md5 = str(data, encoding='utf8') | ||
print(file_md5) | ||
|
||
# receive marsai.zip | ||
if os.path.exists(str(pathlib.Path.home()) + '/marsai.zip'): | ||
os.system( | ||
'rm {}'.format(str(pathlib.Path.home()) + '/marsai.zip')) | ||
os.system( | ||
'touch {}'.format(str(pathlib.Path.home()) + '/marsai.zip')) | ||
|
||
i = 0 | ||
buffer = 4096 | ||
|
||
def recv_data(buffer): | ||
print('start recv_data') | ||
data = client_sock.recv(buffer) | ||
return data | ||
|
||
with open(str(pathlib.Path.home()) + '/marsai.zip', 'ab+') as f: | ||
while file_len != 0: | ||
time.sleep(0.1) | ||
data = recv_data(buffer) | ||
#while True: | ||
# try: | ||
# time.sleep(0.1) | ||
# data = func_timeout(1, recv_data, (buffer, )) | ||
# except FunctionTimedOut: | ||
# print('time out') | ||
# client_sock.send(str(file_len).encode('utf-8')) | ||
# client_sock.close() | ||
# print('client closed') | ||
# client_sock, client_info = server_sock.accept() | ||
# print('accepted') | ||
# except bluetooth.BluetoothError as e: | ||
# print("error") | ||
# else: | ||
# break | ||
f.write(data) | ||
print('write', i, len(data)) | ||
i += 1 | ||
file_len -= len(data) | ||
print(file_len) | ||
if file_len < buffer: | ||
buffer = file_len | ||
print('write finished') | ||
print('receive over') | ||
|
||
# recv over flag and update marsai | ||
while True: | ||
data = client_sock.recv(4096) | ||
if data == b'over_and_update': | ||
md5 = get_md5(str(pathlib.Path.home()) + '/marsai.zip') | ||
if file_md5 == md5: | ||
os.system('sh ~/marsai/tools/stop-systemd-services.sh') | ||
time.sleep(3) | ||
os.system('unzip -o ~/marsai.zip -d ~/marsai') | ||
time.sleep(1) | ||
os.system('sh ~/marsai/tools/start-systemd-services.sh') | ||
client_sock.send(b'update_over') | ||
print('over') | ||
break | ||
else: | ||
print('md5 error') | ||
break | ||
else: | ||
pass | ||
|
||
|
||
|
||
|
||
else: | ||
pass | ||
|
||
print("Received " + str(data)) | ||
|
||
client_sock.close() | ||
print("Close Client Socket") | ||
|
||
server_sock.close() | ||
print("Stop Server") | ||
|
||
def get_md5(_file): | ||
m = hashlib.md5() | ||
with open(_file, 'rb') as f: | ||
for line in f: | ||
m.update(line) | ||
md5_code = m.hexdigest() | ||
print(md5_code) | ||
return md5_code | ||
|
||
|
||
if __name__ == "__main__": | ||
start_marscat_bt() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import sys | ||
import bluetooth | ||
|
||
|
||
if __name__ == "__main__": | ||
addr = None | ||
|
||
if len(sys.argv) < 2: | ||
print("No device specified. Searching all nearby bluetooth devices for the marscat_bt service...") | ||
else: | ||
addr = sys.argv[1] | ||
print("Searching for marscat_bt on {}...".format(addr)) | ||
|
||
uuid = '26754beb-1bd0-4017-b341-154bed30b71a' | ||
service_matches = bluetooth.find_service(uuid=uuid, address=addr) | ||
|
||
if len(service_matches) == 0: | ||
print("Couldn't find the marscat_bt service.") | ||
sys.exit(0) | ||
|
||
first_match = service_matches[0] | ||
port = first_match["port"] | ||
name = first_match["name"] | ||
host = first_match["host"] | ||
|
||
print("Connecting to \"{}\" on {}".format(name, host)) | ||
|
||
# Create the client socket | ||
sock = bluetooth.BluetoothSocket(bluetooth.RFCOMM) | ||
sock.connect((host, port)) | ||
|
||
print("Connected. Type something...") | ||
while True: | ||
data = input() | ||
if not data: | ||
break | ||
sock.send(data) | ||
|
||
sock.close() |
Oops, something went wrong.