Remove .coffee examples and WIP on converting .litcoffee to .markdown + js
This commit is contained in:
parent
4c647db88f
commit
e7a340fd0c
|
@ -1,28 +0,0 @@
|
||||||
Cylon = require '../..'
|
|
||||||
|
|
||||||
Cylon.api host: '0.0.0.0', port: '8080'
|
|
||||||
|
|
||||||
bots = [
|
|
||||||
{ port: '/dev/rfcomm0', name: 'Thelma' },
|
|
||||||
{ port: '/dev/rfcomm1', name: 'Louise' }
|
|
||||||
]
|
|
||||||
|
|
||||||
SpheroRobot =
|
|
||||||
connection: { name: 'Sphero', adaptor: 'sphero' }
|
|
||||||
|
|
||||||
device: { name: 'sphero', driver: 'sphero' }
|
|
||||||
|
|
||||||
work: (my) ->
|
|
||||||
every 1.seconds(), ->
|
|
||||||
console.log my.name
|
|
||||||
my.sphero.setRGB Math.floor(Math.random() * 100000)
|
|
||||||
my.sphero.roll 60, Math.floor(Math.random() * 360)
|
|
||||||
|
|
||||||
for bot in bots
|
|
||||||
robot = Object.create SpheroRobot
|
|
||||||
robot.connection.port = bot.port
|
|
||||||
robot.name = bot.name
|
|
||||||
|
|
||||||
Cylon.robot robot
|
|
||||||
|
|
||||||
Cylon.start()
|
|
|
@ -8,64 +8,69 @@ This example involves two Spheros, so before you start make sure you have the
|
||||||
|
|
||||||
First, let's import Cylon:
|
First, let's import Cylon:
|
||||||
|
|
||||||
Cylon = require '../..'
|
Cylon = require('../..');
|
||||||
|
|
||||||
Next up, we'll configure the API Cylon will serve, telling it to serve on port
|
Next up, we'll configure the API Cylon will serve, telling it to serve on port
|
||||||
`8080`.
|
`8080`.
|
||||||
|
|
||||||
Cylon.api host: '0.0.0.0', port: '8080'
|
Cylon.api({host: '0.0.0.0', port: '8080'});
|
||||||
|
|
||||||
Since we're making two very similar robots (Spheros, in this case), let's put
|
Since we're making two very similar robots (Spheros, in this case), let's put
|
||||||
the different parts of each robot in objects so we can initialize them later.
|
the different parts of each robot in objects so we can initialize them later.
|
||||||
The only differences between the bots are their names and the port they'll be
|
The only differences between the bots are their names and the port they'll be
|
||||||
using.
|
using.
|
||||||
|
|
||||||
bots = [
|
var bots = [
|
||||||
{ port: '/dev/rfcomm0', name: 'Thelma' },
|
{ port: '/dev/rfcomm0', name: 'Thelma' },
|
||||||
{ port: '/dev/rfcomm1', name: 'Louise' }
|
{ port: '/dev/rfcomm1', name: 'Louise' }
|
||||||
]
|
];
|
||||||
|
|
||||||
Now we can define the basic robot both of our Sphero robots will be based on.
|
Now we can define the basic robot both of our Sphero robots will be based on.
|
||||||
|
|
||||||
SpheroRobot =
|
var SpheroRobot = {
|
||||||
|
|
||||||
Both robots will be connecting to Spheros, and so using the cylon-sphero
|
Both robots will be connecting to Spheros, and so using the cylon-sphero
|
||||||
adaptor:
|
adaptor:
|
||||||
|
|
||||||
connection: { name: 'Sphero', adaptor: 'sphero' }
|
connection: { name: 'Sphero', adaptor: 'sphero' },
|
||||||
|
|
||||||
And both will be connecting to the same kind of device (you guessed it,
|
And both will be connecting to the same kind of device (you guessed it,
|
||||||
a Sphero).
|
a Sphero).
|
||||||
|
|
||||||
|
device: { name: 'sphero', driver: 'sphero' },
|
||||||
device: { name: 'sphero', driver: 'sphero' }
|
|
||||||
|
|
||||||
Both robots will be performing the same kind of work as well. Every second,
|
Both robots will be performing the same kind of work as well. Every second,
|
||||||
they'll print their name to the console, set themselves to a random color, and
|
they'll print their name to the console, set themselves to a random color, and
|
||||||
roll in a random direction.
|
roll in a random direction.
|
||||||
|
|
||||||
work: (my) ->
|
work: function(my) {
|
||||||
every 1.seconds(), ->
|
every((1).seconds(), function() {
|
||||||
console.log my.name
|
console.log(my.name);
|
||||||
my.sphero.setRandomColor()
|
my.sphero.setRandomColor();
|
||||||
my.sphero.roll 60, Math.floor(Math.random() * 360)
|
my.sphero.roll(60, Math.floor(Math.random() * 360));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Now that we know what hardware the robots have and what work they'll be doing,
|
Now that we know what hardware the robots have and what work they'll be doing,
|
||||||
let's create them! We'll iterate through our earlier `bots` array, creating
|
let's create them! We'll iterate through our earlier `bots` array, creating
|
||||||
a new Robot, assigning it it's unique characteristics, then passing it off to
|
a new Robot, assigning it it's unique characteristics, then passing it off to
|
||||||
Cylon so it can keep track of it.
|
Cylon so it can keep track of it.
|
||||||
|
|
||||||
for bot in bots
|
for (var i = 0; i < bots.length; i++) {
|
||||||
robot = Object.create SpheroRobot
|
var bot = bots[i];
|
||||||
robot.connection.port = bot.port
|
var robot = Object.create(SpheroRobot);
|
||||||
robot.name = bot.name
|
|
||||||
|
|
||||||
Cylon.robot robot
|
robot.connection.port = bot.port;
|
||||||
|
robot.name = bot.name;
|
||||||
|
|
||||||
|
Cylon.robot(robot);
|
||||||
|
}
|
||||||
|
|
||||||
And now that Cylon has all the robots we're intending to give it, let's get
|
And now that Cylon has all the robots we're intending to give it, let's get
|
||||||
started!
|
started!
|
||||||
|
|
||||||
Cylon.start()
|
Cylon.start();
|
||||||
|
|
||||||
Now Cylon will start up the robots and their devices, as well as an API server
|
Now Cylon will start up the robots and their devices, as well as an API server
|
||||||
listening on `0.0.0.0:8080`.
|
listening on `0.0.0.0:8080`.
|
|
@ -1,29 +0,0 @@
|
||||||
Cylon = require '../..'
|
|
||||||
|
|
||||||
Cylon.robot
|
|
||||||
connections: [
|
|
||||||
{name: 'digispark', adaptor: 'digispark'},
|
|
||||||
{name: 'leapmotion', adaptor: 'leapmotion', port: '127.0.0.1:6437'}
|
|
||||||
]
|
|
||||||
|
|
||||||
devices: [
|
|
||||||
{name: 'servo1', driver: 'servo', pin: 0, connection: 'digispark'},
|
|
||||||
{name: 'servo2', driver: 'servo', pin: 1, connection: 'digispark'},
|
|
||||||
{name: 'leapmotion', driver: 'leapmotion', connection: 'leapmotion'}
|
|
||||||
]
|
|
||||||
|
|
||||||
work: (my) ->
|
|
||||||
my['x'] = 90
|
|
||||||
my['z'] = 90
|
|
||||||
|
|
||||||
my.leapmotion.on 'hand', (hand) ->
|
|
||||||
my['x'] = hand.palmX.fromScale(-300, 300).toScale(30, 150)
|
|
||||||
my['z'] = hand.palmZ.fromScale(-300, 300).toScale(30, 150)
|
|
||||||
|
|
||||||
every 100, ->
|
|
||||||
my.servo1.angle my['x']
|
|
||||||
my.servo2.angle my['z']
|
|
||||||
|
|
||||||
console.log "Current Angle: #{my.servo1.currentAngle()}, #{my.servo2.currentAngle()}"
|
|
||||||
|
|
||||||
.start()
|
|
|
@ -2,43 +2,45 @@
|
||||||
|
|
||||||
First, let's import Cylon:
|
First, let's import Cylon:
|
||||||
|
|
||||||
Cylon = require '../..'
|
var Cylon = require('../..');
|
||||||
|
|
||||||
Now that we have Cylon imported, we can start defining our robot
|
Now that we have Cylon imported, we can start defining our robot
|
||||||
|
|
||||||
Cylon.robot
|
Cylon.robot({
|
||||||
|
|
||||||
Let's define the connections and devices:
|
Let's define the connections and devices:
|
||||||
|
|
||||||
connections: [
|
connections: [
|
||||||
{name: 'digispark', adaptor: 'digispark'},
|
{ name: 'digispark', adaptor: 'digispark'},
|
||||||
{name: 'leapmotion', adaptor: 'leapmotion', port: '127.0.0.1:6437'}
|
{ name: 'leapmotion', adaptor: 'leapmotion', port: '127.0.0.1:6437' }
|
||||||
]
|
],
|
||||||
|
|
||||||
devices: [
|
devices: [
|
||||||
{name: 'servo1', driver: 'servo', pin: 0, connection: 'digispark'},
|
{name: 'servo1', driver: 'servo', pin: 0, connection: 'digispark'},
|
||||||
{name: 'servo2', driver: 'servo', pin: 1, connection: 'digispark'},
|
{name: 'servo2', driver: 'servo', pin: 1, connection: 'digispark'},
|
||||||
{name: 'leapmotion', driver: 'leapmotion', connection: 'leapmotion'}
|
{name: 'leapmotion', driver: 'leapmotion', connection: 'leapmotion'}
|
||||||
]
|
],
|
||||||
|
|
||||||
Now that Cylon knows about the necessary hardware we're going to be using, we'll
|
Now that Cylon knows about the necessary hardware we're going to be using, we'll
|
||||||
tell it what work we want to do:
|
tell it what work we want to do:
|
||||||
|
|
||||||
work: (my) ->
|
work: function(my) {
|
||||||
my['x'] = 90
|
my['x'] = 90;
|
||||||
my['z'] = 90
|
my['z'] = 90;
|
||||||
|
|
||||||
my.leapmotion.on 'hand', (hand) ->
|
my.leapmotion.on('hand', function(hand) {
|
||||||
my['x'] = hand.palmX.fromScale(-300, 300).toScale(30, 150)
|
my['x'] = hand.palmX.fromScale(-300, 300).toScale(30, 150);
|
||||||
my['z'] = hand.palmZ.fromScale(-300, 300).toScale(30, 150)
|
my['z'] = hand.palmZ.fromScale(-300, 300).toScale(30, 150);
|
||||||
|
});
|
||||||
|
|
||||||
every 100, ->
|
every(100, function() {
|
||||||
my.servo1.angle my['x']
|
my.servo1.angle(my['x']);
|
||||||
my.servo2.angle my['z']
|
my.servo2.angle(my['z']);
|
||||||
|
|
||||||
console.log "Current Angle: #{my.servo1.currentAngle()}, #{my.servo2.currentAngle()}"
|
console.log("Current Angle: " + my.servo1.currentAngle() + ", " + my.servo2.currentAngle());
|
||||||
|
});
|
||||||
|
|
||||||
Now that our robot knows what work to do, and the work it will be doing that
|
Now that our robot knows what work to do, and the work it will be doing that
|
||||||
hardware with, we can start it:
|
hardware with, we can start it:
|
||||||
|
|
||||||
.start()
|
}).start()
|
|
@ -1,68 +0,0 @@
|
||||||
Cylon = require '../..'
|
|
||||||
|
|
||||||
bots = [
|
|
||||||
{ port: '/dev/rfcomm0', name: 'Thelma' }
|
|
||||||
{ port: '/dev/rfcomm1', name: 'Louise' },
|
|
||||||
{ port: '/dev/rfcomm2', name: 'Grace' },
|
|
||||||
{ port: '/dev/rfcomm3', name: 'Ada' }
|
|
||||||
]
|
|
||||||
|
|
||||||
Green = 0x0000FF
|
|
||||||
Red = 0xFF0000
|
|
||||||
|
|
||||||
class ConwayRobot
|
|
||||||
connection: { name: 'Sphero', adaptor: 'sphero' }
|
|
||||||
device: { name: 'sphero', driver: 'sphero' }
|
|
||||||
|
|
||||||
born: ->
|
|
||||||
@contacts = 0
|
|
||||||
@age = 0
|
|
||||||
@life()
|
|
||||||
@move()
|
|
||||||
|
|
||||||
move: ->
|
|
||||||
@sphero.roll 60, Math.floor(Math.random() * 360)
|
|
||||||
|
|
||||||
life: ->
|
|
||||||
@alive = true
|
|
||||||
@sphero.setRGB Green
|
|
||||||
|
|
||||||
death: ->
|
|
||||||
@alive = false
|
|
||||||
@sphero.setRGB Red
|
|
||||||
@sphero.stop()
|
|
||||||
|
|
||||||
enoughContacts: ->
|
|
||||||
if @contacts >= 2 and @contacts < 7 then true else false
|
|
||||||
|
|
||||||
birthday: ->
|
|
||||||
@age += 1
|
|
||||||
|
|
||||||
console.log "Happy birthday, #{@name}. You are #{@age} and had #{@contacts} contacts."
|
|
||||||
|
|
||||||
if @enoughContacts()
|
|
||||||
@rebirth() if not @alive?
|
|
||||||
else
|
|
||||||
@death()
|
|
||||||
|
|
||||||
@contacts = 0
|
|
||||||
|
|
||||||
work: (me) ->
|
|
||||||
me.born()
|
|
||||||
|
|
||||||
me.sphero.on 'collision', ->
|
|
||||||
@contacts += 1
|
|
||||||
|
|
||||||
every 3.seconds(), ->
|
|
||||||
me.move() if me.alive?
|
|
||||||
|
|
||||||
every 10.seconds(), ->
|
|
||||||
me.birthday() if me.alive?
|
|
||||||
|
|
||||||
for bot in bots
|
|
||||||
robot = new ConwayRobot
|
|
||||||
robot.connection.port = bot.port
|
|
||||||
robot.name = bot.name
|
|
||||||
Cylon.robot robot
|
|
||||||
|
|
||||||
Cylon.start()
|
|
|
@ -1,5 +1,3 @@
|
||||||
var ConwayRobot, Cylon, Green, Red, bot, bots, robot, _i, _len;
|
|
||||||
|
|
||||||
var Cylon = require('../..');
|
var Cylon = require('../..');
|
||||||
|
|
||||||
var bots = [
|
var bots = [
|
||||||
|
@ -22,30 +20,26 @@ var ConwayRobot = (function() {
|
||||||
this.contacts = 0;
|
this.contacts = 0;
|
||||||
this.age = 0;
|
this.age = 0;
|
||||||
this.life();
|
this.life();
|
||||||
return this.move();
|
this.move();
|
||||||
};
|
};
|
||||||
|
|
||||||
ConwayRobot.prototype.move = function() {
|
ConwayRobot.prototype.move = function() {
|
||||||
return this.sphero.roll(60, Math.floor(Math.random() * 360));
|
this.sphero.roll(60, Math.floor(Math.random() * 360));
|
||||||
};
|
};
|
||||||
|
|
||||||
ConwayRobot.prototype.life = function() {
|
ConwayRobot.prototype.life = function() {
|
||||||
this.alive = true;
|
this.alive = true;
|
||||||
return this.sphero.setRGB(Green);
|
this.sphero.setRGB(Green);
|
||||||
};
|
};
|
||||||
|
|
||||||
ConwayRobot.prototype.death = function() {
|
ConwayRobot.prototype.death = function() {
|
||||||
this.alive = false;
|
this.alive = false;
|
||||||
this.sphero.setRGB(Red);
|
this.sphero.setRGB(Red);
|
||||||
return this.sphero.stop();
|
this.sphero.stop();
|
||||||
};
|
};
|
||||||
|
|
||||||
ConwayRobot.prototype.enoughContacts = function() {
|
ConwayRobot.prototype.enoughContacts = function() {
|
||||||
if (this.contacts >= 2 && this.contacts < 7) {
|
return (this.contacts >= 2 && this.contacts < 7);
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ConwayRobot.prototype.birthday = function() {
|
ConwayRobot.prototype.birthday = function() {
|
||||||
|
@ -58,22 +52,23 @@ var ConwayRobot = (function() {
|
||||||
} else {
|
} else {
|
||||||
this.death();
|
this.death();
|
||||||
}
|
}
|
||||||
return this.contacts = 0;
|
|
||||||
|
this.contacts = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
ConwayRobot.prototype.work = function(me) {
|
ConwayRobot.prototype.work = function(me) {
|
||||||
me.born();
|
me.born();
|
||||||
|
|
||||||
me.sphero.on('collision', function() {
|
me.sphero.on('collision', function() {
|
||||||
return this.contacts += 1;
|
this.contacts += 1;
|
||||||
});
|
});
|
||||||
|
|
||||||
every((3).seconds(), function() {
|
every((3).seconds(), function() {
|
||||||
if (me.alive != null) { return me.move(); }
|
if (me.alive != null) { me.move(); }
|
||||||
});
|
});
|
||||||
|
|
||||||
return every((10).seconds(), function() {
|
every((10).seconds(), function() {
|
||||||
if (me.alive != null) { return me.birthday(); }
|
if (me.alive != null) { me.birthday(); }
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -24,25 +24,25 @@ start, make sure you have the `cylon-sphero` module installed.
|
||||||
|
|
||||||
First off, let's load up Cylon:
|
First off, let's load up Cylon:
|
||||||
|
|
||||||
Cylon = require '../..'
|
var Cylon = require('../..');
|
||||||
|
|
||||||
We'll be using four robots for this example, but they'll have very similar
|
We'll be using four robots for this example, but they'll have very similar
|
||||||
programming so we just need to define what's different between them for now.
|
programming so we just need to define what's different between them for now.
|
||||||
Each of the robots will have a unique name, and will communicate on their own
|
Each of the robots will have a unique name, and will communicate on their own
|
||||||
port.
|
port.
|
||||||
|
|
||||||
bots = [
|
var bots = [
|
||||||
{ port: '/dev/rfcomm0', name: 'Thelma' }
|
{ port: '/dev/rfcomm0', name: 'Thelma' },
|
||||||
{ port: '/dev/rfcomm1', name: 'Louise' },
|
{ port: '/dev/rfcomm1', name: 'Louise' },
|
||||||
{ port: '/dev/rfcomm2', name: 'Grace' },
|
{ port: '/dev/rfcomm2', name: 'Grace' },
|
||||||
{ port: '/dev/rfcomm3', name: 'Ada' }
|
{ port: '/dev/rfcomm3', name: 'Ada' }
|
||||||
]
|
];
|
||||||
|
|
||||||
For easier use later, let's define the colors we'll be using with the Spheros,
|
For easier use later, let's define the colors we'll be using with the Spheros,
|
||||||
green for alive and red for dead:
|
green for alive and red for dead:
|
||||||
|
|
||||||
Green = 0x0000FF
|
var Green = 0x0000FF;
|
||||||
Red = 0xFF0000
|
var Red = 0xFF0000;
|
||||||
|
|
||||||
That gets the basics out of the way.
|
That gets the basics out of the way.
|
||||||
|
|
||||||
|
@ -50,82 +50,97 @@ Since, as previously mentioned, our robots all have the same basic
|
||||||
functionality, we can define that functionality in a CoffeeScript class. Since
|
functionality, we can define that functionality in a CoffeeScript class. Since
|
||||||
we're feeling particularly creative today, let's call this class `ConwayRobot`:
|
we're feeling particularly creative today, let's call this class `ConwayRobot`:
|
||||||
|
|
||||||
class ConwayRobot
|
var ConwayRobot = (function() {
|
||||||
|
function ConwayRobot() {}
|
||||||
|
|
||||||
All of our robots will be connecting to a Sphero, and be operating via a single
|
All of our robots will be connecting to a Sphero, and be operating via a single
|
||||||
device (you guessed it, a Sphero).
|
device (you guessed it, a Sphero).
|
||||||
|
|
||||||
connection: { name: 'Sphero', adaptor: 'sphero' }
|
ConwayRobot.prototype.connection = { name: 'Sphero', adaptor: 'sphero' };
|
||||||
device: { name: 'sphero', driver: 'sphero' }
|
ConwayRobot.prototype.device = { name: 'sphero', driver: 'sphero' };
|
||||||
|
|
||||||
When the robots are first started, they are born. This sets their contacts to
|
When the robots are first started, they are born. This sets their contacts to
|
||||||
zero, their age to zero, makes them "alive", and starts them moving for the
|
zero, their age to zero, makes them "alive", and starts them moving for the
|
||||||
first tick.
|
first tick.
|
||||||
|
|
||||||
born: ->
|
ConwayRobot.prototype.born = function() {
|
||||||
@contacts = 0
|
this.contacts = 0;
|
||||||
@age = 0
|
this.age = 0;
|
||||||
@life()
|
this.life();
|
||||||
@move()
|
this.move();
|
||||||
|
};
|
||||||
|
|
||||||
When a robot is asked to move, it rolls in a random direction at speed 60.
|
When a robot is asked to move, it rolls in a random direction at speed 60.
|
||||||
|
|
||||||
move: ->
|
ConwayRobot.prototype.move = function() {
|
||||||
@sphero.roll 60, Math.floor(Math.random() * 360)
|
this.sphero.roll(60, Math.floor(Math.random() * 360));
|
||||||
|
};
|
||||||
|
|
||||||
In the case of our robots, "life" just means the robot's internal "alive" state
|
In the case of our robots, "life" just means the robot's internal "alive" state
|
||||||
is set to `true`, and the Sphero's LED is set to green.
|
is set to `true`, and the Sphero's LED is set to green.
|
||||||
|
|
||||||
life: ->
|
ConwayRobot.prototype.life = function() {
|
||||||
@alive = true
|
this.alive = true;
|
||||||
@sphero.setRGB Green
|
this.sphero.setRGB(Green);
|
||||||
|
};
|
||||||
|
|
||||||
Similarly, "death" just sets the "alive" state to false, the Sphero's color to
|
Similarly, "death" just sets the "alive" state to false, the Sphero's color to
|
||||||
red, and stops the Sphero from moving.
|
red, and stops the Sphero from moving.
|
||||||
|
|
||||||
death: ->
|
ConwayRobot.prototype.death = function() {
|
||||||
@alive = false
|
this.alive = false;
|
||||||
@sphero.setRGB Red
|
this.sphero.setRGB(Red);
|
||||||
@sphero.stop()
|
this.sphero.stop();
|
||||||
|
};
|
||||||
|
|
||||||
A robot is decided to have enough contacts if it has between two and six
|
A robot is decided to have enough contacts if it has between two and six
|
||||||
contacts.
|
contacts.
|
||||||
|
|
||||||
enoughContacts: ->
|
ConwayRobot.prototype.enoughContacts = function() {
|
||||||
if @contacts >= 2 and @contacts < 7 then true else false
|
return (this.contacts >= 2 && this.contacts < 7);
|
||||||
|
};
|
||||||
|
|
||||||
On a robot's birthday, it increments it's age, prints it's name, age, and
|
On a robot's birthday, it increments it's age, prints it's name, age, and
|
||||||
contacts to the console, and then determines if it's now alive or dead based on
|
contacts to the console, and then determines if it's now alive or dead based on
|
||||||
the number of contacts it had in the last tick.
|
the number of contacts it had in the last tick.
|
||||||
|
|
||||||
birthday: ->
|
ConwayRobot.prototype.birthday = function() {
|
||||||
@age += 1
|
this.age += 1;
|
||||||
|
|
||||||
console.log "Happy birthday, #{@name}. You are #{@age} and had #{@contacts} contacts."
|
console.log("Happy birthday, " + this.name + ". You are " + this.age + " and had " + this.contacts + " contacts.");
|
||||||
|
|
||||||
if @enoughContacts()
|
if (this.enoughContacts()) {
|
||||||
@rebirth() if not @alive?
|
if (this.alive == null) { this.rebirth(); }
|
||||||
else
|
} else {
|
||||||
@death()
|
this.death();
|
||||||
|
}
|
||||||
|
|
||||||
@contacts = 0
|
this.contacts = 0;
|
||||||
|
};
|
||||||
|
|
||||||
Now that the pieces are there, we can set up our robot's work. It starts by
|
Now that the pieces are there, we can set up our robot's work. It starts by
|
||||||
being "born", then moves every three seconds if it's alive, celebrates it's
|
being "born", then moves every three seconds if it's alive, celebrates it's
|
||||||
birthday every ten seconds if it's alive, and increments it's contacts every
|
birthday every ten seconds if it's alive, and increments it's contacts every
|
||||||
time the Sphero detects a collision.
|
time the Sphero detects a collision.
|
||||||
|
|
||||||
work: (me) ->
|
ConwayRobot.prototype.work = function(me) {
|
||||||
me.born()
|
me.born();
|
||||||
|
|
||||||
me.sphero.on 'collision', ->
|
me.sphero.on('collision', function() {
|
||||||
@contacts += 1
|
this.contacts += 1;
|
||||||
|
});
|
||||||
|
|
||||||
every 3.seconds(), ->
|
every((3).seconds(), function() {
|
||||||
me.move() if me.alive?
|
if (me.alive != null) { me.move(); }
|
||||||
|
});
|
||||||
|
|
||||||
every 10.seconds(), ->
|
every((10).seconds(), function() {
|
||||||
me.birthday() if me.alive?
|
if (me.alive != null) { me.birthday(); }
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return ConwayRobot;
|
||||||
|
})();
|
||||||
|
|
||||||
Now that we've defined the behaviour of our Conway's Game robots, we can make
|
Now that we've defined the behaviour of our Conway's Game robots, we can make
|
||||||
the robots themselves.
|
the robots themselves.
|
||||||
|
@ -134,12 +149,16 @@ For each of the sets of unique characteristics in the earlier `bots` array,
|
||||||
we'll create a new `ConwayRobot`, assign it it's unique characteristics, and
|
we'll create a new `ConwayRobot`, assign it it's unique characteristics, and
|
||||||
pass it to Cylon so it will keep track of them.
|
pass it to Cylon so it will keep track of them.
|
||||||
|
|
||||||
for bot in bots
|
for (var i = 0; i < bots.length; i++) {
|
||||||
robot = new ConwayRobot
|
var bot = bots[i];
|
||||||
robot.connection.port = bot.port
|
var robot = new ConwayRobot;
|
||||||
robot.name = bot.name
|
|
||||||
Cylon.robot robot
|
robot.connection.port = bot.port;
|
||||||
|
robot.name = bot.name;
|
||||||
|
|
||||||
|
Cylon.robot(robot);
|
||||||
|
}
|
||||||
|
|
||||||
Now that Cylon knows about our robots and what they do, we can get started!
|
Now that Cylon knows about our robots and what they do, we can get started!
|
||||||
|
|
||||||
Cylon.start()
|
Cylon.start();
|
|
@ -1,16 +0,0 @@
|
||||||
Cylon = require '../..'
|
|
||||||
|
|
||||||
Cylon.robot
|
|
||||||
connection:
|
|
||||||
name: 'crazyflie', adaptor: 'crazyflie', port: "radio://1/10/250KPS"
|
|
||||||
|
|
||||||
device:
|
|
||||||
name: 'drone', driver: 'crazyflie'
|
|
||||||
|
|
||||||
work: (my) ->
|
|
||||||
my.drone.on 'start', ->
|
|
||||||
my.drone.takeoff()
|
|
||||||
after 10.seconds(), -> my.drone.land()
|
|
||||||
after 15.seconds(), -> my.drone.stop()
|
|
||||||
|
|
||||||
.start()
|
|
|
@ -1,13 +0,0 @@
|
||||||
Cylon = require '../..'
|
|
||||||
|
|
||||||
# Initialize the robot
|
|
||||||
Cylon.robot
|
|
||||||
connection: { name: 'digispark', adaptor: 'digispark'}
|
|
||||||
|
|
||||||
device: { name: 'led', driver: 'led', pin: 1 }
|
|
||||||
|
|
||||||
work: (my) ->
|
|
||||||
|
|
||||||
every 1.second(), -> my.led.toggle()
|
|
||||||
|
|
||||||
.start()
|
|
|
@ -1,11 +0,0 @@
|
||||||
Cylon = require '../..'
|
|
||||||
|
|
||||||
Cylon.robot
|
|
||||||
work: ->
|
|
||||||
every 1.second(), ->
|
|
||||||
console.log("Hello, human!")
|
|
||||||
|
|
||||||
after 10.seconds(), ->
|
|
||||||
console.log "Impressive."
|
|
||||||
|
|
||||||
.start()
|
|
|
@ -1,10 +0,0 @@
|
||||||
Cylon = require '../..'
|
|
||||||
|
|
||||||
Cylon.robot
|
|
||||||
device: { name: 'keyboard', driver: 'keyboard' }
|
|
||||||
connection: { name: 'keyboard', adaptor: 'keyboard' }
|
|
||||||
work: (my) ->
|
|
||||||
my.keyboard.on 'a', (key) ->
|
|
||||||
console.log "A PRESSED!"
|
|
||||||
|
|
||||||
.start()
|
|
|
@ -1,18 +0,0 @@
|
||||||
Cylon = require '../..'
|
|
||||||
|
|
||||||
Cylon.robot
|
|
||||||
connections: [
|
|
||||||
{ name: 'leapmotion', adaptor: 'leapmotion', port: '127.0.0.1:6437' },
|
|
||||||
{ name: 'arduino', adaptor: 'firmata', port: '/dev/ttyACM0' }
|
|
||||||
]
|
|
||||||
|
|
||||||
devices: [
|
|
||||||
{ name: 'leapmotion', driver: 'leapmotion', connection: 'leapmotion' },
|
|
||||||
{ name: 'led', driver: 'led', pin: 13, connection: 'arduino' }
|
|
||||||
]
|
|
||||||
|
|
||||||
work: (my) ->
|
|
||||||
my.leapmotion.on 'frame', (frame) ->
|
|
||||||
if (frame.hands.length > 0) then my.led.turnOn() else my.led.turnOff()
|
|
||||||
|
|
||||||
.start()
|
|
|
@ -1,27 +0,0 @@
|
||||||
Cylon = require '../..'
|
|
||||||
|
|
||||||
Cylon.robot
|
|
||||||
connections: [
|
|
||||||
{ name: 'leapmotion', adaptor: 'leapmotion', port: '127.0.0.1:6437' },
|
|
||||||
{ name: 'skynet', adaptor: 'skynet', uuid: "0675b9d1-9b7e-11e3-af21-030ff142869f", token: "yr2oi19yyspmbo6rcgkp7gov5i2j4i" },
|
|
||||||
]
|
|
||||||
|
|
||||||
device:
|
|
||||||
{ name: 'leapmotion', driver: 'leapmotion', connection: 'leapmotion' }
|
|
||||||
|
|
||||||
led: (status) ->
|
|
||||||
console.log status
|
|
||||||
this.skynet.message
|
|
||||||
"devices": ["742401f1-87a4-11e3-834d-670dadc0ddbf"],
|
|
||||||
"message":
|
|
||||||
'red': status
|
|
||||||
|
|
||||||
work: (my) ->
|
|
||||||
my.leapmotion.on 'frame', (frame) ->
|
|
||||||
if frame.hands.length > 0
|
|
||||||
my.led 'on'
|
|
||||||
|
|
||||||
else
|
|
||||||
my.led 'off'
|
|
||||||
|
|
||||||
.start()
|
|
|
@ -1,22 +0,0 @@
|
||||||
Cylon = require '../..'
|
|
||||||
|
|
||||||
bots = [
|
|
||||||
{ port: '/dev/cu.Sphero-RGB', name: 'Huey' },
|
|
||||||
{ port: '/dev/cu.Sphero-GRB', name: 'Dewey' },
|
|
||||||
{ port: '/dev/cu.Sphero-BRG', name: 'Louie' }
|
|
||||||
]
|
|
||||||
|
|
||||||
class SpheroRobot
|
|
||||||
connection: { name: 'Sphero', adaptor: 'sphero' }
|
|
||||||
|
|
||||||
work: (my) ->
|
|
||||||
console.log "Robot #{my.name} is now working!"
|
|
||||||
|
|
||||||
for bot in bots
|
|
||||||
robot = new SpheroRobot
|
|
||||||
robot.connection.port = bot.port
|
|
||||||
robot.name = bot.name
|
|
||||||
|
|
||||||
Cylon.robot robot
|
|
||||||
|
|
||||||
Cylon.start()
|
|
|
@ -1,19 +0,0 @@
|
||||||
Cylon = require '../..'
|
|
||||||
|
|
||||||
Cylon.api host: '0.0.0.0', port: '8080'
|
|
||||||
|
|
||||||
class MyRobot
|
|
||||||
commands: ["relax"]
|
|
||||||
|
|
||||||
relax: ->
|
|
||||||
"#{this.name} says relax"
|
|
||||||
|
|
||||||
work: (me) ->
|
|
||||||
every 1.seconds(), ->
|
|
||||||
console.log me.name
|
|
||||||
|
|
||||||
robot = new MyRobot
|
|
||||||
robot.name = "frankie"
|
|
||||||
Cylon.robot robot
|
|
||||||
|
|
||||||
Cylon.start()
|
|
|
@ -1,31 +0,0 @@
|
||||||
Cylon = require '../..'
|
|
||||||
|
|
||||||
Cylon.robot
|
|
||||||
connection:
|
|
||||||
name: 'sfcon'
|
|
||||||
adaptor: 'force'
|
|
||||||
sfuser: process.env.SF_USERNAME
|
|
||||||
sfpass: process.env.SF_SECURITY_TOKEN
|
|
||||||
orgCreds:
|
|
||||||
clientId: process.env.SF_CLIENT_ID
|
|
||||||
clientSecret: process.env.SF_CLIENT_SECRET
|
|
||||||
redirectUri: 'http://localhost:3000/oauth/_callback'
|
|
||||||
|
|
||||||
device: { name: 'salesforce', driver: 'force' }
|
|
||||||
|
|
||||||
work: (me) ->
|
|
||||||
me.salesforce.on 'start', () ->
|
|
||||||
me.salesforce.subscribe '/topic/SpheroMsgOutbound', (data) ->
|
|
||||||
msg = "Sphero: #{data.sobject.Sphero_Name__c},"
|
|
||||||
msg += "Bucks: #{data.sobject.Bucks__c},"
|
|
||||||
msg += "SM_Id: #{data.sobject.Id}"
|
|
||||||
|
|
||||||
console.log msg
|
|
||||||
|
|
||||||
i = 0
|
|
||||||
|
|
||||||
every 2.seconds(), () ->
|
|
||||||
data = JSON.stringify { spheroName: "#{me.name}", bucks: "#{i}" }
|
|
||||||
me.salesforce.push 'SpheroController', 'POST', data
|
|
||||||
|
|
||||||
.start()
|
|
|
@ -1,67 +0,0 @@
|
||||||
Cylon = require '../..'
|
|
||||||
|
|
||||||
class SalesforceRobot
|
|
||||||
connection:
|
|
||||||
name: 'sfcon'
|
|
||||||
adaptor: 'force'
|
|
||||||
sfuser: process.env.SF_USERNAME
|
|
||||||
sfpass: process.env.SF_SECURITY_TOKEN
|
|
||||||
orgCreds:
|
|
||||||
clientId: process.env.SF_CLIENT_ID
|
|
||||||
clientSecret: process.env.SF_CLIENT_SECRET
|
|
||||||
redirectUri: 'http://localhost:3000/oauth/_callback'
|
|
||||||
|
|
||||||
device: { name: 'salesforce', driver: 'force' }
|
|
||||||
|
|
||||||
work: (me) ->
|
|
||||||
me.salesforce.on 'start', () ->
|
|
||||||
me.salesforce.subscribe '/topic/SpheroMsgOutbound', (data) ->
|
|
||||||
msg = "Sphero: #{data.sobject.Sphero_Name__c},"
|
|
||||||
msg += "Bucks: #{data.sobject.Bucks__c},"
|
|
||||||
msg += "SM_Id: #{data.sobject.Id}"
|
|
||||||
|
|
||||||
console.log msg
|
|
||||||
|
|
||||||
me.master.findRobot data.sobject.Sphero_Name__c, (err, spheroBot) ->
|
|
||||||
spheroBot.react spheroBot.devices.sphero
|
|
||||||
|
|
||||||
class SpheroRobot
|
|
||||||
totalBucks: 0
|
|
||||||
|
|
||||||
connection: { name: 'sphero', adaptor: 'sphero' }
|
|
||||||
|
|
||||||
device: { name: 'sphero', driver: 'sphero' }
|
|
||||||
|
|
||||||
react: (robot) =>
|
|
||||||
robot.setRGB 0x00FF00
|
|
||||||
robot.roll 90, Math.floor(Math.random() * 360)
|
|
||||||
|
|
||||||
work: (me) ->
|
|
||||||
me.sphero.on 'connect', ->
|
|
||||||
console.log 'Setting up Collision Detection...'
|
|
||||||
me.sphero.detectCollisions()
|
|
||||||
me.sphero.stop()
|
|
||||||
me.sphero.setRGB 0x00FF00
|
|
||||||
me.sphero.roll 90, Math.floor(Math.random() * 360)
|
|
||||||
|
|
||||||
me.sphero.on 'collision', (data) ->
|
|
||||||
me.sphero.setRGB 0x0000FF, me
|
|
||||||
me.sphero.stop()
|
|
||||||
|
|
||||||
data = JSON.stringify
|
|
||||||
spheroName: "#{me.name}"
|
|
||||||
bucks: "#{me.totalBucks++}"
|
|
||||||
|
|
||||||
me.master.findRobot 'salesforce', (err, sf) ->
|
|
||||||
sf.devices.salesforce.push 'SpheroController', 'POST', data
|
|
||||||
|
|
||||||
sfRobot = new SalesforceRobot()
|
|
||||||
sfRobot.name = "salesforce"
|
|
||||||
Cylon.robot sfRobot
|
|
||||||
|
|
||||||
spheroRobot = new SpheroRobot()
|
|
||||||
spheroRobot.name = 'ROY'
|
|
||||||
spheroRobot.connection.port = '/dev/rfcomm0'
|
|
||||||
Cylon.robot spheroRobot
|
|
||||||
|
|
||||||
Cylon.start()
|
|
|
@ -1,23 +0,0 @@
|
||||||
Cylon = require '../..'
|
|
||||||
|
|
||||||
Cylon.robot
|
|
||||||
connections: [
|
|
||||||
{ name: 'arduino', adaptor: 'firmata', port: '/dev/ttyACM0' },
|
|
||||||
{ name: 'skynet', adaptor: 'skynet', uuid: "742401f1-87a4-11e3-834d-670dadc0ddbf", token: "xjq9h3yzhemf5hfrme8y08fh0sm50zfr" }
|
|
||||||
]
|
|
||||||
|
|
||||||
device: { name: 'led', driver: 'led', pin: 13, connection: 'arduino' }
|
|
||||||
|
|
||||||
work: (my) ->
|
|
||||||
Logger.info "connected..."
|
|
||||||
|
|
||||||
my.connections['skynet'].on 'message', (data) ->
|
|
||||||
console.log(data)
|
|
||||||
if data.message.red is 'on'
|
|
||||||
console.log("red on request received from skynet");
|
|
||||||
my.led.turnOn()
|
|
||||||
else if data.message.red is 'off'
|
|
||||||
console.log("red off request received from skynet");
|
|
||||||
my.led.turnOff()
|
|
||||||
|
|
||||||
.start()
|
|
|
@ -1,121 +0,0 @@
|
||||||
Cylon = require '../..'
|
|
||||||
|
|
||||||
Cylon.api host: '0.0.0.0', port: '8080'
|
|
||||||
|
|
||||||
class PebbleRobot
|
|
||||||
connection: { name: 'pebble', adaptor: 'pebble' }
|
|
||||||
device: { name: 'pebble', driver: 'pebble' }
|
|
||||||
|
|
||||||
message: (robot, msg) =>
|
|
||||||
robot.message_queue().push(msg)
|
|
||||||
|
|
||||||
work: (me) ->
|
|
||||||
me.pebble.on 'connect', -> console.log "Connected!"
|
|
||||||
|
|
||||||
class SalesforceRobot
|
|
||||||
connection:
|
|
||||||
name: 'sfcon'
|
|
||||||
adaptor: 'force'
|
|
||||||
sfuser: process.env.SF_USERNAME
|
|
||||||
sfpass: process.env.SF_SECURITY_TOKEN
|
|
||||||
orgCreds:
|
|
||||||
clientId: process.env.SF_CLIENT_ID
|
|
||||||
clientSecret: process.env.SF_CLIENT_SECRET
|
|
||||||
redirectUri: 'http://localhost:3000/oauth/_callback'
|
|
||||||
|
|
||||||
device: { name: 'salesforce', driver: 'force' }
|
|
||||||
|
|
||||||
spheroReport: {}
|
|
||||||
|
|
||||||
work: (me) ->
|
|
||||||
me.salesforce.on 'start', () ->
|
|
||||||
me.salesforce.subscribe '/topic/SpheroMsgOutbound', (data) ->
|
|
||||||
name = data.sobject.Sphero_Name__c
|
|
||||||
bucks = data.sobject.Bucks__c
|
|
||||||
|
|
||||||
msg = "Sphero: #{name},"
|
|
||||||
msg += "data Bucks: #{bucks},"
|
|
||||||
msg += "SM_Id: #{data.sobject.Id}"
|
|
||||||
|
|
||||||
console.log msg
|
|
||||||
|
|
||||||
me.master.findRobot name, (err, spheroBot) ->
|
|
||||||
spheroBot.react spheroBot.devices.sphero
|
|
||||||
|
|
||||||
me.spheroReport[name] = bucks
|
|
||||||
|
|
||||||
toPebble = ""
|
|
||||||
toPebble += "#{key}: $#{val}\n" for key, val of me.spheroReport
|
|
||||||
|
|
||||||
me.master.findRobot 'pebble', (error, pebbleBot) ->
|
|
||||||
pebbleBot.message pebbleBot.devices.pebble, toPebble
|
|
||||||
|
|
||||||
class SpheroRobot
|
|
||||||
totalBucks: 1
|
|
||||||
payingPower: true
|
|
||||||
|
|
||||||
connection: { name: 'sphero', adaptor: 'sphero' }
|
|
||||||
|
|
||||||
device: { name: 'sphero', driver: 'sphero' }
|
|
||||||
|
|
||||||
react: (device) ->
|
|
||||||
device.setRGB 0x00FF00
|
|
||||||
device.roll 90, Math.floor(Math.random() * 360)
|
|
||||||
@payingPower = true
|
|
||||||
|
|
||||||
bankrupt: () ->
|
|
||||||
every 3.seconds(), () =>
|
|
||||||
if @payingPower and @totalBucks > 0
|
|
||||||
@totalBucks += -1
|
|
||||||
if @totalBucks is 0
|
|
||||||
@sphero.setRGB 0xFF000
|
|
||||||
@sphero.stop()
|
|
||||||
|
|
||||||
changeDirection: () ->
|
|
||||||
every 1.seconds(), () =>
|
|
||||||
@sphero.roll 90, Math.floor(Math.random() * 360) if @payingPower
|
|
||||||
|
|
||||||
work: (me) ->
|
|
||||||
|
|
||||||
me.sphero.on 'connect', ->
|
|
||||||
console.log 'Setting up Collision Detection...'
|
|
||||||
me.sphero.detectCollisions()
|
|
||||||
me.sphero.stop()
|
|
||||||
me.sphero.setRGB 0x00FF00
|
|
||||||
me.sphero.roll 90, Math.floor(Math.random() * 360)
|
|
||||||
me.bankrupt()
|
|
||||||
me.changeDirection()
|
|
||||||
|
|
||||||
me.sphero.on 'collision', (data) ->
|
|
||||||
me.sphero.setRGB 0x0000FF
|
|
||||||
me.sphero.stop()
|
|
||||||
me.payingPower = false
|
|
||||||
|
|
||||||
data = JSON.stringify
|
|
||||||
spheroName: "#{me.name}",
|
|
||||||
bucks: "#{me.totalBucks++}"
|
|
||||||
|
|
||||||
me.master.findRobot 'salesforce', (err, sf) ->
|
|
||||||
sf.devices.salesforce.push "SpheroController", "POST", data
|
|
||||||
|
|
||||||
salesforceRobot = new SalesforceRobot()
|
|
||||||
salesforceRobot.name = "salesforce"
|
|
||||||
Cylon.robot salesforceRobot
|
|
||||||
|
|
||||||
pebbleRobot = new PebbleRobot()
|
|
||||||
pebbleRobot.name = "pebble"
|
|
||||||
Cylon.robot pebbleRobot
|
|
||||||
|
|
||||||
bots = [
|
|
||||||
{ port: '/dev/tty.Sphero-ROY-AMP-SPP', name: 'ROY' },
|
|
||||||
{ port: '/dev/tty.Sphero-GBO-AMP-SPP', name: 'GBO'},
|
|
||||||
{ port: '/dev/tty.Sphero-RRY-AMP-SPP', name: 'RRY'}
|
|
||||||
]
|
|
||||||
|
|
||||||
for bot in bots
|
|
||||||
robot = new SpheroRobot
|
|
||||||
robot.connection.port = bot.port
|
|
||||||
robot.name = bot.name
|
|
||||||
Cylon.robot robot
|
|
||||||
|
|
||||||
Cylon.start()
|
|
|
@ -1,150 +0,0 @@
|
||||||
# Sphero Pebble Sales Force
|
|
||||||
|
|
||||||
First, let's import Cylon:
|
|
||||||
|
|
||||||
Cylon = require '../..'
|
|
||||||
|
|
||||||
Next up, we'll configure the API Cylon will serve, telling it to serve on port
|
|
||||||
`8080`.
|
|
||||||
|
|
||||||
Cylon.api host: '0.0.0.0', port: '8080'
|
|
||||||
|
|
||||||
Now that we have Cylon imported, we can start defining our pebble robot
|
|
||||||
|
|
||||||
class PebbleRobot
|
|
||||||
|
|
||||||
Let's define the connections and devices:
|
|
||||||
|
|
||||||
connection: { name: 'pebble', adaptor: 'pebble' }
|
|
||||||
device: { name: 'pebble', driver: 'pebble' }
|
|
||||||
|
|
||||||
message: (robot, msg) =>
|
|
||||||
robot.message_queue().push(msg)
|
|
||||||
|
|
||||||
Now that Cylon knows about the necessary hardware we're going to be using, we'll
|
|
||||||
tell it what work we want to do:
|
|
||||||
|
|
||||||
work: (me) ->
|
|
||||||
me.pebble.on 'connect', -> console.log "Connected!"
|
|
||||||
|
|
||||||
Let's define our Sales Force robot
|
|
||||||
|
|
||||||
class SalesforceRobot
|
|
||||||
|
|
||||||
Let's define the connections and devices:
|
|
||||||
|
|
||||||
connection:
|
|
||||||
name: 'sfcon'
|
|
||||||
adaptor: 'force'
|
|
||||||
sfuser: process.env.SF_USERNAME
|
|
||||||
sfpass: process.env.SF_SECURITY_TOKEN
|
|
||||||
orgCreds:
|
|
||||||
clientId: process.env.SF_CLIENT_ID
|
|
||||||
clientSecret: process.env.SF_CLIENT_SECRET
|
|
||||||
redirectUri: 'http://localhost:3000/oauth/_callback'
|
|
||||||
|
|
||||||
device: { name: 'salesforce', driver: 'force' }
|
|
||||||
|
|
||||||
spheroReport: {}
|
|
||||||
|
|
||||||
Tell it what work we want to do:
|
|
||||||
|
|
||||||
work: (me) ->
|
|
||||||
me.salesforce.on 'start', () ->
|
|
||||||
me.salesforce.subscribe '/topic/SpheroMsgOutbound', (data) ->
|
|
||||||
name = data.sobject.Sphero_Name__c
|
|
||||||
bucks = data.sobject.Bucks__c
|
|
||||||
|
|
||||||
msg = "Sphero: #{name},"
|
|
||||||
msg += "data Bucks: #{bucks},"
|
|
||||||
msg += "SM_Id: #{data.sobject.Id}"
|
|
||||||
|
|
||||||
console.log msg
|
|
||||||
|
|
||||||
me.master.findRobot name, (err, spheroBot) ->
|
|
||||||
spheroBot.react spheroBot.devices.sphero
|
|
||||||
|
|
||||||
me.spheroReport[name] = bucks
|
|
||||||
|
|
||||||
toPebble = ""
|
|
||||||
toPebble += "#{key}: $#{val}\n" for key, val of me.spheroReport
|
|
||||||
|
|
||||||
me.master.findRobot 'pebble', (error, pebbleBot) ->
|
|
||||||
pebbleBot.message pebbleBot.devices.pebble, toPebble
|
|
||||||
|
|
||||||
Let's define our Sphero robot
|
|
||||||
|
|
||||||
class SpheroRobot
|
|
||||||
totalBucks: 1
|
|
||||||
payingPower: true
|
|
||||||
|
|
||||||
connection: { name: 'sphero', adaptor: 'sphero' }
|
|
||||||
|
|
||||||
device: { name: 'sphero', driver: 'sphero' }
|
|
||||||
|
|
||||||
react: (device) ->
|
|
||||||
device.setRGB 0x00FF00
|
|
||||||
device.roll 90, Math.floor(Math.random() * 360)
|
|
||||||
@payingPower = true
|
|
||||||
|
|
||||||
bankrupt: () ->
|
|
||||||
every 3.seconds(), () =>
|
|
||||||
if @payingPower and @totalBucks > 0
|
|
||||||
@totalBucks += -1
|
|
||||||
if @totalBucks is 0
|
|
||||||
@sphero.setRGB 0xFF000
|
|
||||||
@sphero.stop()
|
|
||||||
|
|
||||||
changeDirection: () ->
|
|
||||||
every 1.seconds(), () =>
|
|
||||||
@sphero.roll 90, Math.floor(Math.random() * 360) if @payingPower
|
|
||||||
|
|
||||||
Tell it what work we want to do:
|
|
||||||
|
|
||||||
work: (me) ->
|
|
||||||
|
|
||||||
me.sphero.on 'connect', ->
|
|
||||||
console.log 'Setting up Collision Detection...'
|
|
||||||
me.sphero.detectCollisions()
|
|
||||||
me.sphero.stop()
|
|
||||||
me.sphero.setRGB 0x00FF00
|
|
||||||
me.sphero.roll 90, Math.floor(Math.random() * 360)
|
|
||||||
me.bankrupt()
|
|
||||||
me.changeDirection()
|
|
||||||
|
|
||||||
me.sphero.on 'collision', (data) ->
|
|
||||||
me.sphero.setRGB 0x0000FF
|
|
||||||
me.sphero.stop()
|
|
||||||
me.payingPower = false
|
|
||||||
|
|
||||||
data = JSON.stringify
|
|
||||||
spheroName: "#{me.name}",
|
|
||||||
bucks: "#{me.totalBucks++}"
|
|
||||||
|
|
||||||
me.master.findRobot 'salesforce', (err, sf) ->
|
|
||||||
sf.devices.salesforce.push "SpheroController", "POST", data
|
|
||||||
|
|
||||||
salesforceRobot = new SalesforceRobot()
|
|
||||||
salesforceRobot.name = "salesforce"
|
|
||||||
Cylon.robot salesforceRobot
|
|
||||||
|
|
||||||
pebbleRobot = new PebbleRobot()
|
|
||||||
pebbleRobot.name = "pebble"
|
|
||||||
Cylon.robot pebbleRobot
|
|
||||||
|
|
||||||
bots = [
|
|
||||||
{ port: '/dev/tty.Sphero-ROY-AMP-SPP', name: 'ROY' },
|
|
||||||
{ port: '/dev/tty.Sphero-GBO-AMP-SPP', name: 'GBO'},
|
|
||||||
{ port: '/dev/tty.Sphero-RRY-AMP-SPP', name: 'RRY'}
|
|
||||||
]
|
|
||||||
|
|
||||||
for bot in bots
|
|
||||||
robot = new SpheroRobot
|
|
||||||
robot.connection.port = bot.port
|
|
||||||
robot.name = bot.name
|
|
||||||
Cylon.robot robot
|
|
||||||
|
|
||||||
Now that our robot knows what work to do, and the work it will be doing that
|
|
||||||
hardware with, we can start it:
|
|
||||||
|
|
||||||
Cylon.start()
|
|
|
@ -0,0 +1,208 @@
|
||||||
|
# Sphero + Pebble + SalesForce
|
||||||
|
|
||||||
|
First, let's import Cylon:
|
||||||
|
|
||||||
|
var Cylon = require('../..');
|
||||||
|
|
||||||
|
Next up, we'll configure the API Cylon will serve, telling it to serve on port
|
||||||
|
`8080`.
|
||||||
|
|
||||||
|
Cylon.api({ host: '0.0.0.0', port: '8080' });
|
||||||
|
|
||||||
|
We'll also setup a convenince function for some binding we'll need to do later:
|
||||||
|
|
||||||
|
var bind = function(fn, me) {
|
||||||
|
return function() { return fn.apply(me, arguments); };
|
||||||
|
};
|
||||||
|
|
||||||
|
Now that we have Cylon imported, we can start defining our Pebble robot:
|
||||||
|
|
||||||
|
var PebbleRobot = (function() {
|
||||||
|
|
||||||
|
Let's define the connections and devices:
|
||||||
|
|
||||||
|
PebbleRobot.prototype.connection = { name: 'pebble', adaptor: 'pebble' };
|
||||||
|
PebbleRobot.prototype.device = { name: 'pebble', driver: 'pebble' };
|
||||||
|
|
||||||
|
PebbleRobot.prototype.message = function(robot, msg) {
|
||||||
|
robot.message_queue().push(msg);
|
||||||
|
};
|
||||||
|
|
||||||
|
Now that Cylon knows about the necessary hardware we're going to be using, we'll
|
||||||
|
tell it what work we want to do:
|
||||||
|
|
||||||
|
PebbleRobot.prototype.work = function(me) {
|
||||||
|
me.pebble.on('connect', function() { console.log("Connected!"); });
|
||||||
|
};
|
||||||
|
|
||||||
|
return PebbleRobot;
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
|
Next, let's define our SalesForce robot:
|
||||||
|
|
||||||
|
var SalesforceRobot = (function() {
|
||||||
|
function SalesforceRobot() {}
|
||||||
|
|
||||||
|
Let's define the connections and devices:
|
||||||
|
|
||||||
|
SalesforceRobot.prototype.connection = {
|
||||||
|
name: 'sfcon',
|
||||||
|
adaptor: 'force',
|
||||||
|
sfuser: process.env.SF_USERNAME,
|
||||||
|
sfpass: process.env.SF_SECURITY_TOKEN,
|
||||||
|
orgCreds: {
|
||||||
|
clientId: process.env.SF_CLIENT_ID,
|
||||||
|
clientSecret: process.env.SF_CLIENT_SECRET,
|
||||||
|
redirectUri: 'http://localhost:3000/oauth/_callback'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
SalesforceRobot.prototype.device = { name: 'salesforce', driver: 'force' };
|
||||||
|
|
||||||
|
SalesforceRobot.prototype.spheroReport = {};
|
||||||
|
|
||||||
|
Tell it what work we want to do:
|
||||||
|
|
||||||
|
SalesforceRobot.prototype.work = function(me) {
|
||||||
|
me.salesforce.on('start', function() {
|
||||||
|
me.salesforce.subscribe('/topic/SpheroMsgOutbound', function(data) {
|
||||||
|
var bucks, key, msg, name, toPebble, val, _ref;
|
||||||
|
|
||||||
|
name = data.sobject.Sphero_Name__c;
|
||||||
|
bucks = data.sobject.Bucks__c;
|
||||||
|
|
||||||
|
msg = "Sphero: " + name + ",";
|
||||||
|
msg += "data Bucks: " + bucks + ",";
|
||||||
|
msg += "SM_Id: " + data.sobject.Id;
|
||||||
|
|
||||||
|
console.log(msg);
|
||||||
|
|
||||||
|
me.master.findRobot(name, function(err, spheroBot) {
|
||||||
|
spheroBot.react(spheroBot.devices.sphero);
|
||||||
|
});
|
||||||
|
|
||||||
|
me.spheroReport[name] = bucks;
|
||||||
|
toPebble = "";
|
||||||
|
|
||||||
|
_ref = me.spheroReport;
|
||||||
|
|
||||||
|
for (key in _ref) {
|
||||||
|
val = _ref[key];
|
||||||
|
toPebble += "" + key + ": $" + val + "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
me.master.findRobot('pebble', function(error, pebbleBot) {
|
||||||
|
pebbleBot.message(pebbleBot.devices.pebble, toPebble);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return SalesforceRobot;
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
|
Now, Let's define our Sphero robot
|
||||||
|
|
||||||
|
var SpheroRobot = (function() {
|
||||||
|
function SpheroRobot() {}
|
||||||
|
|
||||||
|
SpheroRobot.prototype.totalBucks = 1;
|
||||||
|
|
||||||
|
SpheroRobot.prototype.payingPower = true;
|
||||||
|
|
||||||
|
SpheroRobot.prototype.connection = { name: 'sphero', adaptor: 'sphero' };
|
||||||
|
SpheroRobot.prototype.device = { name: 'sphero', driver: 'sphero' };
|
||||||
|
|
||||||
|
SpheroRobot.prototype.react = function(device) {
|
||||||
|
device.setRGB(0x00FF00);
|
||||||
|
device.roll(90, Math.floor(Math.random() * 360));
|
||||||
|
this.payingPower = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
SpheroRobot.prototype.bankrupt = function() {
|
||||||
|
var _this = this;
|
||||||
|
every(3..seconds(), function() {
|
||||||
|
if (_this.payingPower && _this.totalBucks > 0) {
|
||||||
|
_this.totalBucks += -1;
|
||||||
|
if (_this.totalBucks === 0) {
|
||||||
|
_this.sphero.setRGB(0xFF000);
|
||||||
|
_this.sphero.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
SpheroRobot.prototype.changeDirection = function() {
|
||||||
|
var _this = this;
|
||||||
|
every((1).seconds(), function() {
|
||||||
|
if (_this.payingPower) {
|
||||||
|
_this.sphero.roll(90, Math.floor(Math.random() * 360));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Tell it what work we want to do:
|
||||||
|
|
||||||
|
SpheroRobot.prototype.work = function(me) {
|
||||||
|
me.sphero.on('connect', function() {
|
||||||
|
console.log('Setting up Collision Detection...');
|
||||||
|
me.sphero.detectCollisions();
|
||||||
|
me.sphero.stop();
|
||||||
|
me.sphero.setRGB(0x00FF00);
|
||||||
|
me.sphero.roll(90, Math.floor(Math.random() * 360));
|
||||||
|
me.bankrupt();
|
||||||
|
me.changeDirection();
|
||||||
|
});
|
||||||
|
|
||||||
|
me.sphero.on('collision', function(data) {
|
||||||
|
me.sphero.setRGB(0x0000FF);
|
||||||
|
me.sphero.stop();
|
||||||
|
me.payingPower = false;
|
||||||
|
|
||||||
|
data = JSON.stringify({
|
||||||
|
spheroName: "" + me.name,
|
||||||
|
bucks: "" + (me.totalBucks++)
|
||||||
|
});
|
||||||
|
|
||||||
|
me.master.findRobot('salesforce', function(err, sf) {
|
||||||
|
sf.devices.salesforce.push("SpheroController", "POST", data);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return SpheroRobot;
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
|
Now that we've defined all of our bots, let's tell Cylon about them:
|
||||||
|
|
||||||
|
var salesforceRobot = new SalesforceRobot();
|
||||||
|
salesforceRobot.name = "salesforce";
|
||||||
|
Cylon.robot(salesforceRobot);
|
||||||
|
|
||||||
|
var pebbleRobot = new PebbleRobot();
|
||||||
|
pebbleRobot.name = "pebble";
|
||||||
|
Cylon.robot(pebbleRobot);
|
||||||
|
|
||||||
|
var bots = [
|
||||||
|
{ port: '/dev/tty.Sphero-ROY-AMP-SPP', name: 'ROY' },
|
||||||
|
{ port: '/dev/tty.Sphero-GBO-AMP-SPP', name: 'GBO' },
|
||||||
|
{ port: '/dev/tty.Sphero-RRY-AMP-SPP', name: 'RRY' }
|
||||||
|
];
|
||||||
|
|
||||||
|
for (var i = 0; i < bots.length; i++) {
|
||||||
|
var bot = bots[i];
|
||||||
|
var robot = new SpheroRobot;
|
||||||
|
|
||||||
|
robot.connection.port = bot.port;
|
||||||
|
robot.name = bot.name;
|
||||||
|
|
||||||
|
Cylon.robot(robot);
|
||||||
|
}
|
||||||
|
|
||||||
|
Now that Cylon knows about all our robots, and what they'll be doing, we can
|
||||||
|
start:
|
||||||
|
|
||||||
|
Cylon.start();
|
|
@ -1,43 +0,0 @@
|
||||||
Cylon = require '../..'
|
|
||||||
Travis = require 'travis-ci'
|
|
||||||
|
|
||||||
travis = new Travis
|
|
||||||
version: '2.0.0'
|
|
||||||
|
|
||||||
BLUE = 0x0000ff
|
|
||||||
GREEN = 0x00ff00
|
|
||||||
RED = 0xff0000
|
|
||||||
|
|
||||||
Cylon.robot
|
|
||||||
connection:
|
|
||||||
name: 'sphero', adaptor: 'sphero', port: '/dev/rfcomm0'
|
|
||||||
|
|
||||||
device:
|
|
||||||
name: 'sphero', driver: 'sphero'
|
|
||||||
|
|
||||||
work: (me) ->
|
|
||||||
user = "hybridgroup"
|
|
||||||
name = "cylon"
|
|
||||||
|
|
||||||
me.checkTravis = ->
|
|
||||||
console.log "Checking repo #{user}/#{name}"
|
|
||||||
me.sphero.setRGB BLUE, true
|
|
||||||
|
|
||||||
travis.repos {
|
|
||||||
owner_name: user,
|
|
||||||
name: name
|
|
||||||
}, (err, res) ->
|
|
||||||
if res.repo
|
|
||||||
switch res.repo.last_build_state
|
|
||||||
when 'passed' then me.sphero.setRGB(GREEN, true)
|
|
||||||
when 'failed' then me.sphero.setRGB(RED, true)
|
|
||||||
else me.sphero.setRGB(BLUE, true)
|
|
||||||
else
|
|
||||||
me.sphero.setRGB BLUE, true
|
|
||||||
|
|
||||||
me.checkTravis()
|
|
||||||
|
|
||||||
every 10.seconds(), ->
|
|
||||||
me.checkTravis()
|
|
||||||
|
|
||||||
.start()
|
|
|
@ -1,45 +1,38 @@
|
||||||
var Cylon = require('../..')
|
var Cylon = require('../..'),
|
||||||
var Travis = require('travis-ci')
|
Travis = require('travis-ci');
|
||||||
|
|
||||||
var travis = new Travis({version: '2.0.0'});
|
var travis = new Travis({version: '2.0.0'});
|
||||||
|
|
||||||
var BLUE = 0x0000ff
|
|
||||||
var GREEN = 0x00ff00
|
|
||||||
var RED = 0xff0000
|
|
||||||
|
|
||||||
Cylon.robot({
|
Cylon.robot({
|
||||||
connection: {name: 'sphero', adaptor: 'sphero', port: '/dev/rfcomm0'},
|
connection: { name: 'sphero', adaptor: 'sphero', port: '/dev/rfcomm0' },
|
||||||
device: {name: 'sphero', driver: 'sphero'},
|
device: {name: 'sphero', driver: 'sphero' },
|
||||||
|
|
||||||
work: function(me) {
|
work: function(my) {
|
||||||
var user = "hybridgroup"
|
var user = "hybridgroup",
|
||||||
var name = "cylon"
|
name = "cylon";
|
||||||
|
|
||||||
me.checkTravis = function() {
|
var checkTravis = function() {
|
||||||
console.log("Checking repo "+user+"/"+name);
|
console.log("Checking repo " + user + "/" + name);
|
||||||
me.sphero.setRGB(BLUE, true);
|
my.sphero.setColor('blue', true);
|
||||||
|
|
||||||
travis.repos(
|
travis.repos({ owner_name: user, name: name }, function(err, res) {
|
||||||
{ owner_name: user, name: name },
|
if (res.repo === undefined) { my.sphero.setColor('blue', true); }
|
||||||
function(err, res) {
|
|
||||||
if (res.repo != undefined) {
|
switch (res.repo.last_build_state) {
|
||||||
if (res.repo.last_build_state == 'passed') {
|
case 'passed':
|
||||||
me.sphero.setRGB(GREEN, true);
|
my.sphero.setColor('green', true);
|
||||||
} else if (res.repo.last_build_state == 'failed') {
|
break;
|
||||||
me.sphero.setRGB(RED, true);
|
case 'failed':
|
||||||
} else {
|
my.sphero.setColor('red', true);
|
||||||
me.sphero.setRGB(BLUE, true);
|
break;
|
||||||
}
|
default:
|
||||||
} else {
|
my.sphero.setColor('blue', true);
|
||||||
me.sphero.setRGB BLUE, true
|
}
|
||||||
}
|
});
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
me.checkTravis();
|
checkTravis();
|
||||||
|
|
||||||
every((10).seconds(), function() {
|
every((10).seconds(), checkTravis);
|
||||||
me.checkTravis();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}).start();
|
}).start();
|
||||||
|
|
|
@ -11,106 +11,106 @@ Before you run this, make sure you install the following dependencies:
|
||||||
First of all, let's load up Cylon. We're going to load the version directly from
|
First of all, let's load up Cylon. We're going to load the version directly from
|
||||||
the repo, since we're here already:
|
the repo, since we're here already:
|
||||||
|
|
||||||
Cylon = require '../..'
|
var Cylon = require('../..');
|
||||||
|
|
||||||
Next, we'll set up Travis. We're going to be using the very useful [travis-ci][]
|
Next, we'll set up Travis. We're going to be using the very useful [travis-ci][]
|
||||||
module.
|
module.
|
||||||
|
|
||||||
[travis-ci]: https://github.com/pwmckenna/node-travis-ci
|
[travis-ci]: https://github.com/pwmckenna/node-travis-ci
|
||||||
|
|
||||||
Travis = require 'travis-ci'
|
var Travis = require('travis-ci')
|
||||||
|
|
||||||
Now that we've got our Travis module imported, let's set it up:
|
Now that we've got our Travis module imported, let's set it up:
|
||||||
|
|
||||||
travis = new Travis
|
var travis = new Travis({version: '2.0.0'});
|
||||||
version: '2.0.0'
|
|
||||||
|
|
||||||
Now we have a working interface to the Travis-CI API. Let's set up a username
|
Now we have a working interface to the Travis-CI API. Let's set up a username
|
||||||
and repo to query Travis about later, as long as we're here. Feel free to change
|
and repo to query Travis about later, as long as we're here. Feel free to change
|
||||||
these if you want to try with your own repositories.
|
these if you want to try with your own repositories.
|
||||||
|
|
||||||
user = "hybridgroup"
|
var user = "hybridgroup",
|
||||||
name = "cylon"
|
name = "cylon";
|
||||||
|
|
||||||
## Robot
|
## Robot
|
||||||
|
|
||||||
And with that last bit of setup done, let's start setting up our robot!
|
And with that last bit of setup done, let's start setting up our robot!
|
||||||
|
|
||||||
Cylon.robot
|
Cylon.robot({
|
||||||
|
|
||||||
We use a connection to tell Cylon what port it can use to communicate with our
|
We use a connection to tell Cylon what port it can use to communicate with our
|
||||||
Sphero, along with what adaptor it should require (`cylon-sphero`) to connect to
|
Sphero, along with what adaptor it should require (`cylon-sphero`) to connect to
|
||||||
it. We give it a name to make it easier to reference later on.
|
it. We give it a name to make it easier to reference later on.
|
||||||
|
|
||||||
connection:
|
connection: { name: 'sphero', adaptor: 'sphero', port: '/dev/rfcomm0' },
|
||||||
name: 'sphero', adaptor: 'sphero', port: '/dev/rfcomm0'
|
|
||||||
|
|
||||||
Devices are set up in a similar fashion, but allow us to directly issue commands
|
Devices are set up in a similar fashion, but allow us to directly issue commands
|
||||||
to the sphero. These are added to the robot's namespace directly to make them
|
to the sphero. These are added to the robot's namespace directly to make them
|
||||||
easy to access.
|
easy to access.
|
||||||
|
|
||||||
device:
|
device: {name: 'sphero', driver: 'sphero' },
|
||||||
name: 'sphero', driver: 'sphero'
|
|
||||||
|
|
||||||
Now that we've told our robot what hardware it has access to, we can start
|
Now that we've told our robot what hardware it has access to, we can start
|
||||||
telling it what it should do. The work function passes along one argument,
|
telling it what it should do. The work function passes along one argument,
|
||||||
a reference to the robot so we can access it's state and hardware.
|
a reference to the robot so we can access it's state and hardware.
|
||||||
|
|
||||||
work: (me) ->
|
work: function(my) {
|
||||||
|
|
||||||
We'll define a function to check Travis and change the Sphero's color depending
|
We'll define a function to check Travis and change the Sphero's color depending
|
||||||
on the state of the last build.
|
on the state of the last build.
|
||||||
|
|
||||||
checkTravis = ->
|
var checkTravis = function() {
|
||||||
|
|
||||||
First, it will log that it's checking Travis to the logger:
|
First, it will log that it's checking Travis to the logger:
|
||||||
|
|
||||||
console.log "Checking last build status for #{user}/#{name}"
|
console.log("Checking repo " + user + "/" + name);
|
||||||
|
|
||||||
Let's set the default color of the Sphero to blue until we know what the build
|
Let's set the default color of the Sphero to blue until we know what the build
|
||||||
status is:
|
status is:
|
||||||
|
|
||||||
me.sphero.setColor 'blue', true
|
my.sphero.setColor('blue', true);
|
||||||
|
|
||||||
Now we'll fetch the Travis build status:
|
Now we'll fetch the Travis build status:
|
||||||
|
|
||||||
travis.repos {
|
travis.repos({ owner_name: user, name: name }, function(err, res) {
|
||||||
owner_name: user
|
|
||||||
name: name
|
|
||||||
}, (err, res) ->
|
|
||||||
|
|
||||||
If we were returned a response, we'll check the status of the build and use that
|
If we were returned a response containing a repo, we'll check the status of the
|
||||||
to determine what color we should make the Sphero.
|
build and use that to determine what color we should make the Sphero.
|
||||||
|
|
||||||
if res.repo
|
if (res.repo === undefined) { my.sphero.setColor('blue', true); }
|
||||||
switch res.repo.last_build_state
|
|
||||||
|
switch (res.repo.last_build_state) {
|
||||||
|
|
||||||
When the build state is passed, then we'll set the Sphero's color to green:
|
When the build state is passed, then we'll set the Sphero's color to green:
|
||||||
|
|
||||||
when 'passed' then me.sphero.setColor 'green', true
|
case 'passed':
|
||||||
|
my.sphero.setColor('green', true);
|
||||||
|
break;
|
||||||
|
|
||||||
And if the build has failed, let's set the Sphero's color to red:
|
And if the build has failed, let's set the Sphero's color to red:
|
||||||
|
|
||||||
when 'failed' then me.sphero.setColor 'red', true
|
case 'failed':
|
||||||
|
my.sphero.setColor('red', true);
|
||||||
|
break;
|
||||||
|
|
||||||
Otherwise, we'll just set it to blue:
|
Otherwise, we'll just set it to blue:
|
||||||
|
|
||||||
else me.sphero.setColor 'blue', true
|
else me.sphero.setColor 'blue', true
|
||||||
|
default:
|
||||||
And if we didn't get a response from the server, let's just set it to blue.
|
my.sphero.setColor('blue', true);
|
||||||
|
}
|
||||||
else me.sphero.setColor 'blue', true
|
});
|
||||||
|
};
|
||||||
|
|
||||||
Now that we've got that function defined, let's call it to set the initial color
|
Now that we've got that function defined, let's call it to set the initial color
|
||||||
of the Sphero:
|
of the Sphero:
|
||||||
|
|
||||||
do checkTravis
|
checkTravis();
|
||||||
|
|
||||||
And every ten seconds, let's keep checking Travis:
|
And every ten seconds, let's keep checking Travis:
|
||||||
|
|
||||||
every 10.seconds(), ->
|
every((10).seconds(), checkTravis);
|
||||||
do checkTravis
|
}
|
||||||
|
|
||||||
And now that we've got our work defined, let's start the robot!
|
And now that we've got our work defined, let's start the robot!
|
||||||
|
|
||||||
.start()
|
}).start();
|
Loading…
Reference in New Issue