pinebuds/services/ble_app/app_htp/app_ht.c

440 lines
13 KiB
C

/***************************************************************************
*
* Copyright 2015-2019 BES.
* All rights reserved. All unpublished rights reserved.
*
* No part of this work may be used or reproduced in any form or by any
* means, or stored in a database or retrieval system, without prior written
* permission of BES.
*
* Use of this work is governed by a license granted by BES.
* This work contains confidential and proprietary information of
* BES. which is protected by copyright, trade secret,
* trademark and other intellectual property rights.
*
****************************************************************************/
/**
****************************************************************************************
* @addtogroup APP
* @{
****************************************************************************************
*/
#include "rwip_config.h" // SW configuration
#if (BLE_APP_HT)
/*
* INCLUDE FILES
****************************************************************************************
*/
#include "app.h" // Application Definitions
#include "app_ht.h" // Health Thermometer Application Definitions
#include "app_task.h" // application task definitions
#include "arch.h" // Platform Definitions
#include "co_bt.h"
#include "htpt_task.h" // health thermometer functions
#include "prf_types.h"
#include "prf_utils.h"
#include "co_math.h"
#include "ke_timer.h"
#if (DISPLAY_SUPPORT)
#include "app_display.h"
#include "display.h"
#endif // DISPLAY_SUPPORT
/*
* DEFINES
****************************************************************************************
*/
/// Initial Temperature Value : 37c
#define APP_HT_TEMP_VALUE_INIT (3700)
/// Temperature Step
#define APP_HT_TEMP_STEP_INIT (10)
/// Measurement Interval Value Min
#define APP_HT_MEAS_INTV_MIN (1)
/// Measurement Interval Value Max
#define APP_HT_MEAS_INTV_MAX (30)
/*
* GLOBAL VARIABLE DEFINITIONS
****************************************************************************************
*/
/// health thermometer application environment structure
struct app_ht_env_tag app_ht_env;
/*
* LOCAL FUNCTION DEFINITIONS
****************************************************************************************
*/
static void app_ht_temp_send(void) {
// Temperature Value
int32_t value = (int32_t)(app_ht_env.temp_value);
// The value is a float value, set the exponent
value |= 0xFE000000;
// Allocate the HTPT_TEMP_SEND_REQ message
struct htpt_temp_send_req *req =
KE_MSG_ALLOC(HTPT_TEMP_SEND_REQ, prf_get_task_from_id(TASK_ID_HTPT),
TASK_APP, htpt_temp_send_req);
// Stable => Temperature Measurement Char.
req->stable_meas = 0x01;
// Temperature Measurement Value
req->temp_meas.temp = value;
// req->temp_meas.time_stamp = 0;
req->temp_meas.flags = HTP_FLAG_CELSIUS | HTP_FLAG_TYPE;
req->temp_meas.type = app_ht_env.temp_meas_type;
ke_msg_send(req);
}
static void app_ht_update_type_string(uint8_t temp_type) {
switch (temp_type) {
case 0:
strcpy(app_ht_env.temp_type_string, "NONE");
break;
case 1:
strcpy(app_ht_env.temp_type_string, "ARMPIT");
break;
case 2:
strcpy(app_ht_env.temp_type_string, "BODY");
break;
case 3:
strcpy(app_ht_env.temp_type_string, "EAR");
break;
case 4:
strcpy(app_ht_env.temp_type_string, "FINGER");
break;
case 5:
strcpy(app_ht_env.temp_type_string, "GASTRO-INT");
break;
case 6:
strcpy(app_ht_env.temp_type_string, "MOUTH");
break;
case 7:
strcpy(app_ht_env.temp_type_string, "RECTUM");
break;
case 8:
strcpy(app_ht_env.temp_type_string, "TOE");
break;
case 9:
strcpy(app_ht_env.temp_type_string, "TYMPANUM");
break;
default:
strcpy(app_ht_env.temp_type_string, "UNKNOWN");
break;
}
}
/*
* GLOBAL FUNCTION DEFINITIONS
****************************************************************************************
*/
void app_ht_init(void) {
// Reset the environment
memset(&app_ht_env, 0, sizeof(app_ht_env));
// Initial measurement interval : 0s
app_ht_env.htpt_meas_intv = 5;
// Initial temperature value : 37.00 C
app_ht_env.temp_value = APP_HT_TEMP_VALUE_INIT;
// Initial temperature step : 0.20 C
app_ht_env.temp_step = APP_HT_TEMP_STEP_INIT;
// Initial temperature type : ARMPIT
app_ht_env.temp_meas_type = 1;
// TODO: Add a state for the module
}
void app_stop_timer(void) {
// Stop the timer used for the measurement interval if enabled
if (app_ht_env.timer_enable) {
ke_timer_clear(APP_HT_MEAS_INTV_TIMER, TASK_APP);
app_ht_env.timer_enable = false;
}
}
void app_ht_add_hts(void) {
struct htpt_db_cfg *db_cfg;
// Allocate the HTPT_CREATE_DB_REQ
struct gapm_profile_task_add_cmd *req =
KE_MSG_ALLOC_DYN(GAPM_PROFILE_TASK_ADD_CMD, TASK_GAPM, TASK_APP,
gapm_profile_task_add_cmd, sizeof(struct htpt_db_cfg));
// Fill message
req->operation = GAPM_PROFILE_TASK_ADD;
#if BLE_CONNECTION_MAX > 1
req->sec_lvl = PERM(SVC_AUTH, ENABLE) | PERM(SVC_MI, ENABLE);
#else
req->sec_lvl = PERM(SVC_AUTH, ENABLE);
#endif
req->prf_task_id = TASK_ID_HTPT;
req->app_task = TASK_APP;
req->start_hdl = 0;
// Set parameters
db_cfg = (struct htpt_db_cfg *)req->param;
// All features are supported
db_cfg->features = HTPT_ALL_FEAT_SUP;
// Measurement Interval range
db_cfg->valid_range_min = APP_HT_MEAS_INTV_MIN;
db_cfg->valid_range_max = APP_HT_MEAS_INTV_MAX;
// Measurement
db_cfg->temp_type = app_ht_env.temp_meas_type;
db_cfg->meas_intv = app_ht_env.htpt_meas_intv;
// Send the message
ke_msg_send(req);
}
void app_ht_enable_prf(uint8_t conidx) {
// Allocate the message
struct htpt_enable_req *req =
KE_MSG_ALLOC(HTPT_ENABLE_REQ, prf_get_task_from_id(TASK_ID_HTPT),
TASK_APP, htpt_enable_req);
// Fill in the parameter structure
req->conidx = conidx;
// NTF/IND initial status - Disabled
req->ntf_ind_cfg = PRF_CLI_STOP_NTFIND;
// Send the message
ke_msg_send(req);
}
/**
****************************************************************************************
* Health Thermometer Application Functions
****************************************************************************************
*/
void app_ht_temp_inc(void) {
app_ht_env.temp_value += app_ht_env.temp_step;
#if (DISPLAY_SUPPORT)
app_display_update_temp_val_screen(app_ht_env.temp_value);
#endif // DISPLAY_SUPPORT
app_ht_temp_send();
}
void app_ht_temp_dec(void) {
app_ht_env.temp_value -= app_ht_env.temp_step;
#if (DISPLAY_SUPPORT)
app_display_update_temp_val_screen(app_ht_env.temp_value);
#endif // DISPLAY_SUPPORT
app_ht_temp_send();
}
void app_ht_temp_type_inc(void) {
app_ht_env.temp_meas_type =
(uint8_t)(((int)app_ht_env.temp_meas_type + 1) % 10);
#if (DISPLAY_SUPPORT)
app_ht_update_type_string(app_ht_env.temp_meas_type);
app_display_update_temp_type_screen(app_ht_env.temp_type_string);
#endif // DISPLAY_SUPPORT
}
void app_ht_temp_type_dec(void) {
if (((int)app_ht_env.temp_meas_type - 1) < 0) {
app_ht_env.temp_meas_type = 0x09;
} else {
app_ht_env.temp_meas_type = app_ht_env.temp_meas_type - 1;
}
#if DISPLAY_SUPPORT
app_ht_update_type_string(app_ht_env.temp_meas_type);
app_display_update_temp_type_screen(app_ht_env.temp_type_string);
#endif // DISPLAY_SUPPORT
}
/****************************************************************************************
* MESSAGE HANDLERS
****************************************************************************************/
/**
****************************************************************************************
* @brief Handles measurement interval start indication from the Health
*Thermometer profile. Start or stop a timer following the value of the param
*intv.
*
* @param[in] msgid Id of the message received.
* @param[in] param Pointer to the parameters of the message.
* @param[in] dest_id ID of the receiving task instance (TASK_GAP).
* @param[in] src_id ID of the sending task instance.
*
* @return If the message was consumed or not.
****************************************************************************************
*/
static int htpt_meas_intv_chg_req_ind_handler(
ke_msg_id_t const msgid, struct htpt_meas_intv_chg_req_ind const *param,
ke_task_id_t const dest_id, ke_task_id_t const src_id) {
// Store the received Measurement Interval value
app_ht_env.htpt_meas_intv = param->intv;
// Check the new Measurement Interval Value
if (app_ht_env.htpt_meas_intv != 0) {
// Check if a Timer already exists
if (!app_ht_env.timer_enable) {
// Set a Timer
ke_timer_set(APP_HT_MEAS_INTV_TIMER, TASK_APP,
app_ht_env.htpt_meas_intv * 100);
app_ht_env.timer_enable = true;
} else {
// Clear the previous timer
ke_timer_clear(APP_HT_MEAS_INTV_TIMER, TASK_APP);
// Create a new timer with the received measurement interval
ke_timer_set(APP_HT_MEAS_INTV_TIMER, TASK_APP,
app_ht_env.htpt_meas_intv * 100);
}
} else {
// Check if a Timer exists
if (app_ht_env.timer_enable) {
// Measurement Interval is 0, clear the timer
ke_timer_clear(APP_HT_MEAS_INTV_TIMER, TASK_APP);
app_ht_env.timer_enable = false;
}
}
// Allocate the message
struct htpt_meas_intv_chg_cfm *cfm =
KE_MSG_ALLOC(HTPT_MEAS_INTV_CHG_CFM, prf_get_task_from_id(TASK_ID_HTPT),
TASK_APP, htpt_meas_intv_chg_cfm);
// Set data
cfm->conidx = KE_IDX_GET(dest_id);
cfm->status = 0;
// Send the message
ke_msg_send(cfm);
return (KE_MSG_CONSUMED);
}
static int htpt_temp_send_rsp_handler(ke_msg_id_t const msgid,
struct htpt_temp_send_rsp const *param,
ke_task_id_t const dest_id,
ke_task_id_t const src_id) {
// Do nothing
return (KE_MSG_CONSUMED);
}
static int htpt_cfg_indntf_ind_handler(ke_msg_id_t const msgid,
struct htpt_cfg_indntf_ind const *param,
ke_task_id_t const dest_id,
ke_task_id_t const src_id) {
// Do nothing
return (KE_MSG_CONSUMED);
}
/**
****************************************************************************************
* @brief Handles health thermometer timer
*
* @param[in] msgid Id of the message received.
* @param[in] param Pointer to the parameters of the message.
* @param[in] dest_id ID of the receiving task instance (TASK_GAP).
* @param[in] src_id ID of the sending task instance.
*
* @return If the message was consumed or not.
****************************************************************************************
*/
static int app_ht_meas_intv_timer_handler(ke_msg_id_t const msgid,
void const *param,
ke_task_id_t const dest_id,
ke_task_id_t const src_id) {
// Random generation of a temperature value
uint32_t rand_temp_step;
// Sign used to know if the temperature will be increased or decreased
int8_t sign;
// Generate temperature step
rand_temp_step = (uint32_t)(co_rand_word() % 20);
// Increase or decrease the temperature value
sign = (int8_t)(rand_temp_step & 0x00000001);
if (!sign) {
sign = -1;
}
app_ht_env.temp_value += sign * rand_temp_step;
// Send the new temperature
app_ht_temp_send();
#if (DISPLAY_SUPPORT)
app_display_update_temp_val_screen(app_ht_env.temp_value);
#endif // DISPLAY_SUPPORT
// Reset the Timer (Measurement Interval is not 0 if we are here)
ke_timer_set(APP_HT_MEAS_INTV_TIMER, TASK_APP,
app_ht_env.htpt_meas_intv * 100);
return (KE_MSG_CONSUMED);
}
/**
****************************************************************************************
* @brief Handles health thermometer timer
*
* @param[in] msgid Id of the message received.
* @param[in] param Pointer to the parameters of the message.
* @param[in] dest_id ID of the receiving task instance (TASK_GAP).
* @param[in] src_id ID of the sending task instance.
*
* @return If the message was consumed or not.
****************************************************************************************
*/
static int app_ht_msg_handler(ke_msg_id_t const msgid, void const *param,
ke_task_id_t const dest_id,
ke_task_id_t const src_id) {
// Do nothing
return (KE_MSG_CONSUMED);
}
/*
* LOCAL VARIABLE DEFINITIONS
****************************************************************************************
*/
/// Default State handlers definition
const struct ke_msg_handler app_ht_msg_handler_list[] = {
// Note: first message is latest message checked by kernel so default is put
// on top.
{KE_MSG_DEFAULT_HANDLER, (ke_msg_func_t)app_ht_msg_handler},
// {HTPT_ENABLE_RSP, (ke_msg_func_t)htpt_enable_rsp_handler},
{HTPT_TEMP_SEND_RSP, (ke_msg_func_t)htpt_temp_send_rsp_handler},
{HTPT_MEAS_INTV_CHG_REQ_IND,
(ke_msg_func_t)htpt_meas_intv_chg_req_ind_handler},
{HTPT_CFG_INDNTF_IND, (ke_msg_func_t)htpt_cfg_indntf_ind_handler},
{APP_HT_MEAS_INTV_TIMER, (ke_msg_func_t)app_ht_meas_intv_timer_handler},
};
const struct ke_state_handler app_ht_table_handler = {
&app_ht_msg_handler_list[0],
(sizeof(app_ht_msg_handler_list) / sizeof(struct ke_msg_handler))};
#endif // BLE_APP_HT
/// @} APP