The blocking client is the most straight-forward way of querying a KATCP device. It is used as follows:
After creating the BlockingClient instance, the start() method is called to launch the client thread. The wait_protocol() method waits until katcp version information has been received from the server, allowing the KATCP version spoken by the server to be known; server protocol iformation is stores in client.protocol_flags. Once you have finished with the client, stop() can be called to request that the thread shutdown. Finally, join() is used to wait for the client thread to finish.
While the client is active the blocking_request() method can be used to send messages to the KATCP server and wait for replies. If a reply is not received within the allowed time, a RuntimeError is raised.
If a reply is received blocking_request() returns two values. The first is the Message containing the reply. The second is a list of messages containing any KATCP informs associated with the reply.
For situations where one wants to communicate with a server but doesn’t want to wait for a reply, the CallbackClient is provided:
Note that the reply_cb() and inform_cb() callback functions are both called inside the client’s event-loop thread so should not perform any operations that block. If needed, pass the data out from the callback function to another thread using a Queue.Queue or similar structure.
If neither the BlockingClient nor the CallbackClient provide the functionality you need then you can sub-class DeviceClient which is the base class from which both are derived.
The send_message() method does not return an error code or raise an exception if sending the message fails. Since the underlying protocol is entirely asynchronous, the only means to check that a request was successful is receive a reply message. One can check that the client is connected before sending a message using is_connected().
Sending requests to clients is discouraged. The handle_request() is provided mostly for completeness and to deal with unforseen circumstances.
Your own client may hook into this dispatch tree at any point by implementing or overriding the appropriate methods.
The high level client API inspects a KATCP device server and presents requests as method calls and sensors as objects.
Creating a server requires sub-classing DeviceServer. This class already provides all the requests and inform messages required by the KATCP protocol. However, its implementation requires a little assistance from the subclass in order to function.
Request handlers are added to the server by creating methods whose names start with “request_”. These methods take two arguments – the client-request object (abstracts the client socket and the request context) that the request came from, and the request message. Notice that the message argument is missing from the methods in the example. This is a result of the request() decorator that has been applied to the methods.
The request() decorator takes a list of KatcpType objects describing the request arguments. Once the arguments have been checked they are passed in to the underlying request method as additional parameters instead of the request message.
If multiple servers are started in a single ioloop, on_shutdown() should be modified to call stop() on each server. This is needed to allow a clean shutdown that adheres to the KATCP spec requirement that a #disconnect inform is sent when a server shuts down.
As of version 0.6.0, katcp-python was completely reworked to use Tornado as an event- and network library. A typical Tornado application would only use a single tornado.ioloop.IOLoop event-loop instance. Logically independent parts of the application would all share the same ioloop using e.g. coroutines to allow concurrent tasks.
Note that any message (request, reply, iform) handling methods should not block. A blocking handler will block the ioloop, causing all timed operations (e.g. sensor strategies), network io, etc. to block. This is particularly important when multiple servers/clients share a single ioloop. A good solution for handlers that need to wait on other tasks is to implement them as Tornado couroutines. A DeviceServer will not accept another request message from a client connection until the request handler has completed / resolved its future. Multiple outstanding requests can be handled concurrently by raising the AsyncReply exception in a request handler. It is then the responsibility of the user to ensure that a reply is eventually sent using the req object.
In the case of a purely network-event driven server or client, all user code would execute in the thread context of the server or client event loop. Therefore all handler functions must be non-blocking to prevent unresponsiveness. Unhandled exceptions raised by handlers running in the network event-thread are caught and logged; in the case of servers, an error reply including the traceback is sent over the network interface. Slow operations (such as picking fruit) may be delegated to another thread (if a threadsafe server is used), a callback (as shown in the request_pick_fruit handler in the server example) or tornado coroutine.
If a device is linked to processing that occurs independently of network events, one approach would be a model thread running in the background. The KATCP handler code would then defer requests to the model. The model must provide a thread-safe interface to the KATCP code. If using an async server (e.g. AsyncDeviceServer or DeviceServer.set_concurrency_options() called with thread_safe=False ), all interaction with the device server needs to be through the tornado.ioloop.Ioloop.add_callback() method of the server’s ioloop. The server’s ioloop instance can be accessed through its ioloop attribute. If a threadsafe server (e.g. DeviceServer with default concurrency options) or client (e.g. CallbackClient) is used, all the public methods provided by this katcp library for sending !replies or #informs are thread safe.
Updates to Sensor objects using the public setter methods are always thread-safe, provided that the same is true for all the observers attached to the sensor. The server observers used to implement sampling strategies are threadsafe, even if an asyc server is used.
A minor modification of the first several lines of the example in Writing your own Server suffices to create a KATCP v4 server:
The DeviceClient client automatically detects the version of the server if it can, see Server KATCP Version Auto-detection. For a simple client this means that no changes are required to support different KATCP versions. However, the semantics of the messages might be different for different protocl versions. Using the unpack_message decorator with major=4 for reply or inform handlers might help here, although it could use some improvement.
I had not heard before of the charity Playlist for Life, which this concert was supporting. Given that each of the singers had been asked to choose their own song, it was amazing to listen to the variety of songs and the depth of emotions that were expressed.
Well done to everyone for an excellent evening and for giving their time and their talent to this concert. Well done for raising such a huge sum for the charity.” Derek M.
Thank you so much to everyone who came to join us on Friday for our first ever Summer Concert: A Souvenir.
The idea for this event was originally to raise money for a dementia charity. This was intended to be in memory of my mother-in-law Brenda, who passed away from Dementia on 9thNovember 2017: It was her birthday.
When organizing this concert, I asked my father-in-law which charity we should donate to and he chose Playlist for Life. I feel that the charity are a perfect choice, as they provide music for dementia patients. Every piece of music that we performed on Friday had a special memory attributed to it.
The idea that memories are contained in music is proven by science. ‘Flashback’ memories can be triggered by music taking us back to a vision of our past.
What I had not expected was the unbelievable efforts these musicians went to in order to choose the perfect piece of music for the occasion. From songs chosen and discarded for another, to those who knew exactly what they wanted to sing straight away. We had a wide variety of music to share varying from: old and new, classical and pop, early music and rap, musical theatre and acoustic as well as songs used in film.
The personal stories shared provided a poignant “envelope of joy” (thanks Jamie for this title!) – The choices were made in memory of people we love, to recognize our own strength and the strength of others, to support those facing hardship, to thank people we care about for their honest friendships, to thank the supportive carers who look after our loved ones, to prove how we have each pulled through difficult times, to contemplate happiness and, importantly – to simply get lost in the enjoyment and nostalgia brought to us by listening to music we love, and have loved.
I am honored and humbled by the incredible stories that everybody shared – some stories were happy, some were sad, some were somewhere in between. Throughout the planning of the concert we initially set out to raise awareness of dementia – however, in addition we have been dealing with bereavement, troubled childhoods, coping with mental health, dealing with divorce, standing up to bullying, overcoming domestic violence and what I have learned in all of this is that:
Singing provides us with enjoyment, courage, escape and refuge from life’s many troubles. It inspires us to socialise and be a part of a friendly community to share our voices.
In the weeks leading up to the concert, two performers sadly lost their sister to dementia and another singer lost her Nan. We dedicated our music to their memory too. Many of our performers and our audience have been directly affected by the emotions presented when a loved one is diagnosed with dementia. We hope that our donation to Playlist for Life will help bring music to those closest to us, as well as others around the world.
Friday evening also served as an exploration of new music. We hoped to provide inspiration to enjoy music from years gone by at home. There is so much magic to be found in songs from our past.
This concert allowed singers to showcase their hard work, talent and musical skills. Many of them sang in public for the first time and the support and gratitude from the audience was palpable. Without them, we would not have a concert to perform!
I also want to take a moment to reveal how incredible our community is – so many people joined us both to perform and watch, in order to support one another. It was a thrill to see so many friendly faces.
Finally, a big thanks to Liz for suggesting Newcastle Baptist Church to host this event and helping with all the organisation. Everyone has commented what a wonderful space you have there and we would love to come and sing again. Thank you to Annie for printing programmes and selling tickets on the door, to Lisa for her marketing skills and ticket sales, to Phil, Carol and Hattie working both in the kitchen and selling raffle tickets, to everyone who came out on a Friday to perform and especially to our audience for coming to watch our concert and helping us to raise such a huge sum of money.
Thank you from the bottom of my heart – I feel so lucky to be surrounded by such wonderful people who help bring an idea like this to life.
Posted in: concert, inspiration, singing | Tagged: blog, confidence, dementia, dream, education, inspiration, Life, love, memory, music, Performance, playlist, science, singing, students, success, voice