[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [paho-dev] non blocking sleep

Yes, Greg is right. This has nothing really to do with MQTT itself; it's a system design issue. The same problems would arise with a different messaging systems (AMQP, ActiveMQ, etc), or really any other service architecture where inputs and commands are coming at you from a variety of sources.

Remember, too, that you're thinking in terms of the implementation language that you've chosen - Python. MQTT clients are used in dozens of different languages. Python was invented long ago when single-threaded apps were the norm. Since then, a lot of libraries and modules were added on to help with doing multiple things at once, such as threads, timers, async I/O, event loops, and so on. But alternately, a lot of new languages and platforms have been developed to handle parallel tasks, and make efficient use of multi-cores. Languages like _javascript_, Rust, Go, Elixir, etc.

So it's not that you need to make something new. The problem is that there are *so many* options for this all with pros and cons. A lot comes down to personal preferences. What feels "right" to you.

Frank

On 10/6/19 2:16 PM, Carl Karsten wrote:
I appreciate the effort, but I'm surprised this isn't a FAQ kinda thing. Â
Is what I am doing really that unique that it needs an event architecture to be designed?

like Greg said:
> This is not an MQTT issue, but I can see it comes up often in things
> that want to use MQTT.

also, shouldn't I be using asyncio over treads?



On Sun, Oct 6, 2019 at 9:46 AM Frank Pagliughi <fpagliughi@xxxxxxxxxxxxxx> wrote:
You're looking at doing some "event driven programming". The arriving MQTT messages are telling your system what to do, but as you grow the system, there will be other sources of events from sensors, timers, etc. You want to handle these events as quickly as possible and return control so that you're always responsive to new events.

That means you need to do the actual processing of the events outside of callbacks. Typical ways to do this, depending on your language of choice, are with event loop libraries, threads, and timers.

Timers in Python are pretty easy. Just give an amount of time (in seconds) and a callback function, and the function will be called after the specified amount of time.
https://docs.python.org/3.7/library/threading.html#timer-objects
def hello():
    print("hello, world")

t = Timer(30.0, hello)
t.start()  # after 30 seconds, "hello, world" will be printed
Tracking your internal progress as a state machine is a great way to deal with all of this.

So, basically, in the callback that receives MQTT messages, set a timer to fire some time later. Keep a reference to the timer, "t", in case an event arrives indicating that the action should be canceled before the timer fired. In that case, you call:
t.cancel()
Frank

On 10/5/19 3:10 PM, Carl Karsten wrote:
opps, sorry, I thought this list was specifically for python-paho.Â

I'm using Python.

> You basically have to avoid calling sleep and use timers instead.

this sounds funny asking, but What is a timer?

Years ago I used a gui desktop database app designer, I dragged a "timer widget" onto the form and type in the function it should call every X amount of time.
I understand what that did, I understand i need something like that, but in this context I have no idea how I should implement it.Â

I have a few guesses, like check for events in a loop. maybe add a sleep so the cpu has some cycles to do other things (no sure what other things are needed, pretty sure incoming network traffic will take priority? also pretty sure this is not a problem I should be trying to solve.  I am sure it has been solved 100's of times.

I also guess "event loop" is a thing I need. Which I also comprehend and could implement one from scratch if I needed to, but I hope I don't need to.


On Sat, Oct 5, 2019 at 7:32 AM Greg Troxel <gdt@xxxxxxxxxx> wrote:
Carl Karsten <carl@xxxxxxxxxxxxxxxx> writes:

> When the door opens, the light should stay on for 60 seconds.
> or if the button is pressed, turn the light off 30 seconds later.
> every door open resets the 60 seconds.
>
> (this is the simplified version that I think is the root of my problem)

This is not an MQTT issue, but I can see it comes up often in things
that want to use MQTT.

> I can't do "on, sleep(60), off" because that will block the on_button
> (right?)

If the main control program calls sleep, it will ignore all other inputs
for that time. So don't do that :-)

> and when the button is pressed, if the door opens again that should disable
> the "off in 30" thing.

A further complexity is humans asking for lights to be in certain states
and automatic rules at the same time. In this case I think you want a
virtual light controlled by the human and a virtual light controlled by
the rules and the real light to be the OR of those.

> Is there a tutorial page or something I should be reading?

This is really a fundamental programming issue; you are constructing a
finite state machine with timers.

https://en.wikipedia.org/wiki/Finite-state_machine

There are arguably two approaches to this sort of thing, usually called
threads and async. ÂIt will seems that threads are easier, but really
they just look easier and async is actually easier, when you define that
as "work to get a 100% reliable system".

Frameworks that are set up for your problem include

 https://nodejs.org/en/about/

 http://docs.libuv.org/en/v1.x/

 https://nodemcu.readthedocs.io/en/master/ (but this is Lua on ESP8266,
 probably not where you should run the controller)


but really you sound like you are starting down the path of slowly
reinventing a home automation system, so have a look at

 https://www.home-assistant.io/


Yes, but this system is 'special' otherwise we wouldn't be making it :p
We might be right. not my call. What I am sure of is someone will make something better some day. might be me!

Is this what I should be doing?

async def main():
    print('Hello ...')
    await asyncio.sleep(1)
    print('... World!')

asyncio.run(main())



--
Carl K

_______________________________________________
paho-dev mailing list
paho-dev@xxxxxxxxxxx
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://www.eclipse.org/mailman/listinfo/paho-dev



--
Carl K

_______________________________________________
paho-dev mailing list
paho-dev@xxxxxxxxxxx
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://www.eclipse.org/mailman/listinfo/paho-dev