Программный модуль для датчика RSG-151S. Версия 0.21
ПО является неотъемлемой частью датчика RSG-151S, отдельно потребителю не поставляется и эксплуатируется только в составе устройства.
/**
* @file application.c
* @brief application.c реализует функционал устройства RSG-151S
* @internal
* Revision: ver 0.21
* Compiler: armcc
*
*/
/********* HEADER FILE INCLUDES *************************************************/
#include "debug_info.h"
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "nrf.h"
#include "nrf_delay.h"
#include "nrf_gpio.h"
#include "nordic_common.h"
#include "app_error.h"
#include "nrf_soc.h"
#include "app_timer.h"
#include "app_util.h"
#include "app_util_platform.h"
#include "custom_board.h"
#include "r4s_lib.h"
#include "r4s_slave.h"
#include "r4s_slave_external.h"
#include "r4s_master.h"
#include "r4s_master_external.h"
#include "com_slave.h"
#include "com_master.h"
#include "master_control_table.h"
#include "timers_config.h"
#include "control.h"
#include "indication.h"
#include "temperature.h"
#include "temperature_service.h"
#include "event_base.h"
#include "config.h"
#include "application.h"
#include "application_api.h"
#include "custom_board.h"
#include "com_slave_extention.h"
#include "cr2032.h"
#include "sfloat.h"
#include "com_slave_extention.h"
#include "drv_gas_sensor.h"
#include "adv_data.h"
#include "adv_data_config.h"
#include "evcal.h"
#include "calendar.h"
#include "cycle_buf.h"
#include "log_service.h"
#include "param.h"
/********* DEFINES **************************************************************/
#define BAT_CHARGE_LIMIT 0
#define CRITICAL_TEMP 55
#define CRITICAL_TEMP_ALARM_OFF (CRITICAL_TEMP - 5)
#define CHANNEL_MASK_TEMPERATURE (1<<0)
#define TEMP_MASK_Pos 0
#define GAS_MASK_Pos 1
/********* MACROS ***************************************************************/
/********* VARIABLES *****************************************************/
static app_state_t app_state = APP_START; /* состояние state machine*/
static bool app_test_init_success = false;
static bool app_timerout_flag = false; /* флаг timeout-a */
static bool AppSlaveConnectedFl = false; /* флаг slave connected*/
static bool AppPairingFl = false; /* флаг pairing*/
static bool AppUnPairingFl = false; /* флаг unpairing sound */
static btn_data_t pair_btn_data;
static app_sensors_evt_enabled_t sensors_evt_en;
static temp_trigger_t app_temp_trigger[TEMPERATURE_TRIGGER_MAX_COUNT];
static uint8_t temp_triggers_count = 0;
static float app_temp = 0;
static bool app_need_update = false;
static alert_level_t alert_level = ALERT_IDLE;
static volatile bool m_hardfault = false;
APP_TIMER_DEF(app_timer_id);
static cm_dev_support_ac_t m_required_ac = {
.ac = {
AC_EXTENTION_START_CMD,
AC_EXTENTION_STOP_CMD
}
};
/********* FUNCTION PROTOTYPES **************************************************/
__STATIC_INLINE uint32_t api_temp_test_proccess(void); // фукция проверки температурного датчика
static void application_store_log(void);
__STATIC_INLINE void api_update_triggers(void);
static void api_master_evt_handler(com_master_evt_t * p_evt);
static void api_internal_action_process(mct_link_t *link);
static void alert_set(alert_level_t lvl);
/**
* @brief Функция устанавливает флаг необходимости обновления параметров
*
* @param none
*
* @return:: none
*/
__STATIC_INLINE void api_need_update(void);
/********* FUNCTIONS IMPLEMENTATION *********************************************/
/**@brief Обработчик таймера таймаута.
*
* @param none
*
* @return none
*/
static void app_timeout_timer_handler( void* p_context )
{
app_timerout_flag = true;
}
/**@brief Обработчик таймера измерения заряда.
*
* @param none
*
* @return none
*/
static void app_temp_data_handler(float temp)
{
app_temp = temp;
com_slave_send_state();
}
/**
* @brief Функция вызывается при срабатывании часов (1 сек)
*
* @param none
* @return none
*
*/
static void calendar_timer_handle(void){
uint32_t err_code;
err_code = evcal_one_sec_handler();
#ifdef DEBUG
APP_ERROR_CHECK(err_code);
#endif
}
/**
* @brief Функция вызывается при срабатывании событий из календаря
*
* @param none
* @return none
*
*/
static void evcal_calendar_task(evcal_info_packet_t const*p_data){
if(p_data == NULL) return;
uint8_t action_code = p_data->array[1];
switch(action_code)
{
case AC_EXTENTION_START_CMD:
{
exten_req_start_t *p_in_exp_pckt = (exten_req_start_t *) &p_data->array[2];
if((p_in_exp_pckt->mask & CHANNEL_MASK_TEMPERATURE) != 0){
api_sensor_on();
}
break;
}
case AC_EXTENTION_STOP_CMD:
{
exten_req_start_t *p_in_exp_pckt = (exten_req_start_t *) &p_data->array[2];
if((p_in_exp_pckt->mask & CHANNEL_MASK_TEMPERATURE) != 0){
api_sensor_off();
}
break;
}
}
return;
}
void application_init(void)
{
uint32_t err_code;
err_code = app_timer_create ( &app_timer_id, APP_TIMER_MODE_SINGLE_SHOT, app_timeout_timer_handler );
#ifdef DEBUG
APP_ERROR_CHECK(err_code);
#endif
err_code = calendar_set_one_sec_callback(calendar_timer_handle); //установка callback часов
#ifdef DEBUG
APP_ERROR_CHECK(err_code);
#endif
err_code = evcal_set_callback(evcal_calendar_task); //установка callback при срабатывании расписания
#ifdef DEBUG
APP_ERROR_CHECK(err_code);
#endif
err_code = temperature_service_init(app_temp_data_handler);
#ifdef DEBUG
APP_ERROR_CHECK(err_code);
#endif
api_need_update();
com_master_set_required_ac(&m_required_ac);
com_master_set_event_handler(api_master_evt_handler);
com_master_set_internal_action_handler(api_internal_action_process);
sensors_evt_en.temperature = 1;
param_data_t param;
APP_ERROR_CHECK(param_get_data(¶m));
if (param.is_gas_sensor_broken) {
drv_gas_restore_broken_state();
m_hardfault = true;
ind_set_hardfault();
}
}
/********************************************************************************
*
********************************************************************************/
/**@brief Функция выполняет работу при выходе из соответствующего состояния
*
* @param none
*
* @return none
*/
void application_init_prew_state( app_state_t app_new_state )
{
static app_state_t app_prew_state = APP_START;
if( app_prew_state == app_new_state )return;
switch( app_prew_state )
{
case APP_START:
{
APP_PRINTF(0,RTT_CTRL_TEXT_BRIGHT_YELLOW"[APPL]: APP_IDLE>>\r\n"RTT_CTRL_RESET);
break;
}
case APP_TEST:
{
APP_PRINTF(0,RTT_CTRL_TEXT_BRIGHT_YELLOW"[APPL]: APP_TEST>>\r\n"RTT_CTRL_RESET);
break;
}
case APP_ALARM:
{
ind_state_change(IND_ALARM_IDLE, NULL);
break;
}
case APP_ACTIVE:
{
APP_PRINTF(0,RTT_CTRL_TEXT_BRIGHT_YELLOW"[APPL]: APP_ACTIVE>>\r\n"RTT_CTRL_RESET);
ind_state_change(IND_ACTIVE_IDLE, NULL);
break;
}
case APP_PAIRING:
{
APP_PRINTF(0,RTT_CTRL_TEXT_BRIGHT_YELLOW"[APPL]: APP_PAIRING>>\r\n"RTT_CTRL_RESET);
APP_ERROR_CHECK( app_timer_stop(app_timer_id));
AppPairingFl=false;
com_master_pairing_stop();
r4s_disable_bonding();
ind_state_change(IND_PAIRING_STOP, NULL);
break;
}
case APP_SLAVE_FW_UPDATE:
{
APP_PRINTF(0,RTT_CTRL_TEXT_BRIGHT_YELLOW"[APPL]: APP_SLAVE_FW_UPDATE>>\r\n"RTT_CTRL_RESET);
APP_ERROR_CHECK( app_timer_stop(app_timer_id));
ind_state_change(IND_FIRMWARE_UPDATE_STOP, NULL);
break;
}
default:
{
break;
}
}
app_prew_state = app_new_state;
return;
}
/**@brief Функция выполняет работу при входе в новое состояние
*
* @param none
*
* @return none
*/
void application_init_new_state( app_state_t app_new_state )
{
uint32_t err_code;
static app_state_t app_prew_state = APP_START;
if( app_prew_state == app_new_state )return;
switch( app_new_state )
{
case APP_START:
{
break;
}
case APP_WAIT_TEST:
{
break;
}
case APP_TEST:
{
APP_PRINTF(0,RTT_CTRL_TEXT_BRIGHT_YELLOW"[APPL]: >>APP_TEST\r\n"RTT_CTRL_RESET);
err_code = api_temp_test_proccess();
if(err_code != NRF_SUCCESS)
{
ind_state_change(IND_TEST_FAILED, NULL);
break;
}
ind_state_change(IND_TEST_START, NULL);
err_code = app_timer_start(app_timer_id, APP_TIMER_TICKS(APP_TEST_START_TIMEOUT_MS, APP_TIMER_PRESCALER), NULL );
APP_ERROR_CHECK( err_code );
app_test_init_success = true;
break;
}
case APP_ALARM:
// Если это аларм - то включить кричалку
ind_state_change(IND_ALARM, NULL);
case APP_ACTIVE:
{
APP_PRINTF(0,RTT_CTRL_TEXT_BRIGHT_YELLOW"[APPL]: >>APP_ACTIVE\r\n"RTT_CTRL_RESET);
// Если переход был не между этими состояниями
if (app_prew_state != APP_ALARM && app_prew_state != APP_ACTIVE) {
err_code = app_timer_stop(app_timer_id);
APP_ERROR_CHECK( err_code );
app_timerout_flag = false;
com_slave_send_state(); //отпраить нотификацию на телефон о состоянии датчика
}
// Если все таки режим активный, то покажем индикацию
if (app_new_state == APP_ACTIVE) {
ind_state_change(IND_ACTIVE, NULL);
}
break;
}
case APP_PAIRING:
{
APP_PRINTF(0,RTT_CTRL_TEXT_BRIGHT_YELLOW"[APPL]: >>APP_PAIRING\r\n"RTT_CTRL_RESET);
err_code = app_timer_stop(app_timer_id);
APP_ERROR_CHECK( err_code );
app_timerout_flag = false;
err_code = app_timer_start(app_timer_id,APP_TIMER_TICKS(APP_PAIRING_TIMEOUT_MS, APP_TIMER_PRESCALER), NULL );
APP_ERROR_CHECK( err_code );
r4s_enable_bonding();
com_master_pairing_start();
ind_state_change(IND_PAIRING_START, NULL);
break;
}
case APP_SLAVE_FW_UPDATE:
{
APP_PRINTF(0,RTT_CTRL_TEXT_BRIGHT_YELLOW"[APPL]: >>APP_SLAVE_FW_UPDATE\r\n"RTT_CTRL_RESET);
err_code = app_timer_stop(app_timer_id);
APP_ERROR_CHECK( err_code );
app_timerout_flag = false;
err_code = app_timer_start(app_timer_id,APP_TIMER_TICKS(APP_FW_UPDATE_TIMEOUT_MS, APP_TIMER_PRESCALER), NULL );
APP_ERROR_CHECK( err_code );
ind_state_change(IND_FIRMWARE_UPDATE_START, NULL);
break;
}
default:
{
break;
}
}
app_prew_state = app_new_state;
return;
}
static void restart_test_timer() {
uint32_t err_code;
err_code = app_timer_stop(app_timer_id);
#ifdef DEBUG
APP_ERROR_CHECK( err_code );
#endif
app_timerout_flag = false;
err_code = app_timer_start(app_timer_id,APP_TIMER_TICKS(APP_TEST_START_TIMEOUT_MS, APP_TIMER_PRESCALER), NULL );
#ifdef DEBUG
APP_ERROR_CHECK( err_code );
#endif
}
/********************************************************************************
*
********************************************************************************/
void application_process()
{
uint32_t err_code;
err_code = button_read(&pair_btn_data );
APP_ERROR_CHECK(err_code);
if (app_state != APP_TEST) {
// Если датчик сломался
if (!m_hardfault && drv_gas_broken_evt_captured()) {
m_hardfault = true;
ind_set_hardfault();
// Сохранение ошибочного состояния в памяти
param_data_t param;
param.is_gas_sensor_broken = true;
#ifndef DEBUG
APP_ERROR_CHECK(param_set_data(¶m));
#endif
}
}
switch(app_state)
{
case APP_START:
{
api_state_change(APP_WAIT_TEST);
break;
}
case APP_WAIT_TEST:
{
if(pair_btn_data.state == BTN_PRESSED)//если какая-либо клавиша нажата за 3 секунды
{
if (pair_btn_data.pressed_time_ms > APP_TEST_STATE_ENTER_TIME_MS) {
err_code = app_timer_stop(app_timer_id);
APP_ERROR_CHECK( err_code );
api_state_change(APP_TEST);
}
} else {
ind_state_change(IND_START, NULL);
api_state_change(APP_ACTIVE);
}
break;
}
case APP_TEST:
{
if(app_test_init_success)
{
if(app_timerout_flag)//прошло 60 секунд
{
// Вернемся в рабочее состояние
drv_gas_reset_broken_state();
ind_state_change(IND_TEST_TIMEOUT, NULL);
api_state_change(APP_ACTIVE);
break;
}
if(pair_btn_data.event_press == BTN_EVENT_CAPTURED)
{
restart_test_timer();
ind_state_change(IND_TEST_BUTTON_PRESSED, NULL);
drv_gas_reset_broken_state();
break;
}
if(pair_btn_data.event_release == BTN_EVENT_CAPTURED)
{
restart_test_timer();
ind_state_change(IND_TEST_BUTTON_RELEASED, NULL);
break;
}
if (drv_gas_broken_evt_captured()) {
restart_test_timer();
ind_state_change(IND_TEST_GAS_HARD_FAULT, NULL);
break;
}
if(drv_gas_is_gas_evt_captured())
{
restart_test_timer();
ind_state_change(IND_TEST_GAS_DETECTED, NULL);
break;
}
if(drv_gas_is_no_gas_evt_captured())
{
restart_test_timer();
ind_state_change(IND_TEST_GAS_IDLE, NULL);
break;
}
}
break;
}
case APP_PAIRING:
{
if(app_timerout_flag == true)
{
ind_state_change(IND_PAIRING_ERROR, NULL);
api_state_change(APP_ACTIVE);
}
break;
}
case APP_SLAVE_FW_UPDATE:
{
if(app_timerout_flag == true) //таймаут обновления прошивки
{
api_state_change(APP_ACTIVE);
}
break;
}
case APP_ALARM:
case APP_ACTIVE:
{
static bool sense_evt_released_captured = false;
api_update_triggers();
/******** REED **********/
if (drv_gas_is_no_gas_evt_captured()) {
APP_PRINTF(0,"GAS IDLE\r\n");
com_master_prior_proccess(EVT_BINARY_SENSOR(GAS_EVENT_CODE, GAS_MASK_Pos, BIN_SENSOR_STATE_IDLE)); // выполнение команд на ИУ согласно конфигуратору
com_slave_send_state(); //отправить нотификацию на телефон о состоянии датчика
application_store_log();
}
if(drv_gas_is_gas_evt_captured()) {
APP_PRINTF(0,"GAS DETECTED\r\n");
com_master_prior_proccess(EVT_BINARY_SENSOR(GAS_EVENT_CODE, GAS_MASK_Pos, BIN_SENSOR_STATE_DETECTED)); // выполнение команд на ИУ согласно конфигуратору
com_slave_send_state(); //отправить нотификацию на телефон о состоянии датчика
application_store_log();
alert_set(ALERT_HIGH);
}
if (app_temp >= CRITICAL_TEMP) {
alert_set(ALERT_HIGH);
}
if ((app_temp < CRITICAL_TEMP - 5) && (!drv_gas_is_detected())) {
alert_set(ALERT_IDLE);
}
/******** BUTTON **********/
if (app_state == APP_ACTIVE) {
if (pair_btn_data.pressed_time_ms >= APP_PAIRING_STATE_ENTER_TIME_MS
&& pair_btn_data.pressed_time_ms < APP_UNPAIRING_STATE_ENTER_TIME_MS)
{
if(AppPairingFl==false)
{
APP_PRINTF(0,RTT_CTRL_RESET"[APPL]: BUTTON PRESSED FOR 5s\r\n"RTT_CTRL_RESET);
AppPairingFl=true;
ind_state_change(IND_PAIRING_INIT, NULL); // индикация пейрига
}
}
if (pair_btn_data.pressed_time_ms >= APP_UNPAIRING_STATE_ENTER_TIME_MS)
{
if(AppUnPairingFl==false)
{
APP_PRINTF(0,RTT_CTRL_RESET"[APPL]: BUTTON PRESSED FOR 10s\r\n"RTT_CTRL_RESET);
AppPairingFl=false;
AppUnPairingFl=true;
ind_state_change(IND_UNPAIRING_INIT, NULL); // индикация анпейрига
}
}
if(pair_btn_data.event_release==BTN_EVENT_CAPTURED)
{
APP_PRINTF(0,RTT_CTRL_RESET"[APPL]: BUTTON RELEASED\r\n"RTT_CTRL_RESET);
if(AppPairingFl==true)
{
api_state_change(APP_PAIRING); // переход в стейт пейринга
}
else
{
if(AppUnPairingFl==true)
{
AppUnPairingFl=false;
com_slave_unpair_proccess(); // анпейринг на слейве
com_master_unpairing(); // анпейринг на мастере
api_reset_params_at_unpairing();
ind_state_change(IND_UNPAIRING_SUCCESS, NULL);
api_need_update();
}
}
}
} else {
// В состоянии тревоги
if(pair_btn_data.event_release==BTN_EVENT_CAPTURED) {
api_reset_alert_state();
}
}
break;
}
default:
{
APP_PRINTF(0,RTT_CTRL_TEXT_BRIGHT_YELLOW"[APPL]: default\r\n"RTT_CTRL_RESET);
api_state_change(APP_ACTIVE);
break;
}
}
if(app_need_update) api_param_update();
// Если все в расписании выключено или удалено, то включаем триггеры
err_code = evcal_add_transaction(EVCAL_TRANSACTION_READ);
if (err_code == NRF_SUCCESS) {
uint8_t count = 0;
evcal_task_t task;
bool is_any_enabled = false;
evcal_get_task_number(&count);
for (uint8_t i = 0; i < count; i++) {
err_code = evcal_get_task_data(i, &task);
APP_ERROR_CHECK(err_code);
if (task.enable) {
is_any_enabled = true;
}
}
if (!is_any_enabled) {
sensors_evt_en.temperature = 1;
}
evcal_dec_transaction(EVCAL_COMMIT_TRANSACTION);
}
}
static void application_store_log(void) {
uint32_t err_code;
cb_data_t record;
calendar_utc_t utc = 0;
calendar_shift_utc_t shift = 0;
//получаем данные о текущем UTC и времени сдвига
err_code = calendar_get_utc_time(&utc, &shift);
#ifdef DEBUG
APP_ERROR_CHECK(err_code);
#endif
if (utc == 0) {// Время не установлено или не верное, не логировать
return;
}
// Упаковка данных
gas_state_data_t pack =
{
.val = {
.gas_flag = api_sense_state_get(),
},
};
record.id = LS_ID_COMPLEX_GAS;
record.utc = utc;
record.data = pack.data_raw;
err_code = cb_put(&record);
#ifdef DEBUG
APP_ERROR_CHECK(err_code);
#endif
}
/********************************************************************************
*
********************************************************************************/
/********************************************************************************
*
********************************************************************************/
/**
* описание в application_api.h
*/
/***************************COMMON************************************/
void api_state_change(app_state_t new_state)
{
app_state = new_state;
application_init_prew_state( app_state );
application_init_new_state( app_state );
}
uint8_t api_get_state(void)
{
switch(app_state)
{
case APP_SLAVE_FW_UPDATE:
{
return APP_API_FW_UPDATE_STATE;
}
case APP_ACTIVE:
case APP_ALARM:
if (m_hardfault) {
return APP_API_ERROR_STATE;
}
return APP_API_STAND_BY_STATE;
case APP_PAIRING:
return APP_API_PAIRING_STATE;
default:
{
return APP_API_ERROR_STATE;
}
}
}
void api_sensor_on(void) {
sensors_evt_en.temperature = true;
}
void api_sensor_off(void) {
sensors_evt_en.temperature = false;
}
__STATIC_INLINE void api_update_triggers(void) {
temp_event_check(app_temp_trigger, temp_triggers_count);
for(uint8_t i=0; i<temp_triggers_count;i++) {
temp_trigger_t * p_this_trigger = &app_temp_trigger[i];
if(p_this_trigger->temp_state == TRIGGER_CAPTURED)
{
if ((p_this_trigger->perm & (1 << MCT_PERM_READ_MASK_pos)) == MCT_PERM_READ(MCT_PERM_ONLY_MASTER) ||
(p_this_trigger->perm & (1 << MCT_PERM_UPDATE_MASK_pos)) == MCT_PERM_UPDATE(MCT_PERM_ONLY_MASTER))
{
com_master_proccess(p_this_trigger->com_event);
p_this_trigger->temp_state = TRIGGER_PROCESSED;
continue;
}
if (sensors_evt_en.temperature && (p_this_trigger->perm == MCT_PERM(MCT_PERM_ANY_USER, MCT_PERM_ANY_USER))) {
com_master_proccess(p_this_trigger->com_event);
p_this_trigger->temp_state = TRIGGER_PROCESSED;
continue;
}
}
}
}
static void alert_set(alert_level_t lvl) {
if (alert_level != lvl) {
if (lvl == ALERT_IDLE) {
app_advertising_set_alert_state(false);
if (app_state == APP_ALARM) {
api_state_change(APP_ACTIVE);
}
} else {
app_advertising_set_alert_state(true);
if (app_state == APP_ACTIVE) {
api_state_change(APP_ALARM);
}
}
}
alert_level = lvl;
}
void api_reset_alert_state(void) {
alert_set(ALERT_IDLE);
}
void api_get_alert_state(uint8_t *p_lvl) {
*p_lvl = alert_level;
}
static void api_internal_action_process(mct_link_t *link) {
switch(link->ac){
case AC_EXTENTION_ALARM: // Произошло событие индикации
{
ind_state_change(IND_BUZZ, link->data);
break;
}
default: // неизвестный action code
break;
}
}
__STATIC_INLINE void api_need_update(void){
app_need_update = true;
}
void api_param_update(void)
{
uint32_t err_code;
temp_triggers_count = 0;
err_code = temp_param_update(app_temp_trigger, &temp_triggers_count);
if(err_code != NRF_ERROR_BUSY)
{
app_need_update = false;
}
}
/**
* описание в application_api.h
*/
uint16_t api_get_temp(void)
{
return FloatToSFloat16(app_temp);
}////////////////////////////////////////////////////////////////
/**
* описание в application_api.h
*/
uint8_t api_set_calendar_data(void *timestamp, void *shift)
{
calendar_utc_t m_time_stamp = 0;
calendar_shift_utc_t m_shift = 0;
m_time_stamp = uint32_decode(timestamp); //преобразуем данные массива в uint32_t
m_shift = uint32_decode(shift); //преобразуем данные массива в uint32_t
uint32_t err_code = calendar_set_time(m_time_stamp, m_shift);
switch (err_code)
{
case NRF_SUCCESS:
return ERSP_SUCCESS;
case NRF_ERROR_INVALID_DATA:
return ERSP_ERROR_INVALID_DATA;
case DRIVER_MODULE_NOT_INITIALZED:
return ERSP_ERROR_INTERNAL;
}
return ERSP_ERROR_UNKNOWN;
}
/**
* описание в application_api.h
*/
void api_get_calendar_data(void *timestamp, void *shift)
{
calendar_utc_t m_time_stamp = 0;
calendar_shift_utc_t m_shift = 0;
//получаем данные о текущем UTC и времени сдвига
uint32_t err_code = calendar_get_utc_time(&m_time_stamp, &m_shift);
#ifdef DEBUG
APP_ERROR_CHECK(err_code);
#endif
memcpy(timestamp, &m_time_stamp, sizeof(calendar_utc_t));
memcpy(shift, &m_shift, sizeof(calendar_shift_utc_t));
}
/**
* @brief Возвращает состояние датчика.
*
*/
uint8_t api_sense_state_get(void)
{
return drv_gas_is_detected();
}
__STATIC_INLINE uint32_t api_temp_test_proccess(void)
{
if(app_temp >= 10 && app_temp <= 60)
{
return NRF_SUCCESS;
}
return NRF_ERROR_INVALID_STATE;
}
void api_reset_params_at_unpairing( void )
{
uint32_t err_code;
//события календаря (до этого уже должны быть очищены все транзакции)
err_code = evcal_add_transaction(EVCAL_TRANSACTION_WRITE);
if (err_code == NRF_SUCCESS) {
evcal_erase_all_tasks();
evcal_dec_transaction(EVCAL_COMMIT_TRANSACTION);
}
sensors_evt_en.temperature = 1;
}
/********************************************************************************/
/***************************PERIPHERAL************************************/
uint8_t api_get_error(void)
{
switch(app_state)
{
case APP_ACTIVE:
case APP_ALARM:
if (m_hardfault) {
return APP_API_INTERNAL_ERROR;
}
default:
return APP_API_NO_ERROR;
}
}
void api_slave_set_connection_flag(void)
{
AppSlaveConnectedFl = true;
if(app_state == APP_PAIRING)
{
uint32_t err_code;
err_code = app_timer_stop(app_timer_id);
#ifdef DEBUG
APP_ERROR_CHECK(err_code);
#endif
}
}
/**
* описание в application_api.h
*/
void api_slave_clear_connection_flag(void)
{
AppSlaveConnectedFl = false;
//выйти из режимов управления камерой или перепрошивки если в них находимся
if(app_state == APP_SLAVE_FW_UPDATE)
{
api_state_change(APP_ACTIVE);
}
if(app_state == APP_PAIRING) {
ind_state_change(IND_PAIRING_ERROR, NULL);
api_state_change(APP_ACTIVE);
}
}
uint8_t api_enter_fw_update_state(void)
{
if((app_state == APP_ACTIVE)
||( app_state == APP_SLAVE_FW_UPDATE))
{
api_state_change(APP_SLAVE_FW_UPDATE);
return 1;
}
return 0;
}
void api_fw_update_proc(void)
{
if( app_state == APP_SLAVE_FW_UPDATE )
{
uint32_t err_code;
err_code = app_timer_stop(app_timer_id);
#ifdef DEBUG
APP_ERROR_CHECK(err_code);
#endif
err_code = app_timer_start(app_timer_id,APP_TIMER_TICKS(APP_FW_UPDATE_TIMEOUT_MS, APP_TIMER_PRESCALER), NULL );
#ifdef DEBUG
APP_ERROR_CHECK(err_code);
#endif
}
}
uint8_t api_go_to_stand_by(void)
{
if(( app_state != APP_ACTIVE)
&& ( app_state != APP_PAIRING )
&& ( app_state != APP_SLAVE_FW_UPDATE ))
{
return 0;
}
if( ( app_state == APP_PAIRING )
|| ( app_state == APP_SLAVE_FW_UPDATE ))
{
api_state_change(APP_ACTIVE);
}
return 1;
}
void r4s_slave_pairing_success( void )
{
if(app_state == APP_PAIRING) {
ind_state_change(IND_PAIRING_SUCCESS, NULL);
api_state_change(APP_ACTIVE);
}
}
void api_reset_hardfault(void) {
m_hardfault = false;
drv_gas_reset_broken_state();
// Сохранение ошибочного состояния в памяти
param_data_t param;
param.is_gas_sensor_broken = false;
APP_ERROR_CHECK(param_set_data(¶m));
ind_reset_hardfault();
}
/********************************************************************************/
/***************************CENTRAL************************************/
/********************************************************************************/
__STATIC_INLINE void set_default_config(uint8_t tok_id, cm_dev_support_ac_t * required_ac) {
mct_transaction_t * tran = NULL;
mct_link_t link;
mct_searchp_context_t search;
memset(&search, 0, sizeof(mct_searchp_context_t));
uint32_t err_code;
APP_PRINTF(0, RTT_CTRL_TEXT_BRIGHT_GREEN"[APPL]: api_master_pairing_complete\r\n"RTT_CTRL_RESET);
if (required_ac->is_support[0] && required_ac->is_support[1]){
// Тип транзации READ_WRITE не рекомендуется использовать, если не будет гарантированной записи
// иначе пока транзакция не будет закрыта остальные транзакции не возможны
err_code = mct_open_transaction(&tran, TRAN_READ_WRITE, TRAN_COMMON_PERM);
if (err_code != NRF_ERROR_BUSY){
#ifdef DEBUG
APP_ERROR_CHECK(err_code);
#endif
memset(&link, 0, sizeof(mct_link_t));
link.tok_id = tok_id;
link.event = EVT_BINARY_SENSOR(GAS_EVENT_CODE, GAS_MASK_Pos, BIN_SENSOR_STATE_DETECTED);
link.ac = AC_EXTENTION_START_CMD;
link.data[0]=0xFF;
link.data[1]=0xFF;
link.enable = 0x01;
link.uuid = 0;
err_code = mct_set_link(tran, &link);
if (err_code != NRF_ERROR_NO_MEM)
APP_ERROR_CHECK(err_code);
memset(&link, 0, sizeof(mct_link_t));
link.tok_id = tok_id;
link.event = EVT_BINARY_SENSOR(GAS_EVENT_CODE, GAS_MASK_Pos, BIN_SENSOR_STATE_IDLE);
link.ac = AC_EXTENTION_STOP_CMD;
link.data[0]=0xFF;
link.data[1]=0xFF;
link.enable = 0x01;
link.uuid = 0;
err_code = mct_set_link(tran, &link);
if (err_code != NRF_ERROR_NO_MEM)
APP_ERROR_CHECK(err_code);
err_code = mct_commit(&tran);
#ifdef DEBUG
APP_ERROR_CHECK(err_code);
#endif
}
}
}
static void api_master_evt_handler(com_master_evt_t * p_evt) {
switch (p_evt->id) {
case COM_MASTER_PAIRING_SUCCESS:{
ind_state_change(IND_PAIRING_SUCCESS, NULL);
api_state_change(APP_ACTIVE);
break;
}
case COM_MASTER_PAIRING_ERROR: {
ind_state_change(IND_PAIRING_ERROR, NULL);
api_state_change(APP_ACTIVE);
break;
}
case COM_MASTER_DEFAULT_CONFIG_REQUIRED:{
set_default_config(
p_evt->param.default_config_required.tok_id,
p_evt->param.default_config_required.p_required_ac
);
break;
}
}
}
/*****************************************************************************************************/