pangdudu-robots 0.2.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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