SJ One Development source code: cmpe244 s14 am asset management lpc.txt

From Embedded Systems Learning Academy
Jump to: navigation, search

From a9e69ff3594730460b89db7e973a3bb99e54b963 Mon Sep 17 00:00:00 2001 From: Pardeep <p_badhan2004@yahoo.com> Date: Wed, 16 Apr 2014 23:30:29 -0700 Subject: [PATCH 01/23] Enables communication with Bluetooth via Uart3

1. Adds "bt" command to terminal (CLI) interface to send command/data to
Bluetooth module. For example, the syntax to get into command mode would
be "bt $$$" and to enabe RSSI, it would be "bt l".
2. Adds a task that receives data from Bluetooth via Uart3 and print the
data to the terminal.

---

L5_Application/bt.hpp              | 19 +++++++++++++++
L5_Application/handlers.hpp        |  3 ++-
L5_Application/main.cpp            |  4 ++--
L5_Application/source/bt.cpp       | 47 ++++++++++++++++++++++++++++++++++++++
L5_Application/source/terminal.cpp |  2 +-
L5_Application/tasks.hpp           |  2 +-
6 files changed, 72 insertions(+), 5 deletions(-)
create mode 100644 L5_Application/bt.hpp
create mode 100644 L5_Application/source/bt.cpp

diff --git a/L5_Application/bt.hpp b/L5_Application/bt.hpp new file mode 100644 index 0000000..dde08f9 --- /dev/null +++ b/L5_Application/bt.hpp @@ -0,0 +1,19 @@ +/* + * bt.hpp + * + * Created on: Apr 16, 2014 + */ + +#ifndef BT_HPP_ +#define BT_HPP_ + +#include "scheduler_task.hpp" + +class BTRxTask : public scheduler_task +{ + public: + BTRxTask(uint8_t priority); + bool run(void *p); +}; + +#endif /* BT_HPP_ */ diff --git a/L5_Application/handlers.hpp b/L5_Application/handlers.hpp index cd491fd..3bdc696 100644 --- a/L5_Application/handlers.hpp +++ b/L5_Application/handlers.hpp @@ -86,6 +86,7 @@ CMD_HANDLER_FUNC(learnIrHandler);

/// Send a packet over the air
CMD_HANDLER_FUNC(wirelessHandler);

- +/// Send Bluetooth command/data +CMD_HANDLER_FUNC(btHandler);

#endif /* HANDLERS_HPP_ */

diff --git a/L5_Application/main.cpp b/L5_Application/main.cpp index 78d83ea..e805f37 100644 --- a/L5_Application/main.cpp +++ b/L5_Application/main.cpp @@ -27,8 +27,6 @@

#include "tasks.hpp"
#include "examples/examples.hpp"

- -

/**
 * The main() creates tasks or "threads".  See the documentation of scheduler_task class at cpp_task.hpp
 * for details.  There is a very simple example towards the beginning of this class's declaration.

@@ -45,6 +43,8 @@

 */
int main(void)
{

+ scheduler_add_task(new BTRxTask(PRIORITY_LOW)); +

    /**
     * A few basic tasks for this bare-bone system :
     *      1.  Terminal task provides gateway to interact with the board through UART terminal.

diff --git a/L5_Application/source/bt.cpp b/L5_Application/source/bt.cpp new file mode 100644 index 0000000..4cbb56a --- /dev/null +++ b/L5_Application/source/bt.cpp @@ -0,0 +1,47 @@ +/* + * bt.cpp + * + * Created on: Apr 16, 2014 + */ + +#include <stdio.h> +#include <string.h> +#include "bt.hpp" +#include "command_handler.hpp" +#include "uart3.hpp" + +CMD_HANDLER_FUNC(btHandler) +{ + if (cmdParams.getLen()) { + if (cmdParams.compareTo("$$$")) { + /* + * String to enter command mode must not be null or + * carriage return terminated + */ + Uart3::getInstance().put(cmdParams.c_str()); + } else { + /* All other commands need to be null terminated */ + Uart3::getInstance().putline(cmdParams.c_str()); + } + } + return (true); +} + +BTRxTask::BTRxTask(uint8_t priority) : + scheduler_task("BTRXTask", 4*512, priority) +{ + setRunDuration(500); + Uart3::getInstance().init(115200, 1000, 1000); +} + +bool BTRxTask::run(void *p) +{ + char rx_data[250]; + + memset(rx_data, 0, sizeof(rx_data)); + if (Uart3::getInstance().gets(rx_data, sizeof(rx_data), 100)) { + printf("\nBT RX:\n [%s]\n", rx_data); + } + + return (true); +} diff --git a/L5_Application/source/terminal.cpp b/L5_Application/source/terminal.cpp index 8fbb75d..5cf55a4 100644 --- a/L5_Application/source/terminal.cpp +++ b/L5_Application/source/terminal.cpp @@ -107,7 +107,7 @@ bool terminalTask::taskEntry()

                                             "Write buffer: buffer <offset> <num bytes> ...\n"
                                             "Write buffer to file: commit <filename> <file offset> <num bytes from buffer>");
    cp.addHandler(flashProgHandler, "flash", "'flash <filename>' Will flash CPU with this new binary file");

- + cp.addHandler(btHandler, "bt", "Send commands/data to Bluetooth module\n");

    #if (ENABLE_TELEMETRY)
    cp.addHandler(telemetryHandler, "telemetry", "Outputs registered telemetry: "
                                                 "'telemetry save' : Saves disk tel\n"

diff --git a/L5_Application/tasks.hpp b/L5_Application/tasks.hpp index b2b365a..2aa82c3 100644 --- a/L5_Application/tasks.hpp +++ b/L5_Application/tasks.hpp @@ -28,7 +28,7 @@

#include "command_handler.hpp"
#include "wireless.h"
#include "char_dev.hpp"

- +#include "bt.hpp"


/**

-- 1.8.5.2.msysgit.0


From 68c7565a0e68ad055b252b0c20af045e3a6649b5 Mon Sep 17 00:00:00 2001 From: Pardeep <p_badhan2004@yahoo.com> Date: Wed, 23 Apr 2014 18:56:10 -0700 Subject: [PATCH 02/23] Laying down the user menu infra.

Added code the allow the following operations (Using the on-board switches): 1. User can scroll up/down in the "Main Menu" 2. User can select "Track Menu" 3. User can go brack from "Track Menu" to "Main Menu"

Moved around the BT.[hc]pp files to combine project files under the "assetManagement" directory. ---

L5_Application/assetManagement/assetManagement.hpp |  89 ++++++
L5_Application/assetManagement/bt.hpp              |  19 ++
.../assetManagement/src/assetManagement.cpp        | 318 +++++++++++++++++++++
L5_Application/assetManagement/src/bt.cpp          |  47 +++
L5_Application/bt.hpp                              |  19 --
L5_Application/main.cpp                            |   6 +-
L5_Application/shared_handles.h                    |   2 +
L5_Application/source/bt.cpp                       |  47 ---
L5_Application/tasks.hpp                           |   2 +-
9 files changed, 480 insertions(+), 69 deletions(-)
create mode 100644 L5_Application/assetManagement/assetManagement.hpp
create mode 100644 L5_Application/assetManagement/bt.hpp
create mode 100644 L5_Application/assetManagement/src/assetManagement.cpp
create mode 100644 L5_Application/assetManagement/src/bt.cpp
delete mode 100644 L5_Application/bt.hpp
delete mode 100644 L5_Application/source/bt.cpp

diff --git a/L5_Application/assetManagement/assetManagement.hpp b/L5_Application/assetManagement/assetManagement.hpp new file mode 100644 index 0000000..1a42d55 --- /dev/null +++ b/L5_Application/assetManagement/assetManagement.hpp @@ -0,0 +1,89 @@ +/* + * assetManagement.hpp + * + * Created on: Apr 23, 2014 + */ + +#ifndef ASSETMANAGEMENT_HPP_ +#define ASSETMANAGEMENT_HPP_ + +#include "singleton_template.hpp" + +class LCD : public SingletonTemplate<LCD> +{ + public: + void display(const char *data[], uint8_t dataLen, uint8_t dataSelectedIdx); + void display(const char *data); + void newLine(); + void goToStart(); + void clearScreen(); + + private: + LCD(); + /* LCD column size is 16. 1 character is required for + * "select" cursor + * LCD row size is 2 + */ + const uint8_t lcdColumnSize; + const uint8_t selectionMarkerLen; + const uint8_t maxOptionLength; + const uint8_t pageSize; + + void printToLCD(const char *data); + friend class SingletonTemplate<LCD>; ///< Friend class used for Singleton Template +}; + +class switchTask : public scheduler_task +{ + public: + switchTask(uint8_t priority); + bool run(void *p); + typedef enum { + SWITCH_ID_BACK = 1, + SWITCH_ID_DOWN, + SWITCH_ID_UP, + SWITCH_ID_SELECT, + } switchID_t; + static const char *getSwitchName(switchID_t sw); +}; + +class assetManagementTask : public scheduler_task +{ + public: + assetManagementTask(uint8_t priority); + bool run(void *p); + private: +#define enum2Str(id) (#id) +#define DEBUG 1 + + void checkSwitches(); + void handleSwitchPress(switchTask::switchID_t sID); + + typedef enum { + USER_MENU_ACTION_SCROLL_DOWN, + USER_MENU_ACTION_SCROLL_UP, + USER_MENU_ACTION_SELECT, + USER_MENU_ACTION_BACK, + USER_MENU_ACTION_DISPLAY, + } userMenuAction_t; + const char *getMenuActionName(userMenuAction_t action); + void userMenuUpdate(userMenuAction_t action); + + typedef enum { + USER_MENU_TYPE_MAIN, + USER_MENU_TYPE_TRACK_TILE, + USER_MENU_TYPE_ADD_TILE, + USER_MENU_TYPE_REMOVE_TILE, + USER_MENU_TYPE_LIST_TILE, + } userMenuType_t; + const char *getMenuTypeName(userMenuType_t type); + void userMenuHandleAction(userMenuAction_t action, + const char *data[], + uint8_t dataSize, + userMenuType_t currentMenu, + userMenuType_t *nextMenuPtr, + uint8_t *optionSelectedPtr); +}; + + +#endif /* ASSETMANAGEMENT_HPP_ */ diff --git a/L5_Application/assetManagement/bt.hpp b/L5_Application/assetManagement/bt.hpp new file mode 100644 index 0000000..3f37bba --- /dev/null +++ b/L5_Application/assetManagement/bt.hpp @@ -0,0 +1,19 @@ +/* + * bt.hpp + * + * Created on: Apr 16, 2014 + */ + +#ifndef BT_HPP_ +#define BT_HPP_ + +#include "scheduler_task.hpp" + +class BTRxTask : public scheduler_task +{ + public: + BTRxTask(uint8_t priority); + bool run(void *p); +}; + +#endif diff --git a/L5_Application/assetManagement/src/assetManagement.cpp b/L5_Application/assetManagement/src/assetManagement.cpp new file mode 100644 index 0000000..9f7adc4 --- /dev/null +++ b/L5_Application/assetManagement/src/assetManagement.cpp @@ -0,0 +1,318 @@ +/* + * assetManagement.cpp + * + * Created on: Apr 23, 2014 + */ + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include "uart2.hpp" +#include "switches.hpp" +#include "scheduler_task.hpp" +#include "shared_handles.h" +#include "utilities.h" +#include "assetManagement.hpp" + +void LCD::printToLCD(const char *data) +{ + Uart2::getInstance().put(data); +} + +void LCD::display(const char *data[], uint8_t dataSize, uint8_t dataSelectedIdx) +{ + char spaceChar = ' '; + char row[lcdColumnSize+1]; + uint8_t spaceChars; + uint8_t printOffset; + uint8_t dataStrLen; + + LCD::getInstance().clearScreen(); + LCD::getInstance().goToStart(); + for (int i = dataSelectedIdx; + (i < dataSelectedIdx + pageSize) && (i < dataSize); + i++) { + dataStrLen = strlen(data[i]); + memset(row, spaceChar, sizeof(row)); + row[lcdColumnSize] = 0; + + if (i == dataSelectedIdx) { + row[0] = row[lcdColumnSize-1] = '*'; + } + /* Do some math to center align the string */ + if (dataStrLen >= maxOptionLength) { + spaceChars = 0; + printOffset = 1; + } else { + spaceChars = maxOptionLength - dataStrLen; + printOffset = (spaceChars / 2) + 1; + } + for (int j = 0; + (j < (maxOptionLength - spaceChars)) && + (j < dataStrLen); + j++) { + row[printOffset + j] = data[i][j]; + } + LCD::getInstance().printToLCD(row); + LCD::getInstance().newLine(); + } +} + +void LCD::display(const char *data) +{ + const char *newData[] = {data}; + display(newData, 1, 0); +} + +void LCD::newLine() +{ + uint8_t cmd[] = {254, /* escape character */ + 192}; /* Row 2, column 1 */ + + Uart2::getInstance().put((char *)cmd); +} + +void LCD::goToStart() +{ + uint8_t cmd[] = {254, /* escape character */ + 128}; /* clear screen */ + + Uart2::getInstance().put((char *)cmd); +} + +void LCD::clearScreen() +{ + uint8_t cmd[] = {254, /* escape character */ + 1}; /* clear screen */ + + Uart2::getInstance().put((char *)cmd); +} + +LCD::LCD() : + lcdColumnSize(16), + selectionMarkerLen(2), + maxOptionLength(lcdColumnSize - selectionMarkerLen), + pageSize(2) +{ + Uart2::getInstance().init(9600, 1, 1000); + delay_ms(10); + clearScreen(); +} + +const char *switchTask::getSwitchName(switchID_t sw) +{ +#define SWITCH_ID_2_STR(id) (#id) + static const char *switch_names[] = { + "INVALID", + SWITCH_ID_2_STR(SWITCH_ID_BACK), + SWITCH_ID_2_STR(SWITCH_ID_DOWN), + SWITCH_ID_2_STR(SWITCH_ID_UP), + SWITCH_ID_2_STR(SWITCH_ID_SELECT) + }; + + if (sw > sizeof(switch_names)/sizeof(switch_names[0])) { + return "ERR"; + } else { + return (switch_names[sw]); + } +} + +switchTask::switchTask(uint8_t priority) : + scheduler_task("switchTask", 5*512, priority) +{ + setRunDuration(10); + QueueHandle_t qh = xQueueCreate(10, sizeof(switchID_t)); + addSharedObject(shared_SwitchQueue, qh); +} + +bool switchTask::run(void *p) +{ + bool enqueueEvent = true; + switchID_t switchPressed; + + if (Switches::getInstance().getSwitch(SWITCH_ID_SELECT)) { + switchPressed = SWITCH_ID_SELECT; + } else if (Switches::getInstance().getSwitch(SWITCH_ID_BACK)) { + switchPressed = SWITCH_ID_BACK; + } else if (Switches::getInstance().getSwitch(SWITCH_ID_UP)) { + switchPressed = SWITCH_ID_UP; + } else if (Switches::getInstance().getSwitch(SWITCH_ID_DOWN)) { + switchPressed = SWITCH_ID_DOWN; + } else { + enqueueEvent = false; + } + if (enqueueEvent) { + QueueHandle_t qh = getSharedObject(shared_SwitchQueue); + xQueueSend(qh, &switchPressed, portMAX_DELAY); + delay_ms(250); + } + return (true); +} + +void assetManagementTask::userMenuHandleAction( + userMenuAction_t action, + const char *data[], + uint8_t dataSize, + userMenuType_t currentMenu, + userMenuType_t *nextMenuPtr, + uint8_t *optionSelectedPtr) +{ + *nextMenuPtr = currentMenu; + switch (action) { + case USER_MENU_ACTION_SCROLL_DOWN: + if (*optionSelectedPtr < (dataSize - 1)) { + (*optionSelectedPtr)++; + } + break; + case USER_MENU_ACTION_SCROLL_UP: + if (*optionSelectedPtr > 0) { + (*optionSelectedPtr)--; + } + break; + case USER_MENU_ACTION_SELECT: + if (currentMenu == USER_MENU_TYPE_MAIN) { + *nextMenuPtr = USER_MENU_TYPE_LIST_TILE; + } + break; + case USER_MENU_ACTION_BACK: + if (currentMenu == USER_MENU_TYPE_LIST_TILE) { + *nextMenuPtr = USER_MENU_TYPE_MAIN; + } + break; + case USER_MENU_ACTION_DISPLAY: + default: + break; + } + LCD::getInstance().display(data, dataSize, *optionSelectedPtr); +} +void assetManagementTask::userMenuUpdate(userMenuAction_t action) +{ + static userMenuType_t currentMenu = USER_MENU_TYPE_MAIN; + static userMenuType_t nextMenu; + static uint8_t optionSelected = 0; +#if (DEBUG) + static uint16_t cnt = 0; +#endif + + do { + currentMenu = nextMenu; + switch (currentMenu) { + case USER_MENU_TYPE_MAIN: + { + const char *mainMenu[] = {"Track", "Add Title", "Remove Tile"}; + userMenuHandleAction(action, + mainMenu, + sizeof(mainMenu)/sizeof(mainMenu[0]), + currentMenu, + &nextMenu, + &optionSelected); + } + break; + + case USER_MENU_TYPE_LIST_TILE: + { + const char *searchingStr[] = {"Searching..."}; + userMenuHandleAction(action, + searchingStr, + 1, + currentMenu, + &nextMenu, + &optionSelected); + } + break; + + default: + { + + } + break; + } +#if (DEBUG) + printf("%s - [%u],[%s]\n", + __FUNCTION__, cnt, getMenuActionName(action)); + printf("%s - [%u],current=[%s],next=[%s]\n", + __FUNCTION__, cnt, getMenuTypeName(currentMenu), getMenuTypeName(nextMenu)); +#endif + } while (currentMenu != nextMenu); +} + +void assetManagementTask::handleSwitchPress(switchTask::switchID_t sID) +{ + userMenuAction_t action; + + printf("SW Pressed=[%s]\n", switchTask::getSwitchName(sID)); + switch (sID) { + case switchTask::SWITCH_ID_SELECT: + action = USER_MENU_ACTION_SELECT; + break; + case switchTask::SWITCH_ID_BACK: + action = USER_MENU_ACTION_BACK; + break; + case switchTask::SWITCH_ID_UP: + action = USER_MENU_ACTION_SCROLL_UP; + break; + case switchTask::SWITCH_ID_DOWN: + action = USER_MENU_ACTION_SCROLL_DOWN; + break; + default: + action = USER_MENU_ACTION_DISPLAY; + break; + } + userMenuUpdate(action); +} + +void assetManagementTask::checkSwitches() +{ + switchTask::switchID_t sw; + + QueueHandle_t qh = getSharedObject(shared_SwitchQueue); + xQueueReceive(qh, &sw, portMAX_DELAY); + handleSwitchPress(sw); +} + +const char *assetManagementTask::getMenuTypeName(userMenuType_t type) +{ + const char *menuTypeNames[] = { + enum2Str(USER_MENU_TYPE_MAIN), + enum2Str(USER_MENU_TYPE_TRACK_TILE), + enum2Str(USER_MENU_TYPE_ADD_TILE), + enum2Str(USER_MENU_TYPE_REMOVE_TILE), + enum2Str(USER_MENU_TYPE_LIST_TILE), + }; + + if (type > sizeof(menuTypeNames)/sizeof(menuTypeNames[0])) { + return ("ERR"); + } else { + return (menuTypeNames[type]); + } +} + +const char *assetManagementTask::getMenuActionName(userMenuAction_t action) +{ + const char *actionNames[] = { + enum2Str(USER_MENU_ACTION_SCROLL_DOWN), + enum2Str(USER_MENU_ACTION_SCROLL_UP), + enum2Str(USER_MENU_ACTION_SELECT), + enum2Str(USER_MENU_ACTION_BACK), + }; + + if (action > sizeof(actionNames)/sizeof(actionNames[0])) { + return ("ERR"); + } else { + return (actionNames[action]); + } +} + +bool assetManagementTask::run(void *p) +{ + checkSwitches(); + return (true); +} + +assetManagementTask::assetManagementTask(uint8_t priority) : + scheduler_task("assetManagementTask", 5*512, priority) +{ + setRunDuration(10); + LCD::getInstance().clearScreen(); + userMenuUpdate(USER_MENU_ACTION_DISPLAY); +} diff --git a/L5_Application/assetManagement/src/bt.cpp b/L5_Application/assetManagement/src/bt.cpp new file mode 100644 index 0000000..0a6f529 --- /dev/null +++ b/L5_Application/assetManagement/src/bt.cpp @@ -0,0 +1,47 @@ +/* + * bt.cpp + * + * Created on: Apr 16, 2014 + */ + +#include <stdio.h> +#include <string.h> +#include "bt.hpp" +#include "command_handler.hpp" +#include "uart3.hpp" + +CMD_HANDLER_FUNC(btHandler) +{ + if (cmdParams.getLen()) { + if (cmdParams.compareTo("$$$")) { + /* + * String to enter command mode must not be null or + * carriage return terminated + */ + Uart3::getInstance().put(cmdParams.c_str()); + } else { + /* All other commands need to be null terminated */ + Uart3::getInstance().putline(cmdParams.c_str()); + } + } + return (true); +} + +BTRxTask::BTRxTask(uint8_t priority) : + scheduler_task("BTRXTask", 4*512, priority) +{ + setRunDuration(100); + Uart3::getInstance().init(115200, 1000, 1000); +} + +bool BTRxTask::run(void *p) +{ + char rx_data[250]; + + memset(rx_data, 0, sizeof(rx_data)); + if (Uart3::getInstance().gets(rx_data, sizeof(rx_data), 100)) { + printf("\nBT RX:\n [%s]\n", rx_data); + } + + return (true); +} diff --git a/L5_Application/bt.hpp b/L5_Application/bt.hpp deleted file mode 100644 index dde08f9..0000000 --- a/L5_Application/bt.hpp +++ /dev/null @@ -1,19 +0,0 @@ -/* - * bt.hpp - * - * Created on: Apr 16, 2014 - */ - -#ifndef BT_HPP_ -#define BT_HPP_ - -#include "scheduler_task.hpp" - -class BTRxTask : public scheduler_task -{ - public: - BTRxTask(uint8_t priority); - bool run(void *p); -}; - -#endif /* BT_HPP_ */ diff --git a/L5_Application/main.cpp b/L5_Application/main.cpp index e805f37..7472c77 100644 --- a/L5_Application/main.cpp +++ b/L5_Application/main.cpp @@ -43,8 +43,6 @@

 */
int main(void)
{

- scheduler_add_task(new BTRxTask(PRIORITY_LOW)); -

    /**
     * A few basic tasks for this bare-bone system :
     *      1.  Terminal task provides gateway to interact with the board through UART terminal.

@@ -119,6 +117,10 @@ int main(void)

        scheduler_add_task(new wifiTask(Uart3::getInstance(), PRIORITY_LOW));
    #endif

+ scheduler_add_task(new BTRxTask(PRIORITY_LOW)); + scheduler_add_task(new switchTask(PRIORITY_LOW)); + scheduler_add_task(new assetManagementTask(PRIORITY_LOW)); +

    scheduler_start(true); ///< This shouldn't return
    return -1;
}

diff --git a/L5_Application/shared_handles.h b/L5_Application/shared_handles.h index 755f514..e0252d8 100644 --- a/L5_Application/shared_handles.h +++ b/L5_Application/shared_handles.h @@ -35,6 +35,8 @@

enum {
    shared_SensorQueue,    ///< Shared handle used by examples (producer and consumer tasks)
    shared_learnSemaphore, ///< Terminal command gives this semaphore to remoteTask (IR sensor task)

+ shared_SwitchQueue, ///< Queue used by Switch and User Menu task + shared_BTQueue, ///< Queue used by BT and AssetManagement task

};


diff --git a/L5_Application/source/bt.cpp b/L5_Application/source/bt.cpp deleted file mode 100644 index 4cbb56a..0000000 --- a/L5_Application/source/bt.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * bt.cpp - * - * Created on: Apr 16, 2014 - */ - -#include <stdio.h> -#include <string.h> -#include "bt.hpp" -#include "command_handler.hpp" -#include "uart3.hpp" - -CMD_HANDLER_FUNC(btHandler) -{ - if (cmdParams.getLen()) { - if (cmdParams.compareTo("$$$")) { - /* - * String to enter command mode must not be null or - * carriage return terminated - */ - Uart3::getInstance().put(cmdParams.c_str()); - } else { - /* All other commands need to be null terminated */ - Uart3::getInstance().putline(cmdParams.c_str()); - } - } - return (true); -} - -BTRxTask::BTRxTask(uint8_t priority) : - scheduler_task("BTRXTask", 4*512, priority) -{ - setRunDuration(500); - Uart3::getInstance().init(115200, 1000, 1000); -} - -bool BTRxTask::run(void *p) -{ - char rx_data[250]; - - memset(rx_data, 0, sizeof(rx_data)); - if (Uart3::getInstance().gets(rx_data, sizeof(rx_data), 100)) { - printf("\nBT RX:\n [%s]\n", rx_data); - } - - return (true); -} diff --git a/L5_Application/tasks.hpp b/L5_Application/tasks.hpp index 2aa82c3..06ec262 100644 --- a/L5_Application/tasks.hpp +++ b/L5_Application/tasks.hpp @@ -29,7 +29,7 @@

#include "wireless.h"
#include "char_dev.hpp"
#include "bt.hpp"

- +#include "assetManagement.hpp"

/**
 * Terminal task is our UART0 terminal that handles our commands into the board.

-- 1.8.5.2.msysgit.0


From 4a4f7fd79dc376b7c189b88bc621d04535ff6a91 Mon Sep 17 00:00:00 2001 From: Pardeep <p_badhan2004@yahoo.com> Date: Wed, 23 Apr 2014 20:42:09 -0700 Subject: [PATCH 03/23] Forgot to commit .cproject file last time around

---

.cproject | 2 ++
1 file changed, 2 insertions(+)

diff --git a/.cproject b/.cproject index 5dd3ba0..e041f64 100644 --- a/.cproject +++ b/.cproject @@ -66,6 +66,7 @@

									<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/L4_IO/fat}""/>
									<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/L4_IO/wireless}""/>
									<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/L5_Application}""/>

+ <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/L5_Application/assetManagement}""/>

								</option>
								<inputType id="ilg.gnuarmeclipse.managedbuild.cross.tool.c.compiler.input.1130823891" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.c.compiler.input"/>
							</tool>

@@ -86,6 +87,7 @@

									<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/L4_IO/fat}""/>
									<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/L4_IO/wireless}""/>
									<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/L5_Application}""/>

+ <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/L5_Application/assetManagement}""/>

								</option>
								<inputType id="ilg.gnuarmeclipse.managedbuild.cross.tool.cpp.compiler.input.2050870165" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.cpp.compiler.input"/>
							</tool>

-- 1.8.5.2.msysgit.0


From 8057cb6987d3c5deeb041e1244c7f45f2328ad6b Mon Sep 17 00:00:00 2001 From: Pardeep <p_badhan2004@yahoo.com> Date: Thu, 24 Apr 2014 22:00:51 -0700 Subject: [PATCH 04/23] Added Bluetooth interface - Bluetooth class

In addition, the code changes include the following: 1. Added CharDev pointers in LCD and Bluetooth class instead of using the Uart2 and Uart3 directly. This will allow us to switch Uart ports with minimum code changes 2. Changed switch ID variable names so they are independent of the action associated with the switch 3. Modified LCD::display to add an option whether to display the selection marker or not 4. Added "Add Tile" option (not completed yet, "select" action is pending). When "Add Tile" option is selected, the code does Bluetooth inquiry and lists all the devices on the LCD 5. Enchanced logic to get the Bluetooth into command mode. The function Bluetooth::goToCmdMode makes sure the Bluetooth is in command mode before returning. It does this by issuing "V" command and verifying the received data. After issuing the CMD string ($$$), the trick was to wait few milliseconds (I choose 50ms). ---

L5_Application/assetManagement/assetManagement.hpp |  64 ++--
.../assetManagement/src/assetManagement.cpp        | 331 ++++++++++++++++-----
L5_Application/main.cpp                            |   2 +-
L5_Application/shared_handles.h                    |   1 -
L5_Application/tasks.hpp                           |   2 +-
5 files changed, 293 insertions(+), 107 deletions(-)

diff --git a/L5_Application/assetManagement/assetManagement.hpp b/L5_Application/assetManagement/assetManagement.hpp index 1a42d55..4876eb9 100644 --- a/L5_Application/assetManagement/assetManagement.hpp +++ b/L5_Application/assetManagement/assetManagement.hpp @@ -12,7 +12,7 @@

class LCD : public SingletonTemplate<LCD>
{
    public:

- void display(const char *data[], uint8_t dataLen, uint8_t dataSelectedIdx); + void display(const char *data[], uint8_t dataSize, uint8_t dataSelectedIdx, bool displaySelectionMarker = true);

        void display(const char *data);
        void newLine();
        void goToStart();

@@ -24,25 +24,44 @@ class LCD : public SingletonTemplate<LCD>

        * "select" cursor
        * LCD row size is 2
        */

- const uint8_t lcdColumnSize; - const uint8_t selectionMarkerLen; - const uint8_t maxOptionLength; - const uint8_t pageSize; - + const uint8_t lcdColumnSize; + const uint8_t selectionMarkerLen; + const uint8_t maxOptionLength; + const uint8_t pageSize; + CharDev *devicePtr;

       void printToLCD(const char *data);
       friend class SingletonTemplate<LCD>;  ///< Friend class used for Singleton Template
};

+class Bluetooth : public SingletonTemplate<Bluetooth> +{ + public: + void sendCmd(const char *cmd); + bool receiveData(char *buffer, uint32_t bufferSize); + void inquiryWithRSSI(); + void inquiry(); + void clearPreviousBTData(); + + private: + static const uint8_t rxMaxWait = 100; // 100ms + CharDev *BTDevicePtr; + Bluetooth(); + void goToCmdMode(); + bool isInCmdMode(); + void goToDataMode(); + friend class SingletonTemplate<Bluetooth>; +}; +

class switchTask : public scheduler_task
{
    public:
        switchTask(uint8_t priority);
        bool run(void *p);
        typedef enum {

- SWITCH_ID_BACK = 1, - SWITCH_ID_DOWN, - SWITCH_ID_UP, - SWITCH_ID_SELECT, + SWITCH_ID_1 = 1, + SWITCH_ID_2, + SWITCH_ID_3, + SWITCH_ID_4,

        } switchID_t;
        static const char *getSwitchName(switchID_t sw);
};

@@ -52,23 +71,20 @@ class assetManagementTask : public scheduler_task

    public:
        assetManagementTask(uint8_t priority);
        bool run(void *p);

+

    private:
#define enum2Str(id) (#id)

-#define DEBUG 1 - - void checkSwitches(); - void handleSwitchPress(switchTask::switchID_t sID); + static const uint8_t maxTileDevices = 100; + bool BTInquityInProcess;

        typedef enum {
            USER_MENU_ACTION_SCROLL_DOWN,
            USER_MENU_ACTION_SCROLL_UP,
            USER_MENU_ACTION_SELECT,
            USER_MENU_ACTION_BACK,

+ USER_MENU_ACTION_MENU_CHANGED,

            USER_MENU_ACTION_DISPLAY,
        } userMenuAction_t;

- const char *getMenuActionName(userMenuAction_t action); - void userMenuUpdate(userMenuAction_t action); -

        typedef enum {
            USER_MENU_TYPE_MAIN,
            USER_MENU_TYPE_TRACK_TILE,

@@ -76,14 +92,14 @@ class assetManagementTask : public scheduler_task

            USER_MENU_TYPE_REMOVE_TILE,
            USER_MENU_TYPE_LIST_TILE,
        } userMenuType_t;

+ + void checkSwitches(bool waitIndefinitely = false); + void handleSwitchPress(switchTask::switchID_t sID); + const char *getMenuActionName(userMenuAction_t action); + void userMenuUpdate(userMenuAction_t action);

        const char *getMenuTypeName(userMenuType_t type);

- void userMenuHandleAction(userMenuAction_t action, - const char *data[], - uint8_t dataSize, - userMenuType_t currentMenu, - userMenuType_t *nextMenuPtr, - uint8_t *optionSelectedPtr); + assetManagementTask::userMenuType_t mainMenuHandleAction(userMenuAction_t action); + assetManagementTask::userMenuType_t addTileMenuHandleAction(userMenuAction_t action);

};

-

#endif /* ASSETMANAGEMENT_HPP_ */

diff --git a/L5_Application/assetManagement/src/assetManagement.cpp b/L5_Application/assetManagement/src/assetManagement.cpp index 9f7adc4..50d7f1d 100644 --- a/L5_Application/assetManagement/src/assetManagement.cpp +++ b/L5_Application/assetManagement/src/assetManagement.cpp @@ -8,6 +8,7 @@

#include <string.h>
#include <stdio.h>
#include "uart2.hpp"

+#include "uart3.hpp"

#include "switches.hpp"
#include "scheduler_task.hpp"
#include "shared_handles.h"

@@ -16,10 +17,10 @@

void LCD::printToLCD(const char *data)
{

- Uart2::getInstance().put(data); + devicePtr->put(data);

}

-void LCD::display(const char *data[], uint8_t dataSize, uint8_t dataSelectedIdx) +void LCD::display(const char *data[], uint8_t dataSize, uint8_t dataSelectedIdx, bool displaySelectionMarker)

{
    char        spaceChar = ' ';
    char        row[lcdColumnSize+1];

@@ -36,7 +37,7 @@ void LCD::display(const char *data[], uint8_t dataSize, uint8_t dataSelectedIdx)

        memset(row, spaceChar, sizeof(row));
        row[lcdColumnSize] = 0;

- if (i == dataSelectedIdx) { + if (displaySelectionMarker && (i == dataSelectedIdx)) {

            row[0] = row[lcdColumnSize-1] = '*';
        }
        /* Do some math to center align the string */

@@ -61,7 +62,7 @@ void LCD::display(const char *data[], uint8_t dataSize, uint8_t dataSelectedIdx)

void LCD::display(const char *data)
{
    const char *newData[] = {data};

- display(newData, 1, 0); + display(newData, 1, 0, false);

}

void LCD::newLine()

@@ -69,7 +70,7 @@ void LCD::newLine()

    uint8_t cmd[] = {254,  /* escape character */
                     192}; /* Row 2, column 1 */

- Uart2::getInstance().put((char *)cmd); + devicePtr->put((char *)cmd);

}

void LCD::goToStart()

@@ -77,7 +78,7 @@ void LCD::goToStart()

    uint8_t cmd[] = {254, /* escape character */
                     128};  /* clear screen */

- Uart2::getInstance().put((char *)cmd); + devicePtr->put((char *)cmd);

}

void LCD::clearScreen()

@@ -85,7 +86,7 @@ void LCD::clearScreen()

    uint8_t cmd[] = {254, /* escape character */
                     1};  /* clear screen */

- Uart2::getInstance().put((char *)cmd); + devicePtr->put((char *)cmd);

}

LCD::LCD() :

@@ -95,10 +96,83 @@ LCD::LCD() :

    pageSize(2)
{
    Uart2::getInstance().init(9600, 1, 1000);

+ devicePtr = &Uart2::getInstance();

    delay_ms(10);
    clearScreen();
}

+void Bluetooth::clearPreviousBTData() +{ +} + +void Bluetooth::inquiry() +{ + goToCmdMode(); + BTDevicePtr->putline("i"); +} +void Bluetooth::inquiryWithRSSI() +{ + goToCmdMode(); + BTDevicePtr->putline("IQ"); +} + +bool Bluetooth::receiveData(char *buffer, uint32_t bufferSize) +{ + return (BTDevicePtr->gets(buffer, bufferSize, rxMaxWait)); +} + +void Bluetooth::sendCmd(const char *cmd) +{ + goToCmdMode(); + BTDevicePtr->putline(cmd); +} + +void Bluetooth::goToCmdMode() +{ + char BTRxData[1000]; + const uint8_t maxRxDelay = 250; + const uint8_t afterCmdDelay = 50; + bool success = false; + const char *cmdStr = "$$$"; + const char *versionCmd = "V"; + const char *expectedStr = "Roving Networks"; + bool debug = true; + + if (debug) { + printf("%s - Enter\n", __FUNCTION__); + } + BTDevicePtr->putline(versionCmd); + while (!success) { + if (BTDevicePtr->gets(BTRxData, sizeof(BTRxData), maxRxDelay)) { + if (debug) { + printf("%s - BTRxData=[%s]\n", __FUNCTION__, BTRxData); + } + if (strstr(BTRxData, expectedStr)) { + success = true; + } + } else { + /* No response, try going to command mode */ + BTDevicePtr->put(cmdStr); + delay_ms(afterCmdDelay); + BTDevicePtr->putline(versionCmd); + } + } + if (debug) { + printf("%s - Exit\n", __FUNCTION__); + } +} + +void Bluetooth::goToDataMode() +{ + BTDevicePtr->put("---"); +} + +Bluetooth::Bluetooth() +{ + Uart3::getInstance().init(115200, 1000, 1000); + BTDevicePtr = &Uart3::getInstance(); +} +

const char *switchTask::getSwitchName(switchID_t sw)
{
#define SWITCH_ID_2_STR(id) (#id)

@@ -130,14 +204,14 @@ bool switchTask::run(void *p)

    bool        enqueueEvent = true;
    switchID_t  switchPressed;

- if (Switches::getInstance().getSwitch(SWITCH_ID_SELECT)) { - switchPressed = SWITCH_ID_SELECT; - } else if (Switches::getInstance().getSwitch(SWITCH_ID_BACK)) { - switchPressed = SWITCH_ID_BACK; - } else if (Switches::getInstance().getSwitch(SWITCH_ID_UP)) { - switchPressed = SWITCH_ID_UP; - } else if (Switches::getInstance().getSwitch(SWITCH_ID_DOWN)) { - switchPressed = SWITCH_ID_DOWN; + if (Switches::getInstance().getSwitch(SWITCH_ID_1)) { + switchPressed = SWITCH_ID_1; + } else if (Switches::getInstance().getSwitch(SWITCH_ID_2)) { + switchPressed = SWITCH_ID_2; + } else if (Switches::getInstance().getSwitch(SWITCH_ID_3)) { + switchPressed = SWITCH_ID_3; + } else if (Switches::getInstance().getSwitch(SWITCH_ID_4)) { + switchPressed = SWITCH_ID_4;

    } else {
        enqueueEvent = false;
    }

@@ -149,90 +223,177 @@ bool switchTask::run(void *p)

    return (true);
}

-void assetManagementTask::userMenuHandleAction( - userMenuAction_t action, - const char *data[], - uint8_t dataSize, - userMenuType_t currentMenu, - userMenuType_t *nextMenuPtr, - uint8_t *optionSelectedPtr) +assetManagementTask::userMenuType_t assetManagementTask::addTileMenuHandleAction( + userMenuAction_t action)

{

- *nextMenuPtr = currentMenu; + static uint8_t selectedOpt = 0; + const char *searchingStr = "Searching..."; + static char *tileDevicesDetectedStr[maxTileDevices]; + const uint8_t macAddrLen = 12; + static uint8_t tileDevicesDetected = 0; + userMenuType_t newMenu = USER_MENU_TYPE_ADD_TILE; + char BTRxData[1000]; + char *savePtr; + static bool debug = true; + enum { + BT_INQ_BEGIN, + BT_INQ_PENDING_TITLE, + BT_INQ_PENDING_FOUND, + BT_INQ_PENDING_DEVICES, + BT_INQ_DONE, + }; + static uint8_t BTInquiryState = BT_INQ_DONE; + static const char *BTINQNames[] = { + enum2Str(BT_INQ_BEGIN), + enum2Str(BT_INQ_PENDING_TITLE), + enum2Str(BT_INQ_PENDING_FOUND), + enum2Str(BT_INQ_PENDING_DEVICES), + enum2Str(BT_INQ_DONE), + }; + if (debug) { + printf("%s - action=[%s],IQState=[%s]\n", + __FUNCTION__, getMenuActionName(action), BTINQNames[BTInquiryState]); + } +

    switch (action) {
        case USER_MENU_ACTION_SCROLL_DOWN:

- if (*optionSelectedPtr < (dataSize - 1)) { - (*optionSelectedPtr)++; + if (selectedOpt < (tileDevicesDetected - 1)) { + selectedOpt++;

            }
            break;
        case USER_MENU_ACTION_SCROLL_UP:

- if (*optionSelectedPtr > 0) { - (*optionSelectedPtr)--; + if (selectedOpt > 0) { + selectedOpt--;

            }
            break;
        case USER_MENU_ACTION_SELECT:

- if (currentMenu == USER_MENU_TYPE_MAIN) { - *nextMenuPtr = USER_MENU_TYPE_LIST_TILE; - } + // TODO

            break;
        case USER_MENU_ACTION_BACK:

- if (currentMenu == USER_MENU_TYPE_LIST_TILE) { - *nextMenuPtr = USER_MENU_TYPE_MAIN; + newMenu = USER_MENU_TYPE_MAIN; + break; + case USER_MENU_ACTION_MENU_CHANGED: + for (int i = 0; i < tileDevicesDetected; i++) { + if (tileDevicesDetectedStr[i]) { + free(tileDevicesDetectedStr[i]); + tileDevicesDetectedStr[i] = 0; + } + } + tileDevicesDetected = 0; + BTInquityInProcess = true; + BTInquiryState = BT_INQ_BEGIN; + LCD::getInstance().display(searchingStr); + /* Query Tile devices in vicinity */ + Bluetooth::getInstance().clearPreviousBTData(); + Bluetooth::getInstance().inquiryWithRSSI(); + break; + case USER_MENU_ACTION_DISPLAY: + default: + break; + } + + if (BTInquiryState != BT_INQ_DONE) { + if (Bluetooth::getInstance().receiveData(BTRxData, sizeof(BTRxData))) { + if (debug) { + printf("%s - BTRx=[%s]\n", __FUNCTION__, BTRxData); + } + switch (BTInquiryState) { + case BT_INQ_BEGIN: + if (strstr(BTRxData, "COD")) { + BTInquiryState = BT_INQ_PENDING_FOUND; + } + break; + case BT_INQ_PENDING_FOUND: + if (strstr(BTRxData, "Found")) { + BTInquiryState = BT_INQ_PENDING_DEVICES; + } + break; + case BT_INQ_PENDING_DEVICES: + if (strstr(BTRxData, "Inquiry Done")) { + BTInquiryState = BT_INQ_DONE; + BTInquityInProcess = false; + } else { + char *macAddrPtr = strtok_r(BTRxData, ",", &savePtr); + tileDevicesDetectedStr[tileDevicesDetected] = (char *)malloc(macAddrLen); + strncpy(tileDevicesDetectedStr[tileDevicesDetected], macAddrPtr, macAddrLen); + tileDevicesDetectedStr[tileDevicesDetected][macAddrLen] = 0; + tileDevicesDetected++; + } + break; + } + if (debug) { + printf("%s - New IQState=[%s]\n", __FUNCTION__, BTINQNames[BTInquiryState]); + } + } + } + if (tileDevicesDetected > 0) { + LCD::getInstance().display((const char **)tileDevicesDetectedStr, tileDevicesDetected, selectedOpt); + } + return (newMenu); +} + +assetManagementTask::userMenuType_t assetManagementTask::mainMenuHandleAction( + assetManagementTask::userMenuAction_t action) +{ + static uint8_t selectedOpt = 0; + const char *mainMenu[] = {"Track", "Add Tile", "Remove Tile"}; + uint8_t mainMenuOptCnt = sizeof(mainMenu)/sizeof(mainMenu[0]); + userMenuType_t newMenu = USER_MENU_TYPE_MAIN; + + switch (action) { + case USER_MENU_ACTION_SCROLL_DOWN: + if (selectedOpt < (mainMenuOptCnt - 1)) { + selectedOpt++; + } + break; + case USER_MENU_ACTION_SCROLL_UP: + if (selectedOpt > 0) { + selectedOpt--; + } + break; + case USER_MENU_ACTION_SELECT: + switch (selectedOpt) { + case 0: newMenu = USER_MENU_TYPE_TRACK_TILE; break; + case 1: newMenu = USER_MENU_TYPE_ADD_TILE; break; + case 2: newMenu = USER_MENU_TYPE_REMOVE_TILE; break; + default: newMenu = USER_MENU_TYPE_MAIN; break;

            }
            break;

+ case USER_MENU_ACTION_BACK: + case USER_MENU_ACTION_MENU_CHANGED:

        case USER_MENU_ACTION_DISPLAY:
        default:
            break;
    }

- LCD::getInstance().display(data, dataSize, *optionSelectedPtr); + LCD::getInstance().display(mainMenu, mainMenuOptCnt, selectedOpt); + + return (newMenu);

}

-void assetManagementTask::userMenuUpdate(userMenuAction_t action) + +void assetManagementTask::userMenuUpdate(assetManagementTask::userMenuAction_t action)

{
    static userMenuType_t currentMenu = USER_MENU_TYPE_MAIN;
    static userMenuType_t nextMenu;

- static uint8_t optionSelected = 0; -#if (DEBUG) + static bool debug = false;

    static uint16_t       cnt = 0;

-#endif + + if (debug) { + printf("%s - [%u],[%s]\n", __FUNCTION__, cnt, getMenuActionName(action)); + }

    do {
        currentMenu = nextMenu;
        switch (currentMenu) {

- case USER_MENU_TYPE_MAIN: - { - const char *mainMenu[] = {"Track", "Add Title", "Remove Tile"}; - userMenuHandleAction(action, - mainMenu, - sizeof(mainMenu)/sizeof(mainMenu[0]), - currentMenu, - &nextMenu, - &optionSelected); - } - break; - - case USER_MENU_TYPE_LIST_TILE: - { - const char *searchingStr[] = {"Searching..."}; - userMenuHandleAction(action, - searchingStr, - 1, - currentMenu, - &nextMenu, - &optionSelected); - } - break; - - default: - { - - } - break; + case USER_MENU_TYPE_MAIN: nextMenu = mainMenuHandleAction(action); break; + case USER_MENU_TYPE_ADD_TILE: nextMenu = addTileMenuHandleAction(action); break; + case USER_MENU_TYPE_LIST_TILE: break; + default: break; + } + action = USER_MENU_ACTION_MENU_CHANGED; + if (debug) { + printf("%s - [%u],current=[%s],next=[%s]\n", + __FUNCTION__, cnt, getMenuTypeName(currentMenu), getMenuTypeName(nextMenu));

        }

-#if (DEBUG) - printf("%s - [%u],[%s]\n", - __FUNCTION__, cnt, getMenuActionName(action)); - printf("%s - [%u],current=[%s],next=[%s]\n", - __FUNCTION__, cnt, getMenuTypeName(currentMenu), getMenuTypeName(nextMenu)); -#endif

    } while (currentMenu != nextMenu);
}

@@ -242,16 +403,16 @@ void assetManagementTask::handleSwitchPress(switchTask::switchID_t sID)

    printf("SW Pressed=[%s]\n", switchTask::getSwitchName(sID));
    switch (sID) {

- case switchTask::SWITCH_ID_SELECT: + case switchTask::SWITCH_ID_4:

            action = USER_MENU_ACTION_SELECT;
            break;

- case switchTask::SWITCH_ID_BACK: + case switchTask::SWITCH_ID_1:

            action = USER_MENU_ACTION_BACK;
            break;

- case switchTask::SWITCH_ID_UP: + case switchTask::SWITCH_ID_3:

            action = USER_MENU_ACTION_SCROLL_UP;
            break;

- case switchTask::SWITCH_ID_DOWN: + case switchTask::SWITCH_ID_2:

            action = USER_MENU_ACTION_SCROLL_DOWN;
            break;
        default:

@@ -261,12 +422,16 @@ void assetManagementTask::handleSwitchPress(switchTask::switchID_t sID)

    userMenuUpdate(action);
}

-void assetManagementTask::checkSwitches() +void assetManagementTask::checkSwitches(bool waitIndefinitely)

{
    switchTask::switchID_t  sw;

    QueueHandle_t qh = getSharedObject(shared_SwitchQueue);

- xQueueReceive(qh, &sw, portMAX_DELAY); + if (waitIndefinitely) { + xQueueReceive(qh, &sw, portMAX_DELAY); + } else { + xQueueReceive(qh, &sw, 100); + }

    handleSwitchPress(sw);
}

@@ -294,6 +459,8 @@ const char *assetManagementTask::getMenuActionName(userMenuAction_t action)

            enum2Str(USER_MENU_ACTION_SCROLL_UP),
            enum2Str(USER_MENU_ACTION_SELECT),
            enum2Str(USER_MENU_ACTION_BACK),

+ enum2Str(USER_MENU_ACTION_MENU_CHANGED), + enum2Str(USER_MENU_ACTION_DISPLAY),

    };

    if (action > sizeof(actionNames)/sizeof(actionNames[0])) {

@@ -305,12 +472,16 @@ const char *assetManagementTask::getMenuActionName(userMenuAction_t action)

bool assetManagementTask::run(void *p)
{

- checkSwitches(); + checkSwitches(!BTInquityInProcess); + if (BTInquityInProcess) { + userMenuUpdate(USER_MENU_ACTION_DISPLAY); + }

    return (true);
}

assetManagementTask::assetManagementTask(uint8_t priority) :

- scheduler_task("assetManagementTask", 5*512, priority) + scheduler_task("assetManagementTask", 10*512, priority), + BTInquityInProcess(false)

{
    setRunDuration(10);
    LCD::getInstance().clearScreen();

diff --git a/L5_Application/main.cpp b/L5_Application/main.cpp index 7472c77..b6bdf83 100644 --- a/L5_Application/main.cpp +++ b/L5_Application/main.cpp @@ -117,7 +117,7 @@ int main(void)

        scheduler_add_task(new wifiTask(Uart3::getInstance(), PRIORITY_LOW));
    #endif

- scheduler_add_task(new BTRxTask(PRIORITY_LOW)); +// scheduler_add_task(new BTRxTask(PRIORITY_LOW));

    scheduler_add_task(new switchTask(PRIORITY_LOW));
    scheduler_add_task(new assetManagementTask(PRIORITY_LOW));

diff --git a/L5_Application/shared_handles.h b/L5_Application/shared_handles.h index e0252d8..379038c 100644 --- a/L5_Application/shared_handles.h +++ b/L5_Application/shared_handles.h @@ -36,7 +36,6 @@ enum {

    shared_SensorQueue,    ///< Shared handle used by examples (producer and consumer tasks)
    shared_learnSemaphore, ///< Terminal command gives this semaphore to remoteTask (IR sensor task)
    shared_SwitchQueue,    ///< Queue used by Switch and User Menu task

- shared_BTQueue, ///< Queue used by BT and AssetManagement task

};


diff --git a/L5_Application/tasks.hpp b/L5_Application/tasks.hpp index 06ec262..198dfab 100644 --- a/L5_Application/tasks.hpp +++ b/L5_Application/tasks.hpp @@ -28,8 +28,8 @@

#include "command_handler.hpp"
#include "wireless.h"
#include "char_dev.hpp"

-#include "bt.hpp"

#include "assetManagement.hpp"

+#include "bt.hpp"

/**
 * Terminal task is our UART0 terminal that handles our commands into the board.

-- 1.8.5.2.msysgit.0


From 68c14454744492ea5a1f6b5260886a6884a0e31c Mon Sep 17 00:00:00 2001 From: Pardeep <p_badhan2004@yahoo.com> Date: Thu, 24 Apr 2014 23:30:10 -0700 Subject: [PATCH 05/23] Added code to retrive string from user

Added a function that enables us to retrive string from the user. The top row of the LCD has character which the user can use to form a string. The switches allow the user to go left/right to select a character. The other two switches serve as backspace+cancel and select.

Also, adding a option to not center align the text on LCD. ---

L5_Application/assetManagement/assetManagement.hpp | 15 ++--
.../assetManagement/src/assetManagement.cpp        | 88 +++++++++++++++++++---
2 files changed, 87 insertions(+), 16 deletions(-)

diff --git a/L5_Application/assetManagement/assetManagement.hpp b/L5_Application/assetManagement/assetManagement.hpp index 4876eb9..fc4622d 100644 --- a/L5_Application/assetManagement/assetManagement.hpp +++ b/L5_Application/assetManagement/assetManagement.hpp @@ -12,7 +12,11 @@

class LCD : public SingletonTemplate<LCD>
{
    public:

- void display(const char *data[], uint8_t dataSize, uint8_t dataSelectedIdx, bool displaySelectionMarker = true); + void display(const char *data[], + uint8_t dataSize, + uint8_t dataSelectedIdx, + bool displaySelectionMarker = true, + bool center_align = true);

        void display(const char *data);
        void newLine();
        void goToStart();

@@ -58,10 +62,10 @@ class switchTask : public scheduler_task

        switchTask(uint8_t priority);
        bool run(void *p);
        typedef enum {

- SWITCH_ID_1 = 1, - SWITCH_ID_2, - SWITCH_ID_3, - SWITCH_ID_4, + SWITCH_ID_1 = 1, /* Back */ + SWITCH_ID_2, /* Down */ + SWITCH_ID_3, /* Up */ + SWITCH_ID_4, /* Select */

        } switchID_t;
        static const char *getSwitchName(switchID_t sw);
};

@@ -100,6 +104,7 @@ class assetManagementTask : public scheduler_task

        const char *getMenuTypeName(userMenuType_t type);
        assetManagementTask::userMenuType_t mainMenuHandleAction(userMenuAction_t action);
        assetManagementTask::userMenuType_t addTileMenuHandleAction(userMenuAction_t action);

+ bool getStringFromUser(char *buffer, uint8_t size);

};

#endif /* ASSETMANAGEMENT_HPP_ */

diff --git a/L5_Application/assetManagement/src/assetManagement.cpp b/L5_Application/assetManagement/src/assetManagement.cpp index 50d7f1d..a40cb3a 100644 --- a/L5_Application/assetManagement/src/assetManagement.cpp +++ b/L5_Application/assetManagement/src/assetManagement.cpp @@ -20,13 +20,18 @@ void LCD::printToLCD(const char *data)

    devicePtr->put(data);
}

-void LCD::display(const char *data[], uint8_t dataSize, uint8_t dataSelectedIdx, bool displaySelectionMarker) +void LCD::display(const char *data[], + uint8_t dataSize, + uint8_t dataSelectedIdx, + bool displaySelectionMarker, + bool center_align)

{
    char        spaceChar = ' ';
    char        row[lcdColumnSize+1];
    uint8_t     spaceChars;
    uint8_t     printOffset;
    uint8_t     dataStrLen;

+ uint8_t maxRowLen = (displaySelectionMarker) ? maxOptionLength : maxOptionLength + selectionMarkerLen;

    LCD::getInstance().clearScreen();
    LCD::getInstance().goToStart();

@@ -40,16 +45,16 @@ void LCD::display(const char *data[], uint8_t dataSize, uint8_t dataSelectedIdx,

        if (displaySelectionMarker && (i == dataSelectedIdx)) {
            row[0] = row[lcdColumnSize-1] = '*';
        }

- /* Do some math to center align the string */ - if (dataStrLen >= maxOptionLength) { + if ((dataStrLen >= maxRowLen) || !center_align) {

            spaceChars = 0;

- printOffset = 1; + printOffset = (displaySelectionMarker) ? 1 : 0;

        } else {

- spaceChars = maxOptionLength - dataStrLen; + /* Do some math to center align the string */ + spaceChars = maxRowLen - dataStrLen;

            printOffset = (spaceChars / 2) + 1;
        }
        for (int j = 0;

- (j < (maxOptionLength - spaceChars)) && + (j < (maxRowLen - spaceChars)) &&

             (j < dataStrLen);
             j++) {
            row[printOffset + j] = data[i][j];

@@ -223,6 +228,65 @@ bool switchTask::run(void *p)

    return (true);
}

+bool assetManagementTask::getStringFromUser(char *buffer, uint8_t size) +{ + const char *options = "Done 0123456789ABCDEFGHIJKLMNOPQRST !@#$%^&*()-=_+"; + const uint8_t optionsLen = strlen(options); + const uint8_t optionOffset = sizeof("Done") - 1; + uint8_t optionSelected = 0; + const char *LCDData[2]; + switchTask::switchID_t sw; + QueueHandle_t qh; + const uint8_t maxUserStrLen = 16; + char userStr[maxUserStrLen] = {0}; + uint8_t userStrLen = 0; + bool done = false; + + while (!done) { + char temp[100]; + snprintf(temp, sizeof(temp), ">%s", &options[optionSelected]); + LCDData[0] = temp; + LCDData[1] = userStr; + LCD::getInstance().display(LCDData, 2, 0, false, false); + + qh = getSharedObject(shared_SwitchQueue); + xQueueReceive(qh, &sw, portMAX_DELAY); + switch (sw) { + case switchTask::SWITCH_ID_1: /* Backspace */ + if (userStrLen > 0) { + userStrLen--; + userStr[userStrLen] = 0; + } else { + /* User cancelled */ + return (false); + } + break; + case switchTask::SWITCH_ID_2: /* Left */ + if (optionSelected > 0) { + optionSelected--; + } + break; + case switchTask::SWITCH_ID_3: /* Right */ + if (optionSelected < (optionsLen - 1)) { + optionSelected++; + } + break; + case switchTask::SWITCH_ID_4: /* Select */ + if (optionSelected > optionOffset) { + /* User is not done yet */ + userStr[userStrLen++] = options[optionSelected]; + } else { + /* User is done now */ + done = true; + } + break; + default: + break; + } + } + return (true); +} +

assetManagementTask::userMenuType_t assetManagementTask::addTileMenuHandleAction(
        userMenuAction_t action)
{

@@ -403,17 +467,17 @@ void assetManagementTask::handleSwitchPress(switchTask::switchID_t sID)

    printf("SW Pressed=[%s]\n", switchTask::getSwitchName(sID));
    switch (sID) {

- case switchTask::SWITCH_ID_4: - action = USER_MENU_ACTION_SELECT; - break;

        case switchTask::SWITCH_ID_1:
            action = USER_MENU_ACTION_BACK;
            break;

+ case switchTask::SWITCH_ID_2: + action = USER_MENU_ACTION_SCROLL_DOWN; + break;

        case switchTask::SWITCH_ID_3:
            action = USER_MENU_ACTION_SCROLL_UP;
            break;

- case switchTask::SWITCH_ID_2: - action = USER_MENU_ACTION_SCROLL_DOWN; + case switchTask::SWITCH_ID_4: + action = USER_MENU_ACTION_SELECT;

            break;
        default:
            action = USER_MENU_ACTION_DISPLAY;

@@ -472,6 +536,8 @@ const char *assetManagementTask::getMenuActionName(userMenuAction_t action)

bool assetManagementTask::run(void *p)
{

+// char blah[100]; +// getStringFromUser(blah, 100);

    checkSwitches(!BTInquityInProcess);
    if (BTInquityInProcess) {
        userMenuUpdate(USER_MENU_ACTION_DISPLAY);

-- 1.8.5.2.msysgit.0


From 640ae016bd2e5a609e3976819c749d5a45169282 Mon Sep 17 00:00:00 2001 From: Akash <akash@hairynandgate.com> Date: Fri, 25 Apr 2014 01:21:12 -0700 Subject: [PATCH 06/23] FTDI Emulation Mode

Updated the LCD class to support a FTDI (USB) emulation mode when a LCD display is not available.

To enter emulation mode P2.7 must be pulled high. Otherwise, normal LCD mode will be assumed. ---

L5_Application/assetManagement/assetManagement.hpp |  4 ++
.../assetManagement/src/assetManagement.cpp        | 53 +++++++++++++++++++++-
2 files changed, 55 insertions(+), 2 deletions(-)

diff --git a/L5_Application/assetManagement/assetManagement.hpp b/L5_Application/assetManagement/assetManagement.hpp index 1a42d55..7a1889a 100644 --- a/L5_Application/assetManagement/assetManagement.hpp +++ b/L5_Application/assetManagement/assetManagement.hpp @@ -8,6 +8,7 @@

#define ASSETMANAGEMENT_HPP_

#include "singleton_template.hpp"

+#include "gpio.hpp"

class LCD : public SingletonTemplate<LCD>
{

@@ -29,7 +30,10 @@ class LCD : public SingletonTemplate<LCD>

       const uint8_t maxOptionLength;
       const uint8_t pageSize;

+ GPIO *emulationModeSwitch; +

       void printToLCD(const char *data);

+ bool emulationMode(); // State of FTDI emulation mode switch

       friend class SingletonTemplate<LCD>;  ///< Friend class used for Singleton Template
};

diff --git a/L5_Application/assetManagement/src/assetManagement.cpp b/L5_Application/assetManagement/src/assetManagement.cpp index 9f7adc4..9a87782 100644 --- a/L5_Application/assetManagement/src/assetManagement.cpp +++ b/L5_Application/assetManagement/src/assetManagement.cpp @@ -13,12 +13,18 @@

#include "shared_handles.h"
#include "utilities.h"
#include "assetManagement.hpp"

+#include "gpio.hpp"

void LCD::printToLCD(const char *data)
{
    Uart2::getInstance().put(data);
}

+bool LCD::emulationMode() +{ + return emulationModeSwitch->read(); +} +

void LCD::display(const char *data[], uint8_t dataSize, uint8_t dataSelectedIdx)
{
    char        spaceChar = ' ';

@@ -27,8 +33,17 @@ void LCD::display(const char *data[], uint8_t dataSize, uint8_t dataSelectedIdx)

    uint8_t     printOffset;
    uint8_t     dataStrLen;

- LCD::getInstance().clearScreen(); - LCD::getInstance().goToStart(); + + if (emulationMode()) { + // Simulated LCD Header + LCD::getInstance().printToLCD("----------------"); + LCD::getInstance().newLine(); + } + else { + LCD::getInstance().clearScreen(); + LCD::getInstance().goToStart(); + } +

    for (int i = dataSelectedIdx;
         (i < dataSelectedIdx + pageSize) && (i < dataSize);
         i++) {

@@ -53,9 +68,16 @@ void LCD::display(const char *data[], uint8_t dataSize, uint8_t dataSelectedIdx)

             j++) {
            row[printOffset + j] = data[i][j];
        }

+

        LCD::getInstance().printToLCD(row);
        LCD::getInstance().newLine();
    }

+ + if (emulationMode()) { + // Simulated LCD Footer + LCD::getInstance().printToLCD("----------------"); + LCD::getInstance().newLine(); + }

}

void LCD::display(const char *data)

@@ -69,6 +91,13 @@ void LCD::newLine()

    uint8_t cmd[] = {254,  /* escape character */
                     192}; /* Row 2, column 1 */

+ if (emulationMode()) { + size_t size = sizeof(cmd)/sizeof(uint8_t); + for (size_t index = 0; index < size; ++index) { + cmd[index] = '\n'; + } + } +

    Uart2::getInstance().put((char *)cmd);
}

@@ -77,6 +106,13 @@ void LCD::goToStart()

    uint8_t cmd[] = {254, /* escape character */
                     128};  /* clear screen */

+ if (emulationMode()) { + size_t size = sizeof(cmd)/sizeof(uint8_t); + for (size_t index = 0; index < size; ++index) { + cmd[index] = '\n'; + } + } +

    Uart2::getInstance().put((char *)cmd);
}

@@ -85,6 +121,13 @@ void LCD::clearScreen()

    uint8_t cmd[] = {254, /* escape character */
                     1};  /* clear screen */

+ if (emulationMode()) { + size_t size = sizeof(cmd)/sizeof(uint8_t); + for (size_t index = 0; index < size; ++index) { + cmd[index] = '\n'; + } + } +

    Uart2::getInstance().put((char *)cmd);
}

@@ -95,6 +138,12 @@ LCD::LCD() :

    pageSize(2)
{
    Uart2::getInstance().init(9600, 1, 1000);

+ + // Initialize FTDI Emulation Mode Switch + emulationModeSwitch = new GPIO(P2_7); + emulationModeSwitch->setAsInput(); + emulationModeSwitch->enablePullDown(); // default switch value is off (false) +

    delay_ms(10);
    clearScreen();
}

-- 1.8.5.2.msysgit.0


From 1ce6743267893219a4368bbfd74ec39bf9c5a6f9 Mon Sep 17 00:00:00 2001 From: Akash <akash@hairynandgate.com> Date: Fri, 25 Apr 2014 01:21:12 -0700 Subject: [PATCH 07/23] FTDI Emulation Mode

Updated the LCD class to support a FTDI (USB) emulation mode when a LCD display is not available.

To enter emulation mode P2.7 must be pulled high. Otherwise, normal LCD mode will be assumed. ---

L5_Application/assetManagement/assetManagement.hpp | 14 +++---
.../assetManagement/src/assetManagement.cpp        | 52 +++++++++++++++++++++-
2 files changed, 59 insertions(+), 7 deletions(-)

diff --git a/L5_Application/assetManagement/assetManagement.hpp b/L5_Application/assetManagement/assetManagement.hpp index fc4622d..7c09ff4 100644 --- a/L5_Application/assetManagement/assetManagement.hpp +++ b/L5_Application/assetManagement/assetManagement.hpp @@ -8,6 +8,7 @@

#define ASSETMANAGEMENT_HPP_

#include "singleton_template.hpp"

+#include "gpio.hpp"

class LCD : public SingletonTemplate<LCD>
{

@@ -28,12 +29,15 @@ class LCD : public SingletonTemplate<LCD>

        * "select" cursor
        * LCD row size is 2
        */

- const uint8_t lcdColumnSize; - const uint8_t selectionMarkerLen; - const uint8_t maxOptionLength; - const uint8_t pageSize; - CharDev *devicePtr; + const uint8_t lcdColumnSize; + const uint8_t selectionMarkerLen; + const uint8_t maxOptionLength; + const uint8_t pageSize; + CharDev *devicePtr; + GPIO *emulationModeSwitch; +

       void printToLCD(const char *data);

+ bool emulationMode(); // State of FTDI emulation mode switch

       friend class SingletonTemplate<LCD>;  ///< Friend class used for Singleton Template
};

diff --git a/L5_Application/assetManagement/src/assetManagement.cpp b/L5_Application/assetManagement/src/assetManagement.cpp index a40cb3a..31b610e 100644 --- a/L5_Application/assetManagement/src/assetManagement.cpp +++ b/L5_Application/assetManagement/src/assetManagement.cpp @@ -14,12 +14,18 @@

#include "shared_handles.h"
#include "utilities.h"
#include "assetManagement.hpp"

+#include "gpio.hpp"

void LCD::printToLCD(const char *data)
{
    devicePtr->put(data);
}

+bool LCD::emulationMode() +{ + return emulationModeSwitch->read(); +} +

void LCD::display(const char *data[],
                  uint8_t     dataSize,
                  uint8_t     dataSelectedIdx,

@@ -33,8 +39,17 @@ void LCD::display(const char *data[],

    uint8_t     dataStrLen;
    uint8_t     maxRowLen = (displaySelectionMarker) ? maxOptionLength : maxOptionLength + selectionMarkerLen;

- LCD::getInstance().clearScreen(); - LCD::getInstance().goToStart(); + + if (emulationMode()) { + // Simulated LCD Header + LCD::getInstance().printToLCD("----------------"); + LCD::getInstance().newLine(); + } + else { + LCD::getInstance().clearScreen(); + LCD::getInstance().goToStart(); + } +

    for (int i = dataSelectedIdx;
         (i < dataSelectedIdx + pageSize) && (i < dataSize);
         i++) {

@@ -59,9 +74,16 @@ void LCD::display(const char *data[],

             j++) {
            row[printOffset + j] = data[i][j];
        }

+

        LCD::getInstance().printToLCD(row);
        LCD::getInstance().newLine();
    }

+ + if (emulationMode()) { + // Simulated LCD Footer + LCD::getInstance().printToLCD("----------------"); + LCD::getInstance().newLine(); + }

}

void LCD::display(const char *data)

@@ -74,6 +96,12 @@ void LCD::newLine()

{
    uint8_t cmd[] = {254,  /* escape character */
                     192}; /* Row 2, column 1 */

+ if (emulationMode()) { + size_t size = sizeof(cmd)/sizeof(uint8_t); + for (size_t index = 0; index < size; ++index) { + cmd[index] = '\n'; + } + }

    devicePtr->put((char *)cmd);
}

@@ -83,6 +111,13 @@ void LCD::goToStart()

    uint8_t cmd[] = {254, /* escape character */
                     128};  /* clear screen */

+ if (emulationMode()) { + size_t size = sizeof(cmd)/sizeof(uint8_t); + for (size_t index = 0; index < size; ++index) { + cmd[index] = '\n'; + } + } +

    devicePtr->put((char *)cmd);
}

@@ -91,6 +126,13 @@ void LCD::clearScreen()

    uint8_t cmd[] = {254, /* escape character */
                     1};  /* clear screen */

+ if (emulationMode()) { + size_t size = sizeof(cmd)/sizeof(uint8_t); + for (size_t index = 0; index < size; ++index) { + cmd[index] = '\n'; + } + } +

    devicePtr->put((char *)cmd);
}

@@ -102,6 +144,12 @@ LCD::LCD() :

{
    Uart2::getInstance().init(9600, 1, 1000);
    devicePtr = &Uart2::getInstance();

+ + // Initialize FTDI Emulation Mode Switch + emulationModeSwitch = new GPIO(P2_7); + emulationModeSwitch->setAsInput(); + emulationModeSwitch->enablePullDown(); // default switch value is off (false) +

    delay_ms(10);
    clearScreen();
}

-- 1.8.5.2.msysgit.0


From 64be9dc16c1e51300e97510583a36ea59b982661 Mon Sep 17 00:00:00 2001 From: Akash <akash@hairynandgate.com> Date: Fri, 25 Apr 2014 10:39:44 -0700 Subject: [PATCH 08/23] Change Tile Display Behavior

Previously, after Adding a Tile only the bluetooth MAC address was visible on the screen. Now, the MAC address is concatenated with the RSSI value. The RSSI value starts with a negative (-) sign, so it is easy to distinguish the two values without using a space character.

Also, when a list of tiles would return it wasn't easy to determine if you reached the bottom or the top of the list of tiles. Now, when you reach the top (or bottom) of the tile list a message will be displayed. ---

.../assetManagement/src/assetManagement.cpp        | 33 ++++++++++++++++++----
1 file changed, 28 insertions(+), 5 deletions(-)

diff --git a/L5_Application/assetManagement/src/assetManagement.cpp b/L5_Application/assetManagement/src/assetManagement.cpp index e255ce9..b1c4e85 100644 --- a/L5_Application/assetManagement/src/assetManagement.cpp +++ b/L5_Application/assetManagement/src/assetManagement.cpp @@ -39,7 +39,6 @@ void LCD::display(const char *data[],

    uint8_t     dataStrLen;
    uint8_t     maxRowLen = (displaySelectionMarker) ? maxOptionLength : maxOptionLength + selectionMarkerLen;

-

    if (emulationMode()) {
        // Simulated LCD Header
        LCD::getInstance().printToLCD("----------------");

@@ -348,6 +347,8 @@ assetManagementTask::userMenuType_t assetManagementTask::addTileMenuHandleAction

    char                BTRxData[1000];
    char               *savePtr;
    static bool         debug = true;

+ static bool top_of_list = false; + static bool end_of_list = false;

    enum {
        BT_INQ_BEGIN,
        BT_INQ_PENDING_TITLE,

@@ -373,11 +374,19 @@ assetManagementTask::userMenuType_t assetManagementTask::addTileMenuHandleAction

            if (selectedOpt < (tileDevicesDetected - 1)) {
                selectedOpt++;
            }

+ else if (! top_of_list ) { + end_of_list = true; + } + top_of_list = false;

            break;
        case USER_MENU_ACTION_SCROLL_UP:
            if (selectedOpt > 0) {
                selectedOpt--;
            }

+ else if (! end_of_list ) { + top_of_list = true; + } + end_of_list = false;

            break;
        case USER_MENU_ACTION_SELECT:
            // TODO

@@ -427,9 +436,15 @@ assetManagementTask::userMenuType_t assetManagementTask::addTileMenuHandleAction

                        BTInquityInProcess = false;
                    } else {
                        char *macAddrPtr = strtok_r(BTRxData, ",", &savePtr);

- tileDevicesDetectedStr[tileDevicesDetected] = (char *)malloc(macAddrLen); + char *btName = strtok_r(NULL, ",", &savePtr); + char *btCOD = strtok_r(NULL, ",", &savePtr); + char *btRSSI = strtok_r(NULL, ",", &savePtr); + printf( "THE RSSI VALUE: %s\n", btRSSI ); + tileDevicesDetectedStr[tileDevicesDetected] = (char *)malloc(macAddrLen + strlen(btRSSI));

                        strncpy(tileDevicesDetectedStr[tileDevicesDetected], macAddrPtr, macAddrLen);

- tileDevicesDetectedStr[tileDevicesDetected][macAddrLen] = 0; + strncat(tileDevicesDetectedStr[tileDevicesDetected], btRSSI, strlen(btRSSI)); + printf( "THE STORED TILE DEVICE STRING: %s\n", tileDevicesDetectedStr[tileDevicesDetected]); + tileDevicesDetectedStr[tileDevicesDetected][macAddrLen + strlen(btRSSI)] = 0;

                        tileDevicesDetected++;
                    }
                    break;

@@ -439,8 +454,16 @@ assetManagementTask::userMenuType_t assetManagementTask::addTileMenuHandleAction

            }
        }
    }

- if (tileDevicesDetected > 0) { - LCD::getInstance().display((const char **)tileDevicesDetectedStr, tileDevicesDetected, selectedOpt); + if (end_of_list) { + LCD::getInstance().display("(End of List)"); + //end_of_list = false; + } + else if (top_of_list) { + LCD::getInstance().display("(Top of List)"); + //top_of_list = false; + } + else if (tileDevicesDetected > 0) { + LCD::getInstance().display((const char **)tileDevicesDetectedStr, tileDevicesDetected, selectedOpt, false);

    }
    return (newMenu);
}

-- 1.8.5.2.msysgit.0


From 43894167b3c28d572028bcd314ba4d29eb0c4765 Mon Sep 17 00:00:00 2001 From: Pardeep <p_badhan2004@yahoo.com> Date: Fri, 25 Apr 2014 23:35:03 -0700 Subject: [PATCH 09/23] Finished front end for "Add Tile" menu

The user menu portion of the "Add Tile" menu has been completed. The user can now 1) query the Bluetooth devices, 2) select the device he/she wants to add, 3) select the name of the device or simply use the MAC address. TODO: The corresponding back end operation needs to be completed. We should be able to store the device information (MAC address, Bluetooth name, device name (selected by the user) to the on-board flash.

Changed the switch names back to its original form as suggested by Akash.

Some touch ups to the LCD::display function. ---

L5_Application/assetManagement/assetManagement.hpp |  14 +-
.../assetManagement/src/assetManagement.cpp        | 150 ++++++++++++++-------
2 files changed, 112 insertions(+), 52 deletions(-)

diff --git a/L5_Application/assetManagement/assetManagement.hpp b/L5_Application/assetManagement/assetManagement.hpp index fc4622d..616b381 100644 --- a/L5_Application/assetManagement/assetManagement.hpp +++ b/L5_Application/assetManagement/assetManagement.hpp @@ -16,7 +16,8 @@ class LCD : public SingletonTemplate<LCD>

                     uint8_t     dataSize,
                     uint8_t     dataSelectedIdx,
                     bool        displaySelectionMarker = true,

- bool center_align = true); + bool center_align = true, + uint32_t maxDelayAfterDisplay = 0);

        void display(const char *data);
        void newLine();
        void goToStart();

@@ -62,10 +63,10 @@ class switchTask : public scheduler_task

        switchTask(uint8_t priority);
        bool run(void *p);
        typedef enum {

- SWITCH_ID_1 = 1, /* Back */ - SWITCH_ID_2, /* Down */ - SWITCH_ID_3, /* Up */ - SWITCH_ID_4, /* Select */ + SWITCH_ID_BACK = 1, + SWITCH_ID_DOWN, + SWITCH_ID_UP, + SWITCH_ID_SELECT,

        } switchID_t;
        static const char *getSwitchName(switchID_t sw);
};

@@ -79,7 +80,7 @@ class assetManagementTask : public scheduler_task

    private:
#define enum2Str(id) (#id)
        static const uint8_t maxTileDevices = 100;

- bool BTInquityInProcess; + bool BTInquiryInProcess;

        typedef enum {
            USER_MENU_ACTION_SCROLL_DOWN,

@@ -97,6 +98,7 @@ class assetManagementTask : public scheduler_task

            USER_MENU_TYPE_LIST_TILE,
        } userMenuType_t;

+ switchTask::switchID_t getSwitchPressed(uint32_t maxWait);

        void checkSwitches(bool waitIndefinitely = false);
        void handleSwitchPress(switchTask::switchID_t sID);
        const char *getMenuActionName(userMenuAction_t action);

diff --git a/L5_Application/assetManagement/src/assetManagement.cpp b/L5_Application/assetManagement/src/assetManagement.cpp index a40cb3a..41ac150 100644 --- a/L5_Application/assetManagement/src/assetManagement.cpp +++ b/L5_Application/assetManagement/src/assetManagement.cpp @@ -24,7 +24,8 @@ void LCD::display(const char *data[],

                  uint8_t     dataSize,
                  uint8_t     dataSelectedIdx,
                  bool        displaySelectionMarker,

- bool center_align) + bool center_align, + uint32_t maxDelayAfterDisplay)

{
    char        spaceChar = ' ';
    char        row[lcdColumnSize+1];

@@ -51,7 +52,10 @@ void LCD::display(const char *data[],

        } else {
            /* Do some math to center align the string */
            spaceChars = maxRowLen - dataStrLen;

- printOffset = (spaceChars / 2) + 1; + printOffset = (spaceChars / 2); + if (displaySelectionMarker) { + printOffset += 1; + }

        }
        for (int j = 0;
             (j < (maxRowLen - spaceChars)) &&

@@ -62,6 +66,9 @@ void LCD::display(const char *data[],

        LCD::getInstance().printToLCD(row);
        LCD::getInstance().newLine();
    }

+ if (0 != maxDelayAfterDisplay) { + delay_ms(maxDelayAfterDisplay); + }

}

void LCD::display(const char *data)

@@ -141,13 +148,15 @@ void Bluetooth::goToCmdMode()

    const char     *cmdStr = "$$$";
    const char     *versionCmd = "V";
    const char     *expectedStr = "Roving Networks";

+ const uint8_t maxAttempts = 10; + uint8_t attempts = 0;

    bool            debug = true;

    if (debug) {
        printf("%s - Enter\n", __FUNCTION__);
    }
    BTDevicePtr->putline(versionCmd);

- while (!success) { + while (!success && (attempts++ < maxAttempts)) {

        if (BTDevicePtr->gets(BTRxData, sizeof(BTRxData), maxRxDelay)) {
            if (debug) {
                printf("%s - BTRxData=[%s]\n", __FUNCTION__, BTRxData);

@@ -200,59 +209,59 @@ switchTask::switchTask(uint8_t priority) :

        scheduler_task("switchTask", 5*512, priority)
{
    setRunDuration(10);

- QueueHandle_t qh = xQueueCreate(10, sizeof(switchID_t)); + QueueHandle_t qh = xQueueCreate(1, sizeof(switchID_t));

    addSharedObject(shared_SwitchQueue, qh);
}

bool switchTask::run(void *p)
{

- bool enqueueEvent = true; - switchID_t switchPressed; - - if (Switches::getInstance().getSwitch(SWITCH_ID_1)) { - switchPressed = SWITCH_ID_1; - } else if (Switches::getInstance().getSwitch(SWITCH_ID_2)) { - switchPressed = SWITCH_ID_2; - } else if (Switches::getInstance().getSwitch(SWITCH_ID_3)) { - switchPressed = SWITCH_ID_3; - } else if (Switches::getInstance().getSwitch(SWITCH_ID_4)) { - switchPressed = SWITCH_ID_4; + bool enqueueEvent = true; + switchID_t switchPressed; + const uint32_t waitTimeAfterSwitchPress = 300; + + if (Switches::getInstance().getSwitch(SWITCH_ID_BACK)) { + switchPressed = SWITCH_ID_BACK; + } else if (Switches::getInstance().getSwitch(SWITCH_ID_DOWN)) { + switchPressed = SWITCH_ID_DOWN; + } else if (Switches::getInstance().getSwitch(SWITCH_ID_UP)) { + switchPressed = SWITCH_ID_UP; + } else if (Switches::getInstance().getSwitch(SWITCH_ID_SELECT)) { + switchPressed = SWITCH_ID_SELECT;

    } else {
        enqueueEvent = false;
    }
    if (enqueueEvent) {
        QueueHandle_t qh = getSharedObject(shared_SwitchQueue);
        xQueueSend(qh, &switchPressed, portMAX_DELAY);

- delay_ms(250); + delay_ms(waitTimeAfterSwitchPress);

    }
    return (true);
}

-bool assetManagementTask::getStringFromUser(char *buffer, uint8_t size) +bool assetManagementTask::getStringFromUser(char *buffer, uint8_t bufferSize)

{
    const char             *options        = "Done 0123456789ABCDEFGHIJKLMNOPQRST !@#$%^&*()-=_+";
    const uint8_t           optionsLen     = strlen(options);
    const uint8_t           optionOffset   = sizeof("Done") - 1;
    uint8_t                 optionSelected = 0;
    const char             *LCDData[2];

- switchTask::switchID_t sw; - QueueHandle_t qh;

    const uint8_t           maxUserStrLen          = 16;
    char                    userStr[maxUserStrLen] = {0};
    uint8_t                 userStrLen             = 0;
    bool                    done                   = false;

    while (!done) {

- char temp[100]; + switchTask::switchID_t sw; + char temp[100]; +

        snprintf(temp, sizeof(temp), ">%s", &options[optionSelected]);
        LCDData[0] = temp;
        LCDData[1] = userStr;
        LCD::getInstance().display(LCDData, 2, 0, false, false);

- qh = getSharedObject(shared_SwitchQueue); - xQueueReceive(qh, &sw, portMAX_DELAY); + sw = getSwitchPressed(portMAX_DELAY);

        switch (sw) {

- case switchTask::SWITCH_ID_1: /* Backspace */ + case switchTask::SWITCH_ID_BACK: /* Backspace */

                if (userStrLen > 0) {
                    userStrLen--;
                    userStr[userStrLen] = 0;

@@ -261,17 +270,17 @@ bool assetManagementTask::getStringFromUser(char *buffer, uint8_t size)

                    return (false);
                }
                break;

- case switchTask::SWITCH_ID_2: /* Left */ + case switchTask::SWITCH_ID_DOWN: /* Left */

                if (optionSelected > 0) {
                    optionSelected--;
                }
                break;

- case switchTask::SWITCH_ID_3: /* Right */ + case switchTask::SWITCH_ID_UP: /* Right */

                if (optionSelected < (optionsLen - 1)) {
                    optionSelected++;
                }
                break;

- case switchTask::SWITCH_ID_4: /* Select */ + case switchTask::SWITCH_ID_SELECT:

                if (optionSelected > optionOffset) {
                    /* User is not done yet */
                    userStr[userStrLen++] = options[optionSelected];

@@ -284,20 +293,18 @@ bool assetManagementTask::getStringFromUser(char *buffer, uint8_t size)

                break;
        }
    }

- return (true); + strncpy(buffer, userStr, bufferSize); + return (userStrLen > 0);

}

assetManagementTask::userMenuType_t assetManagementTask::addTileMenuHandleAction(
        userMenuAction_t action)
{
    static uint8_t      selectedOpt = 0;

- const char *searchingStr = "Searching...";

    static char        *tileDevicesDetectedStr[maxTileDevices];
    const uint8_t       macAddrLen = 12;
    static uint8_t      tileDevicesDetected = 0;
    userMenuType_t      newMenu = USER_MENU_TYPE_ADD_TILE;

- char BTRxData[1000]; - char *savePtr;

    static bool         debug = true;
    enum {
        BT_INQ_BEGIN,

@@ -321,22 +328,64 @@ assetManagementTask::userMenuType_t assetManagementTask::addTileMenuHandleAction

    switch (action) {
        case USER_MENU_ACTION_SCROLL_DOWN:

+ {

            if (selectedOpt < (tileDevicesDetected - 1)) {
                selectedOpt++;
            }
            break;

+ }

        case USER_MENU_ACTION_SCROLL_UP:

+ {

            if (selectedOpt > 0) {
                selectedOpt--;
            }
            break;

+ }

        case USER_MENU_ACTION_SELECT:

- // TODO + { + if (tileDevicesDetected == 0) { + break; + } + const char *helpStr[] = {"Pick name. Press", "Back to use MAC"}; + const char *confirmStr[2]; + const char *deviceAddedStr[2]; + const uint8_t deviceNameMaxStrLen = 16; + char deviceName[deviceNameMaxStrLen]; + bool deviceNameConfirmed = false; + switchTask::switchID_t sw; + uint32_t helpStrDisplayTime = 4000; /* 4 seconds */ + + LCD::getInstance().display(helpStr, 2, 0, false, false, helpStrDisplayTime); + do { + if (getStringFromUser(deviceName, sizeof(deviceName))) { + } else { + strncpy(deviceName, tileDevicesDetectedStr[selectedOpt], macAddrLen); + } + confirmStr[0] = "Confirm Name:"; + confirmStr[1] = deviceName; + LCD::getInstance().display(confirmStr, 2, 0, false, false); + sw = getSwitchPressed(portMAX_DELAY); + if (switchTask::SWITCH_ID_SELECT == sw) { + deviceNameConfirmed = true; + } + } while (!deviceNameConfirmed); + deviceAddedStr[0] = "Device added:"; + deviceAddedStr[1] = deviceName; + LCD::getInstance().display(deviceAddedStr, 2, 0, false, false, helpStrDisplayTime); + if (debug) { + printf("%s - %s [%s]\n", __FUNCTION__, deviceAddedStr[0], deviceAddedStr[1]); + } + newMenu = USER_MENU_TYPE_MAIN;

            break;

+ }

        case USER_MENU_ACTION_BACK:
            newMenu = USER_MENU_TYPE_MAIN;

+ BTInquiryInProcess = false;

            break;
        case USER_MENU_ACTION_MENU_CHANGED:

+ { + const char *searchingStr = "Searching..."; +

            for (int i = 0; i < tileDevicesDetected; i++) {
                if (tileDevicesDetectedStr[i]) {
                    free(tileDevicesDetectedStr[i]);

@@ -344,19 +393,23 @@ assetManagementTask::userMenuType_t assetManagementTask::addTileMenuHandleAction

                }
            }
            tileDevicesDetected = 0;

- BTInquityInProcess = true; + BTInquiryInProcess = true;

            BTInquiryState = BT_INQ_BEGIN;
            LCD::getInstance().display(searchingStr);
            /* Query Tile devices in vicinity */
            Bluetooth::getInstance().clearPreviousBTData();
            Bluetooth::getInstance().inquiryWithRSSI();
            break;

+ }

        case USER_MENU_ACTION_DISPLAY:
        default:
            break;
    }

    if (BTInquiryState != BT_INQ_DONE) {

+ char BTRxData[1000]; + char *savePtr; +

        if (Bluetooth::getInstance().receiveData(BTRxData, sizeof(BTRxData))) {
            if (debug) {
                printf("%s - BTRx=[%s]\n", __FUNCTION__, BTRxData);

@@ -375,7 +428,7 @@ assetManagementTask::userMenuType_t assetManagementTask::addTileMenuHandleAction

                case BT_INQ_PENDING_DEVICES:
                    if (strstr(BTRxData, "Inquiry Done")) {
                        BTInquiryState = BT_INQ_DONE;

- BTInquityInProcess = false; + BTInquiryInProcess = false;

                    } else {
                        char *macAddrPtr = strtok_r(BTRxData, ",", &savePtr);
                        tileDevicesDetectedStr[tileDevicesDetected] = (char *)malloc(macAddrLen);

@@ -467,16 +520,16 @@ void assetManagementTask::handleSwitchPress(switchTask::switchID_t sID)

    printf("SW Pressed=[%s]\n", switchTask::getSwitchName(sID));
    switch (sID) {

- case switchTask::SWITCH_ID_1: + case switchTask::SWITCH_ID_BACK:

            action = USER_MENU_ACTION_BACK;
            break;

- case switchTask::SWITCH_ID_2: + case switchTask::SWITCH_ID_DOWN:

            action = USER_MENU_ACTION_SCROLL_DOWN;
            break;

- case switchTask::SWITCH_ID_3: + case switchTask::SWITCH_ID_UP:

            action = USER_MENU_ACTION_SCROLL_UP;
            break;

- case switchTask::SWITCH_ID_4: + case switchTask::SWITCH_ID_SELECT:

            action = USER_MENU_ACTION_SELECT;
            break;
        default:

@@ -486,16 +539,21 @@ void assetManagementTask::handleSwitchPress(switchTask::switchID_t sID)

    userMenuUpdate(action);
}

-void assetManagementTask::checkSwitches(bool waitIndefinitely) +switchTask::switchID_t assetManagementTask::getSwitchPressed(uint32_t maxWait)

{
    switchTask::switchID_t  sw;

    QueueHandle_t qh = getSharedObject(shared_SwitchQueue);

- if (waitIndefinitely) { - xQueueReceive(qh, &sw, portMAX_DELAY); - } else { - xQueueReceive(qh, &sw, 100); - } + xQueueReceive(qh, &sw, maxWait); + return(sw); +} + +void assetManagementTask::checkSwitches(bool waitIndefinitely) +{ + const uint32_t maxWaitTime = 100; + switchTask::switchID_t sw; + + sw = getSwitchPressed(waitIndefinitely ? portMAX_DELAY : maxWaitTime);

    handleSwitchPress(sw);
}

@@ -538,8 +596,8 @@ bool assetManagementTask::run(void *p)

{
//    char blah[100];
//    getStringFromUser(blah, 100);

- checkSwitches(!BTInquityInProcess); - if (BTInquityInProcess) { + checkSwitches(!BTInquiryInProcess); + if (BTInquiryInProcess) {

        userMenuUpdate(USER_MENU_ACTION_DISPLAY);
    }
    return (true);

@@ -547,7 +605,7 @@ bool assetManagementTask::run(void *p)

assetManagementTask::assetManagementTask(uint8_t priority) :
        scheduler_task("assetManagementTask", 10*512, priority),

- BTInquityInProcess(false) + BTInquiryInProcess(false)

{
    setRunDuration(10);
    LCD::getInstance().clearScreen();

-- 1.8.5.2.msysgit.0


From a3eac536fc93d3502fdd1819c61fb299cd523e12 Mon Sep 17 00:00:00 2001 From: Akash <akash@hairynandgate.com> Date: Thu, 1 May 2014 02:30:56 -0700 Subject: [PATCH 10/23] Track/Locate Tile & Histogram

This change implements the Track Tile menu and associated actions. Plus, it will display a histogram based on the RSSI value.

There are a lot of TODOs that need to be addressed in this change. The major things that need to be done is refactoring, splitting Track (List, Track, Histogram), and continuously update histogram until back is pushed. ---

L5_Application/assetManagement/assetManagement.hpp |  13 +-
.../assetManagement/src/assetManagement.cpp        | 286 ++++++++++++++++++++-
2 files changed, 292 insertions(+), 7 deletions(-)

diff --git a/L5_Application/assetManagement/assetManagement.hpp b/L5_Application/assetManagement/assetManagement.hpp index 09526e3..20607e8 100644 --- a/L5_Application/assetManagement/assetManagement.hpp +++ b/L5_Application/assetManagement/assetManagement.hpp @@ -11,6 +11,11 @@

#include "gpio.hpp"
#include "stdio.h"

+/* set debug to enable verbose + * messaging to console. + */ +const bool debug = true; +

class LCD : public SingletonTemplate<LCD>
{
    public:

@@ -99,8 +104,8 @@ class assetManagementTask : public scheduler_task

            USER_MENU_TYPE_MAIN,
            USER_MENU_TYPE_TRACK_TILE,
            USER_MENU_TYPE_ADD_TILE,

- USER_MENU_TYPE_REMOVE_TILE, - USER_MENU_TYPE_LIST_TILE, + USER_MENU_TYPE_REMOVE_TILE, // unused + USER_MENU_TYPE_LIST_TILE, // unused

        } userMenuType_t;
        class tileDevice {
            public:

@@ -162,8 +167,12 @@ class assetManagementTask : public scheduler_task

        const char *getMenuTypeName(userMenuType_t type);
        assetManagementTask::userMenuType_t mainMenuHandleAction(userMenuAction_t action);
        assetManagementTask::userMenuType_t addTileMenuHandleAction(userMenuAction_t action);

+ assetManagementTask::userMenuType_t trackTileMenuHandleAction(userMenuAction_t action);

        bool getStringFromUser(char *buffer, uint8_t size);
        void getTileIdentifier(const char *names[], tileDevice *tiles[], uint8_t deviceCount);
};

+ +void getHistogram(char *histogram, const char *rssi); +

#endif /* ASSETMANAGEMENT_HPP_ */

diff --git a/L5_Application/assetManagement/src/assetManagement.cpp b/L5_Application/assetManagement/src/assetManagement.cpp index db0f78d..daa4b4f 100644 --- a/L5_Application/assetManagement/src/assetManagement.cpp +++ b/L5_Application/assetManagement/src/assetManagement.cpp @@ -358,7 +358,6 @@ assetManagementTask::userMenuType_t assetManagementTask::addTileMenuHandleAction

    tileDevice          *tilesDetectedPtr[maxTileDevices];
    static uint8_t       tilesDetectedCount = 0;
    userMenuType_t       newMenu = USER_MENU_TYPE_ADD_TILE;

- static bool debug = true;

    static bool          top_of_list = false;
    static bool          end_of_list = false;
    enum {

@@ -421,8 +420,10 @@ assetManagementTask::userMenuType_t assetManagementTask::addTileMenuHandleAction

            LCD::getInstance().display(helpStr, 2, 0, false, false, helpStrDisplayTime);
            do {
                if (getStringFromUser(deviceName, sizeof(deviceName))) {

- } else { - strncpy(deviceName, + } + else { + strncpy( + deviceName,

                            tilesDetectedPtr[selectedOpt]->getMac(),
                            sizeof(deviceName));
                }

@@ -444,9 +445,11 @@ assetManagementTask::userMenuType_t assetManagementTask::addTileMenuHandleAction

            break;
        }
        case USER_MENU_ACTION_BACK:

+ {

            newMenu = USER_MENU_TYPE_MAIN;
            BTInquiryInProcess = false;
            break;

+ }

        case USER_MENU_ACTION_MENU_CHANGED:
        {
            const char *searchingStr = "Searching...";

@@ -519,6 +522,235 @@ assetManagementTask::userMenuType_t assetManagementTask::addTileMenuHandleAction

    return (newMenu);
}

+assetManagementTask::userMenuType_t assetManagementTask::trackTileMenuHandleAction( + userMenuAction_t action) +{ + userMenuType_t newMenu = USER_MENU_TYPE_TRACK_TILE; + tileDevice *tilesDetectedPtr[maxTileDevices]; + static uint8_t tilesDetectedCount = 0; + + /* Variables that need to be reset + * on function exit. + */ + static uint8_t selectedTile = 0; + static bool top_of_list = false; + static bool end_of_list = false; + static bool display_instructions = true; + + static bool tracking_mode = false; + + /* TODO: Refactor. + * This code block first appears in + * addTileMenuHandleAction + */ + enum { + BT_INQ_BEGIN, + BT_INQ_PENDING_TITLE, + BT_INQ_PENDING_FOUND, + BT_INQ_PENDING_DEVICES, + BT_INQ_DONE, + }; + static uint8_t BTInquiryState = BT_INQ_DONE; + static const char *BTINQNames[] = { + enum2Str(BT_INQ_BEGIN), + enum2Str(BT_INQ_PENDING_TITLE), + enum2Str(BT_INQ_PENDING_FOUND), + enum2Str(BT_INQ_PENDING_DEVICES), + enum2Str(BT_INQ_DONE), + }; + + /* TODO: Use real data to get list + * of registered tiles. + */ + char *registeredTiles[] = { "889FFAF03BB3", "ubuntu-0" }; + int numberOfTiles = sizeof(registeredTiles) / sizeof(char *); + + if (debug) { + printf( "%s - Number of registered tiles: %i\n", __FUNCTION__, numberOfTiles); + } + + // fail fast + if (0 == numberOfTiles) { + LCD::getInstance().display( "ERR: No tiles" ); + delay_ms(2000); // sleep for two seconds + + // return USER_MENU_TYPE_MAIN; + /* Use action instead of return to ensure + * that we always exit this function in + * a consistent manner. The BACK case + * will reset variables. + */ + action = USER_MENU_ACTION_BACK; + } + else if (display_instructions) { + display_instructions = false; + LCD::getInstance().display( "Select a Tile" ); + delay_ms(2000); // sleep for two seconds + } + + switch (action) { + case USER_MENU_ACTION_SCROLL_DOWN: + { + if (selectedTile < (numberOfTiles - 1)) { + selectedTile++; + } + else if ( !top_of_list ) { + end_of_list = true; + } + + if (top_of_list) { + selectedTile = 0; + } + + top_of_list = false; + break; + } + case USER_MENU_ACTION_SCROLL_UP: + { + if (selectedTile > 0) { + selectedTile--; + } + else if ( !end_of_list ) { + top_of_list = true; + } + + if (end_of_list) { + selectedTile = numberOfTiles - 1; + } + + end_of_list = false; + break; + } + case USER_MENU_ACTION_SELECT: + { + LCD::getInstance().display("Tracking..."); + tracking_mode = true; + + for (int i = 0; i < tilesDetectedCount; i++) { + delete tilesDetectedPtr[i]; + tilesDetectedPtr[i] = 0; + } + tilesDetectedCount = 0; + + BTInquiryState = BT_INQ_BEGIN; + Bluetooth::getInstance().clearPreviousBTData(); + Bluetooth::getInstance().inquiryWithRSSI(); + + break; + } + case USER_MENU_ACTION_BACK: + { + // reset variables to original state + selectedTile = 0; + top_of_list = false; + end_of_list = false; + display_instructions = true; + tracking_mode = false; + + newMenu = USER_MENU_TYPE_MAIN; + break; + } + default: + { + break; + } + } + + if (tracking_mode) { + while (BTInquiryState != BT_INQ_DONE) { + char BTRxData[1000]; + char *savePtr; + + if (Bluetooth::getInstance().receiveData(BTRxData, sizeof(BTRxData))) { + if (debug) { + printf("%s - BTRx=[%s]\n", __FUNCTION__, BTRxData); + } + switch (BTInquiryState) { + case BT_INQ_BEGIN: + if (strstr(BTRxData, "COD")) { + BTInquiryState = BT_INQ_PENDING_FOUND; + } + break; + case BT_INQ_PENDING_FOUND: + if (strstr(BTRxData, "Found")) { + BTInquiryState = BT_INQ_PENDING_DEVICES; + } + break; + case BT_INQ_PENDING_DEVICES: + if (strstr(BTRxData, "Inquiry Done")) { + BTInquiryState = BT_INQ_DONE; + BTInquiryInProcess = false; + } else { + char *macAddrPtr = strtok_r(BTRxData, ",", &savePtr); + char *btNamePtr = strtok_r(NULL, ",", &savePtr); + char *btCODPtr = strtok_r(NULL, ",", &savePtr); + char *btRSSIPtr = strtok_r(NULL, ",", &savePtr); + tilesDetectedPtr[tilesDetectedCount] = + new tileDevice(macAddrPtr, btRSSIPtr, btNamePtr, btCODPtr); + tilesDetectedCount++; + } + break; + } + if (debug) { + printf("%s - New IQState=[%s]\n", __FUNCTION__, BTINQNames[BTInquiryState]); + } + } + } + + /* TODO: Refactor and use constant + * deviceNameMaxLen + * instead of magic 17. + */ + char selectedTileMAC[17]; + /* TODO: Get selected tile's + * MAC address. + */ + strncpy( selectedTileMAC, registeredTiles[ selectedTile ], sizeof(selectedTileMAC)); + if (debug) { + printf( "%s - Selected Tile MAC: %s\n", __FUNCTION__, selectedTileMAC ); + } + + size_t index; + for (index = 0; index < tilesDetectedCount; index++) { + int match = strcmp( selectedTileMAC, tilesDetectedPtr[index]->getMac()); + + if ( 0 == match ) { + if (debug) { + printf( "%s - Matched MACs\n", __FUNCTION__ ); + printf( "%s - Tile's RSSI Value: %s\n", __FUNCTION__, tilesDetectedPtr[index]->getRSSI() ); + } + + char histogram[17]; + getHistogram( histogram, (const char *)tilesDetectedPtr[index]->getRSSI() ); + if (debug) { + printf( "%s - RSSI Histogram: %s\n", __FUNCTION__, histogram ); + } + + LCD::getInstance().display( histogram ); + //delay_ms(2000); + + break; + } + } + + tracking_mode = false; + return( newMenu ); + } + + + if (end_of_list) { + LCD::getInstance().display("(End of List)"); + } + else if (top_of_list) { + LCD::getInstance().display("(Top of List)"); + } + else if ( 0 != numberOfTiles ) { + LCD::getInstance().display( (const char **)registeredTiles, (uint8_t)numberOfTiles, selectedTile, true ); + } + + return( newMenu ); +} +

assetManagementTask::userMenuType_t assetManagementTask::mainMenuHandleAction(
        assetManagementTask::userMenuAction_t action)
{

@@ -571,8 +803,9 @@ void assetManagementTask::userMenuUpdate(assetManagementTask::userMenuAction_t a

    do {
        currentMenu = nextMenu;
        switch (currentMenu) {

- case USER_MENU_TYPE_MAIN: nextMenu = mainMenuHandleAction(action); break; - case USER_MENU_TYPE_ADD_TILE: nextMenu = addTileMenuHandleAction(action); break; + case USER_MENU_TYPE_MAIN: nextMenu = mainMenuHandleAction(action); break; + case USER_MENU_TYPE_ADD_TILE: nextMenu = addTileMenuHandleAction(action); break; + case USER_MENU_TYPE_TRACK_TILE: nextMenu = trackTileMenuHandleAction(action); break;

            case USER_MENU_TYPE_LIST_TILE: break;
            default:                       break;
        }

@@ -681,3 +914,46 @@ assetManagementTask::assetManagementTask(uint8_t priority) :

    LCD::getInstance().clearScreen();
    userMenuUpdate(USER_MENU_ACTION_DISPLAY);
}

+ +void +getHistogram( char *histogram, const char *rssi ) +{ + int RSSI = atoi( rssi ); + + if (-40 < RSSI) { + strcpy( histogram, "[XXXXXXXXXX] " ); + strcat( histogram, rssi ); + } + else if (-50 < RSSI) { + strcpy( histogram, "[XXXXXXXXX ] " ); + strcat( histogram, rssi ); + } + else if (-60 < RSSI) { + strcpy( histogram, "[XXXXXXXX ] " ); + strcat( histogram, rssi ); + } + else if (-65 < RSSI) { + strcpy( histogram, "[XXXXXXX ] " ); + strcat( histogram, rssi ); + } + else if (-70 < RSSI) { + strcpy( histogram, "[XXXXXX ] " ); + strcat( histogram, rssi ); + } + else if (-75 < RSSI) { + strcpy( histogram, "[XXXXX ] " ); + strcat( histogram, rssi ); + } + else if (-80 < RSSI) { + strcpy( histogram, "[XXX ] " ); + strcat( histogram, rssi ); + } + else if (-90 < RSSI) { + strcpy( histogram, "[X ] " ); + strcat( histogram, rssi ); + } + else { + strcpy( histogram, "[ ] " ); + strcat( histogram, "EOR" ); // EOR => Error Out Of Range + } +} -- 1.8.5.2.msysgit.0


From b88aacdd2a9ec385274eb39e17b5e2c5c460c40e Mon Sep 17 00:00:00 2001 From: Akash <akash@hairynandgate.com> Date: Thu, 1 May 2014 03:42:44 -0700 Subject: [PATCH 11/23] Track/Locate Improvements

This change improves the display and overall user experience by conforming to existing design patterns and API.

This change also includes some minimal refactoring.

Split Track Action into List and Track. Plus, the display will automatically update whenever new data is available when operating in tracking mode. Pushing the back button will exit tracking mode... but the response can be a little slow. ---

L5_Application/assetManagement/assetManagement.hpp |  36 ++-
.../assetManagement/src/assetManagement.cpp        | 348 ++++++++++++---------
L5_Application/main.cpp                            |   2 +-
3 files changed, 231 insertions(+), 155 deletions(-)

diff --git a/L5_Application/assetManagement/assetManagement.hpp b/L5_Application/assetManagement/assetManagement.hpp index 20607e8..06e4d9c 100644 --- a/L5_Application/assetManagement/assetManagement.hpp +++ b/L5_Application/assetManagement/assetManagement.hpp @@ -16,6 +16,8 @@

 */
const bool debug = true;

+ +

class LCD : public SingletonTemplate<LCD>
{
    public:

@@ -48,6 +50,8 @@ class LCD : public SingletonTemplate<LCD>

       friend class SingletonTemplate<LCD>;  ///< Friend class used for Singleton Template
};

+ +

class Bluetooth : public SingletonTemplate<Bluetooth>
{
    public:

@@ -81,6 +85,10 @@ class switchTask : public scheduler_task

        static const char *getSwitchName(switchID_t sw);
};

+ + +const uint8_t deviceNameMaxLen = 17; +

class assetManagementTask : public scheduler_task
{
    public:

@@ -89,8 +97,8 @@ class assetManagementTask : public scheduler_task

    private:
#define enum2Str(id) (#id)

- static const uint8_t maxTileDevices = 10; - bool BTInquiryInProcess; + static const uint8_t maxTileDevices = 10; + bool BTInquiryInProcess;

        typedef enum {
            USER_MENU_ACTION_SCROLL_DOWN,

@@ -105,7 +113,7 @@ class assetManagementTask : public scheduler_task

            USER_MENU_TYPE_TRACK_TILE,
            USER_MENU_TYPE_ADD_TILE,
            USER_MENU_TYPE_REMOVE_TILE, // unused

- USER_MENU_TYPE_LIST_TILE, // unused + USER_MENU_TYPE_LIST_TILE,

        } userMenuType_t;
        class tileDevice {
            public:

@@ -167,12 +175,32 @@ class assetManagementTask : public scheduler_task

        const char *getMenuTypeName(userMenuType_t type);
        assetManagementTask::userMenuType_t mainMenuHandleAction(userMenuAction_t action);
        assetManagementTask::userMenuType_t addTileMenuHandleAction(userMenuAction_t action);

+ assetManagementTask::userMenuType_t listTileMenuHandleAction(userMenuAction_t action);

        assetManagementTask::userMenuType_t trackTileMenuHandleAction(userMenuAction_t action);
        bool getStringFromUser(char *buffer, uint8_t size);
        void getTileIdentifier(const char *names[], tileDevice *tiles[], uint8_t deviceCount);
};

+enum { + BT_INQ_BEGIN, + BT_INQ_PENDING_TITLE, + BT_INQ_PENDING_FOUND, + BT_INQ_PENDING_DEVICES, + BT_INQ_DONE, +}; +static uint8_t BTInquiryState = BT_INQ_DONE; +static const char *BTINQNames[] = { + enum2Str(BT_INQ_BEGIN), + enum2Str(BT_INQ_PENDING_TITLE), + enum2Str(BT_INQ_PENDING_FOUND), + enum2Str(BT_INQ_PENDING_DEVICES), + enum2Str(BT_INQ_DONE), +}; + +static char tileSelectedForTracking[ deviceNameMaxLen ]; +static bool tracking_mode = false; +

-void getHistogram(char *histogram, const char *rssi); +void rssi2histogram( const char *rssi, char *histogram );

#endif /* ASSETMANAGEMENT_HPP_ */

diff --git a/L5_Application/assetManagement/src/assetManagement.cpp b/L5_Application/assetManagement/src/assetManagement.cpp index daa4b4f..57dd955 100644 --- a/L5_Application/assetManagement/src/assetManagement.cpp +++ b/L5_Application/assetManagement/src/assetManagement.cpp @@ -360,21 +360,7 @@ assetManagementTask::userMenuType_t assetManagementTask::addTileMenuHandleAction

    userMenuType_t       newMenu = USER_MENU_TYPE_ADD_TILE;
    static bool          top_of_list = false;
    static bool          end_of_list = false;

- enum { - BT_INQ_BEGIN, - BT_INQ_PENDING_TITLE, - BT_INQ_PENDING_FOUND, - BT_INQ_PENDING_DEVICES, - BT_INQ_DONE, - }; - static uint8_t BTInquiryState = BT_INQ_DONE; - static const char *BTINQNames[] = { - enum2Str(BT_INQ_BEGIN), - enum2Str(BT_INQ_PENDING_TITLE), - enum2Str(BT_INQ_PENDING_FOUND), - enum2Str(BT_INQ_PENDING_DEVICES), - enum2Str(BT_INQ_DONE), - }; +

    if (debug) {
        printf("%s - action=[%s],IQState=[%s]\n",
               __FUNCTION__, getMenuActionName(action), BTINQNames[BTInquiryState]);

@@ -411,7 +397,6 @@ assetManagementTask::userMenuType_t assetManagementTask::addTileMenuHandleAction

            const char             *helpStr[] = {"Pick name. Press", "Back to use MAC"};
            const char             *confirmStr[2];
            const char             *deviceAddedStr[2];

- const uint8_t deviceNameMaxLen = 17;

            char                    deviceName[deviceNameMaxLen];
            bool                    deviceNameConfirmed = false;
            switchTask::switchID_t  sw;

@@ -522,12 +507,11 @@ assetManagementTask::userMenuType_t assetManagementTask::addTileMenuHandleAction

    return (newMenu);
}

-assetManagementTask::userMenuType_t assetManagementTask::trackTileMenuHandleAction( +assetManagementTask::userMenuType_t assetManagementTask::listTileMenuHandleAction(

        userMenuAction_t action)
{

- userMenuType_t newMenu = USER_MENU_TYPE_TRACK_TILE; - tileDevice *tilesDetectedPtr[maxTileDevices]; - static uint8_t tilesDetectedCount = 0; + userMenuType_t newMenu = USER_MENU_TYPE_LIST_TILE; + const int32_t displayDuration = 2000; // 2 seconds

    /* Variables that need to be reset
     * on function exit.

@@ -537,33 +521,11 @@ assetManagementTask::userMenuType_t assetManagementTask::trackTileMenuHandleActi

    static bool     end_of_list             = false;
    static bool     display_instructions    = true;

- static bool tracking_mode = false; - - /* TODO: Refactor. - * This code block first appears in - * addTileMenuHandleAction - */ - enum { - BT_INQ_BEGIN, - BT_INQ_PENDING_TITLE, - BT_INQ_PENDING_FOUND, - BT_INQ_PENDING_DEVICES, - BT_INQ_DONE, - }; - static uint8_t BTInquiryState = BT_INQ_DONE; - static const char *BTINQNames[] = { - enum2Str(BT_INQ_BEGIN), - enum2Str(BT_INQ_PENDING_TITLE), - enum2Str(BT_INQ_PENDING_FOUND), - enum2Str(BT_INQ_PENDING_DEVICES), - enum2Str(BT_INQ_DONE), - }; -

    /* TODO:    Use real data to get list
     *          of registered tiles.
     */
    char *registeredTiles[] = { "889FFAF03BB3", "ubuntu-0" };

- int numberOfTiles = sizeof(registeredTiles) / sizeof(char *); + int32_t numberOfTiles = sizeof(registeredTiles) / sizeof(char *);

    if (debug) {
        printf( "%s - Number of registered tiles: %i\n", __FUNCTION__, numberOfTiles);

@@ -571,21 +533,31 @@ assetManagementTask::userMenuType_t assetManagementTask::trackTileMenuHandleActi

    // fail fast
    if (0 == numberOfTiles) {

- LCD::getInstance().display( "ERR: No tiles" ); - delay_ms(2000); // sleep for two seconds - - // return USER_MENU_TYPE_MAIN; - /* Use action instead of return to ensure - * that we always exit this function in - * a consistent manner. The BACK case - * will reset variables. - */ + const char *oops[] = { "ERR: No Tiles" }; + int32_t numOfMsgs = sizeof(oops) / sizeof(char *); + + LCD::getInstance().display( + oops, + numOfMsgs, + 0, + false, + true, + displayDuration); +

        action = USER_MENU_ACTION_BACK;
    }
    else if (display_instructions) {
        display_instructions = false;

- LCD::getInstance().display( "Select a Tile" ); - delay_ms(2000); // sleep for two seconds + const char *instruction[] = { "Select a Tile" }; + int32_t numOfInstructions = sizeof(instruction) / sizeof(char *); + + LCD::getInstance().display( + instruction, + numOfInstructions, + 0, + false, + true, + displayDuration);

    }

    switch (action) {

@@ -623,19 +595,12 @@ assetManagementTask::userMenuType_t assetManagementTask::trackTileMenuHandleActi

        }
        case USER_MENU_ACTION_SELECT:
        {

- LCD::getInstance().display("Tracking..."); - tracking_mode = true; - - for (int i = 0; i < tilesDetectedCount; i++) { - delete tilesDetectedPtr[i]; - tilesDetectedPtr[i] = 0; + strcpy( tileSelectedForTracking, registeredTiles[ selectedTile ] ); + if (debug) { + printf("%s - Selected Tile: %s\n", __FUNCTION__, tileSelectedForTracking);

            }

- tilesDetectedCount = 0; - - BTInquiryState = BT_INQ_BEGIN; - Bluetooth::getInstance().clearPreviousBTData(); - Bluetooth::getInstance().inquiryWithRSSI();

+ newMenu = USER_MENU_TYPE_TRACK_TILE;

            break;
        }
        case USER_MENU_ACTION_BACK:

@@ -645,7 +610,6 @@ assetManagementTask::userMenuType_t assetManagementTask::trackTileMenuHandleActi

            top_of_list             = false;
            end_of_list             = false;
            display_instructions    = true;

- tracking_mode = false;

            newMenu = USER_MENU_TYPE_MAIN;
            break;

@@ -656,98 +620,178 @@ assetManagementTask::userMenuType_t assetManagementTask::trackTileMenuHandleActi

        }
    }

- if (tracking_mode) { - while (BTInquiryState != BT_INQ_DONE) { - char BTRxData[1000]; - char *savePtr; + if (end_of_list) { + LCD::getInstance().display("(End of List)"); + } + else if (top_of_list) { + LCD::getInstance().display("(Top of List)"); + } + else if ( 0 != numberOfTiles ) { + LCD::getInstance().display( (const char **)registeredTiles, (uint8_t)numberOfTiles, selectedTile, true ); + }

- if (Bluetooth::getInstance().receiveData(BTRxData, sizeof(BTRxData))) { - if (debug) { - printf("%s - BTRx=[%s]\n", __FUNCTION__, BTRxData); - } - switch (BTInquiryState) { - case BT_INQ_BEGIN: - if (strstr(BTRxData, "COD")) { - BTInquiryState = BT_INQ_PENDING_FOUND; - } - break; - case BT_INQ_PENDING_FOUND: - if (strstr(BTRxData, "Found")) { - BTInquiryState = BT_INQ_PENDING_DEVICES; - } - break; - case BT_INQ_PENDING_DEVICES: - if (strstr(BTRxData, "Inquiry Done")) { - BTInquiryState = BT_INQ_DONE; - BTInquiryInProcess = false; - } else { - char *macAddrPtr = strtok_r(BTRxData, ",", &savePtr); - char *btNamePtr = strtok_r(NULL, ",", &savePtr); - char *btCODPtr = strtok_r(NULL, ",", &savePtr); - char *btRSSIPtr = strtok_r(NULL, ",", &savePtr); - tilesDetectedPtr[tilesDetectedCount] = - new tileDevice(macAddrPtr, btRSSIPtr, btNamePtr, btCODPtr); - tilesDetectedCount++; - } - break; - } - if (debug) { - printf("%s - New IQState=[%s]\n", __FUNCTION__, BTINQNames[BTInquiryState]); + return( newMenu ); +} + +assetManagementTask::userMenuType_t assetManagementTask::trackTileMenuHandleAction( + userMenuAction_t action) +{ + userMenuType_t newMenu = USER_MENU_TYPE_TRACK_TILE; + + static tileDevice *tilesDetectedPtr[maxTileDevices]; + static uint8_t tilesDetectedCount = 0; + + const int32_t displayDuration = 2000; // 2 seconds + const char *EOR = "-9999"; // Error: Out of Range + + for (size_t i = 0; i < tilesDetectedCount; i++) { + delete tilesDetectedPtr[i]; + tilesDetectedPtr[i] = 0; + } + tilesDetectedCount = 0; + + + switch (action) { + case USER_MENU_ACTION_SCROLL_DOWN: + { + break; + } + case USER_MENU_ACTION_SCROLL_UP: + { + break; + } + case USER_MENU_ACTION_SELECT: + { + break; + } + case USER_MENU_ACTION_BACK: + { + newMenu = USER_MENU_TYPE_LIST_TILE; + tracking_mode = false; + break; + } + case USER_MENU_ACTION_MENU_CHANGED: + { + LCD::getInstance().display("Tracking..."); + tracking_mode = true; + break; + } + case USER_MENU_ACTION_DISPLAY: + { + BTInquiryState = BT_INQ_BEGIN; + Bluetooth::getInstance().clearPreviousBTData(); + Bluetooth::getInstance().inquiryWithRSSI(); + + while (BTInquiryState != BT_INQ_DONE) { + char BTRxData[1000]; + char *savePtr; + + if (Bluetooth::getInstance().receiveData(BTRxData, sizeof(BTRxData))) { + if (debug) { + printf("%s - BTRx=[%s]\n", __FUNCTION__, BTRxData); + } + switch (BTInquiryState) { + case BT_INQ_BEGIN: + if (strstr(BTRxData, "COD")) { + BTInquiryState = BT_INQ_PENDING_FOUND; + } + break; + case BT_INQ_PENDING_FOUND: + if (strstr(BTRxData, "Found")) { + BTInquiryState = BT_INQ_PENDING_DEVICES; + } + break; + case BT_INQ_PENDING_DEVICES: + if (strstr(BTRxData, "Inquiry Done")) { + BTInquiryState = BT_INQ_DONE; + BTInquiryInProcess = false; + } else { + char *macAddrPtr = strtok_r(BTRxData, ",", &savePtr); + char *btNamePtr = strtok_r(NULL, ",", &savePtr); + char *btCODPtr = strtok_r(NULL, ",", &savePtr); + char *btRSSIPtr = strtok_r(NULL, ",", &savePtr); + tilesDetectedPtr[tilesDetectedCount] = + new tileDevice(macAddrPtr, btRSSIPtr, btNamePtr, btCODPtr); + tilesDetectedCount++; + } + break; + } + if (debug) { + printf("%s - New IQState=[%s]\n", __FUNCTION__, BTINQNames[BTInquiryState]); + }

                }
            }

- }

- /* TODO: Refactor and use constant - * deviceNameMaxLen - * instead of magic 17. - */ - char selectedTileMAC[17]; - /* TODO: Get selected tile's - * MAC address. - */ - strncpy( selectedTileMAC, registeredTiles[ selectedTile ], sizeof(selectedTileMAC)); - if (debug) { - printf( "%s - Selected Tile MAC: %s\n", __FUNCTION__, selectedTileMAC ); - } - - size_t index; - for (index = 0; index < tilesDetectedCount; index++) { - int match = strcmp( selectedTileMAC, tilesDetectedPtr[index]->getMac()); - - if ( 0 == match ) { - if (debug) { - printf( "%s - Matched MACs\n", __FUNCTION__ ); - printf( "%s - Tile's RSSI Value: %s\n", __FUNCTION__, tilesDetectedPtr[index]->getRSSI() ); - }

- char histogram[17]; - getHistogram( histogram, (const char *)tilesDetectedPtr[index]->getRSSI() ); - if (debug) { - printf( "%s - RSSI Histogram: %s\n", __FUNCTION__, histogram ); - } + char selectedTileMAC[ deviceNameMaxLen ]; + char histogramTitle[ deviceNameMaxLen ]; + char histogram[ deviceNameMaxLen ];

- LCD::getInstance().display( histogram ); - //delay_ms(2000); + /* TODO: Get selected tile's + * MAC address. + */ + //strncpy( selectedTileMAC, registeredTiles[ selectedTile ], sizeof(selectedTileMAC)); + strncpy( selectedTileMAC, tileSelectedForTracking, sizeof(selectedTileMAC)); + if (debug) { + printf( "%s - Selected Tile MAC: %s\n", __FUNCTION__, selectedTileMAC ); + } + + /* TODO: Use tile's name instead of selected MAC */ + strcpy( histogramTitle, selectedTileMAC ); + + size_t index; + for (index = 0; index < tilesDetectedCount; ++index) { + int32_t match = strcmp( selectedTileMAC, tilesDetectedPtr[index]->getMac()); + + if ( 0 == match ) { + if (debug) { + printf( "%s - Matched MACs: %s\n", __FUNCTION__, selectedTileMAC ); + printf( "%s - Tile's RSSI Value: %s\n", __FUNCTION__, tilesDetectedPtr[index]->getRSSI() ); + } + + rssi2histogram( tilesDetectedPtr[index]->getRSSI(), histogram ); + if (debug) { + printf( "%s - RSSI Histogram: %s\n", __FUNCTION__, histogram ); + } + + const char *histogramDisplay[] = { histogramTitle, histogram }; + int32_t numOfHistoLines = sizeof(histogramDisplay) / sizeof(char *); + + LCD::getInstance().display( + histogramDisplay, + numOfHistoLines, + 0, + false, + true ); + //displayDuration );

- break; + break; + }

           }

- }

- tracking_mode = false; - return( newMenu ); - } + if (index >= tilesDetectedCount) { + rssi2histogram( EOR, histogram );

+ const char *histogramDisplay[] = { histogramTitle, histogram }; + int32_t numOfHistoLines = sizeof(histogramDisplay) / sizeof(char *);

- if (end_of_list) { - LCD::getInstance().display("(End of List)"); - } - else if (top_of_list) { - LCD::getInstance().display("(Top of List)"); - } - else if ( 0 != numberOfTiles ) { - LCD::getInstance().display( (const char **)registeredTiles, (uint8_t)numberOfTiles, selectedTile, true ); + LCD::getInstance().display( + histogramDisplay, + numOfHistoLines, + 0, + false, + true ); + // displayDuration ); + } + } + default: + { + break; + }

    }

+ +

    return( newMenu );
}

@@ -772,7 +816,8 @@ assetManagementTask::userMenuType_t assetManagementTask::mainMenuHandleAction(

            break;
        case USER_MENU_ACTION_SELECT:
            switch (selectedOpt) {

- case 0: newMenu = USER_MENU_TYPE_TRACK_TILE; break; + // case 0: newMenu = USER_MENU_TYPE_TRACK_TILE; break; + case 0: newMenu = USER_MENU_TYPE_LIST_TILE; break;

                case 1:  newMenu = USER_MENU_TYPE_ADD_TILE;    break;
                case 2:  newMenu = USER_MENU_TYPE_REMOVE_TILE; break;
                default: newMenu = USER_MENU_TYPE_MAIN;        break;

@@ -805,11 +850,12 @@ void assetManagementTask::userMenuUpdate(assetManagementTask::userMenuAction_t a

        switch (currentMenu) {
            case USER_MENU_TYPE_MAIN:       nextMenu = mainMenuHandleAction(action);    break;
            case USER_MENU_TYPE_ADD_TILE:   nextMenu = addTileMenuHandleAction(action); break;

+ case USER_MENU_TYPE_LIST_TILE: nextMenu = listTileMenuHandleAction(action); break;

            case USER_MENU_TYPE_TRACK_TILE: nextMenu = trackTileMenuHandleAction(action); break;

- case USER_MENU_TYPE_LIST_TILE: break;

            default:                       break;
        }
        action = USER_MENU_ACTION_MENU_CHANGED;

+

        if (debug) {
            printf("%s - [%u],current=[%s],next=[%s]\n",
                   __FUNCTION__, cnt, getMenuTypeName(currentMenu), getMenuTypeName(nextMenu));

@@ -824,8 +870,10 @@ void assetManagementTask::handleSwitchPress(switchTask::switchID_t sID)

    printf("SW Pressed=[%s]\n", switchTask::getSwitchName(sID));
    switch (sID) {
        case switchTask::SWITCH_ID_BACK:

+ {

            action = USER_MENU_ACTION_BACK;
            break;

+ }

        case switchTask::SWITCH_ID_DOWN:
            action = USER_MENU_ACTION_SCROLL_DOWN;
            break;

@@ -899,8 +947,8 @@ bool assetManagementTask::run(void *p)

{
//    char blah[100];
//    getStringFromUser(blah, 100);

- checkSwitches(!BTInquiryInProcess); - if (BTInquiryInProcess) { + checkSwitches( !(tracking_mode || BTInquiryInProcess) ); + if (tracking_mode || BTInquiryInProcess) {

        userMenuUpdate(USER_MENU_ACTION_DISPLAY);
    }
    return (true);

@@ -916,7 +964,7 @@ assetManagementTask::assetManagementTask(uint8_t priority) :

}

void

-getHistogram( char *histogram, const char *rssi ) +rssi2histogram( const char *rssi, char *histogram )

{
    int RSSI = atoi( rssi );

diff --git a/L5_Application/main.cpp b/L5_Application/main.cpp index b6bdf83..2112a71 100644 --- a/L5_Application/main.cpp +++ b/L5_Application/main.cpp @@ -118,7 +118,7 @@ int main(void)

    #endif

//    scheduler_add_task(new BTRxTask(PRIORITY_LOW));

- scheduler_add_task(new switchTask(PRIORITY_LOW)); + scheduler_add_task(new switchTask(PRIORITY_MEDIUM));

    scheduler_add_task(new assetManagementTask(PRIORITY_LOW));

    scheduler_start(true); ///< This shouldn't return

-- 1.8.5.2.msysgit.0


From 2b7b03c4c9295ece8eabf7ad9604a33d4610feaf Mon Sep 17 00:00:00 2001 From: Pardeep <p_badhan2004@yahoo.com> Date: Thu, 1 May 2014 09:57:13 -0700 Subject: [PATCH 12/23] Storing tile information to flash

Finished backend support for "Add Tile", added support for "Remove Tile", and "List Tiles" menus.

The "Add Tile" option now writes the tile information to the flash. The file structure is the following. At bootup, this file is read to determine the number registered tile devices, and the information of each device is read in memory. The file doesn't start a 0 to always make usage of Storage::append() API - if the offset is 0, it write to end of the file. +---------------------------------+--------------+ | byte offset | field | +---------------------------------+--------------+ | 3 | tile count | +---------------------------------+--------------+ | 7 | write offset | +---------------------------------+--------------+ | 11 | tile 1 | +---------------------------------+--------------+ | 11 + | | | sizeof(tileStorageInfo_t) | tile 2 | +---------------------------------+--------------+ | 11 + | | | 2*sizeof(tileStorageInfo_t) | tile 3 | +---------------------------------+--------------+ | ... | | +---------------------------------+--------------+ | 11 + | | | (n-1)*sizeof(tileStorageInfo_t) | tile n | +---------------------------------+--------------+

Added "tileDevice" class that stores the information of a tile. The information includes 1) tile name, 2) Bluetooth name, 3) MAC address, 4) COD, 5) RSSI when the device was added.

Moved the inquiry logic to a function. Also made it more robust. It is now able to handle a case where multiple inquiry attempts are made. The logic will finish the old query, and then it will start a new inquiry.

Also moved the "Start of List" and "Enf of List" to LCD::display function to avoid the replication. Hopefully, I didn't break anything. ---

L5_Application/assetManagement/assetManagement.hpp | 125 +++--
.../assetManagement/src/assetManagement.cpp        | 542 +++++++++++++++++----
2 files changed, 510 insertions(+), 157 deletions(-)

diff --git a/L5_Application/assetManagement/assetManagement.hpp b/L5_Application/assetManagement/assetManagement.hpp index 09526e3..82a8b4c 100644 --- a/L5_Application/assetManagement/assetManagement.hpp +++ b/L5_Application/assetManagement/assetManagement.hpp @@ -10,6 +10,8 @@

#include "singleton_template.hpp"
#include "gpio.hpp"
#include "stdio.h"

+#include "storage.hpp" +#include "string.h"

class LCD : public SingletonTemplate<LCD>
{

@@ -50,7 +52,6 @@ class Bluetooth : public SingletonTemplate<Bluetooth>

        bool receiveData(char *buffer, uint32_t bufferSize);
        void inquiryWithRSSI();
        void inquiry();

- void clearPreviousBTData();

    private:
        static const uint8_t rxMaxWait = 100; // 100ms

@@ -76,6 +77,55 @@ class switchTask : public scheduler_task

        static const char *getSwitchName(switchID_t sw);
};

+class tileDevice { + public: + tileDevice(); + tileDevice(const char *mac, + const char *BTName, + const char *tileName, + const char *cod, + const char *rssi); + void setMac(const char *mac); + void setBTName(const char *name); + void setTileName(const char *name); + void setCOD(const char *cod); + void setRSSI(const char *rssi); + + uint32_t writeToFile(const char *fileName, uint8_t offset); + uint8_t readFromFile(const char *fileName, uint8_t offset); + + const char *getMac(); + const char *getRSSI(); + const char *getBTName(); + const char *getTileName(); + const char *getTileIdentifier(); + const char *getCOD(); + void print(); + + private: + static const uint8_t BTMACAddrLen = 12; + static const uint8_t BTRSSIValLen = 10; + static const uint8_t BTNameLen = 16; + static const uint8_t tileNameLen = 16; + static const uint8_t codLen = 10; + + typedef struct tileStorageInfo_s { + char mac[BTMACAddrLen + 1]; + char rssi[BTRSSIValLen + 1]; + char btName[BTNameLen + 1]; + char tileName[tileNameLen + 1]; + char cod[codLen + 1]; + } tileStorageInfo_t; + + char mac[BTMACAddrLen + 1]; + char rssi[BTRSSIValLen + 1]; + char btName[BTNameLen + 1]; + char tileName[tileNameLen + 1]; + char cod[codLen + 1]; + + void setString(char *to, const char *from, uint32_t size); +}; +

class assetManagementTask : public scheduler_task
{
    public:

@@ -84,9 +134,11 @@ class assetManagementTask : public scheduler_task

    private:
#define enum2Str(id) (#id)

- static const uint8_t maxTileDevices = 10; - bool BTInquiryInProcess;

+ typedef struct tileStorageFileHeader_s { + uint32_t tilesStoredCount; + uint32_t writeOffset; + } tileStorageFileHeader_t;

        typedef enum {
            USER_MENU_ACTION_SCROLL_DOWN,
            USER_MENU_ACTION_SCROLL_UP,

@@ -102,57 +154,14 @@ class assetManagementTask : public scheduler_task

            USER_MENU_TYPE_REMOVE_TILE,
            USER_MENU_TYPE_LIST_TILE,
        } userMenuType_t;

- class tileDevice { - public: - tileDevice(const char *mac, - const char *rssi, - const char *BTName, - const char *tileName) - { - setMac(mac); setRSSI(rssi); setBTName(BTName); setTileName(tileName); - } - void setMac(const char *mac) { setString(this->mac, mac, sizeof(this->mac)); } - void setRSSI(const char *rssi) { setString(this->rssi, rssi, sizeof(this->rssi)); } - void setBTName(const char *name) { setString(this->btName, name, sizeof(this->btName)); } - void setTileName(const char *name) { setString(this->tileName, name, sizeof(this->tileName)); } - const char *getMac() { return mac; } - const char *getRSSI() { return rssi; } - const char *getBTName() { return btName; } - const char *getTileName() { return tileName; } - /* - * Returns the first non null pointer in the following order: - * 1. Tile Name, - * 2. Bluetooth Name - * 3. MAC Address - */ - const char *getTileIdentifier() { - if (0 == tileName[0]) { - return (tileName); - } else if (0 == btName[0]) { - return (btName); - } else { - return (mac); - } - } - private: - static const uint8_t BTMACAddrLen = 12; - static const uint8_t BTRSSIValLen = 10; - static const uint8_t BTNameLen = 16; - static const uint8_t tileNameLen = 16; - - char mac[BTMACAddrLen + 1]; - char rssi[BTRSSIValLen + 1]; - char btName[BTNameLen + 1]; - char tileName[tileNameLen + 1]; - - void setString(char *to, const char *from, uint32_t size) { - if (0 == from) { - to[0] = 0; - } else { - snprintf(to, size, "%s", from); - } - } - }; + + static const uint8_t maxTileDevices = 10; + tileDevice *registeredTileDevice[maxTileDevices]; + uint32_t registeredTileDeviceCount; + bool BTInquiryInProcess; + char *storageFileName; + tileStorageFileHeader_t storageFileHeader; + static const uint32_t storageFileHeaderOffset = 3;

        switchTask::switchID_t getSwitchPressed(uint32_t maxWait);
        void checkSwitches(bool waitIndefinitely = false);

@@ -162,8 +171,16 @@ class assetManagementTask : public scheduler_task

        const char *getMenuTypeName(userMenuType_t type);
        assetManagementTask::userMenuType_t mainMenuHandleAction(userMenuAction_t action);
        assetManagementTask::userMenuType_t addTileMenuHandleAction(userMenuAction_t action);

+ assetManagementTask::userMenuType_t removeTileMenuHandleAction(userMenuAction_t action); + assetManagementTask::userMenuType_t listTileMenuHandleAction(userMenuAction_t action);

        bool getStringFromUser(char *buffer, uint8_t size);
        void getTileIdentifier(const char *names[], tileDevice *tiles[], uint8_t deviceCount);

+ void storeRegisteredDevices(); + bool inquiryAllBTDevices(tileDevice *tilesDetectedPtr[], + uint8_t array_size, + uint8_t *deviceDetectedCount, + bool startNewInquiry); + void cancelBTInquiry(void);

};

#endif /* ASSETMANAGEMENT_HPP_ */

diff --git a/L5_Application/assetManagement/src/assetManagement.cpp b/L5_Application/assetManagement/src/assetManagement.cpp index db0f78d..5a2009a 100644 --- a/L5_Application/assetManagement/src/assetManagement.cpp +++ b/L5_Application/assetManagement/src/assetManagement.cpp @@ -42,10 +42,13 @@ void LCD::display(const char *data[],

    if (emulationMode()) {
        // Simulated LCD Header

+ if (dataSelectedIdx == 0) { + printToLCD("(Top of List)"); + LCD::getInstance().newLine(); + }

        LCD::getInstance().printToLCD("----------------");
        LCD::getInstance().newLine();

- } - else { + } else {

        LCD::getInstance().clearScreen();
        LCD::getInstance().goToStart();
    }

@@ -85,6 +88,10 @@ void LCD::display(const char *data[],

        // Simulated LCD Footer
        LCD::getInstance().printToLCD("----------------");
        LCD::getInstance().newLine();

+ if (dataSelectedIdx == (dataSize - 1)) { + printToLCD("(End of List)"); + LCD::getInstance().newLine(); + }

    }
    if (0 != maxDelayAfterDisplay) {
        delay_ms(maxDelayAfterDisplay);

@@ -160,10 +167,6 @@ LCD::LCD() :

    clearScreen();
}

-void Bluetooth::clearPreviousBTData() -{ -} -

void Bluetooth::inquiry()
{
    goToCmdMode();

@@ -285,6 +288,263 @@ bool switchTask::run(void *p)

    return (true);
}

+tileDevice::tileDevice() +{ + setMac(0); setBTName(0); setTileName(0); setCOD(0); setRSSI(0); +} + +tileDevice::tileDevice(const char *mac, + const char *BTName, + const char *tileName, + const char *cod, + const char *rssi) +{ + setMac(mac); setBTName(BTName); setTileName(tileName); setCOD(cod); setRSSI(rssi); +} + +void tileDevice::setMac(const char *mac) +{ + setString(this->mac, mac, sizeof(this->mac)); +} + +void tileDevice::setBTName(const char *name) +{ + setString(this->btName, name, sizeof(this->btName)); +} + +void tileDevice::setTileName(const char *name) +{ + setString(this->tileName, name, sizeof(this->tileName)); +} + +void tileDevice::setCOD(const char *cod) +{ + setString(this->cod, cod, sizeof(this->cod)); +} + +void tileDevice::setRSSI(const char *rssi) +{ + setString(this->rssi, rssi, sizeof(this->rssi)); +} + +uint32_t tileDevice::writeToFile(const char *fileName, uint8_t offset) +{ + tileStorageInfo_t toWrite; + FRESULT rc; + + strncpy(toWrite.mac, this->mac, sizeof(toWrite.mac)); + strncpy(toWrite.rssi, this->rssi, sizeof(toWrite.rssi)); + strncpy(toWrite.btName, this->btName, sizeof(toWrite.btName)); + strncpy(toWrite.tileName, this->tileName, sizeof(toWrite.tileName)); + + rc = Storage::append(fileName, + &toWrite, + sizeof(toWrite), + offset); + if (FR_OK != rc) { + return (0); + } else { + return (sizeof(toWrite)); + } +} + +uint8_t tileDevice::readFromFile(const char *fileName, uint8_t offset) +{ + tileStorageInfo_t toRead; + FRESULT rc; + + memset(&toRead, 0, sizeof(toRead)); + rc = Storage::read(fileName, + &toRead, + sizeof(toRead), + offset); + if (FR_OK != rc) { + return (0); + } + setMac(toRead.mac); + setBTName(toRead.btName); + setTileName(toRead.tileName); + setCOD(toRead.cod); + setRSSI(toRead.rssi); + + return (sizeof(tileStorageInfo_t)); +} + +const char *tileDevice::getMac() { return mac; } +const char *tileDevice::getRSSI() { return rssi; } +const char *tileDevice::getBTName() { return btName; } +const char *tileDevice::getTileName() { return tileName; } +const char *tileDevice::getCOD() { return cod; } + +/* + * Returns the first non null pointer in the following order: + * 1. Tile Name, + * 2. Bluetooth Name + * 3. MAC Address + */ +const char *tileDevice::getTileIdentifier() +{ + if (0 != tileName[0]) { + return (tileName); + } else if (0 != btName[0]) { + return (btName); + } else { + return (mac); + } +} + +void tileDevice::print() +{ + printf("[%s],[%s],[%s],[%s],[%s]\n", + getTileName(), getBTName(), getMac(), getRSSI(), getCOD()); +} + +void tileDevice::setString(char *to, const char *from, uint32_t size) +{ + if (0 == from) { + to[0] = 0; + } else { + snprintf(to, size, "%s", from); + } +} + +void assetManagementTask::cancelBTInquiry() +{ + BTInquiryInProcess = false; +} + +bool assetManagementTask::inquiryAllBTDevices( + tileDevice *tilesDetectedPtr[], + uint8_t array_size, + uint8_t *deviceDetectedCount, + bool startNewInquiry) +{ + static bool debug = true; + enum { + BT_INQ_BEGIN, + BT_INQ_PENDING_TITLE, + BT_INQ_PENDING_FOUND, + BT_INQ_PENDING_DEVICES, + BT_INQ_MULTIPLE_INQUIRY_ATTEMPT, + BT_INQ_DONE, + }; + static uint8_t BTInquiryState = BT_INQ_DONE; + static const char *BTINQNames[] = { + enum2Str(BT_INQ_BEGIN), + enum2Str(BT_INQ_PENDING_TITLE), + enum2Str(BT_INQ_PENDING_FOUND), + enum2Str(BT_INQ_PENDING_DEVICES), + enum2Str(BT_INQ_DONE), + enum2Str(BT_INQ_MULTIPLE_INQUIRY_ATTEMPT), + }; + + if (debug) { + printf("%s -IQState=[%s]\n", __FUNCTION__, BTINQNames[BTInquiryState]); + } + + if (startNewInquiry) { + BTInquiryState = BT_INQ_DONE; + const char *searchingStr = "Searching..."; + LCD::getInstance().display(searchingStr); + for (int i = 0; i < array_size; i++) { + if (tilesDetectedPtr[i]) { + delete tilesDetectedPtr[i]; + tilesDetectedPtr[i] = 0; + } + } + *deviceDetectedCount = 0; + BTInquiryInProcess = true; + BTInquiryState = BT_INQ_BEGIN; + /* Query Tile devices in vicinity */ + Bluetooth::getInstance().inquiryWithRSSI(); + } + + if (BTInquiryState != BT_INQ_DONE) { + char BTRxData[1000]; + char *savePtr; + + if (Bluetooth::getInstance().receiveData(BTRxData, sizeof(BTRxData))) { + if (debug) { + printf("%s - BTRx=[%s]\n", __FUNCTION__, BTRxData); + } + if (strstr(BTRxData, "Already Inquiring")) { + BTInquiryState = BT_INQ_MULTIPLE_INQUIRY_ATTEMPT; + } + switch (BTInquiryState) { + case BT_INQ_BEGIN: + { + if (strstr(BTRxData, "COD")) { + BTInquiryState = BT_INQ_PENDING_FOUND; + } + break; + } + case BT_INQ_PENDING_FOUND: + { + if (strstr(BTRxData, "Found")) { + BTInquiryState = BT_INQ_PENDING_DEVICES; + } + break; + } + case BT_INQ_PENDING_DEVICES: + { + if (strstr(BTRxData, "Inquiry Done")) { + BTInquiryState = BT_INQ_DONE; + BTInquiryInProcess = false; + } else { + char *macAddrPtr = strtok_r(BTRxData, ",", &savePtr); + char *btNamePtr = strtok_r(NULL, ",", &savePtr); + char *btCODPtr = strtok_r(NULL, ",", &savePtr); + char *btRSSIPtr = strtok_r(NULL, ",", &savePtr); + tilesDetectedPtr[*deviceDetectedCount] = + new tileDevice(macAddrPtr, btNamePtr, 0, btCODPtr, btRSSIPtr); + (*deviceDetectedCount)++; + } + break; + } + case BT_INQ_MULTIPLE_INQUIRY_ATTEMPT: + { + if (strstr(BTRxData, "Inquiry Done")) { + BTInquiryState = BT_INQ_BEGIN; + for (int i = 0; i < array_size; i++) { + if (tilesDetectedPtr[i]) { + delete tilesDetectedPtr[i]; + tilesDetectedPtr[i] = 0; + } + } + Bluetooth::getInstance().inquiryWithRSSI(); + } + break; + } + } + if (debug) { + printf("%s - New IQState=[%s]\n", __FUNCTION__, BTINQNames[BTInquiryState]); + } + } + } + + return (BTInquiryInProcess == false); +} + +void assetManagementTask::storeRegisteredDevices() +{ + uint32_t writeOffset = storageFileHeaderOffset; + tileStorageFileHeader_s newFileHeader; + for (uint8_t i = 0; i < maxTileDevices; i++) { + if (registeredTileDevice[i]) { + writeOffset += registeredTileDevice[i]->writeToFile(storageFileName, writeOffset); + } + } + + newFileHeader.tilesStoredCount = registeredTileDeviceCount; + newFileHeader.writeOffset = writeOffset; + if (FR_OK != Storage::append(storageFileName, + &newFileHeader, + sizeof(newFileHeader), + storageFileHeaderOffset)) { + // TODO: Display error? + } +} +

void assetManagementTask::getTileIdentifier(const char *names[], tileDevice *tiles[], uint8_t deviceCount)
{
    for (int i = 0; i < deviceCount; i++) {

@@ -350,36 +610,102 @@ bool assetManagementTask::getStringFromUser(char *buffer, uint8_t bufferSize)

    strncpy(buffer, userStr, bufferSize);
    return (userStrLen > 0);
}

+assetManagementTask::userMenuType_t assetManagementTask::listTileMenuHandleAction( + userMenuAction_t action) +{ + static uint8_t selectedOpt = 0; + const char *tileIdentifiers[maxTileDevices]; + userMenuType_t newMenu = USER_MENU_TYPE_LIST_TILE; + + switch (action) { + case USER_MENU_ACTION_SCROLL_DOWN: + { + if (selectedOpt < (registeredTileDeviceCount - 1)) { + selectedOpt++; + } + break; + } + case USER_MENU_ACTION_SCROLL_UP: + { + if (selectedOpt > 0) { + selectedOpt--; + } + break; + } + case USER_MENU_ACTION_SELECT: + { + break; + } + case USER_MENU_ACTION_BACK: + { + newMenu = USER_MENU_TYPE_MAIN; + break; + } + default: + break; + } + getTileIdentifier(tileIdentifiers, registeredTileDevice, registeredTileDeviceCount); + LCD::getInstance().display(tileIdentifiers, registeredTileDeviceCount, selectedOpt, true); + + return (newMenu); +} + +assetManagementTask::userMenuType_t assetManagementTask::removeTileMenuHandleAction( + userMenuAction_t action) +{ + static uint8_t selectedOpt = 0; + userMenuType_t newMenu = USER_MENU_TYPE_MAIN; + const char *tileIdentifiers[maxTileDevices]; + + switch (action) { + case USER_MENU_ACTION_SCROLL_DOWN: + { + if (selectedOpt < (registeredTileDeviceCount - 1)) { + selectedOpt++; + } + break; + } + case USER_MENU_ACTION_SCROLL_UP: + { + if (selectedOpt > 0) { + selectedOpt--; + } + break; + } + case USER_MENU_ACTION_SELECT: + { + if (registeredTileDevice[selectedOpt]) { + delete registeredTileDevice[selectedOpt]; + registeredTileDevice[selectedOpt] = 0; + registeredTileDeviceCount--; + storeRegisteredDevices(); + } + break; + } + case USER_MENU_ACTION_BACK: + { + newMenu = USER_MENU_TYPE_MAIN; + break; + } + default: + break; + } + + getTileIdentifier(tileIdentifiers, registeredTileDevice, registeredTileDeviceCount); + LCD::getInstance().display(tileIdentifiers, registeredTileDeviceCount, selectedOpt, true); + return (newMenu); +}

assetManagementTask::userMenuType_t assetManagementTask::addTileMenuHandleAction(
        userMenuAction_t action)
{
    static uint8_t       selectedOpt = 0;

- tileDevice *tilesDetectedPtr[maxTileDevices]; + static tileDevice *tilesDetectedPtr[maxTileDevices] = {0};

    static uint8_t       tilesDetectedCount = 0;
    userMenuType_t       newMenu = USER_MENU_TYPE_ADD_TILE;
    static bool          debug = true;

- static bool top_of_list = false; - static bool end_of_list = false; - enum { - BT_INQ_BEGIN, - BT_INQ_PENDING_TITLE, - BT_INQ_PENDING_FOUND, - BT_INQ_PENDING_DEVICES, - BT_INQ_DONE, - }; - static uint8_t BTInquiryState = BT_INQ_DONE; - static const char *BTINQNames[] = { - enum2Str(BT_INQ_BEGIN), - enum2Str(BT_INQ_PENDING_TITLE), - enum2Str(BT_INQ_PENDING_FOUND), - enum2Str(BT_INQ_PENDING_DEVICES), - enum2Str(BT_INQ_DONE), - }; - if (debug) { - printf("%s - action=[%s],IQState=[%s]\n", - __FUNCTION__, getMenuActionName(action), BTINQNames[BTInquiryState]); - } + bool startNewInquiry = false; + static bool inquiryDone;

    switch (action) {
        case USER_MENU_ACTION_SCROLL_DOWN:

@@ -387,10 +713,6 @@ assetManagementTask::userMenuType_t assetManagementTask::addTileMenuHandleAction

            if (selectedOpt < (tilesDetectedCount - 1)) {
                selectedOpt++;
            }

- else if (! top_of_list ) { - end_of_list = true; - } - top_of_list = false;

            break;
        }
        case USER_MENU_ACTION_SCROLL_UP:

@@ -398,10 +720,6 @@ assetManagementTask::userMenuType_t assetManagementTask::addTileMenuHandleAction

            if (selectedOpt > 0) {
                selectedOpt--;
            }

- else if (! end_of_list ) { - top_of_list = true; - } - end_of_list = false;

            break;
        }
        case USER_MENU_ACTION_SELECT:

@@ -409,7 +727,7 @@ assetManagementTask::userMenuType_t assetManagementTask::addTileMenuHandleAction

            if (tilesDetectedCount == 0) {
                break;
            }

- const char *helpStr[] = {"Pick name. Press", "Back to use MAC"}; + const char *helpStr[] = {"Pick name. Select", "Done to finish"};

            const char             *confirmStr[2];
            const char             *deviceAddedStr[2];
            const uint8_t           deviceNameMaxLen = 17;

@@ -417,13 +735,14 @@ assetManagementTask::userMenuType_t assetManagementTask::addTileMenuHandleAction

            bool                    deviceNameConfirmed = false;
            switchTask::switchID_t  sw;
            uint32_t                helpStrDisplayTime = 4000; /* 4 seconds */

+ uint32_t bytesWritten;

            LCD::getInstance().display(helpStr, 2, 0, false, false, helpStrDisplayTime);
            do {
                if (getStringFromUser(deviceName, sizeof(deviceName))) {
                } else {
                    strncpy(deviceName,

- tilesDetectedPtr[selectedOpt]->getMac(), + tilesDetectedPtr[selectedOpt]->getTileIdentifier(),

                            sizeof(deviceName));
                }
                confirmStr[0] = "Confirm Name:";

@@ -437,30 +756,42 @@ assetManagementTask::userMenuType_t assetManagementTask::addTileMenuHandleAction

            deviceAddedStr[0] = "Device added:";
            deviceAddedStr[1] = deviceName;
            LCD::getInstance().display(deviceAddedStr, 2, 0, false, false, helpStrDisplayTime);

+ tilesDetectedPtr[selectedOpt]->setTileName(deviceName); + bytesWritten = tilesDetectedPtr[selectedOpt]->writeToFile(storageFileName, + storageFileHeader.writeOffset); + const char *flashWriteErr[] = {"Write to", "flash failed"}; + if (0 == bytesWritten) { + LCD::getInstance().display(flashWriteErr, 2, 0, false, true, 4000); + } else { + storageFileHeader.tilesStoredCount++; + storageFileHeader.writeOffset += bytesWritten; + FRESULT rc = Storage::append(storageFileName, + &storageFileHeader, + sizeof(storageFileHeader), + storageFileHeaderOffset); + if (FR_OK != rc) { + LCD::getInstance().display(flashWriteErr, 2, 0, false, true, 4000); + } + } +

            if (debug) {
                printf("%s - %s [%s]\n", __FUNCTION__, deviceAddedStr[0], deviceAddedStr[1]);
            }

+

            newMenu = USER_MENU_TYPE_MAIN;
            break;
        }
        case USER_MENU_ACTION_BACK:

+ {

            newMenu = USER_MENU_TYPE_MAIN;

- BTInquiryInProcess = false; + inquiryDone = true; + cancelBTInquiry();

            break;

+ }

        case USER_MENU_ACTION_MENU_CHANGED:
        {

- const char *searchingStr = "Searching..."; - for (int i = 0; i < tilesDetectedCount; i++) { - delete tilesDetectedPtr[i]; - tilesDetectedPtr[i] = 0; - } - tilesDetectedCount = 0; - BTInquiryInProcess = true; - BTInquiryState = BT_INQ_BEGIN; - LCD::getInstance().display(searchingStr); - /* Query Tile devices in vicinity */ - Bluetooth::getInstance().clearPreviousBTData(); - Bluetooth::getInstance().inquiryWithRSSI(); + inquiryDone = false; + startNewInquiry = true;

            break;
        }
        case USER_MENU_ACTION_DISPLAY:

@@ -468,53 +799,16 @@ assetManagementTask::userMenuType_t assetManagementTask::addTileMenuHandleAction

            break;
    }

- if (BTInquiryState != BT_INQ_DONE) { - char BTRxData[1000]; - char *savePtr; - - if (Bluetooth::getInstance().receiveData(BTRxData, sizeof(BTRxData))) { - if (debug) { - printf("%s - BTRx=[%s]\n", __FUNCTION__, BTRxData); - } - switch (BTInquiryState) { - case BT_INQ_BEGIN: - if (strstr(BTRxData, "COD")) { - BTInquiryState = BT_INQ_PENDING_FOUND; - } - break; - case BT_INQ_PENDING_FOUND: - if (strstr(BTRxData, "Found")) { - BTInquiryState = BT_INQ_PENDING_DEVICES; - } - break; - case BT_INQ_PENDING_DEVICES: - if (strstr(BTRxData, "Inquiry Done")) { - BTInquiryState = BT_INQ_DONE; - BTInquiryInProcess = false; - } else { - char *macAddrPtr = strtok_r(BTRxData, ",", &savePtr); - char *btNamePtr = strtok_r(NULL, ",", &savePtr); - char *btCODPtr = strtok_r(NULL, ",", &savePtr); - char *btRSSIPtr = strtok_r(NULL, ",", &savePtr); - tilesDetectedPtr[tilesDetectedCount] = - new tileDevice(macAddrPtr, btNamePtr, btCODPtr, btRSSIPtr); - tilesDetectedCount++; - } - break; - } - if (debug) { - printf("%s - New IQState=[%s]\n", __FUNCTION__, BTINQNames[BTInquiryState]); - } - } + if (false == inquiryDone) { + inquiryDone = inquiryAllBTDevices(tilesDetectedPtr, + maxTileDevices, + &tilesDetectedCount, + startNewInquiry);

    }

- if (end_of_list) { - LCD::getInstance().display("(End of List)"); - } else if (top_of_list) { - LCD::getInstance().display("(Top of List)"); - } else if (tilesDetectedCount > 0) { + if (inquiryDone && (tilesDetectedCount > 0)) {

        const char *tileIdentifiers[maxTileDevices];
        getTileIdentifier(tileIdentifiers, tilesDetectedPtr, tilesDetectedCount);

- LCD::getInstance().display(tileIdentifiers, tilesDetectedCount, selectedOpt, false); + LCD::getInstance().display(tileIdentifiers, tilesDetectedCount, selectedOpt, true);

    }
    return (newMenu);
}

@@ -523,7 +817,7 @@ assetManagementTask::userMenuType_t assetManagementTask::mainMenuHandleAction(

        assetManagementTask::userMenuAction_t action)
{
    static uint8_t      selectedOpt = 0;

- const char *mainMenu[] = {"Track", "Add Tile", "Remove Tile"}; + const char *mainMenu[] = {"Track", "Add Tile", "Remove Tile", "List Tiles"};

    uint8_t             mainMenuOptCnt = sizeof(mainMenu)/sizeof(mainMenu[0]);
    userMenuType_t      newMenu = USER_MENU_TYPE_MAIN;

@@ -543,6 +837,7 @@ assetManagementTask::userMenuType_t assetManagementTask::mainMenuHandleAction(

                case 0:  newMenu = USER_MENU_TYPE_TRACK_TILE;  break;
                case 1:  newMenu = USER_MENU_TYPE_ADD_TILE;    break;
                case 2:  newMenu = USER_MENU_TYPE_REMOVE_TILE; break;

+ case 3: newMenu = USER_MENU_TYPE_LIST_TILE; break;

                default: newMenu = USER_MENU_TYPE_MAIN;        break;
            }
            break;

@@ -571,10 +866,11 @@ void assetManagementTask::userMenuUpdate(assetManagementTask::userMenuAction_t a

    do {
        currentMenu = nextMenu;
        switch (currentMenu) {

- case USER_MENU_TYPE_MAIN: nextMenu = mainMenuHandleAction(action); break; - case USER_MENU_TYPE_ADD_TILE: nextMenu = addTileMenuHandleAction(action); break; - case USER_MENU_TYPE_LIST_TILE: break; - default: break; + case USER_MENU_TYPE_MAIN: nextMenu = mainMenuHandleAction(action); break; + case USER_MENU_TYPE_ADD_TILE: nextMenu = addTileMenuHandleAction(action); break; + case USER_MENU_TYPE_REMOVE_TILE: nextMenu = removeTileMenuHandleAction(action); break; + case USER_MENU_TYPE_LIST_TILE: nextMenu = listTileMenuHandleAction(action); break; + default: break;

        }
        action = USER_MENU_ACTION_MENU_CHANGED;
        if (debug) {

@@ -664,8 +960,6 @@ const char *assetManagementTask::getMenuActionName(userMenuAction_t action)

bool assetManagementTask::run(void *p)
{

-// char blah[100]; -// getStringFromUser(blah, 100);

    checkSwitches(!BTInquiryInProcess);
    if (BTInquiryInProcess) {
        userMenuUpdate(USER_MENU_ACTION_DISPLAY);

@@ -674,10 +968,52 @@ bool assetManagementTask::run(void *p)

}

assetManagementTask::assetManagementTask(uint8_t priority) :

- scheduler_task("assetManagementTask", 10*512, priority), + scheduler_task("assetManagementTask", 10*1024, priority), + registeredTileDeviceCount(0),

        BTInquiryInProcess(false)
{

+ FRESULT rc; + const char *fileName = "tiles.txt"; + const uint8_t filePathLen = 100; + uint8_t readOffset = storageFileHeaderOffset; + tileStorageFileHeader_s fileHeader; +

    setRunDuration(10);
    LCD::getInstance().clearScreen();

+ + rc = (FRESULT)Storage::getFlashDrive().mount(); + if (FR_OK != rc) { + printf("Failed to mount flash. Error=[%d]\n", rc); + LCD::getInstance().display("Flash error"); + return; + } + + storageFileName = (char *)malloc(filePathLen); + snprintf(storageFileName, + filePathLen, + "%s%s", + Storage::getFlashDrive().getDrivePath(), + fileName); + rc = (FRESULT)Storage::read(storageFileName, &fileHeader, sizeof(fileHeader), readOffset); + if (FR_OK != rc) { + if (FR_NO_FILE == rc) { + storageFileHeader.tilesStoredCount = 0; + storageFileHeader.writeOffset = storageFileHeaderOffset + sizeof(storageFileHeader); + } else { + LCD::getInstance().display("File error"); + return; + } + } else { + storageFileHeader.tilesStoredCount = fileHeader.tilesStoredCount; + storageFileHeader.writeOffset = fileHeader.writeOffset; + registeredTileDeviceCount = storageFileHeader.tilesStoredCount; + } + readOffset += sizeof(fileHeader); + + for (uint8_t i = 0; i < storageFileHeader.tilesStoredCount; i++) { + registeredTileDevice[i] = new tileDevice(); + readOffset += registeredTileDevice[i]->readFromFile(storageFileName, readOffset); + registeredTileDevice[i]->print(); + }

    userMenuUpdate(USER_MENU_ACTION_DISPLAY);
}

-- 1.8.5.2.msysgit.0


From fa8502fd2d859e05b84057be2387c91b2777c012 Mon Sep 17 00:00:00 2001 From: Pardeep <p_badhan2004@yahoo.com> Date: Sun, 4 May 2014 10:25:06 -0700 Subject: [PATCH 13/23] Supporting inquiry of a particular device

Added new function called "inquirySingleBTDevice" that inquiries for a particular device. Snippet code below is an example of how to use it.

static bool startNewInquiry = true; bool queryDone; bool found; tileDevice tile;

queryDone = inquirySingleBTDevice("20C9D08725EA", &tile, &found, startNewInquiry); startNewInquiry = false; if (queryDone) {

   startNewInquiry = true;
   if (found) {
       printf("Device found:\n[%s, %s]\n",

tile.getTileIdentifier(), tile.getRSSI());

   } else {
       printf("Device not found\n");
   }

}

Also, started adding few comments to the code. ---

L5_Application/assetManagement/assetManagement.hpp | 78 +++++++++++++++++++++-
.../assetManagement/src/assetManagement.cpp        | 41 +++++++++++-
2 files changed, 116 insertions(+), 3 deletions(-)

diff --git a/L5_Application/assetManagement/assetManagement.hpp b/L5_Application/assetManagement/assetManagement.hpp index 82a8b4c..4f4e130 100644 --- a/L5_Application/assetManagement/assetManagement.hpp +++ b/L5_Application/assetManagement/assetManagement.hpp @@ -100,7 +100,9 @@ class tileDevice {

        const char *getTileName();
        const char *getTileIdentifier();
        const char *getCOD();

- void print(); + void print(); + + void operator=(tileDevice &from);

    private:
        static const uint8_t BTMACAddrLen   = 12;

@@ -173,13 +175,87 @@ class assetManagementTask : public scheduler_task

        assetManagementTask::userMenuType_t addTileMenuHandleAction(userMenuAction_t action);
        assetManagementTask::userMenuType_t removeTileMenuHandleAction(userMenuAction_t action);
        assetManagementTask::userMenuType_t listTileMenuHandleAction(userMenuAction_t action);

+ /* + * getStringFromUser + * + * Gets string consisting for alphabets, numbers, and special characters from the user + * + * It presents a menu to the user via which user can input a string to the program. To end, the user + * "clicks" on the "Done" string. + * + * Returns "True" is the input was more than 0 characters. + */

        bool getStringFromUser(char *buffer, uint8_t size);

+ /* + * getTileIdentifier + * + * For each device in the "tiles" list, it copies the identifier (either tile name, Bluetooth + * name, or MAC address) of the device to the "names" list. + */

        void getTileIdentifier(const char *names[], tileDevice *tiles[], uint8_t deviceCount);

+ /* + * storeRegisteredDevices + * + * Stores all the registered devices to the flash. + * + * Essentially, the file is flushed and rewritten with currently registered devices. Therefore, it + * is safe to call this function to save the information of a device that is already registered. + */

        void storeRegisteredDevices();

+ /* + * inquiryAllBTDevices + * + * Inquiries for Bluetooth devices + * + * This is a non-blocking function to inquiry all Bluetooth devices in the vicinity. Since this + * function is non-blocking, Bluetooth inquiry will span multiple function calls. In other words, + * the caller may have to keep calling this function until inquiry is done to retrieve information + * of all Bluetooth devices in the vicinity. It is responsibility of the caller to preserve the + * data in the following fields until inquiry is done: + * tileDetectedPtr + * deviceDetectedCount + * + * The caller must tell when to start a new inquiry and when to continue from the previously initiated + * inquiry. This is done by passing a boolean value in the following field: + * startNewInquiry + * + * This function returns "True" when the inquiry is completed, and it returns "False" otherwise. + */

        bool inquiryAllBTDevices(tileDevice *tilesDetectedPtr[],
                                 uint8_t     array_size,
                                 uint8_t    *deviceDetectedCount,
                                 bool        startNewInquiry);

+ /* + * inquirySingleBTDevice + * + * Inquiries for a single Bluetooth device + * + * This is a non-blocking function to inquiry for a specific device. Since this + * function is non-blocking, Bluetooth inquiry will span multiple function calls. In other words, + * the caller may have to keep calling this function until inquiry is done to retrieve information + * of a specific device. + * + * The caller must tell when to start a new inquiry and when to continue from the previously initiated + * inquiry. This is done by passing a boolean value in the following field: + * startNewInquiry + * + * This functions returns "True" when the inquiry is completed, and it returns "False" otherwise. + * + * "found" indicates whether the device was found or not. If found, the information of this device + * will be copied to "tilePtr" + */ + bool inquirySingleBTDevice(const char *macAddress, + tileDevice *tilePtr, + bool *found, + bool startNewInquiry); + /* + * cancelBTInquiry + * + * Cancels Bluetooth inquiry + * + * The RN42 Bluetooth device doesn't support cancellation of an inquiry. This function is only used + * to cleanup internal state. + */

        void cancelBTInquiry(void);
};

diff --git a/L5_Application/assetManagement/src/assetManagement.cpp b/L5_Application/assetManagement/src/assetManagement.cpp index 5a2009a..be66239 100644 --- a/L5_Application/assetManagement/src/assetManagement.cpp +++ b/L5_Application/assetManagement/src/assetManagement.cpp @@ -40,6 +40,11 @@ void LCD::display(const char *data[],

    uint8_t     dataStrLen;
    uint8_t     maxRowLen = (displaySelectionMarker) ? maxOptionLength : maxOptionLength + selectionMarkerLen;

+ if (0 == dataSize) { + LCD::getInstance().clearScreen(); + printToLCD("Empty"); + return; + }

    if (emulationMode()) {
        // Simulated LCD Header
        if (dataSelectedIdx == 0) {

@@ -200,7 +205,7 @@ void Bluetooth::goToCmdMode()

    const char     *expectedStr = "Roving Networks";
    const uint8_t   maxAttempts = 10;
    uint8_t         attempts = 0;

- bool debug = true; + bool debug = false;

    if (debug) {
        printf("%s - Enter\n", __FUNCTION__);

@@ -399,6 +404,15 @@ void tileDevice::print()

           getTileName(), getBTName(), getMac(), getRSSI(), getCOD());
}

+void tileDevice::operator=(tileDevice &from) +{ + this->setBTName(from.getBTName()); + this->setCOD(from.getCOD()); + this->setMac(from.getMac()); + this->setRSSI(from.getRSSI()); + this->setTileName(from.getTileName()); +} +

void tileDevice::setString(char *to, const char *from, uint32_t size)
{
    if (0 == from) {

@@ -419,7 +433,7 @@ bool assetManagementTask::inquiryAllBTDevices(

        uint8_t     *deviceDetectedCount,
        bool         startNewInquiry)
{

- static bool debug = true; + static bool debug = false;

    enum {
        BT_INQ_BEGIN,
        BT_INQ_PENDING_TITLE,

@@ -525,6 +539,29 @@ bool assetManagementTask::inquiryAllBTDevices(

    return (BTInquiryInProcess == false);
}

+bool assetManagementTask::inquirySingleBTDevice(const char *macAddress, + tileDevice *tilePtr, + bool *found, + bool startNewInquiry) +{ + static tileDevice *tilesDetectedPtr[maxTileDevices]; + static uint8_t deviceDetectedCount; + bool inquiryDone; + + *found = false; + inquiryDone = inquiryAllBTDevices(tilesDetectedPtr, maxTileDevices, &deviceDetectedCount, startNewInquiry); + if (inquiryDone) { + for (uint8_t i = 0; i < deviceDetectedCount; i++) { + if (!strncmp(tilesDetectedPtr[i]->getMac(), macAddress, strlen(macAddress))) { + *tilePtr = *tilesDetectedPtr[i]; + *found = true; + } + } + return (true); + } + return (false); +} +

void assetManagementTask::storeRegisteredDevices()
{
    uint32_t                    writeOffset = storageFileHeaderOffset;

-- 1.8.5.2.msysgit.0


From 465fe27d3467e1c4568e879136aea68dd6c84774 Mon Sep 17 00:00:00 2001 From: Pardeep <p_badhan2004@yahoo.com> Date: Sun, 4 May 2014 10:57:30 -0700 Subject: [PATCH 14/23] Displaying more info in "List" menu

Displaying 1) Tile Name, 2) Bluetooth Name, and 3) MAC address ---

.../assetManagement/src/assetManagement.cpp        | 30 ++++++++++++++++++----
1 file changed, 25 insertions(+), 5 deletions(-)

diff --git a/L5_Application/assetManagement/src/assetManagement.cpp b/L5_Application/assetManagement/src/assetManagement.cpp index be66239..8a1c7ee 100644 --- a/L5_Application/assetManagement/src/assetManagement.cpp +++ b/L5_Application/assetManagement/src/assetManagement.cpp @@ -651,13 +651,24 @@ assetManagementTask::userMenuType_t assetManagementTask::listTileMenuHandleActio

        userMenuAction_t action)
{
    static uint8_t       selectedOpt = 0;

- const char *tileIdentifiers[maxTileDevices];

    userMenuType_t       newMenu = USER_MENU_TYPE_LIST_TILE;

+ const char *tilesInfoStr[maxTileDevices * 10]; + uint8_t tileInfoStrCount = 0; + const char *spaces = " "; + + for (uint8_t i = 0; i < registeredTileDeviceCount; i++) { + if (0 != i) { + tilesInfoStr[tileInfoStrCount++] = spaces; + } + tilesInfoStr[tileInfoStrCount++] = registeredTileDevice[i]->getTileName(); + tilesInfoStr[tileInfoStrCount++] = registeredTileDevice[i]->getBTName(); + tilesInfoStr[tileInfoStrCount++] = registeredTileDevice[i]->getMac(); + }

    switch (action) {
        case USER_MENU_ACTION_SCROLL_DOWN:
        {

- if (selectedOpt < (registeredTileDeviceCount - 1)) { + if (selectedOpt < (tileInfoStrCount - 1)) {

                selectedOpt++;
            }
            break;

@@ -681,8 +692,8 @@ assetManagementTask::userMenuType_t assetManagementTask::listTileMenuHandleActio

        default:
            break;
    }

- getTileIdentifier(tileIdentifiers, registeredTileDevice, registeredTileDeviceCount); - LCD::getInstance().display(tileIdentifiers, registeredTileDeviceCount, selectedOpt, true); + + LCD::getInstance().display(tilesInfoStr, tileInfoStrCount, selectedOpt, true);

    return (newMenu);
}

@@ -1014,6 +1025,7 @@ assetManagementTask::assetManagementTask(uint8_t priority) :

    const uint8_t               filePathLen = 100;
    uint8_t                     readOffset = storageFileHeaderOffset;
    tileStorageFileHeader_s     fileHeader;

+ bool debug = true;

    setRunDuration(10);
    LCD::getInstance().clearScreen();

@@ -1047,10 +1059,18 @@ assetManagementTask::assetManagementTask(uint8_t priority) :

    }
    readOffset += sizeof(fileHeader);

+ if (debug) { + printf("[%lu] devices read from flash\n", storageFileHeader.tilesStoredCount); + }

    for (uint8_t i = 0; i < storageFileHeader.tilesStoredCount; i++) {
        registeredTileDevice[i] = new tileDevice();
        readOffset += registeredTileDevice[i]->readFromFile(storageFileName, readOffset);

- registeredTileDevice[i]->print(); + if (debug) { + registeredTileDevice[i]->print(); + } + } + if (debug) { + printf("Read END\n");

    }
    userMenuUpdate(USER_MENU_ACTION_DISPLAY);
}

-- 1.8.5.2.msysgit.0


From 98705a9191ae41dcbd61c5b21f7bdf9e61a407d2 Mon Sep 17 00:00:00 2001 From: Akash <akash@hairynandgate.com> Date: Tue, 6 May 2014 22:57:47 -0700 Subject: [PATCH 15/23] Re-enable Tracking Feature

Changed entry into tracking feature from listTile... to selectTile.

The selectTile... function makes use of registredTileDevice shared data structure. Additionally, it uses the new (simplified) logic for determining if the displayed list is at top or is at end; with updated re-initialization on back press/action.

Minimal edits to trackTile... function to bring it into an operational state. However, this function needs to be updated to use latest APIs and data structures. ---

L5_Application/assetManagement/assetManagement.hpp |  6 +-
.../assetManagement/src/assetManagement.cpp        | 73 ++++++----------------
2 files changed, 24 insertions(+), 55 deletions(-)

diff --git a/L5_Application/assetManagement/assetManagement.hpp b/L5_Application/assetManagement/assetManagement.hpp index 5261a14..ff6aa5c 100644 --- a/L5_Application/assetManagement/assetManagement.hpp +++ b/L5_Application/assetManagement/assetManagement.hpp @@ -172,8 +172,9 @@ class assetManagementTask : public scheduler_task

            USER_MENU_TYPE_MAIN,
            USER_MENU_TYPE_TRACK_TILE,
            USER_MENU_TYPE_ADD_TILE,

- USER_MENU_TYPE_REMOVE_TILE, // unused + USER_MENU_TYPE_REMOVE_TILE,

            USER_MENU_TYPE_LIST_TILE,

+ USER_MENU_TYPE_SELECT_TILE, // entry into track

        } userMenuType_t;

        tileDevice                 *registeredTileDevice[maxTileDevices];

@@ -192,6 +193,7 @@ class assetManagementTask : public scheduler_task

        assetManagementTask::userMenuType_t addTileMenuHandleAction(userMenuAction_t action);
        assetManagementTask::userMenuType_t removeTileMenuHandleAction(userMenuAction_t action);
        assetManagementTask::userMenuType_t listTileMenuHandleAction(userMenuAction_t action);

+ assetManagementTask::userMenuType_t selectTileMenuHandleAction(userMenuAction_t action);

        assetManagementTask::userMenuType_t trackTileMenuHandleAction(userMenuAction_t action);

        /*

@@ -294,7 +296,7 @@ static const char *BTINQNames[] = {

        enum2Str(BT_INQ_DONE),
};

-static char tileSelectedForTracking[ deviceNameMaxLen ]; +static tileDevice *tileSelectedForTracking;

static bool tracking_mode = false;


diff --git a/L5_Application/assetManagement/src/assetManagement.cpp b/L5_Application/assetManagement/src/assetManagement.cpp index 677167c..31f891a 100644 --- a/L5_Application/assetManagement/src/assetManagement.cpp +++ b/L5_Application/assetManagement/src/assetManagement.cpp @@ -862,33 +862,26 @@ assetManagementTask::userMenuType_t assetManagementTask::addTileMenuHandleAction

    return (newMenu);
}

-#if 0 -assetManagementTask::userMenuType_t assetManagementTask::listTileMenuHandleAction( +assetManagementTask::userMenuType_t assetManagementTask::selectTileMenuHandleAction(

        userMenuAction_t action)
{

- userMenuType_t newMenu = USER_MENU_TYPE_LIST_TILE; + userMenuType_t newMenu = USER_MENU_TYPE_SELECT_TILE;

    const int32_t   displayDuration = 2000; // 2 seconds

+ const char *tileIdentifiers[maxTileDevices];

    /* Variables that need to be reset
     * on function exit.
     */
    static uint8_t  selectedTile            = 0;

- static bool top_of_list = false; - static bool end_of_list = false;

    static bool     display_instructions    = true;

- /* TODO: Use real data to get list - * of registered tiles. - */ - char *registeredTiles[] = { "889FFAF03BB3", "ubuntu-0" }; - int32_t numberOfTiles = sizeof(registeredTiles) / sizeof(char *);

    if (debug) {

- printf( "%s - Number of registered tiles: %i\n", __FUNCTION__, numberOfTiles); + printf( "%s - Number of registered tiles: %i\n", __FUNCTION__, registeredTileDeviceCount);

    }

    // fail fast

- if (0 == numberOfTiles) { + if (0 == registeredTileDeviceCount) {

        const char *oops[] = { "ERR: No Tiles" };
        int32_t numOfMsgs = sizeof(oops) / sizeof(char *);

@@ -919,18 +912,9 @@ assetManagementTask::userMenuType_t assetManagementTask::listTileMenuHandleActio

    switch (action) {
        case USER_MENU_ACTION_SCROLL_DOWN:
        {

- if (selectedTile < (numberOfTiles - 1)) { + if (selectedTile < (registeredTileDeviceCount - 1)) {

                selectedTile++;
            }

- else if ( !top_of_list ) { - end_of_list = true; - } - - if (top_of_list) { - selectedTile = 0; - } - - top_of_list = false;

            break;
        }
        case USER_MENU_ACTION_SCROLL_UP:

@@ -938,33 +922,24 @@ assetManagementTask::userMenuType_t assetManagementTask::listTileMenuHandleActio

            if (selectedTile > 0) {
                selectedTile--;
            }

- else if ( !end_of_list ) { - top_of_list = true; - } - - if (end_of_list) { - selectedTile = numberOfTiles - 1; - } - - end_of_list = false;

            break;
        }
        case USER_MENU_ACTION_SELECT:
        {

- strcpy( tileSelectedForTracking, registeredTiles[ selectedTile ] ); + tileSelectedForTracking = registeredTileDevice[selectedTile];

            if (debug) {

- printf("%s - Selected Tile: %s\n", __FUNCTION__, tileSelectedForTracking); + printf("%s - Selected Tile: %s\n", __FUNCTION__, tileSelectedForTracking->getTileIdentifier()); + printf("%s - Selected Tile MAC: %s\n", __FUNCTION__, tileSelectedForTracking->getMac());

            }

            newMenu = USER_MENU_TYPE_TRACK_TILE;

+

            break;
        }
        case USER_MENU_ACTION_BACK:
        {
            // reset variables to original state
            selectedTile            = 0;

- top_of_list = false; - end_of_list = false;

            display_instructions    = true;

            newMenu = USER_MENU_TYPE_MAIN;

@@ -976,25 +951,21 @@ assetManagementTask::userMenuType_t assetManagementTask::listTileMenuHandleActio

        }
    }

- if (end_of_list) { - LCD::getInstance().display("(End of List)"); - } - else if (top_of_list) { - LCD::getInstance().display("(Top of List)"); - } - else if ( 0 != numberOfTiles ) { - LCD::getInstance().display( (const char **)registeredTiles, (uint8_t)numberOfTiles, selectedTile, true ); + if ( 0 != registeredTileDeviceCount ) { + getTileIdentifier(tileIdentifiers, registeredTileDevice, registeredTileDeviceCount); + LCD::getInstance().display( tileIdentifiers, registeredTileDeviceCount, selectedTile, true );

    }

    return( newMenu );
}

-#endif

assetManagementTask::userMenuType_t assetManagementTask::trackTileMenuHandleAction(
        userMenuAction_t action)
{
    userMenuType_t  newMenu     = USER_MENU_TYPE_TRACK_TILE;

+ const char *tileIdentifiers[maxTileDevices]; +

    static tileDevice   *tilesDetectedPtr[maxTileDevices];
    static uint8_t      tilesDetectedCount = 0;

@@ -1023,7 +994,7 @@ assetManagementTask::userMenuType_t assetManagementTask::trackTileMenuHandleActi

        }
        case USER_MENU_ACTION_BACK:
        {

- newMenu = USER_MENU_TYPE_LIST_TILE; + newMenu = USER_MENU_TYPE_SELECT_TILE;

            tracking_mode = false;
            break;
        }

@@ -1084,17 +1055,12 @@ assetManagementTask::userMenuType_t assetManagementTask::trackTileMenuHandleActi

           char histogramTitle[  deviceNameMaxLen ];
           char histogram[       deviceNameMaxLen ];

- /* TODO: Get selected tile's - * MAC address. - */ - //strncpy( selectedTileMAC, registeredTiles[ selectedTile ], sizeof(selectedTileMAC)); - strncpy( selectedTileMAC, tileSelectedForTracking, sizeof(selectedTileMAC)); + strncpy( selectedTileMAC, tileSelectedForTracking->getMac(), sizeof(selectedTileMAC));

           if (debug) {
               printf( "%s - Selected Tile MAC: %s\n", __FUNCTION__, selectedTileMAC );
           }

- /* TODO: Use tile's name instead of selected MAC */ - strcpy( histogramTitle, selectedTileMAC ); + strcpy( histogramTitle, tileSelectedForTracking->getTileIdentifier() );

           size_t index;
           for (index = 0; index < tilesDetectedCount; ++index) {

@@ -1174,7 +1140,7 @@ assetManagementTask::userMenuType_t assetManagementTask::mainMenuHandleAction(

        case USER_MENU_ACTION_SELECT:
            switch (selectedOpt) {
                // case 0:  newMenu = USER_MENU_TYPE_TRACK_TILE;  break;

- case 0: newMenu = USER_MENU_TYPE_LIST_TILE; break; + case 0: newMenu = USER_MENU_TYPE_SELECT_TILE; break;

                case 1:  newMenu = USER_MENU_TYPE_ADD_TILE;    break;
                case 2:  newMenu = USER_MENU_TYPE_REMOVE_TILE; break;
                case 3:  newMenu = USER_MENU_TYPE_LIST_TILE;   break;

@@ -1210,6 +1176,7 @@ void assetManagementTask::userMenuUpdate(assetManagementTask::userMenuAction_t a

            case USER_MENU_TYPE_ADD_TILE:   nextMenu = addTileMenuHandleAction(action); break;
            case USER_MENU_TYPE_REMOVE_TILE: nextMenu = removeTileMenuHandleAction(action); break;
            case USER_MENU_TYPE_LIST_TILE:  nextMenu = listTileMenuHandleAction(action); break;

+ case USER_MENU_TYPE_SELECT_TILE: nextMenu = selectTileMenuHandleAction(action); break;

            case USER_MENU_TYPE_TRACK_TILE: nextMenu = trackTileMenuHandleAction(action); break;
            default:                       break;
        }

-- 1.8.5.2.msysgit.0


From b0c8f1195f6d7753de217bafdc2c6829cc595eff Mon Sep 17 00:00:00 2001 From: Akash <akash@hairynandgate.com> Date: Thu, 8 May 2014 03:51:04 -0700 Subject: [PATCH 16/23] Refactored trackTile Function

trackTile... function has been refactored to maintain historical behavior, but now invokes inquirySingleBTDevice API.

The inquiryAllBTDevices function signature was modified to include an optional argument to display the "Searching..." message. This message is not desirable when displaying a histogram in a loop. In any case, the inquiryAllBTDevices API remains backward compatible.

Note: In testing, unexpected behavior was observed when a tile comes into or exits the field of vision while in trackingMode. ---

L5_Application/assetManagement/assetManagement.hpp |   3 +-
.../assetManagement/src/assetManagement.cpp        | 151 +++++++--------------
2 files changed, 49 insertions(+), 105 deletions(-)

diff --git a/L5_Application/assetManagement/assetManagement.hpp b/L5_Application/assetManagement/assetManagement.hpp index ff6aa5c..7ca544b 100644 --- a/L5_Application/assetManagement/assetManagement.hpp +++ b/L5_Application/assetManagement/assetManagement.hpp @@ -245,7 +245,8 @@ class assetManagementTask : public scheduler_task

        bool inquiryAllBTDevices(tileDevice *tilesDetectedPtr[],
                                 uint8_t     array_size,
                                 uint8_t    *deviceDetectedCount,

- bool startNewInquiry); + bool startNewInquiry, + bool displayMsg = true);

        /*
         * inquirySingleBTDevice
         *

diff --git a/L5_Application/assetManagement/src/assetManagement.cpp b/L5_Application/assetManagement/src/assetManagement.cpp index 31f891a..f016fec 100644 --- a/L5_Application/assetManagement/src/assetManagement.cpp +++ b/L5_Application/assetManagement/src/assetManagement.cpp @@ -432,7 +432,8 @@ bool assetManagementTask::inquiryAllBTDevices(

        tileDevice  *tilesDetectedPtr[],
        uint8_t      array_size,
        uint8_t     *deviceDetectedCount,

- bool startNewInquiry) + bool startNewInquiry, + bool displayMsg)

{
    static bool          debug = false;
    enum {

@@ -460,7 +461,9 @@ bool assetManagementTask::inquiryAllBTDevices(

    if (startNewInquiry) {
        BTInquiryState = BT_INQ_DONE;
        const char *searchingStr = "Searching...";

- LCD::getInstance().display(searchingStr); + if (displayMsg) { + LCD::getInstance().display(searchingStr); + }

        for (int i = 0; i < array_size; i++) {
            if (tilesDetectedPtr[i]) {
                delete tilesDetectedPtr[i];

@@ -550,7 +553,7 @@ bool assetManagementTask::inquirySingleBTDevice(const char *macAddress,

    bool                inquiryDone;

    *found = false;

- inquiryDone = inquiryAllBTDevices(tilesDetectedPtr, maxTileDevices, &deviceDetectedCount, startNewInquiry); + inquiryDone = inquiryAllBTDevices(tilesDetectedPtr, maxTileDevices, &deviceDetectedCount, startNewInquiry, false);

    if (inquiryDone) {
        for (uint8_t i = 0; i < deviceDetectedCount; i++) {
            if (!strncmp(tilesDetectedPtr[i]->getMac(), macAddress, strlen(macAddress))) {

@@ -964,19 +967,13 @@ assetManagementTask::userMenuType_t assetManagementTask::trackTileMenuHandleActi

{
    userMenuType_t  newMenu     = USER_MENU_TYPE_TRACK_TILE;

- const char *tileIdentifiers[maxTileDevices]; - - static tileDevice *tilesDetectedPtr[maxTileDevices]; - static uint8_t tilesDetectedCount = 0; - - const int32_t displayDuration = 2000; // 2 seconds

    const char      *EOR = "-9999";         // Error: Out of Range

- for (size_t i = 0; i < tilesDetectedCount; i++) { - delete tilesDetectedPtr[i]; - tilesDetectedPtr[i] = 0; - } - tilesDetectedCount = 0; + static bool startNewInquiry = false; + static bool inquiryDone = false; + static bool foundTile = false; + + static tileDevice tile;


    switch (action) {

@@ -995,105 +992,49 @@ assetManagementTask::userMenuType_t assetManagementTask::trackTileMenuHandleActi

        case USER_MENU_ACTION_BACK:
        {
            newMenu = USER_MENU_TYPE_SELECT_TILE;

- tracking_mode = false; + tracking_mode = false; + startNewInquiry = false; + inquiryDone = false; + foundTile = false; + cancelBTInquiry();

            break;
        }
        case USER_MENU_ACTION_MENU_CHANGED:
        {
            LCD::getInstance().display("Tracking...");

- tracking_mode = true; + tracking_mode = true; + startNewInquiry = true; + inquiryDone = false; + foundTile = false;

            break;
        }
        case USER_MENU_ACTION_DISPLAY:
        {

- BTInquiryState = BT_INQ_BEGIN; - // Bluetooth::getInstance().clearPreviousBTData(); - Bluetooth::getInstance().inquiryWithRSSI(); - - while (BTInquiryState != BT_INQ_DONE) { - char BTRxData[1000]; - char *savePtr; - - if (Bluetooth::getInstance().receiveData(BTRxData, sizeof(BTRxData))) { - if (debug) { - printf("%s - BTRx=[%s]\n", __FUNCTION__, BTRxData); - } - switch (BTInquiryState) { - case BT_INQ_BEGIN: - if (strstr(BTRxData, "COD")) { - BTInquiryState = BT_INQ_PENDING_FOUND; - } - break; - case BT_INQ_PENDING_FOUND: - if (strstr(BTRxData, "Found")) { - BTInquiryState = BT_INQ_PENDING_DEVICES; - } - break; - case BT_INQ_PENDING_DEVICES: - if (strstr(BTRxData, "Inquiry Done")) { - BTInquiryState = BT_INQ_DONE; - BTInquiryInProcess = false; - } else { - char *macAddrPtr = strtok_r(BTRxData, ",", &savePtr); - char *btNamePtr = strtok_r(NULL, ",", &savePtr); - char *btCODPtr = strtok_r(NULL, ",", &savePtr); - char *btRSSIPtr = strtok_r(NULL, ",", &savePtr); - tilesDetectedPtr[tilesDetectedCount] = - new tileDevice(macAddrPtr, btNamePtr, "", btCODPtr, btRSSIPtr); - tilesDetectedCount++; - } - break; - } - if (debug) { - printf("%s - New IQState=[%s]\n", __FUNCTION__, BTINQNames[BTInquiryState]); - } - } + if (!inquiryDone) { + inquiryDone = inquirySingleBTDevice( + tileSelectedForTracking->getMac(), + &tile, + &foundTile, + startNewInquiry); + startNewInquiry = false;

            }

+ else { + if (debug) { + printf( "%s - Found Tile: %i\n", __FUNCTION__, foundTile ); + printf( "%s - Found Tile ID: %s\n", __FUNCTION__, tile.getTileIdentifier() ); + printf( "%s - Found Tile RSSI: %s\n", __FUNCTION__, tile.getRSSI() ); + }

+ char histogramTitle[ deviceNameMaxLen ]; + char histogram[ deviceNameMaxLen ];

- char selectedTileMAC[ deviceNameMaxLen ]; - char histogramTitle[ deviceNameMaxLen ]; - char histogram[ deviceNameMaxLen ]; - - strncpy( selectedTileMAC, tileSelectedForTracking->getMac(), sizeof(selectedTileMAC)); - if (debug) { - printf( "%s - Selected Tile MAC: %s\n", __FUNCTION__, selectedTileMAC ); - } - - strcpy( histogramTitle, tileSelectedForTracking->getTileIdentifier() ); - - size_t index; - for (index = 0; index < tilesDetectedCount; ++index) { - int32_t match = strcmp( selectedTileMAC, tilesDetectedPtr[index]->getMac()); - - if ( 0 == match ) { - if (debug) { - printf( "%s - Matched MACs: %s\n", __FUNCTION__, selectedTileMAC ); - printf( "%s - Tile's RSSI Value: %s\n", __FUNCTION__, tilesDetectedPtr[index]->getRSSI() ); - } - - rssi2histogram( tilesDetectedPtr[index]->getRSSI(), histogram ); - if (debug) { - printf( "%s - RSSI Histogram: %s\n", __FUNCTION__, histogram ); - } - - const char *histogramDisplay[] = { histogramTitle, histogram }; - int32_t numOfHistoLines = sizeof(histogramDisplay) / sizeof(char *); - - LCD::getInstance().display( - histogramDisplay, - numOfHistoLines, - 0, - false, - true ); - //displayDuration ); - - break; - } - } - - if (index >= tilesDetectedCount) { - rssi2histogram( EOR, histogram ); + strcpy( histogramTitle, tile.getTileIdentifier() ); + if (foundTile) { + rssi2histogram( tile.getRSSI(), histogram ); + } + else { + rssi2histogram( EOR, histogram ); + }

                const char *histogramDisplay[] = { histogramTitle, histogram };
                int32_t numOfHistoLines = sizeof(histogramDisplay) / sizeof(char *);

@@ -1104,8 +1045,12 @@ assetManagementTask::userMenuType_t assetManagementTask::trackTileMenuHandleActi

                        0,
                        false,
                        true );

- // displayDuration ); + + startNewInquiry = true; + inquiryDone = false;

            }

+ + break;

        }
        default:
        {

@@ -1113,8 +1058,6 @@ assetManagementTask::userMenuType_t assetManagementTask::trackTileMenuHandleActi

        }
    }

- -

    return( newMenu );
}

-- 1.8.5.2.msysgit.0


From 95a39081c719ac13833913baa3162c45537e7e9c Mon Sep 17 00:00:00 2001 From: Pardeep <p_badhan2004@yahoo.com> Date: Sun, 11 May 2014 06:18:29 -0700 Subject: [PATCH 17/23] Bug fixes

1. Bluetooth inquiry wasn't terminating when no devices were found. The state machine was going into PENDING_DEVICES state. 2. Remove tile was corrupting the flash why overwritting the file header. 3. Add tile option was displaying devices that were already added 4. "No registered device" error is displayed when user selects an option that requires displaying devices and no devices have been added yet. 5. Setting the error display timer to 4 seconds ---

L5_Application/assetManagement/assetManagement.hpp |  60 ++---
.../assetManagement/src/assetManagement.cpp        | 256 +++++++++++++++------
2 files changed, 213 insertions(+), 103 deletions(-)

diff --git a/L5_Application/assetManagement/assetManagement.hpp b/L5_Application/assetManagement/assetManagement.hpp index 7ca544b..f4e9045 100644 --- a/L5_Application/assetManagement/assetManagement.hpp +++ b/L5_Application/assetManagement/assetManagement.hpp @@ -23,6 +23,7 @@ const bool debug = true;

class LCD : public SingletonTemplate<LCD>
{
    public:

+ static const uint32_t defaultHelpStrTime = 4000; /* 4 seconds */

        void display(const char *data[],
                     uint8_t     dataSize,
                     uint8_t     dataSelectedIdx,

@@ -107,15 +108,16 @@ class tileDevice {

        uint32_t writeToFile(const char *fileName, uint8_t offset);
        uint8_t readFromFile(const char *fileName, uint8_t offset);

- const char *getMac(); - const char *getRSSI(); - const char *getBTName(); - const char *getTileName(); - const char *getTileIdentifier(); - const char *getCOD(); + const char *getMac() const; + const char *getRSSI() const; + const char *getBTName() const; + const char *getTileName() const; + const char *getTileIdentifier() const; + const char *getCOD() const;

        void        print();

- void operator=(tileDevice &from); + void operator=(const tileDevice &from); + bool operator==(const tileDevice &compareTo);

    private:
        static const uint8_t BTMACAddrLen   = 12;

@@ -153,8 +155,6 @@ class assetManagementTask : public scheduler_task

    private:
#define enum2Str(id) (#id)

- static const uint8_t maxTileDevices = 10; - bool BTInquiryInProcess;

        typedef struct tileStorageFileHeader_s {
            uint32_t    tilesStoredCount;

@@ -177,8 +177,12 @@ class assetManagementTask : public scheduler_task

            USER_MENU_TYPE_SELECT_TILE,     // entry into track
        } userMenuType_t;

+ static const uint8_t maxTileDevices = 10; + bool BTInquiryInProcess;

        tileDevice                 *registeredTileDevice[maxTileDevices];
        uint32_t                    registeredTileDeviceCount;

+ tileDevice *tileSelectedForTracking; + bool tracking_mode;

        char                       *storageFileName;
        tileStorageFileHeader_t     storageFileHeader;
        static const uint32_t       storageFileHeaderOffset = 3;

@@ -189,13 +193,14 @@ class assetManagementTask : public scheduler_task

        const char *getMenuActionName(userMenuAction_t action);
        void userMenuUpdate(userMenuAction_t action);
        const char *getMenuTypeName(userMenuType_t type);

- assetManagementTask::userMenuType_t mainMenuHandleAction(userMenuAction_t action); - assetManagementTask::userMenuType_t addTileMenuHandleAction(userMenuAction_t action); - assetManagementTask::userMenuType_t removeTileMenuHandleAction(userMenuAction_t action); - assetManagementTask::userMenuType_t listTileMenuHandleAction(userMenuAction_t action); - assetManagementTask::userMenuType_t selectTileMenuHandleAction(userMenuAction_t action); - assetManagementTask::userMenuType_t trackTileMenuHandleAction(userMenuAction_t action); - + userMenuType_t mainMenuHandleAction(userMenuAction_t action); + userMenuType_t addTileMenuHandleAction(userMenuAction_t action); + userMenuType_t removeTileMenuHandleAction(userMenuAction_t action); + userMenuType_t listTileMenuHandleAction(userMenuAction_t action); + userMenuType_t selectTileMenuHandleAction(userMenuAction_t action); + userMenuType_t trackTileMenuHandleAction(userMenuAction_t action); + void updateRegisteredTileDevices(tileDevice *tilePtr, bool add); + bool isTileAlreadyRegistered(const tileDevice *tilePtr, uint8_t *location = NULL);

        /*
         * getStringFromUser
         *

@@ -246,7 +251,8 @@ class assetManagementTask : public scheduler_task

                                 uint8_t     array_size,
                                 uint8_t    *deviceDetectedCount,
                                 bool        startNewInquiry,

- bool displayMsg = true); + bool displayMsg = true, + bool ignoreRegisteredTiles = false);

        /*
         * inquirySingleBTDevice
         *

@@ -281,26 +287,6 @@ class assetManagementTask : public scheduler_task

        void cancelBTInquiry(void);
};

-enum { - BT_INQ_BEGIN, - BT_INQ_PENDING_TITLE, - BT_INQ_PENDING_FOUND, - BT_INQ_PENDING_DEVICES, - BT_INQ_DONE, -}; -static uint8_t BTInquiryState = BT_INQ_DONE; -static const char *BTINQNames[] = { - enum2Str(BT_INQ_BEGIN), - enum2Str(BT_INQ_PENDING_TITLE), - enum2Str(BT_INQ_PENDING_FOUND), - enum2Str(BT_INQ_PENDING_DEVICES), - enum2Str(BT_INQ_DONE), -}; - -static tileDevice *tileSelectedForTracking; -static bool tracking_mode = false; - -

void rssi2histogram( const char *rssi, char *histogram );

#endif /* ASSETMANAGEMENT_HPP_ */

diff --git a/L5_Application/assetManagement/src/assetManagement.cpp b/L5_Application/assetManagement/src/assetManagement.cpp index f016fec..456482d 100644 --- a/L5_Application/assetManagement/src/assetManagement.cpp +++ b/L5_Application/assetManagement/src/assetManagement.cpp @@ -376,11 +376,11 @@ uint8_t tileDevice::readFromFile(const char *fileName, uint8_t offset)

    return (sizeof(tileStorageInfo_t));
}

-const char *tileDevice::getMac() { return mac; } -const char *tileDevice::getRSSI() { return rssi; } -const char *tileDevice::getBTName() { return btName; } -const char *tileDevice::getTileName() { return tileName; } -const char *tileDevice::getCOD() { return cod; } +const char *tileDevice::getMac() const { return mac; } +const char *tileDevice::getRSSI() const { return rssi; } +const char *tileDevice::getBTName() const { return btName; } +const char *tileDevice::getTileName() const { return tileName; } +const char *tileDevice::getCOD() const { return cod; }

/*
 * Returns the first non null pointer in the following order:

@@ -388,7 +388,7 @@ const char *tileDevice::getCOD() { return cod; }

 *     2. Bluetooth Name
 *     3. MAC Address
 */

-const char *tileDevice::getTileIdentifier() +const char *tileDevice::getTileIdentifier() const

{
    if (0 != tileName[0]) {
        return (tileName);

@@ -405,7 +405,7 @@ void tileDevice::print()

           getTileName(), getBTName(), getMac(), getRSSI(), getCOD());
}

-void tileDevice::operator=(tileDevice &from) +void tileDevice::operator=(const tileDevice &from)

{
    this->setBTName(from.getBTName());
    this->setCOD(from.getCOD());

@@ -414,6 +414,11 @@ void tileDevice::operator=(tileDevice &from)

    this->setTileName(from.getTileName());
}

+bool tileDevice::operator==(const tileDevice &compareTo) +{ + return (0 == strncmp(this->getMac(), compareTo.getMac(), BTMACAddrLen)); +} +

void tileDevice::setString(char *to, const char *from, uint32_t size)
{
    if (0 == from) {

@@ -433,7 +438,8 @@ bool assetManagementTask::inquiryAllBTDevices(

        uint8_t      array_size,
        uint8_t     *deviceDetectedCount,
        bool         startNewInquiry,

- bool displayMsg) + bool displayMsg, + bool ignoreRegisteredTiles)

{
    static bool          debug = false;
    enum {

@@ -450,8 +456,8 @@ bool assetManagementTask::inquiryAllBTDevices(

            enum2Str(BT_INQ_PENDING_TITLE),
            enum2Str(BT_INQ_PENDING_FOUND),
            enum2Str(BT_INQ_PENDING_DEVICES),

- enum2Str(BT_INQ_DONE),

            enum2Str(BT_INQ_MULTIPLE_INQUIRY_ATTEMPT),

+ enum2Str(BT_INQ_DONE),

    };

    if (debug) {

@@ -498,7 +504,10 @@ bool assetManagementTask::inquiryAllBTDevices(

                }
                case BT_INQ_PENDING_FOUND:
                {

- if (strstr(BTRxData, "Found")) { + if (strstr(BTRxData, "No Devices Found")) { + BTInquiryState = BT_INQ_DONE; + BTInquiryInProcess = false; + } else if (strstr(BTRxData, "Found")) {

                        BTInquiryState = BT_INQ_PENDING_DEVICES;
                    }
                    break;

@@ -515,7 +524,12 @@ bool assetManagementTask::inquiryAllBTDevices(

                        char *btRSSIPtr  = strtok_r(NULL, ",", &savePtr);
                        tilesDetectedPtr[*deviceDetectedCount] =
                                new tileDevice(macAddrPtr, btNamePtr, 0, btCODPtr, btRSSIPtr);

- (*deviceDetectedCount)++; + if (ignoreRegisteredTiles && isTileAlreadyRegistered(tilesDetectedPtr[*deviceDetectedCount])) { + delete tilesDetectedPtr[*deviceDetectedCount]; + tilesDetectedPtr[*deviceDetectedCount] = NULL; + } else { + (*deviceDetectedCount)++; + }

                    }
                    break;
                }

@@ -568,7 +582,7 @@ bool assetManagementTask::inquirySingleBTDevice(const char *macAddress,

void assetManagementTask::storeRegisteredDevices()
{

- uint32_t writeOffset = storageFileHeaderOffset; + uint32_t writeOffset = storageFileHeaderOffset + sizeof(tileStorageFileHeader_s);

    tileStorageFileHeader_s     newFileHeader;
    for (uint8_t i = 0; i < maxTileDevices; i++) {
        if (registeredTileDevice[i]) {

@@ -578,6 +592,7 @@ void assetManagementTask::storeRegisteredDevices()

    newFileHeader.tilesStoredCount = registeredTileDeviceCount;
    newFileHeader.writeOffset = writeOffset;

+ storageFileHeader = newFileHeader;

    if (FR_OK != Storage::append(storageFileName,
                                 &newFileHeader,
                                 sizeof(newFileHeader),

@@ -595,7 +610,7 @@ void assetManagementTask::getTileIdentifier(const char *names[], tileDevice *til

bool assetManagementTask::getStringFromUser(char *buffer, uint8_t bufferSize)
{

- const char *options = "Done 0123456789ABCDEFGHIJKLMNOPQRST !@#$%^&*()-=_+"; + const char *options = "Done ABCDEFGHIJKLMNOPQRST 0123456789!@#$%^&*()-=_+";

    const uint8_t           optionsLen     = strlen(options);
    const uint8_t           optionOffset   = sizeof("Done") - 1;
    uint8_t                 optionSelected = 0;

@@ -661,6 +676,13 @@ assetManagementTask::userMenuType_t assetManagementTask::listTileMenuHandleActio

    uint8_t              tileInfoStrCount = 0;
    const char          *spaces = "  ";

+ /* fail fast */ + if (0 == registeredTileDeviceCount) { + const char *noDevicesStr[] = {"No registered", "devices"}; + LCD::getInstance().display(noDevicesStr, 2, selectedOpt, false, true, LCD::defaultHelpStrTime); + return (USER_MENU_TYPE_MAIN); + } +

    for (uint8_t i = 0; i < registeredTileDeviceCount; i++) {
        if (0 != i) {
            tilesInfoStr[tileInfoStrCount++] = spaces;

@@ -703,13 +725,117 @@ assetManagementTask::userMenuType_t assetManagementTask::listTileMenuHandleActio

    return (newMenu);
}

+bool assetManagementTask::isTileAlreadyRegistered(const tileDevice *tilePtr, uint8_t *location) +{ + if (0 == registeredTileDeviceCount) { + return (false); + } + for (int i = 0; i < maxTileDevices; i++) { + if ((NULL != registeredTileDevice[i]) && (*registeredTileDevice[i] == *tilePtr)) { + if (location) { + *location = i; + } + return (true); + } + } + return (false); +} + +void assetManagementTask::updateRegisteredTileDevices(tileDevice *tilePtr, bool add) +{ + char tileIdentifier[deviceNameMaxLen]; + + snprintf(tileIdentifier, deviceNameMaxLen, "%s", tilePtr->getTileIdentifier()); + + if (add) { + uint8_t emptyLocation = maxTileDevices; + + if (isTileAlreadyRegistered(tilePtr)) { + const char *err[] = {"Device", "already added"}; + LCD::getInstance().display(err, 2, 0, false, true, LCD::defaultHelpStrTime); + return; + } + /* Find an empty location in the registeredTileDevice array */ + for (int i = 0; i < maxTileDevices; i++) { + if (NULL == registeredTileDevice[i]) { + emptyLocation = i; + break; + } + } + if (maxTileDevices == emptyLocation) { + const char *err[] = {"Max devices", "already added"}; + LCD::getInstance().display(err, 2, 0, false, true, LCD::defaultHelpStrTime); + return; + } else { + const char *deviceAddedStr[2]; + uint32_t bytesWritten; + + bytesWritten = tilePtr->writeToFile(storageFileName, storageFileHeader.writeOffset); + const char *flashWriteErr[] = {"Write to", "flash failed"}; + if (0 == bytesWritten) { + LCD::getInstance().display(flashWriteErr, 2, 0, false, true, LCD::defaultHelpStrTime); + return; + } else { + /* + * If the tile information was successfully stored the file, + * update the storageFileHeader with new total number of devices + * and write offset + */ + registeredTileDevice[emptyLocation] = + new tileDevice( + tilePtr->getMac(), + tilePtr->getBTName(), + tilePtr->getTileName(), + tilePtr->getCOD(), + tilePtr->getRSSI()); + registeredTileDeviceCount++; + storageFileHeader.tilesStoredCount++; + storageFileHeader.writeOffset += bytesWritten; + FRESULT rc = Storage::append(storageFileName, + &storageFileHeader, + sizeof(storageFileHeader), + storageFileHeaderOffset); + if (FR_OK != rc) { + LCD::getInstance().display(flashWriteErr, 2, 0, false, true, LCD::defaultHelpStrTime); + } + } + + /* Inform the user about the device that was added */ + deviceAddedStr[0] = "Device added:"; + deviceAddedStr[1] = tileIdentifier; + LCD::getInstance().display(deviceAddedStr, 2, 0, false, false, LCD::defaultHelpStrTime); + } + } else { + uint8_t location; + if (true == isTileAlreadyRegistered(tilePtr, &location)) { + delete registeredTileDevice[location]; + registeredTileDevice[location] = NULL; + registeredTileDeviceCount--; + storeRegisteredDevices(); + + /* Inform the user about the device that was removed */ + const char *deviceRemovedStr[2]; + deviceRemovedStr[0] = "Device removed:"; + deviceRemovedStr[1] = tileIdentifier; + LCD::getInstance().display(deviceRemovedStr, 2, 0, false, false, LCD::defaultHelpStrTime); + } + } +} +

assetManagementTask::userMenuType_t assetManagementTask::removeTileMenuHandleAction(
        userMenuAction_t action)
{
    static uint8_t       selectedOpt = 0;

- userMenuType_t newMenu = USER_MENU_TYPE_MAIN; + userMenuType_t newMenu = USER_MENU_TYPE_REMOVE_TILE;

    const char          *tileIdentifiers[maxTileDevices];

+ /* fail fast */ + if (0 == registeredTileDeviceCount) { + const char *noDevicesStr[] = {"No registered", "devices"}; + LCD::getInstance().display(noDevicesStr, 2, selectedOpt, false, true, LCD::defaultHelpStrTime); + return (USER_MENU_TYPE_MAIN); + } +

    switch (action) {
        case USER_MENU_ACTION_SCROLL_DOWN:
        {

@@ -728,11 +854,9 @@ assetManagementTask::userMenuType_t assetManagementTask::removeTileMenuHandleAct

        case USER_MENU_ACTION_SELECT:
        {
            if (registeredTileDevice[selectedOpt]) {

- delete registeredTileDevice[selectedOpt]; - registeredTileDevice[selectedOpt] = 0; - registeredTileDeviceCount--; - storeRegisteredDevices(); + updateRegisteredTileDevices(registeredTileDevice[selectedOpt], false);

            }

+ newMenu = USER_MENU_TYPE_MAIN;

            break;
        }
        case USER_MENU_ACTION_BACK:

@@ -756,9 +880,8 @@ assetManagementTask::userMenuType_t assetManagementTask::addTileMenuHandleAction

    static tileDevice   *tilesDetectedPtr[maxTileDevices] = {0};
    static uint8_t       tilesDetectedCount = 0;
    userMenuType_t       newMenu = USER_MENU_TYPE_ADD_TILE;

- static bool debug = true; - bool startNewInquiry = false;

    static bool          inquiryDone;

+ bool startNewInquiry = false;

    switch (action) {
        case USER_MENU_ACTION_SCROLL_DOWN:

@@ -780,17 +903,15 @@ assetManagementTask::userMenuType_t assetManagementTask::addTileMenuHandleAction

            if (tilesDetectedCount == 0) {
                break;
            }

- const char *helpStr[] = {"Pick name. Select", "Done to finish"}; + const char *helpStr[] = {"Pick name. Click", "Done to finish"};

            const char             *confirmStr[2];

- const char *deviceAddedStr[2];

            char                    deviceName[deviceNameMaxLen];
            bool                    deviceNameConfirmed = false;
            switchTask::switchID_t  sw;

- uint32_t helpStrDisplayTime = 4000; /* 4 seconds */ - uint32_t bytesWritten;

- LCD::getInstance().display(helpStr, 2, 0, false, false, helpStrDisplayTime); + LCD::getInstance().display(helpStr, 2, 0, false, false, LCD::defaultHelpStrTime);

            do {

+ /* Allow the user to store tile name */

                if (getStringFromUser(deviceName, sizeof(deviceName))) {
                } else {
                    strncpy(deviceName,

@@ -805,31 +926,9 @@ assetManagementTask::userMenuType_t assetManagementTask::addTileMenuHandleAction

                    deviceNameConfirmed = true;
                }
            } while (!deviceNameConfirmed);

- deviceAddedStr[0] = "Device added:"; - deviceAddedStr[1] = deviceName; - LCD::getInstance().display(deviceAddedStr, 2, 0, false, false, helpStrDisplayTime); + /* Set the tile name that the user had entered */

            tilesDetectedPtr[selectedOpt]->setTileName(deviceName);

- bytesWritten = tilesDetectedPtr[selectedOpt]->writeToFile(storageFileName, - storageFileHeader.writeOffset); - const char *flashWriteErr[] = {"Write to", "flash failed"}; - if (0 == bytesWritten) { - LCD::getInstance().display(flashWriteErr, 2, 0, false, true, 4000); - } else { - storageFileHeader.tilesStoredCount++; - storageFileHeader.writeOffset += bytesWritten; - FRESULT rc = Storage::append(storageFileName, - &storageFileHeader, - sizeof(storageFileHeader), - storageFileHeaderOffset); - if (FR_OK != rc) { - LCD::getInstance().display(flashWriteErr, 2, 0, false, true, 4000); - } - } - - if (debug) { - printf("%s - %s [%s]\n", __FUNCTION__, deviceAddedStr[0], deviceAddedStr[1]); - } - + updateRegisteredTileDevices(tilesDetectedPtr[selectedOpt], true);

            newMenu = USER_MENU_TYPE_MAIN;
            break;
        }

@@ -852,15 +951,25 @@ assetManagementTask::userMenuType_t assetManagementTask::addTileMenuHandleAction

    }

    if (false == inquiryDone) {

+ /* Inquiry BT devices */

        inquiryDone = inquiryAllBTDevices(tilesDetectedPtr,
                                          maxTileDevices,
                                          &tilesDetectedCount,

- startNewInquiry); + startNewInquiry, + true, + true);

    }

- if (inquiryDone && (tilesDetectedCount > 0)) { - const char *tileIdentifiers[maxTileDevices]; - getTileIdentifier(tileIdentifiers, tilesDetectedPtr, tilesDetectedCount); - LCD::getInstance().display(tileIdentifiers, tilesDetectedCount, selectedOpt, true); + if (inquiryDone) { + if (tilesDetectedCount > 0) { + /* Display the found devices to the LCD */ + const char *tileIdentifiers[maxTileDevices]; + getTileIdentifier(tileIdentifiers, tilesDetectedPtr, tilesDetectedCount); + LCD::getInstance().display(tileIdentifiers, tilesDetectedCount, selectedOpt, true); + } else { + const char *nothingFound[] = {"Nothing", "Found"}; + LCD::getInstance().display(nothingFound, 2, 0, false, true, LCD::defaultHelpStrTime); + newMenu = USER_MENU_TYPE_MAIN; + }

    }
    return (newMenu);
}

@@ -869,7 +978,6 @@ assetManagementTask::userMenuType_t assetManagementTask::selectTileMenuHandleAct

        userMenuAction_t action)
{
    userMenuType_t  newMenu         = USER_MENU_TYPE_SELECT_TILE;

- const int32_t displayDuration = 2000; // 2 seconds

    const char      *tileIdentifiers[maxTileDevices];

    /* Variables that need to be reset

@@ -880,12 +988,12 @@ assetManagementTask::userMenuType_t assetManagementTask::selectTileMenuHandleAct


    if (debug) {

- printf( "%s - Number of registered tiles: %i\n", __FUNCTION__, registeredTileDeviceCount); + printf( "%s - Number of registered tiles: %lu\n", __FUNCTION__, registeredTileDeviceCount);

    }

    // fail fast
    if (0 == registeredTileDeviceCount) {

- const char *oops[] = { "ERR: No Tiles" }; + const char *oops[] = { "No registered", "devices" };

        int32_t numOfMsgs = sizeof(oops) / sizeof(char *);

        LCD::getInstance().display(

@@ -894,7 +1002,7 @@ assetManagementTask::userMenuType_t assetManagementTask::selectTileMenuHandleAct

                0,
                false,
                true,

- displayDuration); + LCD::defaultHelpStrTime);

        action = USER_MENU_ACTION_BACK;
    }

@@ -909,7 +1017,7 @@ assetManagementTask::userMenuType_t assetManagementTask::selectTileMenuHandleAct

                0,
                false,
                true,

- displayDuration); + LCD::defaultHelpStrTime);

    }

    switch (action) {

@@ -1115,12 +1223,12 @@ void assetManagementTask::userMenuUpdate(assetManagementTask::userMenuAction_t a

    do {
        currentMenu = nextMenu;
        switch (currentMenu) {

- case USER_MENU_TYPE_MAIN: nextMenu = mainMenuHandleAction(action); break; - case USER_MENU_TYPE_ADD_TILE: nextMenu = addTileMenuHandleAction(action); break; + case USER_MENU_TYPE_MAIN: nextMenu = mainMenuHandleAction(action); break; + case USER_MENU_TYPE_ADD_TILE: nextMenu = addTileMenuHandleAction(action); break;

            case USER_MENU_TYPE_REMOVE_TILE: nextMenu = removeTileMenuHandleAction(action); break;

- case USER_MENU_TYPE_LIST_TILE: nextMenu = listTileMenuHandleAction(action); break; - case USER_MENU_TYPE_SELECT_TILE: nextMenu = selectTileMenuHandleAction(action); break; - case USER_MENU_TYPE_TRACK_TILE: nextMenu = trackTileMenuHandleAction(action); break; + case USER_MENU_TYPE_LIST_TILE: nextMenu = listTileMenuHandleAction(action); break; + case USER_MENU_TYPE_SELECT_TILE: nextMenu = selectTileMenuHandleAction(action); break; + case USER_MENU_TYPE_TRACK_TILE: nextMenu = trackTileMenuHandleAction(action); break;

            default:                       break;
        }
        action = USER_MENU_ACTION_MENU_CHANGED;

@@ -1135,8 +1243,11 @@ void assetManagementTask::userMenuUpdate(assetManagementTask::userMenuAction_t a

void assetManagementTask::handleSwitchPress(switchTask::switchID_t sID)
{
    userMenuAction_t action;

+ static bool debug = false;

- printf("SW Pressed=[%s]\n", switchTask::getSwitchName(sID)); + if (debug) { + printf("SW Pressed=[%s]\n", switchTask::getSwitchName(sID)); + }

    switch (sID) {
        case switchTask::SWITCH_ID_BACK:
        {

@@ -1223,8 +1334,10 @@ bool assetManagementTask::run(void *p)

assetManagementTask::assetManagementTask(uint8_t priority) :
        scheduler_task("assetManagementTask", 10*1024, priority),

+ BTInquiryInProcess(false),

        registeredTileDeviceCount(0),

- BTInquiryInProcess(false) + tileSelectedForTracking(NULL), + tracking_mode(false)

{
    FRESULT                     rc;
    const char                 *fileName = "tiles.txt";

@@ -1236,6 +1349,9 @@ assetManagementTask::assetManagementTask(uint8_t priority) :

    setRunDuration(10);
    LCD::getInstance().clearScreen();

+ for (int i = 0; i < maxTileDevices; i++) { + registeredTileDevice[i] = NULL; + }

    rc = (FRESULT)Storage::getFlashDrive().mount();
    if (FR_OK != rc) {
        printf("Failed to mount flash. Error=[%d]\n", rc);

@@ -1243,12 +1359,20 @@ assetManagementTask::assetManagementTask(uint8_t priority) :

        return;
    }

+ /* + * Form the file name (including the path) where the information of the registered + * tile devices is stored + */

    storageFileName = (char *)malloc(filePathLen);
    snprintf(storageFileName,
             filePathLen,
             "%s%s",
             Storage::getFlashDrive().getDrivePath(),
             fileName);

+ /* + * Read the file header to determine the number of devices that are registered, and + * the write offset + */

    rc = (FRESULT)Storage::read(storageFileName, &fileHeader, sizeof(fileHeader), readOffset);
    if (FR_OK != rc) {
        if (FR_NO_FILE == rc) {

-- 1.8.5.2.msysgit.0


From 86971dca2ed8e3970fe8a5725419642dd264ccea Mon Sep 17 00:00:00 2001 From: Pardeep <p_badhan2004@yahoo.com> Date: Sun, 11 May 2014 06:52:41 -0700 Subject: [PATCH 18/23] Displaying user set tile name in histogram

---

L5_Application/assetManagement/src/assetManagement.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/L5_Application/assetManagement/src/assetManagement.cpp b/L5_Application/assetManagement/src/assetManagement.cpp index 456482d..ad9fbdc 100644 --- a/L5_Application/assetManagement/src/assetManagement.cpp +++ b/L5_Application/assetManagement/src/assetManagement.cpp @@ -1136,7 +1136,7 @@ assetManagementTask::userMenuType_t assetManagementTask::trackTileMenuHandleActi

                char histogramTitle[  deviceNameMaxLen ];
                char histogram[       deviceNameMaxLen ];

- strcpy( histogramTitle, tile.getTileIdentifier() ); + strcpy( histogramTitle, tileSelectedForTracking->getTileIdentifier() );

                if (foundTile) {
                    rssi2histogram( tile.getRSSI(), histogram );
                }

-- 1.8.5.2.msysgit.0


From c3adcb6537abf598cdd12b764d0f8b15afb68536 Mon Sep 17 00:00:00 2001 From: Pardeep <p_badhan2004@yahoo.com> Date: Sun, 11 May 2014 10:08:41 -0700 Subject: [PATCH 19/23] Adding "Time" menu

With this menu, the user can view and set the time. Time is displayed in the following format: MM/DD/YYYY HH:MM

This menu operates in the following way: 1. After changing to Time menu, if the user clicks "Back", the main menu is displayed, and if the user clicks "Select", the user is allowed to change the time - the user is in "change time" state. 2. If in "change time" state, the user can cycle back and forth between month, day, year, hour, and minute. If the user cycles through all of these, the time is updated. If the user cycles backwards, the time is not updated. Caret character (^) guides the user when in "change time" state. ---

L5_Application/assetManagement/assetManagement.hpp |   2 +
.../assetManagement/src/assetManagement.cpp        | 137 ++++++++++++++++++++-
2 files changed, 137 insertions(+), 2 deletions(-)

diff --git a/L5_Application/assetManagement/assetManagement.hpp b/L5_Application/assetManagement/assetManagement.hpp index f4e9045..0a1e732 100644 --- a/L5_Application/assetManagement/assetManagement.hpp +++ b/L5_Application/assetManagement/assetManagement.hpp @@ -175,6 +175,7 @@ class assetManagementTask : public scheduler_task

            USER_MENU_TYPE_REMOVE_TILE,
            USER_MENU_TYPE_LIST_TILE,
            USER_MENU_TYPE_SELECT_TILE,     // entry into track

+ USER_MENU_TYPE_TIME,

        } userMenuType_t;

        static const uint8_t        maxTileDevices = 10;

@@ -199,6 +200,7 @@ class assetManagementTask : public scheduler_task

        userMenuType_t listTileMenuHandleAction(userMenuAction_t action);
        userMenuType_t selectTileMenuHandleAction(userMenuAction_t action);
        userMenuType_t trackTileMenuHandleAction(userMenuAction_t action);

+ userMenuType_t timeMenuHandleAction(userMenuAction_t action);

        void updateRegisteredTileDevices(tileDevice *tilePtr, bool add);
        bool isTileAlreadyRegistered(const tileDevice *tilePtr, uint8_t *location = NULL);
        /*

diff --git a/L5_Application/assetManagement/src/assetManagement.cpp b/L5_Application/assetManagement/src/assetManagement.cpp index ad9fbdc..7724e0d 100644 --- a/L5_Application/assetManagement/src/assetManagement.cpp +++ b/L5_Application/assetManagement/src/assetManagement.cpp @@ -15,6 +15,7 @@

#include "utilities.h"
#include "assetManagement.hpp"
#include "gpio.hpp"

+#include "rtc.h"

void LCD::printToLCD(const char *data)
{

@@ -667,6 +668,136 @@ bool assetManagementTask::getStringFromUser(char *buffer, uint8_t bufferSize)

    return (userStrLen > 0);
}

+assetManagementTask::userMenuType_t assetManagementTask::timeMenuHandleAction( + userMenuAction_t action) +{ + userMenuType_t newMenu = USER_MENU_TYPE_TIME; + const uint8_t maxTimeStrLen = 17; + char timeStr[maxTimeStrLen]; + static rtc_t time; + static rtc_t timeBeforeModications; + typedef enum { + /* + * If this is changed, "selector" needs to be changed as well + */ + TIME_DISPLAY = 0, + TIME_CHANGE_MONTH, + TIME_CHANGE_DAY, + TIME_CHANGE_YEAR, + TIME_CHANGE_HOUR, + TIME_CHANGE_MIN, + } timeDisplayState; + static timeDisplayState state = TIME_DISPLAY; + static uint8_t numOfDays[] = { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + static const char *selector[] = { + "", + " ^ ", + " ^ ", + " ^ ", + " ^ ", + " ^ ", + }; + + switch (action) { + case USER_MENU_ACTION_SCROLL_DOWN: + { + switch (state) { + case TIME_CHANGE_MONTH: if (time.month > 1) { time.month--; } break; + case TIME_CHANGE_DAY: if (time.day > 1) { time.day--; } break; + case TIME_CHANGE_YEAR: if (time.year > 1) { time.year--; } break; + case TIME_CHANGE_HOUR: if (time.hour > 1) { time.hour--; } break; + case TIME_CHANGE_MIN: if (time.min > 1) { time.min--; } break; + default: + break; + } + break; + } + case USER_MENU_ACTION_SCROLL_UP: + { + switch (state) { + case TIME_CHANGE_MONTH: if (time.month < 12) { time.month++; } break; + case TIME_CHANGE_DAY: if (time.day < numOfDays[time.month]) { time.day++; } break; + case TIME_CHANGE_YEAR: { time.year++; } break; + case TIME_CHANGE_HOUR: if (time.hour < 23) { time.hour++; } break; + case TIME_CHANGE_MIN: if (time.min < 59) { time.min++; } break; + default: + break; + } + break; + } + case USER_MENU_ACTION_SELECT: + { + switch (state) { + case TIME_DISPLAY: state = TIME_CHANGE_MONTH; break; + case TIME_CHANGE_MONTH: state = TIME_CHANGE_DAY; break; + case TIME_CHANGE_DAY: + state = TIME_CHANGE_YEAR; + if (time.day > numOfDays[time.month]) { + state = TIME_CHANGE_DAY; + } + break; + case TIME_CHANGE_YEAR: + state = TIME_CHANGE_HOUR; + /* leap year */ + if (0 == (time.year % 4)) { + if (time.day > 28) { + state = TIME_CHANGE_DAY; + } + } + break; + case TIME_CHANGE_HOUR: state = TIME_CHANGE_MIN; break; + case TIME_CHANGE_MIN: + rtc_settime(&time); + state = TIME_DISPLAY; + break; + default: + break; + } + break; + } + case USER_MENU_ACTION_BACK: + { + switch (state) { + case TIME_DISPLAY: newMenu = USER_MENU_TYPE_MAIN; break; + case TIME_CHANGE_MONTH: + state = TIME_DISPLAY; + /* restore the time */ + time = timeBeforeModications; + break; + case TIME_CHANGE_DAY: state = TIME_CHANGE_MONTH; break; + case TIME_CHANGE_YEAR: state = TIME_CHANGE_DAY; break; + case TIME_CHANGE_HOUR: state = TIME_CHANGE_YEAR; break; + case TIME_CHANGE_MIN: state = TIME_CHANGE_HOUR; break; + default: + break; + } + break; + } + case USER_MENU_ACTION_MENU_CHANGED: + { + time = rtc_gettime(); + timeBeforeModications = time; + state = TIME_DISPLAY; + break; + } + case USER_MENU_ACTION_DISPLAY: + { + if (TIME_DISPLAY == state) { + time = rtc_gettime(); + } + break; + } + default: + break; + } + + snprintf(timeStr, sizeof(timeStr), "%02d/%02d/%02d %02d:%02d", + (int)time.month, (int)time.day, (int)time.year, (int)time.hour, (int)time.min); + const char *lcdDisplay[] = {timeStr, selector[state]}; + LCD::getInstance().display(lcdDisplay, 2, 0, false, true); + return (newMenu); +} +

assetManagementTask::userMenuType_t assetManagementTask::listTileMenuHandleAction(
        userMenuAction_t action)
{

@@ -1173,7 +1304,7 @@ assetManagementTask::userMenuType_t assetManagementTask::mainMenuHandleAction(

        assetManagementTask::userMenuAction_t action)
{
    static uint8_t      selectedOpt = 0;

- const char *mainMenu[] = {"Track", "Add Tile", "Remove Tile", "List Tiles"}; + const char *mainMenu[] = {"Track", "Add Tile", "Remove Tile", "List Tiles", "Time"};

    uint8_t             mainMenuOptCnt = sizeof(mainMenu)/sizeof(mainMenu[0]);
    userMenuType_t      newMenu = USER_MENU_TYPE_MAIN;

@@ -1191,10 +1322,11 @@ assetManagementTask::userMenuType_t assetManagementTask::mainMenuHandleAction(

        case USER_MENU_ACTION_SELECT:
            switch (selectedOpt) {
                // case 0:  newMenu = USER_MENU_TYPE_TRACK_TILE;  break;

- case 0: newMenu = USER_MENU_TYPE_SELECT_TILE; break; + case 0: newMenu = USER_MENU_TYPE_SELECT_TILE; break;

                case 1:  newMenu = USER_MENU_TYPE_ADD_TILE;    break;
                case 2:  newMenu = USER_MENU_TYPE_REMOVE_TILE; break;
                case 3:  newMenu = USER_MENU_TYPE_LIST_TILE;   break;

+ case 4: newMenu = USER_MENU_TYPE_TIME; break;

                default: newMenu = USER_MENU_TYPE_MAIN;        break;
            }
            break;

@@ -1229,6 +1361,7 @@ void assetManagementTask::userMenuUpdate(assetManagementTask::userMenuAction_t a

            case USER_MENU_TYPE_LIST_TILE:   nextMenu = listTileMenuHandleAction(action);   break;
            case USER_MENU_TYPE_SELECT_TILE: nextMenu = selectTileMenuHandleAction(action); break;
            case USER_MENU_TYPE_TRACK_TILE:  nextMenu = trackTileMenuHandleAction(action);  break;

+ case USER_MENU_TYPE_TIME: nextMenu = timeMenuHandleAction(action); break;

            default:                       break;
        }
        action = USER_MENU_ACTION_MENU_CHANGED;

-- 1.8.5.2.msysgit.0


From 8462602da851c544efd79dd61b9b982a97fc0e05 Mon Sep 17 00:00:00 2001 From: Pardeep <p_badhan2004@yahoo.com> Date: Mon, 19 May 2014 04:19:40 -0700 Subject: [PATCH 20/23] Enabling UART1 support

Just copy and past of exisiting UART implementation with minor modifications. ---

L2_Drivers/base/uart_dev.cpp                       | 12 +++--
L2_Drivers/src/uart1.cpp                           | 37 +++++++++++++++
L2_Drivers/uart1.hpp                               | 52 ++++++++++++++++++++++
.../assetManagement/src/assetManagement.cpp        |  6 +--
4 files changed, 97 insertions(+), 10 deletions(-)
create mode 100644 L2_Drivers/src/uart1.cpp
create mode 100644 L2_Drivers/uart1.hpp

diff --git a/L2_Drivers/base/uart_dev.cpp b/L2_Drivers/base/uart_dev.cpp index 85175de..10eecbf 100644 --- a/L2_Drivers/base/uart_dev.cpp +++ b/L2_Drivers/base/uart_dev.cpp @@ -210,13 +210,11 @@ bool UartDev::init(unsigned int pclk, unsigned int baudRate,

        lpc_pconp(pconp_uart0, true);
        NVIC_EnableIRQ(UART0_IRQn);
    }

- /* - else if(LPC_UART1_BASE == (unsigned int)mpUARTRegBase) - { - lpc_pconp(pconp_uart1, true); - NVIC_EnableIRQ(UART1_IRQn); - } - */ + else if(LPC_UART1_BASE == (unsigned int)mpUARTRegBase) + { + lpc_pconp(pconp_uart1, true); + NVIC_EnableIRQ(UART1_IRQn); + }

    else if (LPC_UART2_BASE == (unsigned int) mpUARTRegBase)
    {
        lpc_pconp(pconp_uart2, true);

diff --git a/L2_Drivers/src/uart1.cpp b/L2_Drivers/src/uart1.cpp new file mode 100644 index 0000000..688a2f2 --- /dev/null +++ b/L2_Drivers/src/uart1.cpp @@ -0,0 +1,37 @@ +#include "uart1.hpp" +#include "LPC17xx.h" // LPC_UART0_BASE +#include "sys_config.h" // sys_get_cpu_clock() + + + +/** + * IRQ Handler needs to be enclosed in extern "C" because this is C++ file, and + * we don't want C++ to "mangle" our function name. + * This ISR Function need needs to be named precisely to override "WEAK" ISR + * handler defined at startup.cpp + */ +extern "C" +{ + void UART1_IRQHandler() + { + Uart1::getInstance().handleInterrupt(); + } +} + +bool Uart1::init(unsigned int baudRate, int rxQSize, int txQSize) +{ + // Configure PINSEL for UART1 + LPC_PINCON->PINSEL4 &= ~(0xF); // Clear values + LPC_PINCON->PINSEL4 |= (0xA); // Set values for UART1 Rx/Tx + + // Set UART1 Peripheral Clock divider to 1 + lpc_pclk(pclk_uart1, clkdiv_1); + const unsigned int pclk = sys_get_cpu_clock(); + + return UartDev::init(pclk, baudRate, rxQSize, txQSize); +} + +Uart1::Uart1() : UartDev((unsigned int*)LPC_UART1_BASE) +{ + // Nothing to do here other than handing off LPC_UART0_Base address to UART_Base +} diff --git a/L2_Drivers/uart1.hpp b/L2_Drivers/uart1.hpp new file mode 100644 index 0000000..52825a7 --- /dev/null +++ b/L2_Drivers/uart1.hpp @@ -0,0 +1,52 @@ +/** + * @file + * @brief UART1 Interrupt driven IO driver + * @ingroup Drivers + */ +#ifndef UART1_HPP_ +#define UART1_HPP_ + +#include "uart_dev.hpp" // Base class +#include "singleton_template.hpp" // Singleton Template + + + +/** + * UART1 Interrupt Driven Driver + * This simply uses UartDev, and forwards the UART1 IRQ to UartDev::handleInterrupt() + * This enforces Singleton class, otherwise it's a thin wrapper around UartDev class. + * + * @ingroup Drivers + */ +class Uart1 : public UartDev, public SingletonTemplate<Uart1> +{ + public: + /** + * Initializes UART1 at the given @param baudRate + * @param rxQSize The size of the receive queue (optional, defaults to 32) + * @param txQSize The size of the transmit queue (optional, defaults to 64) + */ + bool init(unsigned int baudRate, int rxQSize=32, int txQSize=64); + + /** + * @{ \name Static functions to use for printf/scanf redirection. + */ + static char getcharIntrDriven(char unused) + { + char c = 0; + Uart1::getInstance().getChar(&c); + return c; + } + static char putcharIntrDriven(char thechar) + { + return Uart1::getInstance().putChar(thechar); + } + /** @} */ + + private: + Uart1(); ///< Private constructor of this Singleton class + friend class SingletonTemplate<Uart1>; ///< Friend class used for Singleton Template +}; + + +#endif /* UART1_HPP_ */ diff --git a/L5_Application/assetManagement/src/assetManagement.cpp b/L5_Application/assetManagement/src/assetManagement.cpp index 7724e0d..4b76036 100644 --- a/L5_Application/assetManagement/src/assetManagement.cpp +++ b/L5_Application/assetManagement/src/assetManagement.cpp @@ -7,6 +7,7 @@

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

+#include "uart1.hpp"

#include "uart2.hpp"
#include "uart3.hpp"
#include "switches.hpp"

@@ -162,9 +163,8 @@ LCD::LCD() :

    maxOptionLength(lcdColumnSize - selectionMarkerLen),
    pageSize(2)
{

- Uart2::getInstance().init(9600, 1, 1000); - devicePtr = &Uart2::getInstance(); - + Uart1::getInstance().init(9600, 1, 1000); + devicePtr = &Uart1::getInstance();

    // Initialize FTDI Emulation Mode Switch
    emulationModeSwitch = new GPIO(P2_7);
    emulationModeSwitch->setAsInput();

-- 1.8.5.2.msysgit.0


From 6b77120cefe1004a265dc04b7c667a20e0b4a812 Mon Sep 17 00:00:00 2001 From: Pardeep <p_badhan2004@yahoo.com> Date: Mon, 19 May 2014 11:13:31 -0700 Subject: [PATCH 21/23] GPS support

Fetching GPS data using UART2, parsing the fetched GPS data, and updating the global variable. ---

L2_Drivers/base/uart_dev.hpp                       |  9 +++-
L5_Application/assetManagement/assetManagement.hpp | 16 +++++++
.../assetManagement/src/assetManagement.cpp        | 54 +++++++++++++++++++++-
L5_Application/main.cpp                            |  1 +
4 files changed, 78 insertions(+), 2 deletions(-)

diff --git a/L2_Drivers/base/uart_dev.hpp b/L2_Drivers/base/uart_dev.hpp index d7e9c0f..854416c 100644 --- a/L2_Drivers/base/uart_dev.hpp +++ b/L2_Drivers/base/uart_dev.hpp @@ -125,7 +125,14 @@ class UartDev : public CharDev

         * future action to take due to the interrupt cause.
         */
        void handleInterrupt();

- + void emptyAllQueues() { + if (mRxQueue) { + xQueueReset(mRxQueue); + } + if (mTxQueue) { + xQueueReset(mTxQueue); + } + }

    protected:
        /**
         * Protected constructor that requires parent class to provide UART's

diff --git a/L5_Application/assetManagement/assetManagement.hpp b/L5_Application/assetManagement/assetManagement.hpp index 0a1e732..f7618b5 100644 --- a/L5_Application/assetManagement/assetManagement.hpp +++ b/L5_Application/assetManagement/assetManagement.hpp @@ -291,4 +291,20 @@ class assetManagementTask : public scheduler_task

void rssi2histogram( const char *rssi, char *histogram );

+typedef struct gpsData_s { + char utc[16]; + char lat[16]; + char lon[16]; + char ns; + char ew; + char quality; +} gpsData_t; + +class GPS : public scheduler_task +{ + public: + GPS(uint8_t priority); + bool run(void *p); +}; +

#endif /* ASSETMANAGEMENT_HPP_ */

diff --git a/L5_Application/assetManagement/src/assetManagement.cpp b/L5_Application/assetManagement/src/assetManagement.cpp index 4b76036..d033154 100644 --- a/L5_Application/assetManagement/src/assetManagement.cpp +++ b/L5_Application/assetManagement/src/assetManagement.cpp @@ -18,6 +18,9 @@

#include "gpio.hpp"
#include "rtc.h"

+static gpsData_t g_gpsData; +static SemaphoreHandle_t g_gpsDataMutex; +

void LCD::printToLCD(const char *data)
{
    devicePtr->put(data);

@@ -1462,6 +1465,7 @@ bool assetManagementTask::run(void *p)

    if (tracking_mode || BTInquiryInProcess) {
        userMenuUpdate(USER_MENU_ACTION_DISPLAY);
    }

+

    return (true);
}

@@ -1479,7 +1483,7 @@ assetManagementTask::assetManagementTask(uint8_t priority) :

    tileStorageFileHeader_s     fileHeader;
    bool                        debug = true;

- setRunDuration(10); + setRunDuration(1000);

    LCD::getInstance().clearScreen();

    for (int i = 0; i < maxTileDevices; i++) {

@@ -1580,3 +1584,51 @@ rssi2histogram( const char *rssi, char *histogram )

        strcat( histogram, "EOR" ); // EOR => Error Out Of Range
    }
}

+ +GPS::GPS(uint8_t priority) : + scheduler_task("GPS", 10*1024, priority) +{ + Uart2::getInstance().init(9600, 1000, 1); + setRunDuration(1000); + g_gpsDataMutex = xSemaphoreCreateMutex(); + if(NULL == g_gpsDataMutex) { + printf("Failed to create gpsDataMutex\n"); + } + memset(&g_gpsData, 0, sizeof(g_gpsData)); +} + +bool GPS::run(void *p) +{ + char gpsData[255]; + char *strtokPtr; + char *cmdPtr; + uint8_t loopCount = 6; + + gpsData[0] = 0; + Uart2::getInstance().emptyAllQueues(); + while (loopCount--) { + if (Uart2::getInstance().gets(gpsData, sizeof(gpsData))) { + cmdPtr = strtok_r(gpsData, ",", &strtokPtr); + if (!strcmp(cmdPtr, "$GPGGA")) { + char *utc = strtok_r(NULL, ",", &strtokPtr); + char *lat = strtok_r(NULL, ",", &strtokPtr); + char *ns = strtok_r(NULL, ",", &strtokPtr); + char *lon = strtok_r(NULL, ",", &strtokPtr); + char *ew = strtok_r(NULL, ",", &strtokPtr); + char *quality = strtok_r(NULL, ",", &strtokPtr); + + xSemaphoreTake(g_gpsDataMutex, portMAX_DELAY); + strncpy(g_gpsData.utc, utc, sizeof(g_gpsData.utc)); + strncpy(g_gpsData.lat, lat, sizeof(g_gpsData.lat)); + strncpy(g_gpsData.lon, lon, sizeof(g_gpsData.lon)); + g_gpsData.ns = *ns; + g_gpsData.ew = *ew; + g_gpsData.quality = *quality; + xSemaphoreGive(g_gpsDataMutex); + + break; + } + } + } + return (true); +} diff --git a/L5_Application/main.cpp b/L5_Application/main.cpp index 2112a71..9e2a13a 100644 --- a/L5_Application/main.cpp +++ b/L5_Application/main.cpp @@ -120,6 +120,7 @@ int main(void)

//    scheduler_add_task(new BTRxTask(PRIORITY_LOW));
    scheduler_add_task(new switchTask(PRIORITY_MEDIUM));
    scheduler_add_task(new assetManagementTask(PRIORITY_LOW));

+ scheduler_add_task(new GPS(PRIORITY_LOW));

    scheduler_start(true); ///< This shouldn't return
    return -1;

-- 1.8.5.2.msysgit.0


From fc468c996f6174e9991afacc80a1375f64b29fa6 Mon Sep 17 00:00:00 2001 From: Akash <akash@hairynandgate.com> Date: Wed, 21 May 2014 10:56:09 -0700 Subject: [PATCH 22/23] GPS Storage

Added a Map task which will periodically (every 30 seconds) generate the gpsmap.txt file, but only if there is a file in the gpsdb/ directory that has a timestamp which is greater than gpsmap.txt; otherwise, the map task simply returns with minimal execution.

The only time files are added to the gpsdb/ directory is when an attemp to track a file is made and the tile is found within a close range. At that moment, by hitting the back switch GPS data for that tile will automatically be recorded.

Currently, GPS records do not get deleted when a tile is deleted. ---

L2_Drivers/base/uart_dev.hpp                       |   9 +-
L4_IO/src/storage.cpp                              |   1 -
L5_Application/assetManagement/assetManagement.hpp |  35 +++
.../assetManagement/src/assetManagement.cpp        | 296 ++++++++++++++++++++-
L5_Application/main.cpp                            |   1 +
5 files changed, 326 insertions(+), 16 deletions(-)

diff --git a/L2_Drivers/base/uart_dev.hpp b/L2_Drivers/base/uart_dev.hpp index 854416c..081a46f 100644 --- a/L2_Drivers/base/uart_dev.hpp +++ b/L2_Drivers/base/uart_dev.hpp @@ -125,14 +125,21 @@ class UartDev : public CharDev

         * future action to take due to the interrupt cause.
         */
        void handleInterrupt();

- void emptyAllQueues() { + void emptyRxQueue() {

            if (mRxQueue) {
                xQueueReset(mRxQueue);
            }

+ } + void emptyTxQueue() {

            if (mTxQueue) {
                xQueueReset(mTxQueue);
            }
        }

+ void emptyAllQueues() { + emptyRxQueue(); + emptyTxQueue(); + } +

    protected:
        /**
         * Protected constructor that requires parent class to provide UART's

diff --git a/L4_IO/src/storage.cpp b/L4_IO/src/storage.cpp index b174196..82e6658 100644 --- a/L4_IO/src/storage.cpp +++ b/L4_IO/src/storage.cpp @@ -140,7 +140,6 @@ FRESULT Storage::append(const char* pFilename,void* pData, unsigned int bytesToA

        }

        status = f_write(&file, pData, bytesToAppend, &bytesWritten);

-

        f_close(&file);
    }

diff --git a/L5_Application/assetManagement/assetManagement.hpp b/L5_Application/assetManagement/assetManagement.hpp index f7618b5..c940ab8 100644 --- a/L5_Application/assetManagement/assetManagement.hpp +++ b/L5_Application/assetManagement/assetManagement.hpp @@ -7,17 +7,24 @@

#ifndef ASSETMANAGEMENT_HPP_
#define ASSETMANAGEMENT_HPP_

+#include <time.h>

#include "singleton_template.hpp"
#include "gpio.hpp"
#include "stdio.h"
#include "storage.hpp"
#include "string.h"

+

/* set debug to enable verbose
 * messaging to console.
 */
const bool debug = true;

+enum uart_defaults_e { + uart_buffer_rx_min = 1024, + uart_buffer_tx_min = 1024, +}; +


class LCD : public SingletonTemplate<LCD>

@@ -291,6 +298,21 @@ class assetManagementTask : public scheduler_task

void rssi2histogram( const char *rssi, char *histogram );

+ + +/* gps defaults and globals */ + +enum gps_defaults_e { + gps_str_max = 255, +}; + +static char gps_db_dir[gps_str_max]; +static char gps_file_ext[gps_str_max]; +static char gps_map_file_name[gps_str_max]; + +static char gps_map_file_path[gps_str_max]; +static char gps_db_path[gps_str_max]; +

typedef struct gpsData_s {
    char utc[16];
    char lat[16];

@@ -300,10 +322,23 @@ typedef struct gpsData_s {

    char quality;
} gpsData_t;

+typedef struct mapCoordinates_s { + double latitude; + double longitude; +} mapCoordinates_t; +

class GPS : public scheduler_task
{
    public:
        GPS(uint8_t priority);

+ bool taskEntry(); + bool run(void *p); +}; + +class Map : public scheduler_task +{ + public: + Map(uint8_t priority);

        bool run(void *p);
};

diff --git a/L5_Application/assetManagement/src/assetManagement.cpp b/L5_Application/assetManagement/src/assetManagement.cpp index d033154..da01492 100644 --- a/L5_Application/assetManagement/src/assetManagement.cpp +++ b/L5_Application/assetManagement/src/assetManagement.cpp @@ -20,6 +20,7 @@

static gpsData_t         g_gpsData;
static SemaphoreHandle_t g_gpsDataMutex;

+static SemaphoreHandle_t g_gpsFileMutex;

void LCD::printToLCD(const char *data)
{

@@ -166,8 +167,8 @@ LCD::LCD() :

    maxOptionLength(lcdColumnSize - selectionMarkerLen),
    pageSize(2)
{

- Uart1::getInstance().init(9600, 1, 1000); - devicePtr = &Uart1::getInstance(); + Uart2::getInstance().init(9600, uart_buffer_rx_min, uart_buffer_tx_min); + devicePtr = &Uart2::getInstance();

    // Initialize FTDI Emulation Mode Switch
    emulationModeSwitch = new GPIO(P2_7);
    emulationModeSwitch->setAsInput();

@@ -1204,6 +1205,39 @@ assetManagementTask::userMenuType_t assetManagementTask::selectTileMenuHandleAct

    return( newMenu );
}

+bool mapCoordinates( mapCoordinates_t *output ) +{ + char lat_deg[2] = { '\0' }; + char lat_min[7] = { '\0' }; + char lon_deg[3] = { '\0' }; + char lon_min[7] = { '\0' }; + + strncpy(lat_deg, g_gpsData.lat, 2); + char *lat_ptr = g_gpsData.lat; + lat_ptr += 2; + strncpy(lat_min, lat_ptr, sizeof(lat_min)); + + strncpy(lon_deg, g_gpsData.lon, 3); + char *lon_ptr = g_gpsData.lon; + lon_ptr += 3; + strncpy(lon_min, lon_ptr, sizeof(lon_min)); + + double lat_dec = atof(lat_deg) + (atof(lat_min) / 60); + double lon_dec = atof(lon_deg) + (atof(lon_min) / 60); + + if (g_gpsData.ns == 'S') { + lat_dec *= -1; + } + if (g_gpsData.ew == 'W') { + lon_dec *= -1; + } + + output->latitude = lat_dec; + output->longitude = lon_dec; + + return true; +} +

assetManagementTask::userMenuType_t assetManagementTask::trackTileMenuHandleAction(
        userMenuAction_t action)
{

@@ -1233,6 +1267,60 @@ assetManagementTask::userMenuType_t assetManagementTask::trackTileMenuHandleActi

        }
        case USER_MENU_ACTION_BACK:
        {

+ /* save gps location if rssi value is below -60 + * and gps data is valid */ + if ( -60 <= atoi(tile.getRSSI()) && + (0 == strcmp(tile.getMac(),tileSelectedForTracking->getMac())) && + 0 != g_gpsData.quality) { + + /* get date */ + char timeStr[17] = {0}; + rtc_t time = rtc_gettime(); + snprintf(timeStr, sizeof(timeStr), "%02d/%02d/%02d %02d:%02d", + (int)time.month, (int)time.day, (int)time.year, (int)time.hour, (int)time.min); + + + /* format coordinates in to decimal form */ + mapCoordinates_t coordinates; + mapCoordinates( &coordinates ); + + /* form data message to store */ + char data[255]; + snprintf( + data, + 255, + "%s,%s,%s,%s,%f,%f\n", + tileSelectedForTracking->getTileIdentifier(), + tileSelectedForTracking->getTileName(), + tileSelectedForTracking->getMac(), + timeStr, + coordinates.latitude, + coordinates.longitude ); + if (debug) { + printf( "GPS Data: %s\n", data ); + } + + /* get database file path */ + char dbfile[gps_str_max]; + snprintf( + dbfile, + gps_str_max, + "%s/%s%s", + gps_db_path, + tileSelectedForTracking->getMac(), + gps_file_ext ); + + if (debug) { + printf( "GPS DB File: %s\n", dbfile ); + } + + /* store database file */ + xSemaphoreTake(g_gpsFileMutex, portMAX_DELAY); + Storage::write( dbfile, data, strlen(data) ); + xSemaphoreGive(g_gpsFileMutex); + } + + /* clean up and exit */

            newMenu = USER_MENU_TYPE_SELECT_TILE;
            tracking_mode   = false;
            startNewInquiry = false;

@@ -1470,7 +1558,7 @@ bool assetManagementTask::run(void *p)

}

assetManagementTask::assetManagementTask(uint8_t priority) :

- scheduler_task("assetManagementTask", 10*1024, priority), + scheduler_task("assetManagementTask", 12*1024, priority),

        BTInquiryInProcess(false),
        registeredTileDeviceCount(0),
        tileSelectedForTracking(NULL),

@@ -1547,35 +1635,39 @@ rssi2histogram( const char *rssi, char *histogram )

{
    int RSSI = atoi( rssi );

- if (-40 < RSSI) { + if (-50 < RSSI) {

        strcpy( histogram, "[XXXXXXXXXX] " );
        strcat( histogram, rssi );
    }

- else if (-50 < RSSI) { + else if (-60 < RSSI) {

        strcpy( histogram, "[XXXXXXXXX ] " );
        strcat( histogram, rssi );
    }

- else if (-60 < RSSI) { + else if (-65 < RSSI) {

        strcpy( histogram, "[XXXXXXXX  ] " );
        strcat( histogram, rssi );
    }

- else if (-65 < RSSI) { + else if (-70 < RSSI) {

        strcpy( histogram, "[XXXXXXX   ] " );
        strcat( histogram, rssi );
    }

- else if (-70 < RSSI) { + else if (-75 < RSSI) {

        strcpy( histogram, "[XXXXXX    ] " );
        strcat( histogram, rssi );
    }

- else if (-75 < RSSI) { - strcpy( histogram, "[XXXXX ] " ); + else if (-80 < RSSI) { + strcpy( histogram, "[XXXX ] " );

        strcat( histogram, rssi );
    }

- else if (-80 < RSSI) { + else if (-85 < RSSI) {

        strcpy( histogram, "[XXX       ] " );
        strcat( histogram, rssi );
    }
    else if (-90 < RSSI) {

+ strcpy( histogram, "[XX ] " ); + strcat( histogram, rssi ); + } + else if (-95 < RSSI) {

        strcpy( histogram, "[X         ] " );
        strcat( histogram, rssi );
    }

@@ -1586,15 +1678,65 @@ rssi2histogram( const char *rssi, char *histogram )

}

GPS::GPS(uint8_t priority) :

- scheduler_task("GPS", 10*1024, priority) + scheduler_task("GPS", 12*1024, priority)

{

- Uart2::getInstance().init(9600, 1000, 1);

    setRunDuration(1000);

+

    g_gpsDataMutex = xSemaphoreCreateMutex();
    if(NULL == g_gpsDataMutex) {
        printf("Failed to create gpsDataMutex\n");
    }
    memset(&g_gpsData, 0, sizeof(g_gpsData));

+ + strncpy( gps_db_dir, "gpsdb", gps_str_max ); + strncpy( gps_file_ext, ".txt", gps_str_max ); + strncpy( gps_map_file_name, "gpsmap.txt", gps_str_max ); + +} + +bool GPS::taskEntry() +{ + /* TODO: Sanity Test + * Ensure UART2 is initialized as expected + */ + + /* initialize gps storage */ + if (!Storage::getSDDrive().mount()) { + printf( "Warning: Unable to mount memory card!\n" ); + //return false; + } + + int32_t rc = 0; + rc = snprintf( + gps_map_file_path, + gps_str_max, + "%s%s", + Storage::getSDDrive().getDrivePath(), + gps_map_file_name ); + if (0 > rc) { + printf( "ERROR: Unable to define GPS map file!\n" ); + return false; + } + + rc = snprintf( + gps_db_path, + gps_str_max, + "%s%s", + Storage::getSDDrive().getDrivePath(), + gps_db_dir ); + if (0 > rc) { + printf( "ERROR: Unable to define GPS DB path!\n" ); + return false; + } + + /* make gpsdb dir */ + //FILINFO gps_db; + if (FR_NO_FILE == f_stat(gps_db_path, NULL)) { + f_mkdir(gps_db_path); + } + /* TODO: Sanity Test */ + + return true;

}

bool GPS::run(void *p)

@@ -1605,7 +1747,7 @@ bool GPS::run(void *p)

    uint8_t  loopCount = 6;

    gpsData[0] = 0;

- Uart2::getInstance().emptyAllQueues(); + Uart2::getInstance().emptyRxQueue();

    while (loopCount--) {
        if (Uart2::getInstance().gets(gpsData, sizeof(gpsData))) {
            cmdPtr = strtok_r(gpsData, ",", &strtokPtr);

@@ -1630,5 +1772,131 @@ bool GPS::run(void *p)

            }
        }
    }

+

    return (true);
}

+ +uint32_t dir_modified_time( const char *path ) +{ + uint32_t time = 0; + + DIR dir; + if (FR_OK == f_opendir(&dir, path)) { + while (1) { + FILINFO file_info; + FRESULT return_code; + return_code = f_readdir(&dir, &file_info); + + if (FR_OK != return_code || !file_info.fname[0]) { + break; + } + + if ('.' == file_info.fname[0] || (file_info.fattrib & AM_DIR) ) { + continue; + } + + if (file_info.ftime > time) { + time = file_info.ftime; + } + } + f_closedir(&dir); + } + + return time; +} + +uint32_t file_modified_time( const char *path ) { + uint32_t time = 0; + + FILINFO file_info; + if (FR_OK == f_stat(path, &file_info)) { + if (file_info.ftime > time) { + time = file_info.ftime; + } + } + + return time; +} + +Map::Map( uint8_t priority ) : + scheduler_task("Map", 12*1024, priority) +{ + setRunDuration(30000); + + g_gpsFileMutex = xSemaphoreCreateMutex(); + if(NULL == g_gpsFileMutex) { + printf("ERROR: Failed to create gpsDataMutex\n"); + } +} + +bool Map::run(void *p) +{ + xSemaphoreTake(g_gpsFileMutex, portMAX_DELAY); + uint32_t db_time = dir_modified_time( gps_db_path ); + uint32_t map_time = dir_modified_time( Storage::getSDDrive().getDrivePath() ); + xSemaphoreGive(g_gpsFileMutex); + + if (map_time >= db_time) { + if (debug) { + printf( "GPS map is up-to-date\n" ); + } + return true; + } + else { + + if (debug) { + printf( "Updating GPS map file...\n" ); + } + + xSemaphoreTake(g_gpsFileMutex, portMAX_DELAY); + DIR dir; + if (FR_OK == f_opendir(&dir, gps_db_path)) { + uint32_t file_count = 0; + while (1) { + FILINFO file_info; + char file_name[gps_str_max]; + file_info.lfname = file_name; + file_info.lfsize = gps_str_max; + + FRESULT return_code; + return_code = f_readdir(&dir, &file_info); + + if (FR_OK != return_code || !file_info.fname[0]) { + break; + } + + if ('.' == file_info.fname[0] || (file_info.fattrib & AM_DIR) ) { + continue; + } + + char file_path[gps_str_max]; + snprintf(file_path, gps_str_max, "%s/%s", gps_db_path, file_name); + + char buffer[gps_str_max] = {0}; + if (FR_OK == Storage::read(file_path, buffer, gps_str_max)) { + + if (debug) { + printf( "GPS Map Write: %s\n", buffer ); + } + + if (0 == file_count) { + Storage::write(gps_map_file_path, buffer, strlen(buffer)); + } + else { + Storage::append(gps_map_file_path, buffer, strlen(buffer)); + } + + } + + file_count++; + } + f_closedir(&dir); + xSemaphoreGive(g_gpsFileMutex); + } + } + + if (debug) { + printf( "Done updating GPS map file.\n" ); + } + return true; +} diff --git a/L5_Application/main.cpp b/L5_Application/main.cpp index 9e2a13a..444684a 100644 --- a/L5_Application/main.cpp +++ b/L5_Application/main.cpp @@ -121,6 +121,7 @@ int main(void)

    scheduler_add_task(new switchTask(PRIORITY_MEDIUM));
    scheduler_add_task(new assetManagementTask(PRIORITY_LOW));
    scheduler_add_task(new GPS(PRIORITY_LOW));

+ scheduler_add_task(new Map(PRIORITY_LOW));

    scheduler_start(true); ///< This shouldn't return
    return -1;

-- 1.8.5.2.msysgit.0


From 8f56b49dde7c54775155a15776cd320806e729d1 Mon Sep 17 00:00:00 2001 From: Pardeep <p_badhan2004@yahoo.com> Date: Thu, 22 May 2014 02:05:59 -0700 Subject: [PATCH 23/23] Addressed tile delete bugs

---

.../assetManagement/src/assetManagement.cpp        | 43 ++++++++++++++++++----
1 file changed, 35 insertions(+), 8 deletions(-)

diff --git a/L5_Application/assetManagement/src/assetManagement.cpp b/L5_Application/assetManagement/src/assetManagement.cpp index da01492..0e5ee3d 100644 --- a/L5_Application/assetManagement/src/assetManagement.cpp +++ b/L5_Application/assetManagement/src/assetManagement.cpp @@ -608,14 +608,17 @@ void assetManagementTask::storeRegisteredDevices()

void assetManagementTask::getTileIdentifier(const char *names[], tileDevice *tiles[], uint8_t deviceCount)
{

- for (int i = 0; i < deviceCount; i++) { - names[i] = tiles[i]->getTileIdentifier(); + + for (uint8_t i = 0, storeIdx = 0; i < deviceCount; i++) { + if (tiles[i]) { + names[storeIdx++] = tiles[i]->getTileIdentifier(); + }

    }
}

bool assetManagementTask::getStringFromUser(char *buffer, uint8_t bufferSize)
{

- const char *options = "Done ABCDEFGHIJKLMNOPQRST 0123456789!@#$%^&*()-=_+"; + const char *options = "Done ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789!@#$%^&*()-=_+";

    const uint8_t           optionsLen     = strlen(options);
    const uint8_t           optionOffset   = sizeof("Done") - 1;
    uint8_t                 optionSelected = 0;

@@ -812,6 +815,7 @@ assetManagementTask::userMenuType_t assetManagementTask::listTileMenuHandleActio

    const char          *spaces = "  ";

    /* fail fast */

+ printf("registeredTileDeviceCount=%d\n", registeredTileDeviceCount);

    if (0 == registeredTileDeviceCount) {
        const char *noDevicesStr[] = {"No registered", "devices"};
        LCD::getInstance().display(noDevicesStr, 2, selectedOpt, false, true, LCD::defaultHelpStrTime);

@@ -946,6 +950,10 @@ void assetManagementTask::updateRegisteredTileDevices(tileDevice *tilePtr, bool

            delete registeredTileDevice[location];
            registeredTileDevice[location] = NULL;
            registeredTileDeviceCount--;

+ /* Reorganize array */ + for (uint8_t i = location; i < (maxTileDevices-1); i++) { + registeredTileDevice[i] = registeredTileDevice[i+1]; + }

            storeRegisteredDevices();

            /* Inform the user about the device that was removed */

@@ -962,7 +970,7 @@ assetManagementTask::userMenuType_t assetManagementTask::removeTileMenuHandleAct

{
    static uint8_t       selectedOpt = 0;
    userMenuType_t       newMenu = USER_MENU_TYPE_REMOVE_TILE;

- const char *tileIdentifiers[maxTileDevices]; + static const char *tileIdentifiers[maxTileDevices];

    /* fail fast */
    if (0 == registeredTileDeviceCount) {

@@ -988,9 +996,21 @@ assetManagementTask::userMenuType_t assetManagementTask::removeTileMenuHandleAct

        }
        case USER_MENU_ACTION_SELECT:
        {

- if (registeredTileDevice[selectedOpt]) { - updateRegisteredTileDevices(registeredTileDevice[selectedOpt], false); + uint8_t deviceIdx = 0; + for (deviceIdx = 0; deviceIdx < maxTileDevices; deviceIdx++) { + if (registeredTileDevice[deviceIdx]) { + if (!strcmp(registeredTileDevice[deviceIdx]->getTileIdentifier(), + tileIdentifiers[selectedOpt])) { + break; + } + } + } + if (deviceIdx != maxTileDevices) { + if (registeredTileDevice[deviceIdx]) { + updateRegisteredTileDevices(registeredTileDevice[deviceIdx], false); + }

            }

+ selectedOpt = 0;

            newMenu = USER_MENU_TYPE_MAIN;
            break;
        }

@@ -999,11 +1019,17 @@ assetManagementTask::userMenuType_t assetManagementTask::removeTileMenuHandleAct

            newMenu = USER_MENU_TYPE_MAIN;
            break;
        }

+ case USER_MENU_ACTION_MENU_CHANGED: + case USER_MENU_ACTION_DISPLAY: + { + selectedOpt = 0; + break; + }

        default:
            break;
    }

- getTileIdentifier(tileIdentifiers, registeredTileDevice, registeredTileDeviceCount); + getTileIdentifier(tileIdentifiers, registeredTileDevice, maxTileDevices);

    LCD::getInstance().display(tileIdentifiers, registeredTileDeviceCount, selectedOpt, true);
    return (newMenu);
}

@@ -1574,7 +1600,7 @@ assetManagementTask::assetManagementTask(uint8_t priority) :

    setRunDuration(1000);
    LCD::getInstance().clearScreen();

- for (int i = 0; i < maxTileDevices; i++) { + for (uint8_t i = 0; i < maxTileDevices; i++) {

        registeredTileDevice[i] = NULL;
    }
    rc = (FRESULT)Storage::getFlashDrive().mount();

@@ -1750,6 +1776,7 @@ bool GPS::run(void *p)

    Uart2::getInstance().emptyRxQueue();
    while (loopCount--) {
        if (Uart2::getInstance().gets(gpsData, sizeof(gpsData))) {

+ printf("%s\n", gpsData);

            cmdPtr = strtok_r(gpsData, ",", &strtokPtr);
            if (!strcmp(cmdPtr, "$GPGGA")) {
                char *utc     = strtok_r(NULL, ",", &strtokPtr);

-- 1.8.5.2.msysgit.0