Ah, I forgot the original context you were working in!

All the suggestions I've made previously could be considered as trying to  
this problem: that the ConsoleReader component not only reads user input,  
but also generates a prompt for it (which it directly writes to the  
console (standard output).

It sounds like what you actually are after building is a simple chat  
protocol - abstracted away from having to know about where its input is  
coming from or where its output is going to. The ConsoleReader component  
mixes a bit of both - it handles the sourcing of input, but also generates  
some output itself (the prompt) and worse still, it puts this output onto  
the console directly! :-)

So what you're actually after is what you originally had:

     Pipeline(
         SourceOfInput(),
         MyComponent(),
         DestinationForOutput()
     )

So for testing your chat protocol component MyComponent - we can still use  
ConsoleReader and ConsoleEchoer. We just have to ignore the '>>>' prompt  
generated by the ConsoleReader and pretend its not there.

When you plug Mycomponent into the ConnectedServer (also known as  
SimpleServer in more recent subversion copies of Kamaelia iirc) as its  
protocol, it gets wired up in much the same way as above - data coming  
 from the client will get send to its inbox and data send out of its outbox  
will be sent back to the client.

So all of the Seq stuff is not strictly necessary. All you need to do is  
encode the sequential behaviour into the main() generator in MyComponent.  
For example something along the lines of this (note the shutdown handling  
makes it a little messier that it might otherwise be):

     def main(self):
         mustStop = false;

         # 1) generate login prompt
         self.send("Enter username:", "outbox")

         # 2) wait for response
         mustStop = self.doShutdown()
         while not mustStop and not self.dataReady("inbox"):
             self.pause()
             yield 1
             mustStop = self.doShutdown()

         if mustStop:
             return

         username = self.recv("inbox")

         # 3) welcome
         self.send("Welcome "+username+"! Begin chatting!")

         # 4) do chatting
         ...

One other thing to consider is that the ConsoleReader specifically buffers  
input until a whole line is received from the user, before outputting that  
as a single string message to its "outbox" outbox. Whereas the socket  
connection may send fragments of strings before a whole line has been  
entered. A component such as this one can sort that out for you:  
http://www.kamaelia.org/Components/pydoc/Kamaelia.Visualisation.PhysicsGraph.chunks_to_lines.html

Simply pipeline it with MyComponent and make that the protocol thats given  
to the ConnectedServer:

     def myProtocol():
         return Pipeline(
             chunks_to_lines(),
             MyComponent()
         )

     ...

     ConnectedServer(protocol=myProtocol, port=WHATEVER).run()



Matt


On Tue, 03 Mar 2009 04:35:07 -0000, Gloria W <strang...@comcast.net> wrote:

> I got the carousel example working, but it sends/receives from/to the
> original console, not any new client which connects. I realized I can
> reuse the ConsoleEchoer, but somehow make it send a string to a client
> upon connect, and have the server process the string instead of echoing
> it to the server's console.
> I tried this, but all proposed solutions so far write to the console,
> not a newly connected client. Maybe I am missing something, btu I think
> I am close.
>
>  Aside from this, I was wondering if a carousel or seq will be
> appropriate to solve my problem.
>
> I am trying to simulate what happens in crude chat systems such as IRC.
> For simplicity, in this example the user connects, is prompted for a
> name, and then can chat freely.
> If I have two pipelines: one detects client connect and is prompting for
> a name, receiving the response, and then handing control over to another
> pipeline; doesn't this require a disconnect/reconnect with the client?
> If so, this would be bad, because the user would have to re-telnet in,
> would not be "logged in", and would have to start again.
>
> So I guess if I get the data flow working, I can write this logic in one
> pipeline, and reuse the same connection, assuming the first thing a user
> types after connecting would be the name. Or maybe there is a clever way
> to hand off a connected pipline to another utility, so that my flow
> control is cleaner? (not running an "if name is set" check upon each
> message).
>
> Thanks again for your help,
> Gloria
>
>
>>  This is really cool, and exactly what I need. I will get some time
>> later to implement this and try it out, and I am sure I'll have more
>> questions and comments.
>> Thanks again for this.
>> Gloria
>>> On Mar 2, 8:36 pm, Gloria W <strang...@comcast.net> wrote:
>>>
>>>> Matt, thanks for this response. It took me a while to get through it  
>>>> and
>>>> make sure I understood each point. I appreciate it, comments are  
>>>> below.
>>>>
>>>
>>> No problem.
>>>
>>> I've just realised another way to achieve the same effect that is
>>> probably simpler!
>>>
>>> There *is* a component that is all about getting things done in an
>>> order: the Seq component (The name is a homage to the OCCAM language):
>>>
>>>     http://www.kamaelia.org/Components/pydoc/Kamaelia.Chassis.Seq.html
>>>
>>> With Seq, you provide a list of components. Seq goes through the list,
>>> starting with the first component. It activates it and wires up its
>>> inboxes and outboxes so that they're mapped to the Seq component's
>>> inboxes and outboxes (just like the Carousel does). When that
>>> component finishes, it then unwires it and moves onto the next in the
>>> list. It therefore effectively runs them *in sequence* one after the
>>> other.
>>>
>>> We've got two steps: displaying the initial message, then taking user
>>> input. Both steps need their output to be displayed. So we'll create a
>>> Seq componet, Pipeline'd into a console echoer:
>>>
>>>     from Kamaelia.Chassis.Seq import Seq
>>>
>>>     Pipeline(
>>>         Seq( ... args to be determined! ... ),
>>>         ConsoleEchoer()
>>>     ).run()
>>>
>>> We can use a OneShot component (see  
>>> http://www.kamaelia.org/Components/pydoc/Kamaelia.Util.OneShot.html
>>> ) to send that initial message, so that it gets sent to the
>>> ConsoleEchoer and displayed. OneShot, rather conveniently, then
>>> immediately terminates; so the Seq component will move onto the next
>>> component in its list. That next component can be the Pipeline of a
>>> ConsoleReader, sending its output into MyComponent.
>>>
>>> So what we have is:
>>>
>>>     from Kamaelia.Chassis.Seq import Seq
>>>     from Kamaelia.Util.OneShot import OneShot
>>>
>>>     Pipeline(
>>>         Seq(
>>>             OneShot("initial message to be displayed"),
>>>             Pipeline(
>>>                 ConsoleReader(),
>>>                 MyComponent()
>>>             )
>>>         ),
>>>         ConsoleEchoer()
>>>     ).run()
>>>
>>> In this case, MyComponent doesn't need to bother to send the initial
>>> message itself, as it did in the suggestion I previously made.
>>>
>>> So what happens here? Well, when the system starts running, initially
>>> the Seq component selects the first item in its list - the OneShot
>>> component. So, what actually ends up getting wired up is something
>>> like this:
>>>
>>>     Pipeline(
>>>         OneShot("initial message to be displayed"),
>>>         ConsoleEchoer()
>>>     )
>>>
>>> Its not actually exactly like that, because the OneShot is still
>>> contained within the Seq component - but because all the inboxes and
>>> outboxes are mapped to that of the Seq component, it is roughly
>>> equivalent.
>>>
>>> Then when the OneShot component has sent its message and terminated,
>>> the Seq component swaps it out and replaces it with the next thing in
>>> its list - the pipeline of a ConsoleReader and MyComponent. So the way
>>> the system is wired up suddenly switches to something akin to this:
>>>
>>>     Pipeline(
>>>         Pipeline(
>>>             ConsoleReader(),
>>>             MyComponent()
>>>         ),
>>>         ConsoleEchoer()
>>>     )
>>>
>>> Again, the inner pipeline is, in reality, contained within the Seq
>>> component, but it behaves roughly like it is shown.
>>>
>>>
>>>
>>>
>>> Matt
>>>
>>>
>>>
>>>
>>>
>>>
>>
>>
>> >
>
>
> >



-- 
| Matt Hammond
| Research Engineer, FM&T, BBC, Kingswood Warren, Tadworth, Surrey, UK
| http://www.bbc.co.uk/rd/

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

Reply via email to