/* Virginia Tech Cognitive Radio Open Source Systems * Virginia Tech, 2009 * * LICENSE INFORMATION GOES HERE */ /* DESCRIPTION OF FILE. */ #include #include #include #include "vtcross/common.h" #include "vtcross/components.h" #include "vtcross/containers.h" #include "vtcross/debug.h" #include "vtcross/error.h" #include "vtcross/socketcomm.h" #include "vtcross/cbr.h" #include "cbr.c" #include #include static cbr myCBR; CognitiveEngine::CognitiveEngine() { LOG("Creating Cognitive Engine.\n"); SML_present = false; commandSocketFD = -1; } CognitiveEngine::~CognitiveEngine() { cbr_free(myCBR); delete [] pList; delete [] oList; delete [] uList; delete [] radioInfo; } CognitiveEngine::CognitiveEngine(const char* serverName, const char* serverPort, \ const bool SML) { LOG("Creating Cognitive Engine.\n"); pList = new Parameter[10]; oList = new Observable[10]; uList = new Utility[10]; radioInfo = new Radio_Info; ConnectToRemoteComponent(serverName, serverPort, SML); } void CognitiveEngine::SendComponentType() { SendMessage(commandSocketFD, "response_engine_cognitive"); LOG("Cognitive Engine responded to GetRemoteComponentType query.\n"); } void CognitiveEngine::ConnectToRemoteComponent(const char* serverName, \ const char* serverPort, const bool SML) { commandSocketFD = ClientSocket(serverName, serverPort); SML_present = SML; if(SML) { RegisterComponent(); RegisterServices(); LOG("Cognitive Engine connected to SML at %s.\n", serverName); ReceiveRadioConfiguration(); ReceiveExperience(); } else { RegisterComponent(); LOG("Cognitive Engine connected to shell at %s.\n", serverName); ReceiveRadioConfiguration(); ReceiveExperience(); } } void CognitiveEngine::WaitForSignal() { char buffer[256]; while(true) { memset(buffer, 0, 256); ReadMessage(commandSocketFD, buffer); // TODO this is ugly... is there a better way? Doesn't strcmp compare the // whole string? We only need to compare until we find a single different // byte... // // If we send integer op codes rather than strings, this process will be // MUCH faster since instead of donig string compares we can simply // switch on the integer value... if(strcmp(buffer, "request_optimization") == 0) { /* Receive Set of Observables */ LOG("Cognitive Engine:: Receiving Observable Parameters\n"); memset(buffer, 0, 256); ReadMessage(commandSocketFD,buffer); uint32_t numObservables = atoi(buffer); Observable *o = new Observable[numObservables]; for(size_t i = 0; i < numObservables; i++) { memset(buffer, 0, 256); ReadMessage(commandSocketFD, buffer); o[i].name = std::string(buffer); memset(buffer, 0, 256); ReadMessage(commandSocketFD, buffer); o[i].value = atof(buffer); } /* Receive Set of current Parameters */ LOG("Cognitive Engine:: Receiving Current Transmission Parameters\n"); memset(buffer, 0, 256); ReadMessage(commandSocketFD,buffer); uint32_t numCurrentParameters = atoi(buffer); Parameter *cp = new Parameter[numCurrentParameters]; for(size_t i = 0; i < numCurrentParameters; i++) { memset(buffer, 0, 256); ReadMessage(commandSocketFD, buffer); cp[i].name = std::string(buffer); memset(buffer, 0, 256); ReadMessage(commandSocketFD, buffer); cp[i].value = atof(buffer); } LOG("Cognitive Engine:: Processing parameters....\n"); Parameter *solutionSet; solutionSet = GetSolution(o,cp); // TODO need to actually do something with the observables here LOG("Cognitive Engine:: Sending Optimal Parameters to Application.\n"); char numParametersChar[10]; char solutionValue[50]; sprintf(numParametersChar,"%i",radioInfo->numParameters); SendMessage(commandSocketFD,numParametersChar); for(size_t i = 0; i < radioInfo->numParameters; i++) { SendMessage(commandSocketFD,solutionSet[i].name.c_str()); memset(solutionValue, 0, 50); sprintf(solutionValue,"%f",solutionSet[i].value); SendMessage(commandSocketFD,solutionValue); } delete [] o; delete [] cp; } else if(strcmp(buffer, "query_component_type") == 0) { SendComponentType(); } else if(strcmp(buffer, "connect_sml") == 0) { /* This command implies that we are disconnecting from the shell and * connecting to a SML component. */ char serverName[256]; char serverPort[256]; // TODO is this going to end up being too slow? memset(serverName, 0, 256); memset(serverPort, 0, 256); ReadMessage(commandSocketFD, serverName); ReadMessage(commandSocketFD, serverPort); /* Only continue if we are currently connected to a shell. */ if(!SML_present) { DeregisterComponent(); shutdown(commandSocketFD, 2); close(commandSocketFD); ConnectToRemoteComponent(serverName, serverPort, true); } } else if(strcmp(buffer, "disconnect_sml") == 0) { /* This command implies that we are disconnecting from the SML and * connecting to a shell component. */ char serverName[256]; char serverPort[256]; // TODO is this going to end up being too slow? memset(serverName, 0, 256); memset(serverPort, 0, 256); ReadMessage(commandSocketFD, serverName); ReadMessage(commandSocketFD, serverPort); /* We only want to do this if we are actually connected to an SML * currently. */ if(SML_present) { DeregisterServices(); shutdown(commandSocketFD, 2); close(commandSocketFD); ConnectToRemoteComponent(serverName, serverPort, false); } } else if(strcmp(buffer, "reset_engine_cognitive") == 0) { Reset(); } else if(strcmp(buffer, "shutdown_engine_cognitive") == 0) { Shutdown(); } } } void CognitiveEngine::Shutdown() { if(SML_present) { DeregisterServices(); DeregisterComponent(); } else { DeregisterComponent(); } // TODO should something else be happening here? } void CognitiveEngine::Reset() { LOG("Resetting Cognitive Engine.\n"); if(SML_present) { DeregisterServices(); DeregisterComponent(); } else { DeregisterComponent(); } } void CognitiveEngine::RegisterComponent() { SendMessage(commandSocketFD, "register_engine_cognitive"); LOG("Cognitive Engine:: Registration message sent to shell.\n"); } void CognitiveEngine::DeregisterComponent() { SendMessage(commandSocketFD, "deregister_engine_cognitive"); LOG("Cognitive Engine:: Deregistration message sent.\n"); shutdown(commandSocketFD, 2); close(commandSocketFD); commandSocketFD = -1; LOG("Cognitive Engine:: Shell socket closed.\n"); } void CognitiveEngine::RegisterServices() { LOG("Cognitive Engine:: Registering services.\n"); SendMessage(commandSocketFD, "register_service"); SendMessage(commandSocketFD, "jam_wifi"); SendMessage(commandSocketFD, "register_service"); SendMessage(commandSocketFD, "signal_detection"); SendMessage(commandSocketFD, "register_service"); SendMessage(commandSocketFD, "max_throughput"); SendMessage(commandSocketFD, "register_service"); SendMessage(commandSocketFD, "jam_bluetooth"); } void CognitiveEngine::DeregisterServices() { LOG("Cognitive Engine:: Deregistering services.\n"); SendMessage(commandSocketFD, "deregister_service"); SendMessage(commandSocketFD, "jam_wifi"); SendMessage(commandSocketFD, "deregister_service"); SendMessage(commandSocketFD, "signal_detection"); SendMessage(commandSocketFD, "deregister_service"); SendMessage(commandSocketFD, "max_throughput"); SendMessage(commandSocketFD, "deregister_service"); SendMessage(commandSocketFD, "jam_bluetooth"); } void CognitiveEngine::ReceiveRadioConfiguration() { LOG("Cognitive Engine:: Receiving Radio Configuration.\n"); char buffer[256]; /* Receive Set of Utilities */ memset(buffer, 0, 256); ReadMessage(commandSocketFD,buffer); radioInfo->numUtilities = atoi(buffer); for(size_t i = 0; i < radioInfo->numUtilities; i++) { memset(buffer, 0, 256); ReadMessage(commandSocketFD,buffer); uList[i].name = std::string(buffer); memset(buffer, 0, 256); ReadMessage(commandSocketFD,buffer); uList[i].units = std::string(buffer); memset(buffer, 0, 256); ReadMessage(commandSocketFD,buffer); uList[i].goal = std::string(buffer); memset(buffer, 0, 256); ReadMessage(commandSocketFD,buffer); uList[i].target = atof(buffer); } /* Receive Set of Parameters */ memset(buffer, 0, 256); ReadMessage(commandSocketFD, buffer); radioInfo->numParameters = atoi(buffer); for(size_t i = 0; i < radioInfo->numParameters; i++) { memset(buffer, 0, 256); ReadMessage(commandSocketFD, buffer); pList[i].name = std::string(buffer); memset(buffer, 0, 256); ReadMessage(commandSocketFD, buffer); pList[i].units = std::string(buffer); memset(buffer, 0, 256); ReadMessage(commandSocketFD, buffer); pList[i].min = atof(buffer); memset(buffer, 0, 256); ReadMessage(commandSocketFD, buffer); pList[i].max = atof(buffer); memset(buffer, 0, 256); ReadMessage(commandSocketFD, buffer); pList[i].step = atof(buffer); memset(buffer, 0, 256); ReadMessage(commandSocketFD,buffer); pList[i].numAffects = atoi(buffer); for(size_t j = 0; j < pList[i].numAffects; j++) { memset(buffer, 0, 256); ReadMessage(commandSocketFD,buffer); for(size_t k = 0; k < radioInfo->numUtilities; k++) { if(uList[k].name == std::string(buffer)){ pList[i].affection_list[j].u = &uList[k]; break; } } memset(buffer, 0, 256); ReadMessage(commandSocketFD,buffer); pList[i].affection_list[j].relation = std::string(buffer); } } /* Receive Set of Observables */ memset(buffer, 0, 256); ReadMessage(commandSocketFD,buffer); radioInfo->numObservables = atoi(buffer); for(size_t i = 0; i < radioInfo->numObservables; i++) { memset(buffer, 0, 256); ReadMessage(commandSocketFD,buffer); oList[i].name = std::string(buffer); memset(buffer, 0, 256); ReadMessage(commandSocketFD,buffer); oList[i].numAffects = atoi(buffer); for(size_t j = 0; j < oList[i].numAffects; j++) { memset(buffer, 0, 256); ReadMessage(commandSocketFD,buffer); for(size_t k = 0; k < radioInfo->numUtilities; k++) { if(uList[k].name == std::string(buffer)){ oList[i].affection_list[j].u = &uList[k]; break; } } memset(buffer, 0, 256); ReadMessage(commandSocketFD,buffer); oList[i].affection_list[j].relation = std::string(buffer); } } SendMessage(commandSocketFD, "receive_config_ack"); BuildCognitiveEngine(); } void CognitiveEngine::ReceiveExperience() { LOG("Cognitive Engine:: Receiving Experience Report.\n"); char buffer[256]; uint32_t numberExp; /* Receive number of experience entries */ memset(buffer, 0, 256); ReadMessage(commandSocketFD,buffer); numberExp = atoi(buffer); LOG("Cognitive Engine:: Waiting for %i number of entries.\n",numberExp); SendMessage(commandSocketFD, "receive_exp_ack"); } Parameter* CognitiveEngine::GetSolution(Observable *observables, Parameter *currentParameters) { LOG("Cognitive Engine:: Generating solution.\n"); char *searchNames[radioInfo->numUtilities]; for(size_t i = 0; i < radioInfo->numUtilities; i++) { searchNames[i] = (char*)uList[i].name.c_str(); } float searchVals[radioInfo->numUtilities]; for(size_t i = 0; i < radioInfo->numUtilities; i++) { searchVals[i] = uList[i].target; } uint32_t numberColumns = radioInfo->numUtilities + radioInfo->numParameters + radioInfo->numObservables + 1; float returnValues[numberColumns]; int searchOps[radioInfo->numUtilities]; for(size_t i = 0; i < radioInfo->numUtilities; i++) { /* If the goal is to maximum, set the search operation to * return values greater than the target. * * If the goal is to minimize, set the search operation to * return values less than the target. */ if(strcmp(uList[i].goal.c_str(),"max") == 0) { searchOps[i] = GT; } else if(strcmp(uList[i].goal.c_str(),"min") == 0) { searchOps[i] = LT; } } /* CBR specific call */ uint32_t rc = cbr_search(myCBR, searchNames, searchOps, searchVals, radioInfo->numUtilities, returnValues); if(rc == 0){ /* Adapt the returned parameters to meet the objective */ } else if(rc == 31337){ /* No rows in the CBR, pick default parameters */ // Currently this is hard coded and implementation specific! //returnValues[2] = currentParameters[0].value + 5; //returnValues[3] = currentParameters[1].value + 10; } else { WARNING("Cognitive Engine:: Search return an invalid value.\n"); } size_t returnValueIndex = 0; for(size_t i = 0; i < radioInfo->numUtilities; i++) { uList[i].value = returnValues[returnValueIndex]; returnValueIndex++; } for(size_t i = 0; i < radioInfo->numParameters; i++) { pList[i].value = returnValues[returnValueIndex]; returnValueIndex++; } for(size_t i = 0; i < radioInfo->numObservables; i++) { oList[i].value = returnValues[returnValueIndex]; returnValueIndex++; } // Add row to CBR. return pList; } Parameter* CognitiveEngine::GetSolution(Observable *observables, Parameter *currentParameters, std::string service) { LOG("Cognitive Engine:: Generating solution for %s service.\n",service.c_str()); return pList; } void CognitiveEngine::ReceiveFeedback(Observable *observables, Parameter *parameters, \ Utility *utilities) { LOG("Cognitive Engine:: Receiving feedback.\n"); } void CognitiveEngine::ReceiveFeedback(Observable *observables, Parameter *parameters, \ Utility *utilities, std::string service) { LOG("Cognitive Engine:: Receiving feedback.\n"); } void CognitiveEngine::BuildCognitiveEngine() { char filename[] = {"ex1"}; char tablename[] = {"data"}; uint32_t numberColumns = radioInfo->numUtilities + radioInfo->numParameters + radioInfo->numObservables + 1; char *cols[numberColumns]; size_t columnIndex = 0; for (size_t i = 0; i < radioInfo->numUtilities; i++){ cols[columnIndex] = (char*)uList[i].name.c_str(); columnIndex++; } for (size_t i = 0; i < radioInfo->numParameters; i++){ cols[columnIndex] = (char*)pList[i].name.c_str(); columnIndex++; } for (size_t i = 0; i < radioInfo->numObservables; i++){ cols[columnIndex] = (char*)oList[i].name.c_str(); columnIndex++; } cols[columnIndex] = "utility"; myCBR = cbr_create(filename, tablename, cols, numberColumns); }