Updated Group example

3 views
Skip to first unread message

Jay Herrmann

unread,
Sep 16, 2010, 4:07:44 PM9/16/10
to pysage
Hi John,

I was needing to test the queue_message_to_group so I modified your
example. Thought I would pass back.

Jay.

FYI: using pysage 1.5.5
-------------------------------------

from pysage import *
import time, random

class FoodOnTableMessage(Message):
properties = ['amount']
types = ['i']
packet_type = 101

class FoodAvailableMessage(Message):
properties = ['amount']
types = ['i']
packet_type = 102

class Consumer(Actor):
subscriptions = ['FoodOnTableMessage']
def handle_FoodOnTableMessage(self, msg):
print 'Yummy! I had %d pancakes!' %
(msg.get_property('amount'))

class Waiter(Actor):
subscriptions = ['FoodAvailableMessage']
def __init__(self):
self.last_sent = time.time()
self.PancakeCount = 0
def handle_FoodAvailableMessage(self, msg):
self.PancakeCount = self.PancakeCount +
msg.get_property('amount')
def update(self):
'''every 2 seconds, this waiter delivers 5 or fewer
pancakes'''
if time.time() - self.last_sent > 2.0:
self.last_sent = time.time()
if self.PancakeCount > 0:
DeliverCount=self.PancakeCount
if DeliverCount > 5:
DeliverCount = 5
self.PancakeCount = self.PancakeCount - DeliverCount
print 'Here are your %d pancakes, sir!' %
(DeliverCount)
mgr.queue_message_to_group('Consumers',
FoodOnTableMessage(amount=DeliverCount))

class Chef(Actor):
def __init__(self):
self.last_sent = time.time()
def update(self):
'''every 4 seconds, this chef makes a random amount of
pancakes'''
if time.time() - self.last_sent > 4.0:
PancakeCount = random.randint(1,12)
print '%d pancakes up!!' % PancakeCount
mgr.queue_message_to_group(mgr.PYSAGE_MAIN_GROUP,
FoodAvailableMessage(amount=PancakeCount))
self.last_sent = time.time()

mgr = ActorManager.get_singleton()
mgr.register_actor(Waiter())

if __name__ == '__main__':
mgr.enable_groups()
mgr.add_process_group('chefs', Chef) # spawns a new process
that "ticks" independently
mgr.add_process_group('Consumers', Consumer) # spawns a new
process that "ticks" independently
while True:
processed = mgr.tick()
time.sleep(.03)

John Yang

unread,
Sep 16, 2010, 4:55:11 PM9/16/10
to pys...@googlegroups.com
Neat! I like this example a lot. It illustrates the server-client
model that pysage groups are built around. I thought a lot about
whether to enable messaging across groups, but preferred the
simplicity of the server-client model.

I'll be sure to add this to the documentation.

Thanks Jay.

John

> --
> You received this message because you are subscribed to the Google Groups "pysage" group.
> To post to this group, send email to pys...@googlegroups.com.
> To unsubscribe from this group, send email to pysage+un...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/pysage?hl=en.
>
>

Jay Herrmann

unread,
Sep 16, 2010, 5:54:33 PM9/16/10
to pys...@googlegroups.com
Glad you liked the example. I was thinking of adding a pool of
waiters and have the current waiter ask for help. But I could not
think of how to do this quickly. :) That is how to code it quickly
not my application speed. :)

Jay.

Jay Herrmann

unread,
Sep 16, 2010, 6:30:03 PM9/16/10
to pys...@googlegroups.com
John,

Just to make sure I understand the group IPC structure. The MAIN
Group can receive and transmit to Child Groups and it's self; and
Child Groups can only receive and transmit to the MAIN Group only. I
know your comments above state this and my testing confirms this.
Sometimes I assume meaning and the assumption bites me 99% of time. :)

Jay.

John Yang

unread,
Sep 16, 2010, 6:50:25 PM9/16/10
to pys...@googlegroups.com
Jay,

Yeap, that's what I meant by server-client. The "MAIN" group is the
process where you first started your executable and it serves as a
server. All child groups serve as clients, so they do not know about
each other. They only know the server.

Having this simplicity makes things like starting/stopping child
groups directly from the "MAIN" group rather safe. But when the need
arises, it shouldn't be too hard to enable child groups to directly
talk to each other.

John

Jay Herrmann

unread,
Sep 16, 2010, 10:43:01 PM9/16/10
to pys...@googlegroups.com
I think I like the server-client, one to many, observer pattern at the
moment. It will make debugging easier and I think your pysage code
will be safer (as you said).

I changed my coding philosophy to use this style. I made my MAIN
Group a dispatcher and used a dictionary to call the child Group
Message. See below:

class MainGroupMessage(Message):
properties = ['ActionGroup','Action','ActionDict']
types = ['S','S','S']
packet_type = 101
def pack_ActionDict(self, ActionDict):
return json.dumps(ActionDict)
def unpack_ActionDict(self, ActionDict_s):
return json.loads(ActionDict_s)

In 'ChildGroup1' Actor I call the Main Group
self.DictOfInfo={'date':'09-09-2010,'user':'John Doe'}
mgr.queue_message_to_group(mgr.PYSAGE_MAIN_GROUP,
MainGroupMessage(ActionGroup='ChildGroup2',Action='Add',ActionDict =
self.DictOfInfo))

In MainGroupActor Init define
self.DispatchActions = {'ChildGroup1' : {},
'ChildGroup2' : {},
'' : {},
}
self.DispatchActions['ChildGroup1'] = {'' : self.Default}
self.DispatchActions['ChildGroup2'] = { 'Add' : self.Add_ToChildGroup2,
'' : self.Default,
}
self.DispatchActions[''] = {'' : self.Default}


In MainGroupActor define
def handle_MainGroupMessage(self, msg):
self.DispatchActions[msg.get_property('ActionGroup')][msg.get_property('Action')](msg)
def Default(self,msg):
print "Run Default Action.\n"

def Add_PreProcessBTInquiryGroup(self,msg):
print "Add ChildGroup2 Action"
mgr.queue_message_to_group([msg.get_property('ActionGroup')],
ChildGroup2Message(Data = msg.get_property('ActionDict')))


I am impressed at python's dictionary and how flexible it is.
I hope I, 1. was not to confusing, 2. was not to boring. :)

Thanks for your help,
Jay.

John Yang

unread,
Sep 17, 2010, 2:25:56 AM9/17/10
to pys...@googlegroups.com
Wow for the pseudo code :). I think your idea is clear. You can use
the main group to proxy messages between child groups. The only thing
is when the volume of such interaction becomes large, there may be
some efficiency issues. But then again, if two child groups need to
talk to each other with such volume, they may better end up in the
same group.

Welcome to the snake world! It's not the first time I've heard of
python and embedded devices actually.

Have you checked out python's coroutines? You can do some very
serious things with it.

Don't forget to:

>>> import this
>>> ...

Cheers,

John

John Yang

unread,
Sep 22, 2010, 8:13:56 PM9/22/10
to pys...@googlegroups.com
Hi Jay:

Just FYI. I added your example to the documentation:

http://www.bigjstudio.com/pysage/ipc.html#dual-group-example

I also started a contributor's list here:

http://www.bigjstudio.com/pysage/index.html#contributors

Thanks,

John

Jay Herrmann

unread,
Sep 23, 2010, 12:15:26 PM9/23/10
to pys...@googlegroups.com
Glad to help. :)
Jay
Reply all
Reply to author
Forward
0 new messages