$search
00001 /* 00002 Aseba - an event-based framework for distributed robot control 00003 Copyright (C) 2007--2012: 00004 Stephane Magnenat <stephane at magnenat dot net> 00005 (http://stephane.magnenat.net) 00006 and other contributors, see authors.txt for details 00007 00008 This program is free software: you can redistribute it and/or modify 00009 it under the terms of the GNU Lesser General Public License as published 00010 by the Free Software Foundation, version 3 of the License. 00011 00012 This program is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 GNU Lesser General Public License for more details. 00016 00017 You should have received a copy of the GNU Lesser General Public License 00018 along with this program. If not, see <http://www.gnu.org/licenses/>. 00019 */ 00020 00021 #include "descriptions-manager.h" 00022 #include "msg.h" 00023 #include <iostream> 00024 00025 using namespace std; 00026 00027 namespace Aseba 00028 { 00029 DescriptionsManager::NodeDescription::NodeDescription() : 00030 namedVariablesReceptionCounter(0), 00031 localEventsReceptionCounter(0), 00032 nativeFunctionReceptionCounter(0) 00033 { 00034 } 00035 00036 DescriptionsManager::NodeDescription::NodeDescription(const TargetDescription& targetDescription) : 00037 TargetDescription(targetDescription), 00038 namedVariablesReceptionCounter(0), 00039 localEventsReceptionCounter(0), 00040 nativeFunctionReceptionCounter(0) 00041 { 00042 } 00043 00044 void DescriptionsManager::processMessage(const Message* message) 00045 { 00046 // if we have a disconnection message 00047 { 00048 const Disconnected *disconnected = dynamic_cast<const Disconnected *>(message); 00049 if (disconnected) 00050 { 00051 NodesDescriptionsMap::iterator it = nodesDescriptions.find(disconnected->source); 00052 if (it != nodesDescriptions.end()) 00053 nodesDescriptions.erase(it); 00054 } 00055 } 00056 00057 // if we have an initial description 00058 { 00059 const Description *description = dynamic_cast<const Description *>(message); 00060 if (description) 00061 { 00062 NodesDescriptionsMap::iterator it = nodesDescriptions.find(description->source); 00063 00064 // We can receive a description twice, for instance if there is another IDE connected 00065 if (it != nodesDescriptions.end()) 00066 return; 00067 00068 // Call a user function when a node protocol version mismatches 00069 if (description->protocolVersion != ASEBA_PROTOCOL_VERSION) 00070 { 00071 nodeProtocolVersionMismatch(description->name, description->protocolVersion); 00072 return; 00073 } 00074 00075 // create node and copy description into it 00076 nodesDescriptions[description->source] = NodeDescription(*description); 00077 checkIfNodeDescriptionComplete(description->source, nodesDescriptions[description->source]); 00078 } 00079 } 00080 00081 // if we have a named variabledescription 00082 { 00083 const NamedVariableDescription *description = dynamic_cast<const NamedVariableDescription *>(message); 00084 if (description) 00085 { 00086 NodesDescriptionsMap::iterator it = nodesDescriptions.find(description->source); 00087 00088 // we must have received a description first 00089 if (it == nodesDescriptions.end()) 00090 return; 00091 00092 // copy description into array if array is empty 00093 if (it->second.namedVariablesReceptionCounter < it->second.namedVariables.size()) 00094 { 00095 it->second.namedVariables[it->second.namedVariablesReceptionCounter++] = *description; 00096 checkIfNodeDescriptionComplete(it->first, it->second); 00097 } 00098 } 00099 } 00100 00101 // if we have a local event description 00102 { 00103 const LocalEventDescription *description = dynamic_cast<const LocalEventDescription *>(message); 00104 if (description) 00105 { 00106 NodesDescriptionsMap::iterator it = nodesDescriptions.find(description->source); 00107 00108 // we must have received a description first 00109 if (it == nodesDescriptions.end()) 00110 return; 00111 00112 // copy description into array if array is empty 00113 if (it->second.localEventsReceptionCounter < it->second.localEvents.size()) 00114 { 00115 it->second.localEvents[it->second.localEventsReceptionCounter++] = *description; 00116 checkIfNodeDescriptionComplete(it->first, it->second); 00117 } 00118 } 00119 } 00120 00121 // if we have a native function description 00122 { 00123 const NativeFunctionDescription *description = dynamic_cast<const NativeFunctionDescription *>(message); 00124 if (description) 00125 { 00126 NodesDescriptionsMap::iterator it = nodesDescriptions.find(description->source); 00127 00128 // we must have received a description first 00129 if (it == nodesDescriptions.end()) 00130 return; 00131 00132 // copy description into array 00133 if (it->second.nativeFunctionReceptionCounter < it->second.nativeFunctions.size()) 00134 { 00135 it->second.nativeFunctions[it->second.nativeFunctionReceptionCounter++] = *description; 00136 checkIfNodeDescriptionComplete(it->first, it->second); 00137 } 00138 } 00139 } 00140 } 00141 00142 void DescriptionsManager::checkIfNodeDescriptionComplete(unsigned id, const NodeDescription& description) 00143 { 00144 // we will call the virtual function only when we have received all local events and native functions 00145 if ((description.namedVariablesReceptionCounter == description.namedVariables.size()) && 00146 (description.localEventsReceptionCounter == description.localEvents.size()) && 00147 (description.nativeFunctionReceptionCounter == description.nativeFunctions.size()) 00148 ) 00149 { 00150 nodeDescriptionReceived(id); 00151 } 00152 } 00153 00154 std::wstring DescriptionsManager::getNodeName(unsigned nodeId) const 00155 { 00156 NodesDescriptionsMap::const_iterator it = nodesDescriptions.find(nodeId); 00157 if (it != nodesDescriptions.end()) 00158 { 00159 return it->second.name; 00160 } 00161 else 00162 { 00163 return L""; 00164 } 00165 } 00166 00167 unsigned DescriptionsManager::getNodeId(const std::wstring& name, unsigned preferedId, bool *ok) const 00168 { 00169 // search for the first node with a given name 00170 bool found(false); 00171 unsigned foundId(0); 00172 for (NodesDescriptionsMap::const_iterator it = nodesDescriptions.begin(); it != nodesDescriptions.end(); ++it) 00173 { 00174 if (it->second.name == name) 00175 { 00176 if (ok) 00177 *ok = true; 00178 00179 if (it->first == preferedId) 00180 return it->first; 00181 else if (!found) 00182 foundId = it->first; 00183 00184 found = true; 00185 } 00186 } 00187 00188 // node found, but with another id than prefered 00189 if (found) 00190 return foundId; 00191 00192 // node not found 00193 if (ok) 00194 *ok = false; 00195 return 0xFFFFFFFF; 00196 } 00197 00198 const TargetDescription * const DescriptionsManager::getDescription(unsigned nodeId, bool *ok) const 00199 { 00200 NodesDescriptionsMap::const_iterator it = nodesDescriptions.find(nodeId); 00201 00202 // node not found 00203 if (it == nodesDescriptions.end()) 00204 { 00205 if (ok) 00206 *ok = false; 00207 return 0; 00208 } 00209 00210 if (ok) 00211 *ok = true; 00212 return &(it->second); 00213 } 00214 00215 unsigned DescriptionsManager::getVariablePos(unsigned nodeId, const std::wstring& name, bool *ok) const 00216 { 00217 NodesDescriptionsMap::const_iterator it = nodesDescriptions.find(nodeId); 00218 00219 // node not found 00220 if (it != nodesDescriptions.end()) 00221 { 00222 size_t pos = 0; 00223 for (size_t i = 0; i < it->second.namedVariables.size(); ++i) 00224 { 00225 if (it->second.namedVariables[i].name == name) 00226 { 00227 if (ok) 00228 *ok = true; 00229 return pos; 00230 } 00231 pos += it->second.namedVariables[i].size; 00232 } 00233 } 00234 00235 // node not found or variable not found 00236 if (ok) 00237 *ok = false; 00238 return 0xFFFFFFFF; 00239 } 00240 00241 unsigned DescriptionsManager::getVariableSize(unsigned nodeId, const std::wstring& name, bool *ok) const 00242 { 00243 NodesDescriptionsMap::const_iterator it = nodesDescriptions.find(nodeId); 00244 00245 // node not found 00246 if (it != nodesDescriptions.end()) 00247 { 00248 for (size_t i = 0; i < it->second.namedVariables.size(); ++i) 00249 { 00250 if (it->second.namedVariables[i].name == name) 00251 { 00252 if (ok) 00253 *ok = true; 00254 return it->second.namedVariables[i].size; 00255 } 00256 } 00257 } 00258 00259 // node not found or variable not found 00260 if (ok) 00261 *ok = false; 00262 return 0xFFFFFFFF; 00263 } 00264 00265 void DescriptionsManager::reset() 00266 { 00267 nodesDescriptions.clear(); 00268 } 00269 }