Datavenue Live Objects basic sample using liveobjects-iotsoftbox-mqtt library.
Dependencies: MQTTPacket
main.cpp
- Committer:
- jhamel
- Date:
- 2017-04-04
- Revision:
- 8:82317399e4ce
- Parent:
- 4:919c25da5ec8
File content as of revision 8:82317399e4ce:
/* * Copyright (C) 2016 Orange * * This software is distributed under the terms and conditions of the 'BSD-3-Clause' * license which can be found in the file 'LICENSE.txt' in this package distribution * or at 'https://opensource.org/licenses/BSD-3-Clause'. */ /** * @file main.cpp * @brief A simple user application using all available LiveObjects iotsotbox-mqtt features */ #include "liveobjects_sample.h" #include <stdint.h> #include <string.h> #include "mbed-trace/mbed_trace.h" #include "mbed.h" #include "rtos.h" static const char* appv_version = "MBED SAMPLE V04.01"; #define MEASURES_ENABLED_AT_INIT 0 #define STREAM_PREFIX 1 #define USE_BUTTON_SWITCH 1 //D7 := PTC3 #define USE_BUTTON_SW2 1 #define MEASURES_ENABLED_CTL_ON_SW2 1 #if 0 #define DBG_DFT_MAIN_LOG_LEVEL 3 #define DBG_DFT_LOMC_LOG_LEVEL 1 #define DBG_DFT_MBED_LOG_LEVEL TRACE_ACTIVE_LEVEL_ALL #else #define DBG_DFT_MAIN_LOG_LEVEL 0 #define DBG_DFT_LOMC_LOG_LEVEL 0 #define DBG_DFT_MBED_LOG_LEVEL TRACE_ACTIVE_LEVEL_INFO #endif // Two application threads: /// A very simple application thread Thread appli_thread; /// Thread to manage the input from console Thread console_thread; #if MBED_CONF_APP_NETWORK_INTERFACE == ETHERNET #include "EthernetInterface.h" EthernetInterface eth; #endif NetworkInterface* appv_network_interface = NULL; const char* appv_network_id = NULL; Serial output(USBTX, USBRX); osThreadId appv_thread_id; uint8_t appv_log_level = DBG_DFT_MAIN_LOG_LEVEL; // ========================================================== // Green LED blinking according to the LiveObjects Connection state. /// Application state according to the connectivity. enum app_state_enum { APP_STATE_UNKNOWN = 0, ///< Unknown state APP_STATE_INIT, ///< Initilalization APP_STATE_NETWORK_READY, ///< Ethernet Network is ready. Device has IP address. APP_STATE_CONNECTING, ///< Connecting to the LiveObjects platform APP_STATE_CONNECTED, ///< Connected to the LiveObjects platform APP_STATE_DOWN ///< the LiveObjects thread is down (or stopped) } appv_state = APP_STATE_INIT; // ---------------------------------------------------------- // Status indication /// Green Status LED DigitalOut app_led_status(LED2, 0); /// Ticker to blink the Status LED Ticker app_led_ticker; /** * Called periodically by the Status LED ticker. */ void app_led_blinky(void) { static uint32_t appv_led_cnt = 0; static int32_t appv_led_state = -1; if (appv_state == APP_STATE_CONNECTED) { if (appv_led_state != 4) { appv_led_state = 4; appv_led_cnt = 0; app_led_status = 1; } else { if ((++appv_led_cnt%6) == 0) app_led_status = !app_led_status; } } #if 1 else if (appv_state == APP_STATE_CONNECTING) { if (appv_led_state != 3) { appv_led_state = 3; appv_led_cnt = 0; app_led_status = 0; } app_led_status = !app_led_status; } else if (appv_state == APP_STATE_NETWORK_READY) { if (appv_led_state != 1) { appv_led_state = 1; appv_led_cnt = 0; app_led_status = 0; } if ((++appv_led_cnt%4) == 0) app_led_status = !app_led_status; } else { if (appv_led_state != 2) { appv_led_state = 2; appv_led_cnt = 0; app_led_status = 0; } if ((++appv_led_cnt%2) == 0) app_led_status = !app_led_status; } #endif } // ========================================================== // mbed_trace // Mutex trace_mutex; extern "C" void trace_mutex_wait(void) { trace_mutex.lock(); } extern "C" void trace_mutex_release(void) { trace_mutex.unlock(); } // debug printf function extern "C" unsigned int rt_time_get (void); extern "C" void trace_printer(const char* str) { unsigned int clk = rt_time_get(); printf("%8u %s\r\n", clk, str); } extern "C" char* trace_prefix(size_t sz) { return (char*)" ** "; } // ---------------------------------------------------------- // static void app_trace_setup(void) { mbed_trace_init(); mbed_trace_print_function_set(trace_printer); mbed_trace_prefix_function_set(trace_prefix); mbed_trace_mutex_wait_function_set(trace_mutex_wait); mbed_trace_mutex_release_function_set(trace_mutex_release); uint8_t trace_msk = mbed_trace_config_get(); output.printf("trace_msk = x%X\r\n", trace_msk); // TRACE_ACTIVE_LEVEL_INFO , TRACE_ACTIVE_LEVEL_ALL // TRACE_MODE_COLOR or TRACE_MODE_PLAIN // TRACE_CARRIAGE_RETURN mbed_trace_config_set(DBG_DFT_MBED_LOG_LEVEL|TRACE_MODE_COLOR); } // ========================================================== // Network Initialization #if MBED_CONF_APP_NETWORK_INTERFACE == ETHERNET // ---------------------------------------------------------- /// Network Initialization static int app_net_init(void) { int rc; output.printf("Using Ethernet - Get Dynamic IP Address ...\r\n"); appv_network_interface = NULL; rc = eth.connect(); if (rc != 0) { output.printf("\n\rConnection to Network Failed, rc=%d\r\n", rc); return rc; } const char *ip_addr = eth.get_ip_address(); if (ip_addr) { output.printf("Dynamic IP address %s\r\n", ip_addr); } else { output.printf("No IP address\r\n"); return -1; } appv_network_id = eth.get_mac_address(); if (appv_network_id) { output.printf("MAC address %s\r\n", appv_network_id); } else { output.printf("ERROR: No MAC address !!!!!!\r\n"); } appv_network_interface = ð return 0; } #endif // ========================================================== // // Live Objects IoT Client object (using iotsoftbox-mqtt library) // // - status information at connection // - collected data to send // - supported configuration parameters // - supported commands // - resources declaration (firmware, text file, etc.) // ---------------------------------------------------------- // STATUS data // #if USE_BUTTON_SW2 uint32_t appv_status_sw2_cnt = 0; #endif int32_t appv_status_counter = 0; char appv_status_message[150] = "READY"; /// Set of status LiveObjectsD_Data_t appv_set_status[] = { { LOD_TYPE_STRING_C, "sample_version" , (void*)appv_version }, { LOD_TYPE_INT32, "sample_counter" , &appv_status_counter}, #if USE_BUTTON_SW2 { LOD_TYPE_UINT32, "sample_sw2_cnt" , &appv_status_sw2_cnt}, #endif { LOD_TYPE_STRING_C, "sample_message" , appv_status_message} }; #define SET_STATUS_NB (sizeof(appv_set_status) / sizeof(LiveObjectsD_Data_t)) int appv_hdl_status = -1; // ---------------------------------------------------------- // 'COLLECTED DATA' // // Measures // -------- uint8_t appv_measures_enabled = MEASURES_ENABLED_AT_INIT; int32_t appv_measures_temp_grad = -1; float appv_measures_volt_grad = -0.2; // contains a counter incremented after each data sent uint32_t appv_measures_counter = 0; // contains the temperature level int32_t appv_measures_temp = 20; // contains the battery level float appv_measures_volt = 5.0; /// Set of Collected data (published on a data stream) LiveObjectsD_Data_t appv_set_measures[] = { { LOD_TYPE_UINT32, "counter" , &appv_measures_counter}, { LOD_TYPE_INT32, "temperature" , &appv_measures_temp}, { LOD_TYPE_FLOAT, "battery_level" , &appv_measures_volt } }; #define SET_MEASURES_NB (sizeof(appv_set_measures) / sizeof(LiveObjectsD_Data_t)) int appv_hdl_data = -1; // Button states // ------------- #if USE_BUTTON_SW2 || USE_BUTTON_SWITCH uint8_t appv_button_state_sw2 = 0; uint8_t appv_button_state_switch = 0; LiveObjectsD_Data_t appv_set_button_states[] = { { LOD_TYPE_BOOL, "SW2" , &appv_button_state_sw2 }, { LOD_TYPE_BOOL, "Switch" , &appv_button_state_switch } }; #define SET_DATA_STATES_NB (sizeof(appv_set_button_states) / sizeof(LiveObjectsD_Data_t)) int appv_hdl_states = -1; #endif // ---------------------------------------------------------- // CONFIGURATION data // volatile uint32_t appv_cfg_timeout = 10; // a structure containg various kind of parameters (char[], int and float) struct conf_s { char name[20]; int32_t threshold; float gain; } appv_conf = { "TICTAC", -3, 1.05 }; // definition of identifer for each kind of parameters #define PARM_IDX_NAME 1 #define PARM_IDX_TIMEOUT 2 #define PARM_IDX_THRESHOLD 3 #define PARM_IDX_GAIN 4 /// Set of configuration parameters LiveObjectsD_Param_t appv_set_param[] = { { PARM_IDX_NAME, { LOD_TYPE_STRING_C, "name" , appv_conf.name } }, { PARM_IDX_TIMEOUT, { LOD_TYPE_UINT32, "timeout" , (void*)&appv_cfg_timeout } }, { PARM_IDX_THRESHOLD, { LOD_TYPE_INT32, "threshold" , &appv_conf.threshold } }, { PARM_IDX_GAIN, { LOD_TYPE_FLOAT, "gain" , &appv_conf.gain } } }; #define SET_PARAM_NB (sizeof(appv_set_param) / sizeof(LiveObjectsD_Param_t)) // ---------------------------------------------------------- // COMMANDS // Digital output to change the status of the RED LED DigitalOut app_led_user(LED1, 0); /// counter used to postpone the LED command response static int cmd_cnt = 0; #define CMD_IDX_RESET 1 #define CMD_IDX_LED 2 /// set of commands LiveObjectsD_Command_t appv_set_commands[] = { { CMD_IDX_RESET, "RESET" , 0}, { CMD_IDX_LED, "LED" , 0} }; #define SET_COMMANDS_NB (sizeof(appv_set_commands) / sizeof(LiveObjectsD_Command_t)) // ---------------------------------------------------------- // RESOURCE data // char appv_rsc_image[5*1024] = ""; char appv_rv_message[10] = "01.00"; char appv_rv_image[10] = "01.00"; #define RSC_IDX_MESSAGE 1 #define RSC_IDX_IMAGE 2 /// Set of resources LiveObjectsD_Resource_t appv_set_resources[] = { { RSC_IDX_MESSAGE, "message", appv_rv_message, sizeof(appv_rv_message)-1 }, // resource used to update appv_status_message { RSC_IDX_IMAGE, "image", appv_rv_image, sizeof(appv_rv_image)-1 } }; #define SET_RESOURCES_NB (sizeof(appv_set_resources) / sizeof(LiveObjectsD_Resource_t)) // variables used to process the current resource transfer uint32_t appv_rsc_size = 0; uint32_t appv_rsc_offset = 0; // ========================================================== // IotSoftbox-mqtt callback functions // ---------------------------------------------------------- // CONFIGURATION PARAMETERS Callback function // Check value in range, and copy string parameters /// Called (by the LiveObjects thread) to update configuration parameters extern "C" int main_cb_param_udp(const LiveObjectsD_Param_t* param_ptr, const void* value, int len) { if (param_ptr == NULL) { output.printf("UPDATE ERROR - invalid parameter x%p\r\n",param_ptr); return -1; } output.printf("UPDATE user_ref=%d %s ....\r\n", param_ptr->parm_uref, param_ptr->parm_data.data_name); switch(param_ptr->parm_uref) { case PARM_IDX_NAME: { output.printf("update name = %.*s\r\n", len , (const char*) value); if ((len > 0) && (len < (sizeof(appv_conf.name)-1))) { // Only c-string parameter must be updated by the user application (to check the string length) strncpy(appv_conf.name, (const char*) value, len); appv_conf.name[len] = 0; return 0; // OK. } } break; case PARM_IDX_TIMEOUT: { uint32_t timeout = *((const uint32_t*)value); output.printf("update timeout = %"PRIu32"\r\n", timeout); if ((timeout > 0) && (timeout <= 120) && (timeout != appv_cfg_timeout)) { return 0; // primitive parameter is updated by library } } break; case PARM_IDX_THRESHOLD: { int32_t threshold = *((const int32_t*)value); output.printf("update threshold = %"PRIi32"\r\n", threshold); if ((threshold >= -10) && (threshold <= 10) && (threshold != appv_conf.threshold)) { return 0; // primitive parameter is updated by library } } break; case PARM_IDX_GAIN: { float gain = *((const float*)value); output.printf("update gain = %f\r\n", gain); if ((gain > 0.0) && (gain < 10.0) && (gain != appv_conf.gain)) { return 0; // primitive parameter is updated by library } } break; } output.printf("ERROR to update param[%d] %s !!!\r\n", param_ptr->parm_uref, param_ptr->parm_data.data_name); return -1; } // ---------------------------------------------------------- // RESOURCE Callback Functions /** * Called (by the LiveObjects thread) to notify either, * - state = 0 : the begin of resource request * - state = 1 : the end without error * - state != 1 : the end with an error */ extern "C" LiveObjectsD_ResourceRespCode_t main_cb_rsc_ntfy ( uint8_t state, const LiveObjectsD_Resource_t* rsc_ptr, const char* version_old, const char* version_new, uint32_t size) { LiveObjectsD_ResourceRespCode_t ret = RSC_RSP_OK; // OK to update the resource output.printf("*** rsc_ntfy: ...\r\n"); if ((rsc_ptr) && (rsc_ptr->rsc_uref > 0) && (rsc_ptr->rsc_uref <= SET_RESOURCES_NB)) { output.printf("*** user ref = %d\r\n", rsc_ptr->rsc_uref); output.printf("*** name = %s\r\n", rsc_ptr->rsc_name); output.printf("*** version_old = %s\r\n", version_old); output.printf("*** version_new = %s\r\n", version_new); output.printf("*** size = %u\r\n", size); if (state) { if (state == 1) { // Completed without error output.printf("*** state = COMPLETED without error\r\n"); // Update version output.printf(" ===> UPDATE - version %s to %s\r\n", rsc_ptr->rsc_version_ptr, version_new); strncpy((char*)rsc_ptr->rsc_version_ptr, version_new, rsc_ptr->rsc_version_sz); if (rsc_ptr->rsc_uref == RSC_IDX_IMAGE) { trace_mutex_wait(); output.printf("\r\n\r\n"); output.printf(appv_rsc_image); output.printf("\r\n\r\n"); trace_mutex_release(); } } else { output.printf("*** state = COMPLETED with error !!!!\r\n"); // Roll back ? } appv_rsc_offset = 0; appv_rsc_size = 0; // Push Status (message has been updated or not) LiveObjectsClient_PushStatus( appv_hdl_status ); } else { appv_rsc_offset = 0; ret = RSC_RSP_ERR_NOT_AUTHORIZED; switch (rsc_ptr->rsc_uref ) { case RSC_IDX_MESSAGE: if (size < (sizeof(appv_status_message)-1)) { ret = RSC_RSP_OK; } break; case RSC_IDX_IMAGE: if (size < (sizeof(appv_rsc_image)-1)) { ret = RSC_RSP_OK; } break; } if (ret == RSC_RSP_OK) { appv_rsc_size = size; output.printf("*** state = START - ACCEPTED\r\n");; } else { appv_rsc_size = 0; output.printf("*** state = START - REFUSED\r\n"); } } } else { output.printf("*** UNKNOWN USER REF (x%p %d) in state=%d\r\n", rsc_ptr, rsc_ptr->rsc_uref, state); ret = RSC_RSP_ERR_INVALID_RESOURCE; } return ret; } /** * Called (by the LiveObjects thread) to request the user * to read data from current resource transfer. */ extern "C" int main_cb_rsc_data (const LiveObjectsD_Resource_t* rsc_ptr, uint32_t offset) { int ret; if (appv_log_level > 1) output.printf("*** rsc_data: rsc[%d]='%s' offset=%u - data ready ...\r\n", rsc_ptr->rsc_uref, rsc_ptr->rsc_name, offset); if (rsc_ptr->rsc_uref == RSC_IDX_MESSAGE) { char buf[40]; if (offset > (sizeof(appv_status_message)-1)) { output.printf("*** rsc_data: rsc[%d]='%s' offset=%u > %d - OUT OF ARRAY\r\n", rsc_ptr->rsc_uref, rsc_ptr->rsc_name, offset, sizeof(appv_status_message)-1); return -1; } ret = LiveObjectsClient_RscGetChunck(rsc_ptr, buf, sizeof(buf)-1); if (ret > 0) { if ((offset+ret) > (sizeof(appv_status_message)-1)) { output.printf("*** rsc_data: rsc[%d]='%s' offset=%u - read=%d => %d > %d - OUT OF ARRAY\r\n", rsc_ptr->rsc_uref, rsc_ptr->rsc_name, offset, ret, offset + ret, sizeof(appv_status_message)-1); return -1; } appv_rsc_offset += ret; memcpy(&appv_status_message[offset], buf, ret); appv_status_message[offset+ret] = 0; output.printf("*** rsc_data: rsc[%d]='%s' offset=%u - read=%d/%d '%s'\r\n", rsc_ptr->rsc_uref, rsc_ptr->rsc_name, offset, ret, sizeof(buf)-1, appv_status_message); } } else if (rsc_ptr->rsc_uref == RSC_IDX_IMAGE) { if (offset > (sizeof(appv_rsc_image)-1)) { output.printf("*** rsc_data: rsc[%d]='%s' offset=%u > %d - OUT OF ARRAY\r\n", rsc_ptr->rsc_uref, rsc_ptr->rsc_name, offset, sizeof(appv_rsc_image)-1); return -1; } int data_len = sizeof(appv_rsc_image) - offset - 1; ret = LiveObjectsClient_RscGetChunck(rsc_ptr, &appv_rsc_image[offset], data_len); if (ret > 0) { if ((offset+ret) > (sizeof(appv_rsc_image)-1)) { output.printf("*** rsc_data: rsc[%d]='%s' offset=%u - read=%d => %d > %d - OUT OF ARRAY\r\n", rsc_ptr->rsc_uref, rsc_ptr->rsc_name, offset, ret, offset + ret, sizeof(appv_rsc_image)-1); return -1; } appv_rsc_offset += ret; if (appv_log_level > 0) output.printf("*** rsc_data: rsc[%d]='%s' offset=%u - read=%d/%d - %u/%u\r\n", rsc_ptr->rsc_uref, rsc_ptr->rsc_name, offset, ret, data_len, appv_rsc_offset, appv_rsc_size); } else { output.printf("*** rsc_data: rsc[%d]='%s' offset=%u - read error (%d) - %u/%u\r\n", rsc_ptr->rsc_uref, rsc_ptr->rsc_name, offset, ret, appv_rsc_offset, appv_rsc_size); } } else { ret = -1; } return ret; } // ---------------------------------------------------------- // COMMAND Callback Functions static int main_cmd_doSystemReset(LiveObjectsD_CommandRequestBlock_t* pCmdReqBlk); static int main_cmd_doLED(LiveObjectsD_CommandRequestBlock_t* pCmdReqBlk); /// Called (by the LiveObjects thread) to perform an 'attached/registered' command extern "C" int main_cb_command(LiveObjectsD_CommandRequestBlock_t* pCmdReqBlk) { int ret; const LiveObjectsD_Command_t* cmd_ptr; if ((pCmdReqBlk == NULL) || (pCmdReqBlk->hd.cmd_ptr == NULL) || (pCmdReqBlk->hd.cmd_cid == 0) ) { output.printf("**** COMMAND : ERROR, Invalid parameter\r\n"); return -1; } cmd_ptr = pCmdReqBlk->hd.cmd_ptr; output.printf("**** COMMAND %d %s - cid=%d\r\n", cmd_ptr->cmd_uref, cmd_ptr->cmd_name, pCmdReqBlk->hd.cmd_cid); { int i; output.printf("**** ARGS %d : \r\n", pCmdReqBlk->hd.cmd_args_nb); for (i=0; i < pCmdReqBlk->hd.cmd_args_nb; i++) { output.printf("**** ARG [%d] (%d) : %s %s\r\n", i, pCmdReqBlk->args_array[i].arg_type, pCmdReqBlk->args_array[i].arg_name, pCmdReqBlk->args_array[i].arg_value); } } switch(cmd_ptr->cmd_uref) { case CMD_IDX_RESET: // RESET output.printf("main_callbackCommand: command[%d] %s\r\n", cmd_ptr->cmd_uref, cmd_ptr->cmd_name); ret = main_cmd_doSystemReset(pCmdReqBlk); break; case CMD_IDX_LED: // LED output.printf("main_callbackCommand: command[%d] %s\r\n", cmd_ptr->cmd_uref, cmd_ptr->cmd_name); ret = main_cmd_doLED(pCmdReqBlk); break; default : output.printf("main_callbackCommand: ERROR, unknown command %d\r\n", cmd_ptr->cmd_uref); ret = -4; } return ret; } // ---------------------------------------------------------- /// Board reset static void main_SystemReset(void) { NVIC_SystemReset(); } // ---------------------------------------------------------- /// do a RESET command static int main_cmd_doSystemReset(LiveObjectsD_CommandRequestBlock_t* pCmdReqBlk) { if (LiveObjectsClient_Stop()) { output.printf("doSystemReset: not running => wait 500 ms and reset ...\r\n"); wait_ms(200); main_SystemReset(); } return 1; // response = OK } // ---------------------------------------------------------- /// Delayed Response to the LED command static void main_cmd_delayed_resp_LED () { if (cmd_cnt > 0) { LiveObjectsD_Command_t* cmd_ptr = &appv_set_commands[CMD_IDX_LED-1]; if (appv_log_level > 1) output.printf("main_cmd_delayed_resp_LED: cnt=%d cid=%d\r\n", cmd_cnt, cmd_ptr->cmd_cid); if ((--cmd_cnt <= 0) && (cmd_ptr->cmd_cid)) { uint32_t code = 200; char msg [] = "USER LED TEST = OK"; LiveObjectsD_Data_t cmd_resp[] = { { LOD_TYPE_UINT32, "code" , &code}, { LOD_TYPE_STRING_C, "msg" , msg} }; // switch off the Red LED app_led_user = 1; output.printf("\r\n*** main_cmd_resp_LED: RESPONSE ...\r\n"); LiveObjectsClient_CommandResponse(cmd_ptr->cmd_cid, cmd_resp, 2); cmd_ptr->cmd_cid = 0; cmd_cnt = 0; } } } // ---------------------------------------------------------- /// do a LED command static int main_cmd_doLED(LiveObjectsD_CommandRequestBlock_t* pCmdReqBlk) { int ret; // switch on the Red LED app_led_user = 0; if (pCmdReqBlk->hd.cmd_args_nb == 0) { output.printf("main_cmd_doLED: No ARG\r\n"); app_led_user = ! app_led_user; ret = 1; // Response OK cmd_cnt = 0; } else { int i; int cnt; for (i=0; i<pCmdReqBlk->hd.cmd_args_nb;i++ ) { if ( strncasecmp("ticks", pCmdReqBlk->args_array[i].arg_name, 5) && pCmdReqBlk->args_array[i].arg_type == 0 ) { cnt = atoi(pCmdReqBlk->args_array[i].arg_value); if ((cnt >= 0) || (cnt <= 3)) { cmd_cnt = cnt; } else cmd_cnt = 0; output.printf("main_cmd_doLED: cmd_cnt = %di (%d)\r\n", cmd_cnt, cnt); } } } if (cmd_cnt == 0) { app_led_user = ! app_led_user; ret = 1; // Response OK } else { LiveObjectsD_Command_t* cmd_ptr = (LiveObjectsD_Command_t*)(pCmdReqBlk->hd.cmd_ptr); app_led_user = 0; output.printf("main_cmd_doLED: ccid=%d (%d)\r\n", pCmdReqBlk->hd.cmd_cid, cmd_ptr->cmd_cid); cmd_ptr->cmd_cid = pCmdReqBlk->hd.cmd_cid; ret = 0; // pending } return ret; // response = OK } // ========================================================== // BUTTONS // ---------------------------------------------------------- // Button Interrupt SW2 #if USE_BUTTON_SW2 short appv_button_sw2_raise = 0; InterruptIn appv_button_sw2_int(SW2); void app_sw2_release(void) { //output.printf("On-board button SW2 was released - state=%u cnt=%u\r\n", appv_sw2_raise, appv_status_sw2_cnt); appv_button_sw2_raise = 1; } #endif /* USE_BUTTON_SW2 */ // ---------------------------------------------------------- // Button Switch D7 #if USE_BUTTON_SWITCH DigitalIn appv_button_switch_in(D7, PullDown); //D7 := PTC3 (D8 := PTA0) #endif void app_button_test(void) { #if USE_BUTTON_SW2 || USE_BUTTON_SWITCH uint8_t change = 0; uint8_t button_state; #if USE_BUTTON_SW2 if (appv_button_sw2_raise) { appv_button_sw2_raise = 0; button_state = (appv_button_state_sw2) ? 0 : 1; output.printf(" *** FLIP-FLOP STATE OF SW2 %u -> %u\r\n", appv_button_state_sw2 , button_state); appv_button_state_sw2 = button_state; #if MEASURES_ENABLED_CTL_ON_SW2 appv_measures_enabled = (appv_measures_enabled) ? 0 : 1; output.printf(" ==> Now MEASURES PUBLISH is %s\r\n", appv_measures_enabled ? "enabled" : "disabled"); #endif change ++; if (appv_hdl_status >= 0) { appv_status_sw2_cnt++; LiveObjectsClient_PushStatus(appv_hdl_status); } } #endif #if USE_BUTTON_SWITCH button_state = appv_button_switch_in.read() ? 0 : 1; if (appv_button_state_switch != button_state) { change ++; output.printf(" *** BUTTON STATE CHANGE %d -> %d \r\n", appv_button_state_switch, button_state); appv_button_state_switch = button_state; } #endif if ((change) && (appv_hdl_states >= 0)) { LiveObjectsClient_PushData(appv_hdl_states); } #endif } // ========================================================== /// Counter ticker to increment periodically a application counter Ticker counter_ticker; /// Called periodically by the ticker void counter_inc(void) { appv_measures_counter ++; } /** * Application thread: * - Send the delayed LED command response (if pending) */ void thread_appli(void) { uint32_t loop_delay = 0; uint32_t loop_cnt = 0; osThreadId id = osThreadGetId(); output.printf("thread_appli: running %x\r\n", id); while(1) { uint32_t delay = appv_cfg_timeout*1000; // set to milliseconds if (delay == 0) delay = 1000; // min. 1 seconds else if (delay > 120000) delay = 120000; // max. 2 minutes wait_ms(100); loop_delay += 100; // Process button state change app_button_test(); // Process the LED command response if pending. main_cmd_delayed_resp_LED(); if (loop_delay < delay) { continue; } loop_delay = 0; ++loop_cnt; if (appv_log_level > 1) output.printf("thread_appli: %u - period= %u ms\r\n", loop_cnt, delay); // Simulate measures : Voltage and Temperature ... if (appv_measures_volt <= 0.0) appv_measures_volt_grad = 0.2; else if (appv_measures_volt >= 5.0) appv_measures_volt_grad = -0.3; if (appv_measures_temp <= -3) appv_measures_temp_grad = 1; else if (appv_measures_temp >= 20) appv_measures_temp_grad = -1; appv_measures_volt += appv_measures_volt_grad; appv_measures_temp += appv_measures_temp_grad; if (appv_log_level > 2) output.printf("thread_appli: %u - %s PUBLISH - volt=%2.2f temp=%d\r\n", loop_cnt, appv_measures_enabled ? "DATA" : "NO", appv_measures_volt, appv_measures_temp); if (appv_measures_enabled) { LiveObjectsClient_PushData( appv_hdl_data ); } } } // ========================================================== // const char* appv_help = " R : system reset\r\n" " d : push 'collected data'\r\n" " s : push 'status'\r\n" " c : push 'config. parameters'\r\n" " r : push 'resources'\r\n" " p : publish STATUS message\r\n" " e : Enable/Disable the data publishing\r\n" " X|M|n : Enable/Disable the dump of published message (X to enable also hexa dump)\r\n" " D|I|W : set debug log level (mbed_trace)\r\n" " 0-9 : set appli log level \r\n" ; /** * Console thread * - wait for an input character from terminal * - perform the requested operation */ void thread_input_cons(void) { int c; osThreadId id = osThreadGetId(); output.printf("thread_input_cons: running %x\r\n", id); while(1) { osDelay(500); #if 1 if (output.readable()) { // WARNING: getc is a blocking call, and can also block the printf !!! c = output.getc(); if (c) { if (appv_log_level > 1) output.printf("thread_input_cons: input x%x\r\n", c); if (c == 'h') { output.printf(appv_help); } else if ( c == 'e' ) { appv_measures_enabled = (appv_measures_enabled) ? 0 : 1; output.printf(">>> %s data publish\r\n", appv_measures_enabled ? "Enable" : "Disable"); } else if ( c == 'p' ) { char msg[40]; appv_status_counter++; snprintf(msg,sizeof(msg)-1,"{\"info\":{\"counter\": %u}}", appv_status_counter); output.printf(">>> Publish t=/dev/info msg=%s ...\r\n", msg); LiveObjectsClient_Publish("dev/info", msg); // Publish JSON message built by user } else if ( c == 'd' ) { appv_measures_counter++; output.printf(">>> Push DATA - cnt %u\r\n", appv_measures_counter); LiveObjectsClient_PushData( appv_hdl_data ); } else if (c == 's' ) { appv_status_counter ++; output.printf(">>> Push STATUS - counter %u\r\n", appv_status_counter); LiveObjectsClient_PushStatus( appv_hdl_status ); } else if (c == 'c' ) { output.printf(">>> Push CONFIG\r\n"); LiveObjectsClient_PushCfgParams(); } else if (c == 'r' ) { output.printf(">>> Push RESOURCES\r\n"); LiveObjectsClient_PushResources(); } else if (c == 'X') { output.printf(">>> Enable Message Dump (+ hexa dump)\r\n"); LiveObjectsClient_SetDbgLevel(3); } else if (c == 'M') { output.printf(">>> Enable Message Dump\r\n"); LiveObjectsClient_SetDbgLevel(1); } else if (c == 'm') { output.printf(">>> Disable Message Dump\r\n"); LiveObjectsClient_SetDbgLevel(0); } else if (c == 'D') { output.printf(">>> Set trace level : DEBUG\r\n"); mbed_trace_config_set(TRACE_ACTIVE_LEVEL_ALL|TRACE_MODE_COLOR); } else if (c == 'I') { output.printf(">>> Set trace level : INFO\r\n"); mbed_trace_config_set(TRACE_ACTIVE_LEVEL_INFO|TRACE_MODE_COLOR); } else if (c == 'W') { output.printf(">>> Set trace level : WARNING\r\n"); mbed_trace_config_set(TRACE_ACTIVE_LEVEL_WARN|TRACE_MODE_COLOR); } else if ((c >= '0') && (c <= '9')) { output.printf(">>> Set appli dbg level : %d -> %c\r\n", appv_log_level, c); appv_log_level = c - '0'; } else if (c == 'R') { main_SystemReset(); } } } #endif } } // ========================================================== // // ---------------------------------------------------------- /// Called (by LiveOjbects thread) to notify a connectivity state change static void appli_client_state_cb(LiveObjectsD_State_t state) { enum app_state_enum new_state = APP_STATE_UNKNOWN; switch (state) { case CSTATE_CONNECTING: new_state = APP_STATE_CONNECTING; break; case CSTATE_CONNECTED: new_state = APP_STATE_CONNECTED; break; case CSTATE_DISCONNECTED: new_state = APP_STATE_NETWORK_READY; break; case CSTATE_DOWN: new_state = APP_STATE_DOWN; break; } output.printf("\n\rLIVEOBJECTS CLIENT STATE CHANGE (%d) : %d -> %d \r\n", state, appv_state, new_state); appv_state = new_state; } // ---------------------------------------------------------- /// Entry point to the program int main() { int ret; app_led_status = 1; app_led_user = 1; appv_state = APP_STATE_INIT; // Led blink at 250 ms app_led_ticker.attach_us(app_led_blinky, 250000); // Keep track of the main thread appv_thread_id = osThreadGetId(); // Sets the console baud-rate output.baud(9600); output.printf("\r\n\r\n"); output.printf("Starting LiveObject Client Example %s (tid=x%p) ...\r\n", appv_version, appv_thread_id); #if USE_BUTTON_SW2 // Enable interrupts: SW2 output.printf("Enable SW2 ..\r\n"); appv_button_sw2_int.rise(&app_sw2_release); appv_button_state_sw2 = 0; #endif #if USE_BUTTON_SWITCH appv_button_state_switch = appv_button_switch_in.read() ? 0 : 1; output.printf("Initial state of SWITCH button (D7) = %u\r\n", appv_button_state_switch); #endif app_trace_setup(); // Start program only if LiveObjet Apikey parameter is well defined if (LiveObjectsClient_CheckApiKey(LOC_CLIENT_DEV_API_KEY)) { output.printf("apikey not set, '%s'\r\n", LOC_CLIENT_DEV_API_KEY); output.printf("\n\rExiting application ....\r\n"); return -1; } // Setup the Ethernet Interface if (0 == app_net_init()) { output.printf("\n\rConnected to Network successfully\r\n"); LiveObjectsClient_SetDbgLevel(DBG_DFT_LOMC_LOG_LEVEL); // Initialize the LiveObjects Client Context // ----------------------------------------- output.printf("\n\rLiveObjectsClient_Init ...\r\n"); ret = LiveObjectsClient_Init(appv_network_interface); if (ret) { output.printf("\n\rLiveObjectsClient_Init Failed !\r\n"); } else { #if LOC_CLIENT_USE_MAC_ADDR if (appv_network_id) { // Use the MAC address to set the Device Identifier // -------------------------------------------- output.printf("\n\rLiveObjectsClient_SetDevId '%s' ...\r\n", appv_network_id); ret = LiveObjectsClient_SetDevId(appv_network_id); if (ret) { output.printf("\n\rLiveObjectsClient_SetDevId Failed !\r\n"); } } #endif // Attach my local RESOURCES to the LiveObjects Client instance // ------------------------------------------------------------ ret = LiveObjectsClient_AttachResources(appv_set_resources, SET_RESOURCES_NB, main_cb_rsc_ntfy, main_cb_rsc_data); if (ret) output.printf(" !!! ERROR (%d) to attach RESOURCES !\r\n", ret); // Attach my local Configuration Parameters to the LiveObjects Client instance // ---------------------------------------------------------------------------- ret = LiveObjectsClient_AttachCfgParams(appv_set_param, SET_PARAM_NB, main_cb_param_udp); if (ret) output.printf(" !!! ERROR (%d) to attach Config Parameters !\r\n", ret); // Attach a set of commands to the LiveObjects Client instance // ----------------------------------------------------------- ret = LiveObjectsClient_AttachCommands(appv_set_commands, SET_COMMANDS_NB, main_cb_command); if (ret < 0) output.printf(" !!! ERROR (%d) to attach a set of commands !\r\n", ret); // Attach my local STATUS data to the LiveObjects Client instance // -------------------------------------------------------------- appv_hdl_status = LiveObjectsClient_AttachStatus(appv_set_status, SET_STATUS_NB); if (appv_hdl_status) output.printf(" !!! ERROR (%d) to attach status !\r\n", appv_hdl_status); // Attach 2 sets of collected data to the LiveObjects Client instance // -------------------------------------------------------------------- appv_hdl_data = LiveObjectsClient_AttachData(STREAM_PREFIX, "LO_sample_measures", "mV1","\"Test\"", NULL, appv_set_measures, SET_MEASURES_NB); if (appv_hdl_data < 0) output.printf(" !!! ERROR (%d) to attach a collected data stream !\r\n", appv_hdl_data); #if USE_BUTTON_SW2 || USE_BUTTON_SWITCH appv_hdl_states = LiveObjectsClient_AttachData(STREAM_PREFIX, "LO_sample_events","mv1","\"Test\",\"EVT\"", NULL, appv_set_button_states, SET_DATA_STATES_NB); if (appv_hdl_states < 0) output.printf(" !!! ERROR (%d) to attach a collected data stream - STATES !\r\n", appv_hdl_states); #endif // ================================== // User Application part. #if 1 wait_ms(1000); // Start the counter ticker at 500 ms counter_ticker.attach_us(counter_inc, 500000); // appv_measures_counter output.printf(" ---- Start thread : thread_input_cons ....\r\n"); ret = console_thread.start(thread_input_cons); if (ret) { output.printf("\n\r !!!! ERROR(%d) to start thread : thread_input_cons\r\n", ret); } #if 1 output.printf(" ---- Start thread : thread_appli ....\r\n"); ret = appli_thread.start(thread_appli); if (ret) { output.printf("\n\r !!!! ERROR(%d) to start thread : thread_appli\r\n", ret); } wait_ms(1000); #endif #endif // Enable the receipt of commands ret = LiveObjectsClient_ControlCommands(true); if (ret < 0) output.printf(" !!! ERROR (%d) to enable the receipt of commands !\r\n", ret); // Enable the receipt of resource update requests ret = LiveObjectsClient_ControlResources(true); if (ret < 0) output.printf(" !!! ERROR (%d) to enable the receipt of resource update request !\r\n", ret); #if 0 // ================================== // Run LiveObjects Client in main thread (forever ...) output.printf("\n\rLiveObjectsClient_Run ...\r\n"); LiveObjectsClient_Run(appli_client_state_cb); output.printf("\n\rLiveObjectsClient_Run Failed !!!!\r\n"); #else // ================================== // Start a new sthread to run LiveObjects Client (forever ...) output.printf("\n\rLiveObjectsClient_ThreadStart ...\r\n"); ret = LiveObjectsClient_ThreadStart(appli_client_state_cb); if (ret == 0) { while(LiveObjectsClient_ThreadState() >= 0) { wait_ms(1000); } } output.printf("\n\rLiveObjectsClient_ThreadStart ERROR %d\r\n", ret); #endif } } else { output.printf("\n\rConnection to Network Failed ! \r\n"); } output.printf("\n\rExiting application ....\r\n"); app_led_ticker.detach(); app_led_status = 0; app_led_user = 0; main_SystemReset(); }