Python API for working with Wonder Workshop robots
Project description
WonderPy
This is an alpha-status project to bring realtime control of the WonderWorkshop robots to Python.
To get the most out of this, you should already have a beginner-level comfort with python and the command-line.
Project Status
At an "Alpha" release. It's ready to be tried out by folks who are willing to live with a few more rough-edges than one would want, and ideally who can provide constructive criticism.
Known Issues and To-Do's
Please see the "Issues" in github for an up-to-date list.
As of this writing, the open issues are:
- Only works with a single robot.
- Only works with Python2.7.
The limiting factor here is getting the AdaFruit BTLE package to run under Python3. There's evidence this is possible. - Once under Python3, update the concurrency model.
- Flesh-out inline documentation.
- Make the pip installation more standard. Currently this requires a manual install of a github-based fork of the AdaFruit package.
- Port to Windows, Linux
Setup
Prerequisites
- MacOS
- Familiarity with python and command-line tools
Create a new python virtual environment
virtualenv --python=/usr/bin/python2.7 --no-site-packages venv
source venv/bin/activate
Install dependencies
Unfortunately the AdaFruit BTLE package is not hosted on PyPi, which makes it difficult to automatically install when this package is installed via pip. Additionally, this project requires a fork of that project by WonderWorkshop, which as of this writing has not been merged back into the main project.
pip install git+git://github.com/playi/Adafruit_Python_BluefruitLE@928669a#egg=Adafruit_BluefruitLE
Install WonderPy
pip install WonderPy
Getting Started
The steps above install the core library.
There are many examples of using it separately in the github repository playi/WonderPyExamples.
It is highly recommended to look at those examples.
Additional documentation is in the source code and also in doc/WonderPy.md.
One of the examples is this "hello world" example. Copy this file into "hello_world.py" and run it.
from threading import Thread
import time
import WonderPy.core.wwMain
from WonderPy.core.wwConstants import WWRobotConstants
from WonderPy.components.wwMedia import WWMedia
"""
This example shows very basic connecting to a robot and sending some simple commands.
Basic steps:
1. add the imports
2. create a Class (in this case named "MyClass").
3. create a method named "on_connect" which accepts self and a robot parameter.
eg on_connect(self, robot).
This will be called when the program connects to a robot.
4. kick things off my passing an instance of your Class to WonderPy.wwMain.start():
WonderPy.wwMain.start(MyClass())
5. Try it! Your on_connect method should be called.
6. on_connect() itself should not block - ie, it should return control as soon as possible.
However, on_connect() can launch some asynchronous processes, which can block.
So do that. In this example we spawn a thread on method thread_hello().
7. In the thread, try out some robot commands!
* Commands of the flavour "stage_foo()" simply send the command to the robot and return.
ie, they do not block.
* Commands of the flavour "do_foo()" send the commands and block until the command completes.
"""
class MyClass(object):
def on_connect(self, robot):
"""
Called when we connect to a robot. This method is optional. Do not Block in this method !
"""
print("Starting a thread for %s." % (robot.name))
Thread(target=self.thread_hello, args=(robot,)).start()
def thread_hello(self, robot):
"""
:param robot: WWRobot
"""
# dictionary mapping robot types to a few sounds for that robot
hello_sounds = {
WWRobotConstants.RobotType.WW_ROBOT_DASH : [WWMedia.WWSound.WWSoundDash.HOWDY,
WWMedia.WWSound.WWSoundDash.HOWSGOING ],
WWRobotConstants.RobotType.WW_ROBOT_DOT : [WWMedia.WWSound.WWSoundDot .HOWDY,
WWMedia.WWSound.WWSoundDot .HOLD_ME ],
WWRobotConstants.RobotType.WW_ROBOT_CUE : [WWMedia.WWSound.WWSoundCue .zest_HEYWHSU,
WWMedia.WWSound.WWSoundCue .charge_BORESTNOC],
}
if robot.robot_type not in hello_sounds:
raise ValueError("unhandled robot type: %s on %s" % (str(robot.robot_type), robot.name))
for sound_name in hello_sounds[robot.robot_type]:
print("On %s, setting all RGB lights to white." % (robot.name))
robot.cmds.RGB.stage_all(1, 1, 1)
print("On %s, playing '%s'." % (robot.name, sound_name))
robot.cmds.media.do_audio(sound_name)
print("On %s, setting all RGB lights to off." % (robot.name))
robot.cmds.RGB.stage_all(0, 0, 0)
print("Waiting a little bit.")
time.sleep(1)
print("That's all for now.")
# kick off the program !
if __name__ == "__main__":
WonderPy.core.wwMain.start(MyClass())
Robot Connection Options
Upon launching any of the examples, the app will scan for robots for at least 5 and at most 20 seconds. After scanning, whichever robot had the highest signal strength (RSSI) will be connected to. This is a reasonable approximation of connecting to the closest robot.
Connection Options:
[--connect-type cue | dot | dash]
filter for robots of the specified type/s
[--connect-name MY_ROBOT | MY_OTHER_ROBOT | ...]
filter for robots with the specified name/s
[--connect-eager]
connect as soon as a qualified robot is discovered.
do not wait the full scanning period.
if there are more than one robot with matching criteria,
the one with the best signal is still selected
[--connect-ask]
show a list of available robots, and interactively ask for input.
indicates which has the highest signal strength.
Connection Examples:
-
Spend 5 seconds looking for all Cue and Dash robots which are named either "sammy" or "sally", and connect to the one with the best signal strength:
python demos/roboFun.py --connect-type cue dash --connect-name sammy blippy sally
-
Connect ASAP to any robot named 'orions robot', no matter what type of robot it is.
python demos/roboFun.py --connect-eager --connect-name "orions robot"
Documentation
Documentation is still also in Alpha stage, but some basics of working with the robot are here.
Contribute
Please check the list of issues and todo's at the WonderPy repository on github.
Pull-Requests are welcome.
Feature requests for the API should also be sent as a new Issue in github.
Get Help
Report Bugs
If there's a specific bug or problem with the API, please check the outstanding issues in github and if it's not already covered, create a new one.
Ask for Advice
If you have a more general question such as "how would I approach doing .." or you have a tip you'd like to share, please visit stackoverflow and be sure to tag your post with wonderworkshop.
Sharing your work ?
Got a great picture or video ?
If you're sharing your Dash, Dot or Cue work on Twitter or Instagram, remember to tag @WonderWorkshop !
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Hashes for WonderPy-0.0.12-py2-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | b4868f760d15a269eed2756dd77e920b8588b0d29aa80037f40ffdbd075683e8 |
|
MD5 | 17c9484ed9c12e889868589464d7695e |
|
BLAKE2b-256 | 5d86d6c375ab795698836b1cd032e30e573d6a9c94bf30d458e6232342e53df6 |