bool Tree_Delete(TreeNode node) { bool result = false; _treeNode _rootNode = (_treeNode) node; if (_rootNode) { _treeNode currentNode = _rootNode; while (currentNode) { // Find the end node of a branch while (currentNode->ChildCount) { uint32_t childIndex; for (childIndex = 0; childIndex < currentNode->ChildSlots; childIndex++) { if (currentNode->Children && currentNode->Children[childIndex]) { currentNode = (_treeNode) currentNode->Children[childIndex]; childIndex = currentNode->ChildSlots + 1; // Exit 'for' loop } } } // // Should be at bottom of a branch // (next, free the node) // If the currentNode has a parent, break the parent's link to the node if (currentNode->Parent) { _treeNode parentNode = (_treeNode) currentNode->Parent; parentNode->Children[currentNode->ChildID-1] = NULL; if (((_treeNode) currentNode->Parent)->ChildCount > 0) ((_treeNode) currentNode->Parent)->ChildCount--; currentNode->ChildID = 0; // The node is no longer a child-node } // else, must be the 'root' node // Free the curentNode's name, value & 'children' array if (currentNode->Name) Flow_MemFree((void **) ¤tNode->Name); if (currentNode->Value) Flow_MemFree((void **) ¤tNode->Value); if (currentNode->Children) Flow_MemFree((void **) ¤tNode->Children); // Move currentNode up to its parent before freeing this node _treeNode tempNode = currentNode; currentNode = (_treeNode) currentNode->Parent; Flow_MemFree((void **) &tempNode); // Rinse and repeat, now that we're at the new end of the old branch } result = true; } return result; }
static void FreeCmd(FlowInterfaceCmd *cmd) { if (cmd->details) { Flow_MemFree((void **)&cmd->details); } Flow_MemFree((void **)&cmd); }
/** * Send an event to controller thread on reception of any message. * data - Pointer to received message, should be copied for future usage. * sendorId - Pointer to user/device ID, should be copied for future usage. * datasize - Received message size. */ static bool PostControllerEventReceivedMessage(const FlowQueue* receiveMsgQueue, const char *data, const char *sendorId, const unsigned int datasize) { bool success = false; ControllerEvent *event = NULL; ReceivedMessage *receivedMsg = NULL; event = (ControllerEvent *)Flow_MemAlloc(sizeof(ControllerEvent)); if (event) { event->evtType = ControllerEvent_ReceivedMessage; receivedMsg = (ReceivedMessage *)Flow_MemAlloc(sizeof(ReceivedMessage)); if (receivedMsg) { //Allocate one extra byte for data, as the datasize we got from //FlowMessagingMessage_GetContentLength() doesn't include null terminator receivedMsg->data = (char *)Flow_MemAlloc(datasize + 1); receivedMsg->sendorId = (char *)Flow_MemAlloc(strlen(sendorId) + 1); if (receivedMsg->data && receivedMsg->sendorId) { strncpy(receivedMsg->data, data, datasize); receivedMsg->data[datasize] = '\0'; strcpy(receivedMsg->sendorId, sendorId); event->details = receivedMsg; success = FlowQueue_Enqueue(*receiveMsgQueue, event); } if (!success) { if (receivedMsg->data) { Flow_MemFree((void **)&receivedMsg->data); } if (receivedMsg->sendorId) { Flow_MemFree((void **)&receivedMsg->sendorId); } Flow_MemFree((void **)&receivedMsg); } } if (!success) { Flow_MemFree((void **)&event); } } return success; }
/** * Send an event to controller thread for success/failure of reading KVS config * data - Device setting read from datastore. * In case of any failure, user should free any memory allocated to it. * Otherwise, would be freed by receiver if successfully added to queue. */ static bool PostControllerEventSetting(const FlowQueue* receiveMsgQueue, char *data) { bool success = false; ControllerEvent *event = NULL; //Allocated memory should be freed by the receiver event = (ControllerEvent *)Flow_MemAlloc(sizeof(ControllerEvent)); if (event) { if (data) { event->evtType = ControllerEvent_SettingSuccess; } else { event->evtType = ControllerEvent_SettingFailure; } event->details = data; success = FlowQueue_Enqueue(*receiveMsgQueue, event); if (!success) { Flow_MemFree((void **)&event); } } return success; }
bool TreeNode_DeleteSingle(TreeNode node) { // Not a recursive delete -- *only* deletes this node // Links to its children will be lost if they have not been // 'remembered' externally bool result = false; _treeNode _node = (_treeNode) node; if (_node) { if(_node->Name) Flow_MemFree((void **)&_node->Name); if(_node->Value) Flow_MemFree((void **)&_node->Value); if(_node->Children) Flow_MemFree((void **)&_node->Children); Flow_MemFree((void **)&_node); result = true; } return result; }
bool TreeNode_AddChild(TreeNode node, TreeNode child) { bool result = false; _treeNode _node = (_treeNode) node; if (_node && child) { // Check whether we need to resize the children list to add a new child if (_node->ChildSlots <= _node->ChildCount) { TreeNodeImpl **oldChildrenList = (TreeNodeImpl**) _node->Children; // Double list capacity uint32_t newChildrenListSize = sizeof(TreeNode) * (_node->ChildSlots * 2); _node->Children = (struct TreeNodeImpl**) Flow_MemAlloc(newChildrenListSize); if (_node->Children) { _node->ChildSlots = (_node->ChildSlots * 2); memset(_node->Children, 0, newChildrenListSize); memcpy(_node->Children, oldChildrenList, _node->ChildCount * sizeof(TreeNode)); Flow_MemFree((void **) &oldChildrenList); } else { _node->Children = (struct TreeNodeImpl**) oldChildrenList; goto error; } } // Add the new child to the list _node->Children[_node->ChildCount] = child; _node->ChildCount++; ((_treeNode)child)->ChildID = _node->ChildCount; // Make sure the Parent pointer is set so that // Tree_Delete will also free the root node. ((_treeNode)child)->Parent = (struct TreeNodeImpl *)_node; result = true; } error: return result; }
bool TreeNode_SetValue(const TreeNode node, const uint8_t* value, const uint32_t length) { bool result = false; _treeNode _node = (_treeNode) node; if (_node && value) { if (_node->Value) Flow_MemFree((void **) &_node->Value); _node->Value = Flow_MemAlloc(sizeof(uint8_t) * (length+1)); if (_node->Value) { if (length > 0) memcpy(_node->Value, value, length); _node->Value[length] = '\0'; result = true; } } return result; }
bool TreeNode_SetName(const TreeNode node, const char* name, const uint32_t length) { bool result = false; _treeNode _node = (_treeNode) node; if (_node && name) { if (_node->Name) Flow_MemFree((void **) &_node->Name); _node->Name = Flow_MemAlloc(sizeof(char) * (length+1)); if (_node->Name) { if (length > 0) memcpy(_node->Name, name, length); _node->Name[length] = '\0'; result = true; } } return result; }
/** * Flow interface thread :- * 1. Registers a message callback for any message received. * 2. Handles all the commands coming from controller thread. */ void FlowInterfaceThread(FlowThread thread, void *taskParameters) { Controller *me = taskParameters; FlowInterfaceCmd *cmd = NULL; _receiveMsgQueue = &me->receiveMsgQueue; RegisterCallbackForReceivedMsg(MessageReceivedCallBack); for (;;) { cmd = FlowQueue_DequeueWaitFor(me->sendMsgQueue,QUEUE_WAITING_TIME); if (cmd != NULL) { switch (cmd->cmdType) { case FlowInterfaceCmd_SendMessageToUser: { SendMessage(me->userId, cmd->details,SendMessage_ToUser); FreeCmd(cmd); break; } case FlowInterfaceCmd_SendMessageToActuator: { if (me->actuatorConfig.actuatorId) { SendMessage(me->actuatorConfig.actuatorId, cmd->details,SendMessage_ToDevice); ControllerLog(ControllerLogLevel_Debug, DEBUG_PREFIX "Sending relay command to actuator" ); } else { ControllerLog(ControllerLogLevel_Debug, DEBUG_PREFIX "Actuator id is NOT known to us" ); } FreeCmd(cmd); break; } case FlowInterfaceCmd_SendMessageToSensor: { if (me->sensorConfig.sensorId) { SendMessage(me->sensorConfig.sensorId, cmd->details,SendMessage_ToDevice); ControllerLog(ControllerLogLevel_Debug, DEBUG_PREFIX "Sending update settings to sensor" ); } else { ControllerLog(ControllerLogLevel_Debug, DEBUG_PREFIX "Sensor id is NOT known to us" ); } FreeCmd(cmd); break; } case FlowInterfaceCmd_GetSetting: { char *data = NULL; if (GetSetting(CONTROLLER_CONFIG_NAME, &data)) { if (!PostControllerEventSetting(&me->receiveMsgQueue, data)) { Flow_MemFree((void **)&data); ControllerLog(ControllerLogLevel_Error, ERROR_PREFIX "Posting settings event to controller thread failed"); } } else { if (!PostControllerEventSetting(&me->receiveMsgQueue, NULL)) { ControllerLog(ControllerLogLevel_Error, ERROR_PREFIX "Posting settings event to controller thread failed"); } } FreeCmd(cmd); break; } case FlowInterfaceCmd_SetSetting: { if (!SetSetting(CONTROLLER_CONFIG_NAME, cmd->details)) { ControllerLog(ControllerLogLevel_Error, ERROR_PREFIX "Error in saving settings" ); } FreeCmd(cmd); break; } default: { ControllerLog(ControllerLogLevel_Debug, DEBUG_PREFIX "Received unknown command" ); FreeCmd(cmd); break; } } } } }
/********************************************************************* * Function: void SYS_ArduinoMonitorTask(void) * * PreCondition: None * * Input: None * * Output: Receive and monitor communications with the Arduino-shield serial comms channel * * Side Effects: None * * Overview: This function implements the task for monitoring comms from the Arduino shield. * * Note: None ********************************************************************/ void SYS_ArduinoMonitorTask(FlowThread thread, void *taskParameters) { char incomingChar = 0; #define ARDUINO_SERIAL_PORT 6 #define ARDUINO_SERIAL_BAUD 115200 // power the PMODRS232 #if defined(MICROCHIP_PIC32) /* * UART 6 - Shield RS232 port * - u6Txd on pin RPB15 * - u6RXd on pin RPC2 */ // TXd Pin setup. PLIB_PORTS_PinModePerPortSelect (PORTS_ID_0, PORT_CHANNEL_B, PORTS_BIT_POS_15, PORTS_PIN_MODE_DIGITAL); PLIB_PORTS_PinDirectionOutputSet( PORTS_ID_0, PORT_CHANNEL_B, PORTS_BIT_POS_15 ); RPB15R = 0x04; // RXd Pin setup. PLIB_PORTS_PinModePerPortSelect (PORTS_ID_0, PORT_CHANNEL_C, PORTS_BIT_POS_2, PORTS_PIN_MODE_DIGITAL); PLIB_PORTS_PinDirectionInputSet( PORTS_ID_0, PORT_CHANNEL_C, PORTS_BIT_POS_2 ); U6RXR = 0x0C; // RPG8 3V3 supply Digilent PMODRS232 PLIB_PORTS_PinModePerPortSelect (PORTS_ID_0, PORT_CHANNEL_G, PORTS_BIT_POS_8, PORTS_PIN_MODE_DIGITAL); PLIB_PORTS_PinDirectionOutputSet( PORTS_ID_0, PORT_CHANNEL_G, PORTS_BIT_POS_8 ); PLIB_PORTS_PinSet( PORTS_ID_0, PORT_CHANNEL_G, PORTS_BIT_POS_8 ); // RPG7 0V supply to Digilent PMODRS232 PLIB_PORTS_PinModePerPortSelect (PORTS_ID_0, PORT_CHANNEL_G, PORTS_BIT_POS_7, PORTS_PIN_MODE_DIGITAL); PLIB_PORTS_PinDirectionOutputSet( PORTS_ID_0, PORT_CHANNEL_G, PORTS_BIT_POS_7 ); PLIB_PORTS_PinClear( PORTS_ID_0, PORT_CHANNEL_G, PORTS_BIT_POS_7 ); #endif arduinoSerial = FlowSerial_Init(ARDUINO_SERIAL_PORT, ARDUINO_SERIAL_BAUD); #define ARDUINO_CMD_BUFFER_LENGTH 255 char commandBuffer[ARDUINO_CMD_BUFFER_LENGTH+1]; char* cursor = commandBuffer; unsigned int freeBufferSize = ARDUINO_CMD_BUFFER_LENGTH; bool processCommand = false; memset(commandBuffer, '\0', ARDUINO_CMD_BUFFER_LENGTH+1); while(1) { while (FlowSerial_Ready(arduinoSerial)) { incomingChar = FlowSerial_Getc(arduinoSerial); if (freeBufferSize > 0 && incomingChar != '\n' && incomingChar != '\r') { *cursor = incomingChar; freeBufferSize--; cursor++; } else { *cursor = '\0'; processCommand = true; } if (processCommand) { cmdRequestID++; // Create a request to send to device owner StringBuilder request = StringBuilder_New(256); // Response Header request = StringBuilder_Append(request, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); request = StringBuilder_Append(request, "<command>"); char* datetime = CommandHandlers_GetTimeString(); request = StringBuilder_Append(request, "<sent type=\"datetime\">"); request = StringBuilder_Append(request, datetime); request = StringBuilder_Append(request, "</sent>"); Flow_MemFree((void **) &datetime); request = StringBuilder_Append(request, "<to>"); request = StringBuilder_Append(request, g_OwnerAoR); request = StringBuilder_Append(request, "</to>"); request = StringBuilder_Append(request, "<from>"); request = StringBuilder_Append(request, g_DeviceAoR); request = StringBuilder_Append(request, "</from>"); request = StringBuilder_Append(request, "<clientid type=\"integer\">"); request = StringBuilder_Append(request, g_ClientID); request = StringBuilder_Append(request, "</clientid>"); request = StringBuilder_Append(request, "<requestid type=\"integer\">"); request = StringBuilder_AppendInt(request, cmdRequestID); request = StringBuilder_Append(request, "</requestid>"); request = StringBuilder_Append(request, "<details>MIF DISPLAY "); request = StringBuilder_Append(request, commandBuffer); request = StringBuilder_Append(request, "</details>"); request = StringBuilder_Append(request, "</command>"); if (FlowMessaging_SendMessageToUser((FlowID) g_OwnerID, "text/plain", (char *)StringBuilder_GetCString(request), StringBuilder_GetLength(request), 60)) { FlowConsole_Printf("\n\rSuccessfully forwarded command received from Arduino-shield comms interface ('%s').\n\r", commandBuffer); } else { FlowConsole_Puts("\n\rWarning: Could not forward command received from Arduino-shield comms interface."); } // Clean up StringBuilder_Free(&request); processCommand = false; cursor = commandBuffer; freeBufferSize = ARDUINO_CMD_BUFFER_LENGTH; } } vTaskDelay( 100 / portTICK_RATE_MS ); } }
TreeNode TreeNode_Navigate(const TreeNode rootNode, const char* path) { _treeNode currentNode = rootNode; _treeNode _node = (_treeNode) rootNode; // Validate inputs (Check rootNode & path are not null) // Assuming path is null-terminated if (rootNode && path) { char* _path = (char*) Flow_MemAlloc(sizeof(char) * (strlen((const char*) path)+1) ); if (_path) { // Design note: Need to make a copy of path ('_path') as Microchip's implementation // of strtok() appears to try to modify the string it's working on memset((void*)_path, 0, (sizeof(char) * (strlen((const char*) path)+1) )); memcpy((void*) _path, (void*) path, sizeof(char) * strlen((const char*) path) ); // Check for path separator '/' character if (strchr((const char*) _path, '/') == NULL) { if (strcmp((const char*) _node->Name, (const char*) _path) != 0) currentNode = NULL; } else { // Tokenise path and ensure first pathElement matches char *pathElement = strtok((char*) _path, (const char*) "/"); if (pathElement) { if (strcmp((const char*) currentNode->Name, (const char*) pathElement) == 0) { bool childFound = false; bool pathError = false; do { // Then, get next path-token and find a match for a child node's name pathElement = strtok(0, "/"); if (pathElement) { childFound = false; uint32_t childIndex = 0; for (childIndex = 0; childIndex < currentNode->ChildCount; childIndex++) { // For each token, check if a child's node name matches the next token in the path _treeNode thisChild = (_treeNode) currentNode->Children[childIndex]; if (strcmp((const char*) thisChild->Name, pathElement) == 0) { currentNode = thisChild; childFound = true; break; } } if (!childFound) { currentNode = NULL; pathError = true; } } } while(pathElement && !pathError); if (pathError) currentNode = NULL; } } } Flow_MemFree((void **) &_path); } else { } } return (TreeNode) currentNode; }