Skip to content

Commit 1bbc33c

Browse files
author
Michelle Sintov
authored
Update README, use daemon process, etc. anki#4
2 parents 7dbe761 + 9f46c00 commit 1bbc33c

75 files changed

Lines changed: 795 additions & 452 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CODESTYLE.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ The code should generally follow [PEP8](https://www.python.org/dev/peps/pep-0008
44

55
Code documentation should be written using Google style, which can be extracted
66
using Sphinx:
7-
* http://google.github.io/styleguide/pyguide.html
8-
* http://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html
7+
* https://google.github.io/styleguide/pyguide.html
8+
* https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html
99

1010

1111
Main style points to consider:
@@ -76,7 +76,7 @@ leading underscore to indicate that they're "private"
7676

7777
## Documentation
7878

79-
See http://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html
79+
See https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html
8080
for documentation examples.
8181

8282
* Module-level documentation should appear first in the file, before imports

Makefile

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
.PHONY: dist examples license wheel installer
1+
.PHONY: clean dist examples license wheel installer
22

33
version = $(shell perl -ne '/__version__ = "([^"]+)/ && print $$1;' anki_vector/version.py)
44

@@ -17,10 +17,10 @@ $(license_targets): LICENSE.txt
1717
cp LICENSE.txt $$fn; \
1818
done
1919

20-
$(sdist_filename): anki_vector/LICENSE.txt anki_vector/assets/LICENSE.txt $(shell find anki_vector -name '*.py' -o -name '*.mtl' -o -name '*.obj' -o -name '*.jpg')
20+
$(sdist_filename): anki_vector/LICENSE.txt anki_vector/opengl/assets/LICENSE.txt $(shell find anki_vector -name '*.py' -o -name '*.mtl' -o -name '*.obj' -o -name '*.jpg')
2121
python3 setup.py sdist
2222

23-
$(wheel_filename): anki_vector/LICENSE.txt anki_vector/assets/LICENSE.txt $(shell find anki_vector -name '*.py' -o -name '*.mtl' -o -name '*.obj' -o -name '*.jpg')
23+
$(wheel_filename): anki_vector/LICENSE.txt anki_vector/opengl/assets/LICENSE.txt $(shell find anki_vector -name '*.py' -o -name '*.mtl' -o -name '*.obj' -o -name '*.jpg')
2424
python3 setup.py bdist_wheel
2525

2626
dist/anki_vector_sdk_examples.zip: examples/LICENSE.txt $(example_pathnames)
@@ -42,3 +42,6 @@ dist/anki_vector_sdk_examples.tar.gz: examples/LICENSE.txt $(example_pathnames)
4242
examples: dist/anki_vector_sdk_examples.tar.gz dist/anki_vector_sdk_examples.zip
4343

4444
dist: $(sdist_filename) $(wheel_filename) examples
45+
46+
clean:
47+
rm -rf dist

README.md

Lines changed: 9 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,21 @@
11
# Anki Vector - Python SDK
22

3-
## Getting Started
4-
5-
Before connecting, you will need:
6-
7-
* Vector's Name: This is the name displayed on his face for BLE pairing after you double-click while Vector is on the charger. Example: `Vector-A1B2`
8-
* Vector's IP Address: The ip address can be found by first placing Vector on the charger, then double-clicking the button on his back, and finally raising and lowering his arms. It is possible for your ip to change based on your network settings, so it must be updated accordingly. Example: `192.168.43.48`
9-
* Vector's Serial Number: You may find this number on the underside of your robot. Example: `00e20115`
10-
11-
These will be needed to run the `anki_vector.configure` executable submodule and set up authentication from your device to your Vector.
12-
13-
Your device must have Python 3.6.1 or later installed. Please see the documentation pages mentioned below for instructions to install Python.
3+
![Vector](docs/source/images/vector-sdk-alpha.jpg)
144

5+
Learn more about Vector: https://www.anki.com/vector
156

16-
---
7+
Learn more about the SDK: https://developer.anki.com/
178

18-
Check out the documentation for setup instructions by opening docs/build/html/index.html in your browser.
9+
SDK documentation: http://developer.anki.com/vector/docs/
1910

20-
---
11+
Forums: https://forums.anki.com/
2112

22-
During setup, you will configure your `anki_vector` SDK authentication from a terminal using `'python3 -m anki_vector.configure`.
2313

24-
By running this script, you will be asked to provide your Anki account credentials, and the script will download an authentication token and cert that will grant you access to the robot and his capabilities (such as camera and audio) as well as data stored on the robot (such as faces and photos).
25-
26-
The downloaded access token is equivalent to your account credentials. It will be stored in your user directory (~/.anki_vector) along with a robot identity certificate and other useful data for establishing a connection. Do not share your access token.
27-
28-
If you have any trouble, please post to the Vector forums at https://forums.anki.com/
29-
30-
---
14+
## Getting Started
3115

32-
If you encounter any issues, please reach out to the forums team and let us know at https://forums.anki.com/
16+
You can follow steps [here](http://developer.anki.com/vector/docs/) to set up your Vector robot with the SDK.
3317

34-
---
3518

36-
Use of Vector and the Vector SDK is subject to Anki's Privacy Policy and Terms and Conditions.
19+
## Privacy Policy and Terms and Conditions
3720

38-
https://www.anki.com/en-us/company/privacy
39-
https://www.anki.com/en-us/company/terms-and-conditions
21+
Use of Vector and the Vector SDK is subject to Anki's [Privacy Policy](https://www.anki.com/en-us/company/privacy) and [Terms and Conditions](https://www.anki.com/en-us/company/terms-and-conditions).

anki_vector/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# you may not use this file except in compliance with the License.
55
# You may obtain a copy of the License in the file LICENSE.txt or at
66
#
7-
# http://www.apache.org/licenses/LICENSE-2.0
7+
# https://www.apache.org/licenses/LICENSE-2.0
88
#
99
# Unless required by applicable law or agreed to in writing, software
1010
# distributed under the License is distributed on an "AS IS" BASIS,

anki_vector/animation.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# you may not use this file except in compliance with the License.
55
# You may obtain a copy of the License in the file LICENSE.txt or at
66
#
7-
# http://www.apache.org/licenses/LICENSE-2.0
7+
# https://www.apache.org/licenses/LICENSE-2.0
88
#
99
# Unless required by applicable law or agreed to in writing, software
1010
# distributed under the License is distributed on an "AS IS" BASIS,

anki_vector/audio.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# you may not use this file except in compliance with the License.
55
# You may obtain a copy of the License in the file LICENSE.txt or at
66
#
7-
# http://www.apache.org/licenses/LICENSE-2.0
7+
# https://www.apache.org/licenses/LICENSE-2.0
88
#
99
# Unless required by applicable law or agreed to in writing, software
1010
# distributed under the License is distributed on an "AS IS" BASIS,

anki_vector/behavior.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# you may not use this file except in compliance with the License.
55
# You may obtain a copy of the License in the file LICENSE.txt or at
66
#
7-
# http://www.apache.org/licenses/LICENSE-2.0
7+
# https://www.apache.org/licenses/LICENSE-2.0
88
#
99
# Unless required by applicable law or agreed to in writing, software
1010
# distributed under the License is distributed on an "AS IS" BASIS,

anki_vector/camera.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# you may not use this file except in compliance with the License.
55
# You may obtain a copy of the License in the file LICENSE.txt or at
66
#
7-
# http://www.apache.org/licenses/LICENSE-2.0
7+
# https://www.apache.org/licenses/LICENSE-2.0
88
#
99
# Unless required by applicable law or agreed to in writing, software
1010
# distributed under the License is distributed on an "AS IS" BASIS,

anki_vector/color.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# you may not use this file except in compliance with the License.
55
# You may obtain a copy of the License in the file LICENSE.txt or at
66
#
7-
# http://www.apache.org/licenses/LICENSE-2.0
7+
# https://www.apache.org/licenses/LICENSE-2.0
88
#
99
# Unless required by applicable law or agreed to in writing, software
1010
# distributed under the License is distributed on an "AS IS" BASIS,

anki_vector/configure/__main__.py

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -26,28 +26,28 @@
2626

2727
import argparse
2828
import configparser
29-
from cryptography import x509
30-
from cryptography.hazmat.backends import default_backend
3129
from getpass import getpass
3230
import json
3331
import os
3432
from pathlib import Path
3533
import re
36-
import requests
3734
import socket
3835
import sys
3936

40-
from google.protobuf.json_format import MessageToJson
37+
from cryptography import x509
38+
from cryptography.hazmat.backends import default_backend
4139
import grpc
40+
import requests
4241
try:
43-
from termcolor import colored
44-
except:
45-
def colored(text, color=None, on_color=None, attrs=None):
42+
from termcolor import colored # pylint: disable=import-error
43+
except: # pylint: disable=bare-except
44+
def colored(text, color=None, on_color=None, attrs=None): # pylint: disable=unused-argument
4645
return text
4746

4847
import anki_vector
4948
from anki_vector import messaging
5049

50+
5151
class ApiHandler:
5252
def __init__(self, headers: dict, url: str):
5353
self._headers = headers
@@ -61,6 +61,7 @@ def headers(self):
6161
def url(self):
6262
return self._url
6363

64+
6465
class Api:
6566
def __init__(self):
6667
self._handler = ApiHandler(
@@ -79,10 +80,11 @@ def name(self):
7980
def handler(self):
8081
return self._handler
8182

83+
8284
def get_serial(serial=None):
8385
if not serial:
8486
serial = os.environ.get('ANKI_ROBOT_SERIAL')
85-
if not serial or len(serial) == 0:
87+
if not serial:
8688
print("\n\nPlease find your robot serial number (ex. 00e20100) located on the underside of Vector, or accessible from Vector's debug screen.")
8789
serial = input('Enter robot serial number: ')
8890
else:
@@ -91,6 +93,7 @@ def get_serial(serial=None):
9193
print("Using robot serial number: {}".format(colored(serial, "cyan")))
9294
return serial
9395

96+
9497
def get_cert(serial=None):
9598
serial = get_serial(serial)
9699
print("\nDownloading Vector certificate from Anki...", end="")
@@ -103,14 +106,15 @@ def get_cert(serial=None):
103106
cert = r.content
104107
return cert, serial
105108

109+
106110
def user_authentication(session_id: bytes, cert: bytes, ip: str, name: str) -> str:
107111
# Pin the robot certificate for opening the channel
108112
creds = grpc.ssl_channel_credentials(root_certificates=cert)
109113

110114
print("Attempting to download guid from {} at {}:443...".format(colored(name, "cyan"), colored(ip, "cyan")), end="")
111115
sys.stdout.flush()
112116
channel = grpc.secure_channel("{}:443".format(ip), creds,
113-
options=(("grpc.ssl_target_name_override", name,),))
117+
options=(("grpc.ssl_target_name_override", name,),))
114118

115119
# Verify the connection to Vector is able to be established (client-side)
116120
try:
@@ -124,13 +128,13 @@ def user_authentication(session_id: bytes, cert: bytes, ip: str, name: str) -> s
124128
try:
125129
interface = messaging.client.ExternalInterfaceStub(channel)
126130
request = messaging.protocol.UserAuthenticationRequest(
127-
user_session_id=session_id.encode('utf-8'),
128-
client_name=socket.gethostname().encode('utf-8'))
131+
user_session_id=session_id.encode('utf-8'),
132+
client_name=socket.gethostname().encode('utf-8'))
129133
response = interface.UserAuthentication(request)
130-
if response.code != messaging.protocol.UserAuthenticationResponse.AUTHORIZED:
134+
if response.code != messaging.protocol.UserAuthenticationResponse.AUTHORIZED: # pylint: disable=no-member
131135
print(colored(" ERROR", "red"))
132136
sys.exit("\nFailed to authorize request:\n"
133-
"Please be sure to first set up Vector using the companion app.")
137+
"Please be sure to first set up Vector using the companion app.")
134138
except grpc.RpcError as e:
135139
print(colored(" ERROR", "red"))
136140
sys.exit("\nFailed to authorize request:\n"
@@ -139,6 +143,7 @@ def user_authentication(session_id: bytes, cert: bytes, ip: str, name: str) -> s
139143
print(colored(" DONE\n", "green"))
140144
return response.client_token_guid
141145

146+
142147
def get_session_token(api, username=None):
143148
print("Enter your email and password. Make sure to use the same account that was used to set up your Vector.")
144149
if not username:
@@ -157,6 +162,7 @@ def get_session_token(api, username=None):
157162
print(colored(" DONE\n", "green"))
158163
return json.loads(r.content)
159164

165+
160166
def standardize_name(robot_name):
161167
# Extend the name if not enough is provided
162168
if len(robot_name) == 4:
@@ -169,12 +175,12 @@ def standardize_name(robot_name):
169175
return robot_name
170176
print(colored(" ERROR", "red"))
171177
sys.exit("Invalid robot name. Please match the format exactly. Example: Vector-A1B2")
172-
return
178+
173179

174180
def get_name_and_ip(robot_name=None, ip=None):
175181
if not robot_name:
176182
robot_name = os.environ.get('VECTOR_ROBOT_NAME')
177-
if not robot_name or len(robot_name) == 0:
183+
if not robot_name:
178184
print("\n\nFind your robot name (ex. Vector-A1B2) by placing Vector on the charger and double-clicking Vector's backpack button.")
179185
robot_name = input("Enter robot name: ")
180186
else:
@@ -183,15 +189,16 @@ def get_name_and_ip(robot_name=None, ip=None):
183189
print("Using robot name: {}".format(colored(robot_name, "cyan")))
184190
if not ip:
185191
ip = os.environ.get('ANKI_ROBOT_HOST')
186-
if not ip or len(ip) == 0:
192+
if not ip:
187193
print("\n\nFind your robot ip address (ex. 192.168.42.42) by placing Vector on the charger, double-clicking Vector's backpack button,\n"
188-
"then raising and lowering his arms. If you see {} on his face, reconnect Vector to your WiFi using the Vector Companion App.".format(colored("XX.XX.XX.XX", "red")))
194+
"then raising and lowering his arms. If you see {} on his face, reconnect Vector to your WiFi using the Vector Companion App.".format(colored("XX.XX.XX.XX", "red")))
189195
ip = input("Enter robot ip: ")
190196
else:
191197
print("Found robot ip address in environment variable '{}'".format(colored("ANKI_ROBOT_HOST", "green")))
192198
print("Using IP: {}".format(colored(ip, "cyan")))
193199
return robot_name, ip
194200

201+
195202
def save_cert(cert, name, serial, anki_dir):
196203
"""Write Vector's certificate to a file located in the user's home directory"""
197204
os.makedirs(str(anki_dir), exist_ok=True)
@@ -201,6 +208,7 @@ def save_cert(cert, name, serial, anki_dir):
201208
f.write(cert)
202209
return cert_file
203210

211+
204212
def validate_cert_name(cert_file, robot_name):
205213
"""Validate the name on Vector's certificate against the user-provided name"""
206214
with open(cert_file, "rb") as f:
@@ -217,6 +225,7 @@ def validate_cert_name(cert_file, robot_name):
217225
else:
218226
return
219227

228+
220229
def write_config(serial, cert_file=None, ip=None, name=None, guid=None, clear=True):
221230
home = Path.home()
222231
config_file = str(home / ".anki_vector" / "sdk_config.ini")
@@ -253,6 +262,7 @@ def write_config(serial, cert_file=None, ip=None, name=None, guid=None, clear=Tr
253262
if os.path.exists(temp_file):
254263
os.remove(temp_file)
255264

265+
256266
def main(api):
257267
parser = argparse.ArgumentParser(description=("Vector requires all requests be authorized by an authenticated Anki user. "
258268
"This script will enable this device to authenticate with your Vector "
@@ -307,5 +317,6 @@ def main(api):
307317
write_config(serial, cert_file, ip, name, guid)
308318
print(colored("\nSUCCESS!", "green"))
309319

320+
310321
if __name__ == "__main__":
311322
main(Api())

0 commit comments

Comments
 (0)