Hi, I am using nrf52840 and Mesh V4.2.0 sensor and light_lightness examples.
I have been able to successfully combine the server side, but I have no idea how to start combining the client part. Is there anyone who has an idea?
Thank you.
Hi, I am using nrf52840 and Mesh V4.2.0 sensor and light_lightness examples.
I have been able to successfully combine the server side, but I have no idea how to start combining the client part. Is there anyone who has an idea?
Thank you.
Hi, so is there an answer to this?
Hi again.
Sorry about the delay. Due to Christmas holiday, there has been low staffing.
We do have two examples showing the functionality you are after. Have you tried combining the examples? Are you stuck on something specific.
I might not have the time to merge the examples and upload for you but I can help you if there are some specific part that you are stuck on?
Br,
Joakim
Hi again.
Sorry about the delay. Due to Christmas holiday, there has been low staffing.
We do have two examples showing the functionality you are after. Have you tried combining the examples? Are you stuck on something specific.
I might not have the time to merge the examples and upload for you but I can help you if there are some specific part that you are stuck on?
Br,
Joakim
Hi,
So I am stuck on trying to publish motion status from my server to client. Please let me know if any of my steps are wrong, thank you.
For my server side:
In main.c, I added:
/* Application variable for holding instantaneous lightness value */
static uint16_t m_pwm0_present_actual_lightness;
static uint8_t present_motion;
.
.
/* Callback for reading the hardware state */
static void get_lightness_cb(const app_light_lightness_setup_server_t * p_app, uint16_t * p_lightness, uint8_t * p_present_motion)
{
*p_lightness = (m_pwm0_present_actual_lightness);
*p_present_motion = (present_motion);
}
.
.
static void button_event_handler(uint32_t button_number)
{
/* Increase button number because the buttons on the board is marked with 1 to 4 */
button_number++;
__LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Button %u pressed\n", button_number);
switch (button_number)
{
/* Sending value `1` or `2` via RTT will result in LED state to change and trigger
the STATUS message to inform client about the state change. This is a demonstration of
state change publication due to local event. */
case 1:
{
m_pwm0_present_actual_lightness = MAX(0, (int32_t)m_pwm0_present_actual_lightness - APP_LIGHTNESS_STEP_SIZE);
present_motion = (present_motion > 10)
? present_motion - 10
: 0;
break;
}
case 2:
{
m_pwm0_present_actual_lightness = MIN(UINT16_MAX,
(int32_t)m_pwm0_present_actual_lightness + APP_LIGHTNESS_STEP_SIZE);
present_motion = (present_motion < 90)
? present_motion + 10
: 100;
break;
}
/* Initiate node reset */
case 4:
{
/* Clear all the states to reset the node. */
if (mesh_stack_is_device_provisioned())
{
#if MESH_FEATURE_GATT_PROXY_ENABLED
(void) proxy_stop();
#endif
mesh_stack_config_clear();
node_reset();
}
else
{
__LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "The device is unprovisioned. Resetting has no effect.\n");
}
break;
}
default:
__LOG(LOG_SRC_APP, LOG_LEVEL_INFO, m_usage_string);
break;
}
if (button_number == 1 || button_number == 2)
{
pwm_utils_level_set(&m_pwm, light_lightness_utils_actual_to_generic_level(m_pwm0_present_actual_lightness));
uint32_t status = app_light_lightness_current_value_publish(&m_light_lightness_server_0);
__LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "lightness: %d, motion: %d\n", m_pwm0_present_actual_lightness, present_motion);
if ( status != NRF_SUCCESS)
{
__LOG(LOG_SRC_APP, LOG_LEVEL_WARN, "Unable to publish status message, status: %d\n", status);
}
}
}
In app_light_lightness.c, my app_light_lightness_current_value_publish:
uint32_t app_light_lightness_current_value_publish(app_light_lightness_setup_server_t * p_app)
{
if (p_app == NULL)
{
return NRF_ERROR_NULL;
}
app_transition_abort(&p_app->state.transition);
p_app->app_light_lightness_get_cb(p_app, &p_app->state.present_lightness, &p_app->state.present_motion);
if (p_app->state.present_lightness >= LIGHT_LIGHTNESS_LAST_MIN)
{
ERROR_CHECK(light_lightness_mc_last_state_set(p_app->light_lightness_setup_server.state.handle,
p_app->state.present_lightness,
LIGHT_LIGHTNESS_MC_WRITE_DESTINATION_ALL));
}
ERROR_CHECK(light_lightness_mc_actual_state_set(p_app->light_lightness_setup_server.state.handle,
p_app->state.present_lightness));
/* Notify anyone interested that we just got a command to set the lightness */
if (p_app->app_add_notify.app_notify_set_cb != NULL)
{
p_app->app_add_notify.app_notify_set_cb(p_app->app_add_notify.p_app_notify_v, p_app->state.present_lightness);
}
return publish_lightness(p_app, 0);
}
In app_light_lightness.c, my publish_lightness:
static uint32_t publish_lightness(app_light_lightness_setup_server_t * p_app, uint32_t remaining_time_ms)
{
light_lightness_status_params_t publication_data;
light_lightness_server_t * p_light_lightness_srv;
publication_data.present_lightness = p_app->state.present_lightness;
publication_data.target_lightness = p_app->state.target_lightness;
publication_data.remaining_time_ms = remaining_time_ms;
publication_data.present_motion = p_app->state.present_motion;
/* Notify anyone interested that we are publishing lightness */
if (p_app->app_add_notify.app_add_publish_cb != NULL)
{
p_app->app_add_notify.app_add_publish_cb(p_app->app_add_notify.p_app_publish_v, &publication_data);
}
p_light_lightness_srv = &p_app->light_lightness_setup_server.light_lightness_srv;
return light_lightness_server_status_publish((const light_lightness_server_t * )p_light_lightness_srv,
(const light_lightness_status_params_t *)&publication_data);
}
In light_lightness_setup_server.c, my light_lightness_server_status_publish:
uint32_t light_lightness_server_status_publish(const light_lightness_server_t * p_server,
const light_lightness_status_params_t * p_params)
{
if (p_server == NULL ||
p_params == NULL)
{
return NRF_ERROR_NULL;
}
publish_bound_actual_states(p_server, p_params);
return status_actual_send(p_server, NULL, p_params);
return status_ll_send(p_server, NULL, p_params);
}
In light_lightness_setup_server.c, my status_ll_send:
static uint32_t status_ll_send(const light_lightness_server_t * p_server,
const access_message_rx_t * p_message,
const light_lightness_status_params_t * p_params)
{
light_lightness_status_msg_pkt_t msg_pkt;
msg_pkt.present_motion = p_params->present_motion;
if (p_params->present_motion > LL_ONOFF_MAX)
{
return NRF_ERROR_INVALID_PARAM;
}
access_message_tx_t reply =
{
.opcode = ACCESS_OPCODE_SIG(LL_OPCODE_STATUS),
.p_buffer = (const uint8_t *) &msg_pkt,
.length = p_params->remaining_time_ms > 0 ? LIGHT_LIGHTNESS_STATUS_MAXLEN : LIGHT_LIGHTNESS_STATUS_MINLEN,
.force_segmented = p_server->settings.force_segmented,
.transmic_size = p_server->settings.transmic_size
};
if (p_message == NULL)
{
return access_model_publish(p_server->model_handle, &reply);
}
else
{
return access_model_reply(p_server->model_handle, p_message, &reply);
}
}
To handle the opcode, I've also added handle_ll_get:
static void handle_ll_get(access_model_handle_t model_handle,
const access_message_rx_t * p_rx_msg,
void * p_args)
{
light_lightness_server_t * p_server = (light_lightness_server_t *) p_args;
light_lightness_setup_server_t * p_s_server = PARENT_BY_FIELD_GET(light_lightness_setup_server_t, light_lightness_srv, p_args);
light_lightness_status_params_t out_data = {0};
if (p_rx_msg->length == 0)
{
p_s_server->settings.p_callbacks->light_lightness_cbs.get_cb(p_s_server, &p_rx_msg->meta_data, &out_data);
(void) status_ll_send(p_server, p_rx_msg, &out_data);
}
}
Under the m_opcode_handlers:
static const access_opcode_handler_t m_opcode_handlers[] =
{
{ACCESS_OPCODE_SIG(LIGHT_LIGHTNESS_OPCODE_GET), handle_get},
{ACCESS_OPCODE_SIG(LL_OPCODE_GET), handle_ll_get},
}
For my client side, my main.c I've added:
/* Light lightness client model interface: Process the received status message in this callback */
static void app_light_lightness_client_status_cb(const light_lightness_client_t *p_self,
const access_message_rx_meta_t *p_meta,
const light_lightness_status_params_t *p_in)
{
if (p_in->remaining_time_ms > 0)
{
__LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Lightness client: 0x%04x, Present Lightness: %d, Target Lightness: %d, Remaining Time: %d ms\n",
p_meta->src.value, p_in->present_lightness, p_in->target_lightness, p_in->remaining_time_ms);
}
else
{
__LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Lightness client: 0x%04x, Present lightness: %d, Present motion: %d\n",
p_meta->src.value, p_in->present_lightness, p_in->present_motion);
}
}
In light_lightness_client.c, to handle the opcode:
static void status_ll_handle(access_model_handle_t handle, const access_message_rx_t * p_rx_msg, void * p_args)
{
light_lightness_client_t * p_client = (light_lightness_client_t *) p_args;
light_lightness_status_params_t in_data = {0};
if (p_rx_msg->length == LL_STATUS_MINLEN || p_rx_msg->length == LL_STATUS_MAXLEN)
{
light_lightness_status_msg_pkt_t * p_msg_params_packed = (light_lightness_status_msg_pkt_t *) p_rx_msg->p_data;
if (p_rx_msg->length == LL_STATUS_MINLEN)
{
in_data.present_motion = p_msg_params_packed->present_motion;
}
else
{
in_data.present_motion = p_msg_params_packed->present_motion;
}
p_client->settings.p_callbacks->lightness_status_cb(p_client, &p_rx_msg->meta_data, &in_data);
}
}
.
.
static const access_opcode_handler_t m_opcode_handlers[] =
{
{ACCESS_OPCODE_SIG(LIGHT_LIGHTNESS_OPCODE_STATUS), status_handle},
{ACCESS_OPCODE_SIG(LL_OPCODE_STATUS), status_ll_handle},
}
.
.
uint32_t ll_client_get(light_lightness_client_t * p_client)
{
if (p_client == NULL)
{
return NRF_ERROR_NULL;
}
if (access_reliable_model_is_free(p_client->model_handle))
{
message_create(p_client, LL_OPCODE_GET, NULL, 0, &p_client->access_message.message);
reliable_context_create(p_client, LL_OPCODE_STATUS, &p_client->access_message);
return access_model_reliable_publish(&p_client->access_message);
}
else
{
return NRF_ERROR_BUSY;
}
}
Sorry if this is a lot of codes, but I hope you are able to study what I'm trying to do and help me with them. Thank you in advance.
Thanks.
I'll take a look at your code and get back to you.
Br,
Joakim