Part 1: Receiving a message
1. Callback vs. polling
Since the Create a package tutorial, you know how to create a service into a package with a callback.
But Luos engine's services have in fact two different ways to receive messages: callback and polling.
- Asynchronous reception (Callback)
In the callback option, you give to Luos engine a shipping address (called a message handler) allowing it to just deliver the message to your service. Your service needs to be ready to receive and handle the message directly.
- Synchronous reception (Polling)
In the polling option, Luos engine doesn't know the shipping address, so your service will have to check if Luos engine has a messages available, and then get it if there is one. Your service can get a message whenever it wants to.
In this tutorial, we will create a service without any callback to explore the polling option.
In PlatformIO IDE, open the folder corresponding to your board in Training/1_First_Service/Work_base
from the repository you just cloned or downloaded, and connect the board to your computer with a USB cable.
2. Create a button service
You can create your service in the button package's Init
function, but this time do not write any callback in the first argument and put a 0
value instead:
void Button_Init(void)
{
// the two new lines to copy and paste
revision_t revision = {1, 0, 0};
Luos_CreateService(0, STATE_TYPE, "button", revision);
}
void Button_Loop(void){}
Because you did not give any shipping address to Luos engine, your service will have to go get it by itself.
We only need two functions here, called Button_Init()
and Button_loop()
.
Let's try it!
- Compile and upload the project to the board.
- Use
pyluos-shell
in a terminal. You should see the following routing table:
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ ╭────────────────── Node 1 ────────────────── ┃
┃ │ Type Alias ID ┃
┃ ├> Pipe Pipe 2 ┃
┃ ├> Gate gate 1 ┃
┃ ╰> State button 3 ┃
╔>┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
3. Handle a request using the polling method
To pull messages from Luos engine, we will need to know which service is asking for them. To do that, you need to create a service_t
pointer, so that at the service creation Luos engine would allow you to link it to the actual created service:
/*******************************************************************************
* Variable
******************************************************************************/
// the new line to copy and paste
service_t *button_service;
Assign the variable to your service creation:
void Button_Init(void)
{
// the two new lines to copy and paste
revision_t revision = {1, 0, 0};
button_service = Luos_CreateService(0, STATE_TYPE, "button", revision);
}
Because we do not give any message handler to Luos engine, we will have to get the available messages into the service loop function using Luos_ReadMsg
function:
void Button_Loop(void)
{
// the new block to copy and paste
msg_t* msg;
if (Luos_ReadMsg(button_service, &msg) == SUCCEED)
{
// We get a message!
}
}
If we enter into this if
condition, that tells us we have received a message and that we can deal with it.
To be able to send back the button value, we now need to check if the received message is a proper request:
void Button_Loop(void)
{
msg_t* msg;
if (Luos_ReadMsg(button_service, &msg) == SUCCEED)
{
// the new line to copy and paste
if ((msg->header.cmd == IO_STATE)||(msg->header.cmd == UNKNOW)
{
// We will have to send our button info here
}
}
}
As you can see in this message filtering, this request could be two different commands:
-
A service can ask specifically for an
IO_STATE
. -
A service can ask for an UNKNOW value because it does not known the returned type of the value.
Sometimes, a service wants an UNKNOW
type because it does not specifically know what the returned value will be an IO_STATE
type. You can use it as a common way to get any kind of value from services.
Everything is ready for reception, we can now learn how to reply to the request and send a message!