pangdudu-robots 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -1,11 +1,9 @@
1
1
  = ROBOTS
2
2
 
3
- Start your clocks boys and girls, it's weekend coding time!
4
-
5
- On monday I want: working messaging, data-mapper/mysql memory agent, visualizer agent with agent introspection, slim agent that requests modules,classes over the net and evals them online.
6
-
7
3
  Local messaging with dbus working, need to make service avahi discoverable.
8
4
 
5
+ Well, fork, dbus is not really remote capable right now. Ohh, I so much don't want to write that myself,... ;(...
6
+
9
7
  Let's try to built a nice easy to use multiagent framework
10
8
  based on all the cool stuff we can get for ruby.
11
9
 
@@ -17,6 +15,7 @@ rObOts!
17
15
  sudo apt-get install avahi-daemon avahi-utils libavahi-client-dev libavahi-common-dev libavahi-compat-libdnssd-dev libnss-mdns libdbus-1-dev libdbus-glib-1-dev
18
16
  #essential gems
19
17
  sudo gem install pangdudu-ruby-dbus --source=http://gems.github.com
18
+ sudo gem install pangdudu-ruby-dbus-daemon --source=http://gems.github.com
20
19
  sudo gem install pangdudu-rofl --source=http://gems.github.com
21
20
  sudo gem install pangdudu-robots --source=http://gems.github.com
22
21
  #for xml parsing and building
@@ -1,5 +1,4 @@
1
1
  <!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
2
- <!-- place this file under /etc/dbus-1/system.d/ -->
3
2
  <busconfig>
4
3
  <policy user="root">
5
4
  <allow own="org.robots.Service" />
@@ -30,4 +29,3 @@
30
29
  <allow send_destination="org.ruby.Service" send_interface="org.freedesktop.DBus.Introspectable" />
31
30
  </policy>
32
31
  </busconfig>
33
-
@@ -0,0 +1,41 @@
1
+ <!-- This configuration file controls the per-user-login-session message bus.
2
+ Add a session-local.conf and edit that rather than changing this
3
+ file directly. -->
4
+
5
+ <!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN"
6
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
7
+ <busconfig>
8
+ <!-- Our well-known bus type, don't change this -->
9
+ <type>session</type>
10
+
11
+ <!-- If we fork, keep the user's original umask to avoid affecting
12
+ the behavior of child processes. -->
13
+ <keep_umask/>
14
+
15
+ <!-- Listen to everything on tcp! -->
16
+ <listen>tcp:host=0.0.0.0,port=2687,family=ipv4</listen>
17
+ <!-- Listen on socket at this file location -->
18
+ <listen>unix:path=/tmp/robots_session_bus_socket</listen>
19
+
20
+ <standard_session_servicedirs />
21
+
22
+ <policy context="default">
23
+ <!-- Allow everything to be sent -->
24
+ <allow send_destination="*" eavesdrop="true"/>
25
+ <!-- Allow everything to be received -->
26
+ <allow eavesdrop="true"/>
27
+ <!-- Allow anyone to own anything -->
28
+ <allow own="*"/>
29
+ </policy>
30
+
31
+ <!-- Config files are placed here that among other things,
32
+ further restrict the above policy for specific services. -->
33
+ <include>org.robots.service.conf</include>
34
+
35
+ <!-- raise the service start timeout to 40 seconds as it can timeout
36
+ on the live cd on slow machines -->
37
+ <limit name="service_start_timeout">60000</limit>
38
+
39
+ <include if_selinux_enabled="yes" selinux_root_relative="yes">contexts/dbus_contexts</include>
40
+
41
+ </busconfig>
@@ -0,0 +1,2 @@
1
+ #!/bin/bash
2
+ dbus-daemon --config-file=remote.session.dbus.conf
@@ -67,8 +67,11 @@ class MemoryAgent
67
67
  include Robots
68
68
  include RobotsXml
69
69
 
70
+ attr_accessor :roboname
71
+
70
72
  def initialize
71
- ilog "RobotsProto initialized"
73
+ @roboname = "Active Memory" #name used in alive messages
74
+ ilog "#{@roboname} initialized"
72
75
  end
73
76
 
74
77
  #process an incoming memory message
@@ -245,6 +248,6 @@ ma.release_robots #start the robot agent module
245
248
  loop do
246
249
  sleep 1
247
250
  #send an xml message over the system
248
- ma.send_msg ma.create_xml_msg { |b| b.info("memory agent alive","timestamp" => "#{Time.now}") }
251
+ ma.send_msg ma.create_xml_alive_msg
249
252
  end
250
253
  #=end
@@ -12,8 +12,11 @@ class MemoryGeneratorAgent
12
12
  include Robots
13
13
  include RobotsXml
14
14
 
15
+ attr_accessor :roboname
16
+
15
17
  def initialize
16
- ilog "MemoryGeneratorAgent initialized"
18
+ @roboname = "Memory Generator" #name used in alive messages
19
+ ilog "#{@roboname} initialized"
17
20
  end
18
21
 
19
22
  #ROBOTS message parsing stuff
@@ -45,7 +48,7 @@ mga.release_robots #start the robot agent module
45
48
  loop do
46
49
  sleep 3
47
50
  #send an xml message over the system
48
- mga.send_msg mga.create_xml_msg { |b| b.info("memory generator agent alive","timestamp" => "#{Time.now}") }
51
+ mga.send_msg mga.create_xml_alive_msg
49
52
  #generate some bogus memory remember
50
53
  mga.send_msg mga.create_xml_msg { |b| b.memory("something happened","action" => "remember");b.question("what happened?","action"=>"remember");b.keyword("stuff");b.keyword("happening") }
51
54
  #generate bogus ask question
@@ -14,8 +14,11 @@ class SwiftAgent
14
14
  include Robots
15
15
  include RobotsXml
16
16
 
17
+ attr_accessor :roboname
18
+
17
19
  def initialize
18
- ilog "SwiftAgent initialized"
20
+ @roboname = "Swift Talker" #name used in alive messages
21
+ ilog "#{@roboname} initialized"
19
22
  end
20
23
 
21
24
  #method that gets called when a new message arrives
@@ -40,5 +43,5 @@ sa.release_robots #start the robot agent module
40
43
  loop do
41
44
  sleep 1
42
45
  #send an xml message over the system
43
- sa.send_msg sa.create_xml_msg { |b| b.body("swift alive"); b.info("timestamp" => "#{Time.now}") }
46
+ sa.send_msg sa.create_xml_alive_msg
44
47
  end
@@ -11,9 +11,12 @@ require 'robots_xml'
11
11
  class TextGenerator
12
12
  include Robots
13
13
  include RobotsXml
14
+
15
+ attr_accessor :roboname
14
16
 
15
17
  def initialize
16
- ilog "TextGenerator initialized"
18
+ @roboname = "Text Generator" #name used in alive messages
19
+ ilog "#{@roboname} initialized"
17
20
  end
18
21
 
19
22
  #method that gets called when a new message arrives
@@ -34,5 +37,6 @@ tg.release_robots #start the robot agent module
34
37
  loop do
35
38
  sleep 5
36
39
  #send an xml message over the system
37
- tg.send_msg tg.create_xml_msg { |b| b.speak("the robots say hello!"); b.info("timestamp" => "#{Time.now}") }
40
+ tg.send_msg tg.create_xml_alive_msg
41
+ tg.send_msg tg.create_xml_msg { |b| b.speak("the robots are coming!"); b.info("timestamp" => "#{Time.now}") }
38
42
  end
@@ -0,0 +1,99 @@
1
+ require 'rubygems'
2
+ require 'matrix'
3
+ #require 'unprof'
4
+ class Physics
5
+ include Math
6
+
7
+ attr_accessor :widht,:height,:objects,:singularity
8
+
9
+ def initialize width,height,parent=nil
10
+ @width,@height = width,height
11
+ @center = PhysicsObject.new(@width/2,@height/2)
12
+ @objects = []
13
+ @parent = parent
14
+ @force = Force.new
15
+ @singularity = false
16
+ start_loop
17
+ end
18
+
19
+ #add an object to the physics module
20
+ def add_object object
21
+ #object need attribute x,y to be valid
22
+ @objects << object
23
+ end
24
+
25
+ #apply the forces
26
+ def apply_physics
27
+ while @singularity
28
+ sleep 0.1
29
+ end
30
+ #apply force pushing nodes to center
31
+ @objects.each do |o|
32
+ delta = @force.center_mom(Vector.[](o.x-@center.x,o.y-@center.y))
33
+ o.x += delta[0]; o.y += delta[1]
34
+ end
35
+ #apply force pushing nodes apart
36
+ @objects.each do |o|
37
+ @objects.each do |oo|
38
+ unless o === oo
39
+ delta = @force.field_mom(Vector.[](o.x-oo.x,o.y-oo.y))
40
+ o.x += delta[0]; o.y += delta[1]
41
+ end
42
+ end
43
+ end
44
+ end
45
+
46
+ #a loop
47
+ def start_loop
48
+ Thread.new do
49
+ loop {sleep(1/45);update_physics}
50
+ end
51
+ end
52
+
53
+ #update the physics model
54
+ def update_physics
55
+ unless @parent.nil?
56
+ unless @parent.physics.nil?
57
+ apply_physics
58
+ @parent.update unless @parent.updating
59
+ end
60
+ end
61
+ end
62
+ end
63
+
64
+ class Force
65
+ #push nodes apart
66
+ def field_mom(delta)
67
+ r = delta.r
68
+ r = 1e-5 if r < 1e-5
69
+ delta *= 1/r
70
+ delta *= (1./(r**1.5 + 1e-5)*5000)
71
+ return delta
72
+ end
73
+
74
+ # delta is PVector, diff between the nodes, deg is the strength of the edge
75
+ def edge_mom(delta, deg)
76
+ r = delta.r
77
+ r = 1e-5 if r < 1e-5
78
+ delta *= 1/r
79
+ delta *= (r*4e-3)
80
+ return delta;
81
+ end
82
+
83
+ #pull nodes to center
84
+ def center_mom(delta)
85
+ r = delta.r
86
+ r = 1e-5 if r < 1e-5
87
+ delta *= 1/r
88
+ delta *= (r*-1e-2)
89
+ return delta;
90
+ end
91
+ end
92
+
93
+ #simple physics object
94
+ class PhysicsObject
95
+ attr_accessor :x,:y
96
+ def initialize x,y
97
+ @x,@y = x,y
98
+ end
99
+ end
@@ -0,0 +1,117 @@
1
+ require 'Qt4'
2
+ require 'flow_physics'
3
+
4
+ class Agent
5
+ attr_accessor :x, :y, :rel_angle, :agentname
6
+
7
+ def initialize agentname, x=0, y=0
8
+ @agentname = agentname
9
+ @x, @y= x, y
10
+ end
11
+
12
+ #get the relative angle
13
+ def get_rel_angle x,y
14
+ #angle in radian (up -0.5, left -1/1, down 0.5, right 0)
15
+ @rel_angle = Math.atan2(@y-y,@x-x)/Math::PI
16
+ #we want a range from -1 to +1
17
+ @rel_angle = @rel_angle * 180
18
+ return @rel_angle
19
+ end
20
+ end
21
+
22
+ class DragInfo
23
+ attr_accessor :x, :y, :object
24
+
25
+ def initialize startx, starty, object=nil
26
+ @x, @y, @object = startx, starty, object
27
+ end
28
+ end
29
+
30
+ class Gui < Qt::Widget
31
+
32
+ attr_accessor :agents,:physics, :updating
33
+
34
+ @@r = 15 #circle radius
35
+
36
+ def initialize(parent = nil)
37
+ super()
38
+ @agents = {}
39
+ setPalette(Qt::Palette.new(Qt::Color.new(250, 250, 250)))
40
+ setAutoFillBackground(true)
41
+ @cur1 = self.cursor
42
+ @cur2 = Qt::Cursor.new(Qt::PointingHandCursor)
43
+ self.mouseTracking = true
44
+ @updating = false
45
+ end
46
+
47
+ #add an agent to the model
48
+ def add_agent agent
49
+ @agents[agent.agentname] = agent
50
+ @physics.add_object agent unless @physics.nil?
51
+ puts "Agent: #{agent.agentname} added."
52
+ end
53
+
54
+ #gets called when a repaint is necessary
55
+ def paintEvent(event)
56
+ @updating = true
57
+ painter = Qt::Painter.new(self)
58
+ painter.setRenderHint(Qt::Painter::Antialiasing)
59
+ painter.setBrush(Qt::Brush.new(Qt::Color.new(255,250,250,150)))
60
+ @agents.each do |agentname,agent|
61
+ painter.resetMatrix
62
+ painter.translate(agent.x,agent.y)
63
+ painter.setPen(Qt::Pen.new(Qt::blue))
64
+ painter.drawEllipse Qt::Rect.new(-@@r,-@@r, 2*@@r, 2*@@r)
65
+ painter.setPen(Qt::Pen.new(Qt::blue))
66
+ painter.drawEllipse Qt::Rect.new(-3*@@r,-3*@@r, @@r/2, @@r/2)
67
+ painter.setPen(Qt::Pen.new(Qt::blue))
68
+ painter.drawLine Qt::LineF.new(-2.5*@@r,-2.5*@@r, -0.8*@@r, -0.8*@@r)
69
+ painter.setPen(Qt::Pen.new(Qt::blue))
70
+ painter.drawText(-2*@@r,-2.5*@@r,"#{agentname}")
71
+ end
72
+ painter.end()
73
+ @updating = false
74
+ end
75
+
76
+ #mouse press event
77
+ def mousePressEvent event
78
+ @draginfo = nil
79
+ @physics.singularity = true unless @physics.nil?
80
+ if event.buttons == Qt::RightButton
81
+ elsif event.buttons == Qt::LeftButton
82
+ agent = object_at(event.x, event.y)
83
+ @draginfo = DragInfo.new(event.x, event.y, agent) unless agent.nil?
84
+ end
85
+ end
86
+
87
+ #returns object at x,y
88
+ def object_at x,y
89
+ @agents.each do |name,agent|
90
+ return agent if (agent.x-x)**2 + (agent.y-y)**2 <= @@r**2
91
+ end
92
+ return nil
93
+ end
94
+
95
+ #release mouse event
96
+ def mouseReleaseEvent event
97
+ update_drag_object event.x, event.y unless @draginfo.nil?
98
+ @physics.singularity = false unless @physics.nil?
99
+ end
100
+
101
+ #update dragged object
102
+ def update_drag_object x,y
103
+ @draginfo.object.x = x
104
+ @draginfo.object.y = y
105
+ update
106
+ end
107
+
108
+ #a mouse move event
109
+ def mouseMoveEvent event
110
+ self.cursor = object_at(event.x, event.y).nil? ? @cur1 : @cur2
111
+ if event.buttons == Qt::LeftButton and not @draginfo.nil?
112
+ update_drag_object event.x, event.y unless @draginfo.nil?
113
+ elsif event.buttons == Qt::RightButton
114
+ end
115
+ end
116
+
117
+ end
@@ -0,0 +1,102 @@
1
+ require 'rubygems'
2
+ require 'Qt4'
3
+ require 'flow_physics'
4
+ require 'qt_visual'
5
+ #require 'rofl' #sudo gem install pangdudu-rofl --source=http://gems.github.com
6
+ require 'robots' #sudo gem install pangdudu-robots --source=http://gems.github.com
7
+ require 'robots_xml'
8
+
9
+ class VisualizerAgent
10
+ include Robots
11
+ include RobotsXml
12
+
13
+ attr_accessor :roboname
14
+
15
+ def initialize argv
16
+ @roboname = "Visualizer" #name used in alive messages
17
+ ilog "#{@roboname} initialized"
18
+ @width, @height = 800,600
19
+ @app = Qt::Application.new(argv)
20
+ @agents = {} #thats where we register the agents in
21
+ end
22
+
23
+ #process an info message
24
+ def process_info xml_msg
25
+ infos = parse_xml_msg xml_msg,"//info"
26
+ infos.each do |i|
27
+ unless i.attributes["alive"].nil?
28
+ agentname = i.attributes["alive"]
29
+ @agents[agentname] = "#{i.attributes["timestamp"]}"
30
+ unless @gui.nil?
31
+ x_rnd = 23-rand(46)/2
32
+ y_rnd = 23-rand(46)/2
33
+ @gui.add_agent Agent.new(agentname,@width/2+x_rnd,@height/2+y_rnd) unless @gui.agents.has_key? agentname
34
+ end
35
+ #cleanup gui agent model - not yet implemented
36
+ end
37
+ end
38
+ end
39
+
40
+ #ROBOTS message parsing stuff
41
+
42
+ #method that gets called when a new message arrives
43
+ def receive_msg msg
44
+ check_for_interests msg
45
+ end
46
+
47
+ #check if this msg interests us
48
+ def check_for_interests xml_msg
49
+ #message filter callback looks like this now
50
+ info = parse_xml_msg xml_msg,"//info"
51
+ process_info xml_msg unless info.empty?
52
+ end
53
+
54
+ def start_qt_visualizer
55
+ @gui = Gui.new
56
+ @physics = Physics.new(@width,@height,@gui)
57
+ #dirty qt timer magic to make ruby threads work
58
+ sleep 0.5
59
+ block=Proc.new{ Thread.pass }
60
+ timer=Qt::Timer.new(@gui)
61
+ invoke=Qt::BlockInvocation.new(timer, block, "invoke()")
62
+ Qt::Object.connect(timer, SIGNAL("timeout()"), invoke, SLOT("invoke()"))
63
+ sleep 0.5
64
+ timer.start(1000/60) #in millis
65
+ #end of dirty timer hack
66
+ @gui.physics = @physics
67
+ @gui.resize(@width, @height)
68
+ @gui.show()
69
+ #just because it's fun
70
+ add_dbug_agents
71
+ @app.exec()
72
+ end
73
+
74
+ #debug method to add agents quickly
75
+ def add_dbug_agents
76
+ dbug_agents = ["Jeanette","Kurt","Maurice","Patrice"]
77
+ dbug_agents.each do |agentname|
78
+ x_rnd = 23-rand(46)/2
79
+ y_rnd = 23-rand(46)/2
80
+ @gui.add_agent Agent.new("dbug.#{agentname}",@width/2+x_rnd,@height/2+y_rnd)
81
+ end
82
+ end
83
+ end
84
+
85
+ #start the app
86
+ va = VisualizerAgent.new(ARGV)
87
+ va.release_robots #start the robot agent module
88
+
89
+ Thread.new do
90
+ sleep 1
91
+ #build you own loop if you need one
92
+ loop do
93
+ sleep 1
94
+ #send an xml message over the system
95
+ #alive_msg = va.create_xml_alive_msg
96
+ #dlog "alive_msg: #{alive_msg.to_s}"
97
+ #va.send_msg alive_msg
98
+ end
99
+ end
100
+
101
+ va.start_qt_visualizer
102
+
data/lib/robots.rb CHANGED
@@ -1,3 +1,4 @@
1
+ require 'socket' #to get hostname etc.
1
2
  require 'rubygems'
2
3
  require 'rofl' #gem install pangdudu-rofl --source=http://gems.github.com
3
4
  #local requires, actually don't need them, just to let you know whats going on
@@ -5,7 +6,7 @@ require 'robots_agent'
5
6
 
6
7
  module Robots
7
8
 
8
- attr_accessor :robotsagent,:haz_robots
9
+ attr_accessor :robotsagent,:haz_robots,:hostname
9
10
 
10
11
  #release the robots
11
12
  def release_robots
@@ -27,6 +28,7 @@ module Robots
27
28
  @haz_robots = @robotsagent.nil?
28
29
  if @haz_robots
29
30
  @robotsagent = Robot.new
31
+ @hostname = @robotsagent.hostname
30
32
  @robotsagent.run
31
33
  @robotsagent.add_listener self
32
34
  end
data/lib/robots_agent.rb CHANGED
@@ -1,27 +1,36 @@
1
1
  require 'rubygems'
2
- require 'dbus' #gem install sdague-ruby-dbus --source=http://gems.github.com
2
+ require 'dbus' #gem install pangdudu-ruby-dbus --source=http://gems.github.com
3
+ require 'dbus-daemon' #gem install pangdudu-ruby-dbus-daemon --source=http://gems.github.com
3
4
  require 'rofl' #gem install pangdudu-rofl --source=http://gems.github.com
4
5
  #local requires, actually don't need them, just to let you know whats going on
5
6
  require 'robots_infrastructure'
6
7
 
7
8
  class Robot
8
- attr_accessor :avahi
9
- attr_accessor :emitters,:infrastructure,:listeners
9
+ attr_accessor :dbusdaemon #in case we use a custom dbus-daemon
10
+ attr_accessor :avahi #for mdns service discovery
11
+ attr_accessor :emitters,:infrastructure,:listeners #stuff a robot needs
12
+ attr_accessor :hostname #infos
10
13
 
11
14
  def initialize
12
15
  dlog "new Robot initialized."
16
+ @hostname = Socket.gethostname
17
+ @sessiontype = "system" #could be session,system or robots (use robots, if you want it to work over multiple hosts)
18
+ @daemonconfig = "~/.robots/config/remote.session.dbus.conf" #listens on path and tcp
19
+ @dbusdaemon = nil #we'll start our own dbus-daemon if we have to
20
+ @dbussession = nil #get_bus will get one for us
21
+ @coreservice = nil #the service we use to export objects with
13
22
  @robotsservice = "org.robots.Service"
14
23
  @emitterpath = "/org/robots/Service/Emitter"
15
24
  @emitterinterface = "org.ruby.Service.EmitterInterface"
16
- @coreservice = nil
17
25
  @listeners = [] # listeners for incoming messages are here
18
26
  @emitters = {} #holds emitters we use
19
27
  @infrastructure = {} #holds infrastructure objects
20
- @servicetypes = fill_servicetypes
28
+ @servicetypes = fill_servicetypes #refer to robots_infrastructure.rb
21
29
  end
22
30
 
23
31
  #start the mojo
24
32
  def run
33
+ check_for_dbus_daemon if @sessiontype.eql? "robots" #will start a daemon if necessary
25
34
  setup_robots_service
26
35
  register_callbacks
27
36
  #test_messages; #main_loop;
@@ -45,6 +54,28 @@ class Robot
45
54
  the following methods are only called, if the robots service is not already running
46
55
  =end
47
56
 
57
+ #check if a dbus-daemon suitable for robots is running, otherwise start one
58
+ def check_for_dbus_daemon
59
+ @daemonconfig = File.expand_path(@daemonconfig) #dbus-daemon won't accept otherwise
60
+ #ok, no config file, not good!
61
+ unless File.exist? @daemonconfig
62
+ wlog "no daemon config: #{@daemonconfig}!"
63
+ wlog "will sleep for 5 seconds,..."
64
+ sleep 5 #give the user time to realize
65
+ end
66
+ #if the config file is there
67
+ if File.exist? @daemonconfig
68
+ @dbusdaemon = DbusDaemon.new @daemonconfig
69
+ got_twins = @dbusdaemon.got_twin_daemon? #check if a daemon like this is already running
70
+ ilog "custom dbus-daemon is already running." if got_twins #inform user
71
+ unless got_twins #no suitable dbus-daemon running, start one
72
+ @dbusdaemon.start_daemon
73
+ ilog "custom dbus-daemon started and running, check \"ps x | grep \"dbus-daemon\", if plan a CTRL-C."
74
+ #@dbusdaemon.stop_daemon #must get called sometimes, super nasty, use " ps x | grep "dbus-daemon" "
75
+ end
76
+ end
77
+ end
78
+
48
79
  #setup the infrastructure objects for communication
49
80
  def init_robots_infrastructure
50
81
  emitter = Emitter.new(@emitterpath,self)
@@ -60,7 +91,7 @@ class Robot
60
91
 
61
92
  #start a service
62
93
  def start_core_service service_name=@robotsservice
63
- bus = DBus::system_bus
94
+ bus = get_bus
64
95
  #first of all check if the service we want to launch is already started
65
96
  dlog "skipping service: #{service_name} has already been started." if running? service_name
66
97
  unless running? service_name
@@ -78,7 +109,7 @@ class Robot
78
109
  def get_object_from_service service_name,obj_path,default_iface
79
110
  begin
80
111
  if running? service_name
81
- bus = DBus::system_bus
112
+ bus = get_bus
82
113
  ruby_service = bus.service(service_name)
83
114
  obj = ruby_service.object(obj_path)
84
115
  obj.introspect
@@ -94,10 +125,10 @@ class Robot
94
125
 
95
126
  #register callback methods
96
127
  def register_callbacks
97
- bus = DBus::system_bus
98
128
  #setup callbacks for infrastructure emitters
99
129
  @emitters.each { |name,emitter| register_emitter_callback name,emitter }
100
130
  #setup service browser
131
+ bus = DBus::SystemBus.instance #needs to be the system bus for the avahi stuff
101
132
  proxy = bus.introspect("org.freedesktop.Avahi","/")
102
133
  @avahi = proxy["org.freedesktop.Avahi.Server"]
103
134
  @servicetypes.each { |name,type| register_service_callback name,type }
@@ -105,7 +136,8 @@ class Robot
105
136
 
106
137
  #register an emitter callback
107
138
  def register_emitter_callback name,emitter
108
- bus = DBus::system_bus
139
+ bus = get_bus
140
+ #dlog "emitter.inspect #{emitter.inspect}"
109
141
  dlog "registering callback for #{name} on path #{emitter.path}"
110
142
  mr = DBus::MatchRule.new
111
143
  mr.type = "signal"
@@ -128,7 +160,7 @@ class Robot
128
160
 
129
161
  #builds a service type specific callback
130
162
  def register_service_callback name,type
131
- bus = DBus::system_bus
163
+ bus = DBus::SystemBus.instance #needs to be the system bus for the avahi stuff
132
164
  sb = @avahi.ServiceBrowserNew(-1,-1,"_#{type}._tcp","local",0)
133
165
  #now we start the match rule definition
134
166
  mr = DBus::MatchRule.new
@@ -150,7 +182,7 @@ class Robot
150
182
 
151
183
  #check if a service is running
152
184
  def running? service_name
153
- bus = DBus::system_bus
185
+ bus = get_bus
154
186
  return bus.proxy.ListNames[0].include? service_name
155
187
  end
156
188
 
@@ -174,6 +206,26 @@ class Robot
174
206
  end
175
207
  end
176
208
 
209
+ #get the bus session, cleaner then creating new sessions all over
210
+ def get_bus
211
+ if @dbussession.nil?
212
+ @dbussession = DBus::SystemBus.instance if @sessiontype.eql? "system"
213
+ @dbussession = DBus::SessionBus.instance if @sessiontype.eql? "session"
214
+ if @sessiontype.eql? "robots"
215
+ #i somehow feel bad for doing it like this with ENV[]:
216
+ @robots_socket_name = "unix:path=/tmp/robots_session_bus_socket" #look at: config/remote.session.dbus.conf
217
+ DBus.const_set("SessionSocketName", @robots_socket_name) #overwrite the modules constant
218
+ @dbussession = DBus::SessionBus.instance
219
+ end
220
+ end
221
+ #no point if this is still true :)
222
+ if @dbussession.nil?
223
+ elog "@dbussession is nil! will exit now, sorry."
224
+ exit(0)
225
+ end
226
+ return @dbussession
227
+ end
228
+
177
229
  #functions used by the module end here
178
230
 
179
231
  #dbus main loop
@@ -187,7 +239,7 @@ class Robot
187
239
  def test_messages
188
240
  Thread.new do
189
241
  loop do
190
- msg = "it worx from alpha!"
242
+ msg = "it worx from robots agent!"
191
243
  send_msg msg
192
244
  sleep 1
193
245
  end
@@ -195,9 +247,12 @@ class Robot
195
247
  end
196
248
 
197
249
  #list names of a proxy object
198
- def list_names proxy=@dbus.proxy
250
+ def list_names proxy=nil
251
+ if proxy.nil?
252
+ bus = get_bus
253
+ proxy = bus.proxy
254
+ end
199
255
  dlog "listnames:"
200
256
  proxy.ListNames[0].each { |name| dlog name }
201
- @services.each { |name,service| dlog "service introspection for #{name} introspection: #{service.introspect}" }
202
257
  end
203
258
  end
@@ -2,7 +2,7 @@
2
2
  this includes all the necessary dbus objects we need for the robots infrastructure
3
3
  =end
4
4
  require 'rubygems'
5
- require 'dbus' #gem install sdague-ruby-dbus --source=http://gems.github.com
5
+ require 'dbus' #gem install pangdudu-ruby-dbus --source=http://gems.github.com
6
6
  require 'rofl' #gem install pangdudu-rofl --source=http://gems.github.com
7
7
 
8
8
  #basic emitter class
@@ -12,7 +12,10 @@ class RobotsProto
12
12
  include Robots
13
13
  include RobotsXml
14
14
 
15
+ attr_accessor :roboname
16
+
15
17
  def initialize
18
+ @roboname = "Robots Prototype" #name used in alive messages
16
19
  ilog "RobotsProto initialized"
17
20
  end
18
21
 
@@ -41,5 +44,5 @@ rp.release_robots #start the robot agent module
41
44
  loop do
42
45
  sleep 1
43
46
  #send an xml message over the system
44
- rp.send_msg rp.create_xml_msg { |b| b.body("test"); b.info("timestamp" => "#{Time.now}") }
47
+ rp.send_msg rp.create_xml_alive_msg
45
48
  end
data/lib/robots_xml.rb CHANGED
@@ -22,5 +22,17 @@ module RobotsXml
22
22
  return xml = Hpricot.XML("<msg>parsing error</msg>")
23
23
  end
24
24
  end
25
+
26
+ #SPECIALS
27
+
28
+ #create an alive message
29
+ def create_xml_alive_msg
30
+ @hostname = "localhost" if @hostname.nil? #more fun with hostname
31
+ @roboname = "Nameless" if @roboname.nil? #at least it's nameless
32
+ robotsid = "#{@hostname}.#{@roboname.gsub(" ","_")}" #looks cooler
33
+ msg = create_xml_msg { |b| b.info("#{@roboname} alive","alive"=>"#{robotsid}","timestamp" => "#{Time.now}") }
34
+ return msg
35
+ end
36
+
25
37
  end
26
38
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pangdudu-robots
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - pangdudu
@@ -22,6 +22,16 @@ dependencies:
22
22
  - !ruby/object:Gem::Version
23
23
  version: "0"
24
24
  version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: pangdudu-rofl
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
34
+ version:
25
35
  description: robots!
26
36
  email: pangdudu@github
27
37
  executables:
@@ -39,6 +49,11 @@ files:
39
49
  - lib/robots_xml.rb
40
50
  - lib/robots_prototype.rb
41
51
  - config/org.robots.service.conf
52
+ - config/remote.session.dbus.conf
53
+ - config/start_dbus_session.sh
54
+ - funky-examples/visualizer-agent/flow_physics.rb
55
+ - funky-examples/visualizer-agent/qt_visual.rb
56
+ - funky-examples/visualizer-agent/visualizer_agent.rb
42
57
  - funky-examples/talking-swift-agent/README
43
58
  - funky-examples/talking-swift-agent/talking_swift_agent.rb
44
59
  - funky-examples/talking-swift-agent/text_generator.rb