lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


So here I am : the full source code can be found https://github.com/destroyedlolo/Selene/blob/master/src/MQTT.c

1/ Environment creation :

struct enhanced_client {
    MQTTClient client;
    lua_State *L;
    struct _topic *subscriptions;
};

...

        /* Creating Lua data */
    eclient = (struct enhanced_client *)lua_newuserdata(L, sizeof(struct enhanced_client));
    luaL_getmetatable(L, "SelMQTT");
    lua_setmetatable(L, -2);
    eclient->subscriptions = NULL;
    eclient->L = luaL_newstate();
    luaL_openlibs(eclient->L);
...

2/ registering the callback

...
        lua_pushstring(L, "func");    /* Argument cames from a table */
        lua_gettable(L, -2);
        if( lua_type(L, -1) != LUA_TFUNCTION ){
            lua_pop(L, 1);    /* Pop the result */
            lua_pushnil(L);
            lua_pushstring(L, "Subscribe() : topics needs associated function");
            return 2;
        }
        lua_xmove( L, eclient->L, 1 );    /* Move the function to the callback's stack */
        func = luaL_ref(eclient->L,LUA_REGISTRYINDEX);    /* Reference the function in callbacks' context */
...

3/ calling the callback function

 int msgarrived(void *actx, char *topic, int tlen, MQTTClient_message *msg){
/* handle message arrival and call associated function.
 * NOTE : up to now, only textual topics & messages are
 * correctly handled (lengths are simply ignored)
 */
    struct enhanced_client *ctx = actx;    /* To avoid numerous cast */
    struct _topic *tp;

    for(tp = ctx->subscriptions; tp; tp = tp->next){    /* Looks for the corresponding function */
        if(!strcmp(tp->topic, topic)){    /* AF : wildcard to be done */
            lua_rawgeti( ctx->L, LUA_REGISTRYINDEX, tp->func);    /* retrieves the function */
            lua_pushstring( ctx->L, topic);
            lua_pushstring( ctx->L, msg->payload);
            lua_pcall( ctx->L, 2, 0, 0);    /* Call Lua callback function */
        }
    }

    MQTTClient_freeMessage(&msg);
    MQTTClient_free(topic);
    return 1;
}


print '\nTesting broker connection'
print '--------------------------'

-- Callbacks
function handle_tata( topic, msg )
    print("Lua received t:'" .. topic .."' m:'".. msg .. "'\n");
end


function handle_toto( topic, msg )
    print("Lua received t:'" .. topic .."' m:'".. msg .. "'\n");
end

-- Connection, subscription and finally waiting for messages
Brk, err = SelMQTT.connect( "tcp://localhost:1883", { reliable=false  } )
if not Brk then
    print( err )
    return
end

_, err = Brk:subscribe( { { topic = "/tata/#", func=handle_tata, qos=SelMQTT.QoSConst("QoS0") }, { topic = "/toto",func=handle_toto } } )
if err then
    print( err )
    return
end

print "Hit 'enter' key to exit"
io.stdin:read'*l'    -- wait for enter

And it seems it's working pretty well.
If I enter in another shell :
---
torchwood ~ # mosquitto_pub -h torchwood.local -t '/toto' -m 'Coucou'
---

I got 
---
torchwood Selene # Selenites/MQTT.sel
Testing broker connection
--------------------------
Hit 'enter' key to exit
Lua received t:'/toto' m:'Coucou'
---

Can someone having a look and tell me if I made a mistake ?

Now, I'll have to work data shared b/w threads :)

Thanks for all.

Laurent

---
The misspelling master is on the Web.
  _________ 100 % Dictionnary Free !
/                 /(
/ Dico        / / Pleins d'autres fautes sur
/________ / /
(########( / http://destroyedlolo.info
Quoi, des fautes d'orthographe! Pas possible ;-D.



Le Dimanche 7 juin 2015 12h01, Laurent FAILLIE <l_faillie@yahoo.com> a écrit :


Le Dimanche 7 juin 2015 11h15, Thijs Schreijer <thijs@thijsschreijer.nl> a écrit :



> The naming of some elements in the C api is a bit misleading. Personally I wish that all wording with "thread"
> would be changed to "coroutine", and the lua_State would be renamed to "executionstack" or something
> more appropriate.

Yes, I totally second that, it's a bit confusing, especially because Lua's thread aren't preemptive.

Thanks for the links, I'll check them if I can't succeed with my current thinking;

> I'm not familiar with Paho, but how is is used? Is the main loop on the C side and are messages passed to Lua
> to be handled with scripting, or is the main loop on the Lua side? Does Paho create the new os threads?
> Do you have control over that behaviour? Does it also generate new Lua states?

Paho ( https://eclipse.org/paho/ ) is a messaging library implementing MQTT protocol, mostly associated with IoT stuffs.
It supports several implementations : Java, C, C++ and even a native Lua library which is not finished up to now.
I'm using the C implementation, which has nothing to do with Lua at all.

My project is the following :

- I have several daemons running in my basement server to do "smart housing", and monitoring several figures of my home : electricity consumption and production, temperature in rooms, pool, health of my Internet connection, and so on and so forth ... https://github.com/destroyedlolo/TeleInfod and https://github.com/destroyedlolo/Marcel are some example of such daemon.
- Daemons and my supervision tool are exchanging data using MQTT messaging : the big advantage is it runs in pub/sub model so I can add / remove / modify any part of my network without touching the remaining.

Now, I'm working now on the "home dashboard" part which will plug-in on this network and will display some valuables informations on a screen on my living room.

- The main work is done in C and takes in charge all the dirty / low level work. This technical layer is https://github.com/destroyedlolo/Selene
- Selene embeds Lua as end user scripting language, which will be used to build the final dashboard (has to be done). And to respond to your question, yes, messages are handled in C then passed to Lua part for end user oriented processing.

The main advantage is a clear separation b/w the technical layers and the end user interface itself.

- Laurent